* 'staging-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (1519 commits) staging: et131x: Remove redundant check and return statement staging: et131x: Mainly whitespace changes to appease checkpatch staging: et131x: Remove last of the forward declarations staging: et131x: Remove even more forward declarations staging: et131x: Remove yet more forward declarations staging: et131x: Remove more forward declarations staging: et131x: Remove forward declaration of et131x_adapter_setup staging: et131x: Remove some forward declarations staging: et131x: Remove unused rx_ring.recv_packet_pool staging: et131x: Remove call to find pci pm capability staging: et131x: Remove redundant et131x_reset_recv() call staging: et131x: Remove unused rx_ring.recv_buffer_pool Staging: bcm: Fix three initialization errors in InterfaceDld.c Staging: bcm: Fix coding style issues in InterfaceDld.c staging:iio:dac: Add AD5360 driver staging:iio:trigger:bfin-timer: Fix compile error Staging: vt6655: add some range checks before memcpy() Staging: vt6655: whitespace fixes to iotcl.c Staging: vt6656: add some range checks before memcpy() Staging: vt6656: whitespace cleanups in ioctl.c ... Fix up conflicts in: - drivers/{Kconfig,Makefile}, drivers/staging/{Kconfig,Makefile}: vg driver movement - drivers/staging/brcm80211/brcmfmac/{dhd_linux.c,mac80211_if.c}: driver removal vs now stale changes - drivers/staging/rtl8192e/r8192E_core.c: driver removal vs now stale changes - drivers/staging/et131x/et131*: driver consolidation into one file, tried to do fixups
Unified · Split
| @@ -6171,7 +6171,7 @@ S: Maintained · 6170 unmodified lines | |||
| 6171 | 6171 | ||
| 6172 | STAGING SUBSYSTEM | 6172 | STAGING SUBSYSTEM |
| 6173 | M: Greg Kroah-Hartman <gregkh@suse.de> | 6173 | M: Greg Kroah-Hartman <gregkh@suse.de> |
| 6174 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6.git | 6174 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git |
| 6175 | L: devel@driverdev.osuosl.org | 6175 | L: devel@driverdev.osuosl.org |
| 6176 | S: Maintained | 6176 | S: Maintained |
| 6177 | F: drivers/staging/ | 6177 | F: drivers/staging/ |
| @@ -6212,6 +6212,11 @@ M: David Rowe <david@rowetel.com> · 34 unmodified lines | |||
| 6212 | S: Odd Fixes | 6212 | S: Odd Fixes |
| 6213 | F: drivers/staging/echo/ | 6213 | F: drivers/staging/echo/ |
| 6214 | 6214 | ||
| 6215 | STAGING - ET131X NETWORK DRIVER | ||
| 6216 | M: Mark Einon <mark.einon@gmail.com> | ||
| 6217 | S: Odd Fixes | ||
| 6218 | F: drivers/staging/et131x/ | ||
| 6219 | |||
| 6215 | STAGING - FLARION FT1000 DRIVERS | 6220 | STAGING - FLARION FT1000 DRIVERS |
| 6216 | M: Marek Belisko <marek.belisko@gmail.com> | 6221 | M: Marek Belisko <marek.belisko@gmail.com> |
| 6217 | S: Odd Fixes | 6222 | S: Odd Fixes |
| @@ -6240,6 +6245,13 @@ W: http://www.lirc.org/ · 22 unmodified lines | |||
| 6240 | S: Odd Fixes | 6245 | S: Odd Fixes |
| 6241 | F: drivers/staging/lirc/ | 6246 | F: drivers/staging/lirc/ |
| 6242 | 6247 | ||
| 6248 | STAGING - NVIDIA COMPLIANT EMBEDDED CONTROLLER INTERFACE (nvec) | ||
| 6249 | M: Julian Andres Klode <jak@jak-linux.org> | ||
| 6250 | M: Marc Dietrich <marvin24@gmx.de> | ||
| 6251 | L: ac100@lists.launchpad.net (moderated for non-subscribers) | ||
| 6252 | S: Maintained | ||
| 6253 | F: drivers/staging/nvec/ | ||
| 6254 | |||
| 6243 | STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON) | 6255 | STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON) |
| 6244 | M: Andres Salomon <dilinger@queued.net> | 6256 | M: Andres Salomon <dilinger@queued.net> |
| 6245 | M: Chris Ball <cjb@laptop.org> | 6257 | M: Chris Ball <cjb@laptop.org> |
| @@ -189,5 +189,6 @@ · 188 unmodified lines | |||
| 189 | #define HV_STATUS_INVALID_HYPERCALL_CODE 2 | 189 | #define HV_STATUS_INVALID_HYPERCALL_CODE 2 |
| 190 | #define HV_STATUS_INVALID_HYPERCALL_INPUT 3 | 190 | #define HV_STATUS_INVALID_HYPERCALL_INPUT 3 |
| 191 | #define HV_STATUS_INVALID_ALIGNMENT 4 | 191 | #define HV_STATUS_INVALID_ALIGNMENT 4 |
| 192 | #define HV_STATUS_INSUFFICIENT_BUFFERS 19 | ||
| 192 | 193 | ||
| 193 | #endif | 194 | #endif |
| @@ -132,6 +132,8 @@ source "drivers/iommu/Kconfig" · 131 unmodified lines | |||
| 132 | 132 | ||
| 133 | source "drivers/virt/Kconfig" | 133 | source "drivers/virt/Kconfig" |
| 134 | 134 | ||
| 135 | source "drivers/hv/Kconfig" | ||
| 136 | |||
| 135 | source "drivers/devfreq/Kconfig" | 137 | source "drivers/devfreq/Kconfig" |
| 136 | 138 | ||
| 137 | endmenu | 139 | endmenu |
| @@ -129,5 +129,6 @@ obj-$(CONFIG_IOMMU_SUPPORT) += iommu/ · 128 unmodified lines | |||
| 129 | 129 | ||
| 130 | # Virtualization drivers | 130 | # Virtualization drivers |
| 131 | obj-$(CONFIG_VIRT_DRIVERS) += virt/ | 131 | obj-$(CONFIG_VIRT_DRIVERS) += virt/ |
| 132 | obj-$(CONFIG_HYPERV) += hv/ | ||
| 132 | 133 | ||
| 133 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ | 134 | obj-$(CONFIG_PM_DEVFREQ) += devfreq/ |
| @@ -1,613 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller | ||
| 3 | * | ||
| 4 | * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> | ||
| 5 | * | ||
| 6 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 7 | * License. See the file COPYING in the main directory of this archive | ||
| 8 | * for more details. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | |||
| 13 | #ifndef _SCC_H | ||
| 14 | #define _SCC_H | ||
| 15 | |||
| 16 | #include <linux/delay.h> | ||
| 17 | |||
| 18 | /* Special configuration ioctls for the Atari SCC5380 Serial | ||
| 19 | * Communications Controller | ||
| 20 | */ | ||
| 21 | |||
| 22 | /* ioctl command codes */ | ||
| 23 | |||
| 24 | #define TIOCGATSCC 0x54c0 /* get SCC configuration */ | ||
| 25 | #define TIOCSATSCC 0x54c1 /* set SCC configuration */ | ||
| 26 | #define TIOCDATSCC 0x54c2 /* reset configuration to defaults */ | ||
| 27 | |||
| 28 | /* Clock sources */ | ||
| 29 | |||
| 30 | #define CLK_RTxC 0 | ||
| 31 | #define CLK_TRxC 1 | ||
| 32 | #define CLK_PCLK 2 | ||
| 33 | |||
| 34 | /* baud_bases for the common clocks in the Atari. These are the real | ||
| 35 | * frequencies divided by 16. | ||
| 36 | */ | ||
| 37 | |||
| 38 | #define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */ | ||
| 39 | #define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */ | ||
| 40 | #define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */ | ||
| 41 | #define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */ | ||
| 42 | #define SCC_BAUD_BASE_NONE 0 /* for not connected or unused | ||
| 43 | * clock sources */ | ||
| 44 | |||
| 45 | /* The SCC clock configuration structure */ | ||
| 46 | |||
| 47 | struct scc_clock_config { | ||
| 48 | unsigned RTxC_base; /* base_baud of RTxC */ | ||
| 49 | unsigned TRxC_base; /* base_baud of TRxC */ | ||
| 50 | unsigned PCLK_base; /* base_baud of PCLK, both channels! */ | ||
| 51 | struct { | ||
| 52 | unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */ | ||
| 53 | unsigned divisor; /* divisor for base baud, valid values: | ||
| 54 | * see below */ | ||
| 55 | } baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300, | ||
| 56 | * 600, 1200, 1800, 2400, 4800, 9600, | ||
| 57 | * 19200, 38400, 57600 and 115200 bps. | ||
| 58 | * The last two could be replaced by | ||
| 59 | * other rates > 38400 if they're not | ||
| 60 | * possible. | ||
| 61 | */ | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* The following divisors are valid: | ||
| 65 | * | ||
| 66 | * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use | ||
| 67 | * the BRG) | ||
| 68 | * | ||
| 69 | * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible) | ||
| 70 | * | ||
| 71 | * - CLK_PCLK: >= 4 and even (no direct modes, only BRG) | ||
| 72 | * | ||
| 73 | */ | ||
| 74 | |||
| 75 | struct scc_port { | ||
| 76 | struct gs_port gs; | ||
| 77 | volatile unsigned char *ctrlp; | ||
| 78 | volatile unsigned char *datap; | ||
| 79 | int x_char; /* xon/xoff character */ | ||
| 80 | int c_dcd; | ||
| 81 | int channel; | ||
| 82 | struct scc_port *port_a; /* Reference to port A and B */ | ||
| 83 | struct scc_port *port_b; /* structs for reg access */ | ||
| 84 | }; | ||
| 85 | |||
| 86 | #define SCC_MAGIC 0x52696368 | ||
| 87 | |||
| 88 | /***********************************************************************/ | ||
| 89 | /* */ | ||
| 90 | /* Register Names */ | ||
| 91 | /* */ | ||
| 92 | /***********************************************************************/ | ||
| 93 | |||
| 94 | /* The SCC documentation gives no explicit names to the registers, | ||
| 95 | * they're just called WR0..15 and RR0..15. To make the source code | ||
| 96 | * better readable and make the transparent write reg read access (see | ||
| 97 | * below) possible, I christen them here with self-invented names. | ||
| 98 | * Note that (real) read registers are assigned numbers 16..31. WR7' | ||
| 99 | * has number 33. | ||
| 100 | */ | ||
| 101 | |||
| 102 | #define COMMAND_REG 0 /* wo */ | ||
| 103 | #define INT_AND_DMA_REG 1 /* wo */ | ||
| 104 | #define INT_VECTOR_REG 2 /* rw, common to both channels */ | ||
| 105 | #define RX_CTRL_REG 3 /* rw */ | ||
| 106 | #define AUX1_CTRL_REG 4 /* rw */ | ||
| 107 | #define TX_CTRL_REG 5 /* rw */ | ||
| 108 | #define SYNC_ADR_REG 6 /* wo */ | ||
| 109 | #define SYNC_CHAR_REG 7 /* wo */ | ||
| 110 | #define SDLC_OPTION_REG 33 /* wo */ | ||
| 111 | #define TX_DATA_REG 8 /* wo */ | ||
| 112 | #define MASTER_INT_CTRL 9 /* wo, common to both channels */ | ||
| 113 | #define AUX2_CTRL_REG 10 /* rw */ | ||
| 114 | #define CLK_CTRL_REG 11 /* wo */ | ||
| 115 | #define TIMER_LOW_REG 12 /* rw */ | ||
| 116 | #define TIMER_HIGH_REG 13 /* rw */ | ||
| 117 | #define DPLL_CTRL_REG 14 /* wo */ | ||
| 118 | #define INT_CTRL_REG 15 /* rw */ | ||
| 119 | |||
| 120 | #define STATUS_REG 16 /* ro */ | ||
| 121 | #define SPCOND_STATUS_REG 17 /* wo */ | ||
| 122 | /* RR2 is WR2 for Channel A, Channel B gives vector + current status: */ | ||
| 123 | #define CURR_VECTOR_REG 18 /* Ch. B only, Ch. A for rw */ | ||
| 124 | #define INT_PENDING_REG 19 /* Channel A only! */ | ||
| 125 | /* RR4 is WR4, if b6(MR7') == 1 */ | ||
| 126 | /* RR5 is WR5, if b6(MR7') == 1 */ | ||
| 127 | #define FS_FIFO_LOW_REG 22 /* ro */ | ||
| 128 | #define FS_FIFO_HIGH_REG 23 /* ro */ | ||
| 129 | #define RX_DATA_REG 24 /* ro */ | ||
| 130 | /* RR9 is WR3, if b6(MR7') == 1 */ | ||
| 131 | #define DPLL_STATUS_REG 26 /* ro */ | ||
| 132 | /* RR11 is WR10, if b6(MR7') == 1 */ | ||
| 133 | /* RR12 is WR12 */ | ||
| 134 | /* RR13 is WR13 */ | ||
| 135 | /* RR14 not present */ | ||
| 136 | /* RR15 is WR15 */ | ||
| 137 | |||
| 138 | |||
| 139 | /***********************************************************************/ | ||
| 140 | /* */ | ||
| 141 | /* Register Values */ | ||
| 142 | /* */ | ||
| 143 | /***********************************************************************/ | ||
| 144 | |||
| 145 | |||
| 146 | /* WR0: COMMAND_REG "CR" */ | ||
| 147 | |||
| 148 | #define CR_RX_CRC_RESET 0x40 | ||
| 149 | #define CR_TX_CRC_RESET 0x80 | ||
| 150 | #define CR_TX_UNDERRUN_RESET 0xc0 | ||
| 151 | |||
| 152 | #define CR_EXTSTAT_RESET 0x10 | ||
| 153 | #define CR_SEND_ABORT 0x18 | ||
| 154 | #define CR_ENAB_INT_NEXT_RX 0x20 | ||
| 155 | #define CR_TX_PENDING_RESET 0x28 | ||
| 156 | #define CR_ERROR_RESET 0x30 | ||
| 157 | #define CR_HIGHEST_IUS_RESET 0x38 | ||
| 158 | |||
| 159 | |||
| 160 | /* WR1: INT_AND_DMA_REG "IDR" */ | ||
| 161 | |||
| 162 | #define IDR_EXTSTAT_INT_ENAB 0x01 | ||
| 163 | #define IDR_TX_INT_ENAB 0x02 | ||
| 164 | #define IDR_PARERR_AS_SPCOND 0x04 | ||
| 165 | |||
| 166 | #define IDR_RX_INT_DISAB 0x00 | ||
| 167 | #define IDR_RX_INT_FIRST 0x08 | ||
| 168 | #define IDR_RX_INT_ALL 0x10 | ||
| 169 | #define IDR_RX_INT_SPCOND 0x18 | ||
| 170 | #define IDR_RX_INT_MASK 0x18 | ||
| 171 | |||
| 172 | #define IDR_WAITREQ_RX 0x20 | ||
| 173 | #define IDR_WAITREQ_IS_REQ 0x40 | ||
| 174 | #define IDR_WAITREQ_ENAB 0x80 | ||
| 175 | |||
| 176 | |||
| 177 | /* WR3: RX_CTRL_REG "RCR" */ | ||
| 178 | |||
| 179 | #define RCR_RX_ENAB 0x01 | ||
| 180 | #define RCR_DISCARD_SYNC_CHARS 0x02 | ||
| 181 | #define RCR_ADDR_SEARCH 0x04 | ||
| 182 | #define RCR_CRC_ENAB 0x08 | ||
| 183 | #define RCR_SEARCH_MODE 0x10 | ||
| 184 | #define RCR_AUTO_ENAB_MODE 0x20 | ||
| 185 | |||
| 186 | #define RCR_CHSIZE_MASK 0xc0 | ||
| 187 | #define RCR_CHSIZE_5 0x00 | ||
| 188 | #define RCR_CHSIZE_6 0x40 | ||
| 189 | #define RCR_CHSIZE_7 0x80 | ||
| 190 | #define RCR_CHSIZE_8 0xc0 | ||
| 191 | |||
| 192 | |||
| 193 | /* WR4: AUX1_CTRL_REG "A1CR" */ | ||
| 194 | |||
| 195 | #define A1CR_PARITY_MASK 0x03 | ||
| 196 | #define A1CR_PARITY_NONE 0x00 | ||
| 197 | #define A1CR_PARITY_ODD 0x01 | ||
| 198 | #define A1CR_PARITY_EVEN 0x03 | ||
| 199 | |||
| 200 | #define A1CR_MODE_MASK 0x0c | ||
| 201 | #define A1CR_MODE_SYNCR 0x00 | ||
| 202 | #define A1CR_MODE_ASYNC_1 0x04 | ||
| 203 | #define A1CR_MODE_ASYNC_15 0x08 | ||
| 204 | #define A1CR_MODE_ASYNC_2 0x0c | ||
| 205 | |||
| 206 | #define A1CR_SYNCR_MODE_MASK 0x30 | ||
| 207 | #define A1CR_SYNCR_MONOSYNC 0x00 | ||
| 208 | #define A1CR_SYNCR_BISYNC 0x10 | ||
| 209 | #define A1CR_SYNCR_SDLC 0x20 | ||
| 210 | #define A1CR_SYNCR_EXTCSYNC 0x30 | ||
| 211 | |||
| 212 | #define A1CR_CLKMODE_MASK 0xc0 | ||
| 213 | #define A1CR_CLKMODE_x1 0x00 | ||
| 214 | #define A1CR_CLKMODE_x16 0x40 | ||
| 215 | #define A1CR_CLKMODE_x32 0x80 | ||
| 216 | #define A1CR_CLKMODE_x64 0xc0 | ||
| 217 | |||
| 218 | |||
| 219 | /* WR5: TX_CTRL_REG "TCR" */ | ||
| 220 | |||
| 221 | #define TCR_TX_CRC_ENAB 0x01 | ||
| 222 | #define TCR_RTS 0x02 | ||
| 223 | #define TCR_USE_CRC_CCITT 0x00 | ||
| 224 | #define TCR_USE_CRC_16 0x04 | ||
| 225 | #define TCR_TX_ENAB 0x08 | ||
| 226 | #define TCR_SEND_BREAK 0x10 | ||
| 227 | |||
| 228 | #define TCR_CHSIZE_MASK 0x60 | ||
| 229 | #define TCR_CHSIZE_5 0x00 | ||
| 230 | #define TCR_CHSIZE_6 0x20 | ||
| 231 | #define TCR_CHSIZE_7 0x40 | ||
| 232 | #define TCR_CHSIZE_8 0x60 | ||
| 233 | |||
| 234 | #define TCR_DTR 0x80 | ||
| 235 | |||
| 236 | |||
| 237 | /* WR7': SLDC_OPTION_REG "SOR" */ | ||
| 238 | |||
| 239 | #define SOR_AUTO_TX_ENAB 0x01 | ||
| 240 | #define SOR_AUTO_EOM_RESET 0x02 | ||
| 241 | #define SOR_AUTO_RTS_MODE 0x04 | ||
| 242 | #define SOR_NRZI_DISAB_HIGH 0x08 | ||
| 243 | #define SOR_ALT_DTRREQ_TIMING 0x10 | ||
| 244 | #define SOR_READ_CRC_CHARS 0x20 | ||
| 245 | #define SOR_EXTENDED_REG_ACCESS 0x40 | ||
| 246 | |||
| 247 | |||
| 248 | /* WR9: MASTER_INT_CTRL "MIC" */ | ||
| 249 | |||
| 250 | #define MIC_VEC_INCL_STAT 0x01 | ||
| 251 | #define MIC_NO_VECTOR 0x02 | ||
| 252 | #define MIC_DISAB_LOWER_CHAIN 0x04 | ||
| 253 | #define MIC_MASTER_INT_ENAB 0x08 | ||
| 254 | #define MIC_STATUS_HIGH 0x10 | ||
| 255 | #define MIC_IGN_INTACK 0x20 | ||
| 256 | |||
| 257 | #define MIC_NO_RESET 0x00 | ||
| 258 | #define MIC_CH_A_RESET 0x40 | ||
| 259 | #define MIC_CH_B_RESET 0x80 | ||
| 260 | #define MIC_HARD_RESET 0xc0 | ||
| 261 | |||
| 262 | |||
| 263 | /* WR10: AUX2_CTRL_REG "A2CR" */ | ||
| 264 | |||
| 265 | #define A2CR_SYNC_6 0x01 | ||
| 266 | #define A2CR_LOOP_MODE 0x02 | ||
| 267 | #define A2CR_ABORT_ON_UNDERRUN 0x04 | ||
| 268 | #define A2CR_MARK_IDLE 0x08 | ||
| 269 | #define A2CR_GO_ACTIVE_ON_POLL 0x10 | ||
| 270 | |||
| 271 | #define A2CR_CODING_MASK 0x60 | ||
| 272 | #define A2CR_CODING_NRZ 0x00 | ||
| 273 | #define A2CR_CODING_NRZI 0x20 | ||
| 274 | #define A2CR_CODING_FM1 0x40 | ||
| 275 | #define A2CR_CODING_FM0 0x60 | ||
| 276 | |||
| 277 | #define A2CR_PRESET_CRC_1 0x80 | ||
| 278 | |||
| 279 | |||
| 280 | /* WR11: CLK_CTRL_REG "CCR" */ | ||
| 281 | |||
| 282 | #define CCR_TRxCOUT_MASK 0x03 | ||
| 283 | #define CCR_TRxCOUT_XTAL 0x00 | ||
| 284 | #define CCR_TRxCOUT_TXCLK 0x01 | ||
| 285 | #define CCR_TRxCOUT_BRG 0x02 | ||
| 286 | #define CCR_TRxCOUT_DPLL 0x03 | ||
| 287 | |||
| 288 | #define CCR_TRxC_OUTPUT 0x04 | ||
| 289 | |||
| 290 | #define CCR_TXCLK_MASK 0x18 | ||
| 291 | #define CCR_TXCLK_RTxC 0x00 | ||
| 292 | #define CCR_TXCLK_TRxC 0x08 | ||
| 293 | #define CCR_TXCLK_BRG 0x10 | ||
| 294 | #define CCR_TXCLK_DPLL 0x18 | ||
| 295 | |||
| 296 | #define CCR_RXCLK_MASK 0x60 | ||
| 297 | #define CCR_RXCLK_RTxC 0x00 | ||
| 298 | #define CCR_RXCLK_TRxC 0x20 | ||
| 299 | #define CCR_RXCLK_BRG 0x40 | ||
| 300 | #define CCR_RXCLK_DPLL 0x60 | ||
| 301 | |||
| 302 | #define CCR_RTxC_XTAL 0x80 | ||
| 303 | |||
| 304 | |||
| 305 | /* WR14: DPLL_CTRL_REG "DCR" */ | ||
| 306 | |||
| 307 | #define DCR_BRG_ENAB 0x01 | ||
| 308 | #define DCR_BRG_USE_PCLK 0x02 | ||
| 309 | #define DCR_DTRREQ_IS_REQ 0x04 | ||
| 310 | #define DCR_AUTO_ECHO 0x08 | ||
| 311 | #define DCR_LOCAL_LOOPBACK 0x10 | ||
| 312 | |||
| 313 | #define DCR_DPLL_EDGE_SEARCH 0x20 | ||
| 314 | #define DCR_DPLL_ERR_RESET 0x40 | ||
| 315 | #define DCR_DPLL_DISAB 0x60 | ||
| 316 | #define DCR_DPLL_CLK_BRG 0x80 | ||
| 317 | #define DCR_DPLL_CLK_RTxC 0xa0 | ||
| 318 | #define DCR_DPLL_FM 0xc0 | ||
| 319 | #define DCR_DPLL_NRZI 0xe0 | ||
| 320 | |||
| 321 | |||
| 322 | /* WR15: INT_CTRL_REG "ICR" */ | ||
| 323 | |||
| 324 | #define ICR_OPTIONREG_SELECT 0x01 | ||
| 325 | #define ICR_ENAB_BRG_ZERO_INT 0x02 | ||
| 326 | #define ICR_USE_FS_FIFO 0x04 | ||
| 327 | #define ICR_ENAB_DCD_INT 0x08 | ||
| 328 | #define ICR_ENAB_SYNC_INT 0x10 | ||
| 329 | #define ICR_ENAB_CTS_INT 0x20 | ||
| 330 | #define ICR_ENAB_UNDERRUN_INT 0x40 | ||
| 331 | #define ICR_ENAB_BREAK_INT 0x80 | ||
| 332 | |||
| 333 | |||
| 334 | /* RR0: STATUS_REG "SR" */ | ||
| 335 | |||
| 336 | #define SR_CHAR_AVAIL 0x01 | ||
| 337 | #define SR_BRG_ZERO 0x02 | ||
| 338 | #define SR_TX_BUF_EMPTY 0x04 | ||
| 339 | #define SR_DCD 0x08 | ||
| 340 | #define SR_SYNC_ABORT 0x10 | ||
| 341 | #define SR_CTS 0x20 | ||
| 342 | #define SR_TX_UNDERRUN 0x40 | ||
| 343 | #define SR_BREAK 0x80 | ||
| 344 | |||
| 345 | |||
| 346 | /* RR1: SPCOND_STATUS_REG "SCSR" */ | ||
| 347 | |||
| 348 | #define SCSR_ALL_SENT 0x01 | ||
| 349 | #define SCSR_RESIDUAL_MASK 0x0e | ||
| 350 | #define SCSR_PARITY_ERR 0x10 | ||
| 351 | #define SCSR_RX_OVERRUN 0x20 | ||
| 352 | #define SCSR_CRC_FRAME_ERR 0x40 | ||
| 353 | #define SCSR_END_OF_FRAME 0x80 | ||
| 354 | |||
| 355 | |||
| 356 | /* RR3: INT_PENDING_REG "IPR" */ | ||
| 357 | |||
| 358 | #define IPR_B_EXTSTAT 0x01 | ||
| 359 | #define IPR_B_TX 0x02 | ||
| 360 | #define IPR_B_RX 0x04 | ||
| 361 | #define IPR_A_EXTSTAT 0x08 | ||
| 362 | #define IPR_A_TX 0x10 | ||
| 363 | #define IPR_A_RX 0x20 | ||
| 364 | |||
| 365 | |||
| 366 | /* RR7: FS_FIFO_HIGH_REG "FFHR" */ | ||
| 367 | |||
| 368 | #define FFHR_CNT_MASK 0x3f | ||
| 369 | #define FFHR_IS_FROM_FIFO 0x40 | ||
| 370 | #define FFHR_FIFO_OVERRUN 0x80 | ||
| 371 | |||
| 372 | |||
| 373 | /* RR10: DPLL_STATUS_REG "DSR" */ | ||
| 374 | |||
| 375 | #define DSR_ON_LOOP 0x02 | ||
| 376 | #define DSR_ON_LOOP_SENDING 0x10 | ||
| 377 | #define DSR_TWO_CLK_MISSING 0x40 | ||
| 378 | #define DSR_ONE_CLK_MISSING 0x80 | ||
| 379 | |||
| 380 | /***********************************************************************/ | ||
| 381 | /* */ | ||
| 382 | /* Register Access */ | ||
| 383 | /* */ | ||
| 384 | /***********************************************************************/ | ||
| 385 | |||
| 386 | |||
| 387 | /* The SCC needs 3.5 PCLK cycles recovery time between to register | ||
| 388 | * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 * | ||
| 389 | * 125 ns = 437.5 ns. This is too short for udelay(). | ||
| 390 | * 10/16/95: A tstb st_mfp.par_dt_reg takes 600ns (sure?) and thus should be | ||
| 391 | * quite right | ||
| 392 | */ | ||
| 393 | |||
| 394 | #define scc_reg_delay() \ | ||
| 395 | do { \ | ||
| 396 | if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) \ | ||
| 397 | __asm__ __volatile__ ( " nop; nop"); \ | ||
| 398 | else if (MACH_IS_ATARI) \ | ||
| 399 | __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\ | ||
| 400 | } while (0) | ||
| 401 | |||
| 402 | static unsigned char scc_shadow[2][16]; | ||
| 403 | |||
| 404 | /* The following functions should relax the somehow complicated | ||
| 405 | * register access of the SCC. _SCCwrite() stores all written values | ||
| 406 | * (except for WR0 and WR8) in shadow registers for later recall. This | ||
| 407 | * removes the burden of remembering written values as needed. The | ||
| 408 | * extra work of storing the value doesn't count, since a delay is | ||
| 409 | * needed after a SCC access anyway. Additionally, _SCCwrite() manages | ||
| 410 | * writes to WR0 and WR8 differently, because these can be accessed | ||
| 411 | * directly with less overhead. Another special case are WR7 and WR7'. | ||
| 412 | * _SCCwrite automatically checks what of this registers is selected | ||
| 413 | * and changes b0 of WR15 if needed. | ||
| 414 | * | ||
| 415 | * _SCCread() for standard read registers is straightforward, except | ||
| 416 | * for RR2 (split into two "virtual" registers: one for the value | ||
| 417 | * written to WR2 (from the shadow) and one for the vector including | ||
| 418 | * status from RR2, Ch. B) and RR3. The latter must be read from | ||
| 419 | * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can | ||
| 420 | * be accessed directly as before. | ||
| 421 | * | ||
| 422 | * The two inline function contain complicated switch statements. But | ||
| 423 | * I rely on regno and final_delay being constants, so gcc can reduce | ||
| 424 | * the whole stuff to just some assembler statements. | ||
| 425 | * | ||
| 426 | * _SCCwrite and _SCCread aren't intended to be used directly under | ||
| 427 | * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are | ||
| 428 | * for that purpose. They assume that a local variable 'port' is | ||
| 429 | * declared and pointing to the port's scc_struct entry. The | ||
| 430 | * variants with "_NB" appended should be used if no other SCC | ||
| 431 | * accesses follow immediately (within 0.5 usecs). They just skip the | ||
| 432 | * final delay nops. | ||
| 433 | * | ||
| 434 | * Please note that accesses to SCC registers should only take place | ||
| 435 | * when interrupts are turned off (at least if SCC interrupts are | ||
| 436 | * enabled). Otherwise, an interrupt could interfere with the | ||
| 437 | * two-stage accessing process. | ||
| 438 | * | ||
| 439 | */ | ||
| 440 | |||
| 441 | |||
| 442 | static __inline__ void _SCCwrite( | ||
| 443 | struct scc_port *port, | ||
| 444 | unsigned char *shadow, | ||
| 445 | volatile unsigned char *_scc_del, | ||
| 446 | int regno, | ||
| 447 | unsigned char val, int final_delay ) | ||
| 448 | { | ||
| 449 | switch( regno ) { | ||
| 450 | |||
| 451 | case COMMAND_REG: | ||
| 452 | /* WR0 can be written directly without pointing */ | ||
| 453 | *port->ctrlp = val; | ||
| 454 | break; | ||
| 455 | |||
| 456 | case SYNC_CHAR_REG: | ||
| 457 | /* For WR7, first set b0 of WR15 to 0, if needed */ | ||
| 458 | if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) { | ||
| 459 | *port->ctrlp = 15; | ||
| 460 | shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT; | ||
| 461 | scc_reg_delay(); | ||
| 462 | *port->ctrlp = shadow[INT_CTRL_REG]; | ||
| 463 | scc_reg_delay(); | ||
| 464 | } | ||
| 465 | goto normal_case; | ||
| 466 | |||
| 467 | case SDLC_OPTION_REG: | ||
| 468 | /* For WR7', first set b0 of WR15 to 1, if needed */ | ||
| 469 | if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) { | ||
| 470 | *port->ctrlp = 15; | ||
| 471 | shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT; | ||
| 472 | scc_reg_delay(); | ||
| 473 | *port->ctrlp = shadow[INT_CTRL_REG]; | ||
| 474 | scc_reg_delay(); | ||
| 475 | } | ||
| 476 | *port->ctrlp = 7; | ||
| 477 | shadow[8] = val; /* WR7' shadowed at WR8 */ | ||
| 478 | scc_reg_delay(); | ||
| 479 | *port->ctrlp = val; | ||
| 480 | break; | ||
| 481 | |||
| 482 | case TX_DATA_REG: /* WR8 */ | ||
| 483 | /* TX_DATA_REG can be accessed directly on some h/w */ | ||
| 484 | if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) | ||
| 485 | { | ||
| 486 | *port->ctrlp = regno; | ||
| 487 | scc_reg_delay(); | ||
| 488 | *port->ctrlp = val; | ||
| 489 | } | ||
| 490 | else | ||
| 491 | *port->datap = val; | ||
| 492 | break; | ||
| 493 | |||
| 494 | case MASTER_INT_CTRL: | ||
| 495 | *port->ctrlp = regno; | ||
| 496 | val &= 0x3f; /* bits 6..7 are the reset commands */ | ||
| 497 | scc_shadow[0][regno] = val; | ||
| 498 | scc_reg_delay(); | ||
| 499 | *port->ctrlp = val; | ||
| 500 | break; | ||
| 501 | |||
| 502 | case DPLL_CTRL_REG: | ||
| 503 | *port->ctrlp = regno; | ||
| 504 | val &= 0x1f; /* bits 5..7 are the DPLL commands */ | ||
| 505 | shadow[regno] = val; | ||
| 506 | scc_reg_delay(); | ||
| 507 | *port->ctrlp = val; | ||
| 508 | break; | ||
| 509 | |||
| 510 | case 1 ... 6: | ||
| 511 | case 10 ... 13: | ||
| 512 | case 15: | ||
| 513 | normal_case: | ||
| 514 | *port->ctrlp = regno; | ||
| 515 | shadow[regno] = val; | ||
| 516 | scc_reg_delay(); | ||
| 517 | *port->ctrlp = val; | ||
| 518 | break; | ||
| 519 | |||
| 520 | default: | ||
| 521 | printk( "Bad SCC write access to WR%d\n", regno ); | ||
| 522 | break; | ||
| 523 | |||
| 524 | } | ||
| 525 | |||
| 526 | if (final_delay) | ||
| 527 | scc_reg_delay(); | ||
| 528 | } | ||
| 529 | |||
| 530 | |||
| 531 | static __inline__ unsigned char _SCCread( | ||
| 532 | struct scc_port *port, | ||
| 533 | unsigned char *shadow, | ||
| 534 | volatile unsigned char *_scc_del, | ||
| 535 | int regno, int final_delay ) | ||
| 536 | { | ||
| 537 | unsigned char rv; | ||
| 538 | |||
| 539 | switch( regno ) { | ||
| 540 | |||
| 541 | /* --- real read registers --- */ | ||
| 542 | case STATUS_REG: | ||
| 543 | rv = *port->ctrlp; | ||
| 544 | break; | ||
| 545 | |||
| 546 | case INT_PENDING_REG: | ||
| 547 | /* RR3: read only from Channel A! */ | ||
| 548 | port = port->port_a; | ||
| 549 | goto normal_case; | ||
| 550 | |||
| 551 | case RX_DATA_REG: | ||
| 552 | /* RR8 can be accessed directly on some h/w */ | ||
| 553 | if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) | ||
| 554 | { | ||
| 555 | *port->ctrlp = 8; | ||
| 556 | scc_reg_delay(); | ||
| 557 | rv = *port->ctrlp; | ||
| 558 | } | ||
| 559 | else | ||
| 560 | rv = *port->datap; | ||
| 561 | break; | ||
| 562 | |||
| 563 | case CURR_VECTOR_REG: | ||
| 564 | /* RR2 (vector including status) from Ch. B */ | ||
| 565 | port = port->port_b; | ||
| 566 | goto normal_case; | ||
| 567 | |||
| 568 | /* --- reading write registers: access the shadow --- */ | ||
| 569 | case 1 ... 7: | ||
| 570 | case 10 ... 15: | ||
| 571 | return shadow[regno]; /* no final delay! */ | ||
| 572 | |||
| 573 | /* WR7' is special, because it is shadowed at the place of WR8 */ | ||
| 574 | case SDLC_OPTION_REG: | ||
| 575 | return shadow[8]; /* no final delay! */ | ||
| 576 | |||
| 577 | /* WR9 is special too, because it is common for both channels */ | ||
| 578 | case MASTER_INT_CTRL: | ||
| 579 | return scc_shadow[0][9]; /* no final delay! */ | ||
| 580 | |||
| 581 | default: | ||
| 582 | printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W', | ||
| 583 | regno & ~16 ); | ||
| 584 | break; | ||
| 585 | |||
| 586 | case SPCOND_STATUS_REG: | ||
| 587 | case FS_FIFO_LOW_REG: | ||
| 588 | case FS_FIFO_HIGH_REG: | ||
| 589 | case DPLL_STATUS_REG: | ||
| 590 | normal_case: | ||
| 591 | *port->ctrlp = regno & 0x0f; | ||
| 592 | scc_reg_delay(); | ||
| 593 | rv = *port->ctrlp; | ||
| 594 | break; | ||
| 595 | |||
| 596 | } | ||
| 597 | |||
| 598 | if (final_delay) | ||
| 599 | scc_reg_delay(); | ||
| 600 | return rv; | ||
| 601 | } | ||
| 602 | |||
| 603 | #define SCC_ACCESS_INIT(port) \ | ||
| 604 | unsigned char *_scc_shadow = &scc_shadow[port->channel][0] | ||
| 605 | |||
| 606 | #define SCCwrite(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1) | ||
| 607 | #define SCCwrite_NB(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0) | ||
| 608 | #define SCCread(reg) _SCCread(port,_scc_shadow,scc_del,(reg),1) | ||
| 609 | #define SCCread_NB(reg) _SCCread(port,_scc_shadow,scc_del,(reg),0) | ||
| 610 | |||
| 611 | #define SCCmod(reg,and,or) SCCwrite((reg),(SCCread(reg)&(and))|(or)) | ||
| 612 | |||
| 613 | #endif /* _SCC_H */ | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | config HYPERV | ||
| 2 | tristate "Microsoft Hyper-V client drivers" | ||
| 3 | depends on X86 && ACPI && PCI | ||
| 4 | help | ||
| 5 | Select this option to run Linux as a Hyper-V client operating | ||
| 6 | system. | ||
| 7 | |||
| 8 | config HYPERV_UTILS | ||
| 9 | tristate "Microsoft Hyper-V Utilities driver" | ||
| 10 | depends on HYPERV && CONNECTOR && NLS | ||
| 11 | help | ||
| 12 | Select this option to enable the Hyper-V Utilities. | ||
| 13 | |||
| 14 | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | obj-$(CONFIG_HYPERV) += hv_vmbus.o | ||
| 2 | obj-$(CONFIG_HYPERV_UTILS) += hv_utils.o | ||
| 3 | |||
| 4 | hv_vmbus-y := vmbus_drv.o \ | ||
| 5 | hv.o connection.o channel.o \ | ||
| 6 | channel_mgmt.o ring_buffer.o | ||
| 7 | hv_utils-y := hv_util.o hv_kvp.o | ||
| @@ -26,8 +26,8 @@ · 25 unmodified lines | |||
| 26 | #include <linux/mm.h> | 26 | #include <linux/mm.h> |
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
| 29 | #include <linux/hyperv.h> | ||
| 29 | 30 | ||
| 30 | #include "hyperv.h" | ||
| 31 | #include "hyperv_vmbus.h" | 31 | #include "hyperv_vmbus.h" |
| 32 | 32 | ||
| 33 | #define NUM_PAGES_SPANNED(addr, len) \ | 33 | #define NUM_PAGES_SPANNED(addr, len) \ |
| @@ -76,15 +76,14 @@ void vmbus_get_debug_info(struct vmbus_channel *channel, · 42 unmodified lines | |||
| 76 | struct hv_monitor_page *monitorpage; | 76 | struct hv_monitor_page *monitorpage; |
| 77 | u8 monitor_group = (u8)channel->offermsg.monitorid / 32; | 77 | u8 monitor_group = (u8)channel->offermsg.monitorid / 32; |
| 78 | u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; | 78 | u8 monitor_offset = (u8)channel->offermsg.monitorid % 32; |
| 79 | /* u32 monitorBit = 1 << monitorOffset; */ | ||
| 80 | 79 | ||
| 81 | debuginfo->relid = channel->offermsg.child_relid; | 80 | debuginfo->relid = channel->offermsg.child_relid; |
| 82 | debuginfo->state = channel->state; | 81 | debuginfo->state = channel->state; |
| 83 | memcpy(&debuginfo->interfacetype, | 82 | memcpy(&debuginfo->interfacetype, |
| 84 | &channel->offermsg.offer.if_type, sizeof(struct hv_guid)); | 83 | &channel->offermsg.offer.if_type, sizeof(uuid_le)); |
| 85 | memcpy(&debuginfo->interface_instance, | 84 | memcpy(&debuginfo->interface_instance, |
| 86 | &channel->offermsg.offer.if_instance, | 85 | &channel->offermsg.offer.if_instance, |
| 87 | sizeof(struct hv_guid)); | 86 | sizeof(uuid_le)); |
| 88 | 87 | ||
| 89 | monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages; | 88 | monitorpage = (struct hv_monitor_page *)vmbus_connection.monitor_pages; |
| 90 | 89 | ||
| @@ -119,8 +118,8 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, · 28 unmodified lines | |||
| 119 | u32 recv_ringbuffer_size, void *userdata, u32 userdatalen, | 118 | u32 recv_ringbuffer_size, void *userdata, u32 userdatalen, |
| 120 | void (*onchannelcallback)(void *context), void *context) | 119 | void (*onchannelcallback)(void *context), void *context) |
| 121 | { | 120 | { |
| 122 | struct vmbus_channel_open_channel *openMsg; | 121 | struct vmbus_channel_open_channel *open_msg; |
| 123 | struct vmbus_channel_msginfo *openInfo = NULL; | 122 | struct vmbus_channel_msginfo *open_info = NULL; |
| 124 | void *in, *out; | 123 | void *in, *out; |
| 125 | unsigned long flags; | 124 | unsigned long flags; |
| 126 | int ret, t, err = 0; | 125 | int ret, t, err = 0; |
| @@ -173,24 +172,24 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, · 46 unmodified lines | |||
| 173 | } | 172 | } |
| 174 | 173 | ||
| 175 | /* Create and init the channel open message */ | 174 | /* Create and init the channel open message */ |
| 176 | openInfo = kmalloc(sizeof(*openInfo) + | 175 | open_info = kmalloc(sizeof(*open_info) + |
| 177 | sizeof(struct vmbus_channel_open_channel), | 176 | sizeof(struct vmbus_channel_open_channel), |
| 178 | GFP_KERNEL); | 177 | GFP_KERNEL); |
| 179 | if (!openInfo) { | 178 | if (!open_info) { |
| 180 | err = -ENOMEM; | 179 | err = -ENOMEM; |
| 181 | goto errorout; | 180 | goto errorout; |
| 182 | } | 181 | } |
| 183 | 182 | ||
| 184 | init_completion(&openInfo->waitevent); | 183 | init_completion(&open_info->waitevent); |
| 185 | 184 | ||
| 186 | openMsg = (struct vmbus_channel_open_channel *)openInfo->msg; | 185 | open_msg = (struct vmbus_channel_open_channel *)open_info->msg; |
| 187 | openMsg->header.msgtype = CHANNELMSG_OPENCHANNEL; | 186 | open_msg->header.msgtype = CHANNELMSG_OPENCHANNEL; |
| 188 | openMsg->openid = newchannel->offermsg.child_relid; | 187 | open_msg->openid = newchannel->offermsg.child_relid; |
| 189 | openMsg->child_relid = newchannel->offermsg.child_relid; | 188 | open_msg->child_relid = newchannel->offermsg.child_relid; |
| 190 | openMsg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle; | 189 | open_msg->ringbuffer_gpadlhandle = newchannel->ringbuffer_gpadlhandle; |
| 191 | openMsg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >> | 190 | open_msg->downstream_ringbuffer_pageoffset = send_ringbuffer_size >> |
| 192 | PAGE_SHIFT; | 191 | PAGE_SHIFT; |
| 193 | openMsg->server_contextarea_gpadlhandle = 0; | 192 | open_msg->server_contextarea_gpadlhandle = 0; |
| 194 | 193 | ||
| 195 | if (userdatalen > MAX_USER_DEFINED_BYTES) { | 194 | if (userdatalen > MAX_USER_DEFINED_BYTES) { |
| 196 | err = -EINVAL; | 195 | err = -EINVAL; |
| @@ -198,35 +197,35 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, · 1 unmodified line | |||
| 198 | } | 197 | } |
| 199 | 198 | ||
| 200 | if (userdatalen) | 199 | if (userdatalen) |
| 201 | memcpy(openMsg->userdata, userdata, userdatalen); | 200 | memcpy(open_msg->userdata, userdata, userdatalen); |
| 202 | 201 | ||
| 203 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); | 202 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
| 204 | list_add_tail(&openInfo->msglistentry, | 203 | list_add_tail(&open_info->msglistentry, |
| 205 | &vmbus_connection.chn_msg_list); | 204 | &vmbus_connection.chn_msg_list); |
| 206 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); | 205 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
| 207 | 206 | ||
| 208 | ret = vmbus_post_msg(openMsg, | 207 | ret = vmbus_post_msg(open_msg, |
| 209 | sizeof(struct vmbus_channel_open_channel)); | 208 | sizeof(struct vmbus_channel_open_channel)); |
| 210 | 209 | ||
| 211 | if (ret != 0) | 210 | if (ret != 0) |
| 212 | goto cleanup; | 211 | goto cleanup; |
| 213 | 212 | ||
| 214 | t = wait_for_completion_timeout(&openInfo->waitevent, 5*HZ); | 213 | t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); |
| 215 | if (t == 0) { | 214 | if (t == 0) { |
| 216 | err = -ETIMEDOUT; | 215 | err = -ETIMEDOUT; |
| 217 | goto errorout; | 216 | goto errorout; |
| 218 | } | 217 | } |
| 219 | 218 | ||
| 220 | 219 | ||
| 221 | if (openInfo->response.open_result.status) | 220 | if (open_info->response.open_result.status) |
| 222 | err = openInfo->response.open_result.status; | 221 | err = open_info->response.open_result.status; |
| 223 | 222 | ||
| 224 | cleanup: | 223 | cleanup: |
| 225 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); | 224 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
| 226 | list_del(&openInfo->msglistentry); | 225 | list_del(&open_info->msglistentry); |
| 227 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); | 226 | spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); |
| 228 | 227 | ||
| 229 | kfree(openInfo); | 228 | kfree(open_info); |
| 230 | return err; | 229 | return err; |
| 231 | 230 | ||
| 232 | errorout: | 231 | errorout: |
| @@ -234,56 +233,11 @@ errorout: · 1 unmodified line | |||
| 234 | hv_ringbuffer_cleanup(&newchannel->inbound); | 233 | hv_ringbuffer_cleanup(&newchannel->inbound); |
| 235 | free_pages((unsigned long)out, | 234 | free_pages((unsigned long)out, |
| 236 | get_order(send_ringbuffer_size + recv_ringbuffer_size)); | 235 | get_order(send_ringbuffer_size + recv_ringbuffer_size)); |
| 237 | kfree(openInfo); | 236 | kfree(open_info); |
| 238 | return err; | 237 | return err; |
| 239 | } | 238 | } |
| 240 | EXPORT_SYMBOL_GPL(vmbus_open); | 239 | EXPORT_SYMBOL_GPL(vmbus_open); |
| 241 | 240 | ||
| 242 | /* | ||
| 243 | * dump_gpadl_body - Dump the gpadl body message to the console for | ||
| 244 | * debugging purposes. | ||
| 245 | */ | ||
| 246 | static void dump_gpadl_body(struct vmbus_channel_gpadl_body *gpadl, u32 len) | ||
| 247 | { | ||
| 248 | int i; | ||
| 249 | int pfncount; | ||
| 250 | |||
| 251 | pfncount = (len - sizeof(struct vmbus_channel_gpadl_body)) / | ||
| 252 | sizeof(u64); | ||
| 253 | |||
| 254 | DPRINT_DBG(VMBUS, "gpadl body - len %d pfn count %d", len, pfncount); | ||
| 255 | |||
| 256 | for (i = 0; i < pfncount; i++) | ||
| 257 | DPRINT_DBG(VMBUS, "gpadl body - %d) pfn %llu", | ||
| 258 | i, gpadl->pfn[i]); | ||
| 259 | } | ||
| 260 | |||
| 261 | /* | ||
| 262 | * dump_gpadl_header - Dump the gpadl header message to the console for | ||
| 263 | * debugging purposes. | ||
| 264 | */ | ||
| 265 | static void dump_gpadl_header(struct vmbus_channel_gpadl_header *gpadl) | ||
| 266 | { | ||
| 267 | int i, j; | ||
| 268 | int pagecount; | ||
| 269 | |||
| 270 | DPRINT_DBG(VMBUS, | ||
| 271 | "gpadl header - relid %d, range count %d, range buflen %d", | ||
| 272 | gpadl->child_relid, gpadl->rangecount, gpadl->range_buflen); | ||
| 273 | for (i = 0; i < gpadl->rangecount; i++) { | ||
| 274 | pagecount = gpadl->range[i].byte_count >> PAGE_SHIFT; | ||
| 275 | pagecount = (pagecount > 26) ? 26 : pagecount; | ||
| 276 | |||
| 277 | DPRINT_DBG(VMBUS, "gpadl range %d - len %d offset %d " | ||
| 278 | "page count %d", i, gpadl->range[i].byte_count, | ||
| 279 | gpadl->range[i].byte_offset, pagecount); | ||
| 280 | |||
| 281 | for (j = 0; j < pagecount; j++) | ||
| 282 | DPRINT_DBG(VMBUS, "%d) pfn %llu", j, | ||
| 283 | gpadl->range[i].pfn_array[j]); | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | /* | 241 | /* |
| 288 | * create_gpadl_header - Creates a gpadl for the specified buffer | 242 | * create_gpadl_header - Creates a gpadl for the specified buffer |
| 289 | */ | 243 | */ |
| @@ -437,7 +391,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, · 147 unmodified lines | |||
| 437 | { | 391 | { |
| 438 | struct vmbus_channel_gpadl_header *gpadlmsg; | 392 | struct vmbus_channel_gpadl_header *gpadlmsg; |
| 439 | struct vmbus_channel_gpadl_body *gpadl_body; | 393 | struct vmbus_channel_gpadl_body *gpadl_body; |
| 440 | /* struct vmbus_channel_gpadl_created *gpadlCreated; */ | ||
| 441 | struct vmbus_channel_msginfo *msginfo = NULL; | 394 | struct vmbus_channel_msginfo *msginfo = NULL; |
| 442 | struct vmbus_channel_msginfo *submsginfo; | 395 | struct vmbus_channel_msginfo *submsginfo; |
| 443 | u32 msgcount; | 396 | u32 msgcount; |
| @@ -461,7 +414,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, · 17 unmodified lines | |||
| 461 | gpadlmsg->child_relid = channel->offermsg.child_relid; | 414 | gpadlmsg->child_relid = channel->offermsg.child_relid; |
| 462 | gpadlmsg->gpadl = next_gpadl_handle; | 415 | gpadlmsg->gpadl = next_gpadl_handle; |
| 463 | 416 | ||
| 464 | dump_gpadl_header(gpadlmsg); | ||
| 465 | 417 | ||
| 466 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); | 418 | spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); |
| 467 | list_add_tail(&msginfo->msglistentry, | 419 | list_add_tail(&msginfo->msglistentry, |
| @@ -485,8 +437,6 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer, · 17 unmodified lines | |||
| 485 | CHANNELMSG_GPADL_BODY; | 437 | CHANNELMSG_GPADL_BODY; |
| 486 | gpadl_body->gpadl = next_gpadl_handle; | 438 | gpadl_body->gpadl = next_gpadl_handle; |
| 487 | 439 | ||
| 488 | dump_gpadl_body(gpadl_body, submsginfo->msgsize - | ||
| 489 | sizeof(*submsginfo)); | ||
| 490 | ret = vmbus_post_msg(gpadl_body, | 440 | ret = vmbus_post_msg(gpadl_body, |
| 491 | submsginfo->msgsize - | 441 | submsginfo->msgsize - |
| 492 | sizeof(*submsginfo)); | 442 | sizeof(*submsginfo)); |
| @@ -522,8 +472,6 @@ int vmbus_teardown_gpadl(struct vmbus_channel *channel, u32 gpadl_handle) · 29 unmodified lines | |||
| 522 | unsigned long flags; | 472 | unsigned long flags; |
| 523 | int ret, t; | 473 | int ret, t; |
| 524 | 474 | ||
| 525 | /* ASSERT(gpadl_handle != 0); */ | ||
| 526 | |||
| 527 | info = kmalloc(sizeof(*info) + | 475 | info = kmalloc(sizeof(*info) + |
| 528 | sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL); | 476 | sizeof(struct vmbus_channel_gpadl_teardown), GFP_KERNEL); |
| 529 | if (!info) | 477 | if (!info) |
| @@ -565,9 +513,12 @@ void vmbus_close(struct vmbus_channel *channel) · 35 unmodified lines | |||
| 565 | { | 513 | { |
| 566 | struct vmbus_channel_close_channel *msg; | 514 | struct vmbus_channel_close_channel *msg; |
| 567 | int ret; | 515 | int ret; |
| 516 | unsigned long flags; | ||
| 568 | 517 | ||
| 569 | /* Stop callback and cancel the timer asap */ | 518 | /* Stop callback and cancel the timer asap */ |
| 519 | spin_lock_irqsave(&channel->inbound_lock, flags); | ||
| 570 | channel->onchannel_callback = NULL; | 520 | channel->onchannel_callback = NULL; |
| 521 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 571 | 522 | ||
| 572 | /* Send a closing message */ | 523 | /* Send a closing message */ |
| 573 | 524 | ||
| @@ -787,19 +738,15 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, · 213 unmodified lines | |||
| 787 | u32 packetlen; | 738 | u32 packetlen; |
| 788 | u32 userlen; | 739 | u32 userlen; |
| 789 | int ret; | 740 | int ret; |
| 790 | unsigned long flags; | ||
| 791 | 741 | ||
| 792 | *buffer_actual_len = 0; | 742 | *buffer_actual_len = 0; |
| 793 | *requestid = 0; | 743 | *requestid = 0; |
| 794 | 744 | ||
| 795 | spin_lock_irqsave(&channel->inbound_lock, flags); | ||
| 796 | 745 | ||
| 797 | ret = hv_ringbuffer_peek(&channel->inbound, &desc, | 746 | ret = hv_ringbuffer_peek(&channel->inbound, &desc, |
| 798 | sizeof(struct vmpacket_descriptor)); | 747 | sizeof(struct vmpacket_descriptor)); |
| 799 | if (ret != 0) { | 748 | if (ret != 0) |
| 800 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 801 | return 0; | 749 | return 0; |
| 802 | } | ||
| 803 | 750 | ||
| 804 | packetlen = desc.len8 << 3; | 751 | packetlen = desc.len8 << 3; |
| 805 | userlen = packetlen - (desc.offset8 << 3); | 752 | userlen = packetlen - (desc.offset8 << 3); |
| @@ -807,7 +754,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, · 1 unmodified line | |||
| 807 | *buffer_actual_len = userlen; | 754 | *buffer_actual_len = userlen; |
| 808 | 755 | ||
| 809 | if (userlen > bufferlen) { | 756 | if (userlen > bufferlen) { |
| 810 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 811 | 757 | ||
| 812 | pr_err("Buffer too small - got %d needs %d\n", | 758 | pr_err("Buffer too small - got %d needs %d\n", |
| 813 | bufferlen, userlen); | 759 | bufferlen, userlen); |
| @@ -820,7 +766,6 @@ int vmbus_recvpacket(struct vmbus_channel *channel, void *buffer, · 6 unmodified lines | |||
| 820 | ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen, | 766 | ret = hv_ringbuffer_read(&channel->inbound, buffer, userlen, |
| 821 | (desc.offset8 << 3)); | 767 | (desc.offset8 << 3)); |
| 822 | 768 | ||
| 823 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 824 | 769 | ||
| 825 | return 0; | 770 | return 0; |
| 826 | } | 771 | } |
| @@ -837,19 +782,15 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, · 10 unmodified lines | |||
| 837 | u32 packetlen; | 782 | u32 packetlen; |
| 838 | u32 userlen; | 783 | u32 userlen; |
| 839 | int ret; | 784 | int ret; |
| 840 | unsigned long flags; | ||
| 841 | 785 | ||
| 842 | *buffer_actual_len = 0; | 786 | *buffer_actual_len = 0; |
| 843 | *requestid = 0; | 787 | *requestid = 0; |
| 844 | 788 | ||
| 845 | spin_lock_irqsave(&channel->inbound_lock, flags); | ||
| 846 | 789 | ||
| 847 | ret = hv_ringbuffer_peek(&channel->inbound, &desc, | 790 | ret = hv_ringbuffer_peek(&channel->inbound, &desc, |
| 848 | sizeof(struct vmpacket_descriptor)); | 791 | sizeof(struct vmpacket_descriptor)); |
| 849 | if (ret != 0) { | 792 | if (ret != 0) |
| 850 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 851 | return 0; | 793 | return 0; |
| 852 | } | ||
| 853 | 794 | ||
| 854 | 795 | ||
| 855 | packetlen = desc.len8 << 3; | 796 | packetlen = desc.len8 << 3; |
| @@ -858,12 +799,10 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, · 2 unmodified lines | |||
| 858 | *buffer_actual_len = packetlen; | 799 | *buffer_actual_len = packetlen; |
| 859 | 800 | ||
| 860 | if (packetlen > bufferlen) { | 801 | if (packetlen > bufferlen) { |
| 861 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 862 | |||
| 863 | pr_err("Buffer too small - needed %d bytes but " | 802 | pr_err("Buffer too small - needed %d bytes but " |
| 864 | "got space for only %d bytes\n", | 803 | "got space for only %d bytes\n", |
| 865 | packetlen, bufferlen); | 804 | packetlen, bufferlen); |
| 866 | return -2; | 805 | return -ENOBUFS; |
| 867 | } | 806 | } |
| 868 | 807 | ||
| 869 | *requestid = desc.trans_id; | 808 | *requestid = desc.trans_id; |
| @@ -871,7 +810,6 @@ int vmbus_recvpacket_raw(struct vmbus_channel *channel, void *buffer, · 1 unmodified line | |||
| 871 | /* Copy over the entire packet to the user buffer */ | 810 | /* Copy over the entire packet to the user buffer */ |
| 872 | ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0); | 811 | ret = hv_ringbuffer_read(&channel->inbound, buffer, packetlen, 0); |
| 873 | 812 | ||
| 874 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 875 | return 0; | 813 | return 0; |
| 876 | } | 814 | } |
| 877 | EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); | 815 | EXPORT_SYMBOL_GPL(vmbus_recvpacket_raw); |
| @@ -28,8 +28,8 @@ · 27 unmodified lines | |||
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/completion.h> | 30 | #include <linux/completion.h> |
| 31 | #include <linux/hyperv.h> | ||
| 31 | 32 | ||
| 32 | #include "hyperv.h" | ||
| 33 | #include "hyperv_vmbus.h" | 33 | #include "hyperv_vmbus.h" |
| 34 | 34 | ||
| 35 | struct vmbus_channel_message_table_entry { | 35 | struct vmbus_channel_message_table_entry { |
| @@ -40,12 +40,12 @@ struct vmbus_channel_message_table_entry { · 4 unmodified lines | |||
| 40 | #define MAX_MSG_TYPES 4 | 40 | #define MAX_MSG_TYPES 4 |
| 41 | #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 | 41 | #define MAX_NUM_DEVICE_CLASSES_SUPPORTED 8 |
| 42 | 42 | ||
| 43 | static const struct hv_guid | 43 | static const uuid_le |
| 44 | supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { | 44 | supported_device_classes[MAX_NUM_DEVICE_CLASSES_SUPPORTED] = { |
| 45 | /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ | 45 | /* {ba6163d9-04a1-4d29-b605-72e2ffb1dc7f} */ |
| 46 | /* Storage - SCSI */ | 46 | /* Storage - SCSI */ |
| 47 | { | 47 | { |
| 48 | .data = { | 48 | .b = { |
| 49 | 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, | 49 | 0xd9, 0x63, 0x61, 0xba, 0xa1, 0x04, 0x29, 0x4d, |
| 50 | 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f | 50 | 0xb6, 0x05, 0x72, 0xe2, 0xff, 0xb1, 0xdc, 0x7f |
| 51 | } | 51 | } |
| @@ -54,7 +54,7 @@ static const struct hv_guid · 2 unmodified lines | |||
| 54 | /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ | 54 | /* {F8615163-DF3E-46c5-913F-F2D2F965ED0E} */ |
| 55 | /* Network */ | 55 | /* Network */ |
| 56 | { | 56 | { |
| 57 | .data = { | 57 | .b = { |
| 58 | 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, | 58 | 0x63, 0x51, 0x61, 0xF8, 0x3E, 0xDF, 0xc5, 0x46, |
| 59 | 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E | 59 | 0x91, 0x3F, 0xF2, 0xD2, 0xF9, 0x65, 0xED, 0x0E |
| 60 | } | 60 | } |
| @@ -63,7 +63,7 @@ static const struct hv_guid · 2 unmodified lines | |||
| 63 | /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ | 63 | /* {CFA8B69E-5B4A-4cc0-B98B-8BA1A1F3F95A} */ |
| 64 | /* Input */ | 64 | /* Input */ |
| 65 | { | 65 | { |
| 66 | .data = { | 66 | .b = { |
| 67 | 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, | 67 | 0x9E, 0xB6, 0xA8, 0xCF, 0x4A, 0x5B, 0xc0, 0x4c, |
| 68 | 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A | 68 | 0xB9, 0x8B, 0x8B, 0xA1, 0xA1, 0xF3, 0xF9, 0x5A |
| 69 | } | 69 | } |
| @@ -72,7 +72,7 @@ static const struct hv_guid · 2 unmodified lines | |||
| 72 | /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ | 72 | /* {32412632-86cb-44a2-9b5c-50d1417354f5} */ |
| 73 | /* IDE */ | 73 | /* IDE */ |
| 74 | { | 74 | { |
| 75 | .data = { | 75 | .b = { |
| 76 | 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, | 76 | 0x32, 0x26, 0x41, 0x32, 0xcb, 0x86, 0xa2, 0x44, |
| 77 | 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 | 77 | 0x9b, 0x5c, 0x50, 0xd1, 0x41, 0x73, 0x54, 0xf5 |
| 78 | } | 78 | } |
| @@ -80,7 +80,7 @@ static const struct hv_guid · 1 unmodified line | |||
| 80 | /* 0E0B6031-5213-4934-818B-38D90CED39DB */ | 80 | /* 0E0B6031-5213-4934-818B-38D90CED39DB */ |
| 81 | /* Shutdown */ | 81 | /* Shutdown */ |
| 82 | { | 82 | { |
| 83 | .data = { | 83 | .b = { |
| 84 | 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, | 84 | 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, |
| 85 | 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB | 85 | 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB |
| 86 | } | 86 | } |
| @@ -88,7 +88,7 @@ static const struct hv_guid · 1 unmodified line | |||
| 88 | /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ | 88 | /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ |
| 89 | /* TimeSync */ | 89 | /* TimeSync */ |
| 90 | { | 90 | { |
| 91 | .data = { | 91 | .b = { |
| 92 | 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, | 92 | 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, |
| 93 | 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf | 93 | 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf |
| 94 | } | 94 | } |
| @@ -96,7 +96,7 @@ static const struct hv_guid · 1 unmodified line | |||
| 96 | /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ | 96 | /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ |
| 97 | /* Heartbeat */ | 97 | /* Heartbeat */ |
| 98 | { | 98 | { |
| 99 | .data = { | 99 | .b = { |
| 100 | 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, | 100 | 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, |
| 101 | 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d | 101 | 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d |
| 102 | } | 102 | } |
| @@ -104,7 +104,7 @@ static const struct hv_guid · 1 unmodified line | |||
| 104 | /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ | 104 | /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ |
| 105 | /* KVP */ | 105 | /* KVP */ |
| 106 | { | 106 | { |
| 107 | .data = { | 107 | .b = { |
| 108 | 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, | 108 | 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, |
| 109 | 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 | 109 | 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 |
| 110 | } | 110 | } |
| @@ -114,7 +114,7 @@ static const struct hv_guid · 3 unmodified lines | |||
| 114 | 114 | ||
| 115 | 115 | ||
| 116 | /** | 116 | /** |
| 117 | * prep_negotiate_resp() - Create default response for Hyper-V Negotiate message | 117 | * vmbus_prep_negotiate_resp() - Create default response for Hyper-V Negotiate message |
| 118 | * @icmsghdrp: Pointer to msg header structure | 118 | * @icmsghdrp: Pointer to msg header structure |
| 119 | * @icmsg_negotiate: Pointer to negotiate message structure | 119 | * @icmsg_negotiate: Pointer to negotiate message structure |
| 120 | * @buf: Raw buffer channel data | 120 | * @buf: Raw buffer channel data |
| @@ -128,9 +128,8 @@ static const struct hv_guid · 7 unmodified lines | |||
| 128 | * | 128 | * |
| 129 | * Mainly used by Hyper-V drivers. | 129 | * Mainly used by Hyper-V drivers. |
| 130 | */ | 130 | */ |
| 131 | void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, | 131 | void vmbus_prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, |
| 132 | struct icmsg_negotiate *negop, | 132 | struct icmsg_negotiate *negop, u8 *buf) |
| 133 | u8 *buf) | ||
| 134 | { | 133 | { |
| 135 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 134 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 136 | icmsghdrp->icmsgsize = 0x10; | 135 | icmsghdrp->icmsgsize = 0x10; |
| @@ -156,119 +155,7 @@ void prep_negotiate_resp(struct icmsg_hdr *icmsghdrp, · 19 unmodified lines | |||
| 156 | negop->icmsg_vercnt = 1; | 155 | negop->icmsg_vercnt = 1; |
| 157 | } | 156 | } |
| 158 | } | 157 | } |
| 159 | EXPORT_SYMBOL(prep_negotiate_resp); | 158 | EXPORT_SYMBOL_GPL(vmbus_prep_negotiate_resp); |
| 160 | |||
| 161 | /** | ||
| 162 | * chn_cb_negotiate() - Default handler for non IDE/SCSI/NETWORK | ||
| 163 | * Hyper-V requests | ||
| 164 | * @context: Pointer to argument structure. | ||
| 165 | * | ||
| 166 | * Set up the default handler for non device driver specific requests | ||
| 167 | * from Hyper-V. This stub responds to the default negotiate messages | ||
| 168 | * that come in for every non IDE/SCSI/Network request. | ||
| 169 | * This behavior is normally overwritten in the hv_utils driver. That | ||
| 170 | * driver handles requests like graceful shutdown, heartbeats etc. | ||
| 171 | * | ||
| 172 | * Mainly used by Hyper-V drivers. | ||
| 173 | */ | ||
| 174 | void chn_cb_negotiate(void *context) | ||
| 175 | { | ||
| 176 | struct vmbus_channel *channel = context; | ||
| 177 | u8 *buf; | ||
| 178 | u32 buflen, recvlen; | ||
| 179 | u64 requestid; | ||
| 180 | |||
| 181 | struct icmsg_hdr *icmsghdrp; | ||
| 182 | struct icmsg_negotiate *negop = NULL; | ||
| 183 | |||
| 184 | if (channel->util_index >= 0) { | ||
| 185 | /* | ||
| 186 | * This is a properly initialized util channel. | ||
| 187 | * Route this callback appropriately and setup state | ||
| 188 | * so that we don't need to reroute again. | ||
| 189 | */ | ||
| 190 | if (hv_cb_utils[channel->util_index].callback != NULL) { | ||
| 191 | /* | ||
| 192 | * The util driver has established a handler for | ||
| 193 | * this service; do the magic. | ||
| 194 | */ | ||
| 195 | channel->onchannel_callback = | ||
| 196 | hv_cb_utils[channel->util_index].callback; | ||
| 197 | (hv_cb_utils[channel->util_index].callback)(channel); | ||
| 198 | return; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | buflen = PAGE_SIZE; | ||
| 203 | buf = kmalloc(buflen, GFP_ATOMIC); | ||
| 204 | |||
| 205 | vmbus_recvpacket(channel, buf, buflen, &recvlen, &requestid); | ||
| 206 | |||
| 207 | if (recvlen > 0) { | ||
| 208 | icmsghdrp = (struct icmsg_hdr *)&buf[ | ||
| 209 | sizeof(struct vmbuspipe_hdr)]; | ||
| 210 | |||
| 211 | prep_negotiate_resp(icmsghdrp, negop, buf); | ||
| 212 | |||
| 213 | icmsghdrp->icflags = ICMSGHDRFLAG_TRANSACTION | ||
| 214 | | ICMSGHDRFLAG_RESPONSE; | ||
| 215 | |||
| 216 | vmbus_sendpacket(channel, buf, | ||
| 217 | recvlen, requestid, | ||
| 218 | VM_PKT_DATA_INBAND, 0); | ||
| 219 | } | ||
| 220 | |||
| 221 | kfree(buf); | ||
| 222 | } | ||
| 223 | EXPORT_SYMBOL(chn_cb_negotiate); | ||
| 224 | |||
| 225 | /* | ||
| 226 | * Function table used for message responses for non IDE/SCSI/Network type | ||
| 227 | * messages. (Such as KVP/Shutdown etc) | ||
| 228 | */ | ||
| 229 | struct hyperv_service_callback hv_cb_utils[MAX_MSG_TYPES] = { | ||
| 230 | /* 0E0B6031-5213-4934-818B-38D90CED39DB */ | ||
| 231 | /* Shutdown */ | ||
| 232 | { | ||
| 233 | .msg_type = HV_SHUTDOWN_MSG, | ||
| 234 | .data = { | ||
| 235 | 0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, | ||
| 236 | 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB | ||
| 237 | }, | ||
| 238 | .log_msg = "Shutdown channel functionality initialized" | ||
| 239 | }, | ||
| 240 | |||
| 241 | /* {9527E630-D0AE-497b-ADCE-E80AB0175CAF} */ | ||
| 242 | /* TimeSync */ | ||
| 243 | { | ||
| 244 | .msg_type = HV_TIMESYNC_MSG, | ||
| 245 | .data = { | ||
| 246 | 0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, | ||
| 247 | 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf | ||
| 248 | }, | ||
| 249 | .log_msg = "Timesync channel functionality initialized" | ||
| 250 | }, | ||
| 251 | /* {57164f39-9115-4e78-ab55-382f3bd5422d} */ | ||
| 252 | /* Heartbeat */ | ||
| 253 | { | ||
| 254 | .msg_type = HV_HEARTBEAT_MSG, | ||
| 255 | .data = { | ||
| 256 | 0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, | ||
| 257 | 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d | ||
| 258 | }, | ||
| 259 | .log_msg = "Heartbeat channel functionality initialized" | ||
| 260 | }, | ||
| 261 | /* {A9A0F4E7-5A45-4d96-B827-8A841E8C03E6} */ | ||
| 262 | /* KVP */ | ||
| 263 | { | ||
| 264 | .data = { | ||
| 265 | 0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, | ||
| 266 | 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6 | ||
| 267 | }, | ||
| 268 | .log_msg = "KVP channel functionality initialized" | ||
| 269 | }, | ||
| 270 | }; | ||
| 271 | EXPORT_SYMBOL(hv_cb_utils); | ||
| 272 | 159 | ||
| 273 | /* | 160 | /* |
| 274 | * alloc_channel - Allocate and initialize a vmbus channel object | 161 | * alloc_channel - Allocate and initialize a vmbus channel object |
| @@ -309,7 +196,7 @@ static void release_channel(struct work_struct *work) · 34 unmodified lines | |||
| 309 | /* | 196 | /* |
| 310 | * free_channel - Release the resources used by the vmbus channel object | 197 | * free_channel - Release the resources used by the vmbus channel object |
| 311 | */ | 198 | */ |
| 312 | void free_channel(struct vmbus_channel *channel) | 199 | static void free_channel(struct vmbus_channel *channel) |
| 313 | { | 200 | { |
| 314 | 201 | ||
| 315 | /* | 202 | /* |
| @@ -333,7 +220,7 @@ static void vmbus_process_rescind_offer(struct work_struct *work) · 17 unmodified lines | |||
| 333 | struct vmbus_channel, | 220 | struct vmbus_channel, |
| 334 | work); | 221 | work); |
| 335 | 222 | ||
| 336 | vmbus_child_device_unregister(channel->device_obj); | 223 | vmbus_device_unregister(channel->device_obj); |
| 337 | } | 224 | } |
| 338 | 225 | ||
| 339 | /* | 226 | /* |
| @@ -348,7 +235,6 @@ static void vmbus_process_offer(struct work_struct *work) · 8 unmodified lines | |||
| 348 | struct vmbus_channel *channel; | 235 | struct vmbus_channel *channel; |
| 349 | bool fnew = true; | 236 | bool fnew = true; |
| 350 | int ret; | 237 | int ret; |
| 351 | int cnt; | ||
| 352 | unsigned long flags; | 238 | unsigned long flags; |
| 353 | 239 | ||
| 354 | /* The next possible work is rescind handling */ | 240 | /* The next possible work is rescind handling */ |
| @@ -358,12 +244,10 @@ static void vmbus_process_offer(struct work_struct *work) · 3 unmodified lines | |||
| 358 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); | 244 | spin_lock_irqsave(&vmbus_connection.channel_lock, flags); |
| 359 | 245 | ||
| 360 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { | 246 | list_for_each_entry(channel, &vmbus_connection.chn_list, listentry) { |
| 361 | if (!memcmp(&channel->offermsg.offer.if_type, | 247 | if (!uuid_le_cmp(channel->offermsg.offer.if_type, |
| 362 | &newchannel->offermsg.offer.if_type, | 248 | newchannel->offermsg.offer.if_type) && |
| 363 | sizeof(struct hv_guid)) && | 249 | !uuid_le_cmp(channel->offermsg.offer.if_instance, |
| 364 | !memcmp(&channel->offermsg.offer.if_instance, | 250 | newchannel->offermsg.offer.if_instance)) { |
| 365 | &newchannel->offermsg.offer.if_instance, | ||
| 366 | sizeof(struct hv_guid))) { | ||
| 367 | fnew = false; | 251 | fnew = false; |
| 368 | break; | 252 | break; |
| 369 | } | 253 | } |
| @@ -385,7 +269,7 @@ static void vmbus_process_offer(struct work_struct *work) · 15 unmodified lines | |||
| 385 | * We need to set the DeviceObject field before calling | 269 | * We need to set the DeviceObject field before calling |
| 386 | * vmbus_child_dev_add() | 270 | * vmbus_child_dev_add() |
| 387 | */ | 271 | */ |
| 388 | newchannel->device_obj = vmbus_child_device_create( | 272 | newchannel->device_obj = vmbus_device_create( |
| 389 | &newchannel->offermsg.offer.if_type, | 273 | &newchannel->offermsg.offer.if_type, |
| 390 | &newchannel->offermsg.offer.if_instance, | 274 | &newchannel->offermsg.offer.if_instance, |
| 391 | newchannel); | 275 | newchannel); |
| @@ -395,7 +279,7 @@ static void vmbus_process_offer(struct work_struct *work) · 3 unmodified lines | |||
| 395 | * binding which eventually invokes the device driver's AddDevice() | 279 | * binding which eventually invokes the device driver's AddDevice() |
| 396 | * method. | 280 | * method. |
| 397 | */ | 281 | */ |
| 398 | ret = vmbus_child_device_register(newchannel->device_obj); | 282 | ret = vmbus_device_register(newchannel->device_obj); |
| 399 | if (ret != 0) { | 283 | if (ret != 0) { |
| 400 | pr_err("unable to add child device object (relid %d)\n", | 284 | pr_err("unable to add child device object (relid %d)\n", |
| 401 | newchannel->offermsg.child_relid); | 285 | newchannel->offermsg.child_relid); |
| @@ -412,48 +296,26 @@ static void vmbus_process_offer(struct work_struct *work) · 10 unmodified lines | |||
| 412 | * can cleanup properly | 296 | * can cleanup properly |
| 413 | */ | 297 | */ |
| 414 | newchannel->state = CHANNEL_OPEN_STATE; | 298 | newchannel->state = CHANNEL_OPEN_STATE; |
| 415 | newchannel->util_index = -1; /* Invalid index */ | ||
| 416 | |||
| 417 | /* Open IC channels */ | ||
| 418 | for (cnt = 0; cnt < MAX_MSG_TYPES; cnt++) { | ||
| 419 | if (memcmp(&newchannel->offermsg.offer.if_type, | ||
| 420 | &hv_cb_utils[cnt].data, | ||
| 421 | sizeof(struct hv_guid)) == 0 && | ||
| 422 | vmbus_open(newchannel, 2 * PAGE_SIZE, | ||
| 423 | 2 * PAGE_SIZE, NULL, 0, | ||
| 424 | chn_cb_negotiate, | ||
| 425 | newchannel) == 0) { | ||
| 426 | hv_cb_utils[cnt].channel = newchannel; | ||
| 427 | newchannel->util_index = cnt; | ||
| 428 | |||
| 429 | pr_info("%s\n", hv_cb_utils[cnt].log_msg); | ||
| 430 | |||
| 431 | } | ||
| 432 | } | ||
| 433 | } | 299 | } |
| 434 | } | 300 | } |
| 435 | 301 | ||
| 436 | /* | 302 | /* |
| 437 | * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. | 303 | * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. |
| 438 | * | 304 | * |
| 439 | * We ignore all offers except network and storage offers. For each network and | ||
| 440 | * storage offers, we create a channel object and queue a work item to the | ||
| 441 | * channel object to process the offer synchronously | ||
| 442 | */ | 305 | */ |
| 443 | static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) | 306 | static void vmbus_onoffer(struct vmbus_channel_message_header *hdr) |
| 444 | { | 307 | { |
| 445 | struct vmbus_channel_offer_channel *offer; | 308 | struct vmbus_channel_offer_channel *offer; |
| 446 | struct vmbus_channel *newchannel; | 309 | struct vmbus_channel *newchannel; |
| 447 | struct hv_guid *guidtype; | 310 | uuid_le *guidtype; |
| 448 | struct hv_guid *guidinstance; | 311 | uuid_le *guidinstance; |
| 449 | int i; | 312 | int i; |
| 450 | int fsupported = 0; | 313 | int fsupported = 0; |
| 451 | 314 | ||
| 452 | offer = (struct vmbus_channel_offer_channel *)hdr; | 315 | offer = (struct vmbus_channel_offer_channel *)hdr; |
| 453 | for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { | 316 | for (i = 0; i < MAX_NUM_DEVICE_CLASSES_SUPPORTED; i++) { |
| 454 | if (memcmp(&offer->offer.if_type, | 317 | if (!uuid_le_cmp(offer->offer.if_type, |
| 455 | &supported_device_classes[i], | 318 | supported_device_classes[i])) { |
| 456 | sizeof(struct hv_guid)) == 0) { | ||
| 457 | fsupported = 1; | 319 | fsupported = 1; |
| 458 | break; | 320 | break; |
| 459 | } | 321 | } |
| @@ -25,11 +25,12 @@ · 24 unmodified lines | |||
| 25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
| 26 | #include <linux/sched.h> | 26 | #include <linux/sched.h> |
| 27 | #include <linux/wait.h> | 27 | #include <linux/wait.h> |
| 28 | #include <linux/delay.h> | ||
| 28 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
| 29 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 30 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
| 31 | 32 | #include <linux/hyperv.h> | |
| 32 | #include "hyperv.h" | 33 | #include <asm/hyperv.h> |
| 33 | #include "hyperv_vmbus.h" | 34 | #include "hyperv_vmbus.h" |
| 34 | 35 | ||
| 35 | 36 | ||
| @@ -49,10 +50,6 @@ int vmbus_connect(void) · 13 unmodified lines | |||
| 49 | struct vmbus_channel_initiate_contact *msg; | 50 | struct vmbus_channel_initiate_contact *msg; |
| 50 | unsigned long flags; | 51 | unsigned long flags; |
| 51 | 52 | ||
| 52 | /* Make sure we are not connecting or connected */ | ||
| 53 | if (vmbus_connection.conn_state != DISCONNECTED) | ||
| 54 | return -EISCONN; | ||
| 55 | |||
| 56 | /* Initialize the vmbus connection */ | 53 | /* Initialize the vmbus connection */ |
| 57 | vmbus_connection.conn_state = CONNECTING; | 54 | vmbus_connection.conn_state = CONNECTING; |
| 58 | vmbus_connection.work_queue = create_workqueue("hv_vmbus_con"); | 55 | vmbus_connection.work_queue = create_workqueue("hv_vmbus_con"); |
| @@ -214,8 +211,7 @@ struct vmbus_channel *relid2channel(u32 relid) · 155 unmodified lines | |||
| 214 | static void process_chn_event(u32 relid) | 211 | static void process_chn_event(u32 relid) |
| 215 | { | 212 | { |
| 216 | struct vmbus_channel *channel; | 213 | struct vmbus_channel *channel; |
| 217 | 214 | unsigned long flags; | |
| 218 | /* ASSERT(relId > 0); */ | ||
| 219 | 215 | ||
| 220 | /* | 216 | /* |
| 221 | * Find the channel based on this relid and invokes the | 217 | * Find the channel based on this relid and invokes the |
| @@ -223,11 +219,27 @@ static void process_chn_event(u32 relid) · 1 unmodified line | |||
| 223 | */ | 219 | */ |
| 224 | channel = relid2channel(relid); | 220 | channel = relid2channel(relid); |
| 225 | 221 | ||
| 226 | if (channel) { | 222 | if (!channel) { |
| 227 | channel->onchannel_callback(channel->channel_callback_context); | ||
| 228 | } else { | ||
| 229 | pr_err("channel not found for relid - %u\n", relid); | 223 | pr_err("channel not found for relid - %u\n", relid); |
| 224 | return; | ||
| 230 | } | 225 | } |
| 226 | |||
| 227 | /* | ||
| 228 | * A channel once created is persistent even when there | ||
| 229 | * is no driver handling the device. An unloading driver | ||
| 230 | * sets the onchannel_callback to NULL under the | ||
| 231 | * protection of the channel inbound_lock. Thus, checking | ||
| 232 | * and invoking the driver specific callback takes care of | ||
| 233 | * orderly unloading of the driver. | ||
| 234 | */ | ||
| 235 | |||
| 236 | spin_lock_irqsave(&channel->inbound_lock, flags); | ||
| 237 | if (channel->onchannel_callback != NULL) | ||
| 238 | channel->onchannel_callback(channel->channel_callback_context); | ||
| 239 | else | ||
| 240 | pr_err("no channel callback for relid - %u\n", relid); | ||
| 241 | |||
| 242 | spin_unlock_irqrestore(&channel->inbound_lock, flags); | ||
| 231 | } | 243 | } |
| 232 | 244 | ||
| 233 | /* | 245 | /* |
| @@ -248,16 +260,17 @@ void vmbus_on_event(unsigned long data) · 14 unmodified lines | |||
| 248 | if (!recv_int_page[dword]) | 260 | if (!recv_int_page[dword]) |
| 249 | continue; | 261 | continue; |
| 250 | for (bit = 0; bit < 32; bit++) { | 262 | for (bit = 0; bit < 32; bit++) { |
| 251 | if (sync_test_and_clear_bit(bit, (unsigned long *)&recv_int_page[dword])) { | 263 | if (sync_test_and_clear_bit(bit, |
| 264 | (unsigned long *)&recv_int_page[dword])) { | ||
| 252 | relid = (dword << 5) + bit; | 265 | relid = (dword << 5) + bit; |
| 253 | 266 | ||
| 254 | if (relid == 0) { | 267 | if (relid == 0) |
| 255 | /* | 268 | /* |
| 256 | * Special case - vmbus | 269 | * Special case - vmbus |
| 257 | * channel protocol msg | 270 | * channel protocol msg |
| 258 | */ | 271 | */ |
| 259 | continue; | 272 | continue; |
| 260 | } | 273 | |
| 261 | process_chn_event(relid); | 274 | process_chn_event(relid); |
| 262 | } | 275 | } |
| 263 | } | 276 | } |
| @@ -270,10 +283,25 @@ void vmbus_on_event(unsigned long data) · 6 unmodified lines | |||
| 270 | int vmbus_post_msg(void *buffer, size_t buflen) | 283 | int vmbus_post_msg(void *buffer, size_t buflen) |
| 271 | { | 284 | { |
| 272 | union hv_connection_id conn_id; | 285 | union hv_connection_id conn_id; |
| 286 | int ret = 0; | ||
| 287 | int retries = 0; | ||
| 273 | 288 | ||
| 274 | conn_id.asu32 = 0; | 289 | conn_id.asu32 = 0; |
| 275 | conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; | 290 | conn_id.u.id = VMBUS_MESSAGE_CONNECTION_ID; |
| 276 | return hv_post_message(conn_id, 1, buffer, buflen); | 291 | |
| 292 | /* | ||
| 293 | * hv_post_message() can have transient failures because of | ||
| 294 | * insufficient resources. Retry the operation a couple of | ||
| 295 | * times before giving up. | ||
| 296 | */ | ||
| 297 | while (retries < 3) { | ||
| 298 | ret = hv_post_message(conn_id, 1, buffer, buflen); | ||
| 299 | if (ret != HV_STATUS_INSUFFICIENT_BUFFERS) | ||
| 300 | return ret; | ||
| 301 | retries++; | ||
| 302 | msleep(100); | ||
| 303 | } | ||
| 304 | return ret; | ||
| 277 | } | 305 | } |
| 278 | 306 | ||
| 279 | /* | 307 | /* |
| @@ -25,8 +25,8 @@ · 24 unmodified lines | |||
| 25 | #include <linux/mm.h> | 25 | #include <linux/mm.h> |
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/vmalloc.h> | 27 | #include <linux/vmalloc.h> |
| 28 | 28 | #include <linux/hyperv.h> | |
| 29 | #include "hyperv.h" | 29 | #include <asm/hyperv.h> |
| 30 | #include "hyperv_vmbus.h" | 30 | #include "hyperv_vmbus.h" |
| 31 | 31 | ||
| 32 | /* The one and only */ | 32 | /* The one and only */ |
| @@ -111,7 +111,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) · 78 unmodified lines | |||
| 111 | u64 hv_status = 0; | 111 | u64 hv_status = 0; |
| 112 | u64 input_address = (input) ? virt_to_phys(input) : 0; | 112 | u64 input_address = (input) ? virt_to_phys(input) : 0; |
| 113 | u64 output_address = (output) ? virt_to_phys(output) : 0; | 113 | u64 output_address = (output) ? virt_to_phys(output) : 0; |
| 114 | volatile void *hypercall_page = hv_context.hypercall_page; | 114 | void *hypercall_page = hv_context.hypercall_page; |
| 115 | 115 | ||
| 116 | __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); | 116 | __asm__ __volatile__("mov %0, %%r8" : : "r" (output_address) : "r8"); |
| 117 | __asm__ __volatile__("call *%3" : "=a" (hv_status) : | 117 | __asm__ __volatile__("call *%3" : "=a" (hv_status) : |
| @@ -132,7 +132,7 @@ static u64 do_hypercall(u64 control, void *input, void *output) · 14 unmodified lines | |||
| 132 | u64 output_address = (output) ? virt_to_phys(output) : 0; | 132 | u64 output_address = (output) ? virt_to_phys(output) : 0; |
| 133 | u32 output_address_hi = output_address >> 32; | 133 | u32 output_address_hi = output_address >> 32; |
| 134 | u32 output_address_lo = output_address & 0xFFFFFFFF; | 134 | u32 output_address_lo = output_address & 0xFFFFFFFF; |
| 135 | volatile void *hypercall_page = hv_context.hypercall_page; | 135 | void *hypercall_page = hv_context.hypercall_page; |
| 136 | 136 | ||
| 137 | __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), | 137 | __asm__ __volatile__ ("call *%8" : "=d"(hv_status_hi), |
| 138 | "=a"(hv_status_lo) : "d" (control_hi), | 138 | "=a"(hv_status_lo) : "d" (control_hi), |
| @@ -151,7 +151,6 @@ static u64 do_hypercall(u64 control, void *input, void *output) · 12 unmodified lines | |||
| 151 | */ | 151 | */ |
| 152 | int hv_init(void) | 152 | int hv_init(void) |
| 153 | { | 153 | { |
| 154 | int ret = 0; | ||
| 155 | int max_leaf; | 154 | int max_leaf; |
| 156 | union hv_x64_msr_hypercall_contents hypercall_msr; | 155 | union hv_x64_msr_hypercall_contents hypercall_msr; |
| 157 | void *virtaddr = NULL; | 156 | void *virtaddr = NULL; |
| @@ -164,11 +163,7 @@ int hv_init(void) · 6 unmodified lines | |||
| 164 | goto cleanup; | 163 | goto cleanup; |
| 165 | 164 | ||
| 166 | max_leaf = query_hypervisor_info(); | 165 | max_leaf = query_hypervisor_info(); |
| 167 | /* HvQueryHypervisorFeatures(maxLeaf); */ | ||
| 168 | 166 | ||
| 169 | /* | ||
| 170 | * We only support running on top of Hyper-V | ||
| 171 | */ | ||
| 172 | rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); | 167 | rdmsrl(HV_X64_MSR_GUEST_OS_ID, hv_context.guestid); |
| 173 | 168 | ||
| 174 | if (hv_context.guestid != 0) | 169 | if (hv_context.guestid != 0) |
| @@ -181,10 +176,6 @@ int hv_init(void) · 6 unmodified lines | |||
| 181 | /* See if the hypercall page is already set */ | 176 | /* See if the hypercall page is already set */ |
| 182 | rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); | 177 | rdmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64); |
| 183 | 178 | ||
| 184 | /* | ||
| 185 | * Allocate the hypercall page memory | ||
| 186 | * virtaddr = osd_page_alloc(1); | ||
| 187 | */ | ||
| 188 | virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); | 179 | virtaddr = __vmalloc(PAGE_SIZE, GFP_KERNEL, PAGE_KERNEL_EXEC); |
| 189 | 180 | ||
| 190 | if (!virtaddr) | 181 | if (!virtaddr) |
| @@ -222,7 +213,7 @@ int hv_init(void) · 31 unmodified lines | |||
| 222 | hv_context.signal_event_param->flag_number = 0; | 213 | hv_context.signal_event_param->flag_number = 0; |
| 223 | hv_context.signal_event_param->rsvdz = 0; | 214 | hv_context.signal_event_param->rsvdz = 0; |
| 224 | 215 | ||
| 225 | return ret; | 216 | return 0; |
| 226 | 217 | ||
| 227 | cleanup: | 218 | cleanup: |
| 228 | if (virtaddr) { | 219 | if (virtaddr) { |
| @@ -233,8 +224,8 @@ cleanup: · 4 unmodified lines | |||
| 233 | 224 | ||
| 234 | vfree(virtaddr); | 225 | vfree(virtaddr); |
| 235 | } | 226 | } |
| 236 | ret = -1; | 227 | |
| 237 | return ret; | 228 | return -ENOTSUPP; |
| 238 | } | 229 | } |
| 239 | 230 | ||
| 240 | /* | 231 | /* |
| @@ -378,7 +369,7 @@ void hv_synic_init(void *irqarg) · 137 unmodified lines | |||
| 378 | shared_sint.as_uint64 = 0; | 369 | shared_sint.as_uint64 = 0; |
| 379 | shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */ | 370 | shared_sint.vector = irq_vector; /* HV_SHARED_SINT_IDT_VECTOR + 0x20; */ |
| 380 | shared_sint.masked = false; | 371 | shared_sint.masked = false; |
| 381 | shared_sint.auto_eoi = true; | 372 | shared_sint.auto_eoi = false; |
| 382 | 373 | ||
| 383 | wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); | 374 | wrmsrl(HV_X64_MSR_SINT0 + VMBUS_MESSAGE_SINT, shared_sint.as_uint64); |
| 384 | 375 | ||
| @@ -26,8 +26,8 @@ · 25 unmodified lines | |||
| 26 | #include <linux/nls.h> | 26 | #include <linux/nls.h> |
| 27 | #include <linux/connector.h> | 27 | #include <linux/connector.h> |
| 28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
| 29 | #include <linux/hyperv.h> | ||
| 29 | 30 | ||
| 30 | #include "hyperv.h" | ||
| 31 | #include "hv_kvp.h" | 31 | #include "hv_kvp.h" |
| 32 | 32 | ||
| 33 | 33 | ||
| @@ -44,21 +44,24 @@ · 10 unmodified lines | |||
| 44 | static struct { | 44 | static struct { |
| 45 | bool active; /* transaction status - active or not */ | 45 | bool active; /* transaction status - active or not */ |
| 46 | int recv_len; /* number of bytes received. */ | 46 | int recv_len; /* number of bytes received. */ |
| 47 | int index; /* current index */ | ||
| 47 | struct vmbus_channel *recv_channel; /* chn we got the request */ | 48 | struct vmbus_channel *recv_channel; /* chn we got the request */ |
| 48 | u64 recv_req_id; /* request ID. */ | 49 | u64 recv_req_id; /* request ID. */ |
| 49 | } kvp_transaction; | 50 | } kvp_transaction; |
| 50 | 51 | ||
| 51 | static int kvp_send_key(int index); | 52 | static void kvp_send_key(struct work_struct *dummy); |
| 53 | |||
| 54 | #define TIMEOUT_FIRED 1 | ||
| 52 | 55 | ||
| 53 | static void kvp_respond_to_host(char *key, char *value, int error); | 56 | static void kvp_respond_to_host(char *key, char *value, int error); |
| 54 | static void kvp_work_func(struct work_struct *dummy); | 57 | static void kvp_work_func(struct work_struct *dummy); |
| 55 | static void kvp_register(void); | 58 | static void kvp_register(void); |
| 56 | 59 | ||
| 57 | static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); | 60 | static DECLARE_DELAYED_WORK(kvp_work, kvp_work_func); |
| 61 | static DECLARE_WORK(kvp_sendkey_work, kvp_send_key); | ||
| 58 | 62 | ||
| 59 | static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; | 63 | static struct cb_id kvp_id = { CN_KVP_IDX, CN_KVP_VAL }; |
| 60 | static const char kvp_name[] = "kvp_kernel_module"; | 64 | static const char kvp_name[] = "kvp_kernel_module"; |
| 61 | static int timeout_fired; | ||
| 62 | static u8 *recv_buffer; | 65 | static u8 *recv_buffer; |
| 63 | /* | 66 | /* |
| 64 | * Register the kernel component with the user-level daemon. | 67 | * Register the kernel component with the user-level daemon. |
| @@ -90,8 +93,7 @@ kvp_work_func(struct work_struct *dummy) · 25 unmodified lines | |||
| 90 | * If the timer fires, the user-mode component has not responded; | 93 | * If the timer fires, the user-mode component has not responded; |
| 91 | * process the pending transaction. | 94 | * process the pending transaction. |
| 92 | */ | 95 | */ |
| 93 | kvp_respond_to_host("Unknown key", "Guest timed out", timeout_fired); | 96 | kvp_respond_to_host("Unknown key", "Guest timed out", TIMEOUT_FIRED); |
| 94 | timeout_fired = 1; | ||
| 95 | } | 97 | } |
| 96 | 98 | ||
| 97 | /* | 99 | /* |
| @@ -121,10 +123,11 @@ kvp_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) · 23 unmodified lines | |||
| 121 | } | 123 | } |
| 122 | } | 124 | } |
| 123 | 125 | ||
| 124 | static int | 126 | static void |
| 125 | kvp_send_key(int index) | 127 | kvp_send_key(struct work_struct *dummy) |
| 126 | { | 128 | { |
| 127 | struct cn_msg *msg; | 129 | struct cn_msg *msg; |
| 130 | int index = kvp_transaction.index; | ||
| 128 | 131 | ||
| 129 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); | 132 | msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC); |
| 130 | 133 | ||
| @@ -136,9 +139,8 @@ kvp_send_key(int index) · 5 unmodified lines | |||
| 136 | msg->len = sizeof(struct hv_ku_msg); | 139 | msg->len = sizeof(struct hv_ku_msg); |
| 137 | cn_netlink_send(msg, 0, GFP_ATOMIC); | 140 | cn_netlink_send(msg, 0, GFP_ATOMIC); |
| 138 | kfree(msg); | 141 | kfree(msg); |
| 139 | return 0; | ||
| 140 | } | 142 | } |
| 141 | return 1; | 143 | return; |
| 142 | } | 144 | } |
| 143 | 145 | ||
| 144 | /* | 146 | /* |
| @@ -177,6 +179,15 @@ kvp_respond_to_host(char *key, char *value, int error) · 32 unmodified lines | |||
| 177 | channel = kvp_transaction.recv_channel; | 179 | channel = kvp_transaction.recv_channel; |
| 178 | req_id = kvp_transaction.recv_req_id; | 180 | req_id = kvp_transaction.recv_req_id; |
| 179 | 181 | ||
| 182 | kvp_transaction.active = false; | ||
| 183 | |||
| 184 | if (channel->onchannel_callback == NULL) | ||
| 185 | /* | ||
| 186 | * We have raced with util driver being unloaded; | ||
| 187 | * silently return. | ||
| 188 | */ | ||
| 189 | return; | ||
| 190 | |||
| 180 | icmsghdrp = (struct icmsg_hdr *) | 191 | icmsghdrp = (struct icmsg_hdr *) |
| 181 | &recv_buffer[sizeof(struct vmbuspipe_hdr)]; | 192 | &recv_buffer[sizeof(struct vmbuspipe_hdr)]; |
| 182 | kvp_msg = (struct hv_kvp_msg *) | 193 | kvp_msg = (struct hv_kvp_msg *) |
| @@ -217,7 +228,6 @@ response_done: · 34 unmodified lines | |||
| 217 | vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, | 228 | vmbus_sendpacket(channel, recv_buffer, buf_len, req_id, |
| 218 | VM_PKT_DATA_INBAND, 0); | 229 | VM_PKT_DATA_INBAND, 0); |
| 219 | 230 | ||
| 220 | kvp_transaction.active = false; | ||
| 221 | } | 231 | } |
| 222 | 232 | ||
| 223 | /* | 233 | /* |
| @@ -243,10 +253,6 @@ void hv_kvp_onchannelcallback(void *context) · 19 unmodified lines | |||
| 243 | struct icmsg_negotiate *negop = NULL; | 253 | struct icmsg_negotiate *negop = NULL; |
| 244 | 254 | ||
| 245 | 255 | ||
| 246 | if (kvp_transaction.active) | ||
| 247 | return; | ||
| 248 | |||
| 249 | |||
| 250 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); | 256 | vmbus_recvpacket(channel, recv_buffer, PAGE_SIZE, &recvlen, &requestid); |
| 251 | 257 | ||
| 252 | if (recvlen > 0) { | 258 | if (recvlen > 0) { |
| @@ -254,7 +260,7 @@ void hv_kvp_onchannelcallback(void *context) · 1 unmodified line | |||
| 254 | sizeof(struct vmbuspipe_hdr)]; | 260 | sizeof(struct vmbuspipe_hdr)]; |
| 255 | 261 | ||
| 256 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 262 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 257 | prep_negotiate_resp(icmsghdrp, negop, recv_buffer); | 263 | vmbus_prep_negotiate_resp(icmsghdrp, negop, recv_buffer); |
| 258 | } else { | 264 | } else { |
| 259 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ | 265 | kvp_msg = (struct hv_kvp_msg *)&recv_buffer[ |
| 260 | sizeof(struct vmbuspipe_hdr) + | 266 | sizeof(struct vmbuspipe_hdr) + |
| @@ -282,6 +288,7 @@ void hv_kvp_onchannelcallback(void *context) · 21 unmodified lines | |||
| 282 | kvp_transaction.recv_channel = channel; | 288 | kvp_transaction.recv_channel = channel; |
| 283 | kvp_transaction.recv_req_id = requestid; | 289 | kvp_transaction.recv_req_id = requestid; |
| 284 | kvp_transaction.active = true; | 290 | kvp_transaction.active = true; |
| 291 | kvp_transaction.index = kvp_data->index; | ||
| 285 | 292 | ||
| 286 | /* | 293 | /* |
| 287 | * Get the information from the | 294 | * Get the information from the |
| @@ -292,8 +299,8 @@ void hv_kvp_onchannelcallback(void *context) · 4 unmodified lines | |||
| 292 | * Set a timeout to deal with | 299 | * Set a timeout to deal with |
| 293 | * user-mode not responding. | 300 | * user-mode not responding. |
| 294 | */ | 301 | */ |
| 295 | kvp_send_key(kvp_data->index); | 302 | schedule_work(&kvp_sendkey_work); |
| 296 | schedule_delayed_work(&kvp_work, 100); | 303 | schedule_delayed_work(&kvp_work, 5*HZ); |
| 297 | 304 | ||
| 298 | return; | 305 | return; |
| 299 | 306 | ||
| @@ -312,16 +319,14 @@ callback_done: · 12 unmodified lines | |||
| 312 | } | 319 | } |
| 313 | 320 | ||
| 314 | int | 321 | int |
| 315 | hv_kvp_init(void) | 322 | hv_kvp_init(struct hv_util_service *srv) |
| 316 | { | 323 | { |
| 317 | int err; | 324 | int err; |
| 318 | 325 | ||
| 319 | err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback); | 326 | err = cn_add_callback(&kvp_id, kvp_name, kvp_cn_callback); |
| 320 | if (err) | 327 | if (err) |
| 321 | return err; | 328 | return err; |
| 322 | recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); | 329 | recv_buffer = srv->recv_buffer; |
| 323 | if (!recv_buffer) | ||
| 324 | return -ENOMEM; | ||
| 325 | 330 | ||
| 326 | return 0; | 331 | return 0; |
| 327 | } | 332 | } |
| @@ -330,5 +335,5 @@ void hv_kvp_deinit(void) · 2 unmodified lines | |||
| 330 | { | 335 | { |
| 331 | cn_del_callback(&kvp_id); | 336 | cn_del_callback(&kvp_id); |
| 332 | cancel_delayed_work_sync(&kvp_work); | 337 | cancel_delayed_work_sync(&kvp_work); |
| 333 | kfree(recv_buffer); | 338 | cancel_work_sync(&kvp_sendkey_work); |
| 334 | } | 339 | } |
| @@ -175,7 +175,7 @@ struct hv_kvp_msg { · 174 unmodified lines | |||
| 175 | struct hv_kvp_msg_enumerate kvp_data; | 175 | struct hv_kvp_msg_enumerate kvp_data; |
| 176 | }; | 176 | }; |
| 177 | 177 | ||
| 178 | int hv_kvp_init(void); | 178 | int hv_kvp_init(struct hv_util_service *); |
| 179 | void hv_kvp_deinit(void); | 179 | void hv_kvp_deinit(void); |
| 180 | void hv_kvp_onchannelcallback(void *); | 180 | void hv_kvp_onchannelcallback(void *); |
| 181 | 181 | ||
| @@ -26,15 +26,31 @@ · 25 unmodified lines | |||
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/sysctl.h> | 27 | #include <linux/sysctl.h> |
| 28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
| 29 | #include <linux/dmi.h> | 29 | #include <linux/hyperv.h> |
| 30 | #include <linux/pci.h> | ||
| 31 | 30 | ||
| 32 | #include "hyperv.h" | ||
| 33 | #include "hv_kvp.h" | 31 | #include "hv_kvp.h" |
| 34 | 32 | ||
| 35 | static u8 *shut_txf_buf; | 33 | |
| 36 | static u8 *time_txf_buf; | 34 | static void shutdown_onchannelcallback(void *context); |
| 37 | static u8 *hbeat_txf_buf; | 35 | static struct hv_util_service util_shutdown = { |
| 36 | .util_cb = shutdown_onchannelcallback, | ||
| 37 | }; | ||
| 38 | |||
| 39 | static void timesync_onchannelcallback(void *context); | ||
| 40 | static struct hv_util_service util_timesynch = { | ||
| 41 | .util_cb = timesync_onchannelcallback, | ||
| 42 | }; | ||
| 43 | |||
| 44 | static void heartbeat_onchannelcallback(void *context); | ||
| 45 | static struct hv_util_service util_heartbeat = { | ||
| 46 | .util_cb = heartbeat_onchannelcallback, | ||
| 47 | }; | ||
| 48 | |||
| 49 | static struct hv_util_service util_kvp = { | ||
| 50 | .util_cb = hv_kvp_onchannelcallback, | ||
| 51 | .util_init = hv_kvp_init, | ||
| 52 | .util_deinit = hv_kvp_deinit, | ||
| 53 | }; | ||
| 38 | 54 | ||
| 39 | static void shutdown_onchannelcallback(void *context) | 55 | static void shutdown_onchannelcallback(void *context) |
| 40 | { | 56 | { |
| @@ -42,6 +58,7 @@ static void shutdown_onchannelcallback(void *context) · 1 unmodified line | |||
| 42 | u32 recvlen; | 58 | u32 recvlen; |
| 43 | u64 requestid; | 59 | u64 requestid; |
| 44 | u8 execute_shutdown = false; | 60 | u8 execute_shutdown = false; |
| 61 | u8 *shut_txf_buf = util_shutdown.recv_buffer; | ||
| 45 | 62 | ||
| 46 | struct shutdown_msg_data *shutdown_msg; | 63 | struct shutdown_msg_data *shutdown_msg; |
| 47 | 64 | ||
| @@ -56,7 +73,7 @@ static void shutdown_onchannelcallback(void *context) · 8 unmodified lines | |||
| 56 | sizeof(struct vmbuspipe_hdr)]; | 73 | sizeof(struct vmbuspipe_hdr)]; |
| 57 | 74 | ||
| 58 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 75 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 59 | prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); | 76 | vmbus_prep_negotiate_resp(icmsghdrp, negop, shut_txf_buf); |
| 60 | } else { | 77 | } else { |
| 61 | shutdown_msg = | 78 | shutdown_msg = |
| 62 | (struct shutdown_msg_data *)&shut_txf_buf[ | 79 | (struct shutdown_msg_data *)&shut_txf_buf[ |
| @@ -91,7 +108,7 @@ static void shutdown_onchannelcallback(void *context) · 28 unmodified lines | |||
| 91 | } | 108 | } |
| 92 | 109 | ||
| 93 | if (execute_shutdown == true) | 110 | if (execute_shutdown == true) |
| 94 | orderly_poweroff(false); | 111 | orderly_poweroff(true); |
| 95 | } | 112 | } |
| 96 | 113 | ||
| 97 | /* | 114 | /* |
| @@ -108,6 +125,24 @@ static inline void do_adj_guesttime(u64 hosttime) · 10 unmodified lines | |||
| 108 | do_settimeofday(&host_ts); | 125 | do_settimeofday(&host_ts); |
| 109 | } | 126 | } |
| 110 | 127 | ||
| 128 | /* | ||
| 129 | * Set the host time in a process context. | ||
| 130 | */ | ||
| 131 | |||
| 132 | struct adj_time_work { | ||
| 133 | struct work_struct work; | ||
| 134 | u64 host_time; | ||
| 135 | }; | ||
| 136 | |||
| 137 | static void hv_set_host_time(struct work_struct *work) | ||
| 138 | { | ||
| 139 | struct adj_time_work *wrk; | ||
| 140 | |||
| 141 | wrk = container_of(work, struct adj_time_work, work); | ||
| 142 | do_adj_guesttime(wrk->host_time); | ||
| 143 | kfree(wrk); | ||
| 144 | } | ||
| 145 | |||
| 111 | /* | 146 | /* |
| 112 | * Synchronize time with host after reboot, restore, etc. | 147 | * Synchronize time with host after reboot, restore, etc. |
| 113 | * | 148 | * |
| @@ -121,17 +156,26 @@ static inline void do_adj_guesttime(u64 hosttime) · 7 unmodified lines | |||
| 121 | */ | 156 | */ |
| 122 | static inline void adj_guesttime(u64 hosttime, u8 flags) | 157 | static inline void adj_guesttime(u64 hosttime, u8 flags) |
| 123 | { | 158 | { |
| 159 | struct adj_time_work *wrk; | ||
| 124 | static s32 scnt = 50; | 160 | static s32 scnt = 50; |
| 125 | 161 | ||
| 162 | wrk = kmalloc(sizeof(struct adj_time_work), GFP_ATOMIC); | ||
| 163 | if (wrk == NULL) | ||
| 164 | return; | ||
| 165 | |||
| 166 | wrk->host_time = hosttime; | ||
| 126 | if ((flags & ICTIMESYNCFLAG_SYNC) != 0) { | 167 | if ((flags & ICTIMESYNCFLAG_SYNC) != 0) { |
| 127 | do_adj_guesttime(hosttime); | 168 | INIT_WORK(&wrk->work, hv_set_host_time); |
| 169 | schedule_work(&wrk->work); | ||
| 128 | return; | 170 | return; |
| 129 | } | 171 | } |
| 130 | 172 | ||
| 131 | if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) { | 173 | if ((flags & ICTIMESYNCFLAG_SAMPLE) != 0 && scnt > 0) { |
| 132 | scnt--; | 174 | scnt--; |
| 133 | do_adj_guesttime(hosttime); | 175 | INIT_WORK(&wrk->work, hv_set_host_time); |
| 134 | } | 176 | schedule_work(&wrk->work); |
| 177 | } else | ||
| 178 | kfree(wrk); | ||
| 135 | } | 179 | } |
| 136 | 180 | ||
| 137 | /* | 181 | /* |
| @@ -144,6 +188,7 @@ static void timesync_onchannelcallback(void *context) · 6 unmodified lines | |||
| 144 | u64 requestid; | 188 | u64 requestid; |
| 145 | struct icmsg_hdr *icmsghdrp; | 189 | struct icmsg_hdr *icmsghdrp; |
| 146 | struct ictimesync_data *timedatap; | 190 | struct ictimesync_data *timedatap; |
| 191 | u8 *time_txf_buf = util_timesynch.recv_buffer; | ||
| 147 | 192 | ||
| 148 | vmbus_recvpacket(channel, time_txf_buf, | 193 | vmbus_recvpacket(channel, time_txf_buf, |
| 149 | PAGE_SIZE, &recvlen, &requestid); | 194 | PAGE_SIZE, &recvlen, &requestid); |
| @@ -153,7 +198,7 @@ static void timesync_onchannelcallback(void *context) · 3 unmodified lines | |||
| 153 | sizeof(struct vmbuspipe_hdr)]; | 198 | sizeof(struct vmbuspipe_hdr)]; |
| 154 | 199 | ||
| 155 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 200 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 156 | prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); | 201 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, time_txf_buf); |
| 157 | } else { | 202 | } else { |
| 158 | timedatap = (struct ictimesync_data *)&time_txf_buf[ | 203 | timedatap = (struct ictimesync_data *)&time_txf_buf[ |
| 159 | sizeof(struct vmbuspipe_hdr) + | 204 | sizeof(struct vmbuspipe_hdr) + |
| @@ -182,6 +227,7 @@ static void heartbeat_onchannelcallback(void *context) · 22 unmodified lines | |||
| 182 | u64 requestid; | 227 | u64 requestid; |
| 183 | struct icmsg_hdr *icmsghdrp; | 228 | struct icmsg_hdr *icmsghdrp; |
| 184 | struct heartbeat_msg_data *heartbeat_msg; | 229 | struct heartbeat_msg_data *heartbeat_msg; |
| 230 | u8 *hbeat_txf_buf = util_heartbeat.recv_buffer; | ||
| 185 | 231 | ||
| 186 | vmbus_recvpacket(channel, hbeat_txf_buf, | 232 | vmbus_recvpacket(channel, hbeat_txf_buf, |
| 187 | PAGE_SIZE, &recvlen, &requestid); | 233 | PAGE_SIZE, &recvlen, &requestid); |
| @@ -191,7 +237,7 @@ static void heartbeat_onchannelcallback(void *context) · 3 unmodified lines | |||
| 191 | sizeof(struct vmbuspipe_hdr)]; | 237 | sizeof(struct vmbuspipe_hdr)]; |
| 192 | 238 | ||
| 193 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { | 239 | if (icmsghdrp->icmsgtype == ICMSGTYPE_NEGOTIATE) { |
| 194 | prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); | 240 | vmbus_prep_negotiate_resp(icmsghdrp, NULL, hbeat_txf_buf); |
| 195 | } else { | 241 | } else { |
| 196 | heartbeat_msg = | 242 | heartbeat_msg = |
| 197 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ | 243 | (struct heartbeat_msg_data *)&hbeat_txf_buf[ |
| @@ -210,92 +256,94 @@ static void heartbeat_onchannelcallback(void *context) · 12 unmodified lines | |||
| 210 | } | 256 | } |
| 211 | } | 257 | } |
| 212 | 258 | ||
| 213 | static const struct pci_device_id __initconst | 259 | static int util_probe(struct hv_device *dev, |
| 214 | hv_utils_pci_table[] __maybe_unused = { | 260 | const struct hv_vmbus_device_id *dev_id) |
| 215 | { PCI_DEVICE(0x1414, 0x5353) }, /* Hyper-V emulated VGA controller */ | ||
| 216 | { 0 } | ||
| 217 | }; | ||
| 218 | MODULE_DEVICE_TABLE(pci, hv_utils_pci_table); | ||
| 219 | |||
| 220 | |||
| 221 | static const struct dmi_system_id __initconst | ||
| 222 | hv_utils_dmi_table[] __maybe_unused = { | ||
| 223 | { | ||
| 224 | .ident = "Hyper-V", | ||
| 225 | .matches = { | ||
| 226 | DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), | ||
| 227 | DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), | ||
| 228 | DMI_MATCH(DMI_BOARD_NAME, "Virtual Machine"), | ||
| 229 | }, | ||
| 230 | }, | ||
| 231 | { }, | ||
| 232 | }; | ||
| 233 | MODULE_DEVICE_TABLE(dmi, hv_utils_dmi_table); | ||
| 234 | |||
| 235 | |||
| 236 | static int __init init_hyperv_utils(void) | ||
| 237 | { | 261 | { |
| 238 | pr_info("Registering HyperV Utility Driver\n"); | 262 | struct hv_util_service *srv = |
| 239 | 263 | (struct hv_util_service *)dev_id->driver_data; | |
| 240 | if (hv_kvp_init()) | 264 | int ret; |
| 241 | return -ENODEV; | ||
| 242 | |||
| 243 | |||
| 244 | if (!dmi_check_system(hv_utils_dmi_table)) | ||
| 245 | return -ENODEV; | ||
| 246 | |||
| 247 | shut_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 248 | time_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 249 | hbeat_txf_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
| 250 | 265 | ||
| 251 | if (!shut_txf_buf || !time_txf_buf || !hbeat_txf_buf) { | 266 | srv->recv_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL); |
| 252 | pr_info("Unable to allocate memory for receive buffer\n"); | 267 | if (!srv->recv_buffer) |
| 253 | kfree(shut_txf_buf); | ||
| 254 | kfree(time_txf_buf); | ||
| 255 | kfree(hbeat_txf_buf); | ||
| 256 | return -ENOMEM; | 268 | return -ENOMEM; |
| 269 | if (srv->util_init) { | ||
| 270 | ret = srv->util_init(srv); | ||
| 271 | if (ret) { | ||
| 272 | ret = -ENODEV; | ||
| 273 | goto error1; | ||
| 274 | } | ||
| 257 | } | 275 | } |
| 258 | 276 | ||
| 259 | hv_cb_utils[HV_SHUTDOWN_MSG].callback = &shutdown_onchannelcallback; | 277 | ret = vmbus_open(dev->channel, 2 * PAGE_SIZE, 2 * PAGE_SIZE, NULL, 0, |
| 278 | srv->util_cb, dev->channel); | ||
| 279 | if (ret) | ||
| 280 | goto error; | ||
| 281 | |||
| 282 | hv_set_drvdata(dev, srv); | ||
| 283 | return 0; | ||
| 260 | 284 | ||
| 261 | hv_cb_utils[HV_TIMESYNC_MSG].callback = ×ync_onchannelcallback; | 285 | error: |
| 286 | if (srv->util_deinit) | ||
| 287 | srv->util_deinit(); | ||
| 288 | error1: | ||
| 289 | kfree(srv->recv_buffer); | ||
| 290 | return ret; | ||
| 291 | } | ||
| 262 | 292 | ||
| 263 | hv_cb_utils[HV_HEARTBEAT_MSG].callback = &heartbeat_onchannelcallback; | 293 | static int util_remove(struct hv_device *dev) |
| 294 | { | ||
| 295 | struct hv_util_service *srv = hv_get_drvdata(dev); | ||
| 264 | 296 | ||
| 265 | hv_cb_utils[HV_KVP_MSG].callback = &hv_kvp_onchannelcallback; | 297 | vmbus_close(dev->channel); |
| 298 | if (srv->util_deinit) | ||
| 299 | srv->util_deinit(); | ||
| 300 | kfree(srv->recv_buffer); | ||
| 266 | 301 | ||
| 267 | return 0; | 302 | return 0; |
| 268 | } | 303 | } |
| 269 | 304 | ||
| 270 | static void exit_hyperv_utils(void) | 305 | static const struct hv_vmbus_device_id id_table[] = { |
| 271 | { | 306 | /* Shutdown guid */ |
| 272 | pr_info("De-Registered HyperV Utility Driver\n"); | 307 | { VMBUS_DEVICE(0x31, 0x60, 0x0B, 0X0E, 0x13, 0x52, 0x34, 0x49, |
| 308 | 0x81, 0x8B, 0x38, 0XD9, 0x0C, 0xED, 0x39, 0xDB) | ||
| 309 | .driver_data = (unsigned long)&util_shutdown }, | ||
| 310 | /* Time synch guid */ | ||
| 311 | { VMBUS_DEVICE(0x30, 0xe6, 0x27, 0x95, 0xae, 0xd0, 0x7b, 0x49, | ||
| 312 | 0xad, 0xce, 0xe8, 0x0a, 0xb0, 0x17, 0x5c, 0xaf) | ||
| 313 | .driver_data = (unsigned long)&util_timesynch }, | ||
| 314 | /* Heartbeat guid */ | ||
| 315 | { VMBUS_DEVICE(0x39, 0x4f, 0x16, 0x57, 0x15, 0x91, 0x78, 0x4e, | ||
| 316 | 0xab, 0x55, 0x38, 0x2f, 0x3b, 0xd5, 0x42, 0x2d) | ||
| 317 | .driver_data = (unsigned long)&util_heartbeat }, | ||
| 318 | /* KVP guid */ | ||
| 319 | { VMBUS_DEVICE(0xe7, 0xf4, 0xa0, 0xa9, 0x45, 0x5a, 0x96, 0x4d, | ||
| 320 | 0xb8, 0x27, 0x8a, 0x84, 0x1e, 0x8c, 0x3, 0xe6) | ||
| 321 | .driver_data = (unsigned long)&util_kvp }, | ||
| 322 | { }, | ||
| 323 | }; | ||
| 273 | 324 | ||
| 274 | if (hv_cb_utils[HV_SHUTDOWN_MSG].channel != NULL) | 325 | MODULE_DEVICE_TABLE(vmbus, id_table); |
| 275 | hv_cb_utils[HV_SHUTDOWN_MSG].channel->onchannel_callback = | ||
| 276 | &chn_cb_negotiate; | ||
| 277 | hv_cb_utils[HV_SHUTDOWN_MSG].callback = NULL; | ||
| 278 | 326 | ||
| 279 | if (hv_cb_utils[HV_TIMESYNC_MSG].channel != NULL) | 327 | /* The one and only one */ |
| 280 | hv_cb_utils[HV_TIMESYNC_MSG].channel->onchannel_callback = | 328 | static struct hv_driver util_drv = { |
| 281 | &chn_cb_negotiate; | 329 | .name = "hv_util", |
| 282 | hv_cb_utils[HV_TIMESYNC_MSG].callback = NULL; | 330 | .id_table = id_table, |
| 331 | .probe = util_probe, | ||
| 332 | .remove = util_remove, | ||
| 333 | }; | ||
| 283 | 334 | ||
| 284 | if (hv_cb_utils[HV_HEARTBEAT_MSG].channel != NULL) | 335 | static int __init init_hyperv_utils(void) |
| 285 | hv_cb_utils[HV_HEARTBEAT_MSG].channel->onchannel_callback = | 336 | { |
| 286 | &chn_cb_negotiate; | 337 | pr_info("Registering HyperV Utility Driver\n"); |
| 287 | hv_cb_utils[HV_HEARTBEAT_MSG].callback = NULL; | ||
| 288 | 338 | ||
| 289 | if (hv_cb_utils[HV_KVP_MSG].channel != NULL) | 339 | return vmbus_driver_register(&util_drv); |
| 290 | hv_cb_utils[HV_KVP_MSG].channel->onchannel_callback = | 340 | } |
| 291 | &chn_cb_negotiate; | ||
| 292 | hv_cb_utils[HV_KVP_MSG].callback = NULL; | ||
| 293 | 341 | ||
| 294 | hv_kvp_deinit(); | 342 | static void exit_hyperv_utils(void) |
| 343 | { | ||
| 344 | pr_info("De-Registered HyperV Utility Driver\n"); | ||
| 295 | 345 | ||
| 296 | kfree(shut_txf_buf); | 346 | vmbus_driver_unregister(&util_drv); |
| 297 | kfree(time_txf_buf); | ||
| 298 | kfree(hbeat_txf_buf); | ||
| 299 | } | 347 | } |
| 300 | 348 | ||
| 301 | module_init(init_hyperv_utils); | 349 | module_init(init_hyperv_utils); |
| @@ -28,8 +28,7 @@ · 27 unmodified lines | |||
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <asm/sync_bitops.h> | 29 | #include <asm/sync_bitops.h> |
| 30 | #include <linux/atomic.h> | 30 | #include <linux/atomic.h> |
| 31 | 31 | #include <linux/hyperv.h> | |
| 32 | #include "hyperv.h" | ||
| 33 | 32 | ||
| 34 | /* | 33 | /* |
| 35 | * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent | 34 | * The below CPUID leaves are present if VersionAndFeatures.HypervisorPresent |
| @@ -451,8 +450,8 @@ enum { · 415 unmodified lines | |||
| 451 | /* #define VMBUS_PORT_ID 11 */ | 450 | /* #define VMBUS_PORT_ID 11 */ |
| 452 | 451 | ||
| 453 | /* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */ | 452 | /* 628180B8-308D-4c5e-B7DB-1BEB62E62EF4 */ |
| 454 | static const struct hv_guid VMBUS_SERVICE_ID = { | 453 | static const uuid_le VMBUS_SERVICE_ID = { |
| 455 | .data = { | 454 | .b = { |
| 456 | 0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c, | 455 | 0xb8, 0x80, 0x81, 0x62, 0x8d, 0x30, 0x5e, 0x4c, |
| 457 | 0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4 | 456 | 0xb7, 0xdb, 0x1b, 0xeb, 0x62, 0xe6, 0x2e, 0xf4 |
| 458 | }, | 457 | }, |
| @@ -530,8 +529,6 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *ring_info, · 71 unmodified lines | |||
| 530 | 529 | ||
| 531 | u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info); | 530 | u32 hv_get_ringbuffer_interrupt_mask(struct hv_ring_buffer_info *ring_info); |
| 532 | 531 | ||
| 533 | void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix); | ||
| 534 | |||
| 535 | void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, | 532 | void hv_ringbuffer_get_debuginfo(struct hv_ring_buffer_info *ring_info, |
| 536 | struct hv_ring_buffer_debug_info *debug_info); | 533 | struct hv_ring_buffer_debug_info *debug_info); |
| 537 | 534 | ||
| @@ -601,12 +598,12 @@ extern struct vmbus_connection vmbus_connection; · 63 unmodified lines | |||
| 601 | 598 | ||
| 602 | /* General vmbus interface */ | 599 | /* General vmbus interface */ |
| 603 | 600 | ||
| 604 | struct hv_device *vmbus_child_device_create(struct hv_guid *type, | 601 | struct hv_device *vmbus_device_create(uuid_le *type, |
| 605 | struct hv_guid *instance, | 602 | uuid_le *instance, |
| 606 | struct vmbus_channel *channel); | 603 | struct vmbus_channel *channel); |
| 607 | 604 | ||
| 608 | int vmbus_child_device_register(struct hv_device *child_device_obj); | 605 | int vmbus_device_register(struct hv_device *child_device_obj); |
| 609 | void vmbus_child_device_unregister(struct hv_device *device_obj); | 606 | void vmbus_device_unregister(struct hv_device *device_obj); |
| 610 | 607 | ||
| 611 | /* static void */ | 608 | /* static void */ |
| 612 | /* VmbusChildDeviceDestroy( */ | 609 | /* VmbusChildDeviceDestroy( */ |
| @@ -25,8 +25,8 @@ · 24 unmodified lines | |||
| 25 | 25 | ||
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
| 28 | #include <linux/hyperv.h> | ||
| 28 | 29 | ||
| 29 | #include "hyperv.h" | ||
| 30 | #include "hyperv_vmbus.h" | 30 | #include "hyperv_vmbus.h" |
| 31 | 31 | ||
| 32 | 32 | ||
| @@ -34,7 +34,8 @@ · 1 unmodified line | |||
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | /* Amount of space to write to */ | 36 | /* Amount of space to write to */ |
| 37 | #define BYTES_AVAIL_TO_WRITE(r, w, z) ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)) | 37 | #define BYTES_AVAIL_TO_WRITE(r, w, z) \ |
| 38 | ((w) >= (r)) ? ((z) - ((w) - (r))) : ((r) - (w)) | ||
| 38 | 39 | ||
| 39 | 40 | ||
| 40 | /* | 41 | /* |
| @@ -171,37 +172,6 @@ hv_get_ring_bufferindices(struct hv_ring_buffer_info *ring_info) · 130 unmodified lines | |||
| 171 | return (u64)ring_info->ring_buffer->write_index << 32; | 172 | return (u64)ring_info->ring_buffer->write_index << 32; |
| 172 | } | 173 | } |
| 173 | 174 | ||
| 174 | |||
| 175 | /* | ||
| 176 | * | ||
| 177 | * hv_dump_ring_info() | ||
| 178 | * | ||
| 179 | * Dump out to console the ring buffer info | ||
| 180 | * | ||
| 181 | */ | ||
| 182 | void hv_dump_ring_info(struct hv_ring_buffer_info *ring_info, char *prefix) | ||
| 183 | { | ||
| 184 | u32 bytes_avail_towrite; | ||
| 185 | u32 bytes_avail_toread; | ||
| 186 | |||
| 187 | hv_get_ringbuffer_availbytes(ring_info, | ||
| 188 | &bytes_avail_toread, | ||
| 189 | &bytes_avail_towrite); | ||
| 190 | |||
| 191 | DPRINT(VMBUS, | ||
| 192 | DEBUG_RING_LVL, | ||
| 193 | "%s <<ringinfo %p buffer %p avail write %u " | ||
| 194 | "avail read %u read idx %u write idx %u>>", | ||
| 195 | prefix, | ||
| 196 | ring_info, | ||
| 197 | ring_info->ring_buffer->buffer, | ||
| 198 | bytes_avail_towrite, | ||
| 199 | bytes_avail_toread, | ||
| 200 | ring_info->ring_buffer->read_index, | ||
| 201 | ring_info->ring_buffer->write_index); | ||
| 202 | } | ||
| 203 | |||
| 204 | |||
| 205 | /* | 175 | /* |
| 206 | * | 176 | * |
| 207 | * hv_copyfrom_ringbuffer() | 177 | * hv_copyfrom_ringbuffer() |
| @@ -390,7 +360,7 @@ int hv_ringbuffer_write(struct hv_ring_buffer_info *outring_info, · 182 unmodified lines | |||
| 390 | /* is empty since the read index == write index */ | 360 | /* is empty since the read index == write index */ |
| 391 | if (bytes_avail_towrite <= totalbytes_towrite) { | 361 | if (bytes_avail_towrite <= totalbytes_towrite) { |
| 392 | spin_unlock_irqrestore(&outring_info->ring_lock, flags); | 362 | spin_unlock_irqrestore(&outring_info->ring_lock, flags); |
| 393 | return -1; | 363 | return -EAGAIN; |
| 394 | } | 364 | } |
| 395 | 365 | ||
| 396 | /* Write to the ring buffer */ | 366 | /* Write to the ring buffer */ |
| @@ -450,7 +420,7 @@ int hv_ringbuffer_peek(struct hv_ring_buffer_info *Inring_info, · 53 unmodified lines | |||
| 450 | 420 | ||
| 451 | spin_unlock_irqrestore(&Inring_info->ring_lock, flags); | 421 | spin_unlock_irqrestore(&Inring_info->ring_lock, flags); |
| 452 | 422 | ||
| 453 | return -1; | 423 | return -EAGAIN; |
| 454 | } | 424 | } |
| 455 | 425 | ||
| 456 | /* Convert to byte offset */ | 426 | /* Convert to byte offset */ |
| @@ -496,7 +466,7 @@ int hv_ringbuffer_read(struct hv_ring_buffer_info *inring_info, void *buffer, · 39 unmodified lines | |||
| 496 | if (bytes_avail_toread < buflen) { | 466 | if (bytes_avail_toread < buflen) { |
| 497 | spin_unlock_irqrestore(&inring_info->ring_lock, flags); | 467 | spin_unlock_irqrestore(&inring_info->ring_lock, flags); |
| 498 | 468 | ||
| 499 | return -1; | 469 | return -EAGAIN; |
| 500 | } | 470 | } |
| 501 | 471 | ||
| 502 | next_read_location = | 472 | next_read_location = |
| @@ -28,14 +28,12 @@ · 27 unmodified lines | |||
| 28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
| 29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
| 30 | #include <linux/sysctl.h> | 30 | #include <linux/sysctl.h> |
| 31 | #include <linux/pci.h> | ||
| 32 | #include <linux/dmi.h> | ||
| 33 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 34 | #include <linux/acpi.h> | 32 | #include <linux/acpi.h> |
| 35 | #include <acpi/acpi_bus.h> | 33 | #include <acpi/acpi_bus.h> |
| 36 | #include <linux/completion.h> | 34 | #include <linux/completion.h> |
| 37 | 35 | #include <linux/hyperv.h> | |
| 38 | #include "hyperv.h" | 36 | #include <asm/hyperv.h> |
| 39 | #include "hyperv_vmbus.h" | 37 | #include "hyperv_vmbus.h" |
| 40 | 38 | ||
| 41 | 39 | ||
| @@ -43,15 +41,28 @@ static struct acpi_device *hv_acpi_dev; · 1 unmodified line | |||
| 43 | 41 | ||
| 44 | static struct tasklet_struct msg_dpc; | 42 | static struct tasklet_struct msg_dpc; |
| 45 | static struct tasklet_struct event_dpc; | 43 | static struct tasklet_struct event_dpc; |
| 46 | |||
| 47 | unsigned int vmbus_loglevel = (ALL_MODULES << 16 | INFO_LVL); | ||
| 48 | EXPORT_SYMBOL(vmbus_loglevel); | ||
| 49 | /* (ALL_MODULES << 16 | DEBUG_LVL_ENTEREXIT); */ | ||
| 50 | /* (((VMBUS | VMBUS_DRV)<<16) | DEBUG_LVL_ENTEREXIT); */ | ||
| 51 | |||
| 52 | static struct completion probe_event; | 44 | static struct completion probe_event; |
| 53 | static int irq; | 45 | static int irq; |
| 54 | 46 | ||
| 47 | struct hv_device_info { | ||
| 48 | u32 chn_id; | ||
| 49 | u32 chn_state; | ||
| 50 | uuid_le chn_type; | ||
| 51 | uuid_le chn_instance; | ||
| 52 | |||
| 53 | u32 monitor_id; | ||
| 54 | u32 server_monitor_pending; | ||
| 55 | u32 server_monitor_latency; | ||
| 56 | u32 server_monitor_conn_id; | ||
| 57 | u32 client_monitor_pending; | ||
| 58 | u32 client_monitor_latency; | ||
| 59 | u32 client_monitor_conn_id; | ||
| 60 | |||
| 61 | struct hv_dev_port_info inbound; | ||
| 62 | struct hv_dev_port_info outbound; | ||
| 63 | }; | ||
| 64 | |||
| 65 | |||
| 55 | static void get_channel_info(struct hv_device *device, | 66 | static void get_channel_info(struct hv_device *device, |
| 56 | struct hv_device_info *info) | 67 | struct hv_device_info *info) |
| 57 | { | 68 | { |
| @@ -65,9 +76,9 @@ static void get_channel_info(struct hv_device *device, · 7 unmodified lines | |||
| 65 | info->chn_id = debug_info.relid; | 76 | info->chn_id = debug_info.relid; |
| 66 | info->chn_state = debug_info.state; | 77 | info->chn_state = debug_info.state; |
| 67 | memcpy(&info->chn_type, &debug_info.interfacetype, | 78 | memcpy(&info->chn_type, &debug_info.interfacetype, |
| 68 | sizeof(struct hv_guid)); | 79 | sizeof(uuid_le)); |
| 69 | memcpy(&info->chn_instance, &debug_info.interface_instance, | 80 | memcpy(&info->chn_instance, &debug_info.interface_instance, |
| 70 | sizeof(struct hv_guid)); | 81 | sizeof(uuid_le)); |
| 71 | 82 | ||
| 72 | info->monitor_id = debug_info.monitorid; | 83 | info->monitor_id = debug_info.monitorid; |
| 73 | 84 | ||
| @@ -97,6 +108,14 @@ static void get_channel_info(struct hv_device *device, · 23 unmodified lines | |||
| 97 | debug_info.outbound.bytes_avail_towrite; | 108 | debug_info.outbound.bytes_avail_towrite; |
| 98 | } | 109 | } |
| 99 | 110 | ||
| 111 | #define VMBUS_ALIAS_LEN ((sizeof((struct hv_vmbus_device_id *)0)->guid) * 2) | ||
| 112 | static void print_alias_name(struct hv_device *hv_dev, char *alias_name) | ||
| 113 | { | ||
| 114 | int i; | ||
| 115 | for (i = 0; i < VMBUS_ALIAS_LEN; i += 2) | ||
| 116 | sprintf(&alias_name[i], "%02x", hv_dev->dev_type.b[i/2]); | ||
| 117 | } | ||
| 118 | |||
| 100 | /* | 119 | /* |
| 101 | * vmbus_show_device_attr - Show the device attribute in sysfs. | 120 | * vmbus_show_device_attr - Show the device attribute in sysfs. |
| 102 | * | 121 | * |
| @@ -108,97 +127,105 @@ static ssize_t vmbus_show_device_attr(struct device *dev, · 5 unmodified lines | |||
| 108 | char *buf) | 127 | char *buf) |
| 109 | { | 128 | { |
| 110 | struct hv_device *hv_dev = device_to_hv_device(dev); | 129 | struct hv_device *hv_dev = device_to_hv_device(dev); |
| 111 | struct hv_device_info device_info; | 130 | struct hv_device_info *device_info; |
| 131 | char alias_name[VMBUS_ALIAS_LEN + 1]; | ||
| 132 | int ret = 0; | ||
| 112 | 133 | ||
| 113 | memset(&device_info, 0, sizeof(struct hv_device_info)); | 134 | device_info = kzalloc(sizeof(struct hv_device_info), GFP_KERNEL); |
| 135 | if (!device_info) | ||
| 136 | return ret; | ||
| 114 | 137 | ||
| 115 | get_channel_info(hv_dev, &device_info); | 138 | get_channel_info(hv_dev, device_info); |
| 116 | 139 | ||
| 117 | if (!strcmp(dev_attr->attr.name, "class_id")) { | 140 | if (!strcmp(dev_attr->attr.name, "class_id")) { |
| 118 | return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" | 141 | ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" |
| 119 | "%02x%02x%02x%02x%02x%02x%02x%02x}\n", | 142 | "%02x%02x%02x%02x%02x%02x%02x%02x}\n", |
| 120 | device_info.chn_type.data[3], | 143 | device_info->chn_type.b[3], |
| 121 | device_info.chn_type.data[2], | 144 | device_info->chn_type.b[2], |
| 122 | device_info.chn_type.data[1], | 145 | device_info->chn_type.b[1], |
| 123 | device_info.chn_type.data[0], | 146 | device_info->chn_type.b[0], |
| 124 | device_info.chn_type.data[5], | 147 | device_info->chn_type.b[5], |
| 125 | device_info.chn_type.data[4], | 148 | device_info->chn_type.b[4], |
| 126 | device_info.chn_type.data[7], | 149 | device_info->chn_type.b[7], |
| 127 | device_info.chn_type.data[6], | 150 | device_info->chn_type.b[6], |
| 128 | device_info.chn_type.data[8], | 151 | device_info->chn_type.b[8], |
| 129 | device_info.chn_type.data[9], | 152 | device_info->chn_type.b[9], |
| 130 | device_info.chn_type.data[10], | 153 | device_info->chn_type.b[10], |
| 131 | device_info.chn_type.data[11], | 154 | device_info->chn_type.b[11], |
| 132 | device_info.chn_type.data[12], | 155 | device_info->chn_type.b[12], |
| 133 | device_info.chn_type.data[13], | 156 | device_info->chn_type.b[13], |
| 134 | device_info.chn_type.data[14], | 157 | device_info->chn_type.b[14], |
| 135 | device_info.chn_type.data[15]); | 158 | device_info->chn_type.b[15]); |
| 136 | } else if (!strcmp(dev_attr->attr.name, "device_id")) { | 159 | } else if (!strcmp(dev_attr->attr.name, "device_id")) { |
| 137 | return sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" | 160 | ret = sprintf(buf, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-" |
| 138 | "%02x%02x%02x%02x%02x%02x%02x%02x}\n", | 161 | "%02x%02x%02x%02x%02x%02x%02x%02x}\n", |
| 139 | device_info.chn_instance.data[3], | 162 | device_info->chn_instance.b[3], |
| 140 | device_info.chn_instance.data[2], | 163 | device_info->chn_instance.b[2], |
| 141 | device_info.chn_instance.data[1], | 164 | device_info->chn_instance.b[1], |
| 142 | device_info.chn_instance.data[0], | 165 | device_info->chn_instance.b[0], |
| 143 | device_info.chn_instance.data[5], | 166 | device_info->chn_instance.b[5], |
| 144 | device_info.chn_instance.data[4], | 167 | device_info->chn_instance.b[4], |
| 145 | device_info.chn_instance.data[7], | 168 | device_info->chn_instance.b[7], |
| 146 | device_info.chn_instance.data[6], | 169 | device_info->chn_instance.b[6], |
| 147 | device_info.chn_instance.data[8], | 170 | device_info->chn_instance.b[8], |
| 148 | device_info.chn_instance.data[9], | 171 | device_info->chn_instance.b[9], |
| 149 | device_info.chn_instance.data[10], | 172 | device_info->chn_instance.b[10], |
| 150 | device_info.chn_instance.data[11], | 173 | device_info->chn_instance.b[11], |
| 151 | device_info.chn_instance.data[12], | 174 | device_info->chn_instance.b[12], |
| 152 | device_info.chn_instance.data[13], | 175 | device_info->chn_instance.b[13], |
| 153 | device_info.chn_instance.data[14], | 176 | device_info->chn_instance.b[14], |
| 154 | device_info.chn_instance.data[15]); | 177 | device_info->chn_instance.b[15]); |
| 178 | } else if (!strcmp(dev_attr->attr.name, "modalias")) { | ||
| 179 | print_alias_name(hv_dev, alias_name); | ||
| 180 | ret = sprintf(buf, "vmbus:%s\n", alias_name); | ||
| 155 | } else if (!strcmp(dev_attr->attr.name, "state")) { | 181 | } else if (!strcmp(dev_attr->attr.name, "state")) { |
| 156 | return sprintf(buf, "%d\n", device_info.chn_state); | 182 | ret = sprintf(buf, "%d\n", device_info->chn_state); |
| 157 | } else if (!strcmp(dev_attr->attr.name, "id")) { | 183 | } else if (!strcmp(dev_attr->attr.name, "id")) { |
| 158 | return sprintf(buf, "%d\n", device_info.chn_id); | 184 | ret = sprintf(buf, "%d\n", device_info->chn_id); |
| 159 | } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { | 185 | } else if (!strcmp(dev_attr->attr.name, "out_intr_mask")) { |
| 160 | return sprintf(buf, "%d\n", device_info.outbound.int_mask); | 186 | ret = sprintf(buf, "%d\n", device_info->outbound.int_mask); |
| 161 | } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { | 187 | } else if (!strcmp(dev_attr->attr.name, "out_read_index")) { |
| 162 | return sprintf(buf, "%d\n", device_info.outbound.read_idx); | 188 | ret = sprintf(buf, "%d\n", device_info->outbound.read_idx); |
| 163 | } else if (!strcmp(dev_attr->attr.name, "out_write_index")) { | 189 | } else if (!strcmp(dev_attr->attr.name, "out_write_index")) { |
| 164 | return sprintf(buf, "%d\n", device_info.outbound.write_idx); | 190 | ret = sprintf(buf, "%d\n", device_info->outbound.write_idx); |
| 165 | } else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) { | 191 | } else if (!strcmp(dev_attr->attr.name, "out_read_bytes_avail")) { |
| 166 | return sprintf(buf, "%d\n", | 192 | ret = sprintf(buf, "%d\n", |
| 167 | device_info.outbound.bytes_avail_toread); | 193 | device_info->outbound.bytes_avail_toread); |
| 168 | } else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) { | 194 | } else if (!strcmp(dev_attr->attr.name, "out_write_bytes_avail")) { |
| 169 | return sprintf(buf, "%d\n", | 195 | ret = sprintf(buf, "%d\n", |
| 170 | device_info.outbound.bytes_avail_towrite); | 196 | device_info->outbound.bytes_avail_towrite); |
| 171 | } else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) { | 197 | } else if (!strcmp(dev_attr->attr.name, "in_intr_mask")) { |
| 172 | return sprintf(buf, "%d\n", device_info.inbound.int_mask); | 198 | ret = sprintf(buf, "%d\n", device_info->inbound.int_mask); |
| 173 | } else if (!strcmp(dev_attr->attr.name, "in_read_index")) { | 199 | } else if (!strcmp(dev_attr->attr.name, "in_read_index")) { |
| 174 | return sprintf(buf, "%d\n", device_info.inbound.read_idx); | 200 | ret = sprintf(buf, "%d\n", device_info->inbound.read_idx); |
| 175 | } else if (!strcmp(dev_attr->attr.name, "in_write_index")) { | 201 | } else if (!strcmp(dev_attr->attr.name, "in_write_index")) { |
| 176 | return sprintf(buf, "%d\n", device_info.inbound.write_idx); | 202 | ret = sprintf(buf, "%d\n", device_info->inbound.write_idx); |
| 177 | } else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) { | 203 | } else if (!strcmp(dev_attr->attr.name, "in_read_bytes_avail")) { |
| 178 | return sprintf(buf, "%d\n", | 204 | ret = sprintf(buf, "%d\n", |
| 179 | device_info.inbound.bytes_avail_toread); | 205 | device_info->inbound.bytes_avail_toread); |
| 180 | } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { | 206 | } else if (!strcmp(dev_attr->attr.name, "in_write_bytes_avail")) { |
| 181 | return sprintf(buf, "%d\n", | 207 | ret = sprintf(buf, "%d\n", |
| 182 | device_info.inbound.bytes_avail_towrite); | 208 | device_info->inbound.bytes_avail_towrite); |
| 183 | } else if (!strcmp(dev_attr->attr.name, "monitor_id")) { | 209 | } else if (!strcmp(dev_attr->attr.name, "monitor_id")) { |
| 184 | return sprintf(buf, "%d\n", device_info.monitor_id); | 210 | ret = sprintf(buf, "%d\n", device_info->monitor_id); |
| 185 | } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) { | 211 | } else if (!strcmp(dev_attr->attr.name, "server_monitor_pending")) { |
| 186 | return sprintf(buf, "%d\n", device_info.server_monitor_pending); | 212 | ret = sprintf(buf, "%d\n", device_info->server_monitor_pending); |
| 187 | } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { | 213 | } else if (!strcmp(dev_attr->attr.name, "server_monitor_latency")) { |
| 188 | return sprintf(buf, "%d\n", device_info.server_monitor_latency); | 214 | ret = sprintf(buf, "%d\n", device_info->server_monitor_latency); |
| 189 | } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { | 215 | } else if (!strcmp(dev_attr->attr.name, "server_monitor_conn_id")) { |
| 190 | return sprintf(buf, "%d\n", | 216 | ret = sprintf(buf, "%d\n", |
| 191 | device_info.server_monitor_conn_id); | 217 | device_info->server_monitor_conn_id); |
| 192 | } else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) { | 218 | } else if (!strcmp(dev_attr->attr.name, "client_monitor_pending")) { |
| 193 | return sprintf(buf, "%d\n", device_info.client_monitor_pending); | 219 | ret = sprintf(buf, "%d\n", device_info->client_monitor_pending); |
| 194 | } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) { | 220 | } else if (!strcmp(dev_attr->attr.name, "client_monitor_latency")) { |
| 195 | return sprintf(buf, "%d\n", device_info.client_monitor_latency); | 221 | ret = sprintf(buf, "%d\n", device_info->client_monitor_latency); |
| 196 | } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { | 222 | } else if (!strcmp(dev_attr->attr.name, "client_monitor_conn_id")) { |
| 197 | return sprintf(buf, "%d\n", | 223 | ret = sprintf(buf, "%d\n", |
| 198 | device_info.client_monitor_conn_id); | 224 | device_info->client_monitor_conn_id); |
| 199 | } else { | ||
| 200 | return 0; | ||
| 201 | } | 225 | } |
| 226 | |||
| 227 | kfree(device_info); | ||
| 228 | return ret; | ||
| 202 | } | 229 | } |
| 203 | 230 | ||
| 204 | /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */ | 231 | /* Set up per device attributes in /sys/bus/vmbus/devices/<bus device> */ |
| @@ -208,6 +235,7 @@ static struct device_attribute vmbus_device_attrs[] = { · 3 unmodified lines | |||
| 208 | __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), | 235 | __ATTR(class_id, S_IRUGO, vmbus_show_device_attr, NULL), |
| 209 | __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), | 236 | __ATTR(device_id, S_IRUGO, vmbus_show_device_attr, NULL), |
| 210 | __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL), | 237 | __ATTR(monitor_id, S_IRUGO, vmbus_show_device_attr, NULL), |
| 238 | __ATTR(modalias, S_IRUGO, vmbus_show_device_attr, NULL), | ||
| 211 | 239 | ||
| 212 | __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), | 240 | __ATTR(server_monitor_pending, S_IRUGO, vmbus_show_device_attr, NULL), |
| 213 | __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), | 241 | __ATTR(server_monitor_latency, S_IRUGO, vmbus_show_device_attr, NULL), |
| @@ -238,76 +266,60 @@ static struct device_attribute vmbus_device_attrs[] = { · 24 unmodified lines | |||
| 238 | * This routine is invoked when a device is added or removed on the vmbus to | 266 | * This routine is invoked when a device is added or removed on the vmbus to |
| 239 | * generate a uevent to udev in the userspace. The udev will then look at its | 267 | * generate a uevent to udev in the userspace. The udev will then look at its |
| 240 | * rule and the uevent generated here to load the appropriate driver | 268 | * rule and the uevent generated here to load the appropriate driver |
| 269 | * | ||
| 270 | * The alias string will be of the form vmbus:guid where guid is the string | ||
| 271 | * representation of the device guid (each byte of the guid will be | ||
| 272 | * represented with two hex characters. | ||
| 241 | */ | 273 | */ |
| 242 | static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) | 274 | static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env) |
| 243 | { | 275 | { |
| 244 | struct hv_device *dev = device_to_hv_device(device); | 276 | struct hv_device *dev = device_to_hv_device(device); |
| 245 | int ret; | 277 | int ret; |
| 278 | char alias_name[VMBUS_ALIAS_LEN + 1]; | ||
| 246 | 279 | ||
| 247 | ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={" | 280 | print_alias_name(dev, alias_name); |
| 248 | "%02x%02x%02x%02x-%02x%02x-%02x%02x-" | 281 | ret = add_uevent_var(env, "MODALIAS=vmbus:%s", alias_name); |
| 249 | "%02x%02x%02x%02x%02x%02x%02x%02x}", | 282 | return ret; |
| 250 | dev->dev_type.data[3], | 283 | } |
| 251 | dev->dev_type.data[2], | ||
| 252 | dev->dev_type.data[1], | ||
| 253 | dev->dev_type.data[0], | ||
| 254 | dev->dev_type.data[5], | ||
| 255 | dev->dev_type.data[4], | ||
| 256 | dev->dev_type.data[7], | ||
| 257 | dev->dev_type.data[6], | ||
| 258 | dev->dev_type.data[8], | ||
| 259 | dev->dev_type.data[9], | ||
| 260 | dev->dev_type.data[10], | ||
| 261 | dev->dev_type.data[11], | ||
| 262 | dev->dev_type.data[12], | ||
| 263 | dev->dev_type.data[13], | ||
| 264 | dev->dev_type.data[14], | ||
| 265 | dev->dev_type.data[15]); | ||
| 266 | 284 | ||
| 267 | if (ret) | 285 | static uuid_le null_guid; |
| 268 | return ret; | ||
| 269 | 286 | ||
| 270 | ret = add_uevent_var(env, "VMBUS_DEVICE_DEVICE_GUID={" | 287 | static inline bool is_null_guid(const __u8 *guid) |
| 271 | "%02x%02x%02x%02x-%02x%02x-%02x%02x-" | 288 | { |
| 272 | "%02x%02x%02x%02x%02x%02x%02x%02x}", | 289 | if (memcmp(guid, &null_guid, sizeof(uuid_le))) |
| 273 | dev->dev_instance.data[3], | 290 | return false; |
| 274 | dev->dev_instance.data[2], | 291 | return true; |
| 275 | dev->dev_instance.data[1], | 292 | } |
| 276 | dev->dev_instance.data[0], | ||
| 277 | dev->dev_instance.data[5], | ||
| 278 | dev->dev_instance.data[4], | ||
| 279 | dev->dev_instance.data[7], | ||
| 280 | dev->dev_instance.data[6], | ||
| 281 | dev->dev_instance.data[8], | ||
| 282 | dev->dev_instance.data[9], | ||
| 283 | dev->dev_instance.data[10], | ||
| 284 | dev->dev_instance.data[11], | ||
| 285 | dev->dev_instance.data[12], | ||
| 286 | dev->dev_instance.data[13], | ||
| 287 | dev->dev_instance.data[14], | ||
| 288 | dev->dev_instance.data[15]); | ||
| 289 | if (ret) | ||
| 290 | return ret; | ||
| 291 | 293 | ||
| 292 | return 0; | 294 | /* |
| 295 | * Return a matching hv_vmbus_device_id pointer. | ||
| 296 | * If there is no match, return NULL. | ||
| 297 | */ | ||
| 298 | static const struct hv_vmbus_device_id *hv_vmbus_get_id( | ||
| 299 | const struct hv_vmbus_device_id *id, | ||
| 300 | __u8 *guid) | ||
| 301 | { | ||
| 302 | for (; !is_null_guid(id->guid); id++) | ||
| 303 | if (!memcmp(&id->guid, guid, sizeof(uuid_le))) | ||
| 304 | return id; | ||
| 305 | |||
| 306 | return NULL; | ||
| 293 | } | 307 | } |
| 294 | 308 | ||
| 295 | 309 | ||
| 310 | |||
| 296 | /* | 311 | /* |
| 297 | * vmbus_match - Attempt to match the specified device to the specified driver | 312 | * vmbus_match - Attempt to match the specified device to the specified driver |
| 298 | */ | 313 | */ |
| 299 | static int vmbus_match(struct device *device, struct device_driver *driver) | 314 | static int vmbus_match(struct device *device, struct device_driver *driver) |
| 300 | { | 315 | { |
| 301 | int match = 0; | ||
| 302 | struct hv_driver *drv = drv_to_hv_drv(driver); | 316 | struct hv_driver *drv = drv_to_hv_drv(driver); |
| 303 | struct hv_device *hv_dev = device_to_hv_device(device); | 317 | struct hv_device *hv_dev = device_to_hv_device(device); |
| 304 | 318 | ||
| 305 | /* We found our driver ? */ | 319 | if (hv_vmbus_get_id(drv->id_table, hv_dev->dev_type.b)) |
| 306 | if (memcmp(&hv_dev->dev_type, &drv->dev_type, | 320 | return 1; |
| 307 | sizeof(struct hv_guid)) == 0) | ||
| 308 | match = 1; | ||
| 309 | 321 | ||
| 310 | return match; | 322 | return 0; |
| 311 | } | 323 | } |
| 312 | 324 | ||
| 313 | /* | 325 | /* |
| @@ -319,9 +331,11 @@ static int vmbus_probe(struct device *child_device) · 5 unmodified lines | |||
| 319 | struct hv_driver *drv = | 331 | struct hv_driver *drv = |
| 320 | drv_to_hv_drv(child_device->driver); | 332 | drv_to_hv_drv(child_device->driver); |
| 321 | struct hv_device *dev = device_to_hv_device(child_device); | 333 | struct hv_device *dev = device_to_hv_device(child_device); |
| 334 | const struct hv_vmbus_device_id *dev_id; | ||
| 322 | 335 | ||
| 336 | dev_id = hv_vmbus_get_id(drv->id_table, dev->dev_type.b); | ||
| 323 | if (drv->probe) { | 337 | if (drv->probe) { |
| 324 | ret = drv->probe(dev); | 338 | ret = drv->probe(dev, dev_id); |
| 325 | if (ret != 0) | 339 | if (ret != 0) |
| 326 | pr_err("probe failed for device %s (%d)\n", | 340 | pr_err("probe failed for device %s (%d)\n", |
| 327 | dev_name(child_device), ret); | 341 | dev_name(child_device), ret); |
| @@ -339,22 +353,14 @@ static int vmbus_probe(struct device *child_device) · 11 unmodified lines | |||
| 339 | */ | 353 | */ |
| 340 | static int vmbus_remove(struct device *child_device) | 354 | static int vmbus_remove(struct device *child_device) |
| 341 | { | 355 | { |
| 342 | int ret; | 356 | struct hv_driver *drv = drv_to_hv_drv(child_device->driver); |
| 343 | struct hv_driver *drv; | ||
| 344 | |||
| 345 | struct hv_device *dev = device_to_hv_device(child_device); | 357 | struct hv_device *dev = device_to_hv_device(child_device); |
| 346 | 358 | ||
| 347 | if (child_device->driver) { | 359 | if (drv->remove) |
| 348 | drv = drv_to_hv_drv(child_device->driver); | 360 | drv->remove(dev); |
| 349 | 361 | else | |
| 350 | if (drv->remove) { | 362 | pr_err("remove not set for driver %s\n", |
| 351 | ret = drv->remove(dev); | 363 | dev_name(child_device)); |
| 352 | } else { | ||
| 353 | pr_err("remove not set for driver %s\n", | ||
| 354 | dev_name(child_device)); | ||
| 355 | ret = -ENODEV; | ||
| 356 | } | ||
| 357 | } | ||
| 358 | 364 | ||
| 359 | return 0; | 365 | return 0; |
| 360 | } | 366 | } |
| @@ -422,9 +428,6 @@ static void vmbus_onmessage_work(struct work_struct *work) · 61 unmodified lines | |||
| 422 | kfree(ctx); | 428 | kfree(ctx); |
| 423 | } | 429 | } |
| 424 | 430 | ||
| 425 | /* | ||
| 426 | * vmbus_on_msg_dpc - DPC routine to handle messages from the hypervisior | ||
| 427 | */ | ||
| 428 | static void vmbus_on_msg_dpc(unsigned long data) | 431 | static void vmbus_on_msg_dpc(unsigned long data) |
| 429 | { | 432 | { |
| 430 | int cpu = smp_processor_id(); | 433 | int cpu = smp_processor_id(); |
| @@ -468,53 +471,42 @@ static void vmbus_on_msg_dpc(unsigned long data) · 37 unmodified lines | |||
| 468 | } | 471 | } |
| 469 | } | 472 | } |
| 470 | 473 | ||
| 471 | /* | 474 | static irqreturn_t vmbus_isr(int irq, void *dev_id) |
| 472 | * vmbus_on_isr - ISR routine | ||
| 473 | */ | ||
| 474 | static int vmbus_on_isr(void) | ||
| 475 | { | 475 | { |
| 476 | int ret = 0; | ||
| 477 | int cpu = smp_processor_id(); | 476 | int cpu = smp_processor_id(); |
| 478 | void *page_addr; | 477 | void *page_addr; |
| 479 | struct hv_message *msg; | 478 | struct hv_message *msg; |
| 480 | union hv_synic_event_flags *event; | 479 | union hv_synic_event_flags *event; |
| 480 | bool handled = false; | ||
| 481 | 481 | ||
| 482 | page_addr = hv_context.synic_message_page[cpu]; | 482 | /* |
| 483 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; | 483 | * Check for events before checking for messages. This is the order |
| 484 | 484 | * in which events and messages are checked in Windows guests on | |
| 485 | /* Check if there are actual msgs to be process */ | 485 | * Hyper-V, and the Windows team suggested we do the same. |
| 486 | if (msg->header.message_type != HVMSG_NONE) | 486 | */ |
| 487 | ret |= 0x1; | ||
| 488 | 487 | ||
| 489 | page_addr = hv_context.synic_event_page[cpu]; | 488 | page_addr = hv_context.synic_event_page[cpu]; |
| 490 | event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; | 489 | event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT; |
| 491 | 490 | ||
| 492 | /* Since we are a child, we only need to check bit 0 */ | 491 | /* Since we are a child, we only need to check bit 0 */ |
| 493 | if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) | 492 | if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) { |
| 494 | ret |= 0x2; | 493 | handled = true; |
| 495 | 494 | tasklet_schedule(&event_dpc); | |
| 496 | return ret; | 495 | } |
| 497 | } | ||
| 498 | |||
| 499 | |||
| 500 | static irqreturn_t vmbus_isr(int irq, void *dev_id) | ||
| 501 | { | ||
| 502 | int ret; | ||
| 503 | |||
| 504 | ret = vmbus_on_isr(); | ||
| 505 | 496 | ||
| 506 | /* Schedules a dpc if necessary */ | 497 | page_addr = hv_context.synic_message_page[cpu]; |
| 507 | if (ret > 0) { | 498 | msg = (struct hv_message *)page_addr + VMBUS_MESSAGE_SINT; |
| 508 | if (test_bit(0, (unsigned long *)&ret)) | ||
| 509 | tasklet_schedule(&msg_dpc); | ||
| 510 | 499 | ||
| 511 | if (test_bit(1, (unsigned long *)&ret)) | 500 | /* Check if there are actual msgs to be processed */ |
| 512 | tasklet_schedule(&event_dpc); | 501 | if (msg->header.message_type != HVMSG_NONE) { |
| 502 | handled = true; | ||
| 503 | tasklet_schedule(&msg_dpc); | ||
| 504 | } | ||
| 513 | 505 | ||
| 506 | if (handled) | ||
| 514 | return IRQ_HANDLED; | 507 | return IRQ_HANDLED; |
| 515 | } else { | 508 | else |
| 516 | return IRQ_NONE; | 509 | return IRQ_NONE; |
| 517 | } | ||
| 518 | } | 510 | } |
| 519 | 511 | ||
| 520 | /* | 512 | /* |
| @@ -538,26 +530,20 @@ static int vmbus_bus_init(int irq) · 17 unmodified lines | |||
| 538 | return ret; | 530 | return ret; |
| 539 | } | 531 | } |
| 540 | 532 | ||
| 541 | /* Initialize the bus context */ | ||
| 542 | tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0); | 533 | tasklet_init(&msg_dpc, vmbus_on_msg_dpc, 0); |
| 543 | tasklet_init(&event_dpc, vmbus_on_event, 0); | 534 | tasklet_init(&event_dpc, vmbus_on_event, 0); |
| 544 | 535 | ||
| 545 | /* Now, register the bus with LDM */ | ||
| 546 | ret = bus_register(&hv_bus); | 536 | ret = bus_register(&hv_bus); |
| 547 | if (ret) | 537 | if (ret) |
| 548 | return ret; | 538 | goto err_cleanup; |
| 549 | 539 | ||
| 550 | /* Get the interrupt resource */ | ||
| 551 | ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM, | 540 | ret = request_irq(irq, vmbus_isr, IRQF_SAMPLE_RANDOM, |
| 552 | driver_name, hv_acpi_dev); | 541 | driver_name, hv_acpi_dev); |
| 553 | 542 | ||
| 554 | if (ret != 0) { | 543 | if (ret != 0) { |
| 555 | pr_err("Unable to request IRQ %d\n", | 544 | pr_err("Unable to request IRQ %d\n", |
| 556 | irq); | 545 | irq); |
| 557 | 546 | goto err_unregister; | |
| 558 | bus_unregister(&hv_bus); | ||
| 559 | |||
| 560 | return ret; | ||
| 561 | } | 547 | } |
| 562 | 548 | ||
| 563 | vector = IRQ0_VECTOR + irq; | 549 | vector = IRQ0_VECTOR + irq; |
| @@ -568,76 +554,81 @@ static int vmbus_bus_init(int irq) · 4 unmodified lines | |||
| 568 | */ | 554 | */ |
| 569 | on_each_cpu(hv_synic_init, (void *)&vector, 1); | 555 | on_each_cpu(hv_synic_init, (void *)&vector, 1); |
| 570 | ret = vmbus_connect(); | 556 | ret = vmbus_connect(); |
| 571 | if (ret) { | 557 | if (ret) |
| 572 | free_irq(irq, hv_acpi_dev); | 558 | goto err_irq; |
| 573 | bus_unregister(&hv_bus); | ||
| 574 | return ret; | ||
| 575 | } | ||
| 576 | |||
| 577 | 559 | ||
| 578 | vmbus_request_offers(); | 560 | vmbus_request_offers(); |
| 579 | 561 | ||
| 580 | return 0; | 562 | return 0; |
| 563 | |||
| 564 | err_irq: | ||
| 565 | free_irq(irq, hv_acpi_dev); | ||
| 566 | |||
| 567 | err_unregister: | ||
| 568 | bus_unregister(&hv_bus); | ||
| 569 | |||
| 570 | err_cleanup: | ||
| 571 | hv_cleanup(); | ||
| 572 | |||
| 573 | return ret; | ||
| 581 | } | 574 | } |
| 582 | 575 | ||
| 583 | /** | 576 | /** |
| 584 | * vmbus_child_driver_register() - Register a vmbus's child driver | 577 | * __vmbus_child_driver_register - Register a vmbus's driver |
| 585 | * @drv: Pointer to driver structure you want to register | 578 | * @drv: Pointer to driver structure you want to register |
| 586 | * | 579 | * @owner: owner module of the drv |
| 580 | * @mod_name: module name string | ||
| 587 | * | 581 | * |
| 588 | * Registers the given driver with Linux through the 'driver_register()' call | 582 | * Registers the given driver with Linux through the 'driver_register()' call |
| 589 | * And sets up the hyper-v vmbus handling for this driver. | 583 | * and sets up the hyper-v vmbus handling for this driver. |
| 590 | * It will return the state of the 'driver_register()' call. | 584 | * It will return the state of the 'driver_register()' call. |
| 591 | * | 585 | * |
| 592 | * Mainly used by Hyper-V drivers. | ||
| 593 | */ | 586 | */ |
| 594 | int vmbus_child_driver_register(struct device_driver *drv) | 587 | int __vmbus_driver_register(struct hv_driver *hv_driver, struct module *owner, const char *mod_name) |
| 595 | { | 588 | { |
| 596 | int ret; | 589 | int ret; |
| 597 | 590 | ||
| 598 | pr_info("child driver registering - name %s\n", drv->name); | 591 | pr_info("registering driver %s\n", hv_driver->name); |
| 599 | 592 | ||
| 600 | /* The child driver on this vmbus */ | 593 | hv_driver->driver.name = hv_driver->name; |
| 601 | drv->bus = &hv_bus; | 594 | hv_driver->driver.owner = owner; |
| 595 | hv_driver->driver.mod_name = mod_name; | ||
| 596 | hv_driver->driver.bus = &hv_bus; | ||
| 602 | 597 | ||
| 603 | ret = driver_register(drv); | 598 | ret = driver_register(&hv_driver->driver); |
| 604 | 599 | ||
| 605 | vmbus_request_offers(); | 600 | vmbus_request_offers(); |
| 606 | 601 | ||
| 607 | return ret; | 602 | return ret; |
| 608 | } | 603 | } |
| 609 | EXPORT_SYMBOL(vmbus_child_driver_register); | 604 | EXPORT_SYMBOL_GPL(__vmbus_driver_register); |
| 610 | 605 | ||
| 611 | /** | 606 | /** |
| 612 | * vmbus_child_driver_unregister() - Unregister a vmbus's child driver | 607 | * vmbus_driver_unregister() - Unregister a vmbus's driver |
| 613 | * @drv: Pointer to driver structure you want to un-register | 608 | * @drv: Pointer to driver structure you want to un-register |
| 614 | * | ||
| 615 | * | ||
| 616 | * Un-register the given driver with Linux through the 'driver_unregister()' | ||
| 617 | * call. And ungegisters the driver from the Hyper-V vmbus handler. | ||
| 618 | * | 609 | * |
| 619 | * Mainly used by Hyper-V drivers. | 610 | * Un-register the given driver that was previous registered with a call to |
| 611 | * vmbus_driver_register() | ||
| 620 | */ | 612 | */ |
| 621 | void vmbus_child_driver_unregister(struct device_driver *drv) | 613 | void vmbus_driver_unregister(struct hv_driver *hv_driver) |
| 622 | { | 614 | { |
| 623 | pr_info("child driver unregistering - name %s\n", drv->name); | 615 | pr_info("unregistering driver %s\n", hv_driver->name); |
| 624 | 616 | ||
| 625 | driver_unregister(drv); | 617 | driver_unregister(&hv_driver->driver); |
| 626 | 618 | ||
| 627 | } | 619 | } |
| 628 | EXPORT_SYMBOL(vmbus_child_driver_unregister); | 620 | EXPORT_SYMBOL_GPL(vmbus_driver_unregister); |
| 629 | 621 | ||
| 630 | /* | 622 | /* |
| 631 | * vmbus_child_device_create - Creates and registers a new child device | 623 | * vmbus_device_create - Creates and registers a new child device |
| 632 | * on the vmbus. | 624 | * on the vmbus. |
| 633 | */ | 625 | */ |
| 634 | struct hv_device *vmbus_child_device_create(struct hv_guid *type, | 626 | struct hv_device *vmbus_device_create(uuid_le *type, |
| 635 | struct hv_guid *instance, | 627 | uuid_le *instance, |
| 636 | struct vmbus_channel *channel) | 628 | struct vmbus_channel *channel) |
| 637 | { | 629 | { |
| 638 | struct hv_device *child_device_obj; | 630 | struct hv_device *child_device_obj; |
| 639 | 631 | ||
| 640 | /* Allocate the new child device */ | ||
| 641 | child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL); | 632 | child_device_obj = kzalloc(sizeof(struct hv_device), GFP_KERNEL); |
| 642 | if (!child_device_obj) { | 633 | if (!child_device_obj) { |
| 643 | pr_err("Unable to allocate device object for child device\n"); | 634 | pr_err("Unable to allocate device object for child device\n"); |
| @@ -645,29 +636,27 @@ struct hv_device *vmbus_child_device_create(struct hv_guid *type, · 1 unmodified line | |||
| 645 | } | 636 | } |
| 646 | 637 | ||
| 647 | child_device_obj->channel = channel; | 638 | child_device_obj->channel = channel; |
| 648 | memcpy(&child_device_obj->dev_type, type, sizeof(struct hv_guid)); | 639 | memcpy(&child_device_obj->dev_type, type, sizeof(uuid_le)); |
| 649 | memcpy(&child_device_obj->dev_instance, instance, | 640 | memcpy(&child_device_obj->dev_instance, instance, |
| 650 | sizeof(struct hv_guid)); | 641 | sizeof(uuid_le)); |
| 651 | 642 | ||
| 652 | 643 | ||
| 653 | return child_device_obj; | 644 | return child_device_obj; |
| 654 | } | 645 | } |
| 655 | 646 | ||
| 656 | /* | 647 | /* |
| 657 | * vmbus_child_device_register - Register the child device | 648 | * vmbus_device_register - Register the child device |
| 658 | */ | 649 | */ |
| 659 | int vmbus_child_device_register(struct hv_device *child_device_obj) | 650 | int vmbus_device_register(struct hv_device *child_device_obj) |
| 660 | { | 651 | { |
| 661 | int ret = 0; | 652 | int ret = 0; |
| 662 | 653 | ||
| 663 | static atomic_t device_num = ATOMIC_INIT(0); | 654 | static atomic_t device_num = ATOMIC_INIT(0); |
| 664 | 655 | ||
| 665 | /* Set the device name. Otherwise, device_register() will fail. */ | ||
| 666 | dev_set_name(&child_device_obj->device, "vmbus_0_%d", | 656 | dev_set_name(&child_device_obj->device, "vmbus_0_%d", |
| 667 | atomic_inc_return(&device_num)); | 657 | atomic_inc_return(&device_num)); |
| 668 | 658 | ||
| 669 | /* The new device belongs to this bus */ | 659 | child_device_obj->device.bus = &hv_bus; |
| 670 | child_device_obj->device.bus = &hv_bus; /* device->dev.bus; */ | ||
| 671 | child_device_obj->device.parent = &hv_acpi_dev->dev; | 660 | child_device_obj->device.parent = &hv_acpi_dev->dev; |
| 672 | child_device_obj->device.release = vmbus_device_release; | 661 | child_device_obj->device.release = vmbus_device_release; |
| 673 | 662 | ||
| @@ -687,10 +676,10 @@ int vmbus_child_device_register(struct hv_device *child_device_obj) · 13 unmodified lines | |||
| 687 | } | 676 | } |
| 688 | 677 | ||
| 689 | /* | 678 | /* |
| 690 | * vmbus_child_device_unregister - Remove the specified child device | 679 | * vmbus_device_unregister - Remove the specified child device |
| 691 | * from the vmbus. | 680 | * from the vmbus. |
| 692 | */ | 681 | */ |
| 693 | void vmbus_child_device_unregister(struct hv_device *device_obj) | 682 | void vmbus_device_unregister(struct hv_device *device_obj) |
| 694 | { | 683 | { |
| 695 | /* | 684 | /* |
| 696 | * Kick off the process of unregistering the device. | 685 | * Kick off the process of unregistering the device. |
| @@ -727,9 +716,8 @@ static int vmbus_acpi_add(struct acpi_device *device) · 30 unmodified lines | |||
| 727 | 716 | ||
| 728 | hv_acpi_dev = device; | 717 | hv_acpi_dev = device; |
| 729 | 718 | ||
| 730 | result = | 719 | result = acpi_walk_resources(device->handle, METHOD_NAME__CRS, |
| 731 | acpi_walk_resources(device->handle, METHOD_NAME__CRS, | 720 | vmbus_walk_resources, &irq); |
| 732 | vmbus_walk_resources, &irq); | ||
| 733 | 721 | ||
| 734 | if (ACPI_FAILURE(result)) { | 722 | if (ACPI_FAILURE(result)) { |
| 735 | complete(&probe_event); | 723 | complete(&probe_event); |
| @@ -754,21 +742,9 @@ static struct acpi_driver vmbus_acpi_driver = { · 18 unmodified lines | |||
| 754 | }, | 742 | }, |
| 755 | }; | 743 | }; |
| 756 | 744 | ||
| 757 | /* | ||
| 758 | * We use a PCI table to determine if we should autoload this driver This is | ||
| 759 | * needed by distro tools to determine if the hyperv drivers should be | ||
| 760 | * installed and/or configured. We don't do anything else with the table, but | ||
| 761 | * it needs to be present. | ||
| 762 | */ | ||
| 763 | static const struct pci_device_id microsoft_hv_pci_table[] = { | ||
| 764 | { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */ | ||
| 765 | { 0 } | ||
| 766 | }; | ||
| 767 | MODULE_DEVICE_TABLE(pci, microsoft_hv_pci_table); | ||
| 768 | |||
| 769 | static int __init hv_acpi_init(void) | 745 | static int __init hv_acpi_init(void) |
| 770 | { | 746 | { |
| 771 | int ret; | 747 | int ret, t; |
| 772 | 748 | ||
| 773 | init_completion(&probe_event); | 749 | init_completion(&probe_event); |
| 774 | 750 | ||
| @@ -781,22 +757,30 @@ static int __init hv_acpi_init(void) · 6 unmodified lines | |||
| 781 | if (ret) | 757 | if (ret) |
| 782 | return ret; | 758 | return ret; |
| 783 | 759 | ||
| 784 | wait_for_completion(&probe_event); | 760 | t = wait_for_completion_timeout(&probe_event, 5*HZ); |
| 761 | if (t == 0) { | ||
| 762 | ret = -ETIMEDOUT; | ||
| 763 | goto cleanup; | ||
| 764 | } | ||
| 785 | 765 | ||
| 786 | if (irq <= 0) { | 766 | if (irq <= 0) { |
| 787 | acpi_bus_unregister_driver(&vmbus_acpi_driver); | 767 | ret = -ENODEV; |
| 788 | return -ENODEV; | 768 | goto cleanup; |
| 789 | } | 769 | } |
| 790 | 770 | ||
| 791 | ret = vmbus_bus_init(irq); | 771 | ret = vmbus_bus_init(irq); |
| 792 | if (ret) | 772 | if (ret) |
| 793 | acpi_bus_unregister_driver(&vmbus_acpi_driver); | 773 | goto cleanup; |
| 774 | |||
| 775 | return 0; | ||
| 776 | |||
| 777 | cleanup: | ||
| 778 | acpi_bus_unregister_driver(&vmbus_acpi_driver); | ||
| 794 | return ret; | 779 | return ret; |
| 795 | } | 780 | } |
| 796 | 781 | ||
| 797 | 782 | ||
| 798 | MODULE_LICENSE("GPL"); | 783 | MODULE_LICENSE("GPL"); |
| 799 | MODULE_VERSION(HV_DRV_VERSION); | 784 | MODULE_VERSION(HV_DRV_VERSION); |
| 800 | module_param(vmbus_loglevel, int, S_IRUGO|S_IWUSR); | ||
| 801 | 785 | ||
| 802 | module_init(hv_acpi_init); | 786 | module_init(hv_acpi_init); |
| @@ -46,8 +46,6 @@ source "drivers/staging/wlan-ng/Kconfig" · 45 unmodified lines | |||
| 46 | 46 | ||
| 47 | source "drivers/staging/echo/Kconfig" | 47 | source "drivers/staging/echo/Kconfig" |
| 48 | 48 | ||
| 49 | |||
| 50 | |||
| 51 | source "drivers/staging/comedi/Kconfig" | 49 | source "drivers/staging/comedi/Kconfig" |
| 52 | 50 | ||
| 53 | source "drivers/staging/olpc_dcon/Kconfig" | 51 | source "drivers/staging/olpc_dcon/Kconfig" |
| @@ -66,6 +64,8 @@ source "drivers/staging/rtl8712/Kconfig" · 12 unmodified lines | |||
| 66 | 64 | ||
| 67 | source "drivers/staging/rts_pstor/Kconfig" | 65 | source "drivers/staging/rts_pstor/Kconfig" |
| 68 | 66 | ||
| 67 | source "drivers/staging/rts5139/Kconfig" | ||
| 68 | |||
| 69 | source "drivers/staging/frontier/Kconfig" | 69 | source "drivers/staging/frontier/Kconfig" |
| 70 | 70 | ||
| 71 | source "drivers/staging/pohmelfs/Kconfig" | 71 | source "drivers/staging/pohmelfs/Kconfig" |
| @@ -15,8 +15,6 @@ obj-$(CONFIG_USBIP_CORE) += usbip/ · 14 unmodified lines | |||
| 15 | obj-$(CONFIG_W35UND) += winbond/ | 15 | obj-$(CONFIG_W35UND) += winbond/ |
| 16 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ | 16 | obj-$(CONFIG_PRISM2_USB) += wlan-ng/ |
| 17 | obj-$(CONFIG_ECHO) += echo/ | 17 | obj-$(CONFIG_ECHO) += echo/ |
| 18 | |||
| 19 | |||
| 20 | obj-$(CONFIG_COMEDI) += comedi/ | 18 | obj-$(CONFIG_COMEDI) += comedi/ |
| 21 | obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ | 19 | obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ |
| 22 | obj-$(CONFIG_ASUS_OLED) += asus_oled/ | 20 | obj-$(CONFIG_ASUS_OLED) += asus_oled/ |
| @@ -26,6 +24,7 @@ obj-$(CONFIG_RTL8192U) += rtl8192u/ · 3 unmodified lines | |||
| 26 | obj-$(CONFIG_RTL8192E) += rtl8192e/ | 24 | obj-$(CONFIG_RTL8192E) += rtl8192e/ |
| 27 | obj-$(CONFIG_R8712U) += rtl8712/ | 25 | obj-$(CONFIG_R8712U) += rtl8712/ |
| 28 | obj-$(CONFIG_RTS_PSTOR) += rts_pstor/ | 26 | obj-$(CONFIG_RTS_PSTOR) += rts_pstor/ |
| 27 | obj-$(CONFIG_RTS5139) += rts5139/ | ||
| 29 | obj-$(CONFIG_SPECTRA) += spectra/ | 28 | obj-$(CONFIG_SPECTRA) += spectra/ |
| 30 | obj-$(CONFIG_TRANZPORT) += frontier/ | 29 | obj-$(CONFIG_TRANZPORT) += frontier/ |
| 31 | obj-$(CONFIG_POHMELFS) += pohmelfs/ | 30 | obj-$(CONFIG_POHMELFS) += pohmelfs/ |
| @@ -28,6 +28,7 @@ · 27 unmodified lines | |||
| 28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 29 | #include <linux/firmware.h> | 29 | #include <linux/firmware.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/module.h> | ||
| 31 | #include "altera.h" | 32 | #include "altera.h" |
| 32 | #include "altera-exprt.h" | 33 | #include "altera-exprt.h" |
| 33 | #include "altera-jtag.h" | 34 | #include "altera-jtag.h" |
| @@ -2384,7 +2385,7 @@ static int altera_get_act_info(u8 *p, · 2350 unmodified lines | |||
| 2384 | act_proc_attribute = | 2385 | act_proc_attribute = |
| 2385 | (p[proc_table + (13 * act_proc_id) + 8] & 0x03); | 2386 | (p[proc_table + (13 * act_proc_id) + 8] & 0x03); |
| 2386 | 2387 | ||
| 2387 | procptr = (struct altera_procinfo *) | 2388 | procptr = |
| 2388 | kzalloc(sizeof(struct altera_procinfo), | 2389 | kzalloc(sizeof(struct altera_procinfo), |
| 2389 | GFP_KERNEL); | 2390 | GFP_KERNEL); |
| 2390 | 2391 | ||
| @@ -34,7 +34,7 @@ static int bcm_char_open(struct inode *inode, struct file * filp) · 33 unmodified lines | |||
| 34 | /* Store the Adapter structure */ | 34 | /* Store the Adapter structure */ |
| 35 | filp->private_data = pTarang; | 35 | filp->private_data = pTarang; |
| 36 | 36 | ||
| 37 | /*Start Queuing the control response Packets*/ | 37 | /* Start Queuing the control response Packets */ |
| 38 | atomic_inc(&Adapter->ApplicationRunning); | 38 | atomic_inc(&Adapter->ApplicationRunning); |
| 39 | 39 | ||
| 40 | nonseekable_open(inode, filp); | 40 | nonseekable_open(inode, filp); |
| @@ -84,7 +84,7 @@ static int bcm_char_release(struct inode *inode, struct file *filp) · 43 unmodified lines | |||
| 84 | 84 | ||
| 85 | up(&Adapter->RxAppControlQueuelock); | 85 | up(&Adapter->RxAppControlQueuelock); |
| 86 | 86 | ||
| 87 | /*Stop Queuing the control response Packets*/ | 87 | /* Stop Queuing the control response Packets */ |
| 88 | atomic_dec(&Adapter->ApplicationRunning); | 88 | atomic_dec(&Adapter->ApplicationRunning); |
| 89 | 89 | ||
| 90 | kfree(pTarang); | 90 | kfree(pTarang); |
| @@ -100,8 +100,8 @@ static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, · 9 unmodified lines | |||
| 100 | PPER_TARANG_DATA pTarang = filp->private_data; | 100 | PPER_TARANG_DATA pTarang = filp->private_data; |
| 101 | PMINI_ADAPTER Adapter = pTarang->Adapter; | 101 | PMINI_ADAPTER Adapter = pTarang->Adapter; |
| 102 | struct sk_buff *Packet = NULL; | 102 | struct sk_buff *Packet = NULL; |
| 103 | ssize_t PktLen = 0; | 103 | ssize_t PktLen = 0; |
| 104 | int wait_ret_val = 0; | 104 | int wait_ret_val = 0; |
| 105 | unsigned long ret = 0; | 105 | unsigned long ret = 0; |
| 106 | 106 | ||
| 107 | wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue, | 107 | wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue, |
| @@ -157,1942 +157,1824 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) · 49 unmodified lines | |||
| 157 | { | 157 | { |
| 158 | PPER_TARANG_DATA pTarang = filp->private_data; | 158 | PPER_TARANG_DATA pTarang = filp->private_data; |
| 159 | void __user *argp = (void __user *)arg; | 159 | void __user *argp = (void __user *)arg; |
| 160 | PMINI_ADAPTER Adapter = pTarang->Adapter; | 160 | PMINI_ADAPTER Adapter = pTarang->Adapter; |
| 161 | INT Status = STATUS_FAILURE; | 161 | INT Status = STATUS_FAILURE; |
| 162 | int timeout = 0; | 162 | int timeout = 0; |
| 163 | IOCTL_BUFFER IoBuffer; | 163 | IOCTL_BUFFER IoBuffer; |
| 164 | 164 | ||
| 165 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); | 165 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); |
| 166 | 166 | ||
| 167 | if(_IOC_TYPE(cmd) != BCM_IOCTL) | 167 | if (_IOC_TYPE(cmd) != BCM_IOCTL) |
| 168 | return -EFAULT; | 168 | return -EFAULT; |
| 169 | if(_IOC_DIR(cmd) & _IOC_READ) | 169 | if (_IOC_DIR(cmd) & _IOC_READ) |
| 170 | Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd)); | 170 | Status = !access_ok(VERIFY_WRITE, argp, _IOC_SIZE(cmd)); |
| 171 | else if (_IOC_DIR(cmd) & _IOC_WRITE) | 171 | else if (_IOC_DIR(cmd) & _IOC_WRITE) |
| 172 | Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd)); | 172 | Status = !access_ok(VERIFY_READ, argp, _IOC_SIZE(cmd)); |
| 173 | else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE)) | 173 | else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE)) |
| 174 | Status = STATUS_SUCCESS; | 174 | Status = STATUS_SUCCESS; |
| 175 | 175 | ||
| 176 | if(Status) | 176 | if (Status) |
| 177 | return -EFAULT; | 177 | return -EFAULT; |
| 178 | 178 | ||
| 179 | if(Adapter->device_removed) | 179 | if (Adapter->device_removed) |
| 180 | { | ||
| 181 | return -EFAULT; | 180 | return -EFAULT; |
| 182 | } | ||
| 183 | 181 | ||
| 184 | if(FALSE == Adapter->fw_download_done) | 182 | if (FALSE == Adapter->fw_download_done) { |
| 185 | { | 183 | switch (cmd) { |
| 186 | switch (cmd) | 184 | case IOCTL_MAC_ADDR_REQ: |
| 187 | { | 185 | case IOCTL_LINK_REQ: |
| 188 | case IOCTL_MAC_ADDR_REQ: | 186 | case IOCTL_CM_REQUEST: |
| 189 | case IOCTL_LINK_REQ: | 187 | case IOCTL_SS_INFO_REQ: |
| 190 | case IOCTL_CM_REQUEST: | 188 | case IOCTL_SEND_CONTROL_MESSAGE: |
| 191 | case IOCTL_SS_INFO_REQ: | 189 | case IOCTL_IDLE_REQ: |
| 192 | case IOCTL_SEND_CONTROL_MESSAGE: | 190 | case IOCTL_BCM_GPIO_SET_REQUEST: |
| 193 | case IOCTL_IDLE_REQ: | 191 | case IOCTL_BCM_GPIO_STATUS_REQUEST: |
| 194 | case IOCTL_BCM_GPIO_SET_REQUEST: | 192 | return -EACCES; |
| 195 | case IOCTL_BCM_GPIO_STATUS_REQUEST: | 193 | default: |
| 196 | return -EACCES; | 194 | break; |
| 197 | default: | ||
| 198 | break; | ||
| 199 | } | 195 | } |
| 200 | } | 196 | } |
| 201 | 197 | ||
| 202 | Status = vendorextnIoctl(Adapter, cmd, arg); | 198 | Status = vendorextnIoctl(Adapter, cmd, arg); |
| 203 | if(Status != CONTINUE_COMMON_PATH ) | 199 | if (Status != CONTINUE_COMMON_PATH) |
| 204 | return Status; | 200 | return Status; |
| 205 | 201 | ||
| 206 | switch(cmd){ | 202 | switch (cmd) { |
| 207 | // Rdms for Swin Idle... | 203 | /* Rdms for Swin Idle... */ |
| 208 | case IOCTL_BCM_REGISTER_READ_PRIVATE: | 204 | case IOCTL_BCM_REGISTER_READ_PRIVATE: { |
| 209 | { | 205 | RDM_BUFFER sRdmBuffer = {0}; |
| 210 | RDM_BUFFER sRdmBuffer = {0}; | 206 | PCHAR temp_buff; |
| 211 | PCHAR temp_buff; | 207 | UINT Bufflen; |
| 212 | UINT Bufflen; | 208 | u16 temp_value; |
| 209 | |||
| 210 | /* Copy Ioctl Buffer structure */ | ||
| 211 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 212 | return -EFAULT; | ||
| 213 | 213 | ||
| 214 | /* Copy Ioctl Buffer structure */ | 214 | if (IoBuffer.InputLength > sizeof(sRdmBuffer)) |
| 215 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 215 | return -EINVAL; |
| 216 | return -EFAULT; | ||
| 217 | 216 | ||
| 218 | if (IoBuffer.InputLength > sizeof(sRdmBuffer)) | 217 | if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) |
| 219 | return -EINVAL; | 218 | return -EFAULT; |
| 220 | 219 | ||
| 221 | if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 220 | if (IoBuffer.OutputLength > USHRT_MAX || |
| 222 | return -EFAULT; | 221 | IoBuffer.OutputLength == 0) { |
| 222 | return -EINVAL; | ||
| 223 | } | ||
| 223 | 224 | ||
| 224 | /* FIXME: need to restrict BuffLen */ | 225 | Bufflen = IoBuffer.OutputLength; |
| 225 | Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4; | 226 | temp_value = 4 - (Bufflen % 4); |
| 226 | temp_buff = kmalloc(Bufflen, GFP_KERNEL); | 227 | Bufflen += temp_value % 4; |
| 227 | if(!temp_buff) | ||
| 228 | return -ENOMEM; | ||
| 229 | 228 | ||
| 230 | Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register, | 229 | temp_buff = kmalloc(Bufflen, GFP_KERNEL); |
| 231 | (PUINT)temp_buff, Bufflen); | 230 | if (!temp_buff) |
| 232 | if(Status == STATUS_SUCCESS) | 231 | return -ENOMEM; |
| 233 | { | ||
| 234 | if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) | ||
| 235 | Status = -EFAULT; | ||
| 236 | } | ||
| 237 | 232 | ||
| 238 | kfree(temp_buff); | 233 | Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register, |
| 239 | break; | 234 | (PUINT)temp_buff, Bufflen); |
| 235 | if (Status == STATUS_SUCCESS) { | ||
| 236 | if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) | ||
| 237 | Status = -EFAULT; | ||
| 240 | } | 238 | } |
| 241 | case IOCTL_BCM_REGISTER_WRITE_PRIVATE: | ||
| 242 | { | ||
| 243 | WRM_BUFFER sWrmBuffer = {0}; | ||
| 244 | UINT uiTempVar=0; | ||
| 245 | /* Copy Ioctl Buffer structure */ | ||
| 246 | 239 | ||
| 247 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 240 | kfree(temp_buff); |
| 248 | return -EFAULT; | 241 | break; |
| 242 | } | ||
| 249 | 243 | ||
| 250 | if (IoBuffer.InputLength > sizeof(sWrmBuffer)) | 244 | case IOCTL_BCM_REGISTER_WRITE_PRIVATE: { |
| 251 | return -EINVAL; | 245 | WRM_BUFFER sWrmBuffer = {0}; |
| 246 | UINT uiTempVar = 0; | ||
| 247 | /* Copy Ioctl Buffer structure */ | ||
| 252 | 248 | ||
| 253 | /* Get WrmBuffer structure */ | 249 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 254 | if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 250 | return -EFAULT; |
| 255 | return -EFAULT; | 251 | |
| 252 | if (IoBuffer.InputLength > sizeof(sWrmBuffer)) | ||
| 253 | return -EINVAL; | ||
| 256 | 254 | ||
| 257 | uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; | 255 | /* Get WrmBuffer structure */ |
| 258 | if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && | 256 | if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) |
| 259 | ((uiTempVar == EEPROM_REJECT_REG_1)|| | 257 | return -EFAULT; |
| 258 | |||
| 259 | uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; | ||
| 260 | if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && | ||
| 261 | ((uiTempVar == EEPROM_REJECT_REG_1) || | ||
| 260 | (uiTempVar == EEPROM_REJECT_REG_2) || | 262 | (uiTempVar == EEPROM_REJECT_REG_2) || |
| 261 | (uiTempVar == EEPROM_REJECT_REG_3) || | 263 | (uiTempVar == EEPROM_REJECT_REG_3) || |
| 262 | (uiTempVar == EEPROM_REJECT_REG_4))) | 264 | (uiTempVar == EEPROM_REJECT_REG_4))) { |
| 263 | { | 265 | |
| 264 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); | 266 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); |
| 265 | return -EFAULT; | 267 | return -EFAULT; |
| 266 | } | ||
| 267 | Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register, | ||
| 268 | (PUINT)sWrmBuffer.Data, sizeof(ULONG)); | ||
| 269 | if(Status == STATUS_SUCCESS) | ||
| 270 | { | ||
| 271 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"WRM Done\n"); | ||
| 272 | } | ||
| 273 | else | ||
| 274 | { | ||
| 275 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); | ||
| 276 | Status = -EFAULT; | ||
| 277 | } | ||
| 278 | break; | ||
| 279 | } | 268 | } |
| 280 | 269 | ||
| 281 | case IOCTL_BCM_REGISTER_READ: | 270 | Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register, |
| 282 | case IOCTL_BCM_EEPROM_REGISTER_READ: | 271 | (PUINT)sWrmBuffer.Data, sizeof(ULONG)); |
| 283 | { | ||
| 284 | RDM_BUFFER sRdmBuffer = {0}; | ||
| 285 | PCHAR temp_buff = NULL; | ||
| 286 | UINT uiTempVar = 0; | ||
| 287 | if((Adapter->IdleMode == TRUE) || | ||
| 288 | (Adapter->bShutStatus ==TRUE) || | ||
| 289 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 290 | { | ||
| 291 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n"); | ||
| 292 | return -EACCES; | ||
| 293 | } | ||
| 294 | /* Copy Ioctl Buffer structure */ | ||
| 295 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 296 | return -EFAULT; | ||
| 297 | 272 | ||
| 298 | if (IoBuffer.InputLength > sizeof(sRdmBuffer)) | 273 | if (Status == STATUS_SUCCESS) { |
| 299 | return -EINVAL; | 274 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); |
| 275 | } else { | ||
| 276 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); | ||
| 277 | Status = -EFAULT; | ||
| 278 | } | ||
| 279 | break; | ||
| 280 | } | ||
| 300 | 281 | ||
| 301 | if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 282 | case IOCTL_BCM_REGISTER_READ: |
| 302 | return -EFAULT; | 283 | case IOCTL_BCM_EEPROM_REGISTER_READ: { |
| 284 | RDM_BUFFER sRdmBuffer = {0}; | ||
| 285 | PCHAR temp_buff = NULL; | ||
| 286 | UINT uiTempVar = 0; | ||
| 287 | if ((Adapter->IdleMode == TRUE) || | ||
| 288 | (Adapter->bShutStatus == TRUE) || | ||
| 289 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 290 | |||
| 291 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n"); | ||
| 292 | return -EACCES; | ||
| 293 | } | ||
| 303 | 294 | ||
| 304 | /* FIXME: don't trust user supplied length */ | 295 | /* Copy Ioctl Buffer structure */ |
| 305 | temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL); | 296 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 306 | if(!temp_buff) | 297 | return -EFAULT; |
| 307 | return STATUS_FAILURE; | ||
| 308 | 298 | ||
| 309 | if((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || | 299 | if (IoBuffer.InputLength > sizeof(sRdmBuffer)) |
| 310 | ((ULONG)sRdmBuffer.Register & 0x3)) | 300 | return -EINVAL; |
| 311 | { | 301 | |
| 312 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n", | 302 | if (copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) |
| 313 | (int)sRdmBuffer.Register); | 303 | return -EFAULT; |
| 314 | return -EINVAL; | ||
| 315 | } | ||
| 316 | 304 | ||
| 317 | uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; | 305 | /* FIXME: don't trust user supplied length */ |
| 318 | Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, | 306 | temp_buff = kmalloc(IoBuffer.OutputLength, GFP_KERNEL); |
| 319 | (PUINT)temp_buff, IoBuffer.OutputLength); | 307 | if (!temp_buff) |
| 320 | if(Status == STATUS_SUCCESS) | 308 | return STATUS_FAILURE; |
| 321 | if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) | 309 | |
| 322 | Status = -EFAULT; | 310 | if ((((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || |
| 311 | ((ULONG)sRdmBuffer.Register & 0x3)) { | ||
| 312 | |||
| 313 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n", | ||
| 314 | (int)sRdmBuffer.Register); | ||
| 323 | 315 | ||
| 324 | kfree(temp_buff); | 316 | kfree(temp_buff); |
| 325 | break; | 317 | return -EINVAL; |
| 326 | } | 318 | } |
| 327 | case IOCTL_BCM_REGISTER_WRITE: | ||
| 328 | case IOCTL_BCM_EEPROM_REGISTER_WRITE: | ||
| 329 | { | ||
| 330 | WRM_BUFFER sWrmBuffer = {0}; | ||
| 331 | UINT uiTempVar=0; | ||
| 332 | if((Adapter->IdleMode == TRUE) || | ||
| 333 | (Adapter->bShutStatus ==TRUE) || | ||
| 334 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 335 | { | ||
| 336 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n"); | ||
| 337 | return -EACCES; | ||
| 338 | } | ||
| 339 | 319 | ||
| 340 | /* Copy Ioctl Buffer structure */ | 320 | uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; |
| 341 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 321 | Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, (PUINT)temp_buff, IoBuffer.OutputLength); |
| 342 | return -EFAULT; | ||
| 343 | 322 | ||
| 344 | if (IoBuffer.InputLength > sizeof(sWrmBuffer)) | 323 | if (Status == STATUS_SUCCESS) |
| 345 | return -EINVAL; | 324 | if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, IoBuffer.OutputLength)) |
| 325 | Status = -EFAULT; | ||
| 346 | 326 | ||
| 347 | /* Get WrmBuffer structure */ | 327 | kfree(temp_buff); |
| 348 | if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 328 | break; |
| 349 | return -EFAULT; | 329 | } |
| 330 | case IOCTL_BCM_REGISTER_WRITE: | ||
| 331 | case IOCTL_BCM_EEPROM_REGISTER_WRITE: { | ||
| 332 | WRM_BUFFER sWrmBuffer = {0}; | ||
| 333 | UINT uiTempVar = 0; | ||
| 334 | if ((Adapter->IdleMode == TRUE) || | ||
| 335 | (Adapter->bShutStatus == TRUE) || | ||
| 336 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 337 | |||
| 338 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n"); | ||
| 339 | return -EACCES; | ||
| 340 | } | ||
| 350 | 341 | ||
| 351 | if( (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || | 342 | /* Copy Ioctl Buffer structure */ |
| 352 | ((ULONG)sWrmBuffer.Register & 0x3) ) | 343 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 353 | { | 344 | return -EFAULT; |
| 354 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", | 345 | |
| 355 | (int)sWrmBuffer.Register); | 346 | if (IoBuffer.InputLength > sizeof(sWrmBuffer)) |
| 356 | return -EINVAL; | 347 | return -EINVAL; |
| 357 | } | 348 | |
| 349 | /* Get WrmBuffer structure */ | ||
| 350 | if (copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 351 | return -EFAULT; | ||
| 358 | 352 | ||
| 359 | uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; | 353 | if ((((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || |
| 360 | if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && | 354 | ((ULONG)sWrmBuffer.Register & 0x3)) { |
| 361 | ((uiTempVar == EEPROM_REJECT_REG_1)|| | 355 | |
| 356 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)sWrmBuffer.Register); | ||
| 357 | return -EINVAL; | ||
| 358 | } | ||
| 359 | |||
| 360 | uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; | ||
| 361 | if (!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && | ||
| 362 | ((uiTempVar == EEPROM_REJECT_REG_1) || | ||
| 362 | (uiTempVar == EEPROM_REJECT_REG_2) || | 363 | (uiTempVar == EEPROM_REJECT_REG_2) || |
| 363 | (uiTempVar == EEPROM_REJECT_REG_3) || | 364 | (uiTempVar == EEPROM_REJECT_REG_3) || |
| 364 | (uiTempVar == EEPROM_REJECT_REG_4)) && | 365 | (uiTempVar == EEPROM_REJECT_REG_4)) && |
| 365 | (cmd == IOCTL_BCM_REGISTER_WRITE)) | 366 | (cmd == IOCTL_BCM_REGISTER_WRITE)) { |
| 366 | { | 367 | |
| 367 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); | 368 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); |
| 368 | return -EFAULT; | 369 | return -EFAULT; |
| 369 | } | 370 | } |
| 370 | 371 | ||
| 371 | Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register, | 372 | Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register, |
| 372 | (PUINT)sWrmBuffer.Data, sWrmBuffer.Length); | 373 | (PUINT)sWrmBuffer.Data, sWrmBuffer.Length); |
| 373 | if(Status == STATUS_SUCCESS) | 374 | |
| 374 | { | 375 | if (Status == STATUS_SUCCESS) { |
| 375 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); | 376 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); |
| 376 | } | 377 | } else { |
| 377 | else | 378 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); |
| 378 | { | 379 | Status = -EFAULT; |
| 379 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); | 380 | } |
| 380 | Status = -EFAULT; | 381 | break; |
| 381 | } | 382 | } |
| 383 | case IOCTL_BCM_GPIO_SET_REQUEST: { | ||
| 384 | UCHAR ucResetValue[4]; | ||
| 385 | UINT value = 0; | ||
| 386 | UINT uiBit = 0; | ||
| 387 | UINT uiOperation = 0; | ||
| 388 | |||
| 389 | GPIO_INFO gpio_info = {0}; | ||
| 390 | if ((Adapter->IdleMode == TRUE) || | ||
| 391 | (Adapter->bShutStatus == TRUE) || | ||
| 392 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 393 | |||
| 394 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode"); | ||
| 395 | return -EACCES; | ||
| 396 | } | ||
| 397 | |||
| 398 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 399 | return -EFAULT; | ||
| 400 | |||
| 401 | if (IoBuffer.InputLength > sizeof(gpio_info)) | ||
| 402 | return -EINVAL; | ||
| 403 | |||
| 404 | if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 405 | return -EFAULT; | ||
| 406 | |||
| 407 | uiBit = gpio_info.uiGpioNumber; | ||
| 408 | uiOperation = gpio_info.uiGpioValue; | ||
| 409 | value = (1<<uiBit); | ||
| 410 | |||
| 411 | if (IsReqGpioIsLedInNVM(Adapter, value) == FALSE) { | ||
| 412 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!", value); | ||
| 413 | Status = -EINVAL; | ||
| 382 | break; | 414 | break; |
| 383 | } | 415 | } |
| 384 | case IOCTL_BCM_GPIO_SET_REQUEST: | ||
| 385 | { | ||
| 386 | UCHAR ucResetValue[4]; | ||
| 387 | UINT value =0; | ||
| 388 | UINT uiBit = 0; | ||
| 389 | UINT uiOperation = 0; | ||
| 390 | |||
| 391 | GPIO_INFO gpio_info = {0}; | ||
| 392 | if((Adapter->IdleMode == TRUE) || | ||
| 393 | (Adapter->bShutStatus ==TRUE) || | ||
| 394 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 395 | { | ||
| 396 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode"); | ||
| 397 | return -EACCES; | ||
| 398 | } | ||
| 399 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 400 | return -EFAULT; | ||
| 401 | if (IoBuffer.InputLength > sizeof(gpio_info)) | ||
| 402 | return -EINVAL; | ||
| 403 | if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 404 | return -EFAULT; | ||
| 405 | uiBit = gpio_info.uiGpioNumber; | ||
| 406 | uiOperation = gpio_info.uiGpioValue; | ||
| 407 | 416 | ||
| 408 | value= (1<<uiBit); | 417 | /* Set - setting 1 */ |
| 418 | if (uiOperation) { | ||
| 419 | /* Set the gpio output register */ | ||
| 420 | Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, (PUINT)(&value), sizeof(UINT)); | ||
| 409 | 421 | ||
| 410 | if(IsReqGpioIsLedInNVM(Adapter,value) ==FALSE) | 422 | if (Status == STATUS_SUCCESS) { |
| 411 | { | 423 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n"); |
| 412 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to LED !!!",value); | 424 | } else { |
| 413 | Status = -EINVAL; | 425 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to set the %dth GPIO\n", uiBit); |
| 426 | break; | ||
| 427 | } | ||
| 428 | } else { | ||
| 429 | /* Set the gpio output register */ | ||
| 430 | Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)(&value), sizeof(UINT)); | ||
| 431 | |||
| 432 | if (Status == STATUS_SUCCESS) { | ||
| 433 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n"); | ||
| 434 | } else { | ||
| 435 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to clear the %dth GPIO\n", uiBit); | ||
| 414 | break; | 436 | break; |
| 415 | } | 437 | } |
| 438 | } | ||
| 416 | 439 | ||
| 440 | Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); | ||
| 417 | 441 | ||
| 418 | if(uiOperation)//Set - setting 1 | 442 | if (STATUS_SUCCESS != Status) { |
| 419 | { | 443 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, |
| 420 | //Set the gpio output register | 444 | "GPIO_MODE_REGISTER read failed"); |
| 421 | Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG , | 445 | break; |
| 422 | (PUINT)(&value), sizeof(UINT)); | 446 | } |
| 423 | if(Status == STATUS_SUCCESS) | ||
| 424 | { | ||
| 425 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n"); | ||
| 426 | } | ||
| 427 | else | ||
| 428 | { | ||
| 429 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to set the %dth GPIO \n",uiBit); | ||
| 430 | break; | ||
| 431 | } | ||
| 432 | } | ||
| 433 | else//Unset - setting 0 | ||
| 434 | { | ||
| 435 | //Set the gpio output register | ||
| 436 | Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG , | ||
| 437 | (PUINT)(&value), sizeof(UINT)); | ||
| 438 | if(Status == STATUS_SUCCESS) | ||
| 439 | { | ||
| 440 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO bit\n"); | ||
| 441 | } | ||
| 442 | else | ||
| 443 | { | ||
| 444 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to clear the %dth GPIO \n",uiBit); | ||
| 445 | break; | ||
| 446 | } | ||
| 447 | } | ||
| 448 | 447 | ||
| 449 | Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, | 448 | /* Set the gpio mode register to output */ |
| 449 | *(UINT *)ucResetValue |= (1<<uiBit); | ||
| 450 | Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, | ||
| 450 | (PUINT)ucResetValue, sizeof(UINT)); | 451 | (PUINT)ucResetValue, sizeof(UINT)); |
| 451 | if (STATUS_SUCCESS != Status) | 452 | |
| 452 | { | 453 | if (Status == STATUS_SUCCESS) { |
| 453 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO_MODE_REGISTER read failed"); | 454 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO to output Mode\n"); |
| 454 | break; | 455 | } else { |
| 455 | } | 456 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n"); |
| 456 | //Set the gpio mode register to output | 457 | break; |
| 457 | *(UINT*)ucResetValue |= (1<<uiBit); | ||
| 458 | Status = wrmaltWithLock(Adapter,GPIO_MODE_REGISTER , | ||
| 459 | (PUINT)ucResetValue, sizeof(UINT)); | ||
| 460 | if(Status == STATUS_SUCCESS) | ||
| 461 | { | ||
| 462 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO to output Mode\n"); | ||
| 463 | } | ||
| 464 | else | ||
| 465 | { | ||
| 466 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Failed to put GPIO in Output Mode\n"); | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | } | 458 | } |
| 470 | break; | 459 | } |
| 471 | case BCM_LED_THREAD_STATE_CHANGE_REQ: | 460 | break; |
| 472 | { | 461 | |
| 473 | USER_THREAD_REQ threadReq = { 0 }; | 462 | case BCM_LED_THREAD_STATE_CHANGE_REQ: { |
| 474 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"User made LED thread InActive"); | 463 | USER_THREAD_REQ threadReq = {0}; |
| 475 | 464 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "User made LED thread InActive"); | |
| 476 | if((Adapter->IdleMode == TRUE) || | 465 | |
| 477 | (Adapter->bShutStatus ==TRUE) || | 466 | if ((Adapter->IdleMode == TRUE) || |
| 478 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 467 | (Adapter->bShutStatus == TRUE) || |
| 479 | { | 468 | (Adapter->bPreparingForLowPowerMode == TRUE)) { |
| 480 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode"); | 469 | |
| 481 | Status = -EACCES; | 470 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "GPIO Can't be set/clear in Low power Mode"); |
| 482 | break; | 471 | Status = -EACCES; |
| 472 | break; | ||
| 473 | } | ||
| 474 | |||
| 475 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 476 | return -EFAULT; | ||
| 477 | |||
| 478 | if (IoBuffer.InputLength > sizeof(threadReq)) | ||
| 479 | return -EINVAL; | ||
| 480 | |||
| 481 | if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 482 | return -EFAULT; | ||
| 483 | |||
| 484 | /* if LED thread is running(Actively or Inactively) set it state to make inactive */ | ||
| 485 | if (Adapter->LEDInfo.led_thread_running) { | ||
| 486 | if (threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) { | ||
| 487 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Activating thread req"); | ||
| 488 | Adapter->DriverState = LED_THREAD_ACTIVE; | ||
| 489 | } else { | ||
| 490 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DeActivating Thread req....."); | ||
| 491 | Adapter->DriverState = LED_THREAD_INACTIVE; | ||
| 483 | } | 492 | } |
| 484 | 493 | ||
| 485 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 494 | /* signal thread. */ |
| 486 | return -EFAULT; | 495 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 496 | } | ||
| 497 | } | ||
| 498 | break; | ||
| 487 | 499 | ||
| 488 | if (IoBuffer.InputLength > sizeof(threadReq)) | 500 | case IOCTL_BCM_GPIO_STATUS_REQUEST: { |
| 489 | return -EINVAL; | 501 | ULONG uiBit = 0; |
| 502 | UCHAR ucRead[4]; | ||
| 503 | GPIO_INFO gpio_info = {0}; | ||
| 490 | 504 | ||
| 491 | if (copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 505 | if ((Adapter->IdleMode == TRUE) || |
| 492 | return -EFAULT; | 506 | (Adapter->bShutStatus == TRUE) || |
| 507 | (Adapter->bPreparingForLowPowerMode == TRUE)) | ||
| 508 | return -EACCES; | ||
| 493 | 509 | ||
| 494 | //if LED thread is running(Actively or Inactively) set it state to make inactive | 510 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 495 | if(Adapter->LEDInfo.led_thread_running) | 511 | return -EFAULT; |
| 496 | { | ||
| 497 | if(threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) | ||
| 498 | { | ||
| 499 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Activating thread req"); | ||
| 500 | Adapter->DriverState = LED_THREAD_ACTIVE; | ||
| 501 | } | ||
| 502 | else | ||
| 503 | { | ||
| 504 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DeActivating Thread req....."); | ||
| 505 | Adapter->DriverState = LED_THREAD_INACTIVE; | ||
| 506 | } | ||
| 507 | 512 | ||
| 508 | //signal thread. | 513 | if (IoBuffer.InputLength > sizeof(gpio_info)) |
| 509 | wake_up(&Adapter->LEDInfo.notify_led_event); | 514 | return -EINVAL; |
| 515 | |||
| 516 | if (copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 517 | return -EFAULT; | ||
| 518 | |||
| 519 | uiBit = gpio_info.uiGpioNumber; | ||
| 520 | |||
| 521 | /* Set the gpio output register */ | ||
| 522 | Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, | ||
| 523 | (PUINT)ucRead, sizeof(UINT)); | ||
| 510 | 524 | ||
| 525 | if (Status != STATUS_SUCCESS) { | ||
| 526 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n"); | ||
| 527 | return Status; | ||
| 528 | } | ||
| 529 | } | ||
| 530 | break; | ||
| 531 | |||
| 532 | case IOCTL_BCM_GPIO_MULTI_REQUEST: { | ||
| 533 | UCHAR ucResetValue[4]; | ||
| 534 | GPIO_MULTI_INFO gpio_multi_info[MAX_IDX]; | ||
| 535 | PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info; | ||
| 536 | |||
| 537 | memset(pgpio_multi_info, 0, MAX_IDX * sizeof(GPIO_MULTI_INFO)); | ||
| 538 | |||
| 539 | if ((Adapter->IdleMode == TRUE) || | ||
| 540 | (Adapter->bShutStatus == TRUE) || | ||
| 541 | (Adapter->bPreparingForLowPowerMode == TRUE)) | ||
| 542 | return -EINVAL; | ||
| 543 | |||
| 544 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 545 | return -EFAULT; | ||
| 546 | |||
| 547 | if (IoBuffer.InputLength > sizeof(gpio_multi_info)) | ||
| 548 | return -EINVAL; | ||
| 549 | |||
| 550 | if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 551 | return -EFAULT; | ||
| 552 | |||
| 553 | if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_info[WIMAX_IDX].uiGPIOMask) == FALSE) { | ||
| 554 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, | ||
| 555 | "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!", | ||
| 556 | pgpio_multi_info[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap); | ||
| 557 | Status = -EINVAL; | ||
| 558 | break; | ||
| 559 | } | ||
| 560 | |||
| 561 | /* Set the gpio output register */ | ||
| 562 | if ((pgpio_multi_info[WIMAX_IDX].uiGPIOMask) & | ||
| 563 | (pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) { | ||
| 564 | /* Set 1's in GPIO OUTPUT REGISTER */ | ||
| 565 | *(UINT *)ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask & | ||
| 566 | pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & | ||
| 567 | pgpio_multi_info[WIMAX_IDX].uiGPIOValue; | ||
| 568 | |||
| 569 | if (*(UINT *) ucResetValue) | ||
| 570 | Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_SET_REG, | ||
| 571 | (PUINT)ucResetValue, sizeof(ULONG)); | ||
| 572 | |||
| 573 | if (Status != STATUS_SUCCESS) { | ||
| 574 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_SET_REG Failed."); | ||
| 575 | return Status; | ||
| 576 | } | ||
| 577 | |||
| 578 | /* Clear to 0's in GPIO OUTPUT REGISTER */ | ||
| 579 | *(UINT *)ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask & | ||
| 580 | pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & | ||
| 581 | (~(pgpio_multi_info[WIMAX_IDX].uiGPIOValue))); | ||
| 582 | |||
| 583 | if (*(UINT *) ucResetValue) | ||
| 584 | Status = wrmaltWithLock(Adapter, BCM_GPIO_OUTPUT_CLR_REG, (PUINT)ucResetValue, sizeof(ULONG)); | ||
| 585 | |||
| 586 | if (Status != STATUS_SUCCESS) { | ||
| 587 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM to BCM_GPIO_OUTPUT_CLR_REG Failed."); | ||
| 588 | return Status; | ||
| 511 | } | 589 | } |
| 512 | } | 590 | } |
| 513 | break; | ||
| 514 | case IOCTL_BCM_GPIO_STATUS_REQUEST: | ||
| 515 | { | ||
| 516 | ULONG uiBit = 0; | ||
| 517 | UCHAR ucRead[4]; | ||
| 518 | GPIO_INFO gpio_info = {0}; | ||
| 519 | if((Adapter->IdleMode == TRUE) || | ||
| 520 | (Adapter->bShutStatus ==TRUE) || | ||
| 521 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 522 | return -EACCES; | ||
| 523 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 524 | return -EFAULT; | ||
| 525 | if (IoBuffer.InputLength > sizeof(gpio_info)) | ||
| 526 | return -EINVAL; | ||
| 527 | if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 528 | return -EFAULT; | ||
| 529 | uiBit = gpio_info.uiGpioNumber; | ||
| 530 | //Set the gpio output register | ||
| 531 | Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, | ||
| 532 | (PUINT)ucRead, sizeof(UINT)); | ||
| 533 | if(Status != STATUS_SUCCESS) | ||
| 534 | { | ||
| 535 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n"); | ||
| 536 | return Status; | ||
| 537 | } | ||
| 538 | 591 | ||
| 592 | if (pgpio_multi_info[WIMAX_IDX].uiGPIOMask) { | ||
| 593 | Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); | ||
| 594 | |||
| 595 | if (Status != STATUS_SUCCESS) { | ||
| 596 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "RDM to GPIO_PIN_STATE_REGISTER Failed."); | ||
| 597 | return Status; | ||
| 539 | } | 598 | } |
| 599 | |||
| 600 | pgpio_multi_info[WIMAX_IDX].uiGPIOValue = (*(UINT *)ucResetValue & | ||
| 601 | pgpio_multi_info[WIMAX_IDX].uiGPIOMask); | ||
| 602 | } | ||
| 603 | |||
| 604 | Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength); | ||
| 605 | if (Status) { | ||
| 606 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, | ||
| 607 | "Failed while copying Content to IOBufer for user space err:%d", Status); | ||
| 540 | break; | 608 | break; |
| 541 | case IOCTL_BCM_GPIO_MULTI_REQUEST: | 609 | } |
| 542 | { | 610 | } |
| 543 | UCHAR ucResetValue[4]; | 611 | break; |
| 544 | GPIO_MULTI_INFO gpio_multi_info[MAX_IDX]; | ||
| 545 | PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info; | ||
| 546 | |||
| 547 | memset( pgpio_multi_info, 0, MAX_IDX * sizeof( GPIO_MULTI_INFO)); | ||
| 548 | |||
| 549 | if((Adapter->IdleMode == TRUE) || | ||
| 550 | (Adapter->bShutStatus ==TRUE) || | ||
| 551 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 552 | return -EINVAL; | ||
| 553 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 554 | return -EFAULT; | ||
| 555 | if (IoBuffer.InputLength > sizeof(gpio_multi_info)) | ||
| 556 | return -EINVAL; | ||
| 557 | if (copy_from_user(&gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 558 | return -EFAULT; | ||
| 559 | 612 | ||
| 560 | if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_info[WIMAX_IDX].uiGPIOMask)== FALSE) | 613 | case IOCTL_BCM_GPIO_MODE_REQUEST: { |
| 561 | { | 614 | UCHAR ucResetValue[4]; |
| 562 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_info[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap); | 615 | GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX]; |
| 563 | Status = -EINVAL; | 616 | PGPIO_MULTI_MODE pgpio_multi_mode = (PGPIO_MULTI_MODE)gpio_multi_mode; |
| 564 | break; | ||
| 565 | } | ||
| 566 | 617 | ||
| 567 | /* Set the gpio output register */ | 618 | if ((Adapter->IdleMode == TRUE) || |
| 619 | (Adapter->bShutStatus == TRUE) || | ||
| 620 | (Adapter->bPreparingForLowPowerMode == TRUE)) | ||
| 621 | return -EINVAL; | ||
| 568 | 622 | ||
| 569 | if( ( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) & | 623 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 570 | ( pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) | 624 | return -EFAULT; |
| 571 | { | ||
| 572 | /* Set 1's in GPIO OUTPUT REGISTER */ | ||
| 573 | *(UINT*) ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask & | ||
| 574 | pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & | ||
| 575 | pgpio_multi_info[WIMAX_IDX].uiGPIOValue; | ||
| 576 | 625 | ||
| 577 | if( *(UINT*) ucResetValue) | 626 | if (IoBuffer.InputLength > sizeof(gpio_multi_mode)) |
| 578 | Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_SET_REG , (PUINT) ucResetValue, sizeof(ULONG)); | 627 | return -EINVAL; |
| 579 | 628 | ||
| 580 | if( Status != STATUS_SUCCESS) | 629 | if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength)) |
| 581 | { | 630 | return -EFAULT; |
| 582 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_SET_REG Failed."); | ||
| 583 | return Status; | ||
| 584 | } | ||
| 585 | 631 | ||
| 586 | /* Clear to 0's in GPIO OUTPUT REGISTER */ | 632 | Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); |
| 587 | *(UINT*) ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask & | ||
| 588 | pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & | ||
| 589 | ( ~( pgpio_multi_info[WIMAX_IDX].uiGPIOValue))); | ||
| 590 | 633 | ||
| 591 | if( *(UINT*) ucResetValue) | 634 | if (STATUS_SUCCESS != Status) { |
| 592 | Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_CLR_REG , (PUINT) ucResetValue, sizeof(ULONG)); | 635 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Read of GPIO_MODE_REGISTER failed"); |
| 636 | return Status; | ||
| 637 | } | ||
| 593 | 638 | ||
| 594 | if( Status != STATUS_SUCCESS) | 639 | /* Validating the request */ |
| 595 | { | 640 | if (IsReqGpioIsLedInNVM(Adapter, pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) == FALSE) { |
| 596 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed." ); | 641 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, |
| 597 | return Status; | 642 | "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!", |
| 598 | } | 643 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMask, Adapter->gpioBitMap); |
| 599 | } | 644 | Status = -EINVAL; |
| 645 | break; | ||
| 646 | } | ||
| 600 | 647 | ||
| 601 | if( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) | 648 | if (pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) { |
| 602 | { | 649 | /* write all OUT's (1's) */ |
| 603 | Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); | 650 | *(UINT *) ucResetValue |= (pgpio_multi_mode[WIMAX_IDX].uiGPIOMode & |
| 651 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); | ||
| 652 | |||
| 653 | /* write all IN's (0's) */ | ||
| 654 | *(UINT *) ucResetValue &= ~((~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) & | ||
| 655 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); | ||
| 656 | |||
| 657 | /* Currently implemented return the modes of all GPIO's | ||
| 658 | * else needs to bit AND with mask | ||
| 659 | */ | ||
| 660 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue; | ||
| 661 | |||
| 662 | Status = wrmaltWithLock(Adapter, GPIO_MODE_REGISTER, (PUINT)ucResetValue, sizeof(ULONG)); | ||
| 663 | if (Status == STATUS_SUCCESS) { | ||
| 664 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, | ||
| 665 | "WRM to GPIO_MODE_REGISTER Done"); | ||
| 666 | } else { | ||
| 667 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, | ||
| 668 | "WRM to GPIO_MODE_REGISTER Failed"); | ||
| 669 | Status = -EFAULT; | ||
| 670 | break; | ||
| 671 | } | ||
| 672 | } else { | ||
| 673 | /* if uiGPIOMask is 0 then return mode register configuration */ | ||
| 674 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT *)ucResetValue; | ||
| 675 | } | ||
| 604 | 676 | ||
| 605 | if(Status != STATUS_SUCCESS) | 677 | Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength); |
| 606 | { | 678 | if (Status) { |
| 607 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM to GPIO_PIN_STATE_REGISTER Failed."); | 679 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, |
| 608 | return Status; | 680 | "Failed while copying Content to IOBufer for user space err:%d", Status); |
| 609 | } | 681 | break; |
| 682 | } | ||
| 683 | } | ||
| 684 | break; | ||
| 685 | |||
| 686 | case IOCTL_MAC_ADDR_REQ: | ||
| 687 | case IOCTL_LINK_REQ: | ||
| 688 | case IOCTL_CM_REQUEST: | ||
| 689 | case IOCTL_SS_INFO_REQ: | ||
| 690 | case IOCTL_SEND_CONTROL_MESSAGE: | ||
| 691 | case IOCTL_IDLE_REQ: { | ||
| 692 | PVOID pvBuffer = NULL; | ||
| 693 | |||
| 694 | /* Copy Ioctl Buffer structure */ | ||
| 695 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 696 | return -EFAULT; | ||
| 610 | 697 | ||
| 611 | pgpio_multi_info[WIMAX_IDX].uiGPIOValue = ( *(UINT*)ucResetValue & | 698 | if (IoBuffer.InputLength < sizeof(struct link_request)) |
| 612 | pgpio_multi_info[WIMAX_IDX].uiGPIOMask); | 699 | return -EINVAL; |
| 613 | } | ||
| 614 | 700 | ||
| 615 | Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength); | 701 | if (IoBuffer.InputLength > MAX_CNTL_PKT_SIZE) |
| 616 | if(Status) | 702 | return -EINVAL; |
| 617 | { | 703 | |
| 618 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); | 704 | pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); |
| 619 | break; | 705 | if (!pvBuffer) |
| 620 | } | 706 | return -ENOMEM; |
| 621 | } | 707 | |
| 708 | if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { | ||
| 709 | Status = -EFAULT; | ||
| 710 | kfree(pvBuffer); | ||
| 622 | break; | 711 | break; |
| 623 | case IOCTL_BCM_GPIO_MODE_REQUEST: | 712 | } |
| 624 | { | 713 | |
| 625 | UCHAR ucResetValue[4]; | 714 | down(&Adapter->LowPowerModeSync); |
| 626 | GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX]; | 715 | Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, |
| 627 | PGPIO_MULTI_MODE pgpio_multi_mode = ( PGPIO_MULTI_MODE) gpio_multi_mode; | 716 | !Adapter->bPreparingForLowPowerMode, |
| 717 | (1 * HZ)); | ||
| 718 | if (Status == -ERESTARTSYS) | ||
| 719 | goto cntrlEnd; | ||
| 720 | |||
| 721 | if (Adapter->bPreparingForLowPowerMode) { | ||
| 722 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, | ||
| 723 | "Preparing Idle Mode is still True - Hence Rejecting control message\n"); | ||
| 724 | Status = STATUS_FAILURE; | ||
| 725 | goto cntrlEnd; | ||
| 726 | } | ||
| 727 | Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer); | ||
| 728 | |||
| 729 | cntrlEnd: | ||
| 730 | up(&Adapter->LowPowerModeSync); | ||
| 731 | kfree(pvBuffer); | ||
| 732 | break; | ||
| 733 | } | ||
| 628 | 734 | ||
| 629 | if((Adapter->IdleMode == TRUE) || | 735 | case IOCTL_BCM_BUFFER_DOWNLOAD_START: { |
| 630 | (Adapter->bShutStatus ==TRUE) || | 736 | INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); |
| 631 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 737 | if (NVMAccess) { |
| 632 | return -EINVAL; | 738 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, |
| 739 | "IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); | ||
| 740 | return -EACCES; | ||
| 741 | } | ||
| 633 | 742 | ||
| 743 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, | ||
| 744 | "Starting the firmware download PID =0x%x!!!!\n", current->pid); | ||
| 745 | |||
| 746 | if (!down_trylock(&Adapter->fw_download_sema)) { | ||
| 747 | Adapter->bBinDownloaded = FALSE; | ||
| 748 | Adapter->fw_download_process_pid = current->pid; | ||
| 749 | Adapter->bCfgDownloaded = FALSE; | ||
| 750 | Adapter->fw_download_done = FALSE; | ||
| 751 | netif_carrier_off(Adapter->dev); | ||
| 752 | netif_stop_queue(Adapter->dev); | ||
| 753 | Status = reset_card_proc(Adapter); | ||
| 754 | if (Status) { | ||
| 755 | pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name); | ||
| 756 | up(&Adapter->fw_download_sema); | ||
| 757 | up(&Adapter->NVMRdmWrmLock); | ||
| 758 | break; | ||
| 759 | } | ||
| 760 | mdelay(10); | ||
| 761 | } else { | ||
| 762 | Status = -EBUSY; | ||
| 763 | } | ||
| 764 | |||
| 765 | up(&Adapter->NVMRdmWrmLock); | ||
| 766 | break; | ||
| 767 | } | ||
| 768 | |||
| 769 | case IOCTL_BCM_BUFFER_DOWNLOAD: { | ||
| 770 | FIRMWARE_INFO *psFwInfo = NULL; | ||
| 771 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); | ||
| 772 | do { | ||
| 773 | if (!down_trylock(&Adapter->fw_download_sema)) { | ||
| 774 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, | ||
| 775 | "Invalid way to download buffer. Use Start and then call this!!!\n"); | ||
| 776 | Status = -EINVAL; | ||
| 777 | break; | ||
| 778 | } | ||
| 779 | |||
| 780 | /* Copy Ioctl Buffer structure */ | ||
| 634 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 781 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 635 | return -EFAULT; | 782 | return -EFAULT; |
| 636 | if (IoBuffer.InputLength > sizeof(gpio_multi_mode)) | 783 | |
| 784 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, | ||
| 785 | "Length for FW DLD is : %lx\n", IoBuffer.InputLength); | ||
| 786 | |||
| 787 | if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) | ||
| 637 | return -EINVAL; | 788 | return -EINVAL; |
| 638 | if (copy_from_user(&gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 789 | |
| 790 | psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); | ||
| 791 | if (!psFwInfo) | ||
| 792 | return -ENOMEM; | ||
| 793 | |||
| 794 | if (copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 639 | return -EFAULT; | 795 | return -EFAULT; |
| 640 | 796 | ||
| 641 | Status = rdmaltWithLock( Adapter, ( UINT) GPIO_MODE_REGISTER, ( PUINT) ucResetValue, sizeof( UINT)); | 797 | if (!psFwInfo->pvMappedFirmwareAddress || |
| 642 | if( STATUS_SUCCESS != Status) | 798 | (psFwInfo->u32FirmwareLength == 0)) { |
| 643 | { | ||
| 644 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Read of GPIO_MODE_REGISTER failed"); | ||
| 645 | return Status; | ||
| 646 | } | ||
| 647 | 799 | ||
| 648 | //Validating the request | 800 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", |
| 649 | if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)== FALSE) | 801 | psFwInfo->u32FirmwareLength); |
| 650 | { | ||
| 651 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap); | ||
| 652 | Status = -EINVAL; | 802 | Status = -EINVAL; |
| 653 | break; | 803 | break; |
| 654 | } | 804 | } |
| 655 | 805 | ||
| 656 | if( pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) | 806 | Status = bcm_ioctl_fw_download(Adapter, psFwInfo); |
| 657 | { | 807 | |
| 658 | /* write all OUT's (1's) */ | 808 | if (Status != STATUS_SUCCESS) { |
| 659 | *( UINT*) ucResetValue |= ( pgpio_multi_mode[WIMAX_IDX].uiGPIOMode & | 809 | if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) |
| 660 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); | 810 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n"); |
| 661 | /* write all IN's (0's) */ | ||
| 662 | *( UINT*) ucResetValue &= ~( ( ~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) & | ||
| 663 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); | ||
| 664 | |||
| 665 | /* Currently implemented return the modes of all GPIO's | ||
| 666 | * else needs to bit AND with mask | ||
| 667 | * */ | ||
| 668 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT*)ucResetValue; | ||
| 669 | |||
| 670 | Status = wrmaltWithLock( Adapter, GPIO_MODE_REGISTER , ( PUINT) ucResetValue, sizeof( ULONG)); | ||
| 671 | if( Status == STATUS_SUCCESS) | ||
| 672 | { | ||
| 673 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM to GPIO_MODE_REGISTER Done"); | ||
| 674 | } | ||
| 675 | else | 811 | else |
| 676 | { | 812 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n"); |
| 677 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to GPIO_MODE_REGISTER Failed"); | 813 | |
| 678 | Status = -EFAULT; | 814 | /* up(&Adapter->fw_download_sema); */ |
| 679 | break; | 815 | |
| 816 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { | ||
| 817 | Adapter->DriverState = DRIVER_INIT; | ||
| 818 | Adapter->LEDInfo.bLedInitDone = FALSE; | ||
| 819 | wake_up(&Adapter->LEDInfo.notify_led_event); | ||
| 680 | } | 820 | } |
| 681 | } | 821 | } |
| 682 | else /* if uiGPIOMask is 0 then return mode register configuration */ | 822 | break; |
| 683 | { | 823 | |
| 684 | pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *( UINT*) ucResetValue; | 824 | } while (0); |
| 685 | } | 825 | |
| 686 | Status = copy_to_user(IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength); | 826 | if (Status != STATUS_SUCCESS) |
| 687 | if(Status) | 827 | up(&Adapter->fw_download_sema); |
| 688 | { | 828 | |
| 689 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); | 829 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n"); |
| 830 | kfree(psFwInfo); | ||
| 831 | break; | ||
| 832 | } | ||
| 833 | |||
| 834 | case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: { | ||
| 835 | INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); | ||
| 836 | |||
| 837 | if (NVMAccess) { | ||
| 838 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, | ||
| 839 | "FW download blocked as EEPROM Read/Write is in progress\n"); | ||
| 840 | up(&Adapter->fw_download_sema); | ||
| 841 | return -EACCES; | ||
| 842 | } | ||
| 843 | |||
| 844 | if (down_trylock(&Adapter->fw_download_sema)) { | ||
| 845 | Adapter->bBinDownloaded = TRUE; | ||
| 846 | Adapter->bCfgDownloaded = TRUE; | ||
| 847 | atomic_set(&Adapter->CurrNumFreeTxDesc, 0); | ||
| 848 | Adapter->CurrNumRecvDescs = 0; | ||
| 849 | Adapter->downloadDDR = 0; | ||
| 850 | |||
| 851 | /* setting the Mips to Run */ | ||
| 852 | Status = run_card_proc(Adapter); | ||
| 853 | |||
| 854 | if (Status) { | ||
| 855 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n"); | ||
| 856 | up(&Adapter->fw_download_sema); | ||
| 857 | up(&Adapter->NVMRdmWrmLock); | ||
| 690 | break; | 858 | break; |
| 859 | } else { | ||
| 860 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, | ||
| 861 | DBG_LVL_ALL, "Firm Download Over...\n"); | ||
| 691 | } | 862 | } |
| 863 | |||
| 864 | mdelay(10); | ||
| 865 | |||
| 866 | /* Wait for MailBox Interrupt */ | ||
| 867 | if (StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter)) | ||
| 868 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n"); | ||
| 869 | |||
| 870 | timeout = 5*HZ; | ||
| 871 | Adapter->waiting_to_fw_download_done = FALSE; | ||
| 872 | wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue, | ||
| 873 | Adapter->waiting_to_fw_download_done, timeout); | ||
| 874 | Adapter->fw_download_process_pid = INVALID_PID; | ||
| 875 | Adapter->fw_download_done = TRUE; | ||
| 876 | atomic_set(&Adapter->CurrNumFreeTxDesc, 0); | ||
| 877 | Adapter->CurrNumRecvDescs = 0; | ||
| 878 | Adapter->PrevNumRecvDescs = 0; | ||
| 879 | atomic_set(&Adapter->cntrlpktCnt, 0); | ||
| 880 | Adapter->LinkUpStatus = 0; | ||
| 881 | Adapter->LinkStatus = 0; | ||
| 882 | |||
| 883 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { | ||
| 884 | Adapter->DriverState = FW_DOWNLOAD_DONE; | ||
| 885 | wake_up(&Adapter->LEDInfo.notify_led_event); | ||
| 886 | } | ||
| 887 | |||
| 888 | if (!timeout) | ||
| 889 | Status = -ENODEV; | ||
| 890 | } else { | ||
| 891 | Status = -EINVAL; | ||
| 692 | } | 892 | } |
| 893 | |||
| 894 | up(&Adapter->fw_download_sema); | ||
| 895 | up(&Adapter->NVMRdmWrmLock); | ||
| 693 | break; | 896 | break; |
| 897 | } | ||
| 694 | 898 | ||
| 695 | case IOCTL_MAC_ADDR_REQ: | 899 | case IOCTL_BE_BUCKET_SIZE: |
| 696 | case IOCTL_LINK_REQ: | 900 | Status = 0; |
| 697 | case IOCTL_CM_REQUEST: | 901 | if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg)) |
| 698 | case IOCTL_SS_INFO_REQ: | 902 | Status = -EFAULT; |
| 699 | case IOCTL_SEND_CONTROL_MESSAGE: | 903 | break; |
| 700 | case IOCTL_IDLE_REQ: | ||
| 701 | { | ||
| 702 | PVOID pvBuffer=NULL; | ||
| 703 | 904 | ||
| 704 | /* Copy Ioctl Buffer structure */ | 905 | case IOCTL_RTPS_BUCKET_SIZE: |
| 705 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 906 | Status = 0; |
| 706 | return -EFAULT; | 907 | if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg)) |
| 908 | Status = -EFAULT; | ||
| 909 | break; | ||
| 707 | 910 | ||
| 708 | /* FIXME: don't accept any length from user */ | 911 | case IOCTL_CHIP_RESET: { |
| 709 | pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); | 912 | INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); |
| 710 | if(!pvBuffer) | 913 | if (NVMAccess) { |
| 711 | return -ENOMEM; | 914 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); |
| 915 | return -EACCES; | ||
| 916 | } | ||
| 917 | |||
| 918 | down(&Adapter->RxAppControlQueuelock); | ||
| 919 | Status = reset_card_proc(Adapter); | ||
| 920 | flushAllAppQ(); | ||
| 921 | up(&Adapter->RxAppControlQueuelock); | ||
| 922 | up(&Adapter->NVMRdmWrmLock); | ||
| 923 | ResetCounters(Adapter); | ||
| 924 | break; | ||
| 925 | } | ||
| 712 | 926 | ||
| 713 | if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 927 | case IOCTL_QOS_THRESHOLD: { |
| 714 | { | 928 | USHORT uiLoopIndex; |
| 929 | |||
| 930 | Status = 0; | ||
| 931 | for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) { | ||
| 932 | if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold, | ||
| 933 | (unsigned long __user *)arg)) { | ||
| 715 | Status = -EFAULT; | 934 | Status = -EFAULT; |
| 716 | kfree(pvBuffer); | ||
| 717 | break; | 935 | break; |
| 718 | } | 936 | } |
| 937 | } | ||
| 938 | break; | ||
| 939 | } | ||
| 719 | 940 | ||
| 720 | down(&Adapter->LowPowerModeSync); | 941 | case IOCTL_DUMP_PACKET_INFO: |
| 721 | Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, | 942 | DumpPackInfo(Adapter); |
| 722 | !Adapter->bPreparingForLowPowerMode, | 943 | DumpPhsRules(&Adapter->stBCMPhsContext); |
| 723 | (1 * HZ)); | 944 | Status = STATUS_SUCCESS; |
| 724 | if(Status == -ERESTARTSYS) | 945 | break; |
| 725 | goto cntrlEnd; | 946 | |
| 726 | 947 | case IOCTL_GET_PACK_INFO: | |
| 727 | if(Adapter->bPreparingForLowPowerMode) | 948 | if (copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES)) |
| 728 | { | 949 | return -EFAULT; |
| 729 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Preparing Idle Mode is still True - Hence Rejecting control message\n"); | 950 | Status = STATUS_SUCCESS; |
| 730 | Status = STATUS_FAILURE ; | 951 | break; |
| 731 | goto cntrlEnd ; | 952 | |
| 732 | } | 953 | case IOCTL_BCM_SWITCH_TRANSFER_MODE: { |
| 733 | Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer); | 954 | UINT uiData = 0; |
| 734 | cntrlEnd: | 955 | if (copy_from_user(&uiData, argp, sizeof(UINT))) |
| 735 | up(&Adapter->LowPowerModeSync); | 956 | return -EFAULT; |
| 736 | kfree(pvBuffer); | 957 | |
| 958 | if (uiData) { | ||
| 959 | /* Allow All Packets */ | ||
| 960 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n"); | ||
| 961 | Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE; | ||
| 962 | } else { | ||
| 963 | /* Allow IP only Packets */ | ||
| 964 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n"); | ||
| 965 | Adapter->TransferMode = IP_PACKET_ONLY_MODE; | ||
| 966 | } | ||
| 967 | Status = STATUS_SUCCESS; | ||
| 968 | break; | ||
| 969 | } | ||
| 970 | |||
| 971 | case IOCTL_BCM_GET_DRIVER_VERSION: { | ||
| 972 | /* Copy Ioctl Buffer structure */ | ||
| 973 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 974 | return -EFAULT; | ||
| 975 | |||
| 976 | if (copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength)) | ||
| 977 | return -EFAULT; | ||
| 978 | Status = STATUS_SUCCESS; | ||
| 979 | break; | ||
| 980 | } | ||
| 981 | |||
| 982 | case IOCTL_BCM_GET_CURRENT_STATUS: { | ||
| 983 | LINK_STATE link_state; | ||
| 984 | |||
| 985 | /* Copy Ioctl Buffer structure */ | ||
| 986 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { | ||
| 987 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n"); | ||
| 988 | Status = -EFAULT; | ||
| 737 | break; | 989 | break; |
| 738 | } | 990 | } |
| 739 | case IOCTL_BCM_BUFFER_DOWNLOAD_START: | ||
| 740 | { | ||
| 741 | INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock) ; | ||
| 742 | if(NVMAccess) | ||
| 743 | { | ||
| 744 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); | ||
| 745 | return -EACCES; | ||
| 746 | } | ||
| 747 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); | ||
| 748 | if(!down_trylock(&Adapter->fw_download_sema)) | ||
| 749 | { | ||
| 750 | Adapter->bBinDownloaded=FALSE; | ||
| 751 | Adapter->fw_download_process_pid=current->pid; | ||
| 752 | Adapter->bCfgDownloaded=FALSE; | ||
| 753 | Adapter->fw_download_done=FALSE; | ||
| 754 | netif_carrier_off(Adapter->dev); | ||
| 755 | netif_stop_queue(Adapter->dev); | ||
| 756 | Status = reset_card_proc(Adapter); | ||
| 757 | if(Status) | ||
| 758 | { | ||
| 759 | pr_err(PFX "%s: reset_card_proc Failed!\n", Adapter->dev->name); | ||
| 760 | up(&Adapter->fw_download_sema); | ||
| 761 | up(&Adapter->NVMRdmWrmLock); | ||
| 762 | break; | ||
| 763 | } | ||
| 764 | mdelay(10); | ||
| 765 | } | ||
| 766 | else | ||
| 767 | { | ||
| 768 | 991 | ||
| 769 | Status = -EBUSY; | 992 | if (IoBuffer.OutputLength != sizeof(link_state)) { |
| 993 | Status = -EINVAL; | ||
| 994 | break; | ||
| 995 | } | ||
| 770 | 996 | ||
| 771 | } | 997 | memset(&link_state, 0, sizeof(link_state)); |
| 772 | up(&Adapter->NVMRdmWrmLock); | 998 | link_state.bIdleMode = Adapter->IdleMode; |
| 999 | link_state.bShutdownMode = Adapter->bShutStatus; | ||
| 1000 | link_state.ucLinkStatus = Adapter->LinkStatus; | ||
| 1001 | |||
| 1002 | if (copy_to_user(IoBuffer.OutputBuffer, &link_state, min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) { | ||
| 1003 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n"); | ||
| 1004 | Status = -EFAULT; | ||
| 773 | break; | 1005 | break; |
| 774 | } | 1006 | } |
| 775 | case IOCTL_BCM_BUFFER_DOWNLOAD: | 1007 | Status = STATUS_SUCCESS; |
| 776 | { | 1008 | break; |
| 777 | FIRMWARE_INFO *psFwInfo = NULL; | 1009 | } |
| 778 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); | ||
| 779 | do{ | ||
| 780 | if(!down_trylock(&Adapter->fw_download_sema)) | ||
| 781 | { | ||
| 782 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid way to download buffer. Use Start and then call this!!!\n"); | ||
| 783 | Status=-EINVAL; | ||
| 784 | break; | ||
| 785 | } | ||
| 786 | 1010 | ||
| 787 | /* Copy Ioctl Buffer structure */ | 1011 | case IOCTL_BCM_SET_MAC_TRACING: { |
| 788 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1012 | UINT tracing_flag; |
| 789 | return -EFAULT; | ||
| 790 | 1013 | ||
| 791 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n", | 1014 | /* copy ioctl Buffer structure */ |
| 792 | IoBuffer.InputLength); | 1015 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 1016 | return -EFAULT; | ||
| 793 | 1017 | ||
| 794 | if (IoBuffer.InputLength > sizeof(FIRMWARE_INFO)) | 1018 | if (copy_from_user(&tracing_flag, IoBuffer.InputBuffer, sizeof(UINT))) |
| 795 | return -EINVAL; | 1019 | return -EFAULT; |
| 796 | 1020 | ||
| 797 | psFwInfo = kmalloc(sizeof(*psFwInfo), GFP_KERNEL); | 1021 | if (tracing_flag) |
| 798 | if(!psFwInfo) | 1022 | Adapter->pTarangs->MacTracingEnabled = TRUE; |
| 799 | return -ENOMEM; | 1023 | else |
| 1024 | Adapter->pTarangs->MacTracingEnabled = FALSE; | ||
| 1025 | break; | ||
| 1026 | } | ||
| 800 | 1027 | ||
| 801 | if(copy_from_user(psFwInfo, IoBuffer.InputBuffer, IoBuffer.InputLength)) | 1028 | case IOCTL_BCM_GET_DSX_INDICATION: { |
| 802 | return -EFAULT; | 1029 | ULONG ulSFId = 0; |
| 1030 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 1031 | return -EFAULT; | ||
| 803 | 1032 | ||
| 804 | if(!psFwInfo->pvMappedFirmwareAddress || | 1033 | if (IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) { |
| 805 | (psFwInfo->u32FirmwareLength == 0)) | 1034 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, |
| 806 | { | 1035 | "Mismatch req: %lx needed is =0x%zx!!!", |
| 807 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", | 1036 | IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); |
| 808 | psFwInfo->u32FirmwareLength); | 1037 | return -EINVAL; |
| 809 | Status = -EINVAL; | 1038 | } |
| 810 | break; | ||
| 811 | } | ||
| 812 | Status = bcm_ioctl_fw_download(Adapter, psFwInfo); | ||
| 813 | if(Status != STATUS_SUCCESS) | ||
| 814 | { | ||
| 815 | if(psFwInfo->u32StartingAddress==CONFIG_BEGIN_ADDR) | ||
| 816 | { | ||
| 817 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n"); | ||
| 818 | } | ||
| 819 | else | ||
| 820 | { | ||
| 821 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n"); | ||
| 822 | } | ||
| 823 | //up(&Adapter->fw_download_sema); | ||
| 824 | 1039 | ||
| 825 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 1040 | if (copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId))) |
| 826 | { | 1041 | return -EFAULT; |
| 827 | Adapter->DriverState = DRIVER_INIT; | ||
| 828 | Adapter->LEDInfo.bLedInitDone = FALSE; | ||
| 829 | wake_up(&Adapter->LEDInfo.notify_led_event); | ||
| 830 | } | ||
| 831 | } | ||
| 832 | break ; | ||
| 833 | }while(0); | ||
| 834 | 1042 | ||
| 835 | if(Status != STATUS_SUCCESS) | 1043 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId); |
| 836 | up(&Adapter->fw_download_sema); | 1044 | get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer); |
| 837 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n"); | 1045 | Status = STATUS_SUCCESS; |
| 838 | kfree(psFwInfo); | 1046 | } |
| 839 | break; | 1047 | break; |
| 840 | } | ||
| 841 | case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: | ||
| 842 | { | ||
| 843 | INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); | ||
| 844 | if(NVMAccess) | ||
| 845 | { | ||
| 846 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " FW download blocked as EEPROM Read/Write is in progress\n"); | ||
| 847 | up(&Adapter->fw_download_sema); | ||
| 848 | return -EACCES; | ||
| 849 | } | ||
| 850 | if(down_trylock(&Adapter->fw_download_sema)) | ||
| 851 | { | ||
| 852 | Adapter->bBinDownloaded=TRUE; | ||
| 853 | Adapter->bCfgDownloaded=TRUE; | ||
| 854 | atomic_set(&Adapter->CurrNumFreeTxDesc, 0); | ||
| 855 | |||
| 856 | Adapter->CurrNumRecvDescs=0; | ||
| 857 | Adapter->downloadDDR = 0; | ||
| 858 | |||
| 859 | //setting the Mips to Run | ||
| 860 | Status = run_card_proc(Adapter); | ||
| 861 | if(Status) | ||
| 862 | { | ||
| 863 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n"); | ||
| 864 | up(&Adapter->fw_download_sema); | ||
| 865 | up(&Adapter->NVMRdmWrmLock); | ||
| 866 | break; | ||
| 867 | } | ||
| 868 | else | ||
| 869 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Firm Download Over...\n"); | ||
| 870 | mdelay(10); | ||
| 871 | /* Wait for MailBox Interrupt */ | ||
| 872 | if(StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter)) | ||
| 873 | { | ||
| 874 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n"); | ||
| 875 | } | ||
| 876 | timeout = 5*HZ; | ||
| 877 | Adapter->waiting_to_fw_download_done = FALSE; | ||
| 878 | wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue, | ||
| 879 | Adapter->waiting_to_fw_download_done, timeout); | ||
| 880 | Adapter->fw_download_process_pid=INVALID_PID; | ||
| 881 | Adapter->fw_download_done=TRUE; | ||
| 882 | atomic_set(&Adapter->CurrNumFreeTxDesc, 0); | ||
| 883 | Adapter->CurrNumRecvDescs = 0; | ||
| 884 | Adapter->PrevNumRecvDescs = 0; | ||
| 885 | atomic_set(&Adapter->cntrlpktCnt,0); | ||
| 886 | Adapter->LinkUpStatus = 0; | ||
| 887 | Adapter->LinkStatus = 0; | ||
| 888 | |||
| 889 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | ||
| 890 | { | ||
| 891 | Adapter->DriverState = FW_DOWNLOAD_DONE; | ||
| 892 | wake_up(&Adapter->LEDInfo.notify_led_event); | ||
| 893 | } | ||
| 894 | 1048 | ||
| 895 | if(!timeout) | 1049 | case IOCTL_BCM_GET_HOST_MIBS: { |
| 896 | { | 1050 | PVOID temp_buff; |
| 897 | Status = -ENODEV; | 1051 | |
| 898 | } | 1052 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 899 | } | 1053 | return -EFAULT; |
| 900 | else | 1054 | |
| 901 | { | 1055 | if (IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) { |
| 902 | Status = -EINVAL; | 1056 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, |
| 903 | } | 1057 | "Length Check failed %lu %zd\n", |
| 904 | up(&Adapter->fw_download_sema); | 1058 | IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS)); |
| 905 | up(&Adapter->NVMRdmWrmLock); | 1059 | return -EINVAL; |
| 906 | break; | ||
| 907 | } | 1060 | } |
| 908 | case IOCTL_BE_BUCKET_SIZE: | ||
| 909 | Status = 0; | ||
| 910 | if (get_user(Adapter->BEBucketSize, (unsigned long __user *)arg)) | ||
| 911 | Status = -EFAULT; | ||
| 912 | break; | ||
| 913 | 1061 | ||
| 914 | case IOCTL_RTPS_BUCKET_SIZE: | 1062 | /* FIXME: HOST_STATS are too big for kmalloc (122048)! */ |
| 915 | Status = 0; | 1063 | temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL); |
| 916 | if (get_user(Adapter->rtPSBucketSize, (unsigned long __user *)arg)) | 1064 | if (!temp_buff) |
| 1065 | return STATUS_FAILURE; | ||
| 1066 | |||
| 1067 | Status = ProcessGetHostMibs(Adapter, temp_buff); | ||
| 1068 | GetDroppedAppCntrlPktMibs(temp_buff, pTarang); | ||
| 1069 | |||
| 1070 | if (Status != STATUS_FAILURE) | ||
| 1071 | if (copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) | ||
| 917 | Status = -EFAULT; | 1072 | Status = -EFAULT; |
| 918 | break; | 1073 | |
| 919 | case IOCTL_CHIP_RESET: | 1074 | kfree(temp_buff); |
| 920 | { | 1075 | break; |
| 921 | INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); | 1076 | } |
| 922 | if(NVMAccess) | 1077 | |
| 923 | { | 1078 | case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE: |
| 924 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); | 1079 | if ((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE == Adapter->IdleMode)) { |
| 925 | return -EACCES; | 1080 | Adapter->usIdleModePattern = ABORT_IDLE_MODE; |
| 926 | } | 1081 | Adapter->bWakeUpDevice = TRUE; |
| 927 | down(&Adapter->RxAppControlQueuelock); | 1082 | wake_up(&Adapter->process_rx_cntrlpkt); |
| 928 | Status = reset_card_proc(Adapter); | ||
| 929 | flushAllAppQ(); | ||
| 930 | up(&Adapter->RxAppControlQueuelock); | ||
| 931 | up(&Adapter->NVMRdmWrmLock); | ||
| 932 | ResetCounters(Adapter); | ||
| 933 | break; | ||
| 934 | } | 1083 | } |
| 935 | case IOCTL_QOS_THRESHOLD: | ||
| 936 | { | ||
| 937 | USHORT uiLoopIndex; | ||
| 938 | 1084 | ||
| 939 | Status = 0; | 1085 | Status = STATUS_SUCCESS; |
| 940 | for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) { | 1086 | break; |
| 941 | if (get_user(Adapter->PackInfo[uiLoopIndex].uiThreshold, | 1087 | |
| 942 | (unsigned long __user *)arg)) { | 1088 | case IOCTL_BCM_BULK_WRM: { |
| 943 | Status = -EFAULT; | 1089 | PBULKWRM_BUFFER pBulkBuffer; |
| 944 | break; | 1090 | UINT uiTempVar = 0; |
| 945 | } | 1091 | PCHAR pvBuffer = NULL; |
| 946 | } | 1092 | |
| 1093 | if ((Adapter->IdleMode == TRUE) || | ||
| 1094 | (Adapter->bShutStatus == TRUE) || | ||
| 1095 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 1096 | |||
| 1097 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n"); | ||
| 1098 | Status = -EACCES; | ||
| 947 | break; | 1099 | break; |
| 948 | } | 1100 | } |
| 949 | 1101 | ||
| 950 | case IOCTL_DUMP_PACKET_INFO: | 1102 | /* Copy Ioctl Buffer structure */ |
| 1103 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 1104 | return -EFAULT; | ||
| 951 | 1105 | ||
| 952 | DumpPackInfo(Adapter); | 1106 | /* FIXME: restrict length */ |
| 953 | DumpPhsRules(&Adapter->stBCMPhsContext); | 1107 | pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); |
| 954 | Status = STATUS_SUCCESS; | 1108 | if (!pvBuffer) |
| 1109 | return -ENOMEM; | ||
| 1110 | |||
| 1111 | /* Get WrmBuffer structure */ | ||
| 1112 | if (copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) { | ||
| 1113 | kfree(pvBuffer); | ||
| 1114 | Status = -EFAULT; | ||
| 955 | break; | 1115 | break; |
| 1116 | } | ||
| 956 | 1117 | ||
| 957 | case IOCTL_GET_PACK_INFO: | 1118 | pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer; |
| 958 | if(copy_to_user(argp, &Adapter->PackInfo, sizeof(PacketInfo)*NO_OF_QUEUES)) | 1119 | |
| 959 | return -EFAULT; | 1120 | if (((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 || |
| 960 | Status = STATUS_SUCCESS; | 1121 | ((ULONG)pBulkBuffer->Register & 0x3)) { |
| 1122 | kfree(pvBuffer); | ||
| 1123 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", (int)pBulkBuffer->Register); | ||
| 1124 | Status = -EINVAL; | ||
| 961 | break; | 1125 | break; |
| 962 | case IOCTL_BCM_SWITCH_TRANSFER_MODE: | 1126 | } |
| 963 | { | ||
| 964 | UINT uiData = 0; | ||
| 965 | if(copy_from_user(&uiData, argp, sizeof(UINT))) | ||
| 966 | return -EFAULT; | ||
| 967 | 1127 | ||
| 968 | if(uiData) /* Allow All Packets */ | 1128 | uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK; |
| 969 | { | 1129 | if (!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) && |
| 970 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n"); | 1130 | ((uiTempVar == EEPROM_REJECT_REG_1) || |
| 971 | Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE; | 1131 | (uiTempVar == EEPROM_REJECT_REG_2) || |
| 972 | } | 1132 | (uiTempVar == EEPROM_REJECT_REG_3) || |
| 973 | else /* Allow IP only Packets */ | 1133 | (uiTempVar == EEPROM_REJECT_REG_4)) && |
| 974 | { | 1134 | (cmd == IOCTL_BCM_REGISTER_WRITE)) { |
| 975 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n"); | 1135 | |
| 976 | Adapter->TransferMode = IP_PACKET_ONLY_MODE; | 1136 | kfree(pvBuffer); |
| 977 | } | 1137 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); |
| 978 | Status = STATUS_SUCCESS; | 1138 | Status = -EFAULT; |
| 979 | break; | 1139 | break; |
| 980 | } | 1140 | } |
| 981 | 1141 | ||
| 982 | case IOCTL_BCM_GET_DRIVER_VERSION: | 1142 | if (pBulkBuffer->SwapEndian == FALSE) |
| 983 | { | 1143 | Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); |
| 984 | /* Copy Ioctl Buffer structure */ | 1144 | else |
| 985 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1145 | Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); |
| 986 | return -EFAULT; | 1146 | |
| 1147 | if (Status != STATUS_SUCCESS) | ||
| 1148 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n"); | ||
| 1149 | |||
| 1150 | kfree(pvBuffer); | ||
| 1151 | break; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | case IOCTL_BCM_GET_NVM_SIZE: | ||
| 1155 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 1156 | return -EFAULT; | ||
| 987 | 1157 | ||
| 988 | if(copy_to_user(IoBuffer.OutputBuffer, VER_FILEVERSION_STR, IoBuffer.OutputLength)) | 1158 | if (Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH) { |
| 1159 | if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT))) | ||
| 989 | return -EFAULT; | 1160 | return -EFAULT; |
| 990 | Status = STATUS_SUCCESS; | ||
| 991 | break; | ||
| 992 | } | 1161 | } |
| 993 | case IOCTL_BCM_GET_CURRENT_STATUS: | ||
| 994 | { | ||
| 995 | LINK_STATE link_state; | ||
| 996 | 1162 | ||
| 997 | /* Copy Ioctl Buffer structure */ | 1163 | Status = STATUS_SUCCESS; |
| 998 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1164 | break; |
| 999 | { | ||
| 1000 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n"); | ||
| 1001 | Status = -EFAULT; | ||
| 1002 | break; | ||
| 1003 | } | ||
| 1004 | if (IoBuffer.OutputLength != sizeof(link_state)) { | ||
| 1005 | Status = -EINVAL; | ||
| 1006 | break; | ||
| 1007 | } | ||
| 1008 | 1165 | ||
| 1009 | memset(&link_state, 0, sizeof(link_state)); | 1166 | case IOCTL_BCM_CAL_INIT: { |
| 1010 | link_state.bIdleMode = Adapter->IdleMode; | 1167 | UINT uiSectorSize = 0 ; |
| 1011 | link_state.bShutdownMode = Adapter->bShutStatus; | 1168 | if (Adapter->eNVMType == NVM_FLASH) { |
| 1012 | link_state.ucLinkStatus = Adapter->LinkStatus; | 1169 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 1170 | return -EFAULT; | ||
| 1013 | 1171 | ||
| 1014 | if (copy_to_user(IoBuffer.OutputBuffer, &link_state, | 1172 | if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT))) |
| 1015 | min_t(size_t, sizeof(link_state), IoBuffer.OutputLength))) | 1173 | return -EFAULT; |
| 1016 | { | 1174 | |
| 1017 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n"); | 1175 | if ((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) { |
| 1018 | Status = -EFAULT; | 1176 | if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, |
| 1019 | break; | 1177 | sizeof(UINT))) |
| 1178 | return -EFAULT; | ||
| 1179 | } else { | ||
| 1180 | if (IsFlash2x(Adapter)) { | ||
| 1181 | if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, sizeof(UINT))) | ||
| 1182 | return -EFAULT; | ||
| 1183 | } else { | ||
| 1184 | if ((TRUE == Adapter->bShutStatus) || (TRUE == Adapter->IdleMode)) { | ||
| 1185 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is in Idle/Shutdown Mode\n"); | ||
| 1186 | return -EACCES; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | Adapter->uiSectorSize = uiSectorSize; | ||
| 1190 | BcmUpdateSectorSize(Adapter, Adapter->uiSectorSize); | ||
| 1191 | } | ||
| 1020 | } | 1192 | } |
| 1021 | Status = STATUS_SUCCESS; | 1193 | Status = STATUS_SUCCESS; |
| 1022 | break; | 1194 | } else { |
| 1195 | Status = STATUS_FAILURE; | ||
| 1023 | } | 1196 | } |
| 1024 | case IOCTL_BCM_SET_MAC_TRACING: | 1197 | } |
| 1025 | { | 1198 | break; |
| 1026 | UINT tracing_flag; | ||
| 1027 | |||
| 1028 | /* copy ioctl Buffer structure */ | ||
| 1029 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 1030 | return -EFAULT; | ||
| 1031 | |||
| 1032 | if(copy_from_user(&tracing_flag,IoBuffer.InputBuffer,sizeof(UINT))) | ||
| 1033 | return -EFAULT; | ||
| 1034 | |||
| 1035 | if (tracing_flag) | ||
| 1036 | Adapter->pTarangs->MacTracingEnabled = TRUE; | ||
| 1037 | else | ||
| 1038 | Adapter->pTarangs->MacTracingEnabled = FALSE; | ||
| 1039 | break; | ||
| 1040 | } | ||
| 1041 | case IOCTL_BCM_GET_DSX_INDICATION: | ||
| 1042 | { | ||
| 1043 | ULONG ulSFId=0; | ||
| 1044 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 1045 | return -EFAULT; | ||
| 1046 | 1199 | ||
| 1047 | if(IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) | 1200 | case IOCTL_BCM_SET_DEBUG: |
| 1048 | { | 1201 | #ifdef DEBUG |
| 1049 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, | 1202 | { |
| 1050 | "Mismatch req: %lx needed is =0x%zx!!!", | 1203 | USER_BCM_DBG_STATE sUserDebugState; |
| 1051 | IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); | ||
| 1052 | return -EINVAL; | ||
| 1053 | } | ||
| 1054 | 1204 | ||
| 1055 | if(copy_from_user(&ulSFId, IoBuffer.InputBuffer, sizeof(ulSFId))) | 1205 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n"); |
| 1056 | return -EFAULT; | 1206 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 1207 | return -EFAULT; | ||
| 1208 | |||
| 1209 | if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE))) | ||
| 1210 | return -EFAULT; | ||
| 1057 | 1211 | ||
| 1058 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId ); | 1212 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ", |
| 1059 | get_dsx_sf_data_to_application(Adapter, ulSFId, IoBuffer.OutputBuffer); | 1213 | sUserDebugState.OnOff, sUserDebugState.Type); |
| 1060 | Status=STATUS_SUCCESS; | 1214 | /* sUserDebugState.Subtype <<= 1; */ |
| 1215 | sUserDebugState.Subtype = 1 << sUserDebugState.Subtype; | ||
| 1216 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype); | ||
| 1217 | |||
| 1218 | /* Update new 'DebugState' in the Adapter */ | ||
| 1219 | Adapter->stDebugState.type |= sUserDebugState.Type; | ||
| 1220 | /* Subtype: A bitmap of 32 bits for Subtype per Type. | ||
| 1221 | * Valid indexes in 'subtype' array: 1,2,4,8 | ||
| 1222 | * corresponding to valid Type values. Hence we can use the 'Type' field | ||
| 1223 | * as the index value, ignoring the array entries 0,3,5,6,7 ! | ||
| 1224 | */ | ||
| 1225 | if (sUserDebugState.OnOff) | ||
| 1226 | Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype; | ||
| 1227 | else | ||
| 1228 | Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype; | ||
| 1229 | |||
| 1230 | BCM_SHOW_DEBUG_BITMAP(Adapter); | ||
| 1231 | } | ||
| 1232 | #endif | ||
| 1233 | break; | ||
| 1234 | |||
| 1235 | case IOCTL_BCM_NVM_READ: | ||
| 1236 | case IOCTL_BCM_NVM_WRITE: { | ||
| 1237 | NVM_READWRITE stNVMReadWrite; | ||
| 1238 | PUCHAR pReadData = NULL; | ||
| 1239 | ULONG ulDSDMagicNumInUsrBuff = 0; | ||
| 1240 | struct timeval tv0, tv1; | ||
| 1241 | memset(&tv0, 0, sizeof(struct timeval)); | ||
| 1242 | memset(&tv1, 0, sizeof(struct timeval)); | ||
| 1243 | if ((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) { | ||
| 1244 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n"); | ||
| 1245 | Status = -EFAULT; | ||
| 1246 | break; | ||
| 1061 | } | 1247 | } |
| 1062 | break; | ||
| 1063 | case IOCTL_BCM_GET_HOST_MIBS: | ||
| 1064 | { | ||
| 1065 | PVOID temp_buff; | ||
| 1066 | 1248 | ||
| 1067 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1249 | if (IsFlash2x(Adapter)) { |
| 1068 | return -EFAULT; | 1250 | if ((Adapter->eActiveDSD != DSD0) && |
| 1251 | (Adapter->eActiveDSD != DSD1) && | ||
| 1252 | (Adapter->eActiveDSD != DSD2)) { | ||
| 1069 | 1253 | ||
| 1070 | if(IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) | 1254 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No DSD is active..hence NVM Command is blocked"); |
| 1071 | { | 1255 | return STATUS_FAILURE ; |
| 1072 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, | ||
| 1073 | "Length Check failed %lu %zd\n", | ||
| 1074 | IoBuffer.OutputLength, sizeof(S_MIBS_HOST_STATS_MIBS)); | ||
| 1075 | return -EINVAL; | ||
| 1076 | } | 1256 | } |
| 1257 | } | ||
| 1077 | 1258 | ||
| 1078 | /* FIXME: HOST_STATS are too big for kmalloc (122048)! */ | 1259 | /* Copy Ioctl Buffer structure */ |
| 1079 | temp_buff = kzalloc(sizeof(S_MIBS_HOST_STATS_MIBS), GFP_KERNEL); | 1260 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 1080 | if(!temp_buff) | 1261 | return -EFAULT; |
| 1081 | return STATUS_FAILURE; | ||
| 1082 | 1262 | ||
| 1083 | Status = ProcessGetHostMibs(Adapter, temp_buff); | 1263 | if (copy_from_user(&stNVMReadWrite, |
| 1084 | GetDroppedAppCntrlPktMibs(temp_buff, pTarang); | 1264 | (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer, |
| 1265 | sizeof(NVM_READWRITE))) | ||
| 1266 | return -EFAULT; | ||
| 1085 | 1267 | ||
| 1086 | if (Status != STATUS_FAILURE) | 1268 | /* |
| 1087 | if(copy_to_user(IoBuffer.OutputBuffer, temp_buff, sizeof(S_MIBS_HOST_STATS_MIBS))) | 1269 | * Deny the access if the offset crosses the cal area limit. |
| 1088 | Status = -EFAULT; | 1270 | */ |
| 1089 | 1271 | ||
| 1090 | kfree(temp_buff); | 1272 | if ((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) { |
| 1273 | /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); */ | ||
| 1274 | Status = STATUS_FAILURE; | ||
| 1091 | break; | 1275 | break; |
| 1092 | } | 1276 | } |
| 1093 | 1277 | ||
| 1094 | case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE: | 1278 | pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); |
| 1095 | if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE==Adapter->IdleMode)) | 1279 | if (!pReadData) |
| 1096 | { | 1280 | return -ENOMEM; |
| 1097 | Adapter->usIdleModePattern = ABORT_IDLE_MODE; | 1281 | |
| 1098 | Adapter->bWakeUpDevice = TRUE; | 1282 | if (copy_from_user(pReadData, stNVMReadWrite.pBuffer, stNVMReadWrite.uiNumBytes)) { |
| 1099 | wake_up(&Adapter->process_rx_cntrlpkt); | 1283 | Status = -EFAULT; |
| 1100 | } | 1284 | kfree(pReadData); |
| 1101 | Status = STATUS_SUCCESS; | ||
| 1102 | break; | 1285 | break; |
| 1286 | } | ||
| 1103 | 1287 | ||
| 1104 | case IOCTL_BCM_BULK_WRM: | 1288 | do_gettimeofday(&tv0); |
| 1105 | { | 1289 | if (IOCTL_BCM_NVM_READ == cmd) { |
| 1106 | PBULKWRM_BUFFER pBulkBuffer; | 1290 | down(&Adapter->NVMRdmWrmLock); |
| 1107 | UINT uiTempVar=0; | 1291 | |
| 1108 | PCHAR pvBuffer = NULL; | 1292 | if ((Adapter->IdleMode == TRUE) || |
| 1109 | 1293 | (Adapter->bShutStatus == TRUE) || | |
| 1110 | if((Adapter->IdleMode == TRUE) || | 1294 | (Adapter->bPreparingForLowPowerMode == TRUE)) { |
| 1111 | (Adapter->bShutStatus ==TRUE) || | 1295 | |
| 1112 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 1296 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1113 | { | 1297 | up(&Adapter->NVMRdmWrmLock); |
| 1114 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n"); | 1298 | kfree(pReadData); |
| 1115 | Status = -EACCES; | 1299 | return -EACCES; |
| 1116 | break; | 1300 | } |
| 1117 | } | 1301 | |
| 1302 | Status = BeceemNVMRead(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); | ||
| 1303 | up(&Adapter->NVMRdmWrmLock); | ||
| 1304 | |||
| 1305 | if (Status != STATUS_SUCCESS) { | ||
| 1306 | kfree(pReadData); | ||
| 1307 | return Status; | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | if (copy_to_user(stNVMReadWrite.pBuffer, pReadData, stNVMReadWrite.uiNumBytes)) { | ||
| 1311 | kfree(pReadData); | ||
| 1312 | Status = -EFAULT; | ||
| 1313 | } | ||
| 1314 | } else { | ||
| 1315 | down(&Adapter->NVMRdmWrmLock); | ||
| 1118 | 1316 | ||
| 1119 | /* Copy Ioctl Buffer structure */ | 1317 | if ((Adapter->IdleMode == TRUE) || |
| 1120 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1318 | (Adapter->bShutStatus == TRUE) || |
| 1121 | return -EFAULT; | 1319 | (Adapter->bPreparingForLowPowerMode == TRUE)) { |
| 1122 | 1320 | ||
| 1123 | /* FIXME: restrict length */ | 1321 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1124 | pvBuffer = kmalloc(IoBuffer.InputLength, GFP_KERNEL); | 1322 | up(&Adapter->NVMRdmWrmLock); |
| 1125 | if(!pvBuffer) | 1323 | kfree(pReadData); |
| 1126 | return -ENOMEM; | 1324 | return -EACCES; |
| 1127 | 1325 | } | |
| 1128 | /* Get WrmBuffer structure */ | ||
| 1129 | if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) | ||
| 1130 | { | ||
| 1131 | kfree(pvBuffer); | ||
| 1132 | Status = -EFAULT; | ||
| 1133 | break; | ||
| 1134 | } | ||
| 1135 | 1326 | ||
| 1136 | pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer; | 1327 | Adapter->bHeaderChangeAllowed = TRUE; |
| 1328 | if (IsFlash2x(Adapter)) { | ||
| 1329 | /* | ||
| 1330 | * New Requirement:- | ||
| 1331 | * DSD section updation will be allowed in two case:- | ||
| 1332 | * 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull | ||
| 1333 | * 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is | ||
| 1334 | * corrupted then user space program first modify the DSD header with valid DSD sig so | ||
| 1335 | * that this as well as further write may be worthwhile. | ||
| 1336 | * | ||
| 1337 | * This restriction has been put assuming that if DSD sig is corrupted, DSD | ||
| 1338 | * data won't be considered valid. | ||
| 1339 | */ | ||
| 1137 | 1340 | ||
| 1138 | if(((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 || | 1341 | Status = BcmFlash2xCorruptSig(Adapter, Adapter->eActiveDSD); |
| 1139 | ((ULONG)pBulkBuffer->Register & 0x3)) | 1342 | if (Status != STATUS_SUCCESS) { |
| 1140 | { | 1343 | if (((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize) || |
| 1141 | kfree(pvBuffer); | 1344 | (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) { |
| 1142 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM Done On invalid Address : %x Access Denied.\n",(int)pBulkBuffer->Register); | ||
| 1143 | Status = -EINVAL; | ||
| 1144 | break; | ||
| 1145 | } | ||
| 1146 | 1345 | ||
| 1346 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input.."); | ||
| 1347 | up(&Adapter->NVMRdmWrmLock); | ||
| 1348 | kfree(pReadData); | ||
| 1349 | return Status; | ||
| 1350 | } | ||
| 1147 | 1351 | ||
| 1148 | uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK; | 1352 | ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE)); |
| 1149 | if(!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) | 1353 | if (ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) { |
| 1150 | && ((uiTempVar == EEPROM_REJECT_REG_1)|| | 1354 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "DSD Sig is present neither in Flash nor User provided Input.."); |
| 1151 | (uiTempVar == EEPROM_REJECT_REG_2) || | 1355 | up(&Adapter->NVMRdmWrmLock); |
| 1152 | (uiTempVar == EEPROM_REJECT_REG_3) || | 1356 | kfree(pReadData); |
| 1153 | (uiTempVar == EEPROM_REJECT_REG_4)) && | 1357 | return Status; |
| 1154 | (cmd == IOCTL_BCM_REGISTER_WRITE)) | 1358 | } |
| 1155 | { | ||
| 1156 | kfree(pvBuffer); | ||
| 1157 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"EEPROM Access Denied, not in VSG Mode\n"); | ||
| 1158 | Status = -EFAULT; | ||
| 1159 | break; | ||
| 1160 | } | 1359 | } |
| 1360 | } | ||
| 1161 | 1361 | ||
| 1162 | if(pBulkBuffer->SwapEndian == FALSE) | 1362 | Status = BeceemNVMWrite(Adapter, (PUINT)pReadData, stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify); |
| 1163 | Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); | 1363 | if (IsFlash2x(Adapter)) |
| 1164 | else | 1364 | BcmFlash2xWriteSig(Adapter, Adapter->eActiveDSD); |
| 1165 | Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); | ||
| 1166 | |||
| 1167 | if(Status != STATUS_SUCCESS) | ||
| 1168 | { | ||
| 1169 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n"); | ||
| 1170 | } | ||
| 1171 | 1365 | ||
| 1172 | kfree(pvBuffer); | 1366 | Adapter->bHeaderChangeAllowed = FALSE; |
| 1173 | break; | ||
| 1174 | } | ||
| 1175 | 1367 | ||
| 1176 | case IOCTL_BCM_GET_NVM_SIZE: | 1368 | up(&Adapter->NVMRdmWrmLock); |
| 1177 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 1178 | return -EFAULT; | ||
| 1179 | 1369 | ||
| 1180 | if(Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH ) { | 1370 | if (Status != STATUS_SUCCESS) { |
| 1181 | if(copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiNVMDSDSize, sizeof(UINT))) | 1371 | kfree(pReadData); |
| 1182 | return -EFAULT; | 1372 | return Status; |
| 1183 | } | 1373 | } |
| 1184 | Status = STATUS_SUCCESS ; | 1374 | } |
| 1185 | break; | ||
| 1186 | 1375 | ||
| 1187 | case IOCTL_BCM_CAL_INIT : | 1376 | do_gettimeofday(&tv1); |
| 1377 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n", (tv1.tv_sec - tv0.tv_sec)*1000 + (tv1.tv_usec - tv0.tv_usec)/1000); | ||
| 1188 | 1378 | ||
| 1189 | { | 1379 | kfree(pReadData); |
| 1190 | UINT uiSectorSize = 0 ; | 1380 | Status = STATUS_SUCCESS; |
| 1191 | if(Adapter->eNVMType == NVM_FLASH) | 1381 | } |
| 1192 | { | 1382 | break; |
| 1193 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1383 | |
| 1194 | return -EFAULT; | 1384 | case IOCTL_BCM_FLASH2X_SECTION_READ: { |
| 1385 | FLASH2X_READWRITE sFlash2xRead = {0}; | ||
| 1386 | PUCHAR pReadBuff = NULL ; | ||
| 1387 | UINT NOB = 0; | ||
| 1388 | UINT BuffSize = 0; | ||
| 1389 | UINT ReadBytes = 0; | ||
| 1390 | UINT ReadOffset = 0; | ||
| 1391 | void __user *OutPutBuff; | ||
| 1392 | |||
| 1393 | if (IsFlash2x(Adapter) != TRUE) { | ||
| 1394 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); | ||
| 1395 | return -EINVAL; | ||
| 1396 | } | ||
| 1195 | 1397 | ||
| 1196 | if (copy_from_user(&uiSectorSize, IoBuffer.InputBuffer, sizeof(UINT))) | 1398 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called"); |
| 1197 | return -EFAULT; | 1399 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 1400 | return -EFAULT; | ||
| 1198 | 1401 | ||
| 1199 | if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) | 1402 | /* Reading FLASH 2.x READ structure */ |
| 1200 | { | 1403 | if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) |
| 1201 | if (copy_to_user(IoBuffer.OutputBuffer, &Adapter->uiSectorSize, | 1404 | return -EFAULT; |
| 1202 | sizeof(UINT))) | ||
| 1203 | return -EFAULT; | ||
| 1204 | } | ||
| 1205 | else | ||
| 1206 | { | ||
| 1207 | if(IsFlash2x(Adapter)) | ||
| 1208 | { | ||
| 1209 | if (copy_to_user(IoBuffer.OutputBuffer, | ||
| 1210 | &Adapter->uiSectorSize , | ||
| 1211 | sizeof(UINT))) | ||
| 1212 | return -EFAULT; | ||
| 1213 | } | ||
| 1214 | else | ||
| 1215 | { | ||
| 1216 | if((TRUE == Adapter->bShutStatus) || | ||
| 1217 | (TRUE == Adapter->IdleMode)) | ||
| 1218 | { | ||
| 1219 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle/Shutdown Mode\n"); | ||
| 1220 | return -EACCES; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | Adapter->uiSectorSize = uiSectorSize ; | ||
| 1224 | BcmUpdateSectorSize(Adapter,Adapter->uiSectorSize); | ||
| 1225 | } | ||
| 1226 | } | ||
| 1227 | Status = STATUS_SUCCESS ; | ||
| 1228 | } | ||
| 1229 | else | ||
| 1230 | { | ||
| 1231 | Status = STATUS_FAILURE; | ||
| 1232 | } | ||
| 1233 | } | ||
| 1234 | break; | ||
| 1235 | case IOCTL_BCM_SET_DEBUG : | ||
| 1236 | #ifdef DEBUG | ||
| 1237 | { | ||
| 1238 | USER_BCM_DBG_STATE sUserDebugState; | ||
| 1239 | 1405 | ||
| 1240 | // BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Entered the ioctl %x \n", IOCTL_BCM_SET_DEBUG ); | 1406 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xRead.Section); |
| 1407 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%x", sFlash2xRead.offset); | ||
| 1408 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xRead.numOfBytes); | ||
| 1409 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xRead.bVerify); | ||
| 1241 | 1410 | ||
| 1242 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n"); | 1411 | /* This was internal to driver for raw read. now it has ben exposed to user space app. */ |
| 1243 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1412 | if (validateFlash2xReadWrite(Adapter, &sFlash2xRead) == FALSE) |
| 1244 | return -EFAULT; | 1413 | return STATUS_FAILURE; |
| 1245 | 1414 | ||
| 1246 | if (copy_from_user(&sUserDebugState, IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE))) | 1415 | NOB = sFlash2xRead.numOfBytes; |
| 1247 | return -EFAULT; | 1416 | if (NOB > Adapter->uiSectorSize) |
| 1417 | BuffSize = Adapter->uiSectorSize; | ||
| 1418 | else | ||
| 1419 | BuffSize = NOB; | ||
| 1248 | 1420 | ||
| 1421 | ReadOffset = sFlash2xRead.offset ; | ||
| 1422 | OutPutBuff = IoBuffer.OutputBuffer; | ||
| 1423 | pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); | ||
| 1249 | 1424 | ||
| 1250 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ", | 1425 | if (pReadBuff == NULL) { |
| 1251 | sUserDebugState.OnOff, sUserDebugState.Type); | 1426 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure"); |
| 1252 | //sUserDebugState.Subtype <<= 1; | 1427 | return -ENOMEM; |
| 1253 | sUserDebugState.Subtype = 1 << sUserDebugState.Subtype; | 1428 | } |
| 1254 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype); | 1429 | down(&Adapter->NVMRdmWrmLock); |
| 1255 | |||
| 1256 | // Update new 'DebugState' in the Adapter | ||
| 1257 | Adapter->stDebugState.type |= sUserDebugState.Type; | ||
| 1258 | /* Subtype: A bitmap of 32 bits for Subtype per Type. | ||
| 1259 | * Valid indexes in 'subtype' array: 1,2,4,8 | ||
| 1260 | * corresponding to valid Type values. Hence we can use the 'Type' field | ||
| 1261 | * as the index value, ignoring the array entries 0,3,5,6,7 ! | ||
| 1262 | */ | ||
| 1263 | if (sUserDebugState.OnOff) | ||
| 1264 | Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype; | ||
| 1265 | else | ||
| 1266 | Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype; | ||
| 1267 | 1430 | ||
| 1268 | BCM_SHOW_DEBUG_BITMAP(Adapter); | 1431 | if ((Adapter->IdleMode == TRUE) || |
| 1432 | (Adapter->bShutStatus == TRUE) || | ||
| 1433 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 1269 | 1434 | ||
| 1270 | } | 1435 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1271 | #endif | 1436 | up(&Adapter->NVMRdmWrmLock); |
| 1272 | break; | 1437 | kfree(pReadBuff); |
| 1273 | case IOCTL_BCM_NVM_READ: | 1438 | return -EACCES; |
| 1274 | case IOCTL_BCM_NVM_WRITE: | 1439 | } |
| 1275 | { | ||
| 1276 | NVM_READWRITE stNVMReadWrite; | ||
| 1277 | PUCHAR pReadData = NULL; | ||
| 1278 | ULONG ulDSDMagicNumInUsrBuff = 0; | ||
| 1279 | struct timeval tv0, tv1; | ||
| 1280 | memset(&tv0,0,sizeof(struct timeval)); | ||
| 1281 | memset(&tv1,0,sizeof(struct timeval)); | ||
| 1282 | if((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) | ||
| 1283 | { | ||
| 1284 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,"The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n"); | ||
| 1285 | Status = -EFAULT; | ||
| 1286 | break; | ||
| 1287 | } | ||
| 1288 | 1440 | ||
| 1289 | if(IsFlash2x(Adapter)) | 1441 | while (NOB) { |
| 1290 | { | 1442 | if (NOB > Adapter->uiSectorSize) |
| 1291 | if((Adapter->eActiveDSD != DSD0) && | 1443 | ReadBytes = Adapter->uiSectorSize; |
| 1292 | (Adapter->eActiveDSD != DSD1) && | 1444 | else |
| 1293 | (Adapter->eActiveDSD != DSD2)) | 1445 | ReadBytes = NOB; |
| 1294 | { | ||
| 1295 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"No DSD is active..hence NVM Command is blocked"); | ||
| 1296 | return STATUS_FAILURE ; | ||
| 1297 | } | ||
| 1298 | } | ||
| 1299 | 1446 | ||
| 1300 | /* Copy Ioctl Buffer structure */ | 1447 | /* Reading the data from Flash 2.x */ |
| 1448 | Status = BcmFlash2xBulkRead(Adapter, (PUINT)pReadBuff, sFlash2xRead.Section, ReadOffset, ReadBytes); | ||
| 1449 | if (Status) { | ||
| 1450 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Flash 2x read err with Status :%d", Status); | ||
| 1451 | break; | ||
| 1452 | } | ||
| 1301 | 1453 | ||
| 1302 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1454 | BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes); |
| 1303 | return -EFAULT; | ||
| 1304 | 1455 | ||
| 1305 | if(copy_from_user(&stNVMReadWrite, | 1456 | Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes); |
| 1306 | (IOCTL_BCM_NVM_READ == cmd) ? IoBuffer.OutputBuffer : IoBuffer.InputBuffer, | 1457 | if (Status) { |
| 1307 | sizeof(NVM_READWRITE))) | 1458 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy to use failed with status :%d", Status); |
| 1308 | return -EFAULT; | 1459 | break; |
| 1460 | } | ||
| 1461 | NOB = NOB - ReadBytes; | ||
| 1462 | if (NOB) { | ||
| 1463 | ReadOffset = ReadOffset + ReadBytes; | ||
| 1464 | OutPutBuff = OutPutBuff + ReadBytes ; | ||
| 1465 | } | ||
| 1466 | } | ||
| 1309 | 1467 | ||
| 1310 | // | 1468 | up(&Adapter->NVMRdmWrmLock); |
| 1311 | // Deny the access if the offset crosses the cal area limit. | 1469 | kfree(pReadBuff); |
| 1312 | // | 1470 | } |
| 1313 | if((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) | 1471 | break; |
| 1314 | { | 1472 | |
| 1315 | //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset , | 1473 | case IOCTL_BCM_FLASH2X_SECTION_WRITE: { |
| 1316 | // stNVMReadWrite.uiNumBytes); | 1474 | FLASH2X_READWRITE sFlash2xWrite = {0}; |
| 1317 | Status = STATUS_FAILURE; | 1475 | PUCHAR pWriteBuff; |
| 1318 | break; | 1476 | void __user *InputAddr; |
| 1319 | } | 1477 | UINT NOB = 0; |
| 1478 | UINT BuffSize = 0; | ||
| 1479 | UINT WriteOffset = 0; | ||
| 1480 | UINT WriteBytes = 0; | ||
| 1481 | |||
| 1482 | if (IsFlash2x(Adapter) != TRUE) { | ||
| 1483 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); | ||
| 1484 | return -EINVAL; | ||
| 1485 | } | ||
| 1320 | 1486 | ||
| 1321 | pReadData = kzalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); | 1487 | /* First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite */ |
| 1322 | if(!pReadData) | 1488 | Adapter->bAllDSDWriteAllow = FALSE; |
| 1323 | return -ENOMEM; | ||
| 1324 | 1489 | ||
| 1325 | if(copy_from_user(pReadData, stNVMReadWrite.pBuffer, | 1490 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_WRITE Called"); |
| 1326 | stNVMReadWrite.uiNumBytes)) | ||
| 1327 | { | ||
| 1328 | Status = -EFAULT; | ||
| 1329 | kfree(pReadData); | ||
| 1330 | break; | ||
| 1331 | } | ||
| 1332 | 1491 | ||
| 1333 | do_gettimeofday(&tv0); | 1492 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 1334 | if(IOCTL_BCM_NVM_READ == cmd) | 1493 | return -EFAULT; |
| 1335 | { | ||
| 1336 | down(&Adapter->NVMRdmWrmLock); | ||
| 1337 | 1494 | ||
| 1338 | if((Adapter->IdleMode == TRUE) || | 1495 | /* Reading FLASH 2.x READ structure */ |
| 1339 | (Adapter->bShutStatus ==TRUE) || | 1496 | if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) |
| 1340 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 1497 | return -EFAULT; |
| 1341 | { | ||
| 1342 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | ||
| 1343 | up(&Adapter->NVMRdmWrmLock); | ||
| 1344 | kfree(pReadData); | ||
| 1345 | return -EACCES; | ||
| 1346 | } | ||
| 1347 | 1498 | ||
| 1348 | Status = BeceemNVMRead(Adapter, (PUINT)pReadData, | 1499 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.Section :%x", sFlash2xWrite.Section); |
| 1349 | stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); | 1500 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.offset :%d", sFlash2xWrite.offset); |
| 1350 | 1501 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.numOfBytes :%x", sFlash2xWrite.numOfBytes); | |
| 1351 | up(&Adapter->NVMRdmWrmLock); | 1502 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\nsFlash2xRead.bVerify :%x\n", sFlash2xWrite.bVerify); |
| 1352 | |||
| 1353 | if(Status != STATUS_SUCCESS) | ||
| 1354 | { | ||
| 1355 | kfree(pReadData); | ||
| 1356 | return Status; | ||
| 1357 | } | ||
| 1358 | if(copy_to_user(stNVMReadWrite.pBuffer,pReadData, stNVMReadWrite.uiNumBytes)) | ||
| 1359 | { | ||
| 1360 | kfree(pReadData); | ||
| 1361 | Status = -EFAULT; | ||
| 1362 | } | ||
| 1363 | } | ||
| 1364 | else | ||
| 1365 | { | ||
| 1366 | 1503 | ||
| 1367 | down(&Adapter->NVMRdmWrmLock); | 1504 | if ((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && (sFlash2xWrite.Section != VSA2)) { |
| 1505 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Only VSA write is allowed"); | ||
| 1506 | return -EINVAL; | ||
| 1507 | } | ||
| 1368 | 1508 | ||
| 1369 | if((Adapter->IdleMode == TRUE) || | 1509 | if (validateFlash2xReadWrite(Adapter, &sFlash2xWrite) == FALSE) |
| 1370 | (Adapter->bShutStatus ==TRUE) || | 1510 | return STATUS_FAILURE; |
| 1371 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 1372 | { | ||
| 1373 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | ||
| 1374 | up(&Adapter->NVMRdmWrmLock); | ||
| 1375 | kfree(pReadData); | ||
| 1376 | return -EACCES; | ||
| 1377 | } | ||
| 1378 | 1511 | ||
| 1379 | Adapter->bHeaderChangeAllowed = TRUE ; | 1512 | InputAddr = sFlash2xWrite.pDataBuff; |
| 1380 | if(IsFlash2x(Adapter)) | 1513 | WriteOffset = sFlash2xWrite.offset; |
| 1381 | { | 1514 | NOB = sFlash2xWrite.numOfBytes; |
| 1382 | /* | ||
| 1383 | New Requirement:- | ||
| 1384 | DSD section updation will be allowed in two case:- | ||
| 1385 | 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull | ||
| 1386 | 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is | ||
| 1387 | corrupted then user space program first modify the DSD header with valid DSD sig so | ||
| 1388 | that this as well as further write may be worthwhile. | ||
| 1389 | |||
| 1390 | This restriction has been put assuming that if DSD sig is corrupted, DSD | ||
| 1391 | data won't be considered valid. | ||
| 1392 | |||
| 1393 | |||
| 1394 | */ | ||
| 1395 | Status = BcmFlash2xCorruptSig(Adapter,Adapter->eActiveDSD); | ||
| 1396 | if(Status != STATUS_SUCCESS) | ||
| 1397 | { | ||
| 1398 | if(( (stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize ) || | ||
| 1399 | (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) | ||
| 1400 | { | ||
| 1401 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); | ||
| 1402 | up(&Adapter->NVMRdmWrmLock); | ||
| 1403 | kfree(pReadData); | ||
| 1404 | return Status; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE)); | ||
| 1408 | if(ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) | ||
| 1409 | { | ||
| 1410 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); | ||
| 1411 | up(&Adapter->NVMRdmWrmLock); | ||
| 1412 | kfree(pReadData); | ||
| 1413 | return Status; | ||
| 1414 | } | ||
| 1415 | } | ||
| 1416 | } | ||
| 1417 | Status = BeceemNVMWrite(Adapter, (PUINT )pReadData, | ||
| 1418 | stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify); | ||
| 1419 | if(IsFlash2x(Adapter)) | ||
| 1420 | BcmFlash2xWriteSig(Adapter,Adapter->eActiveDSD); | ||
| 1421 | 1515 | ||
| 1422 | Adapter->bHeaderChangeAllowed = FALSE ; | 1516 | if (NOB > Adapter->uiSectorSize) |
| 1517 | BuffSize = Adapter->uiSectorSize; | ||
| 1518 | else | ||
| 1519 | BuffSize = NOB ; | ||
| 1423 | 1520 | ||
| 1424 | up(&Adapter->NVMRdmWrmLock); | 1521 | pWriteBuff = kmalloc(BuffSize, GFP_KERNEL); |
| 1425 | 1522 | ||
| 1523 | if (pWriteBuff == NULL) | ||
| 1524 | return -ENOMEM; | ||
| 1426 | 1525 | ||
| 1427 | if(Status != STATUS_SUCCESS) | 1526 | /* extracting the remainder of the given offset. */ |
| 1428 | { | 1527 | WriteBytes = Adapter->uiSectorSize; |
| 1429 | kfree(pReadData); | 1528 | if (WriteOffset % Adapter->uiSectorSize) |
| 1430 | return Status; | 1529 | WriteBytes = Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize); |
| 1431 | } | ||
| 1432 | } | ||
| 1433 | do_gettimeofday(&tv1); | ||
| 1434 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n",(tv1.tv_sec - tv0.tv_sec)*1000 +(tv1.tv_usec - tv0.tv_usec)/1000); | ||
| 1435 | 1530 | ||
| 1531 | if (NOB < WriteBytes) | ||
| 1532 | WriteBytes = NOB; | ||
| 1436 | 1533 | ||
| 1437 | kfree(pReadData); | 1534 | down(&Adapter->NVMRdmWrmLock); |
| 1438 | Status = STATUS_SUCCESS; | ||
| 1439 | } | ||
| 1440 | break; | ||
| 1441 | case IOCTL_BCM_FLASH2X_SECTION_READ : | ||
| 1442 | { | ||
| 1443 | |||
| 1444 | FLASH2X_READWRITE sFlash2xRead = {0}; | ||
| 1445 | PUCHAR pReadBuff = NULL ; | ||
| 1446 | UINT NOB = 0; | ||
| 1447 | UINT BuffSize = 0; | ||
| 1448 | UINT ReadBytes = 0; | ||
| 1449 | UINT ReadOffset = 0; | ||
| 1450 | void __user *OutPutBuff; | ||
| 1451 | |||
| 1452 | if(IsFlash2x(Adapter) != TRUE) | ||
| 1453 | { | ||
| 1454 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); | ||
| 1455 | return -EINVAL; | ||
| 1456 | } | ||
| 1457 | 1535 | ||
| 1458 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called"); | 1536 | if ((Adapter->IdleMode == TRUE) || |
| 1459 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1537 | (Adapter->bShutStatus == TRUE) || |
| 1460 | return -EFAULT; | 1538 | (Adapter->bPreparingForLowPowerMode == TRUE)) { |
| 1461 | 1539 | ||
| 1462 | //Reading FLASH 2.x READ structure | 1540 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1463 | if (copy_from_user(&sFlash2xRead, IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE))) | 1541 | up(&Adapter->NVMRdmWrmLock); |
| 1464 | return -EFAULT; | 1542 | kfree(pWriteBuff); |
| 1543 | return -EACCES; | ||
| 1544 | } | ||
| 1465 | 1545 | ||
| 1546 | BcmFlash2xCorruptSig(Adapter, sFlash2xWrite.Section); | ||
| 1547 | do { | ||
| 1548 | Status = copy_from_user(pWriteBuff, InputAddr, WriteBytes); | ||
| 1549 | if (Status) { | ||
| 1550 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to user failed with status :%d", Status); | ||
| 1551 | break; | ||
| 1552 | } | ||
| 1553 | BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pWriteBuff, WriteBytes); | ||
| 1466 | 1554 | ||
| 1467 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xRead.Section); | 1555 | /* Writing the data from Flash 2.x */ |
| 1468 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%x" ,sFlash2xRead.offset); | 1556 | Status = BcmFlash2xBulkWrite(Adapter, (PUINT)pWriteBuff, sFlash2xWrite.Section, WriteOffset, WriteBytes, sFlash2xWrite.bVerify); |
| 1469 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xRead.numOfBytes); | ||
| 1470 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xRead.bVerify); | ||
| 1471 | 1557 | ||
| 1472 | //This was internal to driver for raw read. now it has ben exposed to user space app. | 1558 | if (Status) { |
| 1473 | if(validateFlash2xReadWrite(Adapter,&sFlash2xRead) == FALSE) | 1559 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status); |
| 1474 | return STATUS_FAILURE ; | 1560 | break; |
| 1561 | } | ||
| 1475 | 1562 | ||
| 1476 | NOB = sFlash2xRead.numOfBytes; | 1563 | NOB = NOB - WriteBytes; |
| 1477 | if(NOB > Adapter->uiSectorSize ) | 1564 | if (NOB) { |
| 1478 | BuffSize = Adapter->uiSectorSize; | 1565 | WriteOffset = WriteOffset + WriteBytes; |
| 1566 | InputAddr = InputAddr + WriteBytes; | ||
| 1567 | if (NOB > Adapter->uiSectorSize) | ||
| 1568 | WriteBytes = Adapter->uiSectorSize; | ||
| 1479 | else | 1569 | else |
| 1480 | BuffSize = NOB ; | 1570 | WriteBytes = NOB; |
| 1571 | } | ||
| 1572 | } while (NOB > 0); | ||
| 1481 | 1573 | ||
| 1482 | ReadOffset = sFlash2xRead.offset ; | 1574 | BcmFlash2xWriteSig(Adapter, sFlash2xWrite.Section); |
| 1483 | OutPutBuff = IoBuffer.OutputBuffer; | 1575 | up(&Adapter->NVMRdmWrmLock); |
| 1576 | kfree(pWriteBuff); | ||
| 1577 | } | ||
| 1578 | break; | ||
| 1484 | 1579 | ||
| 1580 | case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP: { | ||
| 1581 | PFLASH2X_BITMAP psFlash2xBitMap; | ||
| 1582 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called"); | ||
| 1485 | 1583 | ||
| 1486 | pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); | 1584 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 1487 | if(pReadBuff == NULL) | 1585 | return -EFAULT; |
| 1488 | { | ||
| 1489 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); | ||
| 1490 | return -ENOMEM; | ||
| 1491 | } | ||
| 1492 | down(&Adapter->NVMRdmWrmLock); | ||
| 1493 | |||
| 1494 | if((Adapter->IdleMode == TRUE) || | ||
| 1495 | (Adapter->bShutStatus ==TRUE) || | ||
| 1496 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 1497 | { | ||
| 1498 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | ||
| 1499 | up(&Adapter->NVMRdmWrmLock); | ||
| 1500 | kfree(pReadBuff); | ||
| 1501 | return -EACCES; | ||
| 1502 | } | ||
| 1503 | 1586 | ||
| 1504 | while(NOB) | 1587 | if (IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP)) |
| 1505 | { | 1588 | return -EINVAL; |
| 1506 | 1589 | ||
| 1507 | if(NOB > Adapter->uiSectorSize ) | 1590 | psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); |
| 1508 | ReadBytes = Adapter->uiSectorSize; | 1591 | if (psFlash2xBitMap == NULL) { |
| 1509 | else | 1592 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory is not available"); |
| 1510 | ReadBytes = NOB; | 1593 | return -ENOMEM; |
| 1594 | } | ||
| 1511 | 1595 | ||
| 1596 | /* Reading the Flash Sectio Bit map */ | ||
| 1597 | down(&Adapter->NVMRdmWrmLock); | ||
| 1512 | 1598 | ||
| 1513 | //Reading the data from Flash 2.x | 1599 | if ((Adapter->IdleMode == TRUE) || |
| 1600 | (Adapter->bShutStatus == TRUE) || | ||
| 1601 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 1514 | 1602 | ||
| 1515 | Status = BcmFlash2xBulkRead(Adapter,(PUINT)pReadBuff,sFlash2xRead.Section,ReadOffset,ReadBytes); | 1603 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1516 | if(Status) | 1604 | up(&Adapter->NVMRdmWrmLock); |
| 1517 | { | 1605 | kfree(psFlash2xBitMap); |
| 1518 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Flash 2x read err with Status :%d", Status); | 1606 | return -EACCES; |
| 1519 | break ; | 1607 | } |
| 1520 | } | ||
| 1521 | 1608 | ||
| 1522 | BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes); | 1609 | BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap); |
| 1523 | 1610 | up(&Adapter->NVMRdmWrmLock); | |
| 1524 | Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes); | 1611 | if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) |
| 1525 | if(Status) | 1612 | Status = -EFAULT; |
| 1526 | { | ||
| 1527 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Copy to use failed with status :%d", Status); | ||
| 1528 | break; | ||
| 1529 | } | ||
| 1530 | NOB = NOB - ReadBytes; | ||
| 1531 | if(NOB) | ||
| 1532 | { | ||
| 1533 | ReadOffset = ReadOffset + ReadBytes ; | ||
| 1534 | OutPutBuff = OutPutBuff + ReadBytes ; | ||
| 1535 | } | ||
| 1536 | 1613 | ||
| 1537 | } | 1614 | kfree(psFlash2xBitMap); |
| 1538 | up(&Adapter->NVMRdmWrmLock); | 1615 | } |
| 1539 | kfree(pReadBuff); | 1616 | break; |
| 1540 | |||
| 1541 | } | ||
| 1542 | break ; | ||
| 1543 | case IOCTL_BCM_FLASH2X_SECTION_WRITE : | ||
| 1544 | { | ||
| 1545 | FLASH2X_READWRITE sFlash2xWrite = {0}; | ||
| 1546 | PUCHAR pWriteBuff; | ||
| 1547 | void __user *InputAddr; | ||
| 1548 | UINT NOB = 0; | ||
| 1549 | UINT BuffSize = 0; | ||
| 1550 | UINT WriteOffset = 0; | ||
| 1551 | UINT WriteBytes = 0; | ||
| 1552 | |||
| 1553 | if(IsFlash2x(Adapter) != TRUE) | ||
| 1554 | { | ||
| 1555 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); | ||
| 1556 | return -EINVAL; | ||
| 1557 | } | ||
| 1558 | 1617 | ||
| 1559 | //First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite | 1618 | case IOCTL_BCM_SET_ACTIVE_SECTION: { |
| 1560 | Adapter->bAllDSDWriteAllow = FALSE; | 1619 | FLASH2X_SECTION_VAL eFlash2xSectionVal = 0; |
| 1620 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called"); | ||
| 1561 | 1621 | ||
| 1622 | if (IsFlash2x(Adapter) != TRUE) { | ||
| 1623 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); | ||
| 1624 | return -EINVAL; | ||
| 1625 | } | ||
| 1562 | 1626 | ||
| 1563 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_FLASH2X_SECTION_WRITE Called"); | 1627 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); |
| 1564 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1628 | if (Status) { |
| 1565 | return -EFAULT; | 1629 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); |
| 1630 | return Status; | ||
| 1631 | } | ||
| 1566 | 1632 | ||
| 1567 | //Reading FLASH 2.x READ structure | 1633 | Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT)); |
| 1568 | if (copy_from_user(&sFlash2xWrite, IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE))) | 1634 | if (Status) { |
| 1569 | return -EFAULT; | 1635 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); |
| 1636 | return Status; | ||
| 1637 | } | ||
| 1570 | 1638 | ||
| 1571 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xWrite.Section); | 1639 | down(&Adapter->NVMRdmWrmLock); |
| 1572 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%d" ,sFlash2xWrite.offset); | ||
| 1573 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xWrite.numOfBytes); | ||
| 1574 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xWrite.bVerify); | ||
| 1575 | if((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && | ||
| 1576 | (sFlash2xWrite.Section != VSA2) ) | ||
| 1577 | { | ||
| 1578 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Only VSA write is allowed"); | ||
| 1579 | return -EINVAL; | ||
| 1580 | } | ||
| 1581 | 1640 | ||
| 1582 | if(validateFlash2xReadWrite(Adapter,&sFlash2xWrite) == FALSE) | 1641 | if ((Adapter->IdleMode == TRUE) || |
| 1583 | return STATUS_FAILURE ; | 1642 | (Adapter->bShutStatus == TRUE) || |
| 1643 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 1584 | 1644 | ||
| 1585 | InputAddr = sFlash2xWrite.pDataBuff; | 1645 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1586 | WriteOffset = sFlash2xWrite.offset ; | 1646 | up(&Adapter->NVMRdmWrmLock); |
| 1587 | NOB = sFlash2xWrite.numOfBytes; | 1647 | return -EACCES; |
| 1648 | } | ||
| 1588 | 1649 | ||
| 1589 | if(NOB > Adapter->uiSectorSize ) | 1650 | Status = BcmSetActiveSection(Adapter, eFlash2xSectionVal); |
| 1590 | BuffSize = Adapter->uiSectorSize; | 1651 | if (Status) |
| 1591 | else | 1652 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Failed to make it's priority Highest. Status %d", Status); |
| 1592 | BuffSize = NOB ; | ||
| 1593 | 1653 | ||
| 1594 | pWriteBuff = kmalloc(BuffSize, GFP_KERNEL); | 1654 | up(&Adapter->NVMRdmWrmLock); |
| 1595 | if(pWriteBuff == NULL) | 1655 | } |
| 1596 | return -ENOMEM; | 1656 | break; |
| 1597 | 1657 | ||
| 1658 | case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION: { | ||
| 1659 | /* Right Now we are taking care of only DSD */ | ||
| 1660 | Adapter->bAllDSDWriteAllow = FALSE; | ||
| 1661 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called"); | ||
| 1662 | Status = STATUS_SUCCESS; | ||
| 1663 | } | ||
| 1664 | break; | ||
| 1598 | 1665 | ||
| 1599 | //extracting the remainder of the given offset. | 1666 | case IOCTL_BCM_COPY_SECTION: { |
| 1600 | WriteBytes = Adapter->uiSectorSize ; | 1667 | FLASH2X_COPY_SECTION sCopySectStrut = {0}; |
| 1601 | if(WriteOffset % Adapter->uiSectorSize) | 1668 | Status = STATUS_SUCCESS; |
| 1602 | WriteBytes =Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize); | 1669 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called"); |
| 1603 | if(NOB < WriteBytes) | ||
| 1604 | WriteBytes = NOB; | ||
| 1605 | 1670 | ||
| 1606 | down(&Adapter->NVMRdmWrmLock); | 1671 | Adapter->bAllDSDWriteAllow = FALSE; |
| 1672 | if (IsFlash2x(Adapter) != TRUE) { | ||
| 1673 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); | ||
| 1674 | return -EINVAL; | ||
| 1675 | } | ||
| 1607 | 1676 | ||
| 1608 | if((Adapter->IdleMode == TRUE) || | 1677 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); |
| 1609 | (Adapter->bShutStatus ==TRUE) || | 1678 | if (Status) { |
| 1610 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 1679 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status); |
| 1611 | { | 1680 | return Status; |
| 1612 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | 1681 | } |
| 1613 | up(&Adapter->NVMRdmWrmLock); | ||
| 1614 | kfree(pWriteBuff); | ||
| 1615 | return -EACCES; | ||
| 1616 | } | ||
| 1617 | 1682 | ||
| 1618 | BcmFlash2xCorruptSig(Adapter,sFlash2xWrite.Section); | 1683 | Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); |
| 1619 | do | 1684 | if (Status) { |
| 1620 | { | 1685 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status); |
| 1621 | Status = copy_from_user(pWriteBuff,InputAddr,WriteBytes); | 1686 | return Status; |
| 1622 | if(Status) | 1687 | } |
| 1623 | { | ||
| 1624 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to user failed with status :%d", Status); | ||
| 1625 | break ; | ||
| 1626 | } | ||
| 1627 | BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pWriteBuff,WriteBytes); | ||
| 1628 | //Writing the data from Flash 2.x | ||
| 1629 | Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pWriteBuff,sFlash2xWrite.Section,WriteOffset,WriteBytes,sFlash2xWrite.bVerify); | ||
| 1630 | |||
| 1631 | if(Status) | ||
| 1632 | { | ||
| 1633 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status); | ||
| 1634 | break ; | ||
| 1635 | } | ||
| 1636 | 1688 | ||
| 1637 | NOB = NOB - WriteBytes; | 1689 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection); |
| 1638 | if(NOB) | 1690 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection); |
| 1639 | { | 1691 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset); |
| 1640 | WriteOffset = WriteOffset + WriteBytes ; | 1692 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes); |
| 1641 | InputAddr = InputAddr + WriteBytes ; | ||
| 1642 | if(NOB > Adapter->uiSectorSize ) | ||
| 1643 | WriteBytes = Adapter->uiSectorSize; | ||
| 1644 | else | ||
| 1645 | WriteBytes = NOB; | ||
| 1646 | } | ||
| 1647 | 1693 | ||
| 1694 | if (IsSectionExistInFlash(Adapter, sCopySectStrut.SrcSection) == FALSE) { | ||
| 1695 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection); | ||
| 1696 | return -EINVAL; | ||
| 1697 | } | ||
| 1648 | 1698 | ||
| 1649 | } while(NOB > 0); | 1699 | if (IsSectionExistInFlash(Adapter, sCopySectStrut.DstSection) == FALSE) { |
| 1650 | BcmFlash2xWriteSig(Adapter,sFlash2xWrite.Section); | 1700 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection); |
| 1651 | up(&Adapter->NVMRdmWrmLock); | 1701 | return -EINVAL; |
| 1652 | kfree(pWriteBuff); | 1702 | } |
| 1653 | } | ||
| 1654 | break ; | ||
| 1655 | case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP : | ||
| 1656 | { | ||
| 1657 | 1703 | ||
| 1658 | PFLASH2X_BITMAP psFlash2xBitMap; | 1704 | if (sCopySectStrut.SrcSection == sCopySectStrut.DstSection) { |
| 1659 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called"); | 1705 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source and Destination section should be different"); |
| 1706 | return -EINVAL; | ||
| 1707 | } | ||
| 1660 | 1708 | ||
| 1661 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1709 | down(&Adapter->NVMRdmWrmLock); |
| 1662 | return -EFAULT; | ||
| 1663 | 1710 | ||
| 1664 | if(IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP)) | 1711 | if ((Adapter->IdleMode == TRUE) || |
| 1665 | return -EINVAL; | 1712 | (Adapter->bShutStatus == TRUE) || |
| 1713 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 1666 | 1714 | ||
| 1667 | psFlash2xBitMap = kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); | 1715 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1668 | if(psFlash2xBitMap == NULL) | 1716 | up(&Adapter->NVMRdmWrmLock); |
| 1669 | { | 1717 | return -EACCES; |
| 1670 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory is not available"); | 1718 | } |
| 1671 | return -ENOMEM ; | ||
| 1672 | } | ||
| 1673 | //Reading the Flash Sectio Bit map | ||
| 1674 | down(&Adapter->NVMRdmWrmLock); | ||
| 1675 | |||
| 1676 | if((Adapter->IdleMode == TRUE) || | ||
| 1677 | (Adapter->bShutStatus ==TRUE) || | ||
| 1678 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 1679 | { | ||
| 1680 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | ||
| 1681 | up(&Adapter->NVMRdmWrmLock); | ||
| 1682 | kfree(psFlash2xBitMap); | ||
| 1683 | return -EACCES; | ||
| 1684 | } | ||
| 1685 | 1719 | ||
| 1686 | BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap); | 1720 | if (sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) { |
| 1687 | up(&Adapter->NVMRdmWrmLock); | 1721 | if (IsNonCDLessDevice(Adapter)) { |
| 1688 | if (copy_to_user(IoBuffer.OutputBuffer, psFlash2xBitMap, sizeof(FLASH2X_BITMAP))) | 1722 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Device is Non-CDLess hence won't have ISO !!"); |
| 1689 | Status = -EFAULT; | 1723 | Status = -EINVAL; |
| 1690 | 1724 | } else if (sCopySectStrut.numOfBytes == 0) { | |
| 1691 | kfree(psFlash2xBitMap); | 1725 | Status = BcmCopyISO(Adapter, sCopySectStrut); |
| 1692 | } | 1726 | } else { |
| 1693 | break ; | 1727 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Partial Copy of ISO section is not Allowed.."); |
| 1694 | case IOCTL_BCM_SET_ACTIVE_SECTION : | 1728 | Status = STATUS_FAILURE; |
| 1695 | { | 1729 | } |
| 1696 | FLASH2X_SECTION_VAL eFlash2xSectionVal = 0; | 1730 | up(&Adapter->NVMRdmWrmLock); |
| 1697 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called"); | 1731 | return Status; |
| 1698 | 1732 | } | |
| 1699 | if(IsFlash2x(Adapter) != TRUE) | ||
| 1700 | { | ||
| 1701 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); | ||
| 1702 | return -EINVAL; | ||
| 1703 | } | ||
| 1704 | 1733 | ||
| 1705 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); | 1734 | Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection, |
| 1706 | if(Status) | 1735 | sCopySectStrut.DstSection, sCopySectStrut.offset, sCopySectStrut.numOfBytes); |
| 1707 | { | 1736 | up(&Adapter->NVMRdmWrmLock); |
| 1708 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); | 1737 | } |
| 1709 | return Status; | 1738 | break; |
| 1710 | } | ||
| 1711 | 1739 | ||
| 1712 | Status = copy_from_user(&eFlash2xSectionVal,IoBuffer.InputBuffer, sizeof(INT)); | 1740 | case IOCTL_BCM_GET_FLASH_CS_INFO: { |
| 1713 | if(Status) | 1741 | Status = STATUS_SUCCESS; |
| 1714 | { | 1742 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called"); |
| 1715 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); | ||
| 1716 | return Status; | ||
| 1717 | } | ||
| 1718 | 1743 | ||
| 1719 | down(&Adapter->NVMRdmWrmLock); | 1744 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); |
| 1745 | if (Status) { | ||
| 1746 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); | ||
| 1747 | break; | ||
| 1748 | } | ||
| 1720 | 1749 | ||
| 1721 | if((Adapter->IdleMode == TRUE) || | 1750 | if (Adapter->eNVMType != NVM_FLASH) { |
| 1722 | (Adapter->bShutStatus ==TRUE) || | 1751 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Connected device does not have flash"); |
| 1723 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 1752 | Status = -EINVAL; |
| 1724 | { | 1753 | break; |
| 1725 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | 1754 | } |
| 1726 | up(&Adapter->NVMRdmWrmLock); | ||
| 1727 | return -EACCES; | ||
| 1728 | } | ||
| 1729 | 1755 | ||
| 1730 | Status = BcmSetActiveSection(Adapter,eFlash2xSectionVal); | 1756 | if (IsFlash2x(Adapter) == TRUE) { |
| 1731 | if(Status) | 1757 | if (IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO)) |
| 1732 | { | 1758 | return -EINVAL; |
| 1733 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed to make it's priority Highest. Status %d", Status); | ||
| 1734 | } | ||
| 1735 | up(&Adapter->NVMRdmWrmLock); | ||
| 1736 | } | ||
| 1737 | break ; | ||
| 1738 | case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION : | ||
| 1739 | { | ||
| 1740 | //Right Now we are taking care of only DSD | ||
| 1741 | Adapter->bAllDSDWriteAllow = FALSE ; | ||
| 1742 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called"); | ||
| 1743 | |||
| 1744 | Status = STATUS_SUCCESS ; | ||
| 1745 | } | ||
| 1746 | break ; | ||
| 1747 | case IOCTL_BCM_COPY_SECTION : | ||
| 1748 | { | ||
| 1749 | FLASH2X_COPY_SECTION sCopySectStrut = {0}; | ||
| 1750 | Status = STATUS_SUCCESS; | ||
| 1751 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called"); | ||
| 1752 | |||
| 1753 | Adapter->bAllDSDWriteAllow = FALSE ; | ||
| 1754 | if(IsFlash2x(Adapter) != TRUE) | ||
| 1755 | { | ||
| 1756 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); | ||
| 1757 | return -EINVAL; | ||
| 1758 | } | ||
| 1759 | 1759 | ||
| 1760 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); | 1760 | if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO))) |
| 1761 | if(Status) | 1761 | return -EFAULT; |
| 1762 | { | 1762 | } else { |
| 1763 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status); | 1763 | if (IoBuffer.OutputLength < sizeof(FLASH_CS_INFO)) |
| 1764 | return Status; | 1764 | return -EINVAL; |
| 1765 | } | ||
| 1766 | 1765 | ||
| 1767 | Status = copy_from_user(&sCopySectStrut, IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); | 1766 | if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO))) |
| 1768 | if(Status) | 1767 | return -EFAULT; |
| 1769 | { | 1768 | } |
| 1770 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status); | 1769 | } |
| 1771 | return Status; | 1770 | break; |
| 1772 | } | ||
| 1773 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection); | ||
| 1774 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection); | ||
| 1775 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset); | ||
| 1776 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes); | ||
| 1777 | 1771 | ||
| 1772 | case IOCTL_BCM_SELECT_DSD: { | ||
| 1773 | UINT SectOfset = 0; | ||
| 1774 | FLASH2X_SECTION_VAL eFlash2xSectionVal; | ||
| 1775 | eFlash2xSectionVal = NO_SECTION_VAL; | ||
| 1776 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SELECT_DSD Called"); | ||
| 1778 | 1777 | ||
| 1779 | if(IsSectionExistInFlash(Adapter,sCopySectStrut.SrcSection) == FALSE) | 1778 | if (IsFlash2x(Adapter) != TRUE) { |
| 1780 | { | 1779 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash Does not have 2.x map"); |
| 1781 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection); | 1780 | return -EINVAL; |
| 1782 | return -EINVAL; | 1781 | } |
| 1783 | } | ||
| 1784 | 1782 | ||
| 1785 | if(IsSectionExistInFlash(Adapter,sCopySectStrut.DstSection) == FALSE) | 1783 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); |
| 1786 | { | 1784 | if (Status) { |
| 1787 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection); | 1785 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); |
| 1788 | return -EINVAL; | 1786 | return Status; |
| 1789 | } | 1787 | } |
| 1788 | Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT)); | ||
| 1789 | if (Status) { | ||
| 1790 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); | ||
| 1791 | return Status; | ||
| 1792 | } | ||
| 1790 | 1793 | ||
| 1791 | if(sCopySectStrut.SrcSection == sCopySectStrut.DstSection) | 1794 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read Section :%d", eFlash2xSectionVal); |
| 1792 | { | 1795 | if ((eFlash2xSectionVal != DSD0) && |
| 1793 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Source and Destination section should be different"); | 1796 | (eFlash2xSectionVal != DSD1) && |
| 1794 | return -EINVAL; | 1797 | (eFlash2xSectionVal != DSD2)) { |
| 1795 | } | ||
| 1796 | 1798 | ||
| 1797 | down(&Adapter->NVMRdmWrmLock); | 1799 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Passed section<%x> is not DSD section", eFlash2xSectionVal); |
| 1800 | return STATUS_FAILURE; | ||
| 1801 | } | ||
| 1798 | 1802 | ||
| 1799 | if((Adapter->IdleMode == TRUE) || | 1803 | SectOfset = BcmGetSectionValStartOffset(Adapter, eFlash2xSectionVal); |
| 1800 | (Adapter->bShutStatus ==TRUE) || | 1804 | if (SectOfset == INVALID_OFFSET) { |
| 1801 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 1805 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal); |
| 1802 | { | 1806 | return -EINVAL; |
| 1803 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | 1807 | } |
| 1804 | up(&Adapter->NVMRdmWrmLock); | ||
| 1805 | return -EACCES; | ||
| 1806 | } | ||
| 1807 | 1808 | ||
| 1808 | if(sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) | 1809 | Adapter->bAllDSDWriteAllow = TRUE; |
| 1809 | { | 1810 | Adapter->ulFlashCalStart = SectOfset; |
| 1810 | if(IsNonCDLessDevice(Adapter)) | 1811 | Adapter->eActiveDSD = eFlash2xSectionVal; |
| 1811 | { | 1812 | } |
| 1812 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is Non-CDLess hence won't have ISO !!"); | 1813 | Status = STATUS_SUCCESS; |
| 1813 | Status = -EINVAL ; | 1814 | break; |
| 1814 | } | 1815 | |
| 1815 | else if(sCopySectStrut.numOfBytes == 0) | 1816 | case IOCTL_BCM_NVM_RAW_READ: { |
| 1816 | { | 1817 | NVM_READWRITE stNVMRead; |
| 1817 | Status = BcmCopyISO(Adapter,sCopySectStrut); | 1818 | INT NOB ; |
| 1818 | } | 1819 | INT BuffSize ; |
| 1819 | else | 1820 | INT ReadOffset = 0; |
| 1820 | { | 1821 | UINT ReadBytes = 0 ; |
| 1821 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Partial Copy of ISO section is not Allowed.."); | 1822 | PUCHAR pReadBuff; |
| 1822 | Status = STATUS_FAILURE ; | 1823 | void __user *OutPutBuff; |
| 1823 | } | 1824 | |
| 1824 | up(&Adapter->NVMRdmWrmLock); | 1825 | if (Adapter->eNVMType != NVM_FLASH) { |
| 1825 | return Status; | 1826 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "NVM TYPE is not Flash"); |
| 1826 | } | 1827 | return -EINVAL; |
| 1828 | } | ||
| 1827 | 1829 | ||
| 1828 | Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection, | 1830 | /* Copy Ioctl Buffer structure */ |
| 1829 | sCopySectStrut.DstSection,sCopySectStrut.offset,sCopySectStrut.numOfBytes); | 1831 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) { |
| 1830 | up(&Adapter->NVMRdmWrmLock); | 1832 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); |
| 1831 | } | 1833 | Status = -EFAULT; |
| 1832 | break ; | 1834 | break; |
| 1833 | case IOCTL_BCM_GET_FLASH_CS_INFO : | 1835 | } |
| 1834 | { | ||
| 1835 | Status = STATUS_SUCCESS; | ||
| 1836 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called"); | ||
| 1837 | |||
| 1838 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); | ||
| 1839 | if(Status) | ||
| 1840 | { | ||
| 1841 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); | ||
| 1842 | break; | ||
| 1843 | } | ||
| 1844 | if(Adapter->eNVMType != NVM_FLASH) | ||
| 1845 | { | ||
| 1846 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Connected device does not have flash"); | ||
| 1847 | Status = -EINVAL; | ||
| 1848 | break; | ||
| 1849 | } | ||
| 1850 | if(IsFlash2x(Adapter) == TRUE) | ||
| 1851 | { | ||
| 1852 | 1836 | ||
| 1853 | if(IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO)) | 1837 | if (copy_from_user(&stNVMRead, IoBuffer.OutputBuffer, sizeof(NVM_READWRITE))) |
| 1854 | return -EINVAL; | 1838 | return -EFAULT; |
| 1855 | 1839 | ||
| 1856 | if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO))) | 1840 | NOB = stNVMRead.uiNumBytes; |
| 1857 | return -EFAULT; | 1841 | /* In Raw-Read max Buff size : 64MB */ |
| 1858 | } | ||
| 1859 | else | ||
| 1860 | { | ||
| 1861 | if(IoBuffer.OutputLength < sizeof(FLASH_CS_INFO)) | ||
| 1862 | return -EINVAL; | ||
| 1863 | 1842 | ||
| 1864 | if (copy_to_user(IoBuffer.OutputBuffer, Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO))) | 1843 | if (NOB > DEFAULT_BUFF_SIZE) |
| 1865 | return -EFAULT; | 1844 | BuffSize = DEFAULT_BUFF_SIZE; |
| 1845 | else | ||
| 1846 | BuffSize = NOB; | ||
| 1866 | 1847 | ||
| 1867 | } | 1848 | ReadOffset = stNVMRead.uiOffset; |
| 1868 | } | 1849 | OutPutBuff = stNVMRead.pBuffer; |
| 1869 | break ; | ||
| 1870 | case IOCTL_BCM_SELECT_DSD : | ||
| 1871 | { | ||
| 1872 | UINT SectOfset = 0; | ||
| 1873 | FLASH2X_SECTION_VAL eFlash2xSectionVal; | ||
| 1874 | eFlash2xSectionVal = NO_SECTION_VAL ; | ||
| 1875 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_SELECT_DSD Called"); | ||
| 1876 | |||
| 1877 | if(IsFlash2x(Adapter) != TRUE) | ||
| 1878 | { | ||
| 1879 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); | ||
| 1880 | return -EINVAL; | ||
| 1881 | } | ||
| 1882 | 1850 | ||
| 1883 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); | 1851 | pReadBuff = kzalloc(BuffSize , GFP_KERNEL); |
| 1884 | if(Status) | 1852 | if (pReadBuff == NULL) { |
| 1885 | { | 1853 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Memory allocation failed for Flash 2.x Read Structure"); |
| 1886 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); | 1854 | Status = -ENOMEM; |
| 1887 | return Status; | 1855 | break; |
| 1888 | } | 1856 | } |
| 1889 | Status = copy_from_user(&eFlash2xSectionVal, IoBuffer.InputBuffer, sizeof(INT)); | 1857 | down(&Adapter->NVMRdmWrmLock); |
| 1890 | if(Status) | ||
| 1891 | { | ||
| 1892 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); | ||
| 1893 | return Status; | ||
| 1894 | } | ||
| 1895 | 1858 | ||
| 1896 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", eFlash2xSectionVal); | 1859 | if ((Adapter->IdleMode == TRUE) || |
| 1897 | if((eFlash2xSectionVal != DSD0) && | 1860 | (Adapter->bShutStatus == TRUE) || |
| 1898 | (eFlash2xSectionVal != DSD1) && | 1861 | (Adapter->bPreparingForLowPowerMode == TRUE)) { |
| 1899 | (eFlash2xSectionVal != DSD2) ) | ||
| 1900 | { | ||
| 1901 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Passed section<%x> is not DSD section", eFlash2xSectionVal); | ||
| 1902 | return STATUS_FAILURE ; | ||
| 1903 | } | ||
| 1904 | 1862 | ||
| 1905 | SectOfset= BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal); | 1863 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device is in Idle/Shutdown Mode\n"); |
| 1906 | if(SectOfset == INVALID_OFFSET) | 1864 | kfree(pReadBuff); |
| 1907 | { | 1865 | up(&Adapter->NVMRdmWrmLock); |
| 1908 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal); | 1866 | return -EACCES; |
| 1909 | return -EINVAL; | 1867 | } |
| 1910 | } | ||
| 1911 | 1868 | ||
| 1912 | Adapter->bAllDSDWriteAllow = TRUE ; | 1869 | Adapter->bFlashRawRead = TRUE; |
| 1913 | |||
| 1914 | Adapter->ulFlashCalStart = SectOfset ; | ||
| 1915 | Adapter->eActiveDSD = eFlash2xSectionVal; | ||
| 1916 | } | ||
| 1917 | Status = STATUS_SUCCESS ; | ||
| 1918 | break; | ||
| 1919 | |||
| 1920 | case IOCTL_BCM_NVM_RAW_READ : | ||
| 1921 | { | ||
| 1922 | |||
| 1923 | NVM_READWRITE stNVMRead; | ||
| 1924 | INT NOB ; | ||
| 1925 | INT BuffSize ; | ||
| 1926 | INT ReadOffset = 0; | ||
| 1927 | UINT ReadBytes = 0 ; | ||
| 1928 | PUCHAR pReadBuff; | ||
| 1929 | void __user *OutPutBuff; | ||
| 1930 | |||
| 1931 | if(Adapter->eNVMType != NVM_FLASH) | ||
| 1932 | { | ||
| 1933 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"NVM TYPE is not Flash "); | ||
| 1934 | return -EINVAL ; | ||
| 1935 | } | ||
| 1936 | 1870 | ||
| 1937 | /* Copy Ioctl Buffer structure */ | 1871 | while (NOB) { |
| 1938 | if(copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1872 | if (NOB > DEFAULT_BUFF_SIZE) |
| 1939 | { | 1873 | ReadBytes = DEFAULT_BUFF_SIZE; |
| 1940 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); | 1874 | else |
| 1941 | Status = -EFAULT; | 1875 | ReadBytes = NOB; |
| 1942 | break; | ||
| 1943 | } | ||
| 1944 | 1876 | ||
| 1945 | if(copy_from_user(&stNVMRead, IoBuffer.OutputBuffer,sizeof(NVM_READWRITE))) | 1877 | /* Reading the data from Flash 2.x */ |
| 1946 | return -EFAULT; | 1878 | Status = BeceemNVMRead(Adapter, (PUINT)pReadBuff, ReadOffset, ReadBytes); |
| 1879 | if (Status) { | ||
| 1880 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Flash 2x read err with Status :%d", Status); | ||
| 1881 | break; | ||
| 1882 | } | ||
| 1947 | 1883 | ||
| 1948 | NOB = stNVMRead.uiNumBytes; | 1884 | BCM_DEBUG_PRINT_BUFFER(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, pReadBuff, ReadBytes); |
| 1949 | //In Raw-Read max Buff size : 64MB | ||
| 1950 | 1885 | ||
| 1951 | if(NOB > DEFAULT_BUFF_SIZE) | 1886 | Status = copy_to_user(OutPutBuff, pReadBuff, ReadBytes); |
| 1952 | BuffSize = DEFAULT_BUFF_SIZE; | 1887 | if (Status) { |
| 1953 | else | 1888 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy to use failed with status :%d", Status); |
| 1954 | BuffSize = NOB ; | 1889 | break; |
| 1890 | } | ||
| 1891 | NOB = NOB - ReadBytes; | ||
| 1892 | if (NOB) { | ||
| 1893 | ReadOffset = ReadOffset + ReadBytes; | ||
| 1894 | OutPutBuff = OutPutBuff + ReadBytes; | ||
| 1895 | } | ||
| 1896 | } | ||
| 1897 | Adapter->bFlashRawRead = FALSE; | ||
| 1898 | up(&Adapter->NVMRdmWrmLock); | ||
| 1899 | kfree(pReadBuff); | ||
| 1900 | break; | ||
| 1901 | } | ||
| 1955 | 1902 | ||
| 1956 | ReadOffset = stNVMRead.uiOffset; | 1903 | case IOCTL_BCM_CNTRLMSG_MASK: { |
| 1957 | OutPutBuff = stNVMRead.pBuffer; | 1904 | ULONG RxCntrlMsgBitMask = 0; |
| 1958 | 1905 | ||
| 1959 | pReadBuff = kzalloc(BuffSize , GFP_KERNEL); | 1906 | /* Copy Ioctl Buffer structure */ |
| 1960 | if(pReadBuff == NULL) | 1907 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); |
| 1961 | { | 1908 | if (Status) { |
| 1962 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); | 1909 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of Ioctl buffer is failed from user space"); |
| 1963 | Status = -ENOMEM; | 1910 | Status = -EFAULT; |
| 1964 | break; | 1911 | break; |
| 1965 | } | 1912 | } |
| 1966 | down(&Adapter->NVMRdmWrmLock); | ||
| 1967 | |||
| 1968 | if((Adapter->IdleMode == TRUE) || | ||
| 1969 | (Adapter->bShutStatus ==TRUE) || | ||
| 1970 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 1971 | { | ||
| 1972 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); | ||
| 1973 | kfree(pReadBuff); | ||
| 1974 | up(&Adapter->NVMRdmWrmLock); | ||
| 1975 | return -EACCES; | ||
| 1976 | } | ||
| 1977 | 1913 | ||
| 1978 | Adapter->bFlashRawRead = TRUE ; | 1914 | if (IoBuffer.InputLength != sizeof(unsigned long)) { |
| 1979 | while(NOB) | 1915 | Status = -EINVAL; |
| 1980 | { | 1916 | break; |
| 1981 | if(NOB > DEFAULT_BUFF_SIZE ) | 1917 | } |
| 1982 | ReadBytes = DEFAULT_BUFF_SIZE; | ||
| 1983 | else | ||
| 1984 | ReadBytes = NOB; | ||
| 1985 | |||
| 1986 | //Reading the data from Flash 2.x | ||
| 1987 | Status = BeceemNVMRead(Adapter,(PUINT)pReadBuff,ReadOffset,ReadBytes); | ||
| 1988 | if(Status) | ||
| 1989 | { | ||
| 1990 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status); | ||
| 1991 | break; | ||
| 1992 | } | ||
| 1993 | 1918 | ||
| 1994 | BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff,ReadBytes); | 1919 | Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength); |
| 1995 | 1920 | if (Status) { | |
| 1996 | Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes); | 1921 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "copy of control bit mask failed from user space"); |
| 1997 | if(Status) | 1922 | Status = -EFAULT; |
| 1998 | { | 1923 | break; |
| 1999 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to use failed with status :%d", Status); | 1924 | } |
| 2000 | break; | 1925 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask); |
| 2001 | } | 1926 | pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask; |
| 2002 | NOB = NOB - ReadBytes; | 1927 | } |
| 2003 | if(NOB) | 1928 | break; |
| 2004 | { | ||
| 2005 | ReadOffset = ReadOffset + ReadBytes ; | ||
| 2006 | OutPutBuff = OutPutBuff + ReadBytes ; | ||
| 2007 | } | ||
| 2008 | 1929 | ||
| 2009 | } | 1930 | case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: { |
| 2010 | Adapter->bFlashRawRead = FALSE ; | 1931 | DEVICE_DRIVER_INFO DevInfo; |
| 2011 | up(&Adapter->NVMRdmWrmLock); | ||
| 2012 | kfree(pReadBuff); | ||
| 2013 | break ; | ||
| 2014 | } | ||
| 2015 | |||
| 2016 | case IOCTL_BCM_CNTRLMSG_MASK: | ||
| 2017 | { | ||
| 2018 | ULONG RxCntrlMsgBitMask = 0 ; | ||
| 2019 | |||
| 2020 | /* Copy Ioctl Buffer structure */ | ||
| 2021 | Status = copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER)); | ||
| 2022 | if(Status) | ||
| 2023 | { | ||
| 2024 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space"); | ||
| 2025 | Status = -EFAULT; | ||
| 2026 | break; | ||
| 2027 | } | ||
| 2028 | 1932 | ||
| 2029 | if (IoBuffer.InputLength != sizeof(unsigned long)) { | 1933 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); |
| 2030 | Status = -EINVAL; | ||
| 2031 | break; | ||
| 2032 | } | ||
| 2033 | 1934 | ||
| 2034 | Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength); | 1935 | DevInfo.MaxRDMBufferSize = BUFFER_4K; |
| 2035 | if(Status) | 1936 | DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START; |
| 2036 | { | 1937 | DevInfo.u32RxAlignmentCorrection = 0; |
| 2037 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space"); | 1938 | DevInfo.u32NVMType = Adapter->eNVMType; |
| 2038 | Status = -EFAULT; | 1939 | DevInfo.u32InterfaceType = BCM_USB; |
| 2039 | break; | ||
| 2040 | } | ||
| 2041 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask); | ||
| 2042 | pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask ; | ||
| 2043 | } | ||
| 2044 | break; | ||
| 2045 | case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: | ||
| 2046 | { | ||
| 2047 | DEVICE_DRIVER_INFO DevInfo; | ||
| 2048 | |||
| 2049 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); | ||
| 2050 | |||
| 2051 | DevInfo.MaxRDMBufferSize = BUFFER_4K; | ||
| 2052 | DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START; | ||
| 2053 | DevInfo.u32RxAlignmentCorrection = 0; | ||
| 2054 | DevInfo.u32NVMType = Adapter->eNVMType; | ||
| 2055 | DevInfo.u32InterfaceType = BCM_USB; | ||
| 2056 | |||
| 2057 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | ||
| 2058 | return -EFAULT; | ||
| 2059 | 1940 | ||
| 2060 | if(IoBuffer.OutputLength < sizeof(DevInfo)) | 1941 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 2061 | return -EINVAL; | 1942 | return -EFAULT; |
| 2062 | 1943 | ||
| 2063 | if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo))) | 1944 | if (IoBuffer.OutputLength < sizeof(DevInfo)) |
| 2064 | return -EFAULT; | 1945 | return -EINVAL; |
| 2065 | } | ||
| 2066 | break ; | ||
| 2067 | 1946 | ||
| 2068 | case IOCTL_BCM_TIME_SINCE_NET_ENTRY: | 1947 | if (copy_to_user(IoBuffer.OutputBuffer, &DevInfo, sizeof(DevInfo))) |
| 2069 | { | 1948 | return -EFAULT; |
| 2070 | ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0}; | 1949 | } |
| 1950 | break; | ||
| 2071 | 1951 | ||
| 2072 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_TIME_SINCE_NET_ENTRY called"); | 1952 | case IOCTL_BCM_TIME_SINCE_NET_ENTRY: { |
| 1953 | ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0}; | ||
| 2073 | 1954 | ||
| 2074 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) | 1955 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_TIME_SINCE_NET_ENTRY called"); |
| 2075 | return -EFAULT; | ||
| 2076 | 1956 | ||
| 2077 | if(IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED)) | 1957 | if (copy_from_user(&IoBuffer, argp, sizeof(IOCTL_BUFFER))) |
| 2078 | return -EINVAL; | 1958 | return -EFAULT; |
| 2079 | 1959 | ||
| 2080 | stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry; | 1960 | if (IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED)) |
| 1961 | return -EINVAL; | ||
| 2081 | 1962 | ||
| 2082 | if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED))) | 1963 | stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = get_seconds() - Adapter->liTimeSinceLastNetEntry; |
| 2083 | return -EFAULT; | ||
| 2084 | 1964 | ||
| 2085 | } | 1965 | if (copy_to_user(IoBuffer.OutputBuffer, &stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED))) |
| 2086 | break; | 1966 | return -EFAULT; |
| 1967 | } | ||
| 1968 | break; | ||
| 2087 | 1969 | ||
| 2088 | case IOCTL_CLOSE_NOTIFICATION: | 1970 | case IOCTL_CLOSE_NOTIFICATION: |
| 2089 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_CLOSE_NOTIFICATION"); | 1971 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_CLOSE_NOTIFICATION"); |
| 2090 | break; | 1972 | break; |
| 2091 | 1973 | ||
| 2092 | default: | 1974 | default: |
| 2093 | pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd); | 1975 | pr_info(DRV_NAME ": unknown ioctl cmd=%#x\n", cmd); |
| 2094 | Status = STATUS_FAILURE; | 1976 | Status = STATUS_FAILURE; |
| 2095 | break; | 1977 | break; |
| 2096 | } | 1978 | } |
| 2097 | return Status; | 1979 | return Status; |
| 2098 | } | 1980 | } |
| @@ -2107,8 +1989,6 @@ static const struct file_operations bcm_fops = { · 8 unmodified lines | |||
| 2107 | .llseek = no_llseek, | 1989 | .llseek = no_llseek, |
| 2108 | }; | 1990 | }; |
| 2109 | 1991 | ||
| 2110 | extern struct class *bcm_class; | ||
| 2111 | |||
| 2112 | int register_control_device_interface(PMINI_ADAPTER Adapter) | 1992 | int register_control_device_interface(PMINI_ADAPTER Adapter) |
| 2113 | { | 1993 | { |
| 2114 | 1994 | ||
| @@ -2122,8 +2002,8 @@ int register_control_device_interface(PMINI_ADAPTER Adapter) · 7 unmodified lines | |||
| 2122 | } | 2002 | } |
| 2123 | 2003 | ||
| 2124 | Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL, | 2004 | Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL, |
| 2125 | MKDEV(Adapter->major, 0), | 2005 | MKDEV(Adapter->major, 0), |
| 2126 | Adapter, DEV_NAME); | 2006 | Adapter, DEV_NAME); |
| 2127 | 2007 | ||
| 2128 | if (IS_ERR(Adapter->pstCreatedClassDevice)) { | 2008 | if (IS_ERR(Adapter->pstCreatedClassDevice)) { |
| 2129 | pr_err(DRV_NAME ": class device create failed\n"); | 2009 | pr_err(DRV_NAME ": class device create failed\n"); |
| @@ -2141,3 +2021,4 @@ void unregister_control_device_interface(PMINI_ADAPTER Adapter) · 11 unmodified lines | |||
| 2141 | unregister_chrdev(Adapter->major, DEV_NAME); | 2021 | unregister_chrdev(Adapter->major, DEV_NAME); |
| 2142 | } | 2022 | } |
| 2143 | } | 2023 | } |
| 2024 | |||
| @@ -1,204 +1,183 @@ | |||
| 1 | #include "headers.h" | 1 | #include "headers.h" |
| 2 | 2 | ||
| 3 | 3 | int InterfaceFileDownload(PVOID arg, struct file *flp, unsigned int on_chip_loc) | |
| 4 | int InterfaceFileDownload( PVOID arg, | ||
| 5 | struct file *flp, | ||
| 6 | unsigned int on_chip_loc) | ||
| 7 | { | 4 | { |
| 8 | // unsigned int reg=0; | 5 | /* unsigned int reg = 0; */ |
| 9 | mm_segment_t oldfs={0}; | 6 | mm_segment_t oldfs = {0}; |
| 10 | int errno=0, len=0 /*,is_config_file = 0*/; | 7 | int errno = 0, len = 0; /* ,is_config_file = 0 */ |
| 11 | loff_t pos=0; | 8 | loff_t pos = 0; |
| 12 | PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; | 9 | PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; |
| 13 | //PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; | 10 | /* PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; */ |
| 14 | char *buff=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); | 11 | char *buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); |
| 15 | 12 | ||
| 16 | if(!buff) | 13 | if (!buff) |
| 17 | { | 14 | return -ENOMEM; |
| 18 | return -ENOMEM; | ||
| 19 | } | ||
| 20 | while(1) | ||
| 21 | { | ||
| 22 | oldfs=get_fs(); set_fs(get_ds()); | ||
| 23 | len=vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos); | ||
| 24 | set_fs(oldfs); | ||
| 25 | if(len<=0) | ||
| 26 | { | ||
| 27 | if(len<0) | ||
| 28 | { | ||
| 29 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0"); | ||
| 30 | errno=len; | ||
| 31 | } | ||
| 32 | else | ||
| 33 | { | ||
| 34 | errno = 0; | ||
| 35 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!"); | ||
| 36 | } | ||
| 37 | break; | ||
| 38 | } | ||
| 39 | //BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, buff, MAX_TRANSFER_CTRL_BYTE_USB); | ||
| 40 | errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len) ; | ||
| 41 | if(errno) | ||
| 42 | { | ||
| 43 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed! status: %d", errno); | ||
| 44 | break; | ||
| 45 | 15 | ||
| 16 | while (1) { | ||
| 17 | oldfs = get_fs(); | ||
| 18 | set_fs(get_ds()); | ||
| 19 | len = vfs_read(flp, (void __force __user *)buff, | ||
| 20 | MAX_TRANSFER_CTRL_BYTE_USB, &pos); | ||
| 21 | set_fs(oldfs); | ||
| 22 | if (len <= 0) { | ||
| 23 | if (len < 0) { | ||
| 24 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, | ||
| 25 | DBG_TYPE_INITEXIT, MP_INIT, | ||
| 26 | DBG_LVL_ALL, "len < 0"); | ||
| 27 | errno = len; | ||
| 28 | } else { | ||
| 29 | errno = 0; | ||
| 30 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, | ||
| 31 | DBG_TYPE_INITEXIT, MP_INIT, | ||
| 32 | DBG_LVL_ALL, | ||
| 33 | "Got end of file!"); | ||
| 34 | } | ||
| 35 | break; | ||
| 46 | } | 36 | } |
| 47 | on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB; | 37 | /* BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT, |
| 48 | }/* End of for(;;)*/ | 38 | * DBG_LVL_ALL, buff, |
| 39 | * MAX_TRANSFER_CTRL_BYTE_USB); | ||
| 40 | */ | ||
| 41 | errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len); | ||
| 42 | if (errno) { | ||
| 43 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, | ||
| 44 | DBG_TYPE_PRINTK, 0, 0, | ||
| 45 | "WRM Failed! status: %d", errno); | ||
| 46 | break; | ||
| 47 | } | ||
| 48 | on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB; | ||
| 49 | } | ||
| 49 | 50 | ||
| 50 | kfree(buff); | 51 | kfree(buff); |
| 51 | return errno; | 52 | return errno; |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | int InterfaceFileReadbackFromChip( PVOID arg, | 55 | int InterfaceFileReadbackFromChip(PVOID arg, struct file *flp, unsigned int on_chip_loc) |
| 55 | struct file *flp, | ||
| 56 | unsigned int on_chip_loc) | ||
| 57 | { | 56 | { |
| 58 | char *buff, *buff_readback; | 57 | char *buff, *buff_readback; |
| 59 | unsigned int reg=0; | 58 | unsigned int reg = 0; |
| 60 | mm_segment_t oldfs={0}; | 59 | mm_segment_t oldfs = {0}; |
| 61 | int errno=0, len=0, is_config_file = 0; | 60 | int errno = 0, len = 0, is_config_file = 0; |
| 62 | loff_t pos=0; | 61 | loff_t pos = 0; |
| 63 | static int fw_down = 0; | 62 | static int fw_down; |
| 64 | INT Status = STATUS_SUCCESS; | 63 | INT Status = STATUS_SUCCESS; |
| 65 | PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; | 64 | PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; |
| 66 | 65 | ||
| 67 | buff=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA); | 66 | buff = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA); |
| 68 | buff_readback=kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA); | 67 | buff_readback = kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA); |
| 69 | if(!buff || !buff_readback) | 68 | if (!buff || !buff_readback) { |
| 70 | { | 69 | kfree(buff); |
| 71 | kfree(buff); | 70 | kfree(buff_readback); |
| 72 | kfree(buff_readback); | ||
| 73 | 71 | ||
| 74 | return -ENOMEM; | 72 | return -ENOMEM; |
| 75 | } | 73 | } |
| 76 | 74 | ||
| 77 | is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR)? 1:0; | 75 | is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR) ? 1 : 0; |
| 78 | 76 | ||
| 79 | memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB); | 77 | memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB); |
| 80 | memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB); | 78 | memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB); |
| 81 | while(1) | 79 | while (1) { |
| 82 | { | 80 | oldfs = get_fs(); |
| 83 | oldfs=get_fs(); set_fs(get_ds()); | 81 | set_fs(get_ds()); |
| 84 | len=vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos); | 82 | len = vfs_read(flp, (void __force __user *)buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos); |
| 85 | set_fs(oldfs); | 83 | set_fs(oldfs); |
| 86 | fw_down++; | 84 | fw_down++; |
| 87 | if(len<=0) | 85 | |
| 88 | { | 86 | if (len <= 0) { |
| 89 | if(len<0) | 87 | if (len < 0) { |
| 90 | { | 88 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0"); |
| 91 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0"); | 89 | errno = len; |
| 92 | errno=len; | 90 | } else { |
| 93 | } | 91 | errno = 0; |
| 94 | else | 92 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!"); |
| 95 | { | 93 | } |
| 96 | errno = 0; | 94 | break; |
| 97 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!"); | 95 | } |
| 98 | } | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | |||
| 102 | 96 | ||
| 103 | Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len); | 97 | Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len); |
| 104 | if(Status) | 98 | if (Status) { |
| 105 | { | 99 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg); |
| 106 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg); | ||
| 107 | goto exit; | 100 | goto exit; |
| 108 | } | 101 | } |
| 109 | reg++; | 102 | reg++; |
| 110 | if((len-sizeof(unsigned int))<4) | 103 | if ((len-sizeof(unsigned int)) < 4) { |
| 111 | { | 104 | if (memcmp(buff_readback, buff, len)) { |
| 112 | if(memcmp(buff_readback, buff, len)) | 105 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); |
| 113 | { | 106 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Length is: %d", len); |
| 114 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); | ||
| 115 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT,DBG_LVL_ALL,"Length is: %d",len); | ||
| 116 | Status = -EIO; | 107 | Status = -EIO; |
| 117 | goto exit; | 108 | goto exit; |
| 118 | } | 109 | } |
| 119 | } | 110 | } else { |
| 120 | else | 111 | len -= 4; |
| 121 | { | 112 | |
| 122 | len-=4; | 113 | while (len) { |
| 123 | while(len) | 114 | if (*(unsigned int *)&buff_readback[len] != *(unsigned int *)&buff[len]) { |
| 124 | { | 115 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); |
| 125 | if(*(unsigned int*)&buff_readback[len] != *(unsigned int *)&buff[len]) | 116 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]); |
| 126 | { | 117 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len); |
| 127 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); | ||
| 128 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]); | ||
| 129 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len); | ||
| 130 | Status = -EIO; | 118 | Status = -EIO; |
| 131 | goto exit; | 119 | goto exit; |
| 132 | } | 120 | } |
| 133 | len-=4; | 121 | len -= 4; |
| 134 | } | 122 | } |
| 135 | } | 123 | } |
| 136 | on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB; | 124 | on_chip_loc += MAX_TRANSFER_CTRL_BYTE_USB; |
| 137 | }/* End of while(1)*/ | 125 | } /* End of while(1) */ |
| 126 | |||
| 138 | exit: | 127 | exit: |
| 139 | kfree(buff); | 128 | kfree(buff); |
| 140 | kfree(buff_readback); | 129 | kfree(buff_readback); |
| 141 | return Status; | 130 | return Status; |
| 142 | } | 131 | } |
| 143 | 132 | ||
| 144 | static int bcm_download_config_file(PMINI_ADAPTER Adapter, | 133 | static int bcm_download_config_file(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) |
| 145 | FIRMWARE_INFO *psFwInfo) | ||
| 146 | { | 134 | { |
| 147 | int retval = STATUS_SUCCESS; | 135 | int retval = STATUS_SUCCESS; |
| 148 | B_UINT32 value = 0; | 136 | B_UINT32 value = 0; |
| 149 | 137 | ||
| 150 | if(Adapter->pstargetparams == NULL) | 138 | if (Adapter->pstargetparams == NULL) { |
| 151 | { | 139 | Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL); |
| 152 | if((Adapter->pstargetparams = | 140 | if (Adapter->pstargetparams == NULL) |
| 153 | kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL) | 141 | return -ENOMEM; |
| 154 | { | ||
| 155 | return -ENOMEM; | ||
| 156 | } | ||
| 157 | } | ||
| 158 | if(psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS)) | ||
| 159 | { | ||
| 160 | return -EIO; | ||
| 161 | } | 142 | } |
| 162 | retval = copy_from_user(Adapter->pstargetparams, | 143 | |
| 163 | psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); | 144 | if (psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS)) |
| 164 | if(retval) | 145 | return -EIO; |
| 165 | { | 146 | |
| 147 | retval = copy_from_user(Adapter->pstargetparams, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); | ||
| 148 | if (retval) { | ||
| 166 | kfree(Adapter->pstargetparams); | 149 | kfree(Adapter->pstargetparams); |
| 167 | Adapter->pstargetparams = NULL; | 150 | Adapter->pstargetparams = NULL; |
| 168 | return -EFAULT; | 151 | return -EFAULT; |
| 169 | } | 152 | } |
| 153 | |||
| 170 | /* Parse the structure and then Download the Firmware */ | 154 | /* Parse the structure and then Download the Firmware */ |
| 171 | beceem_parse_target_struct(Adapter); | 155 | beceem_parse_target_struct(Adapter); |
| 172 | 156 | ||
| 173 | //Initializing the NVM. | 157 | /* Initializing the NVM. */ |
| 174 | BcmInitNVM(Adapter); | 158 | BcmInitNVM(Adapter); |
| 159 | retval = InitLedSettings(Adapter); | ||
| 175 | 160 | ||
| 176 | retval = InitLedSettings (Adapter); | 161 | if (retval) { |
| 177 | 162 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n"); | |
| 178 | if(retval) | ||
| 179 | { | ||
| 180 | BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n"); | ||
| 181 | return retval; | 163 | return retval; |
| 182 | } | 164 | } |
| 183 | 165 | ||
| 184 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 166 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 185 | { | ||
| 186 | Adapter->LEDInfo.bLedInitDone = FALSE; | 167 | Adapter->LEDInfo.bLedInitDone = FALSE; |
| 187 | Adapter->DriverState = DRIVER_INIT; | 168 | Adapter->DriverState = DRIVER_INIT; |
| 188 | wake_up(&Adapter->LEDInfo.notify_led_event); | 169 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 189 | } | 170 | } |
| 190 | 171 | ||
| 191 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 172 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 192 | { | ||
| 193 | Adapter->DriverState = FW_DOWNLOAD; | 173 | Adapter->DriverState = FW_DOWNLOAD; |
| 194 | wake_up(&Adapter->LEDInfo.notify_led_event); | 174 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 195 | } | 175 | } |
| 196 | 176 | ||
| 197 | /* Initialize the DDR Controller */ | 177 | /* Initialize the DDR Controller */ |
| 198 | retval = ddr_init(Adapter); | 178 | retval = ddr_init(Adapter); |
| 199 | if(retval) | 179 | if (retval) { |
| 200 | { | 180 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n"); |
| 201 | BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n"); | ||
| 202 | return retval; | 181 | return retval; |
| 203 | } | 182 | } |
| 204 | 183 | ||
| @@ -206,197 +185,166 @@ static int bcm_download_config_file(PMINI_ADAPTER Adapter, · 1 unmodified line | |||
| 206 | wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); | 185 | wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); |
| 207 | wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); | 186 | wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); |
| 208 | 187 | ||
| 209 | if(Adapter->eNVMType == NVM_FLASH) | 188 | if (Adapter->eNVMType == NVM_FLASH) { |
| 210 | { | ||
| 211 | retval = PropagateCalParamsFromFlashToMemory(Adapter); | 189 | retval = PropagateCalParamsFromFlashToMemory(Adapter); |
| 212 | if(retval) | 190 | if (retval) { |
| 213 | { | 191 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "propagaion of cal param failed with status :%d", retval); |
| 214 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"propagaion of cal param failed with status :%d", retval); | ||
| 215 | return retval; | 192 | return retval; |
| 216 | } | 193 | } |
| 217 | } | 194 | } |
| 218 | 195 | ||
| 196 | retval = buffDnldVerify(Adapter, (PUCHAR)Adapter->pstargetparams, sizeof(STARGETPARAMS), CONFIG_BEGIN_ADDR); | ||
| 219 | 197 | ||
| 220 | retval =buffDnldVerify(Adapter,(PUCHAR)Adapter->pstargetparams,sizeof(STARGETPARAMS),CONFIG_BEGIN_ADDR); | 198 | if (retval) |
| 221 | 199 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly"); | |
| 222 | if(retval) | ||
| 223 | { | ||
| 224 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly"); | ||
| 225 | } | ||
| 226 | else | 200 | else |
| 227 | Adapter->bCfgDownloaded = TRUE; | 201 | Adapter->bCfgDownloaded = TRUE; |
| 228 | 202 | ||
| 229 | |||
| 230 | return retval; | 203 | return retval; |
| 231 | } | 204 | } |
| 232 | static int bcm_compare_buff_contents(unsigned char *readbackbuff, | 205 | |
| 233 | unsigned char *buff,unsigned int len) | 206 | static int bcm_compare_buff_contents(unsigned char *readbackbuff, unsigned char *buff, unsigned int len) |
| 234 | { | 207 | { |
| 235 | int retval = STATUS_SUCCESS; | 208 | int retval = STATUS_SUCCESS; |
| 236 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); | 209 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); |
| 237 | if((len-sizeof(unsigned int))<4) | 210 | if ((len-sizeof(unsigned int)) < 4) { |
| 238 | { | 211 | if (memcmp(readbackbuff , buff, len)) |
| 239 | if(memcmp(readbackbuff , buff, len)) | 212 | retval = -EINVAL; |
| 240 | { | 213 | } else { |
| 241 | retval=-EINVAL; | 214 | len -= 4; |
| 242 | } | 215 | |
| 243 | } | 216 | while (len) { |
| 244 | else | 217 | if (*(unsigned int *)&readbackbuff[len] != *(unsigned int *)&buff[len]) { |
| 245 | { | 218 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper"); |
| 246 | len-=4; | 219 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]); |
| 247 | while(len) | 220 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len); |
| 248 | { | 221 | retval = -EINVAL; |
| 249 | if(*(unsigned int*)&readbackbuff[len] != | ||
| 250 | *(unsigned int *)&buff[len]) | ||
| 251 | { | ||
| 252 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper"); | ||
| 253 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]); | ||
| 254 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len); | ||
| 255 | retval=-EINVAL; | ||
| 256 | break; | 222 | break; |
| 257 | } | 223 | } |
| 258 | len-=4; | 224 | len -= 4; |
| 259 | } | 225 | } |
| 260 | } | 226 | } |
| 261 | return retval; | 227 | return retval; |
| 262 | } | 228 | } |
| 229 | |||
| 263 | int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) | 230 | int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) |
| 264 | { | 231 | { |
| 265 | int retval = STATUS_SUCCESS; | 232 | int retval = STATUS_SUCCESS; |
| 266 | PUCHAR buff = NULL; | 233 | PUCHAR buff = NULL; |
| 267 | 234 | ||
| 268 | /* Config File is needed for the Driver to download the Config file and | 235 | /* Config File is needed for the Driver to download the Config file and |
| 269 | Firmware. Check for the Config file to be first to be sent from the | 236 | * Firmware. Check for the Config file to be first to be sent from the |
| 270 | Application | 237 | * Application |
| 271 | */ | 238 | */ |
| 272 | atomic_set (&Adapter->uiMBupdate, FALSE); | 239 | atomic_set(&Adapter->uiMBupdate, FALSE); |
| 273 | if(!Adapter->bCfgDownloaded && | 240 | if (!Adapter->bCfgDownloaded && psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) { |
| 274 | psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) | 241 | /* Can't Download Firmware. */ |
| 275 | { | 242 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Download the config File first\n"); |
| 276 | /*Can't Download Firmware.*/ | ||
| 277 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Download the config File first\n"); | ||
| 278 | return -EINVAL; | 243 | return -EINVAL; |
| 279 | } | 244 | } |
| 280 | 245 | ||
| 281 | /* If Config File, Finish the DDR Settings and then Download CFG File */ | 246 | /* If Config File, Finish the DDR Settings and then Download CFG File */ |
| 282 | if(psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) | 247 | if (psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) { |
| 283 | { | 248 | retval = bcm_download_config_file(Adapter, psFwInfo); |
| 284 | retval = bcm_download_config_file (Adapter, psFwInfo); | 249 | } else { |
| 285 | } | 250 | buff = kzalloc(psFwInfo->u32FirmwareLength, GFP_KERNEL); |
| 286 | else | 251 | if (buff == NULL) { |
| 287 | { | 252 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed in allocation memory"); |
| 288 | |||
| 289 | buff = kzalloc(psFwInfo->u32FirmwareLength,GFP_KERNEL); | ||
| 290 | if(buff==NULL) | ||
| 291 | { | ||
| 292 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Failed in allocation memory"); | ||
| 293 | return -ENOMEM; | 253 | return -ENOMEM; |
| 294 | } | 254 | } |
| 295 | retval = copy_from_user(buff,psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); | 255 | |
| 296 | if(retval != STATUS_SUCCESS) | 256 | retval = copy_from_user(buff, psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); |
| 297 | { | 257 | if (retval != STATUS_SUCCESS) { |
| 298 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed"); | 258 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed"); |
| 299 | retval = -EFAULT; | 259 | retval = -EFAULT; |
| 300 | goto error ; | 260 | goto error; |
| 301 | } | 261 | } |
| 302 | 262 | ||
| 303 | retval = buffDnldVerify(Adapter, | 263 | retval = buffDnldVerify(Adapter, |
| 304 | buff, | 264 | buff, |
| 305 | psFwInfo->u32FirmwareLength, | 265 | psFwInfo->u32FirmwareLength, |
| 306 | psFwInfo->u32StartingAddress); | 266 | psFwInfo->u32StartingAddress); |
| 307 | if(retval != STATUS_SUCCESS) | 267 | |
| 308 | { | 268 | if (retval != STATUS_SUCCESS) { |
| 309 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"f/w download failed status :%d", retval); | 269 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "f/w download failed status :%d", retval); |
| 310 | goto error; | 270 | goto error; |
| 311 | } | 271 | } |
| 312 | } | 272 | } |
| 273 | |||
| 313 | error: | 274 | error: |
| 314 | kfree(buff); | 275 | kfree(buff); |
| 315 | return retval; | 276 | return retval; |
| 316 | } | 277 | } |
| 317 | 278 | ||
| 318 | static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, | 279 | static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) |
| 319 | ULONG u32StartingAddress) | ||
| 320 | { | 280 | { |
| 321 | 281 | unsigned int len = 0; | |
| 322 | unsigned int len = 0; | ||
| 323 | int retval = STATUS_SUCCESS; | 282 | int retval = STATUS_SUCCESS; |
| 324 | len = u32FirmwareLength; | 283 | len = u32FirmwareLength; |
| 325 | 284 | ||
| 326 | while(u32FirmwareLength) | 285 | while (u32FirmwareLength) { |
| 327 | { | 286 | len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); |
| 328 | len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); | 287 | retval = wrm(Adapter, u32StartingAddress, mappedbuffer, len); |
| 329 | retval = wrm (Adapter, u32StartingAddress, mappedbuffer, len); | 288 | |
| 330 | if(retval) | 289 | if (retval) { |
| 331 | { | 290 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval); |
| 332 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval); | ||
| 333 | break; | 291 | break; |
| 334 | } | 292 | } |
| 335 | u32StartingAddress += len; | 293 | u32StartingAddress += len; |
| 336 | u32FirmwareLength -= len; | 294 | u32FirmwareLength -= len; |
| 337 | mappedbuffer +=len; | 295 | mappedbuffer += len; |
| 338 | } | 296 | } |
| 339 | return retval; | 297 | return retval; |
| 340 | |||
| 341 | } | 298 | } |
| 342 | 299 | ||
| 343 | static INT buffRdbkVerify(PMINI_ADAPTER Adapter, | 300 | static INT buffRdbkVerify(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, ULONG u32StartingAddress) |
| 344 | PUCHAR mappedbuffer, UINT u32FirmwareLength, | ||
| 345 | ULONG u32StartingAddress) | ||
| 346 | { | 301 | { |
| 347 | UINT len = u32FirmwareLength; | 302 | UINT len = u32FirmwareLength; |
| 348 | INT retval = STATUS_SUCCESS; | 303 | INT retval = STATUS_SUCCESS; |
| 349 | PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB,GFP_KERNEL); | 304 | PUCHAR readbackbuff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); |
| 350 | 305 | ||
| 351 | if(NULL == readbackbuff) | 306 | if (NULL == readbackbuff) { |
| 352 | { | 307 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED"); |
| 353 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED"); | ||
| 354 | return -ENOMEM; | 308 | return -ENOMEM; |
| 355 | } | 309 | } |
| 356 | while (u32FirmwareLength && !retval) | ||
| 357 | { | ||
| 358 | 310 | ||
| 359 | len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); | 311 | while (u32FirmwareLength && !retval) { |
| 312 | len = MIN_VAL(u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); | ||
| 313 | retval = rdm(Adapter, u32StartingAddress, readbackbuff, len); | ||
| 360 | 314 | ||
| 361 | retval = rdm (Adapter, u32StartingAddress, readbackbuff, len); | 315 | if (retval) { |
| 362 | if(retval) | 316 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d", retval); |
| 363 | { | ||
| 364 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d" ,retval); | ||
| 365 | break; | 317 | break; |
| 366 | } | 318 | } |
| 367 | 319 | ||
| 368 | if (STATUS_SUCCESS != (retval = bcm_compare_buff_contents (readbackbuff, mappedbuffer, len))) | 320 | retval = bcm_compare_buff_contents(readbackbuff, mappedbuffer, len); |
| 369 | { | 321 | if (STATUS_SUCCESS != retval) |
| 370 | break; | 322 | break; |
| 371 | } | 323 | |
| 372 | u32StartingAddress += len; | 324 | u32StartingAddress += len; |
| 373 | u32FirmwareLength -= len; | 325 | u32FirmwareLength -= len; |
| 374 | mappedbuffer +=len; | 326 | mappedbuffer += len; |
| 375 | }/* end of while (u32FirmwareLength && !retval) */ | 327 | |
| 328 | } /* end of while (u32FirmwareLength && !retval) */ | ||
| 376 | kfree(readbackbuff); | 329 | kfree(readbackbuff); |
| 377 | return retval; | 330 | return retval; |
| 378 | } | 331 | } |
| 379 | 332 | ||
| 380 | INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, | 333 | INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, unsigned long u32StartingAddress) |
| 381 | unsigned long u32StartingAddress) | ||
| 382 | { | 334 | { |
| 383 | INT status = STATUS_SUCCESS; | 335 | INT status = STATUS_SUCCESS; |
| 384 | 336 | ||
| 385 | status = buffDnld(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress); | 337 | status = buffDnld(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress); |
| 386 | if(status != STATUS_SUCCESS) | 338 | if (status != STATUS_SUCCESS) { |
| 387 | { | 339 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer download failed"); |
| 388 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer download failed"); | ||
| 389 | goto error; | 340 | goto error; |
| 390 | } | 341 | } |
| 391 | 342 | ||
| 392 | status= buffRdbkVerify(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress); | 343 | status = buffRdbkVerify(Adapter, mappedbuffer, u32FirmwareLength, u32StartingAddress); |
| 393 | if(status != STATUS_SUCCESS) | 344 | if (status != STATUS_SUCCESS) { |
| 394 | { | 345 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Buffer readback verifier failed"); |
| 395 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer readback verifier failed"); | ||
| 396 | goto error; | 346 | goto error; |
| 397 | } | 347 | } |
| 398 | error: | 348 | error: |
| 399 | return status; | 349 | return status; |
| 400 | } | 350 | } |
| 401 | |||
| 402 | |||
| @@ -139,8 +139,7 @@ static void ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) · 138 unmodified lines | |||
| 139 | BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C2, 4, TRUE); | 139 | BeceemEEPROMBulkWrite(Adapter, (PUCHAR)&ulReg, 0x1C2, 4, TRUE); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static int | 142 | static int usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) |
| 143 | usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) | ||
| 144 | { | 143 | { |
| 145 | struct usb_device *udev = interface_to_usbdev(intf); | 144 | struct usb_device *udev = interface_to_usbdev(intf); |
| 146 | int retval; | 145 | int retval; |
| @@ -281,8 +280,9 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter) · 134 unmodified lines | |||
| 281 | int i = 0; | 280 | int i = 0; |
| 282 | 281 | ||
| 283 | for (i = 0; i < MAXIMUM_USB_TCB; i++) { | 282 | for (i = 0; i < MAXIMUM_USB_TCB; i++) { |
| 284 | if ((psIntfAdapter->asUsbTcb[i].urb = | 283 | psIntfAdapter->asUsbTcb[i].urb = usb_alloc_urb(0, GFP_KERNEL); |
| 285 | usb_alloc_urb(0, GFP_KERNEL)) == NULL) { | 284 | |
| 285 | if (psIntfAdapter->asUsbTcb[i].urb == NULL) { | ||
| 286 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, | 286 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, |
| 287 | "Can't allocate Tx urb for index %d\n", i); | 287 | "Can't allocate Tx urb for index %d\n", i); |
| 288 | return -ENOMEM; | 288 | return -ENOMEM; |
| @@ -290,14 +290,17 @@ static int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter) · 1 unmodified line | |||
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | for (i = 0; i < MAXIMUM_USB_RCB; i++) { | 292 | for (i = 0; i < MAXIMUM_USB_RCB; i++) { |
| 293 | if ((psIntfAdapter->asUsbRcb[i].urb = | 293 | psIntfAdapter->asUsbRcb[i].urb = usb_alloc_urb(0, GFP_KERNEL); |
| 294 | usb_alloc_urb(0, GFP_KERNEL)) == NULL) { | 294 | |
| 295 | if (psIntfAdapter->asUsbRcb[i].urb == NULL) { | ||
| 295 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, | 296 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, |
| 296 | "Can't allocate Rx urb for index %d\n", i); | 297 | "Can't allocate Rx urb for index %d\n", i); |
| 297 | return -ENOMEM; | 298 | return -ENOMEM; |
| 298 | } | 299 | } |
| 299 | if ((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer = | 300 | |
| 300 | kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL) { | 301 | psIntfAdapter->asUsbRcb[i].urb->transfer_buffer = kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL); |
| 302 | |||
| 303 | if (psIntfAdapter->asUsbRcb[i].urb->transfer_buffer == NULL) { | ||
| 301 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, | 304 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, |
| 302 | "Can't allocate Rx buffer for index %d\n", i); | 305 | "Can't allocate Rx buffer for index %d\n", i); |
| 303 | return -ENOMEM; | 306 | return -ENOMEM; |
| @@ -389,32 +392,32 @@ static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descripto · 85 unmodified lines | |||
| 389 | 392 | ||
| 390 | static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) | 393 | static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) |
| 391 | { | 394 | { |
| 392 | return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd)); | 395 | return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd); |
| 393 | } | 396 | } |
| 394 | 397 | ||
| 395 | static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) | 398 | static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) |
| 396 | { | 399 | { |
| 397 | return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd)); | 400 | return bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd); |
| 398 | } | 401 | } |
| 399 | 402 | ||
| 400 | static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) | 403 | static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) |
| 401 | { | 404 | { |
| 402 | return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd)); | 405 | return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd); |
| 403 | } | 406 | } |
| 404 | 407 | ||
| 405 | static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) | 408 | static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) |
| 406 | { | 409 | { |
| 407 | return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd)); | 410 | return bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd); |
| 408 | } | 411 | } |
| 409 | 412 | ||
| 410 | static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) | 413 | static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) |
| 411 | { | 414 | { |
| 412 | return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd)); | 415 | return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd); |
| 413 | } | 416 | } |
| 414 | 417 | ||
| 415 | static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) | 418 | static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) |
| 416 | { | 419 | { |
| 417 | return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd)); | 420 | return bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd); |
| 418 | } | 421 | } |
| 419 | 422 | ||
| 420 | static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) | 423 | static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) |
| @@ -462,7 +465,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) · 41 unmodified lines | |||
| 462 | if (bBcm16 == TRUE) { | 465 | if (bBcm16 == TRUE) { |
| 463 | /* selecting alternate setting one as a default setting for High Speed modem. */ | 466 | /* selecting alternate setting one as a default setting for High Speed modem. */ |
| 464 | if (psIntfAdapter->bHighSpeedDevice) | 467 | if (psIntfAdapter->bHighSpeedDevice) |
| 465 | retval= usb_set_interface(psIntfAdapter->udev, DEFAULT_SETTING_0, ALTERNATE_SETTING_1); | 468 | retval = usb_set_interface(psIntfAdapter->udev, DEFAULT_SETTING_0, ALTERNATE_SETTING_1); |
| 466 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, | 469 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, |
| 467 | "BCM16 is applicable on this dongle\n"); | 470 | "BCM16 is applicable on this dongle\n"); |
| 468 | if (retval || (psIntfAdapter->bHighSpeedDevice == FALSE)) { | 471 | if (retval || (psIntfAdapter->bHighSpeedDevice == FALSE)) { |
| @@ -497,7 +500,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) · 28 unmodified lines | |||
| 497 | if ((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint)) { | 500 | if ((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint)) { |
| 498 | /* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */ | 501 | /* Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. */ |
| 499 | UINT _uiData = ntohl(EP2_CFG_INT); | 502 | UINT _uiData = ntohl(EP2_CFG_INT); |
| 500 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, | 503 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, |
| 501 | "Reverting Bulk to INT as it is in Full Speed mode.\n"); | 504 | "Reverting Bulk to INT as it is in Full Speed mode.\n"); |
| 502 | BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter, (PUCHAR)&_uiData, 0x136, 4, TRUE); | 505 | BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter, (PUCHAR)&_uiData, 0x136, 4, TRUE); |
| 503 | } | 506 | } |
| @@ -579,7 +582,7 @@ static int InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) · 75 unmodified lines | |||
| 579 | psIntfAdapter->sIntrOut.int_out_size = buffer_size; | 582 | psIntfAdapter->sIntrOut.int_out_size = buffer_size; |
| 580 | psIntfAdapter->sIntrOut.int_out_endpointAddr = endpoint->bEndpointAddress; | 583 | psIntfAdapter->sIntrOut.int_out_endpointAddr = endpoint->bEndpointAddress; |
| 581 | psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval; | 584 | psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval; |
| 582 | psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size, GFP_KERNEL); | 585 | psIntfAdapter->sIntrOut.int_out_buffer = kmalloc(buffer_size, GFP_KERNEL); |
| 583 | if (!psIntfAdapter->sIntrOut.int_out_buffer) { | 586 | if (!psIntfAdapter->sIntrOut.int_out_buffer) { |
| 584 | dev_err(&psIntfAdapter->udev->dev, | 587 | dev_err(&psIntfAdapter->udev->dev, |
| 585 | "could not allocate interrupt_out_buffer\n"); | 588 | "could not allocate interrupt_out_buffer\n"); |
| @@ -641,8 +644,8 @@ static int InterfaceSuspend(struct usb_interface *intf, pm_message_t message) · 55 unmodified lines | |||
| 641 | static int InterfaceResume(struct usb_interface *intf) | 644 | static int InterfaceResume(struct usb_interface *intf) |
| 642 | { | 645 | { |
| 643 | PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); | 646 | PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); |
| 644 | mdelay(100); | ||
| 645 | 647 | ||
| 648 | mdelay(100); | ||
| 646 | psIntfAdapter->bSuspended = FALSE; | 649 | psIntfAdapter->bSuspended = FALSE; |
| 647 | 650 | ||
| 648 | StartInterruptUrb(psIntfAdapter); | 651 | StartInterruptUrb(psIntfAdapter); |
| @@ -1,246 +1,219 @@ | |||
| 1 | #include "headers.h" | 1 | #include "headers.h" |
| 2 | 2 | ||
| 3 | INT | 3 | INT InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, |
| 4 | InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, | 4 | UINT addr, |
| 5 | UINT addr, | 5 | PVOID buff, |
| 6 | PVOID buff, | 6 | INT len) |
| 7 | INT len) | ||
| 8 | { | 7 | { |
| 9 | int retval = 0; | 8 | int retval = 0; |
| 10 | USHORT usRetries = 0 ; | 9 | USHORT usRetries = 0; |
| 11 | if(psIntfAdapter == NULL ) | 10 | |
| 12 | { | 11 | if (psIntfAdapter == NULL) { |
| 13 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Interface Adapter is NULL"); | 12 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); |
| 14 | return -EINVAL ; | 13 | return -EINVAL; |
| 15 | } | 14 | } |
| 16 | 15 | ||
| 17 | if(psIntfAdapter->psAdapter->device_removed == TRUE) | 16 | if (psIntfAdapter->psAdapter->device_removed == TRUE) { |
| 18 | { | 17 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed"); |
| 19 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed"); | ||
| 20 | return -ENODEV; | 18 | return -ENODEV; |
| 21 | } | 19 | } |
| 22 | 20 | ||
| 23 | if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) | 21 | if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) { |
| 24 | { | 22 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus"); |
| 25 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus"); | ||
| 26 | return -EACCES; | 23 | return -EACCES; |
| 27 | } | 24 | } |
| 28 | 25 | ||
| 29 | if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) | 26 | if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) { |
| 30 | { | 27 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed.."); |
| 31 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed.."); | ||
| 32 | return -EACCES; | 28 | return -EACCES; |
| 33 | } | 29 | } |
| 34 | psIntfAdapter->psAdapter->DeviceAccess = TRUE ; | 30 | psIntfAdapter->psAdapter->DeviceAccess = TRUE; |
| 31 | |||
| 35 | do { | 32 | do { |
| 36 | retval = usb_control_msg(psIntfAdapter->udev, | 33 | retval = usb_control_msg(psIntfAdapter->udev, |
| 37 | usb_rcvctrlpipe(psIntfAdapter->udev,0), | 34 | usb_rcvctrlpipe(psIntfAdapter->udev, 0), |
| 38 | 0x02, | 35 | 0x02, |
| 39 | 0xC2, | 36 | 0xC2, |
| 40 | (addr & 0xFFFF), | 37 | (addr & 0xFFFF), |
| 41 | ((addr >> 16) & 0xFFFF), | 38 | ((addr >> 16) & 0xFFFF), |
| 42 | buff, | 39 | buff, |
| 43 | len, | 40 | len, |
| 44 | 5000); | 41 | 5000); |
| 45 | 42 | ||
| 46 | usRetries++ ; | 43 | usRetries++; |
| 47 | if(-ENODEV == retval) | 44 | if (-ENODEV == retval) { |
| 48 | { | 45 | psIntfAdapter->psAdapter->device_removed = TRUE; |
| 49 | psIntfAdapter->psAdapter->device_removed =TRUE; | ||
| 50 | break; | 46 | break; |
| 51 | } | 47 | } |
| 52 | 48 | ||
| 53 | }while((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES ) ); | 49 | } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES)); |
| 54 | 50 | ||
| 55 | if(retval < 0) | 51 | if (retval < 0) { |
| 56 | { | 52 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval, usRetries); |
| 57 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval,usRetries); | 53 | psIntfAdapter->psAdapter->DeviceAccess = FALSE; |
| 58 | psIntfAdapter->psAdapter->DeviceAccess = FALSE ; | 54 | return retval; |
| 59 | return retval; | 55 | } else { |
| 60 | } | 56 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval); |
| 61 | else | 57 | psIntfAdapter->psAdapter->DeviceAccess = FALSE; |
| 62 | { | 58 | return STATUS_SUCCESS; |
| 63 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval); | ||
| 64 | psIntfAdapter->psAdapter->DeviceAccess = FALSE ; | ||
| 65 | return STATUS_SUCCESS; | ||
| 66 | } | 59 | } |
| 67 | } | 60 | } |
| 68 | 61 | ||
| 69 | INT | 62 | INT InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, |
| 70 | InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, | 63 | UINT addr, |
| 71 | UINT addr, | 64 | PVOID buff, |
| 72 | PVOID buff, | 65 | INT len) |
| 73 | INT len) | ||
| 74 | { | 66 | { |
| 75 | int retval = 0; | 67 | int retval = 0; |
| 76 | USHORT usRetries = 0 ; | 68 | USHORT usRetries = 0; |
| 77 | 69 | ||
| 78 | if(psIntfAdapter == NULL ) | 70 | if (psIntfAdapter == NULL) { |
| 79 | { | 71 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); |
| 80 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); | ||
| 81 | return -EINVAL; | 72 | return -EINVAL; |
| 82 | } | 73 | } |
| 83 | if(psIntfAdapter->psAdapter->device_removed == TRUE) | ||
| 84 | { | ||
| 85 | 74 | ||
| 86 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed"); | 75 | if (psIntfAdapter->psAdapter->device_removed == TRUE) { |
| 76 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_PRINTK, 0, 0, "Device got removed"); | ||
| 87 | return -ENODEV; | 77 | return -ENODEV; |
| 88 | } | 78 | } |
| 89 | 79 | ||
| 90 | if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) | 80 | if ((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) { |
| 91 | { | 81 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Currently Xaction is not allowed on the bus..."); |
| 92 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus..."); | ||
| 93 | return -EACCES; | 82 | return -EACCES; |
| 94 | } | 83 | } |
| 95 | 84 | ||
| 96 | if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) | 85 | if (psIntfAdapter->bSuspended == TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) { |
| 97 | { | 86 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "Bus is in suspended states hence RDM not allowed.."); |
| 98 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed.."); | ||
| 99 | return -EACCES; | 87 | return -EACCES; |
| 100 | } | 88 | } |
| 101 | psIntfAdapter->psAdapter->DeviceAccess = TRUE ; | 89 | |
| 102 | do{ | 90 | psIntfAdapter->psAdapter->DeviceAccess = TRUE; |
| 91 | |||
| 92 | do { | ||
| 103 | retval = usb_control_msg(psIntfAdapter->udev, | 93 | retval = usb_control_msg(psIntfAdapter->udev, |
| 104 | usb_sndctrlpipe(psIntfAdapter->udev,0), | 94 | usb_sndctrlpipe(psIntfAdapter->udev, 0), |
| 105 | 0x01, | 95 | 0x01, |
| 106 | 0x42, | 96 | 0x42, |
| 107 | (addr & 0xFFFF), | 97 | (addr & 0xFFFF), |
| 108 | ((addr >> 16) & 0xFFFF), | 98 | ((addr >> 16) & 0xFFFF), |
| 109 | buff, | 99 | buff, |
| 110 | len, | 100 | len, |
| 111 | 5000); | 101 | 5000); |
| 112 | 102 | ||
| 113 | usRetries++ ; | 103 | usRetries++; |
| 114 | if(-ENODEV == retval) | 104 | if (-ENODEV == retval) { |
| 115 | { | 105 | psIntfAdapter->psAdapter->device_removed = TRUE; |
| 116 | psIntfAdapter->psAdapter->device_removed = TRUE ; | ||
| 117 | break; | 106 | break; |
| 118 | } | 107 | } |
| 119 | 108 | ||
| 120 | }while((retval < 0) && ( usRetries < MAX_RDM_WRM_RETIRES)); | 109 | } while ((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES)); |
| 121 | 110 | ||
| 122 | if(retval < 0) | 111 | if (retval < 0) { |
| 123 | { | 112 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries); |
| 124 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries); | 113 | psIntfAdapter->psAdapter->DeviceAccess = FALSE; |
| 125 | psIntfAdapter->psAdapter->DeviceAccess = FALSE ; | ||
| 126 | return retval; | 114 | return retval; |
| 127 | } | 115 | } else { |
| 128 | else | 116 | psIntfAdapter->psAdapter->DeviceAccess = FALSE; |
| 129 | { | 117 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter, DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval); |
| 130 | psIntfAdapter->psAdapter->DeviceAccess = FALSE ; | ||
| 131 | BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval); | ||
| 132 | return STATUS_SUCCESS; | 118 | return STATUS_SUCCESS; |
| 133 | |||
| 134 | } | 119 | } |
| 135 | |||
| 136 | } | 120 | } |
| 137 | 121 | ||
| 138 | INT | 122 | INT BcmRDM(PVOID arg, |
| 139 | BcmRDM(PVOID arg, | 123 | UINT addr, |
| 140 | UINT addr, | 124 | PVOID buff, |
| 141 | PVOID buff, | 125 | INT len) |
| 142 | INT len) | ||
| 143 | { | 126 | { |
| 144 | return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); | 127 | return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); |
| 145 | } | 128 | } |
| 146 | 129 | ||
| 147 | INT | 130 | INT BcmWRM(PVOID arg, |
| 148 | BcmWRM(PVOID arg, | 131 | UINT addr, |
| 149 | UINT addr, | 132 | PVOID buff, |
| 150 | PVOID buff, | 133 | INT len) |
| 151 | INT len) | ||
| 152 | { | 134 | { |
| 153 | return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); | 135 | return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); |
| 154 | } | 136 | } |
| 155 | 137 | ||
| 156 | |||
| 157 | |||
| 158 | INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter) | 138 | INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter) |
| 159 | { | 139 | { |
| 160 | PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter); | 140 | PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter); |
| 161 | INT status = STATUS_SUCCESS ; | 141 | INT status = STATUS_SUCCESS; |
| 162 | 142 | ||
| 163 | /* | 143 | /* |
| 164 | usb_clear_halt - tells device to clear endpoint halt/stall condition | 144 | * usb_clear_halt - tells device to clear endpoint halt/stall condition |
| 165 | @dev: device whose endpoint is halted | 145 | * @dev: device whose endpoint is halted |
| 166 | @pipe: endpoint "pipe" being cleared | 146 | * @pipe: endpoint "pipe" being cleared |
| 167 | @ Context: !in_interrupt () | 147 | * @ Context: !in_interrupt () |
| 168 | 148 | * | |
| 169 | usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code. | 149 | * usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code. |
| 170 | This is used to clear halt conditions for bulk and interrupt endpoints only. | 150 | * This is used to clear halt conditions for bulk and interrupt endpoints only. |
| 171 | Control and isochronous endpoints never halts. | 151 | * Control and isochronous endpoints never halts. |
| 172 | 152 | * | |
| 173 | Any URBs queued for such an endpoint should normally be unlinked by the driver | 153 | * Any URBs queued for such an endpoint should normally be unlinked by the driver |
| 174 | before clearing the halt condition. | 154 | * before clearing the halt condition. |
| 175 | 155 | * | |
| 176 | */ | 156 | */ |
| 177 | 157 | ||
| 178 | //Killing all the submitted urbs to different end points. | 158 | /* Killing all the submitted urbs to different end points. */ |
| 179 | Bcm_kill_all_URBs(psIntfAdapter); | 159 | Bcm_kill_all_URBs(psIntfAdapter); |
| 180 | 160 | ||
| 161 | /* clear the halted/stalled state for every end point */ | ||
| 162 | status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sIntrIn.int_in_pipe); | ||
| 163 | if (status != STATUS_SUCCESS) | ||
| 164 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status); | ||
| 181 | 165 | ||
| 182 | //clear the halted/stalled state for every end point | 166 | status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_pipe); |
| 183 | status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sIntrIn.int_in_pipe); | 167 | if (status != STATUS_SUCCESS) |
| 184 | if(status != STATUS_SUCCESS) | 168 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status); |
| 185 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status); | ||
| 186 | 169 | ||
| 187 | status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkIn.bulk_in_pipe); | 170 | status = usb_clear_halt(psIntfAdapter->udev, psIntfAdapter->sBulkOut.bulk_out_pipe); |
| 188 | if(status != STATUS_SUCCESS) | 171 | if (status != STATUS_SUCCESS) |
| 189 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status); | 172 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status); |
| 190 | 173 | ||
| 191 | status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkOut.bulk_out_pipe); | 174 | return status; |
| 192 | if(status != STATUS_SUCCESS) | ||
| 193 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status); | ||
| 194 | |||
| 195 | return status ; | ||
| 196 | } | 175 | } |
| 197 | 176 | ||
| 198 | |||
| 199 | VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) | 177 | VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) |
| 200 | { | 178 | { |
| 201 | struct urb *tempUrb = NULL; | 179 | struct urb *tempUrb = NULL; |
| 202 | UINT i; | 180 | UINT i; |
| 203 | 181 | ||
| 204 | /** | 182 | /* |
| 205 | * usb_kill_urb - cancel a transfer request and wait for it to finish | 183 | * usb_kill_urb - cancel a transfer request and wait for it to finish |
| 206 | * @urb: pointer to URB describing a previously submitted request, | 184 | * @urb: pointer to URB describing a previously submitted request, |
| 207 | * returns nothing as it is void returned API. | 185 | * returns nothing as it is void returned API. |
| 208 | * | 186 | * |
| 209 | * This routine cancels an in-progress request. It is guaranteed that | 187 | * This routine cancels an in-progress request. It is guaranteed that |
| 210 | * upon return all completion handlers will have finished and the URB | 188 | * upon return all completion handlers will have finished and the URB |
| 211 | * will be totally idle and available for reuse | 189 | * will be totally idle and available for reuse |
| 212 | 190 | * | |
| 213 | * This routine may not be used in an interrupt context (such as a bottom | 191 | * This routine may not be used in an interrupt context (such as a bottom |
| 214 | * half or a completion handler), or when holding a spinlock, or in other | 192 | * half or a completion handler), or when holding a spinlock, or in other |
| 215 | * situations where the caller can't schedule(). | 193 | * situations where the caller can't schedule(). |
| 216 | * | 194 | * |
| 217 | **/ | 195 | */ |
| 218 | 196 | ||
| 219 | /* Cancel submitted Interrupt-URB's */ | 197 | /* Cancel submitted Interrupt-URB's */ |
| 220 | if(psIntfAdapter->psInterruptUrb != NULL) | 198 | if (psIntfAdapter->psInterruptUrb != NULL) { |
| 221 | { | 199 | if (psIntfAdapter->psInterruptUrb->status == -EINPROGRESS) |
| 222 | if(psIntfAdapter->psInterruptUrb->status == -EINPROGRESS) | 200 | usb_kill_urb(psIntfAdapter->psInterruptUrb); |
| 223 | usb_kill_urb(psIntfAdapter->psInterruptUrb); | ||
| 224 | } | 201 | } |
| 225 | 202 | ||
| 226 | /* Cancel All submitted TX URB's */ | 203 | /* Cancel All submitted TX URB's */ |
| 227 | for(i = 0; i < MAXIMUM_USB_TCB; i++) | 204 | for (i = 0; i < MAXIMUM_USB_TCB; i++) { |
| 228 | { | ||
| 229 | tempUrb = psIntfAdapter->asUsbTcb[i].urb; | 205 | tempUrb = psIntfAdapter->asUsbTcb[i].urb; |
| 230 | if(tempUrb) | 206 | if (tempUrb) { |
| 231 | { | 207 | if (tempUrb->status == -EINPROGRESS) |
| 232 | if(tempUrb->status == -EINPROGRESS) | ||
| 233 | usb_kill_urb(tempUrb); | 208 | usb_kill_urb(tempUrb); |
| 234 | } | 209 | } |
| 235 | } | 210 | } |
| 236 | 211 | ||
| 237 | for(i = 0; i < MAXIMUM_USB_RCB; i++) | 212 | for (i = 0; i < MAXIMUM_USB_RCB; i++) { |
| 238 | { | ||
| 239 | tempUrb = psIntfAdapter->asUsbRcb[i].urb; | 213 | tempUrb = psIntfAdapter->asUsbRcb[i].urb; |
| 240 | if(tempUrb) | 214 | if (tempUrb) { |
| 241 | { | 215 | if (tempUrb->status == -EINPROGRESS) |
| 242 | if(tempUrb->status == -EINPROGRESS) | 216 | usb_kill_urb(tempUrb); |
| 243 | usb_kill_urb(tempUrb); | ||
| 244 | } | 217 | } |
| 245 | } | 218 | } |
| 246 | 219 | ||
| @@ -253,13 +226,12 @@ VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) · 6 unmodified lines | |||
| 253 | 226 | ||
| 254 | VOID putUsbSuspend(struct work_struct *work) | 227 | VOID putUsbSuspend(struct work_struct *work) |
| 255 | { | 228 | { |
| 256 | PS_INTERFACE_ADAPTER psIntfAdapter = NULL ; | 229 | PS_INTERFACE_ADAPTER psIntfAdapter = NULL; |
| 257 | struct usb_interface *intf = NULL ; | 230 | struct usb_interface *intf = NULL; |
| 258 | psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER,usbSuspendWork); | 231 | psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER, usbSuspendWork); |
| 259 | intf=psIntfAdapter->interface ; | 232 | intf = psIntfAdapter->interface; |
| 260 | 233 | ||
| 261 | if(psIntfAdapter->bSuspended == FALSE) | 234 | if (psIntfAdapter->bSuspended == FALSE) |
| 262 | usb_autopm_put_interface(intf); | 235 | usb_autopm_put_interface(intf); |
| 263 | |||
| 264 | } | 236 | } |
| 265 | 237 | ||
| @@ -1,17 +1,17 @@ | |||
| 1 | /************************************* | 1 | /************************************* |
| 2 | * Macros.h | 2 | * Macros.h |
| 3 | **************************************/ | 3 | **************************************/ |
| 4 | #ifndef __MACROS_H__ | 4 | #ifndef __MACROS_H__ |
| 5 | #define __MACROS_H__ | 5 | #define __MACROS_H__ |
| 6 | 6 | ||
| 7 | #define TX_TIMER_PERIOD 10 //10 msec | 7 | #define TX_TIMER_PERIOD 10 /*10 msec*/ |
| 8 | #define MAX_CLASSIFIERS 100 | 8 | #define MAX_CLASSIFIERS 100 |
| 9 | //#define MAX_CLASSIFIERS_PER_SF 20 | 9 | /* #define MAX_CLASSIFIERS_PER_SF 20 */ |
| 10 | #define MAX_TARGET_DSX_BUFFERS 24 | 10 | #define MAX_TARGET_DSX_BUFFERS 24 |
| 11 | 11 | ||
| 12 | #define MAX_CNTRL_PKTS 100 | 12 | #define MAX_CNTRL_PKTS 100 |
| 13 | #define MAX_DATA_PKTS 200 | 13 | #define MAX_DATA_PKTS 200 |
| 14 | #define MAX_ETH_SIZE 1536 | 14 | #define MAX_ETH_SIZE 1536 |
| 15 | #define MAX_CNTL_PKT_SIZE 2048 | 15 | #define MAX_CNTL_PKT_SIZE 2048 |
| 16 | 16 | ||
| 17 | #define MTU_SIZE 1400 | 17 | #define MTU_SIZE 1400 |
| @@ -20,102 +20,102 @@ · 2 unmodified lines | |||
| 20 | #define MAC_ADDR_REGISTER 0xbf60d000 | 20 | #define MAC_ADDR_REGISTER 0xbf60d000 |
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | ///////////Quality of Service/////////////////////////// | 23 | /* Quality of Service */ |
| 24 | #define NO_OF_QUEUES 17 | 24 | #define NO_OF_QUEUES 17 |
| 25 | #define HiPriority NO_OF_QUEUES-1 | 25 | #define HiPriority (NO_OF_QUEUES-1) |
| 26 | #define LowPriority 0 | 26 | #define LowPriority 0 |
| 27 | #define BE 2 | 27 | #define BE 2 |
| 28 | #define rtPS 4 | 28 | #define rtPS 4 |
| 29 | #define ERTPS 5 | 29 | #define ERTPS 5 |
| 30 | #define UGS 6 | 30 | #define UGS 6 |
| 31 | 31 | ||
| 32 | #define BE_BUCKET_SIZE 1024*1024*100 //32kb | 32 | #define BE_BUCKET_SIZE (1024*1024*100) /* 32kb */ |
| 33 | #define rtPS_BUCKET_SIZE 1024*1024*100 //8kb | 33 | #define rtPS_BUCKET_SIZE (1024*1024*100) /* 8kb */ |
| 34 | #define MAX_ALLOWED_RATE 1024*1024*100 | 34 | #define MAX_ALLOWED_RATE (1024*1024*100) |
| 35 | #define TX_PACKET_THRESHOLD 10 | 35 | #define TX_PACKET_THRESHOLD 10 |
| 36 | #define XSECONDS 1*HZ | 36 | #define XSECONDS (1*HZ) |
| 37 | #define DSC_ACTIVATE_REQUEST 248 | 37 | #define DSC_ACTIVATE_REQUEST 248 |
| 38 | #define QUEUE_DEPTH_OFFSET 0x1fc01000 | 38 | #define QUEUE_DEPTH_OFFSET 0x1fc01000 |
| 39 | #define MAX_DEVICE_DESC_SIZE 2040 | 39 | #define MAX_DEVICE_DESC_SIZE 2040 |
| 40 | #define MAX_CTRL_QUEUE_LEN 100 | 40 | #define MAX_CTRL_QUEUE_LEN 100 |
| 41 | #define MAX_APP_QUEUE_LEN 200 | 41 | #define MAX_APP_QUEUE_LEN 200 |
| 42 | #define MAX_LATENCY_ALLOWED 0xFFFFFFFF | 42 | #define MAX_LATENCY_ALLOWED 0xFFFFFFFF |
| 43 | #define DEFAULT_UG_INTERVAL 250 | 43 | #define DEFAULT_UG_INTERVAL 250 |
| 44 | #define DEFAULT_UGI_FACTOR 4 | 44 | #define DEFAULT_UGI_FACTOR 4 |
| 45 | 45 | ||
| 46 | #define DEFAULT_PERSFCOUNT 60 | 46 | #define DEFAULT_PERSFCOUNT 60 |
| 47 | #define MAX_CONNECTIONS 10 | 47 | #define MAX_CONNECTIONS 10 |
| 48 | #define MAX_CLASS_NAME_LENGTH 32 | 48 | #define MAX_CLASS_NAME_LENGTH 32 |
| 49 | 49 | ||
| 50 | #define ETH_LENGTH_OF_ADDRESS 6 | 50 | #define ETH_LENGTH_OF_ADDRESS 6 |
| 51 | #define MAX_MULTICAST_ADDRESSES 32 | 51 | #define MAX_MULTICAST_ADDRESSES 32 |
| 52 | #define IP_LENGTH_OF_ADDRESS 4 | 52 | #define IP_LENGTH_OF_ADDRESS 4 |
| 53 | 53 | ||
| 54 | #define IP_PACKET_ONLY_MODE 0 | 54 | #define IP_PACKET_ONLY_MODE 0 |
| 55 | #define ETH_PACKET_TUNNELING_MODE 1 | 55 | #define ETH_PACKET_TUNNELING_MODE 1 |
| 56 | 56 | ||
| 57 | ////////////Link Request////////////// | 57 | /* Link Request */ |
| 58 | #define SET_MAC_ADDRESS_REQUEST 0 | 58 | #define SET_MAC_ADDRESS_REQUEST 0 |
| 59 | #define SYNC_UP_REQUEST 1 | 59 | #define SYNC_UP_REQUEST 1 |
| 60 | #define SYNCED_UP 2 | 60 | #define SYNCED_UP 2 |
| 61 | #define LINK_UP_REQUEST 3 | 61 | #define LINK_UP_REQUEST 3 |
| 62 | #define LINK_CONNECTED 4 | 62 | #define LINK_CONNECTED 4 |
| 63 | #define SYNC_UP_NOTIFICATION 2 | 63 | #define SYNC_UP_NOTIFICATION 2 |
| 64 | #define LINK_UP_NOTIFICATION 4 | 64 | #define LINK_UP_NOTIFICATION 4 |
| 65 | 65 | ||
| 66 | 66 | ||
| 67 | #define LINK_NET_ENTRY 0x0002 | 67 | #define LINK_NET_ENTRY 0x0002 |
| 68 | #define HMC_STATUS 0x0004 | 68 | #define HMC_STATUS 0x0004 |
| 69 | #define LINK_UP_CONTROL_REQ 0x83 | 69 | #define LINK_UP_CONTROL_REQ 0x83 |
| 70 | 70 | ||
| 71 | #define STATS_POINTER_REQ_STATUS 0x86 | 71 | #define STATS_POINTER_REQ_STATUS 0x86 |
| 72 | #define NETWORK_ENTRY_REQ_PAYLOAD 198 | 72 | #define NETWORK_ENTRY_REQ_PAYLOAD 198 |
| 73 | #define LINK_DOWN_REQ_PAYLOAD 226 | 73 | #define LINK_DOWN_REQ_PAYLOAD 226 |
| 74 | #define SYNC_UP_REQ_PAYLOAD 228 | 74 | #define SYNC_UP_REQ_PAYLOAD 228 |
| 75 | #define STATISTICS_POINTER_REQ 237 | 75 | #define STATISTICS_POINTER_REQ 237 |
| 76 | #define LINK_UP_REQ_PAYLOAD 245 | 76 | #define LINK_UP_REQ_PAYLOAD 245 |
| 77 | #define LINK_UP_ACK 246 | 77 | #define LINK_UP_ACK 246 |
| 78 | 78 | ||
| 79 | #define STATS_MSG_SIZE 4 | 79 | #define STATS_MSG_SIZE 4 |
| 80 | #define INDEX_TO_DATA 4 | 80 | #define INDEX_TO_DATA 4 |
| 81 | 81 | ||
| 82 | #define GO_TO_IDLE_MODE_PAYLOAD 210 | 82 | #define GO_TO_IDLE_MODE_PAYLOAD 210 |
| 83 | #define COME_UP_FROM_IDLE_MODE_PAYLOAD 211 | 83 | #define COME_UP_FROM_IDLE_MODE_PAYLOAD 211 |
| 84 | #define IDLE_MODE_SF_UPDATE_MSG 187 | 84 | #define IDLE_MODE_SF_UPDATE_MSG 187 |
| 85 | 85 | ||
| 86 | #define SKB_RESERVE_ETHERNET_HEADER 16 | 86 | #define SKB_RESERVE_ETHERNET_HEADER 16 |
| 87 | #define SKB_RESERVE_PHS_BYTES 32 | 87 | #define SKB_RESERVE_PHS_BYTES 32 |
| 88 | 88 | ||
| 89 | #define IP_PACKET_ONLY_MODE 0 | 89 | #define IP_PACKET_ONLY_MODE 0 |
| 90 | #define ETH_PACKET_TUNNELING_MODE 1 | 90 | #define ETH_PACKET_TUNNELING_MODE 1 |
| 91 | 91 | ||
| 92 | #define ETH_CS_802_3 1 | 92 | #define ETH_CS_802_3 1 |
| 93 | #define ETH_CS_802_1Q_VLAN 3 | 93 | #define ETH_CS_802_1Q_VLAN 3 |
| 94 | #define IPV4_CS 1 | 94 | #define IPV4_CS 1 |
| 95 | #define IPV6_CS 2 | 95 | #define IPV6_CS 2 |
| 96 | #define ETH_CS_MASK 0x3f | 96 | #define ETH_CS_MASK 0x3f |
| 97 | 97 | ||
| 98 | /** \brief Validity bit maps for TLVs in packet classification rule */ | 98 | /** \brief Validity bit maps for TLVs in packet classification rule */ |
| 99 | 99 | ||
| 100 | #define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0 | 100 | #define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0 |
| 101 | #define PKT_CLASSIFICATION_VLANID_VALID 1 | 101 | #define PKT_CLASSIFICATION_VLANID_VALID 1 |
| 102 | 102 | ||
| 103 | #ifndef MIN | 103 | #ifndef MIN |
| 104 | #define MIN(_a, _b) ((_a) < (_b)? (_a): (_b)) | 104 | #define MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) |
| 105 | #endif | 105 | #endif |
| 106 | 106 | ||
| 107 | 107 | ||
| 108 | /*Leader related terms */ | 108 | /*Leader related terms */ |
| 109 | #define LEADER_STATUS 0x00 | 109 | #define LEADER_STATUS 0x00 |
| 110 | #define LEADER_STATUS_TCP_ACK 0x1 | 110 | #define LEADER_STATUS_TCP_ACK 0x1 |
| 111 | #define LEADER_SIZE sizeof(LEADER) | 111 | #define LEADER_SIZE sizeof(LEADER) |
| 112 | #define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND) | 112 | #define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND) |
| 113 | #define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND) | 113 | #define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND) |
| 114 | #define CM_REQUEST_SIZE LEADER_SIZE + sizeof(stLocalSFChangeRequest) | 114 | #define CM_REQUEST_SIZE (LEADER_SIZE + sizeof(stLocalSFChangeRequest)) |
| 115 | #define IDLE_REQ_SIZE sizeof(PACKETTOSEND) | 115 | #define IDLE_REQ_SIZE sizeof(PACKETTOSEND) |
| 116 | 116 | ||
| 117 | 117 | ||
| 118 | #define MAX_TRANSFER_CTRL_BYTE_USB 2 * 1024 | 118 | #define MAX_TRANSFER_CTRL_BYTE_USB (2*1024) |
| 119 | 119 | ||
| 120 | #define GET_MAILBOX1_REG_REQUEST 0x87 | 120 | #define GET_MAILBOX1_REG_REQUEST 0x87 |
| 121 | #define GET_MAILBOX1_REG_RESPONSE 0x67 | 121 | #define GET_MAILBOX1_REG_RESPONSE 0x67 |
| @@ -124,40 +124,40 @@ · 2 unmodified lines | |||
| 124 | #define TRANSMIT_NETWORK_DATA 0x00 | 124 | #define TRANSMIT_NETWORK_DATA 0x00 |
| 125 | #define RECEIVED_NETWORK_DATA 0x20 | 125 | #define RECEIVED_NETWORK_DATA 0x20 |
| 126 | 126 | ||
| 127 | #define CM_RESPONSES 0xA0 | 127 | #define CM_RESPONSES 0xA0 |
| 128 | #define STATUS_RSP 0xA1 | 128 | #define STATUS_RSP 0xA1 |
| 129 | #define LINK_CONTROL_RESP 0xA2 | 129 | #define LINK_CONTROL_RESP 0xA2 |
| 130 | #define IDLE_MODE_STATUS 0xA3 | 130 | #define IDLE_MODE_STATUS 0xA3 |
| 131 | #define STATS_POINTER_RESP 0xA6 | 131 | #define STATS_POINTER_RESP 0xA6 |
| 132 | #define MGMT_MSG_INFO_SW_STATUS 0xA7 | 132 | #define MGMT_MSG_INFO_SW_STATUS 0xA7 |
| 133 | #define AUTH_SS_HOST_MSG 0xA8 | 133 | #define AUTH_SS_HOST_MSG 0xA8 |
| 134 | 134 | ||
| 135 | #define CM_DSA_ACK_PAYLOAD 247 | 135 | #define CM_DSA_ACK_PAYLOAD 247 |
| 136 | #define CM_DSC_ACK_PAYLOAD 248 | 136 | #define CM_DSC_ACK_PAYLOAD 248 |
| 137 | #define CM_DSD_ACK_PAYLOAD 249 | 137 | #define CM_DSD_ACK_PAYLOAD 249 |
| 138 | #define CM_DSDEACTVATE 250 | 138 | #define CM_DSDEACTVATE 250 |
| 139 | #define TOTAL_MASKED_ADDRESS_IN_BYTES 32 | 139 | #define TOTAL_MASKED_ADDRESS_IN_BYTES 32 |
| 140 | 140 | ||
| 141 | #define MAC_REQ 0 | 141 | #define MAC_REQ 0 |
| 142 | #define LINK_RESP 1 | 142 | #define LINK_RESP 1 |
| 143 | #define RSSI_INDICATION 2 | 143 | #define RSSI_INDICATION 2 |
| 144 | 144 | ||
| 145 | #define SS_INFO 4 | 145 | #define SS_INFO 4 |
| 146 | #define STATISTICS_INFO 5 | 146 | #define STATISTICS_INFO 5 |
| 147 | #define CM_INDICATION 6 | 147 | #define CM_INDICATION 6 |
| 148 | #define PARAM_RESP 7 | 148 | #define PARAM_RESP 7 |
| 149 | #define BUFFER_1K 1024 | 149 | #define BUFFER_1K 1024 |
| 150 | #define BUFFER_2K BUFFER_1K*2 | 150 | #define BUFFER_2K (BUFFER_1K*2) |
| 151 | #define BUFFER_4K BUFFER_2K*2 | 151 | #define BUFFER_4K (BUFFER_2K*2) |
| 152 | #define BUFFER_8K BUFFER_4K*2 | 152 | #define BUFFER_8K (BUFFER_4K*2) |
| 153 | #define BUFFER_16K BUFFER_8K*2 | 153 | #define BUFFER_16K (BUFFER_8K*2) |
| 154 | #define DOWNLINK_DIR 0 | 154 | #define DOWNLINK_DIR 0 |
| 155 | #define UPLINK_DIR 1 | 155 | #define UPLINK_DIR 1 |
| 156 | 156 | ||
| 157 | #define BCM_SIGNATURE "BECEEM" | 157 | #define BCM_SIGNATURE "BECEEM" |
| 158 | 158 | ||
| 159 | 159 | ||
| 160 | #define GPIO_OUTPUT_REGISTER 0x0F00003C | 160 | #define GPIO_OUTPUT_REGISTER 0x0F00003C |
| 161 | #define BCM_GPIO_OUTPUT_SET_REG 0x0F000040 | 161 | #define BCM_GPIO_OUTPUT_SET_REG 0x0F000040 |
| 162 | #define BCM_GPIO_OUTPUT_CLR_REG 0x0F000044 | 162 | #define BCM_GPIO_OUTPUT_CLR_REG 0x0F000044 |
| 163 | #define GPIO_MODE_REGISTER 0x0F000034 | 163 | #define GPIO_MODE_REGISTER 0x0F000034 |
| @@ -165,44 +165,43 @@ · 1 unmodified line | |||
| 165 | 165 | ||
| 166 | 166 | ||
| 167 | typedef struct _LINK_STATE { | 167 | typedef struct _LINK_STATE { |
| 168 | UCHAR ucLinkStatus; | 168 | UCHAR ucLinkStatus; |
| 169 | UCHAR bIdleMode; | 169 | UCHAR bIdleMode; |
| 170 | UCHAR bShutdownMode; | 170 | UCHAR bShutdownMode; |
| 171 | }LINK_STATE, *PLINK_STATE; | 171 | } LINK_STATE, *PLINK_STATE; |
| 172 | 172 | ||
| 173 | 173 | ||
| 174 | enum enLinkStatus { | 174 | enum enLinkStatus { |
| 175 | WAIT_FOR_SYNC = 1, | 175 | WAIT_FOR_SYNC = 1, |
| 176 | PHY_SYNC_ACHIVED = 2, | 176 | PHY_SYNC_ACHIVED = 2, |
| 177 | LINKUP_IN_PROGRESS = 3, | 177 | LINKUP_IN_PROGRESS = 3, |
| 178 | LINKUP_DONE = 4, | 178 | LINKUP_DONE = 4, |
| 179 | DREG_RECEIVED = 5, | 179 | DREG_RECEIVED = 5, |
| 180 | LINK_STATUS_RESET_RECEIVED = 6, | 180 | LINK_STATUS_RESET_RECEIVED = 6, |
| 181 | PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7, | 181 | PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7, |
| 182 | LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8, | 182 | LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8, |
| 183 | COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW =9 | 183 | COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW = 9 |
| 184 | }; | 184 | }; |
| 185 | 185 | ||
| 186 | typedef enum _E_PHS_DSC_ACTION | 186 | typedef enum _E_PHS_DSC_ACTION { |
| 187 | { | 187 | eAddPHSRule = 0, |
| 188 | eAddPHSRule=0, | ||
| 189 | eSetPHSRule, | 188 | eSetPHSRule, |
| 190 | eDeletePHSRule, | 189 | eDeletePHSRule, |
| 191 | eDeleteAllPHSRules | 190 | eDeleteAllPHSRules |
| 192 | }E_PHS_DSC_ACTION; | 191 | } E_PHS_DSC_ACTION; |
| 193 | 192 | ||
| 194 | 193 | ||
| 195 | #define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 // Host to Mac | 194 | #define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 /* Host to Mac */ |
| 196 | #define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 // Mac to Host | 195 | #define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 /* Mac to Host */ |
| 197 | #define MASK_DISABLE_HEADER_SUPPRESSION 0x10 //0b000010000 | 196 | #define MASK_DISABLE_HEADER_SUPPRESSION 0x10 /* 0b000010000 */ |
| 198 | #define MINIMUM_PENDING_DESCRIPTORS 5 | 197 | #define MINIMUM_PENDING_DESCRIPTORS 5 |
| 199 | 198 | ||
| 200 | #define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC | 199 | #define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC |
| 201 | #define SHUTDOWN_ACK_FROM_DRIVER 0x1 | 200 | #define SHUTDOWN_ACK_FROM_DRIVER 0x1 |
| 202 | #define SHUTDOWN_NACK_FROM_DRIVER 0x2 | 201 | #define SHUTDOWN_NACK_FROM_DRIVER 0x2 |
| 203 | 202 | ||
| 204 | #define LINK_SYNC_UP_SUBTYPE 0x0001 | 203 | #define LINK_SYNC_UP_SUBTYPE 0x0001 |
| 205 | #define LINK_SYNC_DOWN_SUBTYPE 0x0001 | 204 | #define LINK_SYNC_DOWN_SUBTYPE 0x0001 |
| 206 | 205 | ||
| 207 | 206 | ||
| 208 | 207 | ||
| @@ -226,9 +225,9 @@ typedef enum _E_PHS_DSC_ACTION · 17 unmodified lines | |||
| 226 | 225 | ||
| 227 | #define MAX_PENDING_CTRL_PACKET (MAX_CTRL_QUEUE_LEN-10) | 226 | #define MAX_PENDING_CTRL_PACKET (MAX_CTRL_QUEUE_LEN-10) |
| 228 | 227 | ||
| 229 | #define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN) | 228 | #define WIMAX_MAX_MTU (MTU_SIZE + ETH_HLEN) |
| 230 | #define AUTO_LINKUP_ENABLE 0x2 | 229 | #define AUTO_LINKUP_ENABLE 0x2 |
| 231 | #define AUTO_SYNC_DISABLE 0x1 | 230 | #define AUTO_SYNC_DISABLE 0x1 |
| 232 | #define AUTO_FIRM_DOWNLOAD 0x1 | 231 | #define AUTO_FIRM_DOWNLOAD 0x1 |
| 233 | #define SETTLE_DOWN_TIME 50 | 232 | #define SETTLE_DOWN_TIME 50 |
| 234 | 233 | ||
| @@ -242,9 +241,9 @@ typedef enum _E_PHS_DSC_ACTION · 7 unmodified lines | |||
| 242 | #define TARGET_CAN_NOT_GO_TO_IDLE_MODE 3 | 241 | #define TARGET_CAN_NOT_GO_TO_IDLE_MODE 3 |
| 243 | #define IDLE_MODE_PAYLOAD_LENGTH 8 | 242 | #define IDLE_MODE_PAYLOAD_LENGTH 8 |
| 244 | 243 | ||
| 245 | #define IP_HEADER(Buffer) ((IPHeaderFormat*)(Buffer)) | 244 | #define IP_HEADER(Buffer) ((IPHeaderFormat *)(Buffer)) |
| 246 | #define IPV4 4 | 245 | #define IPV4 4 |
| 247 | #define IP_VERSION(byte) (((byte&0xF0)>>4)) | 246 | #define IP_VERSION(byte) (((byte&0xF0)>>4)) |
| 248 | 247 | ||
| 249 | #define SET_MAC_ADDRESS 193 | 248 | #define SET_MAC_ADDRESS 193 |
| 250 | #define SET_MAC_ADDRESS_RESPONSE 236 | 249 | #define SET_MAC_ADDRESS_RESPONSE 236 |
| @@ -263,15 +262,15 @@ typedef enum _E_PHS_DSC_ACTION · 12 unmodified lines | |||
| 263 | 262 | ||
| 264 | #define INVALID_QUEUE_INDEX NO_OF_QUEUES | 263 | #define INVALID_QUEUE_INDEX NO_OF_QUEUES |
| 265 | 264 | ||
| 266 | #define INVALID_PID (pid_t)-1 | 265 | #define INVALID_PID ((pid_t)-1) |
| 267 | #define DDR_80_MHZ 0 | 266 | #define DDR_80_MHZ 0 |
| 268 | #define DDR_100_MHZ 1 | 267 | #define DDR_100_MHZ 1 |
| 269 | #define DDR_120_MHZ 2 // Additional Frequency for T3LP | 268 | #define DDR_120_MHZ 2 /* Additional Frequency for T3LP */ |
| 270 | #define DDR_133_MHZ 3 | 269 | #define DDR_133_MHZ 3 |
| 271 | #define DDR_140_MHZ 4 // Not Used (Reserved for future) | 270 | #define DDR_140_MHZ 4 /* Not Used (Reserved for future) */ |
| 272 | #define DDR_160_MHZ 5 // Additional Frequency for T3LP | 271 | #define DDR_160_MHZ 5 /* Additional Frequency for T3LP */ |
| 273 | #define DDR_180_MHZ 6 // Not Used (Reserved for future) | 272 | #define DDR_180_MHZ 6 /* Not Used (Reserved for future) */ |
| 274 | #define DDR_200_MHZ 7 // Not Used (Reserved for future) | 273 | #define DDR_200_MHZ 7 /* Not Used (Reserved for future) */ |
| 275 | 274 | ||
| 276 | #define MIPS_200_MHZ 0 | 275 | #define MIPS_200_MHZ 0 |
| 277 | #define MIPS_160_MHZ 1 | 276 | #define MIPS_160_MHZ 1 |
| @@ -291,27 +290,27 @@ typedef enum _E_PHS_DSC_ACTION · 13 unmodified lines | |||
| 291 | #define EEPROM_REJECT_REG_3 0x0f003008 | 290 | #define EEPROM_REJECT_REG_3 0x0f003008 |
| 292 | #define EEPROM_REJECT_REG_4 0x0f003020 | 291 | #define EEPROM_REJECT_REG_4 0x0f003020 |
| 293 | #define EEPROM_REJECT_MASK 0x0fffffff | 292 | #define EEPROM_REJECT_MASK 0x0fffffff |
| 294 | #define VSG_MODE 0x3 | 293 | #define VSG_MODE 0x3 |
| 295 | 294 | ||
| 296 | /* Idle Mode Related Registers */ | 295 | /* Idle Mode Related Registers */ |
| 297 | #define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C | 296 | #define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C |
| 298 | #define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC | 297 | #define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC |
| 299 | 298 | ||
| 300 | #define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e | 299 | #define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e |
| 301 | #define DEVICE_INT_OUT_EP_REG0 0x0F011870 | 300 | #define DEVICE_INT_OUT_EP_REG0 0x0F011870 |
| 302 | #define DEVICE_INT_OUT_EP_REG1 0x0F011874 | 301 | #define DEVICE_INT_OUT_EP_REG1 0x0F011874 |
| 303 | 302 | ||
| 304 | #define BIN_FILE "/lib/firmware/macxvi200.bin" | 303 | #define BIN_FILE "/lib/firmware/macxvi200.bin" |
| 305 | #define CFG_FILE "/lib/firmware/macxvi.cfg" | 304 | #define CFG_FILE "/lib/firmware/macxvi.cfg" |
| 306 | #define SF_MAX_ALLOWED_PACKETS_TO_BACKUP 128 | 305 | #define SF_MAX_ALLOWED_PACKETS_TO_BACKUP 128 |
| 307 | #define MIN_VAL(x,y) ((x)<(y)?(x):(y)) | 306 | #define MIN_VAL(x, y) ((x) < (y) ? (x) : (y)) |
| 308 | #define MAC_ADDRESS_SIZE 6 | 307 | #define MAC_ADDRESS_SIZE 6 |
| 309 | #define EEPROM_COMMAND_Q_REG 0x0F003018 | 308 | #define EEPROM_COMMAND_Q_REG 0x0F003018 |
| 310 | #define EEPROM_READ_DATA_Q_REG 0x0F003020 | 309 | #define EEPROM_READ_DATA_Q_REG 0x0F003020 |
| 311 | #define CHIP_ID_REG 0x0F000000 | 310 | #define CHIP_ID_REG 0x0F000000 |
| 312 | #define GPIO_MODE_REG 0x0F000034 | 311 | #define GPIO_MODE_REG 0x0F000034 |
| 313 | #define GPIO_OUTPUT_REG 0x0F00003C | 312 | #define GPIO_OUTPUT_REG 0x0F00003C |
| 314 | #define WIMAX_MAX_ALLOWED_RATE 1024*1024*50 | 313 | #define WIMAX_MAX_ALLOWED_RATE (1024*1024*50) |
| 315 | 314 | ||
| 316 | #define T3 0xbece0300 | 315 | #define T3 0xbece0300 |
| 317 | #define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400 | 316 | #define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400 |
| @@ -319,31 +318,29 @@ typedef enum _E_PHS_DSC_ACTION · 1 unmodified line | |||
| 319 | #define RWM_READ 0 | 318 | #define RWM_READ 0 |
| 320 | #define RWM_WRITE 1 | 319 | #define RWM_WRITE 1 |
| 321 | 320 | ||
| 322 | #define T3LPB 0xbece3300 | 321 | #define T3LPB 0xbece3300 |
| 323 | #define BCS220_2 0xbece3311 | 322 | #define BCS220_2 0xbece3311 |
| 324 | #define BCS220_2BC 0xBECE3310 | 323 | #define BCS220_2BC 0xBECE3310 |
| 325 | #define BCS250_BC 0xbece3301 | 324 | #define BCS250_BC 0xbece3301 |
| 326 | #define BCS220_3 0xbece3321 | 325 | #define BCS220_3 0xbece3321 |
| 327 | 326 | ||
| 328 | 327 | ||
| 329 | #define HPM_CONFIG_LDO145 0x0F000D54 | 328 | #define HPM_CONFIG_LDO145 0x0F000D54 |
| 330 | #define HPM_CONFIG_MSW 0x0F000D58 | 329 | #define HPM_CONFIG_MSW 0x0F000D58 |
| 331 | 330 | ||
| 332 | #define T3B 0xbece0310 | 331 | #define T3B 0xbece0310 |
| 333 | typedef enum eNVM_TYPE | 332 | typedef enum eNVM_TYPE { |
| 334 | { | ||
| 335 | NVM_AUTODETECT = 0, | 333 | NVM_AUTODETECT = 0, |
| 336 | NVM_EEPROM, | 334 | NVM_EEPROM, |
| 337 | NVM_FLASH, | 335 | NVM_FLASH, |
| 338 | NVM_UNKNOWN | 336 | NVM_UNKNOWN |
| 339 | }NVM_TYPE; | 337 | } NVM_TYPE; |
| 340 | 338 | ||
| 341 | typedef enum ePMU_MODES | 339 | typedef enum ePMU_MODES { |
| 342 | { | ||
| 343 | HYBRID_MODE_7C = 0, | 340 | HYBRID_MODE_7C = 0, |
| 344 | INTERNAL_MODE_6 = 1, | 341 | INTERNAL_MODE_6 = 1, |
| 345 | HYBRID_MODE_6 = 2 | 342 | HYBRID_MODE_6 = 2 |
| 346 | }PMU_MODE; | 343 | } PMU_MODE; |
| 347 | 344 | ||
| 348 | #define MAX_RDM_WRM_RETIRES 1 | 345 | #define MAX_RDM_WRM_RETIRES 1 |
| 349 | 346 | ||
| @@ -360,4 +357,4 @@ enum eAbortPattern { · 10 unmodified lines | |||
| 360 | #define SKB_CB_LATENCY_OFFSET 1 | 357 | #define SKB_CB_LATENCY_OFFSET 1 |
| 361 | #define SKB_CB_TCPACK_OFFSET 2 | 358 | #define SKB_CB_TCPACK_OFFSET 2 |
| 362 | 359 | ||
| 363 | #endif //__MACROS_H__ | 360 | #endif /* __MACROS_H__ */ |
| @@ -1,113 +1,94 @@ | |||
| 1 | #include "headers.h" | 1 | #include "headers.h" |
| 2 | 2 | ||
| 3 | static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, | 3 | static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, unsigned int loc); |
| 4 | unsigned int loc); | ||
| 5 | static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter); | 4 | static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter); |
| 6 | static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer); | 5 | static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer); |
| 7 | static int bcm_parse_target_params(PMINI_ADAPTER Adapter); | 6 | static int bcm_parse_target_params(PMINI_ADAPTER Adapter); |
| 8 | static void beceem_protocol_reset (PMINI_ADAPTER Adapter); | 7 | static void beceem_protocol_reset(PMINI_ADAPTER Adapter); |
| 9 | 8 | ||
| 10 | static VOID default_wimax_protocol_initialize(PMINI_ADAPTER Adapter) | 9 | static VOID default_wimax_protocol_initialize(PMINI_ADAPTER Adapter) |
| 11 | { | 10 | { |
| 11 | UINT uiLoopIndex; | ||
| 12 | 12 | ||
| 13 | UINT uiLoopIndex; | 13 | for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) { |
| 14 | 14 | Adapter->PackInfo[uiLoopIndex].uiThreshold = TX_PACKET_THRESHOLD; | |
| 15 | for(uiLoopIndex=0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) | 15 | Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate = MAX_ALLOWED_RATE; |
| 16 | { | 16 | Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize = 20*1024*1024; |
| 17 | Adapter->PackInfo[uiLoopIndex].uiThreshold=TX_PACKET_THRESHOLD; | 17 | } |
| 18 | Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate=MAX_ALLOWED_RATE; | ||
| 19 | Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize=20*1024*1024; | ||
| 20 | } | ||
| 21 | |||
| 22 | Adapter->BEBucketSize=BE_BUCKET_SIZE; | ||
| 23 | Adapter->rtPSBucketSize=rtPS_BUCKET_SIZE; | ||
| 24 | Adapter->LinkStatus=SYNC_UP_REQUEST; | ||
| 25 | Adapter->TransferMode=IP_PACKET_ONLY_MODE; | ||
| 26 | Adapter->usBestEffortQueueIndex=-1; | ||
| 27 | return; | ||
| 28 | } | ||
| 29 | 18 | ||
| 19 | Adapter->BEBucketSize = BE_BUCKET_SIZE; | ||
| 20 | Adapter->rtPSBucketSize = rtPS_BUCKET_SIZE; | ||
| 21 | Adapter->LinkStatus = SYNC_UP_REQUEST; | ||
| 22 | Adapter->TransferMode = IP_PACKET_ONLY_MODE; | ||
| 23 | Adapter->usBestEffortQueueIndex = -1; | ||
| 24 | return; | ||
| 25 | } | ||
| 30 | 26 | ||
| 31 | INT | 27 | INT InitAdapter(PMINI_ADAPTER psAdapter) |
| 32 | InitAdapter(PMINI_ADAPTER psAdapter) | ||
| 33 | { | 28 | { |
| 34 | int i = 0; | 29 | int i = 0; |
| 35 | INT Status = STATUS_SUCCESS ; | 30 | INT Status = STATUS_SUCCESS; |
| 36 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter); | 31 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = %p", psAdapter); |
| 37 | 32 | ||
| 38 | if(psAdapter == NULL) | 33 | if (psAdapter == NULL) { |
| 39 | { | 34 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL"); |
| 40 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL"); | ||
| 41 | return -EINVAL; | 35 | return -EINVAL; |
| 42 | } | 36 | } |
| 43 | 37 | ||
| 44 | sema_init(&psAdapter->NVMRdmWrmLock,1); | 38 | sema_init(&psAdapter->NVMRdmWrmLock, 1); |
| 45 | // psAdapter->ulFlashCalStart = FLASH_AUTO_INIT_BASE_ADDR; | ||
| 46 | |||
| 47 | sema_init(&psAdapter->rdmwrmsync, 1); | 39 | sema_init(&psAdapter->rdmwrmsync, 1); |
| 48 | spin_lock_init(&psAdapter->control_queue_lock); | 40 | spin_lock_init(&psAdapter->control_queue_lock); |
| 49 | spin_lock_init(&psAdapter->txtransmitlock); | 41 | spin_lock_init(&psAdapter->txtransmitlock); |
| 50 | sema_init(&psAdapter->RxAppControlQueuelock, 1); | 42 | sema_init(&psAdapter->RxAppControlQueuelock, 1); |
| 51 | // sema_init(&psAdapter->data_packet_queue_lock, 1); | 43 | sema_init(&psAdapter->fw_download_sema, 1); |
| 52 | sema_init(&psAdapter->fw_download_sema, 1); | 44 | sema_init(&psAdapter->LowPowerModeSync, 1); |
| 53 | sema_init(&psAdapter->LowPowerModeSync,1); | 45 | |
| 54 | 46 | for (i = 0; i < NO_OF_QUEUES; i++) | |
| 55 | // spin_lock_init(&psAdapter->sleeper_lock); | 47 | spin_lock_init(&psAdapter->PackInfo[i].SFQueueLock); |
| 56 | 48 | i = 0; | |
| 57 | for(i=0;i<NO_OF_QUEUES; i++) | 49 | |
| 58 | spin_lock_init(&psAdapter->PackInfo[i].SFQueueLock); | 50 | init_waitqueue_head(&psAdapter->process_rx_cntrlpkt); |
| 59 | i=0; | 51 | init_waitqueue_head(&psAdapter->tx_packet_wait_queue); |
| 60 | 52 | init_waitqueue_head(&psAdapter->process_read_wait_queue); | |
| 61 | init_waitqueue_head(&psAdapter->process_rx_cntrlpkt); | 53 | init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue); |
| 62 | init_waitqueue_head(&psAdapter->tx_packet_wait_queue); | 54 | init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue); |
| 63 | init_waitqueue_head(&psAdapter->process_read_wait_queue); | ||
| 64 | init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue); | ||
| 65 | init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue); | ||
| 66 | psAdapter->waiting_to_fw_download_done = TRUE; | 55 | psAdapter->waiting_to_fw_download_done = TRUE; |
| 67 | //init_waitqueue_head(&psAdapter->device_wake_queue); | 56 | psAdapter->fw_download_done = FALSE; |
| 68 | psAdapter->fw_download_done=FALSE; | ||
| 69 | |||
| 70 | 57 | ||
| 71 | default_wimax_protocol_initialize(psAdapter); | 58 | default_wimax_protocol_initialize(psAdapter); |
| 72 | for (i=0;i<MAX_CNTRL_PKTS;i++) | 59 | for (i = 0; i < MAX_CNTRL_PKTS; i++) { |
| 73 | { | ||
| 74 | psAdapter->txctlpacket[i] = kmalloc(MAX_CNTL_PKT_SIZE, GFP_KERNEL); | 60 | psAdapter->txctlpacket[i] = kmalloc(MAX_CNTL_PKT_SIZE, GFP_KERNEL); |
| 75 | if(!psAdapter->txctlpacket[i]) | 61 | if (!psAdapter->txctlpacket[i]) { |
| 76 | { | 62 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i); |
| 77 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i); | ||
| 78 | return -ENOMEM; | 63 | return -ENOMEM; |
| 79 | } | 64 | } |
| 80 | } | 65 | } |
| 81 | if(AllocAdapterDsxBuffer(psAdapter)) | 66 | |
| 82 | { | 67 | if (AllocAdapterDsxBuffer(psAdapter)) { |
| 83 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers"); | 68 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers"); |
| 84 | return -EINVAL; | 69 | return -EINVAL; |
| 85 | } | 70 | } |
| 86 | 71 | ||
| 87 | //Initialize PHS interface | 72 | /* Initialize PHS interface */ |
| 88 | if(phs_init(&psAdapter->stBCMPhsContext,psAdapter)!=0) | 73 | if (phs_init(&psAdapter->stBCMPhsContext, psAdapter) != 0) { |
| 89 | { | 74 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __func__, __LINE__); |
| 90 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __FUNCTION__, __LINE__); | ||
| 91 | return -ENOMEM; | 75 | return -ENOMEM; |
| 92 | } | 76 | } |
| 93 | 77 | ||
| 94 | Status = BcmAllocFlashCSStructure(psAdapter); | 78 | Status = BcmAllocFlashCSStructure(psAdapter); |
| 95 | if(Status) | 79 | if (Status) { |
| 96 | { | 80 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Memory Allocation for Flash structure failed"); |
| 97 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Memory Allocation for Flash structure failed"); | 81 | return Status; |
| 98 | return Status ; | ||
| 99 | } | 82 | } |
| 100 | 83 | ||
| 101 | Status = vendorextnInit(psAdapter); | 84 | Status = vendorextnInit(psAdapter); |
| 102 | 85 | ||
| 103 | if(STATUS_SUCCESS != Status) | 86 | if (STATUS_SUCCESS != Status) { |
| 104 | { | 87 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Vendor Init Failed"); |
| 105 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Vendor Init Failed"); | 88 | return Status; |
| 106 | return Status ; | ||
| 107 | } | 89 | } |
| 108 | 90 | ||
| 109 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised"); | 91 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised"); |
| 110 | |||
| 111 | 92 | ||
| 112 | return STATUS_SUCCESS; | 93 | return STATUS_SUCCESS; |
| 113 | } | 94 | } |
| @@ -115,42 +96,37 @@ InitAdapter(PMINI_ADAPTER psAdapter) · 1 unmodified line | |||
| 115 | VOID AdapterFree(PMINI_ADAPTER Adapter) | 96 | VOID AdapterFree(PMINI_ADAPTER Adapter) |
| 116 | { | 97 | { |
| 117 | int count; | 98 | int count; |
| 118 | |||
| 119 | beceem_protocol_reset(Adapter); | 99 | beceem_protocol_reset(Adapter); |
| 120 | |||
| 121 | vendorextnExit(Adapter); | 100 | vendorextnExit(Adapter); |
| 122 | 101 | ||
| 123 | if(Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler)) | 102 | if (Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler)) |
| 124 | kthread_stop (Adapter->control_packet_handler); | 103 | kthread_stop(Adapter->control_packet_handler); |
| 125 | 104 | ||
| 126 | if(Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread)) | 105 | if (Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread)) |
| 127 | kthread_stop (Adapter->transmit_packet_thread); | 106 | kthread_stop(Adapter->transmit_packet_thread); |
| 128 | 107 | ||
| 129 | wake_up(&Adapter->process_read_wait_queue); | 108 | wake_up(&Adapter->process_read_wait_queue); |
| 130 | 109 | ||
| 131 | if(Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY)) | 110 | if (Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY)) |
| 132 | kthread_stop (Adapter->LEDInfo.led_cntrl_threadid); | 111 | kthread_stop(Adapter->LEDInfo.led_cntrl_threadid); |
| 133 | 112 | ||
| 134 | unregister_networkdev(Adapter); | 113 | unregister_networkdev(Adapter); |
| 135 | 114 | ||
| 136 | /* FIXME: use proper wait_event and refcounting */ | 115 | /* FIXME: use proper wait_event and refcounting */ |
| 137 | while(atomic_read(&Adapter->ApplicationRunning)) | 116 | while (atomic_read(&Adapter->ApplicationRunning)) { |
| 138 | { | 117 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n", atomic_read(&Adapter->ApplicationRunning)); |
| 139 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n",atomic_read(&Adapter->ApplicationRunning)); | ||
| 140 | msleep(100); | 118 | msleep(100); |
| 141 | } | 119 | } |
| 142 | unregister_control_device_interface(Adapter); | 120 | unregister_control_device_interface(Adapter); |
| 143 | |||
| 144 | kfree(Adapter->pstargetparams); | 121 | kfree(Adapter->pstargetparams); |
| 145 | 122 | ||
| 146 | for (count =0;count < MAX_CNTRL_PKTS;count++) | 123 | for (count = 0; count < MAX_CNTRL_PKTS; count++) |
| 147 | kfree(Adapter->txctlpacket[count]); | 124 | kfree(Adapter->txctlpacket[count]); |
| 148 | 125 | ||
| 149 | FreeAdapterDsxBuffer(Adapter); | 126 | FreeAdapterDsxBuffer(Adapter); |
| 150 | |||
| 151 | kfree(Adapter->pvInterfaceAdapter); | 127 | kfree(Adapter->pvInterfaceAdapter); |
| 152 | 128 | ||
| 153 | //Free the PHS Interface | 129 | /* Free the PHS Interface */ |
| 154 | PhsCleanup(&Adapter->stBCMPhsContext); | 130 | PhsCleanup(&Adapter->stBCMPhsContext); |
| 155 | 131 | ||
| 156 | BcmDeAllocFlashCSStructure(Adapter); | 132 | BcmDeAllocFlashCSStructure(Adapter); |
| @@ -160,20 +136,18 @@ VOID AdapterFree(PMINI_ADAPTER Adapter) · 3 unmodified lines | |||
| 160 | 136 | ||
| 161 | static int create_worker_threads(PMINI_ADAPTER psAdapter) | 137 | static int create_worker_threads(PMINI_ADAPTER psAdapter) |
| 162 | { | 138 | { |
| 163 | // Rx Control Packets Processing | 139 | /* Rx Control Packets Processing */ |
| 164 | psAdapter->control_packet_handler = kthread_run((int (*)(void *)) | 140 | psAdapter->control_packet_handler = kthread_run((int (*)(void *)) |
| 165 | control_packet_handler, psAdapter, "%s-rx", DRV_NAME); | 141 | control_packet_handler, psAdapter, "%s-rx", DRV_NAME); |
| 166 | if(IS_ERR(psAdapter->control_packet_handler)) | 142 | if (IS_ERR(psAdapter->control_packet_handler)) { |
| 167 | { | ||
| 168 | pr_notice(DRV_NAME ": could not create control thread\n"); | 143 | pr_notice(DRV_NAME ": could not create control thread\n"); |
| 169 | return PTR_ERR(psAdapter->control_packet_handler); | 144 | return PTR_ERR(psAdapter->control_packet_handler); |
| 170 | } | 145 | } |
| 171 | 146 | ||
| 172 | // Tx Thread | 147 | /* Tx Thread */ |
| 173 | psAdapter->transmit_packet_thread = kthread_run((int (*)(void *)) | 148 | psAdapter->transmit_packet_thread = kthread_run((int (*)(void *)) |
| 174 | tx_pkt_handler, psAdapter, "%s-tx", DRV_NAME); | 149 | tx_pkt_handler, psAdapter, "%s-tx", DRV_NAME); |
| 175 | if(IS_ERR (psAdapter->transmit_packet_thread)) | 150 | if (IS_ERR(psAdapter->transmit_packet_thread)) { |
| 176 | { | ||
| 177 | pr_notice(DRV_NAME ": could not creat transmit thread\n"); | 151 | pr_notice(DRV_NAME ": could not creat transmit thread\n"); |
| 178 | kthread_stop(psAdapter->control_packet_handler); | 152 | kthread_stop(psAdapter->control_packet_handler); |
| 179 | return PTR_ERR(psAdapter->transmit_packet_thread); | 153 | return PTR_ERR(psAdapter->transmit_packet_thread); |
| @@ -183,275 +157,248 @@ static int create_worker_threads(PMINI_ADAPTER psAdapter) · 3 unmodified lines | |||
| 183 | 157 | ||
| 184 | static struct file *open_firmware_file(PMINI_ADAPTER Adapter, const char *path) | 158 | static struct file *open_firmware_file(PMINI_ADAPTER Adapter, const char *path) |
| 185 | { | 159 | { |
| 186 | struct file *flp=NULL; | 160 | struct file *flp = NULL; |
| 187 | mm_segment_t oldfs; | 161 | mm_segment_t oldfs; |
| 188 | oldfs=get_fs(); | 162 | oldfs = get_fs(); |
| 189 | set_fs(get_ds()); | 163 | set_fs(get_ds()); |
| 190 | flp=filp_open(path, O_RDONLY, S_IRWXU); | 164 | flp = filp_open(path, O_RDONLY, S_IRWXU); |
| 191 | set_fs(oldfs); | 165 | set_fs(oldfs); |
| 192 | if(IS_ERR(flp)) | 166 | if (IS_ERR(flp)) { |
| 193 | { | 167 | pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp)); |
| 194 | pr_err(DRV_NAME "Unable To Open File %s, err %ld", | 168 | flp = NULL; |
| 195 | path, PTR_ERR(flp)); | 169 | } |
| 196 | flp = NULL; | ||
| 197 | } | ||
| 198 | |||
| 199 | if(Adapter->device_removed) | ||
| 200 | flp = NULL; | ||
| 201 | |||
| 202 | return flp; | ||
| 203 | } | ||
| 204 | 170 | ||
| 171 | if (Adapter->device_removed) | ||
| 172 | flp = NULL; | ||
| 205 | 173 | ||
| 206 | static int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */ | 174 | return flp; |
| 207 | const char *path, /**< path to image file */ | 175 | } |
| 208 | unsigned int loc /**< Download Address on the chip*/ | 176 | |
| 209 | ) | 177 | /* Arguments: |
| 178 | * Logical Adapter | ||
| 179 | * Path to image file | ||
| 180 | * Download Address on the chip | ||
| 181 | */ | ||
| 182 | static int BcmFileDownload(PMINI_ADAPTER Adapter, const char *path, unsigned int loc) | ||
| 210 | { | 183 | { |
| 211 | int errorno=0; | 184 | int errorno = 0; |
| 212 | struct file *flp=NULL; | 185 | struct file *flp = NULL; |
| 213 | mm_segment_t oldfs; | 186 | mm_segment_t oldfs; |
| 214 | struct timeval tv={0}; | 187 | struct timeval tv = {0}; |
| 215 | 188 | ||
| 216 | flp=open_firmware_file(Adapter, path); | 189 | flp = open_firmware_file(Adapter, path); |
| 217 | if(!flp) | 190 | if (!flp) { |
| 218 | { | 191 | errorno = -ENOENT; |
| 219 | errorno = -ENOENT; | 192 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path); |
| 220 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path); | 193 | goto exit_download; |
| 221 | goto exit_download; | 194 | } |
| 222 | } | 195 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path, (unsigned long)flp->f_dentry->d_inode->i_size, loc); |
| 223 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path,(unsigned long)flp->f_dentry->d_inode->i_size, loc); | 196 | do_gettimeofday(&tv); |
| 224 | do_gettimeofday(&tv); | 197 | |
| 225 | 198 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) + (tv.tv_usec / 1000))); | |
| 226 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) + | 199 | if (Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc)) { |
| 227 | (tv.tv_usec/1000))); | 200 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error %x!!!", -EIO); |
| 228 | if(Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc)) | 201 | errorno = -EIO; |
| 229 | { | 202 | goto exit_download; |
| 230 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error\ | 203 | } |
| 231 | %x!!!", -EIO); | 204 | oldfs = get_fs(); |
| 232 | errorno=-EIO; | 205 | set_fs(get_ds()); |
| 233 | goto exit_download; | 206 | vfs_llseek(flp, 0, 0); |
| 234 | } | 207 | set_fs(oldfs); |
| 235 | oldfs=get_fs();set_fs(get_ds()); | 208 | if (Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, flp, loc)) { |
| 236 | vfs_llseek(flp, 0, 0); | 209 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!"); |
| 237 | set_fs(oldfs); | 210 | errorno = -EIO; |
| 238 | if(Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, | 211 | goto exit_download; |
| 239 | flp, loc)) | 212 | } |
| 240 | { | ||
| 241 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!"); | ||
| 242 | errorno=-EIO; | ||
| 243 | goto exit_download; | ||
| 244 | } | ||
| 245 | 213 | ||
| 246 | exit_download: | 214 | exit_download: |
| 247 | oldfs=get_fs();set_fs(get_ds()); | 215 | oldfs = get_fs(); |
| 248 | if(flp && !(IS_ERR(flp))) | 216 | set_fs(get_ds()); |
| 249 | filp_close(flp, current->files); | 217 | if (flp && !(IS_ERR(flp))) |
| 250 | set_fs(oldfs); | 218 | filp_close(flp, current->files); |
| 219 | set_fs(oldfs); | ||
| 251 | 220 | ||
| 252 | return errorno; | 221 | return errorno; |
| 253 | } | 222 | } |
| 254 | 223 | ||
| 255 | /** | 224 | /** |
| 256 | @ingroup ctrl_pkt_functions | 225 | * @ingroup ctrl_pkt_functions |
| 257 | This function copies the contents of given buffer | 226 | * This function copies the contents of given buffer |
| 258 | to the control packet and queues it for transmission. | 227 | * to the control packet and queues it for transmission. |
| 259 | @note Do not acquire the spinock, as it it already acquired. | 228 | * @note Do not acquire the spinock, as it it already acquired. |
| 260 | @return SUCCESS/FAILURE. | 229 | * @return SUCCESS/FAILURE. |
| 261 | */ | 230 | * Arguments: |
| 262 | INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**<Logical Adapter*/ | 231 | * Logical Adapter |
| 263 | PVOID ioBuffer/**<Control Packet Buffer*/ | 232 | * Control Packet Buffer |
| 264 | ) | 233 | */ |
| 234 | INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter, PVOID ioBuffer) | ||
| 265 | { | 235 | { |
| 266 | PLEADER pLeader=NULL; | 236 | PLEADER pLeader = NULL; |
| 267 | INT Status=0; | 237 | INT Status = 0; |
| 268 | unsigned char *ctrl_buff=NULL; | 238 | unsigned char *ctrl_buff = NULL; |
| 269 | UINT pktlen=0; | 239 | UINT pktlen = 0; |
| 270 | PLINK_REQUEST pLinkReq = NULL; | 240 | PLINK_REQUEST pLinkReq = NULL; |
| 271 | PUCHAR pucAddIndication = NULL; | 241 | PUCHAR pucAddIndication = NULL; |
| 272 | 242 | ||
| 273 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>"); | 243 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "======>"); |
| 274 | if(!ioBuffer) | 244 | if (!ioBuffer) { |
| 275 | { | 245 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got Null Buffer\n"); |
| 276 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Got Null Buffer\n"); | ||
| 277 | return -EINVAL; | 246 | return -EINVAL; |
| 278 | } | 247 | } |
| 279 | 248 | ||
| 280 | pLinkReq = (PLINK_REQUEST)ioBuffer; | 249 | pLinkReq = (PLINK_REQUEST)ioBuffer; |
| 281 | pLeader=(PLEADER)ioBuffer; //ioBuffer Contains sw_Status and Payload | 250 | pLeader = (PLEADER)ioBuffer; /* ioBuffer Contains sw_Status and Payload */ |
| 282 | 251 | ||
| 283 | if(Adapter->bShutStatus == TRUE && | 252 | if (Adapter->bShutStatus == TRUE && |
| 284 | pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD && | 253 | pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD && |
| 285 | pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE) | 254 | pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE) { |
| 286 | { | 255 | |
| 287 | //Got sync down in SHUTDOWN..we could not process this. | 256 | /* Got sync down in SHUTDOWN..we could not process this. */ |
| 288 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n"); | 257 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n"); |
| 289 | return STATUS_FAILURE; | 258 | return STATUS_FAILURE; |
| 290 | } | 259 | } |
| 291 | 260 | ||
| 292 | if((pLeader->Status == LINK_UP_CONTROL_REQ) && | 261 | if ((pLeader->Status == LINK_UP_CONTROL_REQ) && |
| 293 | ((pLinkReq->szData[0] == LINK_UP_REQ_PAYLOAD && | 262 | ((pLinkReq->szData[0] == LINK_UP_REQ_PAYLOAD && |
| 294 | (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) ||//Sync Up Command | 263 | (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) || /* Sync Up Command */ |
| 295 | pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) //Net Entry Command | 264 | pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) /* Net Entry Command */ { |
| 296 | { | 265 | |
| 297 | if(Adapter->LinkStatus > PHY_SYNC_ACHIVED) | 266 | if (Adapter->LinkStatus > PHY_SYNC_ACHIVED) { |
| 298 | { | 267 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "LinkStatus is Greater than PHY_SYN_ACHIEVED"); |
| 299 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"LinkStatus is Greater than PHY_SYN_ACHIEVED"); | ||
| 300 | return STATUS_FAILURE; | 268 | return STATUS_FAILURE; |
| 301 | } | 269 | } |
| 302 | if(TRUE == Adapter->bShutStatus) | 270 | |
| 303 | { | 271 | if (TRUE == Adapter->bShutStatus) { |
| 304 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n"); | 272 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n"); |
| 305 | if(Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) | 273 | if (Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) { |
| 306 | { | 274 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Waking up for the First Time..\n"); |
| 307 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Waking up for the First Time..\n"); | 275 | Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; /* change it to 1 for current support. */ |
| 308 | Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; // change it to 1 for current support. | ||
| 309 | Adapter->bWakeUpDevice = TRUE; | 276 | Adapter->bWakeUpDevice = TRUE; |
| 310 | wake_up(&Adapter->process_rx_cntrlpkt); | 277 | wake_up(&Adapter->process_rx_cntrlpkt); |
| 278 | Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->bShutStatus, (5 * HZ)); | ||
| 311 | 279 | ||
| 312 | Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, | 280 | if (Status == -ERESTARTSYS) |
| 313 | !Adapter->bShutStatus, (5 * HZ)); | ||
| 314 | |||
| 315 | if(Status == -ERESTARTSYS) | ||
| 316 | return Status; | 281 | return Status; |
| 317 | 282 | ||
| 318 | if(Adapter->bShutStatus) | 283 | if (Adapter->bShutStatus) { |
| 319 | { | 284 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n"); |
| 320 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n"); | ||
| 321 | return STATUS_FAILURE; | 285 | return STATUS_FAILURE; |
| 322 | } | 286 | } |
| 323 | } | 287 | } else { |
| 324 | else | 288 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Wakeup has been tried already...\n"); |
| 325 | { | ||
| 326 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Wakeup has been tried already...\n"); | ||
| 327 | } | 289 | } |
| 328 | } | 290 | } |
| 329 | |||
| 330 | } | 291 | } |
| 331 | if(TRUE == Adapter->IdleMode) | ||
| 332 | { | ||
| 333 | //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence \n"); | ||
| 334 | if(pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 || | ||
| 335 | pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ ) | ||
| 336 | 292 | ||
| 337 | { | 293 | if (TRUE == Adapter->IdleMode) { |
| 338 | if((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0]==LINK_DOWN_REQ_PAYLOAD)) | 294 | /* BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence\n"); */ |
| 339 | { | 295 | if (pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 || |
| 340 | if((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE)) | 296 | pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ) { |
| 341 | { | 297 | |
| 342 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Link Down Sent in Idle Mode\n"); | 298 | if ((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD)) { |
| 343 | Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN;//LINK DOWN sent in Idle Mode | 299 | if ((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE)) { |
| 344 | } | 300 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Link Down Sent in Idle Mode\n"); |
| 345 | else | 301 | Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN; /* LINK DOWN sent in Idle Mode */ |
| 346 | { | 302 | } else { |
| 347 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n"); | 303 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n"); |
| 348 | Adapter->usIdleModePattern = ABORT_IDLE_REG; | 304 | Adapter->usIdleModePattern = ABORT_IDLE_REG; |
| 349 | } | 305 | } |
| 350 | } | 306 | } else { |
| 351 | else | 307 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "ABORT_IDLE_MODE pattern is being written\n"); |
| 352 | { | 308 | Adapter->usIdleModePattern = ABORT_IDLE_MODE; |
| 353 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n"); | ||
| 354 | Adapter->usIdleModePattern = ABORT_IDLE_MODE; | ||
| 355 | } | 309 | } |
| 356 | 310 | ||
| 357 | /*Setting bIdleMode_tx_from_host to TRUE to indicate LED control thread to represent | 311 | /*Setting bIdleMode_tx_from_host to TRUE to indicate LED control thread to represent |
| 358 | the wake up from idlemode is from host*/ | 312 | * the wake up from idlemode is from host |
| 359 | //Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE; | 313 | */ |
| 314 | /* Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE; */ | ||
| 360 | Adapter->bWakeUpDevice = TRUE; | 315 | Adapter->bWakeUpDevice = TRUE; |
| 361 | wake_up(&Adapter->process_rx_cntrlpkt); | 316 | wake_up(&Adapter->process_rx_cntrlpkt); |
| 362 | 317 | ||
| 363 | 318 | /* We should not send DREG message down while in idlemode. */ | |
| 364 | 319 | if (LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0]) | |
| 365 | if(LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0]) | ||
| 366 | { | ||
| 367 | // We should not send DREG message down while in idlemode. | ||
| 368 | return STATUS_SUCCESS; | 320 | return STATUS_SUCCESS; |
| 369 | } | ||
| 370 | 321 | ||
| 371 | Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, | 322 | Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, !Adapter->IdleMode, (5 * HZ)); |
| 372 | !Adapter->IdleMode, (5 * HZ)); | ||
| 373 | 323 | ||
| 374 | if(Status == -ERESTARTSYS) | 324 | if (Status == -ERESTARTSYS) |
| 375 | return Status; | 325 | return Status; |
| 376 | 326 | ||
| 377 | if(Adapter->IdleMode) | 327 | if (Adapter->IdleMode) { |
| 378 | { | 328 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n"); |
| 379 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n"); | ||
| 380 | return STATUS_FAILURE; | 329 | return STATUS_FAILURE; |
| 381 | } | 330 | } |
| 382 | } | 331 | } else { |
| 383 | else | ||
| 384 | return STATUS_SUCCESS; | 332 | return STATUS_SUCCESS; |
| 333 | } | ||
| 385 | } | 334 | } |
| 386 | //The Driver has to send control messages with a particular VCID | 335 | |
| 387 | pLeader->Vcid = VCID_CONTROL_PACKET;//VCID for control packet. | 336 | /* The Driver has to send control messages with a particular VCID */ |
| 337 | pLeader->Vcid = VCID_CONTROL_PACKET; /* VCID for control packet. */ | ||
| 388 | 338 | ||
| 389 | /* Allocate skb for Control Packet */ | 339 | /* Allocate skb for Control Packet */ |
| 390 | pktlen = pLeader->PLength; | 340 | pktlen = pLeader->PLength; |
| 391 | ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS]; | 341 | ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS]; |
| 392 | 342 | ||
| 393 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x", | 343 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x", |
| 394 | atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen); | 344 | atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen); |
| 395 | if(ctrl_buff) | 345 | if (ctrl_buff) { |
| 396 | { | 346 | if (pLeader) { |
| 397 | if(pLeader) | 347 | if ((pLeader->Status == 0x80) || |
| 398 | { | 348 | (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) { |
| 399 | if((pLeader->Status == 0x80) || | ||
| 400 | (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) | ||
| 401 | { | ||
| 402 | /* | 349 | /* |
| 403 | //Restructure the DSX message to handle Multiple classifier Support | 350 | * Restructure the DSX message to handle Multiple classifier Support |
| 404 | // Write the Service Flow param Structures directly to the target | 351 | * Write the Service Flow param Structures directly to the target |
| 405 | //and embed the pointers in the DSX messages sent to target. | 352 | * and embed the pointers in the DSX messages sent to target. |
| 406 | */ | 353 | */ |
| 407 | //Lets store the current length of the control packet we are transmitting | 354 | /* Lets store the current length of the control packet we are transmitting */ |
| 408 | pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE; | 355 | pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE; |
| 409 | pktlen = pLeader->PLength; | 356 | pktlen = pLeader->PLength; |
| 410 | Status = StoreCmControlResponseMessage(Adapter,pucAddIndication, &pktlen); | 357 | Status = StoreCmControlResponseMessage(Adapter, pucAddIndication, &pktlen); |
| 411 | if(Status != 1) | 358 | if (Status != 1) { |
| 412 | { | 359 | ClearTargetDSXBuffer(Adapter, ((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE); |
| 413 | ClearTargetDSXBuffer(Adapter,((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE); | 360 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly "); |
| 414 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly "); | ||
| 415 | return STATUS_FAILURE; | 361 | return STATUS_FAILURE; |
| 416 | } | 362 | } |
| 417 | /* | 363 | /* |
| 418 | //update the leader to use the new length | 364 | * update the leader to use the new length |
| 419 | //The length of the control packet is length of message being sent + Leader length | 365 | * The length of the control packet is length of message being sent + Leader length |
| 420 | */ | 366 | */ |
| 421 | pLeader->PLength = pktlen; | 367 | pLeader->PLength = pktlen; |
| 422 | } | 368 | } |
| 423 | } | 369 | } |
| 370 | |||
| 371 | if (pktlen + LEADER_SIZE > MAX_CNTL_PKT_SIZE) | ||
| 372 | return -EINVAL; | ||
| 373 | |||
| 424 | memset(ctrl_buff, 0, pktlen+LEADER_SIZE); | 374 | memset(ctrl_buff, 0, pktlen+LEADER_SIZE); |
| 425 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength); | 375 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength); |
| 426 | *(PLEADER)ctrl_buff=*pLeader; | 376 | *(PLEADER)ctrl_buff = *pLeader; |
| 427 | memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength); | 377 | memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength); |
| 428 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet"); | 378 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet"); |
| 429 | 379 | ||
| 430 | /*Update the statistics counters */ | 380 | /* Update the statistics counters */ |
| 431 | spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); | 381 | spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); |
| 432 | Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost+=pLeader->PLength; | 382 | Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost += pLeader->PLength; |
| 433 | Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++; | 383 | Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++; |
| 434 | atomic_inc(&Adapter->TotalPacketCount); | 384 | atomic_inc(&Adapter->TotalPacketCount); |
| 435 | spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); | 385 | spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); |
| 436 | |||
| 437 | Adapter->PackInfo[HiPriority].bValid = TRUE; | 386 | Adapter->PackInfo[HiPriority].bValid = TRUE; |
| 438 | 387 | ||
| 439 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x", | 388 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x", |
| 440 | Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost, | 389 | Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost, |
| 441 | Adapter->PackInfo[HiPriority].bValid); | 390 | Adapter->PackInfo[HiPriority].bValid); |
| 442 | Status=STATUS_SUCCESS; | 391 | Status = STATUS_SUCCESS; |
| 443 | /*Queue the packet for transmission */ | 392 | /*Queue the packet for transmission */ |
| 444 | atomic_inc(&Adapter->index_wr_txcntrlpkt); | 393 | atomic_inc(&Adapter->index_wr_txcntrlpkt); |
| 445 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Calling transmit_packets"); | 394 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Calling transmit_packets"); |
| 446 | atomic_set(&Adapter->TxPktAvail, 1); | 395 | atomic_set(&Adapter->TxPktAvail, 1); |
| 447 | wake_up(&Adapter->tx_packet_wait_queue); | 396 | wake_up(&Adapter->tx_packet_wait_queue); |
| 397 | } else { | ||
| 398 | Status = -ENOMEM; | ||
| 399 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed"); | ||
| 448 | } | 400 | } |
| 449 | else | 401 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<===="); |
| 450 | { | ||
| 451 | Status=-ENOMEM; | ||
| 452 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed"); | ||
| 453 | } | ||
| 454 | BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<===="); | ||
| 455 | return Status; | 402 | return Status; |
| 456 | } | 403 | } |
| 457 | 404 | ||
| @@ -460,33 +407,30 @@ INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**<Logical Adapter*/ · 2 unmodified lines | |||
| 460 | * Function - SendStatisticsPointerRequest() | 407 | * Function - SendStatisticsPointerRequest() |
| 461 | * | 408 | * |
| 462 | * Description - This function builds and forwards the Statistics | 409 | * Description - This function builds and forwards the Statistics |
| 463 | * Pointer Request control Packet. | 410 | * Pointer Request control Packet. |
| 464 | * | 411 | * |
| 465 | * Parameters - Adapter : Pointer to Adapter structure. | 412 | * Parameters - Adapter : Pointer to Adapter structure. |
| 466 | * - pstStatisticsPtrRequest : Pointer to link request. | 413 | * - pstStatisticsPtrRequest : Pointer to link request. |
| 467 | * | 414 | * |
| 468 | * Returns - None. | 415 | * Returns - None. |
| 469 | *****************************************************************/ | 416 | *****************************************************************/ |
| 470 | static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, | 417 | static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, PLINK_REQUEST pstStatisticsPtrRequest) |
| 471 | PLINK_REQUEST pstStatisticsPtrRequest) | ||
| 472 | { | 418 | { |
| 473 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>"); | 419 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>"); |
| 474 | pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS; | 420 | pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS; |
| 475 | pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG);//minimum 4 bytes | 421 | pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG); /* minimum 4 bytes */ |
| 476 | pstStatisticsPtrRequest->szData[0] = STATISTICS_POINTER_REQ; | 422 | pstStatisticsPtrRequest->szData[0] = STATISTICS_POINTER_REQ; |
| 477 | 423 | CopyBufferToControlPacket(Adapter, pstStatisticsPtrRequest); | |
| 478 | CopyBufferToControlPacket(Adapter,pstStatisticsPtrRequest); | 424 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<====="); |
| 479 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<====="); | ||
| 480 | return; | 425 | return; |
| 481 | } | 426 | } |
| 482 | #endif | 427 | #endif |
| 483 | 428 | ||
| 484 | |||
| 485 | /****************************************************************** | 429 | /****************************************************************** |
| 486 | * Function - LinkMessage() | 430 | * Function - LinkMessage() |
| 487 | * | 431 | * |
| 488 | * Description - This function builds the Sync-up and Link-up request | 432 | * Description - This function builds the Sync-up and Link-up request |
| 489 | * packet messages depending on the device Link status. | 433 | * packet messages depending on the device Link status. |
| 490 | * | 434 | * |
| 491 | * Parameters - Adapter: Pointer to the Adapter structure. | 435 | * Parameters - Adapter: Pointer to the Adapter structure. |
| 492 | * | 436 | * |
| @@ -494,102 +438,90 @@ static VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, · 1 unmodified line | |||
| 494 | *******************************************************************/ | 438 | *******************************************************************/ |
| 495 | VOID LinkMessage(PMINI_ADAPTER Adapter) | 439 | VOID LinkMessage(PMINI_ADAPTER Adapter) |
| 496 | { | 440 | { |
| 497 | PLINK_REQUEST pstLinkRequest=NULL; | 441 | PLINK_REQUEST pstLinkRequest = NULL; |
| 498 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>"); | 442 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>"); |
| 499 | if(Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) | 443 | if (Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) { |
| 500 | { | ||
| 501 | pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); | 444 | pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); |
| 502 | if(!pstLinkRequest) | 445 | if (!pstLinkRequest) { |
| 503 | { | 446 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); |
| 504 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); | ||
| 505 | return; | 447 | return; |
| 506 | } | 448 | } |
| 507 | //sync up request... | 449 | /* sync up request... */ |
| 508 | Adapter->LinkStatus = WAIT_FOR_SYNC;// current link status | 450 | Adapter->LinkStatus = WAIT_FOR_SYNC; /* current link status */ |
| 509 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp..."); | 451 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp..."); |
| 510 | pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD; | 452 | pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD; |
| 511 | pstLinkRequest->szData[1]=LINK_SYNC_UP_SUBTYPE; | 453 | pstLinkRequest->szData[1] = LINK_SYNC_UP_SUBTYPE; |
| 512 | pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ; | 454 | pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ; |
| 513 | pstLinkRequest->Leader.PLength=sizeof(ULONG); | 455 | pstLinkRequest->Leader.PLength = sizeof(ULONG); |
| 514 | Adapter->bSyncUpRequestSent = TRUE; | 456 | Adapter->bSyncUpRequestSent = TRUE; |
| 515 | } | 457 | |
| 516 | else if(Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp) | 458 | } else if (Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp) { |
| 517 | { | ||
| 518 | pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); | 459 | pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); |
| 519 | if(!pstLinkRequest) | 460 | if (!pstLinkRequest) { |
| 520 | { | 461 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); |
| 521 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); | ||
| 522 | return; | 462 | return; |
| 523 | } | 463 | } |
| 524 | //LINK_UP_REQUEST | 464 | /* LINK_UP_REQUEST */ |
| 525 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp..."); | 465 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp..."); |
| 526 | pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD; | 466 | pstLinkRequest->szData[0] = LINK_UP_REQ_PAYLOAD; |
| 527 | pstLinkRequest->szData[1]=LINK_NET_ENTRY; | 467 | pstLinkRequest->szData[1] = LINK_NET_ENTRY; |
| 528 | pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ; | 468 | pstLinkRequest->Leader.Status = LINK_UP_CONTROL_REQ; |
| 529 | pstLinkRequest->Leader.PLength=sizeof(ULONG); | 469 | pstLinkRequest->Leader.PLength = sizeof(ULONG); |
| 530 | } | 470 | } |
| 531 | if(pstLinkRequest) | 471 | if (pstLinkRequest) { |
| 532 | { | 472 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket"); |
| 533 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket"); | ||
| 534 | CopyBufferToControlPacket(Adapter, pstLinkRequest); | 473 | CopyBufferToControlPacket(Adapter, pstLinkRequest); |
| 535 | kfree(pstLinkRequest); | 474 | kfree(pstLinkRequest); |
| 536 | } | 475 | } |
| 537 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <====="); | 476 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <====="); |
| 538 | return; | 477 | return; |
| 539 | } | 478 | } |
| 540 | 479 | ||
| 541 | |||
| 542 | /********************************************************************** | 480 | /********************************************************************** |
| 543 | * Function - StatisticsResponse() | 481 | * Function - StatisticsResponse() |
| 544 | * | 482 | * |
| 545 | * Description - This function handles the Statistics response packet. | 483 | * Description - This function handles the Statistics response packet. |
| 546 | * | 484 | * |
| 547 | * Parameters - Adapter : Pointer to the Adapter structure. | 485 | * Parameters - Adapter : Pointer to the Adapter structure. |
| 548 | * - pvBuffer: Starting address of Statistic response data. | 486 | * - pvBuffer: Starting address of Statistic response data. |
| 549 | * | 487 | * |
| 550 | * Returns - None. | 488 | * Returns - None. |
| 551 | ************************************************************************/ | 489 | ************************************************************************/ |
| 552 | VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer) | 490 | VOID StatisticsResponse(PMINI_ADAPTER Adapter, PVOID pvBuffer) |
| 553 | { | 491 | { |
| 554 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>",__FUNCTION__); | 492 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>", __func__); |
| 555 | Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer); | 493 | Adapter->StatisticsPointer = ntohl(*(__be32 *)pvBuffer); |
| 556 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer); | 494 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %x", (UINT)Adapter->StatisticsPointer); |
| 557 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====",__FUNCTION__); | 495 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====", __func__); |
| 558 | return; | 496 | return; |
| 559 | } | 497 | } |
| 560 | 498 | ||
| 561 | |||
| 562 | /********************************************************************** | 499 | /********************************************************************** |
| 563 | * Function - LinkControlResponseMessage() | 500 | * Function - LinkControlResponseMessage() |
| 564 | * | 501 | * |
| 565 | * Description - This function handles the Link response packets. | 502 | * Description - This function handles the Link response packets. |
| 566 | * | 503 | * |
| 567 | * Parameters - Adapter : Pointer to the Adapter structure. | 504 | * Parameters - Adapter : Pointer to the Adapter structure. |
| 568 | * - pucBuffer: Starting address of Link response data. | 505 | * - pucBuffer: Starting address of Link response data. |
| 569 | * | 506 | * |
| 570 | * Returns - None. | 507 | * Returns - None. |
| 571 | ***********************************************************************/ | 508 | ***********************************************************************/ |
| 572 | VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) | 509 | VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer) |
| 573 | { | 510 | { |
| 574 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>"); | 511 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>"); |
| 575 | 512 | ||
| 576 | if(*pucBuffer==LINK_UP_ACK) | 513 | if (*pucBuffer == LINK_UP_ACK) { |
| 577 | { | 514 | switch (*(pucBuffer+1)) { |
| 578 | switch(*(pucBuffer+1)) | 515 | case PHY_SYNC_ACHIVED: /* SYNCed UP */ |
| 579 | { | 516 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED"); |
| 580 | case PHY_SYNC_ACHIVED: //SYNCed UP | ||
| 581 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED"); | ||
| 582 | 517 | ||
| 583 | if(Adapter->LinkStatus == LINKUP_DONE) | 518 | if (Adapter->LinkStatus == LINKUP_DONE) |
| 584 | { | ||
| 585 | beceem_protocol_reset(Adapter); | 519 | beceem_protocol_reset(Adapter); |
| 586 | } | ||
| 587 | 520 | ||
| 588 | Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ; | 521 | Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX; |
| 589 | Adapter->LinkStatus=PHY_SYNC_ACHIVED; | 522 | Adapter->LinkStatus = PHY_SYNC_ACHIVED; |
| 590 | 523 | ||
| 591 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 524 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 592 | { | ||
| 593 | Adapter->DriverState = NO_NETWORK_ENTRY; | 525 | Adapter->DriverState = NO_NETWORK_ENTRY; |
| 594 | wake_up(&Adapter->LEDInfo.notify_led_event); | 526 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 595 | } | 527 | } |
| @@ -597,161 +529,145 @@ VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) · 1 unmodified line | |||
| 597 | LinkMessage(Adapter); | 529 | LinkMessage(Adapter); |
| 598 | break; | 530 | break; |
| 599 | 531 | ||
| 600 | case LINKUP_DONE: | 532 | case LINKUP_DONE: |
| 601 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE"); | 533 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE"); |
| 602 | Adapter->LinkStatus=LINKUP_DONE; | 534 | Adapter->LinkStatus = LINKUP_DONE; |
| 603 | Adapter->bPHSEnabled = *(pucBuffer+3); | 535 | Adapter->bPHSEnabled = *(pucBuffer+3); |
| 604 | Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK; | 536 | Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK; |
| 605 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x \n",Adapter->bPHSEnabled); | 537 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x\n", Adapter->bPHSEnabled); |
| 606 | if((FALSE == Adapter->bShutStatus)&& | 538 | |
| 607 | (FALSE == Adapter->IdleMode)) | 539 | if ((FALSE == Adapter->bShutStatus) && (FALSE == Adapter->IdleMode)) { |
| 608 | { | 540 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 609 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 541 | Adapter->DriverState = NORMAL_OPERATION; |
| 610 | { | 542 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 611 | Adapter->DriverState = NORMAL_OPERATION; | ||
| 612 | wake_up(&Adapter->LEDInfo.notify_led_event); | ||
| 613 | } | ||
| 614 | } | 543 | } |
| 615 | LinkMessage(Adapter); | 544 | } |
| 616 | break; | 545 | LinkMessage(Adapter); |
| 617 | case WAIT_FOR_SYNC: | 546 | break; |
| 618 | 547 | ||
| 619 | /* | 548 | case WAIT_FOR_SYNC: |
| 620 | * Driver to ignore the DREG_RECEIVED | 549 | /* |
| 621 | * WiMAX Application should handle this Message | 550 | * Driver to ignore the DREG_RECEIVED |
| 622 | */ | 551 | * WiMAX Application should handle this Message |
| 623 | //Adapter->liTimeSinceLastNetEntry = 0; | 552 | */ |
| 624 | Adapter->LinkUpStatus = 0; | 553 | /* Adapter->liTimeSinceLastNetEntry = 0; */ |
| 625 | Adapter->LinkStatus = 0; | 554 | Adapter->LinkUpStatus = 0; |
| 626 | Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ; | 555 | Adapter->LinkStatus = 0; |
| 627 | Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; | 556 | Adapter->usBestEffortQueueIndex = INVALID_QUEUE_INDEX; |
| 628 | Adapter->IdleMode = FALSE; | 557 | Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; |
| 629 | beceem_protocol_reset(Adapter); | 558 | Adapter->IdleMode = FALSE; |
| 559 | beceem_protocol_reset(Adapter); | ||
| 630 | 560 | ||
| 631 | break; | 561 | break; |
| 632 | case LINK_SHUTDOWN_REQ_FROM_FIRMWARE: | 562 | case LINK_SHUTDOWN_REQ_FROM_FIRMWARE: |
| 633 | case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW: | 563 | case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW: |
| 634 | { | 564 | { |
| 635 | HandleShutDownModeRequest(Adapter, pucBuffer); | 565 | HandleShutDownModeRequest(Adapter, pucBuffer); |
| 636 | } | ||
| 637 | break; | ||
| 638 | default: | ||
| 639 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x",*(pucBuffer+1)); | ||
| 640 | break; | ||
| 641 | } | 566 | } |
| 642 | } | 567 | break; |
| 643 | else if(SET_MAC_ADDRESS_RESPONSE==*pucBuffer) | 568 | default: |
| 644 | { | 569 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x", *(pucBuffer + 1)); |
| 570 | break; | ||
| 571 | } | ||
| 572 | } else if (SET_MAC_ADDRESS_RESPONSE == *pucBuffer) { | ||
| 645 | PUCHAR puMacAddr = (pucBuffer + 1); | 573 | PUCHAR puMacAddr = (pucBuffer + 1); |
| 646 | Adapter->LinkStatus=SYNC_UP_REQUEST; | 574 | Adapter->LinkStatus = SYNC_UP_REQUEST; |
| 647 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP"); | 575 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP"); |
| 648 | LinkMessage(Adapter); | 576 | LinkMessage(Adapter); |
| 649 | memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); | 577 | memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); |
| 650 | } | 578 | } |
| 651 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====",__FUNCTION__); | 579 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====", __func__); |
| 652 | return; | 580 | return; |
| 653 | } | 581 | } |
| 654 | 582 | ||
| 655 | void SendIdleModeResponse(PMINI_ADAPTER Adapter) | 583 | void SendIdleModeResponse(PMINI_ADAPTER Adapter) |
| 656 | { | 584 | { |
| 657 | INT status = 0, NVMAccess = 0,lowPwrAbortMsg = 0; | 585 | INT status = 0, NVMAccess = 0, lowPwrAbortMsg = 0; |
| 658 | struct timeval tv; | 586 | struct timeval tv; |
| 659 | CONTROL_MESSAGE stIdleResponse = {{0}}; | 587 | CONTROL_MESSAGE stIdleResponse = {{0} }; |
| 660 | memset(&tv, 0, sizeof(tv)); | 588 | memset(&tv, 0, sizeof(tv)); |
| 661 | stIdleResponse.Leader.Status = IDLE_MESSAGE; | 589 | stIdleResponse.Leader.Status = IDLE_MESSAGE; |
| 662 | stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH; | 590 | stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH; |
| 663 | stIdleResponse.szData[0] = GO_TO_IDLE_MODE_PAYLOAD; | 591 | stIdleResponse.szData[0] = GO_TO_IDLE_MODE_PAYLOAD; |
| 664 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL," ============>"); | 592 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, " ============>"); |
| 665 | 593 | ||
| 666 | /********************************* | 594 | /********************************* |
| 667 | **down_trylock - | 595 | *down_trylock - |
| 668 | ** if [ semaphore is available ] | 596 | * if [ semaphore is available ] |
| 669 | ** acquire semaphone and return value 0 ; | 597 | * acquire semaphone and return value 0 ; |
| 670 | ** else | 598 | * else |
| 671 | ** return non-zero value ; | 599 | * return non-zero value ; |
| 672 | ** | 600 | * |
| 673 | ***********************************/ | 601 | ***********************************/ |
| 674 | 602 | ||
| 675 | NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); | 603 | NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); |
| 604 | lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync); | ||
| 676 | 605 | ||
| 677 | lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync); | ||
| 678 | 606 | ||
| 607 | if ((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) && | ||
| 608 | (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) { | ||
| 679 | 609 | ||
| 680 | if((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) && | 610 | if (!NVMAccess) |
| 681 | (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) ) | ||
| 682 | { | ||
| 683 | if(!NVMAccess) | ||
| 684 | up(&Adapter->NVMRdmWrmLock); | 611 | up(&Adapter->NVMRdmWrmLock); |
| 685 | 612 | ||
| 686 | if(!lowPwrAbortMsg) | 613 | if (!lowPwrAbortMsg) |
| 687 | up(&Adapter->LowPowerModeSync); | 614 | up(&Adapter->LowPowerModeSync); |
| 688 | 615 | ||
| 689 | stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on. | 616 | stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */ |
| 690 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!"); | 617 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!"); |
| 691 | Adapter->bPreparingForLowPowerMode = FALSE; | 618 | Adapter->bPreparingForLowPowerMode = FALSE; |
| 692 | } | 619 | } else { |
| 693 | else | 620 | stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; /* 2; Idle ACK */ |
| 694 | { | ||
| 695 | stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; //2;//Idle ACK | ||
| 696 | Adapter->StatisticsPointer = 0; | 621 | Adapter->StatisticsPointer = 0; |
| 697 | 622 | ||
| 698 | /* Wait for the LED to TURN OFF before sending ACK response */ | 623 | /* Wait for the LED to TURN OFF before sending ACK response */ |
| 699 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 624 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 700 | { | ||
| 701 | INT iRetVal = 0; | 625 | INT iRetVal = 0; |
| 702 | 626 | ||
| 703 | /* Wake the LED Thread with IDLEMODE_ENTER State */ | 627 | /* Wake the LED Thread with IDLEMODE_ENTER State */ |
| 704 | Adapter->DriverState = LOWPOWER_MODE_ENTER; | 628 | Adapter->DriverState = LOWPOWER_MODE_ENTER; |
| 705 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld",jiffies); | 629 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld", jiffies); |
| 706 | wake_up(&Adapter->LEDInfo.notify_led_event); | 630 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 707 | 631 | ||
| 708 | /* Wait for 1 SEC for LED to OFF */ | 632 | /* Wait for 1 SEC for LED to OFF */ |
| 709 | iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, \ | 633 | iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000)); |
| 710 | Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000)); | ||
| 711 | |||
| 712 | 634 | ||
| 713 | /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */ | 635 | /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */ |
| 714 | if(iRetVal <= 0) | 636 | if (iRetVal <= 0) { |
| 715 | { | 637 | stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE; /* NACK- device access is going on. */ |
| 716 | stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on. | ||
| 717 | Adapter->DriverState = NORMAL_OPERATION; | 638 | Adapter->DriverState = NORMAL_OPERATION; |
| 718 | wake_up(&Adapter->LEDInfo.notify_led_event); | 639 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 719 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!"); | 640 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!"); |
| 720 | } | 641 | } |
| 721 | } | 642 | } |
| 722 | if(stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) | 643 | |
| 723 | { | 644 | if (stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) { |
| 724 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"ACKING IDLE MODE !!!!!!!!!"); | 645 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "ACKING IDLE MODE !!!!!!!!!"); |
| 725 | down(&Adapter->rdmwrmsync); | 646 | down(&Adapter->rdmwrmsync); |
| 726 | Adapter->bPreparingForLowPowerMode = TRUE; | 647 | Adapter->bPreparingForLowPowerMode = TRUE; |
| 727 | up(&Adapter->rdmwrmsync); | 648 | up(&Adapter->rdmwrmsync); |
| 728 | //Killing all URBS. | 649 | /* Killing all URBS. */ |
| 729 | if(Adapter->bDoSuspend == TRUE) | 650 | if (Adapter->bDoSuspend == TRUE) |
| 730 | Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); | 651 | Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); |
| 731 | 652 | } else { | |
| 732 | } | ||
| 733 | else | ||
| 734 | { | ||
| 735 | Adapter->bPreparingForLowPowerMode = FALSE; | 653 | Adapter->bPreparingForLowPowerMode = FALSE; |
| 736 | } | 654 | } |
| 737 | 655 | ||
| 738 | if(!NVMAccess) | 656 | if (!NVMAccess) |
| 739 | up(&Adapter->NVMRdmWrmLock); | 657 | up(&Adapter->NVMRdmWrmLock); |
| 740 | 658 | ||
| 741 | if(!lowPwrAbortMsg) | 659 | if (!lowPwrAbortMsg) |
| 742 | up(&Adapter->LowPowerModeSync); | 660 | up(&Adapter->LowPowerModeSync); |
| 743 | |||
| 744 | } | 661 | } |
| 745 | status = CopyBufferToControlPacket(Adapter,&stIdleResponse); | 662 | |
| 746 | if((status != STATUS_SUCCESS)) | 663 | status = CopyBufferToControlPacket(Adapter, &stIdleResponse); |
| 747 | { | 664 | if ((status != STATUS_SUCCESS)) { |
| 748 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"fail to send the Idle mode Request \n"); | 665 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "fail to send the Idle mode Request\n"); |
| 749 | Adapter->bPreparingForLowPowerMode = FALSE; | 666 | Adapter->bPreparingForLowPowerMode = FALSE; |
| 750 | StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); | 667 | StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); |
| 751 | } | 668 | } |
| 752 | do_gettimeofday(&tv); | 669 | do_gettimeofday(&tv); |
| 753 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); | 670 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec * 1000 + tv.tv_usec / 1000); |
| 754 | |||
| 755 | } | 671 | } |
| 756 | 672 | ||
| 757 | /****************************************************************** | 673 | /****************************************************************** |
| @@ -765,307 +681,264 @@ void SendIdleModeResponse(PMINI_ADAPTER Adapter) · 7 unmodified lines | |||
| 765 | *******************************************************************/ | 681 | *******************************************************************/ |
| 766 | VOID DumpPackInfo(PMINI_ADAPTER Adapter) | 682 | VOID DumpPackInfo(PMINI_ADAPTER Adapter) |
| 767 | { | 683 | { |
| 768 | 684 | UINT uiLoopIndex = 0; | |
| 769 | UINT uiLoopIndex = 0; | ||
| 770 | UINT uiIndex = 0; | 685 | UINT uiIndex = 0; |
| 771 | UINT uiClsfrIndex = 0; | 686 | UINT uiClsfrIndex = 0; |
| 772 | S_CLASSIFIER_RULE *pstClassifierEntry = NULL; | 687 | S_CLASSIFIER_RULE *pstClassifierEntry = NULL; |
| 773 | 688 | ||
| 774 | for(uiLoopIndex=0;uiLoopIndex<NO_OF_QUEUES;uiLoopIndex++) | 689 | for (uiLoopIndex = 0; uiLoopIndex < NO_OF_QUEUES; uiLoopIndex++) { |
| 775 | { | 690 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "*********** Showing Details Of Queue %d***** ******", uiLoopIndex); |
| 776 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"*********** Showing Details Of Queue %d***** ******",uiLoopIndex); | 691 | if (FALSE == Adapter->PackInfo[uiLoopIndex].bValid) { |
| 777 | if(FALSE == Adapter->PackInfo[uiLoopIndex].bValid) | 692 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid is FALSE for %X index\n", uiLoopIndex); |
| 778 | { | ||
| 779 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid is FALSE for %X index\n",uiLoopIndex); | ||
| 780 | continue; | 693 | continue; |
| 781 | } | 694 | } |
| 782 | 695 | ||
| 783 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," Dumping SF Rule Entry For SFID %lX \n",Adapter->PackInfo[uiLoopIndex].ulSFID); | 696 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " Dumping SF Rule Entry For SFID %lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID); |
| 784 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," ucDirection %X \n",Adapter->PackInfo[uiLoopIndex].ucDirection); | 697 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, " ucDirection %X\n", Adapter->PackInfo[uiLoopIndex].ucDirection); |
| 785 | if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) | 698 | |
| 786 | { | 699 | if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) |
| 787 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv6 Service Flow \n"); | 700 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv6 Service Flow\n"); |
| 788 | } | ||
| 789 | else | 701 | else |
| 790 | { | 702 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Ipv4 Service Flow\n"); |
| 791 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv4 Service Flow \n"); | ||
| 792 | } | ||
| 793 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," SF Traffic Priority %X \n",Adapter->PackInfo[uiLoopIndex].u8TrafficPriority); | ||
| 794 | 703 | ||
| 795 | for(uiClsfrIndex=0;uiClsfrIndex<MAX_CLASSIFIERS;uiClsfrIndex++) | 704 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SF Traffic Priority %X\n", Adapter->PackInfo[uiLoopIndex].u8TrafficPriority); |
| 796 | { | 705 | |
| 706 | for (uiClsfrIndex = 0; uiClsfrIndex < MAX_CLASSIFIERS; uiClsfrIndex++) { | ||
| 797 | pstClassifierEntry = &Adapter->astClassifierTable[uiClsfrIndex]; | 707 | pstClassifierEntry = &Adapter->astClassifierTable[uiClsfrIndex]; |
| 798 | if(!pstClassifierEntry->bUsed) | 708 | if (!pstClassifierEntry->bUsed) |
| 799 | continue; | 709 | continue; |
| 800 | 710 | ||
| 801 | if(pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID) | 711 | if (pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID) |
| 802 | continue; | 712 | continue; |
| 803 | 713 | ||
| 804 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n",uiClsfrIndex,pstClassifierEntry->uiClassifierRuleIndex); | 714 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n", uiClsfrIndex, pstClassifierEntry->uiClassifierRuleIndex); |
| 805 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n",uiClsfrIndex,pstClassifierEntry->usVCID_Value); | 715 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n", uiClsfrIndex, pstClassifierEntry->usVCID_Value); |
| 806 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n",uiClsfrIndex,pstClassifierEntry->bProtocolValid); | 716 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n", uiClsfrIndex, pstClassifierEntry->bProtocolValid); |
| 807 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n",uiClsfrIndex,pstClassifierEntry->bTOSValid); | 717 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n", uiClsfrIndex, pstClassifierEntry->bTOSValid); |
| 808 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bDestIpValid); | 718 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bDestIpValid); |
| 809 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bSrcIpValid); | 719 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n", uiClsfrIndex, pstClassifierEntry->bSrcIpValid); |
| 810 | 720 | ||
| 811 | 721 | for (uiIndex = 0; uiIndex < MAX_PORT_RANGE; uiIndex++) { | |
| 812 | for(uiIndex=0;uiIndex<MAX_PORT_RANGE;uiIndex++) | 722 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeLo:%X\n", pstClassifierEntry->usSrcPortRangeLo[uiIndex]); |
| 813 | { | 723 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusSrcPortRangeHi:%X\n", pstClassifierEntry->usSrcPortRangeHi[uiIndex]); |
| 814 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusSrcPortRangeLo:%X\n",pstClassifierEntry->usSrcPortRangeLo[uiIndex]); | 724 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeLo:%X\n", pstClassifierEntry->usDestPortRangeLo[uiIndex]); |
| 815 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusSrcPortRangeHi:%X\n",pstClassifierEntry->usSrcPortRangeHi[uiIndex]); | 725 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tusDestPortRangeHi:%X\n", pstClassifierEntry->usDestPortRangeHi[uiIndex]); |
| 816 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeLo:%X\n",pstClassifierEntry->usDestPortRangeLo[uiIndex]); | ||
| 817 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeHi:%X\n",pstClassifierEntry->usDestPortRangeHi[uiIndex]); | ||
| 818 | } | 726 | } |
| 819 | 727 | ||
| 820 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," \tucIPSourceAddressLength : 0x%x\n",pstClassifierEntry->ucIPSourceAddressLength); | 728 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPSourceAddressLength : 0x%x\n", pstClassifierEntry->ucIPSourceAddressLength); |
| 821 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucIPDestinationAddressLength : 0x%x\n",pstClassifierEntry->ucIPDestinationAddressLength); | 729 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucIPDestinationAddressLength : 0x%x\n", pstClassifierEntry->ucIPDestinationAddressLength); |
| 822 | for(uiIndex=0;uiIndex<pstClassifierEntry->ucIPSourceAddressLength;uiIndex++) | 730 | for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPSourceAddressLength; uiIndex++) { |
| 823 | { | 731 | if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) { |
| 824 | if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) | 732 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpAddr :\n"); |
| 825 | { | ||
| 826 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpAddr :\n"); | ||
| 827 | DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr); | 733 | DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr); |
| 828 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpMask :\n"); | 734 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulSrcIpMask :\n"); |
| 829 | DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask); | 735 | DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask); |
| 830 | } | 736 | } else { |
| 831 | else | 737 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpAddr:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]); |
| 832 | { | 738 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulSrcIpMask:%lX\n", pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]); |
| 833 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpAddr:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]); | ||
| 834 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpMask:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]); | ||
| 835 | } | 739 | } |
| 836 | } | 740 | } |
| 837 | for(uiIndex=0;uiIndex<pstClassifierEntry->ucIPDestinationAddressLength;uiIndex++) | 741 | |
| 838 | { | 742 | for (uiIndex = 0; uiIndex < pstClassifierEntry->ucIPDestinationAddressLength; uiIndex++) { |
| 839 | if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) | 743 | if (Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) { |
| 840 | { | 744 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpAddr :\n"); |
| 841 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpAddr :\n"); | ||
| 842 | DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Addr); | 745 | DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Addr); |
| 843 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpMask :\n"); | 746 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tIpv6 ulDestIpMask :\n"); |
| 844 | DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Mask); | 747 | DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Mask); |
| 845 | 748 | } else { | |
| 846 | } | 749 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpAddr:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]); |
| 847 | else | 750 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tulDestIpMask:%lX\n", pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]); |
| 848 | { | ||
| 849 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpAddr:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]); | ||
| 850 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpMask:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]); | ||
| 851 | } | 751 | } |
| 852 | } | 752 | } |
| 853 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucProtocol:0x%X\n",pstClassifierEntry->ucProtocol[0]); | 753 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tucProtocol:0x%X\n", pstClassifierEntry->ucProtocol[0]); |
| 854 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tu8ClassifierRulePriority:%X\n",pstClassifierEntry->u8ClassifierRulePriority); | 754 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\tu8ClassifierRulePriority:%X\n", pstClassifierEntry->u8ClassifierRulePriority); |
| 855 | |||
| 856 | |||
| 857 | } | 755 | } |
| 858 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ulSFID:%lX\n",Adapter->PackInfo[uiLoopIndex].ulSFID); | 756 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ulSFID:%lX\n", Adapter->PackInfo[uiLoopIndex].ulSFID); |
| 859 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"usVCID_Value:%X\n",Adapter->PackInfo[uiLoopIndex].usVCID_Value); | 757 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "usVCID_Value:%X\n", Adapter->PackInfo[uiLoopIndex].usVCID_Value); |
| 860 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"PhsEnabled: 0x%X\n",Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled); | 758 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "PhsEnabled: 0x%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled); |
| 861 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThreshold:%X\n",Adapter->PackInfo[uiLoopIndex].uiThreshold); | 759 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThreshold:%X\n", Adapter->PackInfo[uiLoopIndex].uiThreshold); |
| 862 | 760 | ||
| 863 | 761 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bValid:%X\n", Adapter->PackInfo[uiLoopIndex].bValid); | |
| 864 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid:%X\n",Adapter->PackInfo[uiLoopIndex].bValid); | 762 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bActive:%X\n", Adapter->PackInfo[uiLoopIndex].bActive); |
| 865 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bActive:%X\n",Adapter->PackInfo[uiLoopIndex].bActive); | 763 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent); |
| 866 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent); | 764 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "u8QueueType:%X\n", Adapter->PackInfo[uiLoopIndex].u8QueueType); |
| 867 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"u8QueueType:%X\n",Adapter->PackInfo[uiLoopIndex].u8QueueType); | 765 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxBucketSize:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize); |
| 868 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxBucketSize:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize); | 766 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPerSFTxResourceCount:%X\n", atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount)); |
| 869 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPerSFTxResourceCount:%X\n",atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount)); | 767 | /* DumpDebug(DUMP_INFO,("bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport)); */ |
| 870 | //DumpDebug(DUMP_INFO,(" bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport)); | 768 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget); |
| 871 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget); | 769 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentBytesOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost); |
| 872 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentBytesOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost); | 770 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentPacketsOnHost:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost); |
| 873 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentPacketsOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost); | 771 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes); |
| 874 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes); | 772 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiDroppedCountPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets); |
| 875 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets); | 773 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentBytes); |
| 876 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentBytes); | 774 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiSentPackets:%X\n", Adapter->PackInfo[uiLoopIndex].uiSentPackets); |
| 877 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentPackets); | 775 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentDrainRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate); |
| 878 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentDrainRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate); | 776 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiThisPeriodSentBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes); |
| 879 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThisPeriodSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes); | 777 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liDrainCalculated:%llX\n", Adapter->PackInfo[uiLoopIndex].liDrainCalculated); |
| 880 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liDrainCalculated:%llX\n",Adapter->PackInfo[uiLoopIndex].liDrainCalculated); | 778 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiCurrentTokenCount:%X\n", Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount); |
| 881 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentTokenCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount); | 779 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "liLastUpdateTokenAt:%llX\n", Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt); |
| 882 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liLastUpdateTokenAt:%llX\n",Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt); | 780 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxAllowedRate:%X\n", Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate); |
| 883 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxAllowedRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate); | 781 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiPendedLast:%X\n", Adapter->PackInfo[uiLoopIndex].uiPendedLast); |
| 884 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPendedLast:%X\n",Adapter->PackInfo[uiLoopIndex].uiPendedLast); | 782 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "NumOfPacketsSent:%X\n", Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent); |
| 885 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"NumOfPacketsSent:%X\n",Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent); | 783 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection); |
| 886 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection); | 784 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID); |
| 887 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID); | 785 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid); |
| 888 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid); | 786 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid); |
| 889 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid); | 787 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid); |
| 890 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid); | 788 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid); |
| 891 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid); | 789 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet); |
| 892 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet); | 790 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet); |
| 893 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet); | 791 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet); |
| 894 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet); | 792 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority); |
| 895 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority); | 793 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n", Adapter->PackInfo[uiLoopIndex].uiMaxLatency); |
| 896 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n",Adapter->PackInfo[uiLoopIndex].uiMaxLatency); | 794 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n", Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2], Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]); |
| 897 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n",Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]); | 795 | /* BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled); |
| 898 | // BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled); | 796 | * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes); |
| 899 | // BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes); | 797 | * BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes); |
| 900 | // BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes); | 798 | * DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount)); |
| 901 | // DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount)); | 799 | */ |
| 902 | } | 800 | } |
| 903 | 801 | ||
| 904 | for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++) | 802 | for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++) |
| 905 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aRxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aRxPktSizeHist[uiLoopIndex]); | 803 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aRxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aRxPktSizeHist[uiLoopIndex]); |
| 906 | 804 | ||
| 907 | for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++) | 805 | for (uiLoopIndex = 0; uiLoopIndex < MIBS_MAX_HIST_ENTRIES; uiLoopIndex++) |
| 908 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aTxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aTxPktSizeHist[uiLoopIndex]); | 806 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Adapter->aTxPktSizeHist[%x] = %x\n", uiLoopIndex, Adapter->aTxPktSizeHist[uiLoopIndex]); |
| 909 | |||
| 910 | |||
| 911 | 807 | ||
| 912 | return; | 808 | return; |
| 913 | |||
| 914 | |||
| 915 | } | 809 | } |
| 916 | 810 | ||
| 917 | int reset_card_proc(PMINI_ADAPTER ps_adapter) | 811 | int reset_card_proc(PMINI_ADAPTER ps_adapter) |
| 918 | { | 812 | { |
| 919 | int retval = STATUS_SUCCESS; | 813 | int retval = STATUS_SUCCESS; |
| 920 | 814 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); | |
| 921 | PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); | ||
| 922 | PS_INTERFACE_ADAPTER psIntfAdapter = NULL; | 815 | PS_INTERFACE_ADAPTER psIntfAdapter = NULL; |
| 923 | unsigned int value = 0, uiResetValue = 0; | 816 | unsigned int value = 0, uiResetValue = 0; |
| 924 | 817 | ||
| 925 | psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter)) ; | 818 | psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter)); |
| 926 | |||
| 927 | ps_adapter->bDDRInitDone = FALSE; | 819 | ps_adapter->bDDRInitDone = FALSE; |
| 928 | 820 | ||
| 929 | if(ps_adapter->chip_id >= T3LPB) | 821 | if (ps_adapter->chip_id >= T3LPB) { |
| 930 | { | 822 | /* SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before */ |
| 931 | //SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before | 823 | rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value)); |
| 932 | rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value)); | 824 | rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value)); |
| 933 | rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value)); | ||
| 934 | 825 | ||
| 935 | //making bit[6...5] same as was before f/w download. this setting force the h/w to | 826 | /* making bit[6...5] same as was before f/w download. this setting force the h/w to */ |
| 936 | //re-populated the SP RAM area with the string descriptor . | 827 | /* re-populated the SP RAM area with the string descriptor. */ |
| 937 | value = value | (ps_adapter->syscfgBefFwDld & 0x00000060) ; | 828 | value = value | (ps_adapter->syscfgBefFwDld & 0x00000060); |
| 938 | wrmalt(ps_adapter, SYS_CFG, &value, sizeof(value)); | 829 | wrmalt(ps_adapter, SYS_CFG, &value, sizeof(value)); |
| 939 | } | 830 | } |
| 940 | 831 | ||
| 941 | //killing all submitted URBs. | 832 | /* killing all submitted URBs. */ |
| 942 | psIntfAdapter->psAdapter->StopAllXaction = TRUE ; | 833 | psIntfAdapter->psAdapter->StopAllXaction = TRUE; |
| 943 | Bcm_kill_all_URBs(psIntfAdapter); | 834 | Bcm_kill_all_URBs(psIntfAdapter); |
| 944 | /* Reset the UMA-B Device */ | 835 | /* Reset the UMA-B Device */ |
| 945 | if(ps_adapter->chip_id >= T3LPB) | 836 | if (ps_adapter->chip_id >= T3LPB) { |
| 946 | { | 837 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B\n"); |
| 947 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B \n"); | ||
| 948 | retval = usb_reset_device(psIntfAdapter->udev); | 838 | retval = usb_reset_device(psIntfAdapter->udev); |
| 839 | psIntfAdapter->psAdapter->StopAllXaction = FALSE; | ||
| 949 | 840 | ||
| 950 | psIntfAdapter->psAdapter->StopAllXaction = FALSE ; | 841 | if (retval != STATUS_SUCCESS) { |
| 951 | 842 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval); | |
| 952 | if(retval != STATUS_SUCCESS) | ||
| 953 | { | ||
| 954 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval); | ||
| 955 | goto err_exit; | 843 | goto err_exit; |
| 956 | } | 844 | } |
| 845 | |||
| 957 | if (ps_adapter->chip_id == BCS220_2 || | 846 | if (ps_adapter->chip_id == BCS220_2 || |
| 958 | ps_adapter->chip_id == BCS220_2BC || | 847 | ps_adapter->chip_id == BCS220_2BC || |
| 959 | ps_adapter->chip_id == BCS250_BC || | 848 | ps_adapter->chip_id == BCS250_BC || |
| 960 | ps_adapter->chip_id == BCS220_3) | 849 | ps_adapter->chip_id == BCS220_3) { |
| 961 | { | 850 | |
| 962 | retval = rdmalt(ps_adapter,HPM_CONFIG_LDO145, &value, sizeof(value)); | 851 | retval = rdmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value)); |
| 963 | if( retval < 0) | 852 | if (retval < 0) { |
| 964 | { | 853 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval); |
| 965 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval); | ||
| 966 | goto err_exit; | 854 | goto err_exit; |
| 967 | } | 855 | } |
| 968 | //setting 0th bit | 856 | /* setting 0th bit */ |
| 969 | value |= (1<<0); | 857 | value |= (1<<0); |
| 970 | retval = wrmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value)); | 858 | retval = wrmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value)); |
| 971 | if( retval < 0) | 859 | if (retval < 0) { |
| 972 | { | 860 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval); |
| 973 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); | ||
| 974 | goto err_exit; | 861 | goto err_exit; |
| 975 | } | 862 | } |
| 976 | } | 863 | } |
| 977 | 864 | } else { | |
| 978 | } | 865 | retval = rdmalt(ps_adapter, 0x0f007018, &value, sizeof(value)); |
| 979 | else | 866 | if (retval < 0) { |
| 980 | { | 867 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "read failed with status :%d", retval); |
| 981 | retval = rdmalt(ps_adapter,0x0f007018, &value, sizeof(value)); | ||
| 982 | if( retval < 0) { | ||
| 983 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval); | ||
| 984 | goto err_exit; | 868 | goto err_exit; |
| 985 | } | 869 | } |
| 986 | value&=(~(1<<16)); | 870 | value &= (~(1<<16)); |
| 987 | retval= wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value)) ; | 871 | retval = wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value)); |
| 988 | if( retval < 0) { | 872 | if (retval < 0) { |
| 989 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); | 873 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval); |
| 990 | goto err_exit; | 874 | goto err_exit; |
| 991 | } | 875 | } |
| 992 | 876 | ||
| 993 | // Toggling the GPIO 8, 9 | 877 | /* Toggling the GPIO 8, 9 */ |
| 994 | value = 0; | 878 | value = 0; |
| 995 | retval = wrmalt(ps_adapter, GPIO_OUTPUT_REGISTER, &value, sizeof(value)); | 879 | retval = wrmalt(ps_adapter, GPIO_OUTPUT_REGISTER, &value, sizeof(value)); |
| 996 | if(retval < 0) { | 880 | if (retval < 0) { |
| 997 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); | 881 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval); |
| 998 | goto err_exit; | 882 | goto err_exit; |
| 999 | } | 883 | } |
| 1000 | value = 0x300; | 884 | value = 0x300; |
| 1001 | retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value)) ; | 885 | retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value)); |
| 1002 | if(retval < 0) { | 886 | if (retval < 0) { |
| 1003 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); | 887 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "write failed with status :%d", retval); |
| 1004 | goto err_exit; | 888 | goto err_exit; |
| 1005 | } | 889 | } |
| 1006 | mdelay(50); | 890 | mdelay(50); |
| 1007 | } | 891 | } |
| 1008 | 892 | ||
| 1009 | //ps_adapter->downloadDDR = false; | 893 | /* ps_adapter->downloadDDR = false; */ |
| 1010 | 894 | if (ps_adapter->bFlashBoot) { | |
| 1011 | if(ps_adapter->bFlashBoot) | 895 | /* In flash boot mode MIPS state register has reverse polarity. |
| 1012 | { | 896 | * So just or with setting bit 30. |
| 1013 | //In flash boot mode MIPS state register has reverse polarity. | 897 | * Make the MIPS in Reset state. |
| 1014 | // So just or with setting bit 30. | 898 | */ |
| 1015 | //Make the MIPS in Reset state. | ||
| 1016 | rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue)); | 899 | rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue)); |
| 1017 | 900 | uiResetValue |= (1<<30); | |
| 1018 | uiResetValue |=(1<<30); | ||
| 1019 | wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue)); | 901 | wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue)); |
| 1020 | } | 902 | } |
| 1021 | 903 | ||
| 1022 | if(ps_adapter->chip_id >= T3LPB) | 904 | if (ps_adapter->chip_id >= T3LPB) { |
| 1023 | { | ||
| 1024 | uiResetValue = 0; | 905 | uiResetValue = 0; |
| 1025 | // | 906 | /* |
| 1026 | // WA for SYSConfig Issue. | 907 | * WA for SYSConfig Issue. |
| 1027 | // Read SYSCFG Twice to make it writable. | 908 | * Read SYSCFG Twice to make it writable. |
| 1028 | // | 909 | */ |
| 1029 | rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); | 910 | rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); |
| 1030 | if(uiResetValue & (1<<4)) | 911 | if (uiResetValue & (1<<4)) { |
| 1031 | { | ||
| 1032 | uiResetValue = 0; | 912 | uiResetValue = 0; |
| 1033 | rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));//2nd read to make it writable. | 913 | rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); /* 2nd read to make it writable. */ |
| 1034 | uiResetValue &= (~(1<<4)); | 914 | uiResetValue &= (~(1<<4)); |
| 1035 | wrmalt(ps_adapter,SYS_CFG, &uiResetValue, sizeof(uiResetValue)); | 915 | wrmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); |
| 1036 | } | 916 | } |
| 1037 | |||
| 1038 | } | 917 | } |
| 1039 | uiResetValue = 0; | 918 | uiResetValue = 0; |
| 1040 | wrmalt(ps_adapter, 0x0f01186c, &uiResetValue, sizeof(uiResetValue)); | 919 | wrmalt(ps_adapter, 0x0f01186c, &uiResetValue, sizeof(uiResetValue)); |
| 1041 | 920 | ||
| 1042 | err_exit : | 921 | err_exit: |
| 1043 | psIntfAdapter->psAdapter->StopAllXaction = FALSE ; | 922 | psIntfAdapter->psAdapter->StopAllXaction = FALSE; |
| 1044 | return retval; | 923 | return retval; |
| 1045 | } | 924 | } |
| 1046 | 925 | ||
| 1047 | int run_card_proc(PMINI_ADAPTER ps_adapter ) | 926 | int run_card_proc(PMINI_ADAPTER ps_adapter) |
| 1048 | { | 927 | { |
| 1049 | unsigned int value=0; | 928 | unsigned int value = 0; |
| 1050 | { | 929 | { |
| 1051 | 930 | if (rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) { | |
| 1052 | if(rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) { | 931 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__); |
| 1053 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__); | ||
| 1054 | return STATUS_FAILURE; | 932 | return STATUS_FAILURE; |
| 1055 | } | 933 | } |
| 1056 | 934 | ||
| 1057 | if(ps_adapter->bFlashBoot) | 935 | if (ps_adapter->bFlashBoot) |
| 1058 | { | 936 | value &= (~(1<<30)); |
| 1059 | |||
| 1060 | value&=(~(1<<30)); | ||
| 1061 | } | ||
| 1062 | else | 937 | else |
| 1063 | { | 938 | value |= (1<<30); |
| 1064 | value |=(1<<30); | ||
| 1065 | } | ||
| 1066 | 939 | ||
| 1067 | if(wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) { | 940 | if (wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) { |
| 1068 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__); | 941 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "%s:%d\n", __func__, __LINE__); |
| 1069 | return STATUS_FAILURE; | 942 | return STATUS_FAILURE; |
| 1070 | } | 943 | } |
| 1071 | } | 944 | } |
| @@ -1074,104 +947,87 @@ int run_card_proc(PMINI_ADAPTER ps_adapter ) · 2 unmodified lines | |||
| 1074 | 947 | ||
| 1075 | int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) | 948 | int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) |
| 1076 | { | 949 | { |
| 1077 | |||
| 1078 | int status; | 950 | int status; |
| 1079 | UINT value = 0; | 951 | UINT value = 0; |
| 1080 | /* | 952 | /* |
| 1081 | * Create the threads first and then download the | 953 | * Create the threads first and then download the |
| 1082 | * Firm/DDR Settings.. | 954 | * Firm/DDR Settings.. |
| 1083 | */ | 955 | */ |
| 1084 | |||
| 1085 | status = create_worker_threads(ps_adapter); | 956 | status = create_worker_threads(ps_adapter); |
| 1086 | if (status<0) | 957 | if (status < 0) |
| 1087 | return status; | 958 | return status; |
| 1088 | 959 | ||
| 1089 | /* | 960 | status = bcm_parse_target_params(ps_adapter); |
| 1090 | * For Downloading the Firm, parse the cfg file first. | 961 | if (status) |
| 1091 | */ | ||
| 1092 | status = bcm_parse_target_params (ps_adapter); | ||
| 1093 | if(status){ | ||
| 1094 | return status; | 962 | return status; |
| 1095 | } | ||
| 1096 | 963 | ||
| 1097 | if(ps_adapter->chip_id >= T3LPB) | 964 | if (ps_adapter->chip_id >= T3LPB) { |
| 1098 | { | 965 | rdmalt(ps_adapter, SYS_CFG, &value, sizeof(value)); |
| 1099 | rdmalt(ps_adapter, SYS_CFG, &value, sizeof (value)); | 966 | ps_adapter->syscfgBefFwDld = value; |
| 1100 | ps_adapter->syscfgBefFwDld = value ; | 967 | |
| 1101 | if((value & 0x60)== 0) | 968 | if ((value & 0x60) == 0) |
| 1102 | { | ||
| 1103 | ps_adapter->bFlashBoot = TRUE; | 969 | ps_adapter->bFlashBoot = TRUE; |
| 1104 | } | ||
| 1105 | } | 970 | } |
| 1106 | 971 | ||
| 1107 | reset_card_proc(ps_adapter); | 972 | reset_card_proc(ps_adapter); |
| 1108 | 973 | ||
| 1109 | //Initializing the NVM. | 974 | /* Initializing the NVM. */ |
| 1110 | BcmInitNVM(ps_adapter); | 975 | BcmInitNVM(ps_adapter); |
| 1111 | status = ddr_init(ps_adapter); | 976 | status = ddr_init(ps_adapter); |
| 1112 | if(status) | 977 | if (status) { |
| 1113 | { | ||
| 1114 | pr_err(DRV_NAME "ddr_init Failed\n"); | 978 | pr_err(DRV_NAME "ddr_init Failed\n"); |
| 1115 | return status; | 979 | return status; |
| 1116 | } | 980 | } |
| 1117 | 981 | ||
| 1118 | /* Download cfg file */ | 982 | /* Download cfg file */ |
| 1119 | status = buffDnldVerify(ps_adapter, | 983 | status = buffDnldVerify(ps_adapter, |
| 1120 | (PUCHAR)ps_adapter->pstargetparams, | 984 | (PUCHAR)ps_adapter->pstargetparams, |
| 1121 | sizeof(STARGETPARAMS), | 985 | sizeof(STARGETPARAMS), |
| 1122 | CONFIG_BEGIN_ADDR); | 986 | CONFIG_BEGIN_ADDR); |
| 1123 | if(status) | 987 | if (status) { |
| 1124 | { | 988 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file"); |
| 1125 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file"); | ||
| 1126 | goto OUT; | 989 | goto OUT; |
| 1127 | } | 990 | } |
| 1128 | 991 | ||
| 1129 | if(register_networkdev(ps_adapter)) | 992 | if (register_networkdev(ps_adapter)) { |
| 1130 | { | 993 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed."); |
| 1131 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed."); | ||
| 1132 | return -EIO; | 994 | return -EIO; |
| 1133 | } | 995 | } |
| 1134 | 996 | ||
| 1135 | if(FALSE == ps_adapter->AutoFirmDld) | 997 | if (FALSE == ps_adapter->AutoFirmDld) { |
| 1136 | { | 998 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n"); |
| 1137 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n"); | 999 | /* If Auto f/w download is disable, register the control interface, */ |
| 1138 | //If Auto f/w download is disable, register the control interface, | 1000 | /* register the control interface after the mailbox. */ |
| 1139 | //register the control interface after the mailbox. | 1001 | if (register_control_device_interface(ps_adapter) < 0) { |
| 1140 | if(register_control_device_interface(ps_adapter) < 0) | 1002 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed."); |
| 1141 | { | ||
| 1142 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed."); | ||
| 1143 | return -EIO; | 1003 | return -EIO; |
| 1144 | } | 1004 | } |
| 1145 | |||
| 1146 | return STATUS_SUCCESS; | 1005 | return STATUS_SUCCESS; |
| 1147 | } | 1006 | } |
| 1148 | 1007 | ||
| 1149 | /* | 1008 | /* |
| 1150 | * Do the LED Settings here. It will be used by the Firmware Download | 1009 | * Do the LED Settings here. It will be used by the Firmware Download |
| 1151 | * Thread. | 1010 | * Thread. |
| 1152 | */ | 1011 | */ |
| 1153 | 1012 | ||
| 1154 | /* | 1013 | /* |
| 1155 | * 1. If the LED Settings fails, do not stop and do the Firmware download. | 1014 | * 1. If the LED Settings fails, do not stop and do the Firmware download. |
| 1156 | * 2. This init would happened only if the cfg file is present, else | 1015 | * 2. This init would happened only if the cfg file is present, else |
| 1157 | * call from the ioctl context. | 1016 | * call from the ioctl context. |
| 1158 | */ | 1017 | */ |
| 1159 | |||
| 1160 | status = InitLedSettings (ps_adapter); | ||
| 1161 | 1018 | ||
| 1162 | if(status) | 1019 | status = InitLedSettings(ps_adapter); |
| 1163 | { | 1020 | if (status) { |
| 1164 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0,"INIT LED FAILED\n"); | 1021 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_PRINTK, 0, 0, "INIT LED FAILED\n"); |
| 1165 | return status; | 1022 | return status; |
| 1166 | } | 1023 | } |
| 1167 | if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 1024 | |
| 1168 | { | 1025 | if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 1169 | ps_adapter->DriverState = DRIVER_INIT; | 1026 | ps_adapter->DriverState = DRIVER_INIT; |
| 1170 | wake_up(&ps_adapter->LEDInfo.notify_led_event); | 1027 | wake_up(&ps_adapter->LEDInfo.notify_led_event); |
| 1171 | } | 1028 | } |
| 1172 | 1029 | ||
| 1173 | if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 1030 | if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 1174 | { | ||
| 1175 | ps_adapter->DriverState = FW_DOWNLOAD; | 1031 | ps_adapter->DriverState = FW_DOWNLOAD; |
| 1176 | wake_up(&ps_adapter->LEDInfo.notify_led_event); | 1032 | wake_up(&ps_adapter->LEDInfo.notify_led_event); |
| 1177 | } | 1033 | } |
| @@ -1180,37 +1036,32 @@ int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) · 2 unmodified lines | |||
| 1180 | wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); | 1036 | wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); |
| 1181 | wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); | 1037 | wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); |
| 1182 | 1038 | ||
| 1183 | if(ps_adapter->eNVMType == NVM_FLASH) | 1039 | if (ps_adapter->eNVMType == NVM_FLASH) { |
| 1184 | { | ||
| 1185 | status = PropagateCalParamsFromFlashToMemory(ps_adapter); | 1040 | status = PropagateCalParamsFromFlashToMemory(ps_adapter); |
| 1186 | if(status) | 1041 | if (status) { |
| 1187 | { | 1042 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Propagation of Cal param failed .."); |
| 1188 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propagation of Cal param failed .." ); | ||
| 1189 | goto OUT; | 1043 | goto OUT; |
| 1190 | } | 1044 | } |
| 1191 | } | 1045 | } |
| 1192 | 1046 | ||
| 1193 | /* Download Firmare */ | 1047 | /* Download Firmare */ |
| 1194 | if ((status = BcmFileDownload( ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR))) | 1048 | status = BcmFileDownload(ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR); |
| 1195 | { | 1049 | if (status != 0) { |
| 1196 | BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present... \n"); | 1050 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present...\n"); |
| 1197 | goto OUT; | 1051 | goto OUT; |
| 1198 | } | 1052 | } |
| 1199 | 1053 | ||
| 1200 | status = run_card_proc(ps_adapter); | 1054 | status = run_card_proc(ps_adapter); |
| 1201 | if(status) | 1055 | if (status) { |
| 1202 | { | 1056 | BCM_DEBUG_PRINT(ps_adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n"); |
| 1203 | BCM_DEBUG_PRINT (ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n"); | ||
| 1204 | goto OUT; | 1057 | goto OUT; |
| 1205 | } | 1058 | } |
| 1206 | 1059 | ||
| 1207 | |||
| 1208 | ps_adapter->fw_download_done = TRUE; | 1060 | ps_adapter->fw_download_done = TRUE; |
| 1209 | mdelay(10); | 1061 | mdelay(10); |
| 1210 | 1062 | ||
| 1211 | OUT: | 1063 | OUT: |
| 1212 | if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 1064 | if (ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 1213 | { | ||
| 1214 | ps_adapter->DriverState = FW_DOWNLOAD_DONE; | 1065 | ps_adapter->DriverState = FW_DOWNLOAD_DONE; |
| 1215 | wake_up(&ps_adapter->LEDInfo.notify_led_event); | 1066 | wake_up(&ps_adapter->LEDInfo.notify_led_event); |
| 1216 | } | 1067 | } |
| @@ -1218,41 +1069,39 @@ OUT: · 1 unmodified line | |||
| 1218 | return status; | 1069 | return status; |
| 1219 | } | 1070 | } |
| 1220 | 1071 | ||
| 1221 | |||
| 1222 | static int bcm_parse_target_params(PMINI_ADAPTER Adapter) | 1072 | static int bcm_parse_target_params(PMINI_ADAPTER Adapter) |
| 1223 | { | 1073 | { |
| 1224 | struct file *flp=NULL; | 1074 | struct file *flp = NULL; |
| 1225 | mm_segment_t oldfs={0}; | 1075 | mm_segment_t oldfs = {0}; |
| 1226 | char *buff; | 1076 | char *buff; |
| 1227 | int len = 0; | 1077 | int len = 0; |
| 1228 | loff_t pos = 0; | 1078 | loff_t pos = 0; |
| 1229 | 1079 | ||
| 1230 | buff=kmalloc(BUFFER_1K, GFP_KERNEL); | 1080 | buff = kmalloc(BUFFER_1K, GFP_KERNEL); |
| 1231 | if(!buff) | 1081 | if (!buff) |
| 1232 | { | ||
| 1233 | return -ENOMEM; | 1082 | return -ENOMEM; |
| 1234 | } | 1083 | |
| 1235 | if((Adapter->pstargetparams = | 1084 | Adapter->pstargetparams = kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL); |
| 1236 | kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL) | 1085 | if (Adapter->pstargetparams == NULL) { |
| 1237 | { | ||
| 1238 | kfree(buff); | 1086 | kfree(buff); |
| 1239 | return -ENOMEM; | 1087 | return -ENOMEM; |
| 1240 | } | 1088 | } |
| 1241 | flp=open_firmware_file(Adapter, CFG_FILE); | 1089 | |
| 1242 | if(!flp) { | 1090 | flp = open_firmware_file(Adapter, CFG_FILE); |
| 1243 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE \n", CFG_FILE); | 1091 | if (!flp) { |
| 1092 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE\n", CFG_FILE); | ||
| 1244 | kfree(buff); | 1093 | kfree(buff); |
| 1245 | kfree(Adapter->pstargetparams); | 1094 | kfree(Adapter->pstargetparams); |
| 1246 | Adapter->pstargetparams = NULL; | 1095 | Adapter->pstargetparams = NULL; |
| 1247 | return -ENOENT; | 1096 | return -ENOENT; |
| 1248 | } | 1097 | } |
| 1249 | oldfs=get_fs(); set_fs(get_ds()); | 1098 | oldfs = get_fs(); |
| 1250 | len=vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos); | 1099 | set_fs(get_ds()); |
| 1100 | len = vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos); | ||
| 1251 | set_fs(oldfs); | 1101 | set_fs(oldfs); |
| 1252 | 1102 | ||
| 1253 | if(len != sizeof(STARGETPARAMS)) | 1103 | if (len != sizeof(STARGETPARAMS)) { |
| 1254 | { | 1104 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Mismatch in Target Param Structure!\n"); |
| 1255 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Mismatch in Target Param Structure!\n"); | ||
| 1256 | kfree(buff); | 1105 | kfree(buff); |
| 1257 | kfree(Adapter->pstargetparams); | 1106 | kfree(Adapter->pstargetparams); |
| 1258 | Adapter->pstargetparams = NULL; | 1107 | Adapter->pstargetparams = NULL; |
| @@ -1266,122 +1115,97 @@ static int bcm_parse_target_params(PMINI_ADAPTER Adapter) · 7 unmodified lines | |||
| 1266 | * Values in Adapter->pstargetparams are in network byte order | 1115 | * Values in Adapter->pstargetparams are in network byte order |
| 1267 | */ | 1116 | */ |
| 1268 | memcpy(Adapter->pstargetparams, buff, sizeof(STARGETPARAMS)); | 1117 | memcpy(Adapter->pstargetparams, buff, sizeof(STARGETPARAMS)); |
| 1269 | kfree (buff); | 1118 | kfree(buff); |
| 1270 | beceem_parse_target_struct(Adapter); | 1119 | beceem_parse_target_struct(Adapter); |
| 1271 | return STATUS_SUCCESS; | 1120 | return STATUS_SUCCESS; |
| 1272 | } | 1121 | } |
| 1273 | 1122 | ||
| 1274 | void beceem_parse_target_struct(PMINI_ADAPTER Adapter) | 1123 | void beceem_parse_target_struct(PMINI_ADAPTER Adapter) |
| 1275 | { | 1124 | { |
| 1276 | UINT uiHostDrvrCfg6 =0, uiEEPROMFlag = 0; | 1125 | UINT uiHostDrvrCfg6 = 0, uiEEPROMFlag = 0; |
| 1277 | 1126 | ||
| 1278 | if(ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) | 1127 | if (ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) { |
| 1279 | { | ||
| 1280 | pr_info(DRV_NAME ": AutoSyncup is Disabled\n"); | 1128 | pr_info(DRV_NAME ": AutoSyncup is Disabled\n"); |
| 1281 | Adapter->AutoSyncup = FALSE; | 1129 | Adapter->AutoSyncup = FALSE; |
| 1282 | } | 1130 | } else { |
| 1283 | else | ||
| 1284 | { | ||
| 1285 | pr_info(DRV_NAME ": AutoSyncup is Enabled\n"); | 1131 | pr_info(DRV_NAME ": AutoSyncup is Enabled\n"); |
| 1286 | Adapter->AutoSyncup = TRUE; | 1132 | Adapter->AutoSyncup = TRUE; |
| 1287 | } | 1133 | } |
| 1288 | 1134 | ||
| 1289 | if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE) | 1135 | if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE) { |
| 1290 | { | ||
| 1291 | pr_info(DRV_NAME ": Enabling autolink up"); | 1136 | pr_info(DRV_NAME ": Enabling autolink up"); |
| 1292 | Adapter->AutoLinkUp = TRUE; | 1137 | Adapter->AutoLinkUp = TRUE; |
| 1293 | } | 1138 | } else { |
| 1294 | else | ||
| 1295 | { | ||
| 1296 | pr_info(DRV_NAME ": Disabling autolink up"); | 1139 | pr_info(DRV_NAME ": Disabling autolink up"); |
| 1297 | Adapter->AutoLinkUp = FALSE; | 1140 | Adapter->AutoLinkUp = FALSE; |
| 1298 | } | 1141 | } |
| 1299 | // Setting the DDR Setting.. | 1142 | /* Setting the DDR Setting.. */ |
| 1300 | Adapter->DDRSetting = | 1143 | Adapter->DDRSetting = (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >> 8)&0x0F; |
| 1301 | (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >>8)&0x0F; | 1144 | Adapter->ulPowerSaveMode = (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F; |
| 1302 | Adapter->ulPowerSaveMode = | ||
| 1303 | (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F; | ||
| 1304 | |||
| 1305 | pr_info(DRV_NAME ": DDR Setting: %x\n", Adapter->DDRSetting); | 1145 | pr_info(DRV_NAME ": DDR Setting: %x\n", Adapter->DDRSetting); |
| 1306 | pr_info(DRV_NAME ": Power Save Mode: %lx\n", Adapter->ulPowerSaveMode); | 1146 | pr_info(DRV_NAME ": Power Save Mode: %lx\n", Adapter->ulPowerSaveMode); |
| 1307 | if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD) | 1147 | if (ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD) { |
| 1308 | { | 1148 | pr_info(DRV_NAME ": Enabling Auto Firmware Download\n"); |
| 1309 | pr_info(DRV_NAME ": Enabling Auto Firmware Download\n"); | 1149 | Adapter->AutoFirmDld = TRUE; |
| 1310 | Adapter->AutoFirmDld = TRUE; | 1150 | } else { |
| 1311 | } | 1151 | pr_info(DRV_NAME ": Disabling Auto Firmware Download\n"); |
| 1312 | else | 1152 | Adapter->AutoFirmDld = FALSE; |
| 1313 | { | 1153 | } |
| 1314 | pr_info(DRV_NAME ": Disabling Auto Firmware Download\n"); | ||
| 1315 | Adapter->AutoFirmDld = FALSE; | ||
| 1316 | } | ||
| 1317 | uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6); | 1154 | uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6); |
| 1318 | Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01; | 1155 | Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01; |
| 1319 | pr_info(DRV_NAME ": MIPSConfig : 0x%X\n",Adapter->bMipsConfig); | 1156 | pr_info(DRV_NAME ": MIPSConfig : 0x%X\n", Adapter->bMipsConfig); |
| 1320 | //used for backward compatibility. | 1157 | /* used for backward compatibility. */ |
| 1321 | Adapter->bDPLLConfig = (uiHostDrvrCfg6>>19)&0x01; | 1158 | Adapter->bDPLLConfig = (uiHostDrvrCfg6>>19)&0x01; |
| 1322 | 1159 | Adapter->PmuMode = (uiHostDrvrCfg6 >> 24) & 0x03; | |
| 1323 | Adapter->PmuMode= (uiHostDrvrCfg6 >> 24 ) & 0x03; | ||
| 1324 | pr_info(DRV_NAME ": PMU MODE: %x", Adapter->PmuMode); | 1160 | pr_info(DRV_NAME ": PMU MODE: %x", Adapter->PmuMode); |
| 1325 | 1161 | ||
| 1326 | if((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT ) & (0x01)) | 1162 | if ((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT) & (0x01)) { |
| 1327 | { | 1163 | Adapter->bDoSuspend = TRUE; |
| 1328 | Adapter->bDoSuspend = TRUE; | 1164 | pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile"); |
| 1329 | pr_info(DRV_NAME ": Making DoSuspend TRUE as per configFile"); | 1165 | } |
| 1330 | } | ||
| 1331 | 1166 | ||
| 1332 | uiEEPROMFlag = ntohl(Adapter->pstargetparams->m_u32EEPROMFlag); | 1167 | uiEEPROMFlag = ntohl(Adapter->pstargetparams->m_u32EEPROMFlag); |
| 1333 | pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n",uiEEPROMFlag); | 1168 | pr_info(DRV_NAME ": uiEEPROMFlag : 0x%X\n", uiEEPROMFlag); |
| 1334 | Adapter->eNVMType = (NVM_TYPE)((uiEEPROMFlag>>4)&0x3); | 1169 | Adapter->eNVMType = (NVM_TYPE)((uiEEPROMFlag>>4)&0x3); |
| 1335 | |||
| 1336 | Adapter->bStatusWrite = (uiEEPROMFlag>>6)&0x1; | 1170 | Adapter->bStatusWrite = (uiEEPROMFlag>>6)&0x1; |
| 1337 | |||
| 1338 | Adapter->uiSectorSizeInCFG = 1024*(0xFFFF & ntohl(Adapter->pstargetparams->HostDrvrConfig4)); | 1171 | Adapter->uiSectorSizeInCFG = 1024*(0xFFFF & ntohl(Adapter->pstargetparams->HostDrvrConfig4)); |
| 1172 | Adapter->bSectorSizeOverride = (bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1; | ||
| 1339 | 1173 | ||
| 1340 | Adapter->bSectorSizeOverride =(bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1; | 1174 | if (ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x01) |
| 1341 | |||
| 1342 | if(ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) &0x01) | ||
| 1343 | Adapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE; | 1175 | Adapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE; |
| 1344 | 1176 | ||
| 1345 | if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) | 1177 | if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) |
| 1346 | doPowerAutoCorrection(Adapter); | 1178 | doPowerAutoCorrection(Adapter); |
| 1347 | |||
| 1348 | } | 1179 | } |
| 1349 | 1180 | ||
| 1350 | static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) | 1181 | static VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) |
| 1351 | { | 1182 | { |
| 1352 | UINT reporting_mode; | 1183 | UINT reporting_mode; |
| 1353 | 1184 | ||
| 1354 | reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) &0x02 ; | 1185 | reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) & 0x02; |
| 1355 | psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1); | 1186 | psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1); |
| 1356 | 1187 | ||
| 1357 | if(reporting_mode == TRUE) | 1188 | if (reporting_mode == TRUE) { |
| 1358 | { | 1189 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "can't do suspen/resume as reporting mode is enable"); |
| 1359 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"can't do suspen/resume as reporting mode is enable"); | ||
| 1360 | psAdapter->bDoSuspend = FALSE; | 1190 | psAdapter->bDoSuspend = FALSE; |
| 1361 | } | 1191 | } |
| 1362 | 1192 | ||
| 1363 | if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) | 1193 | if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) { |
| 1364 | { | 1194 | /* If reporting mode is enable, switch PMU to PMC */ |
| 1365 | //If reporting mode is enable, switch PMU to PMC | ||
| 1366 | { | 1195 | { |
| 1367 | psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING; | 1196 | psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING; |
| 1368 | psAdapter->bDoSuspend =FALSE; | 1197 | psAdapter->bDoSuspend = FALSE; |
| 1369 | |||
| 1370 | } | 1198 | } |
| 1371 | 1199 | ||
| 1372 | //clearing space bit[15..12] | 1200 | /* clearing space bit[15..12] */ |
| 1373 | psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl((0xF << 12))); | 1201 | psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl((0xF << 12))); |
| 1374 | //placing the power save mode option | 1202 | /* placing the power save mode option */ |
| 1375 | psAdapter->pstargetparams->HostDrvrConfig6 |= htonl((psAdapter->ulPowerSaveMode << 12)); | 1203 | psAdapter->pstargetparams->HostDrvrConfig6 |= htonl((psAdapter->ulPowerSaveMode << 12)); |
| 1376 | 1204 | } else if (psAdapter->bIsAutoCorrectEnabled == FALSE) { | |
| 1377 | } | 1205 | /* remove the autocorrect disable bit set before dumping. */ |
| 1378 | else if (psAdapter->bIsAutoCorrectEnabled == FALSE) | ||
| 1379 | { | ||
| 1380 | |||
| 1381 | // remove the autocorrect disable bit set before dumping. | ||
| 1382 | psAdapter->ulPowerSaveMode &= ~(1 << 3); | 1206 | psAdapter->ulPowerSaveMode &= ~(1 << 3); |
| 1383 | psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl(1 << 15)); | 1207 | psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl(1 << 15)); |
| 1384 | BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode); | 1208 | BCM_DEBUG_PRINT(psAdapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode); |
| 1385 | } | 1209 | } |
| 1386 | } | 1210 | } |
| 1387 | 1211 | ||
| @@ -1392,63 +1216,56 @@ static unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) · 4 unmodified lines | |||
| 1392 | unsigned int temp = 0; | 1216 | unsigned int temp = 0; |
| 1393 | unsigned char *pucmacaddr = kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL); | 1217 | unsigned char *pucmacaddr = kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL); |
| 1394 | 1218 | ||
| 1395 | if(!pucmacaddr) | 1219 | if (!pucmacaddr) { |
| 1396 | { | 1220 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n"); |
| 1397 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n"); | ||
| 1398 | return NULL; | 1221 | return NULL; |
| 1399 | } | 1222 | } |
| 1400 | 1223 | ||
| 1401 | dwAddress |= 0x5b000000; | 1224 | dwAddress |= 0x5b000000; |
| 1402 | status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG, | 1225 | status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG, (PUINT)&dwAddress, sizeof(UINT)); |
| 1403 | (PUINT)&dwAddress, sizeof(UINT)); | 1226 | if (status != STATUS_SUCCESS) { |
| 1404 | if(status != STATUS_SUCCESS) | 1227 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n"); |
| 1405 | { | ||
| 1406 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n"); | ||
| 1407 | kfree(pucmacaddr); | 1228 | kfree(pucmacaddr); |
| 1408 | pucmacaddr = NULL; | 1229 | pucmacaddr = NULL; |
| 1409 | goto OUT; | 1230 | goto OUT; |
| 1410 | } | 1231 | } |
| 1411 | for(i=0;i<MAC_ADDRESS_SIZE;i++) | 1232 | |
| 1412 | { | 1233 | for (i = 0; i < MAC_ADDRESS_SIZE; i++) { |
| 1413 | status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp,sizeof(temp)); | 1234 | status = rdmalt(Adapter, EEPROM_READ_DATA_Q_REG, &temp, sizeof(temp)); |
| 1414 | if(status != STATUS_SUCCESS) | 1235 | if (status != STATUS_SUCCESS) { |
| 1415 | { | 1236 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n"); |
| 1416 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm Failed..\n"); | ||
| 1417 | kfree(pucmacaddr); | 1237 | kfree(pucmacaddr); |
| 1418 | pucmacaddr = NULL; | 1238 | pucmacaddr = NULL; |
| 1419 | goto OUT; | 1239 | goto OUT; |
| 1420 | } | 1240 | } |
| 1421 | pucmacaddr[i] = temp & 0xff; | 1241 | pucmacaddr[i] = temp & 0xff; |
| 1422 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"%x \n", pucmacaddr[i]); | 1242 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "%x\n", pucmacaddr[i]); |
| 1423 | } | 1243 | } |
| 1424 | OUT: | 1244 | OUT: |
| 1425 | return pucmacaddr; | 1245 | return pucmacaddr; |
| 1426 | } | 1246 | } |
| 1427 | #endif | 1247 | #endif |
| 1428 | 1248 | ||
| 1429 | |||
| 1430 | static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount) | 1249 | static void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount) |
| 1431 | { | 1250 | { |
| 1432 | UINT uiIndex = 0; | 1251 | UINT uiIndex = 0; |
| 1433 | 1252 | ||
| 1434 | if(RWM_WRITE == rwFlag) { | 1253 | if (RWM_WRITE == rwFlag) { |
| 1435 | for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) { | 1254 | for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) |
| 1436 | puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]); | 1255 | puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]); |
| 1437 | } | ||
| 1438 | } else { | 1256 | } else { |
| 1439 | for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) { | 1257 | for (uiIndex = 0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) |
| 1440 | puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]); | 1258 | puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]); |
| 1441 | } | ||
| 1442 | } | 1259 | } |
| 1443 | } | 1260 | } |
| 1444 | 1261 | ||
| 1445 | #define CACHE_ADDRESS_MASK 0x80000000 | 1262 | #define CACHE_ADDRESS_MASK 0x80000000 |
| 1446 | #define UNCACHE_ADDRESS_MASK 0xa0000000 | 1263 | #define UNCACHE_ADDRESS_MASK 0xa0000000 |
| 1447 | 1264 | ||
| 1448 | int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) | 1265 | int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) |
| 1449 | { | 1266 | { |
| 1450 | return Adapter->interface_rdm(Adapter->pvInterfaceAdapter, | 1267 | return Adapter->interface_rdm(Adapter->pvInterfaceAdapter, |
| 1451 | uiAddress, pucBuff, sSize); | 1268 | uiAddress, pucBuff, sSize); |
| 1452 | } | 1269 | } |
| 1453 | 1270 | ||
| 1454 | int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) | 1271 | int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) |
| @@ -1456,112 +1273,103 @@ int wrm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) · 1 unmodified line | |||
| 1456 | int iRetVal; | 1273 | int iRetVal; |
| 1457 | 1274 | ||
| 1458 | iRetVal = Adapter->interface_wrm(Adapter->pvInterfaceAdapter, | 1275 | iRetVal = Adapter->interface_wrm(Adapter->pvInterfaceAdapter, |
| 1459 | uiAddress, pucBuff, sSize); | 1276 | uiAddress, pucBuff, sSize); |
| 1460 | |||
| 1461 | |||
| 1462 | return iRetVal; | 1277 | return iRetVal; |
| 1463 | } | 1278 | } |
| 1464 | 1279 | ||
| 1465 | int wrmalt (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) | 1280 | int wrmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) |
| 1466 | { | 1281 | { |
| 1467 | convertEndian(RWM_WRITE, pucBuff, size); | 1282 | convertEndian(RWM_WRITE, pucBuff, size); |
| 1468 | return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size); | 1283 | return wrm(Adapter, uiAddress, (PUCHAR)pucBuff, size); |
| 1469 | } | 1284 | } |
| 1470 | 1285 | ||
| 1471 | int rdmalt (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) | 1286 | int rdmalt(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) |
| 1472 | { | 1287 | { |
| 1473 | INT uiRetVal =0; | 1288 | INT uiRetVal = 0; |
| 1474 | 1289 | ||
| 1475 | uiRetVal = rdm(Adapter,uiAddress,(PUCHAR)pucBuff,size); | 1290 | uiRetVal = rdm(Adapter, uiAddress, (PUCHAR)pucBuff, size); |
| 1476 | convertEndian(RWM_READ, (PUINT)pucBuff, size); | 1291 | convertEndian(RWM_READ, (PUINT)pucBuff, size); |
| 1477 | 1292 | ||
| 1478 | return uiRetVal; | 1293 | return uiRetVal; |
| 1479 | } | 1294 | } |
| 1480 | 1295 | ||
| 1481 | |||
| 1482 | int wrmWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) | 1296 | int wrmWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) |
| 1483 | { | 1297 | { |
| 1484 | INT status = STATUS_SUCCESS ; | 1298 | INT status = STATUS_SUCCESS; |
| 1485 | down(&Adapter->rdmwrmsync); | 1299 | down(&Adapter->rdmwrmsync); |
| 1486 | 1300 | ||
| 1487 | if((Adapter->IdleMode == TRUE) || | 1301 | if ((Adapter->IdleMode == TRUE) || |
| 1488 | (Adapter->bShutStatus ==TRUE) || | 1302 | (Adapter->bShutStatus == TRUE) || |
| 1489 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 1303 | (Adapter->bPreparingForLowPowerMode == TRUE)) { |
| 1490 | { | 1304 | |
| 1491 | status = -EACCES; | 1305 | status = -EACCES; |
| 1492 | goto exit; | 1306 | goto exit; |
| 1493 | } | 1307 | } |
| 1494 | 1308 | ||
| 1495 | status =wrm(Adapter, uiAddress, pucBuff, sSize); | 1309 | status = wrm(Adapter, uiAddress, pucBuff, sSize); |
| 1496 | |||
| 1497 | exit: | 1310 | exit: |
| 1498 | up(&Adapter->rdmwrmsync); | 1311 | up(&Adapter->rdmwrmsync); |
| 1499 | return status ; | 1312 | return status; |
| 1500 | } | 1313 | } |
| 1501 | 1314 | ||
| 1502 | int wrmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) | 1315 | int wrmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) |
| 1503 | { | 1316 | { |
| 1504 | int iRetVal = STATUS_SUCCESS; | 1317 | int iRetVal = STATUS_SUCCESS; |
| 1505 | 1318 | ||
| 1506 | down(&Adapter->rdmwrmsync); | 1319 | down(&Adapter->rdmwrmsync); |
| 1507 | 1320 | ||
| 1508 | if((Adapter->IdleMode == TRUE) || | 1321 | if ((Adapter->IdleMode == TRUE) || |
| 1509 | (Adapter->bShutStatus ==TRUE) || | 1322 | (Adapter->bShutStatus == TRUE) || |
| 1510 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | 1323 | (Adapter->bPreparingForLowPowerMode == TRUE)) { |
| 1511 | { | 1324 | |
| 1512 | iRetVal = -EACCES; | 1325 | iRetVal = -EACCES; |
| 1513 | goto exit; | 1326 | goto exit; |
| 1514 | } | 1327 | } |
| 1515 | 1328 | ||
| 1516 | iRetVal = wrmalt(Adapter,uiAddress,pucBuff,size); | 1329 | iRetVal = wrmalt(Adapter, uiAddress, pucBuff, size); |
| 1517 | |||
| 1518 | exit: | 1330 | exit: |
| 1519 | up(&Adapter->rdmwrmsync); | 1331 | up(&Adapter->rdmwrmsync); |
| 1520 | return iRetVal; | 1332 | return iRetVal; |
| 1521 | } | 1333 | } |
| 1522 | 1334 | ||
| 1523 | int rdmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) | 1335 | int rdmaltWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) |
| 1524 | { | 1336 | { |
| 1525 | INT uiRetVal =STATUS_SUCCESS; | 1337 | INT uiRetVal = STATUS_SUCCESS; |
| 1526 | 1338 | ||
| 1527 | down(&Adapter->rdmwrmsync); | 1339 | down(&Adapter->rdmwrmsync); |
| 1340 | if ((Adapter->IdleMode == TRUE) || | ||
| 1341 | (Adapter->bShutStatus == TRUE) || | ||
| 1342 | (Adapter->bPreparingForLowPowerMode == TRUE)) { | ||
| 1528 | 1343 | ||
| 1529 | if((Adapter->IdleMode == TRUE) || | ||
| 1530 | (Adapter->bShutStatus ==TRUE) || | ||
| 1531 | (Adapter->bPreparingForLowPowerMode ==TRUE)) | ||
| 1532 | { | ||
| 1533 | uiRetVal = -EACCES; | 1344 | uiRetVal = -EACCES; |
| 1534 | goto exit; | 1345 | goto exit; |
| 1535 | } | 1346 | } |
| 1536 | 1347 | ||
| 1537 | uiRetVal = rdmalt(Adapter,uiAddress, pucBuff, size); | 1348 | uiRetVal = rdmalt(Adapter, uiAddress, pucBuff, size); |
| 1538 | |||
| 1539 | exit: | 1349 | exit: |
| 1540 | up(&Adapter->rdmwrmsync); | 1350 | up(&Adapter->rdmwrmsync); |
| 1541 | return uiRetVal; | 1351 | return uiRetVal; |
| 1542 | } | 1352 | } |
| 1543 | 1353 | ||
| 1544 | |||
| 1545 | static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter) | 1354 | static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter) |
| 1546 | { | 1355 | { |
| 1547 | int clear_abort_pattern = 0,Status = 0; | 1356 | int clear_abort_pattern = 0, Status = 0; |
| 1548 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n"); | 1357 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n"); |
| 1549 | //target has woken up From Shut Down | 1358 | /* target has woken up From Shut Down */ |
| 1550 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n"); | 1359 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n"); |
| 1551 | Status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern)); | 1360 | Status = wrmalt(Adapter, SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern)); |
| 1552 | if(Status) | 1361 | if (Status) { |
| 1553 | { | 1362 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status); |
| 1554 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status); | ||
| 1555 | return; | 1363 | return; |
| 1556 | } | 1364 | } |
| 1557 | if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) | 1365 | |
| 1558 | { | 1366 | if (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) { |
| 1559 | msleep(100); | 1367 | msleep(100); |
| 1560 | InterfaceHandleShutdownModeWakeup(Adapter); | 1368 | InterfaceHandleShutdownModeWakeup(Adapter); |
| 1561 | msleep(100); | 1369 | msleep(100); |
| 1562 | } | 1370 | } |
| 1563 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 1371 | |
| 1564 | { | 1372 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 1565 | Adapter->DriverState = NO_NETWORK_ENTRY; | 1373 | Adapter->DriverState = NO_NETWORK_ENTRY; |
| 1566 | wake_up(&Adapter->LEDInfo.notify_led_event); | 1374 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 1567 | } | 1375 | } |
| @@ -1569,55 +1377,49 @@ static VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter) · 1 unmodified line | |||
| 1569 | Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; | 1377 | Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; |
| 1570 | Adapter->bShutStatus = FALSE; | 1378 | Adapter->bShutStatus = FALSE; |
| 1571 | wake_up(&Adapter->lowpower_mode_wait_queue); | 1379 | wake_up(&Adapter->lowpower_mode_wait_queue); |
| 1572 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n"); | 1380 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n"); |
| 1573 | } | 1381 | } |
| 1574 | 1382 | ||
| 1575 | static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) | 1383 | static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) |
| 1576 | { | 1384 | { |
| 1577 | CONTROL_MESSAGE stShutdownResponse; | 1385 | CONTROL_MESSAGE stShutdownResponse; |
| 1578 | UINT NVMAccess = 0,lowPwrAbortMsg = 0; | 1386 | UINT NVMAccess = 0, lowPwrAbortMsg = 0; |
| 1579 | UINT Status = 0; | 1387 | UINT Status = 0; |
| 1580 | 1388 | ||
| 1581 | memset (&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE)); | 1389 | memset(&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE)); |
| 1582 | stShutdownResponse.Leader.Status = LINK_UP_CONTROL_REQ; | 1390 | stShutdownResponse.Leader.Status = LINK_UP_CONTROL_REQ; |
| 1583 | stShutdownResponse.Leader.PLength = 8;//8 bytes; | 1391 | stShutdownResponse.Leader.PLength = 8; /* 8 bytes; */ |
| 1584 | stShutdownResponse.szData[0] = LINK_UP_ACK; | 1392 | stShutdownResponse.szData[0] = LINK_UP_ACK; |
| 1585 | stShutdownResponse.szData[1] = LINK_SHUTDOWN_REQ_FROM_FIRMWARE; | 1393 | stShutdownResponse.szData[1] = LINK_SHUTDOWN_REQ_FROM_FIRMWARE; |
| 1586 | 1394 | ||
| 1587 | /********************************* | 1395 | /********************************* |
| 1588 | **down_trylock - | 1396 | * down_trylock - |
| 1589 | ** if [ semaphore is available ] | 1397 | * if [ semaphore is available ] |
| 1590 | ** acquire semaphone and return value 0 ; | 1398 | * acquire semaphone and return value 0 ; |
| 1591 | ** else | 1399 | * else |
| 1592 | ** return non-zero value ; | 1400 | * return non-zero value ; |
| 1593 | ** | 1401 | * |
| 1594 | ***********************************/ | 1402 | ***********************************/ |
| 1595 | 1403 | ||
| 1596 | NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); | 1404 | NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); |
| 1405 | lowPwrAbortMsg = down_trylock(&Adapter->LowPowerModeSync); | ||
| 1597 | 1406 | ||
| 1598 | lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync); | 1407 | if (NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) { |
| 1599 | 1408 | if (!NVMAccess) | |
| 1600 | |||
| 1601 | if(NVMAccess || lowPwrAbortMsg|| atomic_read(&Adapter->TotalPacketCount)) | ||
| 1602 | { | ||
| 1603 | if(!NVMAccess) | ||
| 1604 | up(&Adapter->NVMRdmWrmLock); | 1409 | up(&Adapter->NVMRdmWrmLock); |
| 1605 | 1410 | ||
| 1606 | if(!lowPwrAbortMsg) | 1411 | if (!lowPwrAbortMsg) |
| 1607 | up(&Adapter->LowPowerModeSync); | 1412 | up(&Adapter->LowPowerModeSync); |
| 1608 | 1413 | ||
| 1609 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n"); | 1414 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n"); |
| 1610 | stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on. | 1415 | stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */ |
| 1611 | Adapter->bPreparingForLowPowerMode = FALSE; | 1416 | Adapter->bPreparingForLowPowerMode = FALSE; |
| 1612 | } | 1417 | } else { |
| 1613 | else | 1418 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n"); |
| 1614 | { | 1419 | stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER; /* ShutDown ACK */ |
| 1615 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n"); | ||
| 1616 | stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER;//ShutDown ACK | ||
| 1617 | 1420 | ||
| 1618 | /* Wait for the LED to TURN OFF before sending ACK response */ | 1421 | /* Wait for the LED to TURN OFF before sending ACK response */ |
| 1619 | if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) | 1422 | if (Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) { |
| 1620 | { | ||
| 1621 | INT iRetVal = 0; | 1423 | INT iRetVal = 0; |
| 1622 | 1424 | ||
| 1623 | /* Wake the LED Thread with LOWPOWER_MODE_ENTER State */ | 1425 | /* Wake the LED Thread with LOWPOWER_MODE_ENTER State */ |
| @@ -1625,237 +1427,200 @@ static VOID SendShutModeResponse(PMINI_ADAPTER Adapter) · 1 unmodified line | |||
| 1625 | wake_up(&Adapter->LEDInfo.notify_led_event); | 1427 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 1626 | 1428 | ||
| 1627 | /* Wait for 1 SEC for LED to OFF */ | 1429 | /* Wait for 1 SEC for LED to OFF */ |
| 1628 | iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent,\ | 1430 | iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000)); |
| 1629 | Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000)); | ||
| 1630 | 1431 | ||
| 1631 | /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */ | 1432 | /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */ |
| 1632 | if(iRetVal <= 0) | 1433 | if (iRetVal <= 0) { |
| 1633 | { | 1434 | stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER; /* NACK- device access is going on. */ |
| 1634 | stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on. | ||
| 1635 | |||
| 1636 | Adapter->DriverState = NO_NETWORK_ENTRY; | 1435 | Adapter->DriverState = NO_NETWORK_ENTRY; |
| 1637 | wake_up(&Adapter->LEDInfo.notify_led_event); | 1436 | wake_up(&Adapter->LEDInfo.notify_led_event); |
| 1638 | } | 1437 | } |
| 1639 | } | 1438 | } |
| 1640 | 1439 | ||
| 1641 | if(stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER) | 1440 | if (stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER) { |
| 1642 | { | 1441 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ACKING SHUTDOWN MODE !!!!!!!!!"); |
| 1643 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ACKING SHUTDOWN MODE !!!!!!!!!"); | ||
| 1644 | down(&Adapter->rdmwrmsync); | 1442 | down(&Adapter->rdmwrmsync); |
| 1645 | Adapter->bPreparingForLowPowerMode = TRUE; | 1443 | Adapter->bPreparingForLowPowerMode = TRUE; |
| 1646 | up(&Adapter->rdmwrmsync); | 1444 | up(&Adapter->rdmwrmsync); |
| 1647 | //Killing all URBS. | 1445 | /* Killing all URBS. */ |
| 1648 | if(Adapter->bDoSuspend == TRUE) | 1446 | if (Adapter->bDoSuspend == TRUE) |
| 1649 | Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); | 1447 | Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); |
| 1650 | } | 1448 | } else { |
| 1651 | else | ||
| 1652 | { | ||
| 1653 | Adapter->bPreparingForLowPowerMode = FALSE; | 1449 | Adapter->bPreparingForLowPowerMode = FALSE; |
| 1654 | } | 1450 | } |
| 1655 | 1451 | ||
| 1656 | if(!NVMAccess) | 1452 | if (!NVMAccess) |
| 1657 | up(&Adapter->NVMRdmWrmLock); | 1453 | up(&Adapter->NVMRdmWrmLock); |
| 1658 | 1454 | ||
| 1659 | if(!lowPwrAbortMsg) | 1455 | if (!lowPwrAbortMsg) |
| 1660 | up(&Adapter->LowPowerModeSync); | 1456 | up(&Adapter->LowPowerModeSync); |
| 1661 | } | 1457 | } |
| 1662 | Status = CopyBufferToControlPacket(Adapter,&stShutdownResponse); | ||
| 1663 | if((Status != STATUS_SUCCESS)) | ||
| 1664 | { | ||
| 1665 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"fail to send the Idle mode Request \n"); | ||
| 1666 | Adapter->bPreparingForLowPowerMode = FALSE; | ||
| 1667 | 1458 | ||
| 1459 | Status = CopyBufferToControlPacket(Adapter, &stShutdownResponse); | ||
| 1460 | if ((Status != STATUS_SUCCESS)) { | ||
| 1461 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "fail to send the Idle mode Request\n"); | ||
| 1462 | Adapter->bPreparingForLowPowerMode = FALSE; | ||
| 1668 | StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); | 1463 | StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); |
| 1669 | } | 1464 | } |
| 1670 | } | 1465 | } |
| 1671 | 1466 | ||
| 1672 | 1467 | static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter, PUCHAR pucBuffer) | |
| 1673 | static void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) | ||
| 1674 | { | 1468 | { |
| 1675 | B_UINT32 uiResetValue = 0; | 1469 | B_UINT32 uiResetValue = 0; |
| 1676 | 1470 | ||
| 1677 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n"); | 1471 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n"); |
| 1678 | 1472 | ||
| 1679 | if(*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW) | 1473 | if (*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW) { |
| 1680 | { | ||
| 1681 | HandleShutDownModeWakeup(Adapter); | 1474 | HandleShutDownModeWakeup(Adapter); |
| 1682 | } | 1475 | } else if (*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) { |
| 1683 | else if(*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) | 1476 | /* Target wants to go to Shut Down Mode */ |
| 1684 | { | 1477 | /* InterfacePrepareForShutdown(Adapter); */ |
| 1685 | //Target wants to go to Shut Down Mode | 1478 | if (Adapter->chip_id == BCS220_2 || |
| 1686 | //InterfacePrepareForShutdown(Adapter); | 1479 | Adapter->chip_id == BCS220_2BC || |
| 1687 | if(Adapter->chip_id == BCS220_2 || | 1480 | Adapter->chip_id == BCS250_BC || |
| 1688 | Adapter->chip_id == BCS220_2BC || | 1481 | Adapter->chip_id == BCS220_3) { |
| 1689 | Adapter->chip_id == BCS250_BC || | 1482 | |
| 1690 | Adapter->chip_id == BCS220_3) | 1483 | rdmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4); |
| 1691 | { | ||
| 1692 | rdmalt(Adapter,HPM_CONFIG_MSW, &uiResetValue, 4); | ||
| 1693 | uiResetValue |= (1<<17); | 1484 | uiResetValue |= (1<<17); |
| 1694 | wrmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4); | 1485 | wrmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4); |
| 1695 | } | 1486 | } |
| 1696 | 1487 | ||
| 1697 | SendShutModeResponse(Adapter); | 1488 | SendShutModeResponse(Adapter); |
| 1698 | BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n"); | 1489 | BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n"); |
| 1699 | } | 1490 | } |
| 1700 | 1491 | ||
| 1701 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n"); | 1492 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n"); |
| 1702 | return; | 1493 | return; |
| 1703 | |||
| 1704 | } | 1494 | } |
| 1705 | 1495 | ||
| 1706 | VOID ResetCounters(PMINI_ADAPTER Adapter) | 1496 | VOID ResetCounters(PMINI_ADAPTER Adapter) |
| 1707 | { | 1497 | { |
| 1708 | 1498 | beceem_protocol_reset(Adapter); | |
| 1709 | beceem_protocol_reset(Adapter); | ||
| 1710 | |||
| 1711 | Adapter->CurrNumRecvDescs = 0; | 1499 | Adapter->CurrNumRecvDescs = 0; |
| 1712 | Adapter->PrevNumRecvDescs = 0; | 1500 | Adapter->PrevNumRecvDescs = 0; |
| 1713 | Adapter->LinkUpStatus = 0; | 1501 | Adapter->LinkUpStatus = 0; |
| 1714 | Adapter->LinkStatus = 0; | 1502 | Adapter->LinkStatus = 0; |
| 1715 | atomic_set(&Adapter->cntrlpktCnt,0); | 1503 | atomic_set(&Adapter->cntrlpktCnt, 0); |
| 1716 | atomic_set (&Adapter->TotalPacketCount,0); | 1504 | atomic_set(&Adapter->TotalPacketCount, 0); |
| 1717 | Adapter->fw_download_done=FALSE; | 1505 | Adapter->fw_download_done = FALSE; |
| 1718 | Adapter->LinkStatus = 0; | 1506 | Adapter->LinkStatus = 0; |
| 1719 | Adapter->AutoLinkUp = FALSE; | 1507 | Adapter->AutoLinkUp = FALSE; |
| 1720 | Adapter->IdleMode = FALSE; | 1508 | Adapter->IdleMode = FALSE; |
| 1721 | Adapter->bShutStatus = FALSE; | 1509 | Adapter->bShutStatus = FALSE; |
| 1722 | |||
| 1723 | } | 1510 | } |
| 1724 | S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIP) | 1511 | |
| 1512 | S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIP) | ||
| 1725 | { | 1513 | { |
| 1726 | UINT uiIndex=0; | 1514 | UINT uiIndex = 0; |
| 1727 | for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++) | 1515 | for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { |
| 1728 | { | 1516 | if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) && |
| 1729 | if((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)&& | 1517 | (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) && |
| 1730 | (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&& | 1518 | (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIP) && |
| 1731 | (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIP)&& | ||
| 1732 | !Adapter->astFragmentedPktClassifierTable[uiIndex].bOutOfOrderFragment) | 1519 | !Adapter->astFragmentedPktClassifierTable[uiIndex].bOutOfOrderFragment) |
| 1520 | |||
| 1733 | return Adapter->astFragmentedPktClassifierTable[uiIndex].pstMatchedClassifierEntry; | 1521 | return Adapter->astFragmentedPktClassifierTable[uiIndex].pstMatchedClassifierEntry; |
| 1734 | } | 1522 | } |
| 1735 | return NULL; | 1523 | return NULL; |
| 1736 | } | 1524 | } |
| 1737 | 1525 | ||
| 1738 | void AddFragIPClsEntry(PMINI_ADAPTER Adapter,PS_FRAGMENTED_PACKET_INFO psFragPktInfo) | 1526 | void AddFragIPClsEntry(PMINI_ADAPTER Adapter, PS_FRAGMENTED_PACKET_INFO psFragPktInfo) |
| 1739 | { | 1527 | { |
| 1740 | UINT uiIndex=0; | 1528 | UINT uiIndex = 0; |
| 1741 | for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++) | 1529 | for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { |
| 1742 | { | 1530 | if (!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) { |
| 1743 | if(!Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) | 1531 | memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex], psFragPktInfo, sizeof(S_FRAGMENTED_PACKET_INFO)); |
| 1744 | { | ||
| 1745 | memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex],psFragPktInfo,sizeof(S_FRAGMENTED_PACKET_INFO)); | ||
| 1746 | break; | 1532 | break; |
| 1747 | } | 1533 | } |
| 1748 | } | 1534 | } |
| 1749 | |||
| 1750 | } | 1535 | } |
| 1751 | 1536 | ||
| 1752 | void DelFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIp) | 1537 | void DelFragIPClsEntry(PMINI_ADAPTER Adapter, USHORT usIpIdentification, ULONG SrcIp) |
| 1753 | { | 1538 | { |
| 1754 | UINT uiIndex=0; | 1539 | UINT uiIndex = 0; |
| 1755 | for(uiIndex=0;uiIndex<MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES;uiIndex++) | 1540 | for (uiIndex = 0; uiIndex < MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES; uiIndex++) { |
| 1756 | { | 1541 | if ((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed) && |
| 1757 | if((Adapter->astFragmentedPktClassifierTable[uiIndex].bUsed)&& | 1542 | (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification) && |
| 1758 | (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&& | 1543 | (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress == SrcIp)) |
| 1759 | (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIp)) | 1544 | |
| 1760 | memset(&Adapter->astFragmentedPktClassifierTable[uiIndex],0,sizeof(S_FRAGMENTED_PACKET_INFO)); | 1545 | memset(&Adapter->astFragmentedPktClassifierTable[uiIndex], 0, sizeof(S_FRAGMENTED_PACKET_INFO)); |
| 1761 | } | 1546 | } |
| 1762 | } | 1547 | } |
| 1763 | 1548 | ||
| 1764 | void update_per_cid_rx (PMINI_ADAPTER Adapter) | 1549 | void update_per_cid_rx(PMINI_ADAPTER Adapter) |
| 1765 | { | 1550 | { |
| 1766 | UINT qindex = 0; | 1551 | UINT qindex = 0; |
| 1767 | 1552 | ||
| 1768 | if((jiffies - Adapter->liDrainCalculated) < XSECONDS) | 1553 | if ((jiffies - Adapter->liDrainCalculated) < XSECONDS) |
| 1769 | return; | 1554 | return; |
| 1770 | 1555 | ||
| 1771 | for(qindex = 0; qindex < HiPriority; qindex++) | 1556 | for (qindex = 0; qindex < HiPriority; qindex++) { |
| 1772 | { | 1557 | if (Adapter->PackInfo[qindex].ucDirection == 0) { |
| 1773 | if(Adapter->PackInfo[qindex].ucDirection == 0) | ||
| 1774 | { | ||
| 1775 | Adapter->PackInfo[qindex].uiCurrentRxRate = | 1558 | Adapter->PackInfo[qindex].uiCurrentRxRate = |
| 1776 | (Adapter->PackInfo[qindex].uiCurrentRxRate + | 1559 | (Adapter->PackInfo[qindex].uiCurrentRxRate + |
| 1777 | Adapter->PackInfo[qindex].uiThisPeriodRxBytes)/2; | 1560 | Adapter->PackInfo[qindex].uiThisPeriodRxBytes) / 2; |
| 1778 | 1561 | ||
| 1779 | Adapter->PackInfo[qindex].uiThisPeriodRxBytes = 0; | 1562 | Adapter->PackInfo[qindex].uiThisPeriodRxBytes = 0; |
| 1780 | } | 1563 | } else { |
| 1781 | else | ||
| 1782 | { | ||
| 1783 | Adapter->PackInfo[qindex].uiCurrentDrainRate = | 1564 | Adapter->PackInfo[qindex].uiCurrentDrainRate = |
| 1784 | (Adapter->PackInfo[qindex].uiCurrentDrainRate + | 1565 | (Adapter->PackInfo[qindex].uiCurrentDrainRate + |
| 1785 | Adapter->PackInfo[qindex].uiThisPeriodSentBytes)/2; | 1566 | Adapter->PackInfo[qindex].uiThisPeriodSentBytes) / 2; |
| 1786 | 1567 | Adapter->PackInfo[qindex].uiThisPeriodSentBytes = 0; | |
| 1787 | Adapter->PackInfo[qindex].uiThisPeriodSentBytes=0; | ||
| 1788 | } | 1568 | } |
| 1789 | } | 1569 | } |
| 1790 | Adapter->liDrainCalculated=jiffies; | 1570 | Adapter->liDrainCalculated = jiffies; |
| 1791 | } | 1571 | } |
| 1792 | void update_per_sf_desc_cnts( PMINI_ADAPTER Adapter) | 1572 | |
| 1573 | void update_per_sf_desc_cnts(PMINI_ADAPTER Adapter) | ||
| 1793 | { | 1574 | { |
| 1794 | INT iIndex = 0; | 1575 | INT iIndex = 0; |
| 1795 | u32 uibuff[MAX_TARGET_DSX_BUFFERS]; | 1576 | u32 uibuff[MAX_TARGET_DSX_BUFFERS]; |
| 1796 | 1577 | ||
| 1797 | if(!atomic_read (&Adapter->uiMBupdate)) | 1578 | if (!atomic_read(&Adapter->uiMBupdate)) |
| 1798 | return; | 1579 | return; |
| 1799 | 1580 | ||
| 1800 | if(rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS)<0) | 1581 | if (rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS) < 0) { |
| 1801 | { | 1582 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "rdm failed\n"); |
| 1802 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed\n"); | ||
| 1803 | return; | 1583 | return; |
| 1804 | } | 1584 | } |
| 1805 | for(iIndex = 0;iIndex < HiPriority; iIndex++) | 1585 | |
| 1806 | { | 1586 | for (iIndex = 0; iIndex < HiPriority; iIndex++) { |
| 1807 | if(Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection) | 1587 | if (Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection) { |
| 1808 | { | 1588 | if (Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS) |
| 1809 | if(Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS) | ||
| 1810 | { | ||
| 1811 | atomic_set(&Adapter->PackInfo[iIndex].uiPerSFTxResourceCount, uibuff[Adapter->PackInfo[iIndex].usVCID_Value]); | 1589 | atomic_set(&Adapter->PackInfo[iIndex].uiPerSFTxResourceCount, uibuff[Adapter->PackInfo[iIndex].usVCID_Value]); |
| 1812 | } | ||
| 1813 | else | 1590 | else |
| 1814 | { | 1591 | BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x\n", Adapter->PackInfo[iIndex].usVCID_Value); |
| 1815 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x \n", | ||
| 1816 | Adapter->PackInfo[iIndex].usVCID_Value); | ||
| 1817 | } | ||
| 1818 | } | 1592 | } |
| 1819 | } | 1593 | } |
| 1820 | atomic_set (&Adapter->uiMBupdate, FALSE); | 1594 | atomic_set(&Adapter->uiMBupdate, FALSE); |
| 1821 | } | 1595 | } |
| 1822 | 1596 | ||
| 1823 | void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex) | 1597 | void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex) |
| 1824 | { | 1598 | { |
| 1825 | struct sk_buff* PacketToDrop=NULL; | 1599 | struct sk_buff *PacketToDrop = NULL; |
| 1826 | struct net_device_stats* netstats = &Adapter->dev->stats; | 1600 | struct net_device_stats *netstats = &Adapter->dev->stats; |
| 1827 | |||
| 1828 | spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); | 1601 | spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); |
| 1829 | 1602 | ||
| 1830 | while(Adapter->PackInfo[iQIndex].FirstTxQueue && | 1603 | while (Adapter->PackInfo[iQIndex].FirstTxQueue && atomic_read(&Adapter->TotalPacketCount)) { |
| 1831 | atomic_read(&Adapter->TotalPacketCount)) | ||
| 1832 | { | ||
| 1833 | PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue; | 1604 | PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue; |
| 1834 | if(PacketToDrop && PacketToDrop->len) | 1605 | if (PacketToDrop && PacketToDrop->len) { |
| 1835 | { | ||
| 1836 | netstats->tx_dropped++; | 1606 | netstats->tx_dropped++; |
| 1837 | DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, \ | 1607 | DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, Adapter->PackInfo[iQIndex].LastTxQueue); |
| 1838 | Adapter->PackInfo[iQIndex].LastTxQueue); | ||
| 1839 | |||
| 1840 | Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--; | 1608 | Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--; |
| 1841 | Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= PacketToDrop->len; | 1609 | Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= PacketToDrop->len; |
| 1842 | 1610 | ||
| 1843 | //Adding dropped statistics | 1611 | /* Adding dropped statistics */ |
| 1844 | Adapter->PackInfo[iQIndex].uiDroppedCountBytes += PacketToDrop->len; | 1612 | Adapter->PackInfo[iQIndex].uiDroppedCountBytes += PacketToDrop->len; |
| 1845 | Adapter->PackInfo[iQIndex].uiDroppedCountPackets++; | 1613 | Adapter->PackInfo[iQIndex].uiDroppedCountPackets++; |
| 1846 | |||
| 1847 | dev_kfree_skb(PacketToDrop); | 1614 | dev_kfree_skb(PacketToDrop); |
| 1848 | atomic_dec(&Adapter->TotalPacketCount); | 1615 | atomic_dec(&Adapter->TotalPacketCount); |
| 1849 | } | 1616 | } |
| 1850 | } | 1617 | } |
| 1851 | spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); | 1618 | spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); |
| 1852 | |||
| 1853 | } | 1619 | } |
| 1854 | 1620 | ||
| 1855 | static void beceem_protocol_reset (PMINI_ADAPTER Adapter) | 1621 | static void beceem_protocol_reset(PMINI_ADAPTER Adapter) |
| 1856 | { | 1622 | { |
| 1857 | int i; | 1623 | int i; |
| 1858 | |||
| 1859 | if (netif_msg_link(Adapter)) | 1624 | if (netif_msg_link(Adapter)) |
| 1860 | pr_notice(PFX "%s: protocol reset\n", Adapter->dev->name); | 1625 | pr_notice(PFX "%s: protocol reset\n", Adapter->dev->name); |
| 1861 | 1626 | ||
| @@ -1864,32 +1629,22 @@ static void beceem_protocol_reset (PMINI_ADAPTER Adapter) · 2 unmodified lines | |||
| 1864 | 1629 | ||
| 1865 | Adapter->IdleMode = FALSE; | 1630 | Adapter->IdleMode = FALSE; |
| 1866 | Adapter->LinkUpStatus = FALSE; | 1631 | Adapter->LinkUpStatus = FALSE; |
| 1867 | ClearTargetDSXBuffer(Adapter,0, TRUE); | 1632 | ClearTargetDSXBuffer(Adapter, 0, TRUE); |
| 1868 | //Delete All Classifier Rules | 1633 | /* Delete All Classifier Rules */ |
| 1869 | 1634 | ||
| 1870 | for(i = 0;i<HiPriority;i++) | 1635 | for (i = 0; i < HiPriority; i++) |
| 1871 | { | 1636 | DeleteAllClassifiersForSF(Adapter, i); |
| 1872 | DeleteAllClassifiersForSF(Adapter,i); | ||
| 1873 | } | ||
| 1874 | 1637 | ||
| 1875 | flush_all_queues(Adapter); | 1638 | flush_all_queues(Adapter); |
| 1876 | 1639 | ||
| 1877 | if(Adapter->TimerActive == TRUE) | 1640 | if (Adapter->TimerActive == TRUE) |
| 1878 | Adapter->TimerActive = FALSE; | 1641 | Adapter->TimerActive = FALSE; |
| 1879 | 1642 | ||
| 1880 | memset(Adapter->astFragmentedPktClassifierTable, 0, | 1643 | memset(Adapter->astFragmentedPktClassifierTable, 0, sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES); |
| 1881 | sizeof(S_FRAGMENTED_PACKET_INFO) * MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES); | ||
| 1882 | 1644 | ||
| 1883 | for(i = 0;i<HiPriority;i++) | 1645 | for (i = 0; i < HiPriority; i++) { |
| 1884 | { | 1646 | /* resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF. */ |
| 1885 | //resetting only the first size (S_MIBS_SERVICEFLOW_TABLE) for the SF. | 1647 | /* It is same between MIBs and SF. */ |
| 1886 | // It is same between MIBs and SF. | 1648 | memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS)); |
| 1887 | memset(&Adapter->PackInfo[i].stMibsExtServiceFlowTable, | ||
| 1888 | 0, sizeof(S_MIBS_EXTSERVICEFLOW_PARAMETERS)); | ||
| 1889 | } | 1649 | } |
| 1890 | } | 1650 | } |
| 1891 | |||
| 1892 | |||
| 1893 | |||
| 1894 | |||
| 1895 | |||
| @@ -74,4 +74,6 @@ · 73 unmodified lines | |||
| 74 | #define DRV_VERSION VER_FILEVERSION_STR | 74 | #define DRV_VERSION VER_FILEVERSION_STR |
| 75 | #define PFX DRV_NAME " " | 75 | #define PFX DRV_NAME " " |
| 76 | 76 | ||
| 77 | extern struct class *bcm_class; | ||
| 78 | |||
| 77 | #endif | 79 | #endif |
| @@ -4013,7 +4013,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) · 4012 unmodified lines | |||
| 4013 | if(uiTotalDataToCopy < ISOLength) | 4013 | if(uiTotalDataToCopy < ISOLength) |
| 4014 | { | 4014 | { |
| 4015 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); | 4015 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); |
| 4016 | return STATUS_FAILURE; | 4016 | Status = STATUS_FAILURE; |
| 4017 | goto out; | ||
| 4017 | } | 4018 | } |
| 4018 | 4019 | ||
| 4019 | uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - | 4020 | uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - |
| @@ -4026,7 +4027,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) · 6 unmodified lines | |||
| 4026 | if(uiTotalDataToCopy < ISOLength) | 4027 | if(uiTotalDataToCopy < ISOLength) |
| 4027 | { | 4028 | { |
| 4028 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); | 4029 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); |
| 4029 | return STATUS_FAILURE; | 4030 | Status = STATUS_FAILURE; |
| 4031 | goto out; | ||
| 4030 | } | 4032 | } |
| 4031 | 4033 | ||
| 4032 | uiTotalDataToCopy = ISOLength; | 4034 | uiTotalDataToCopy = ISOLength; |
| @@ -4143,7 +4145,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) · 110 unmodified lines | |||
| 4143 | if(uiTotalDataToCopy < ISOLength) | 4145 | if(uiTotalDataToCopy < ISOLength) |
| 4144 | { | 4146 | { |
| 4145 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); | 4147 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); |
| 4146 | return STATUS_FAILURE; | 4148 | Status = STATUS_FAILURE; |
| 4149 | goto out; | ||
| 4147 | } | 4150 | } |
| 4148 | 4151 | ||
| 4149 | uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - | 4152 | uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - |
| @@ -4156,7 +4159,8 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) · 6 unmodified lines | |||
| 4156 | if(uiTotalDataToCopy < ISOLength) | 4159 | if(uiTotalDataToCopy < ISOLength) |
| 4157 | { | 4160 | { |
| 4158 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); | 4161 | BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); |
| 4159 | return STATUS_FAILURE; | 4162 | Status = STATUS_FAILURE; |
| 4163 | goto out; | ||
| 4160 | } | 4164 | } |
| 4161 | 4165 | ||
| 4162 | uiTotalDataToCopy = ISOLength; | 4166 | uiTotalDataToCopy = ISOLength; |
| @@ -4257,6 +4261,7 @@ INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) · 94 unmodified lines | |||
| 4257 | 4261 | ||
| 4258 | } | 4262 | } |
| 4259 | 4263 | ||
| 4264 | out: | ||
| 4260 | kfree(Buff); | 4265 | kfree(Buff); |
| 4261 | 4266 | ||
| 4262 | return Status; | 4267 | return Status; |
| @@ -1,40 +0,0 @@ | |||
| 1 | config BRCMUTIL | ||
| 2 | tristate | ||
| 3 | default n | ||
| 4 | |||
| 5 | config BRCMSMAC | ||
| 6 | tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver" | ||
| 7 | default n | ||
| 8 | depends on PCI | ||
| 9 | depends on WLAN && MAC80211 | ||
| 10 | depends on X86 || MIPS | ||
| 11 | select BRCMUTIL | ||
| 12 | select FW_LOADER | ||
| 13 | select CRC_CCITT | ||
| 14 | ---help--- | ||
| 15 | This module adds support for PCIe wireless adapters based on Broadcom | ||
| 16 | IEEE802.11n SoftMAC chipsets. If you choose to build a module, it'll | ||
| 17 | be called brcmsmac.ko. | ||
| 18 | |||
| 19 | config BRCMFMAC | ||
| 20 | tristate "Broadcom IEEE802.11n embedded FullMAC WLAN driver" | ||
| 21 | default n | ||
| 22 | depends on MMC | ||
| 23 | depends on WLAN && CFG80211 | ||
| 24 | depends on X86 || MIPS | ||
| 25 | select BRCMUTIL | ||
| 26 | select FW_LOADER | ||
| 27 | select WIRELESS_EXT | ||
| 28 | select WEXT_PRIV | ||
| 29 | ---help--- | ||
| 30 | This module adds support for embedded wireless adapters based on | ||
| 31 | Broadcom IEEE802.11n FullMAC chipsets. This driver uses the kernel's | ||
| 32 | wireless extensions subsystem. If you choose to build a module, | ||
| 33 | it'll be called brcmfmac.ko. | ||
| 34 | |||
| 35 | config BRCMDBG | ||
| 36 | bool "Broadcom driver debug functions" | ||
| 37 | default n | ||
| 38 | depends on BRCMSMAC || BRCMFMAC | ||
| 39 | ---help--- | ||
| 40 | Selecting this enables additional code for debug purposes. | ||
| @@ -1,24 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Makefile fragment for Broadcom 802.11n Networking Device Driver | ||
| 3 | # | ||
| 4 | # Copyright (c) 2010 Broadcom Corporation | ||
| 5 | # | ||
| 6 | # Permission to use, copy, modify, and/or distribute this software for any | ||
| 7 | # purpose with or without fee is hereby granted, provided that the above | ||
| 8 | # copyright notice and this permission notice appear in all copies. | ||
| 9 | # | ||
| 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 13 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 15 | # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 16 | # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 17 | |||
| 18 | # common flags | ||
| 19 | subdir-ccflags-y := -DBCMDMA32 | ||
| 20 | subdir-ccflags-$(CONFIG_BRCMDBG) += -DBCMDBG | ||
| 21 | |||
| 22 | obj-$(CONFIG_BRCMUTIL) += brcmutil/ | ||
| 23 | obj-$(CONFIG_BRCMFMAC) += brcmfmac/ | ||
| 24 | obj-$(CONFIG_BRCMSMAC) += brcmsmac/ | ||
| @@ -1 +0,0 @@ | |||
| 1 | refer to: http://linuxwireless.org/en/users/Drivers/brcm80211 | ||
| @@ -1,13 +0,0 @@ | |||
| 1 | To Do List for Broadcom Mac80211 driver before getting in mainline | ||
| 2 | |||
| 3 | Bugs | ||
| 4 | ==== | ||
| 5 | - none known at this moment | ||
| 6 | |||
| 7 | brcmfmac | ||
| 8 | ===================== | ||
| 9 | - ASSERTS deprecated in mainline, replace by warning + error handling | ||
| 10 | |||
| 11 | brcm80211 info page | ||
| 12 | ===================== | ||
| 13 | http://linuxwireless.org/en/users/Drivers/brcm80211 | ||
| @@ -1,39 +0,0 @@ | |||
| 1 | # | ||
| 2 | # Makefile fragment for Broadcom 802.11n Networking Device Driver | ||
| 3 | # | ||
| 4 | # Copyright (c) 2010 Broadcom Corporation | ||
| 5 | # | ||
| 6 | # Permission to use, copy, modify, and/or distribute this software for any | ||
| 7 | # purpose with or without fee is hereby granted, provided that the above | ||
| 8 | # copyright notice and this permission notice appear in all copies. | ||
| 9 | # | ||
| 10 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 11 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 12 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 13 | # SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 14 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 15 | # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 16 | # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 17 | |||
| 18 | ccflags-y := \ | ||
| 19 | -DBRCMF_FIRSTREAD=64 \ | ||
| 20 | -DBRCMF_SDALIGN=64 \ | ||
| 21 | -DMAX_HDR_READ=64 | ||
| 22 | |||
| 23 | ccflags-$(CONFIG_BRCMDBG) += -DSHOW_EVENTS | ||
| 24 | |||
| 25 | ccflags-y += \ | ||
| 26 | -Idrivers/staging/brcm80211/brcmfmac \ | ||
| 27 | -Idrivers/staging/brcm80211/include | ||
| 28 | |||
| 29 | DHDOFILES = \ | ||
| 30 | wl_cfg80211.o \ | ||
| 31 | dhd_cdc.o \ | ||
| 32 | dhd_common.o \ | ||
| 33 | dhd_sdio.o \ | ||
| 34 | dhd_linux.o \ | ||
| 35 | bcmsdh.o \ | ||
| 36 | bcmsdh_sdmmc.o | ||
| 37 | |||
| 38 | obj-$(CONFIG_BRCMFMAC) += brcmfmac.o | ||
| 39 | brcmfmac-objs += $(DHDOFILES) | ||
| @@ -1,32 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _bcmchip_h_ | ||
| 18 | #define _bcmchip_h_ | ||
| 19 | |||
| 20 | /* bcm4329 */ | ||
| 21 | /* SDIO device core, ID 0x829 */ | ||
| 22 | #define BCM4329_CORE_BUS_BASE 0x18011000 | ||
| 23 | /* internal memory core, ID 0x80e */ | ||
| 24 | #define BCM4329_CORE_SOCRAM_BASE 0x18003000 | ||
| 25 | /* ARM Cortex M3 core, ID 0x82a */ | ||
| 26 | #define BCM4329_CORE_ARM_BASE 0x18002000 | ||
| 27 | #define BCM4329_RAMSIZE 0x48000 | ||
| 28 | /* firmware name */ | ||
| 29 | #define BCM4329_FW_NAME "brcm/bcm4329-fullmac-4.bin" | ||
| 30 | #define BCM4329_NV_NAME "brcm/bcm4329-fullmac-4.txt" | ||
| 31 | |||
| 32 | #endif /* _bcmchip_h_ */ | ||
| @@ -1,642 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | /* ****************** SDIO CARD Interface Functions **************************/ | ||
| 17 | |||
| 18 | #include <linux/types.h> | ||
| 19 | #include <linux/netdevice.h> | ||
| 20 | #include <linux/pci.h> | ||
| 21 | #include <linux/pci_ids.h> | ||
| 22 | #include <linux/sched.h> | ||
| 23 | #include <linux/completion.h> | ||
| 24 | |||
| 25 | #include <defs.h> | ||
| 26 | #include <brcm_hw_ids.h> | ||
| 27 | #include <brcmu_utils.h> | ||
| 28 | #include <brcmu_wifi.h> | ||
| 29 | #include <soc.h> | ||
| 30 | #include "dhd.h" | ||
| 31 | #include "dhd_bus.h" | ||
| 32 | #include "sdio_host.h" | ||
| 33 | |||
| 34 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 | ||
| 35 | |||
| 36 | #define BRCMF_SD_ERROR_VAL 0x0001 /* Error */ | ||
| 37 | #define BRCMF_SD_INFO_VAL 0x0002 /* Info */ | ||
| 38 | |||
| 39 | |||
| 40 | #ifdef BCMDBG | ||
| 41 | #define BRCMF_SD_ERROR(x) \ | ||
| 42 | do { \ | ||
| 43 | if ((brcmf_sdio_msglevel & BRCMF_SD_ERROR_VAL) && \ | ||
| 44 | net_ratelimit()) \ | ||
| 45 | printk x; \ | ||
| 46 | } while (0) | ||
| 47 | #define BRCMF_SD_INFO(x) \ | ||
| 48 | do { \ | ||
| 49 | if ((brcmf_sdio_msglevel & BRCMF_SD_INFO_VAL) && \ | ||
| 50 | net_ratelimit()) \ | ||
| 51 | printk x; \ | ||
| 52 | } while (0) | ||
| 53 | #else /* BCMDBG */ | ||
| 54 | #define BRCMF_SD_ERROR(x) | ||
| 55 | #define BRCMF_SD_INFO(x) | ||
| 56 | #endif /* BCMDBG */ | ||
| 57 | |||
| 58 | /* debugging macros */ | ||
| 59 | #define SDLX_MSG(x) | ||
| 60 | |||
| 61 | #define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */ | ||
| 62 | #define SDIOH_CMD_TYPE_APPEND 1 /* Append command */ | ||
| 63 | #define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */ | ||
| 64 | |||
| 65 | #define SDIOH_DATA_PIO 0 /* PIO mode */ | ||
| 66 | #define SDIOH_DATA_DMA 1 /* DMA mode */ | ||
| 67 | |||
| 68 | struct brcmf_sdio_card { | ||
| 69 | bool init_success; /* underlying driver successfully attached */ | ||
| 70 | void *sdioh; /* handler for sdioh */ | ||
| 71 | u32 vendevid; /* Target Vendor and Device ID on SD bus */ | ||
| 72 | bool regfail; /* Save status of last | ||
| 73 | reg_read/reg_write call */ | ||
| 74 | u32 sbwad; /* Save backplane window address */ | ||
| 75 | }; | ||
| 76 | |||
| 77 | /** | ||
| 78 | * SDIO Host Controller info | ||
| 79 | */ | ||
| 80 | struct sdio_hc { | ||
| 81 | struct sdio_hc *next; | ||
| 82 | struct device *dev; /* platform device handle */ | ||
| 83 | void *regs; /* SDIO Host Controller address */ | ||
| 84 | struct brcmf_sdio_card *card; | ||
| 85 | void *ch; | ||
| 86 | unsigned int oob_irq; | ||
| 87 | unsigned long oob_flags; /* OOB Host specifiction | ||
| 88 | as edge and etc */ | ||
| 89 | bool oob_irq_registered; | ||
| 90 | }; | ||
| 91 | |||
| 92 | /* local copy of bcm sd handler */ | ||
| 93 | static struct brcmf_sdio_card *l_card; | ||
| 94 | |||
| 95 | const uint brcmf_sdio_msglevel = BRCMF_SD_ERROR_VAL; | ||
| 96 | |||
| 97 | static struct sdio_hc *sdhcinfo; | ||
| 98 | |||
| 99 | /* driver info, initialized when brcmf_sdio_register is called */ | ||
| 100 | static struct brcmf_sdioh_driver drvinfo = { NULL, NULL }; | ||
| 101 | |||
| 102 | /* Module parameters specific to each host-controller driver */ | ||
| 103 | |||
| 104 | module_param(sd_msglevel, uint, 0); | ||
| 105 | |||
| 106 | extern uint sd_f2_blocksize; | ||
| 107 | module_param(sd_f2_blocksize, int, 0); | ||
| 108 | |||
| 109 | /* forward declarations */ | ||
| 110 | int brcmf_sdio_probe(struct device *dev); | ||
| 111 | EXPORT_SYMBOL(brcmf_sdio_probe); | ||
| 112 | |||
| 113 | int brcmf_sdio_remove(struct device *dev); | ||
| 114 | EXPORT_SYMBOL(brcmf_sdio_remove); | ||
| 115 | |||
| 116 | struct brcmf_sdio_card* | ||
| 117 | brcmf_sdcard_attach(void *cfghdl, u32 *regsva, uint irq) | ||
| 118 | { | ||
| 119 | struct brcmf_sdio_card *card; | ||
| 120 | |||
| 121 | card = kzalloc(sizeof(struct brcmf_sdio_card), GFP_ATOMIC); | ||
| 122 | if (card == NULL) { | ||
| 123 | BRCMF_SD_ERROR(("sdcard_attach: out of memory")); | ||
| 124 | return NULL; | ||
| 125 | } | ||
| 126 | |||
| 127 | /* save the handler locally */ | ||
| 128 | l_card = card; | ||
| 129 | |||
| 130 | card->sdioh = brcmf_sdioh_attach(cfghdl, irq); | ||
| 131 | if (!card->sdioh) { | ||
| 132 | brcmf_sdcard_detach(card); | ||
| 133 | return NULL; | ||
| 134 | } | ||
| 135 | |||
| 136 | card->init_success = true; | ||
| 137 | |||
| 138 | *regsva = SI_ENUM_BASE; | ||
| 139 | |||
| 140 | /* Report the BAR, to fix if needed */ | ||
| 141 | card->sbwad = SI_ENUM_BASE; | ||
| 142 | return card; | ||
| 143 | } | ||
| 144 | |||
| 145 | int brcmf_sdcard_detach(struct brcmf_sdio_card *card) | ||
| 146 | { | ||
| 147 | if (card != NULL) { | ||
| 148 | if (card->sdioh) { | ||
| 149 | brcmf_sdioh_detach(card->sdioh); | ||
| 150 | card->sdioh = NULL; | ||
| 151 | } | ||
| 152 | kfree(card); | ||
| 153 | } | ||
| 154 | |||
| 155 | l_card = NULL; | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | int | ||
| 160 | brcmf_sdcard_iovar_op(struct brcmf_sdio_card *card, const char *name, | ||
| 161 | void *params, int plen, void *arg, int len, bool set) | ||
| 162 | { | ||
| 163 | return brcmf_sdioh_iovar_op(card->sdioh, name, params, plen, arg, | ||
| 164 | len, set); | ||
| 165 | } | ||
| 166 | |||
| 167 | int brcmf_sdcard_intr_enable(struct brcmf_sdio_card *card) | ||
| 168 | { | ||
| 169 | return brcmf_sdioh_interrupt_set(card->sdioh, true); | ||
| 170 | } | ||
| 171 | |||
| 172 | int brcmf_sdcard_intr_disable(struct brcmf_sdio_card *card) | ||
| 173 | { | ||
| 174 | return brcmf_sdioh_interrupt_set(card->sdioh, false); | ||
| 175 | } | ||
| 176 | |||
| 177 | int brcmf_sdcard_intr_reg(struct brcmf_sdio_card *card, | ||
| 178 | void (*fn)(void *), void *argh) | ||
| 179 | { | ||
| 180 | return brcmf_sdioh_interrupt_register(card->sdioh, fn, argh); | ||
| 181 | } | ||
| 182 | |||
| 183 | int brcmf_sdcard_intr_dereg(struct brcmf_sdio_card *card) | ||
| 184 | { | ||
| 185 | return brcmf_sdioh_interrupt_deregister(card->sdioh); | ||
| 186 | } | ||
| 187 | |||
| 188 | u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_card *card, uint fnc_num, u32 addr, | ||
| 189 | int *err) | ||
| 190 | { | ||
| 191 | int status; | ||
| 192 | s32 retry = 0; | ||
| 193 | u8 data = 0; | ||
| 194 | |||
| 195 | if (!card) | ||
| 196 | card = l_card; | ||
| 197 | |||
| 198 | do { | ||
| 199 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
| 200 | udelay(1000); | ||
| 201 | status = | ||
| 202 | brcmf_sdioh_cfg_read(card->sdioh, fnc_num, addr, | ||
| 203 | (u8 *) &data); | ||
| 204 | } while (status != 0 | ||
| 205 | && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); | ||
| 206 | if (err) | ||
| 207 | *err = status; | ||
| 208 | |||
| 209 | BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n", | ||
| 210 | __func__, fnc_num, addr, data)); | ||
| 211 | |||
| 212 | return data; | ||
| 213 | } | ||
| 214 | |||
| 215 | void | ||
| 216 | brcmf_sdcard_cfg_write(struct brcmf_sdio_card *card, uint fnc_num, u32 addr, | ||
| 217 | u8 data, int *err) | ||
| 218 | { | ||
| 219 | int status; | ||
| 220 | s32 retry = 0; | ||
| 221 | |||
| 222 | if (!card) | ||
| 223 | card = l_card; | ||
| 224 | |||
| 225 | do { | ||
| 226 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
| 227 | udelay(1000); | ||
| 228 | status = | ||
| 229 | brcmf_sdioh_cfg_write(card->sdioh, fnc_num, addr, | ||
| 230 | (u8 *) &data); | ||
| 231 | } while (status != 0 | ||
| 232 | && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); | ||
| 233 | if (err) | ||
| 234 | *err = status; | ||
| 235 | |||
| 236 | BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u8data = 0x%x\n", | ||
| 237 | __func__, fnc_num, addr, data)); | ||
| 238 | } | ||
| 239 | |||
| 240 | u32 brcmf_sdcard_cfg_read_word(struct brcmf_sdio_card *card, uint fnc_num, | ||
| 241 | u32 addr, int *err) | ||
| 242 | { | ||
| 243 | int status; | ||
| 244 | u32 data = 0; | ||
| 245 | |||
| 246 | if (!card) | ||
| 247 | card = l_card; | ||
| 248 | |||
| 249 | status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, | ||
| 250 | SDIOH_READ, fnc_num, addr, &data, 4); | ||
| 251 | |||
| 252 | if (err) | ||
| 253 | *err = status; | ||
| 254 | |||
| 255 | BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n", | ||
| 256 | __func__, fnc_num, addr, data)); | ||
| 257 | |||
| 258 | return data; | ||
| 259 | } | ||
| 260 | |||
| 261 | void | ||
| 262 | brcmf_sdcard_cfg_write_word(struct brcmf_sdio_card *card, uint fnc_num, | ||
| 263 | u32 addr, u32 data, int *err) | ||
| 264 | { | ||
| 265 | int status; | ||
| 266 | |||
| 267 | if (!card) | ||
| 268 | card = l_card; | ||
| 269 | |||
| 270 | status = | ||
| 271 | brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, | ||
| 272 | SDIOH_WRITE, fnc_num, addr, &data, 4); | ||
| 273 | |||
| 274 | if (err) | ||
| 275 | *err = status; | ||
| 276 | |||
| 277 | BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, u32data = 0x%x\n", | ||
| 278 | __func__, fnc_num, addr, data)); | ||
| 279 | } | ||
| 280 | |||
| 281 | int brcmf_sdcard_cis_read(struct brcmf_sdio_card *card, uint func, u8 * cis, | ||
| 282 | uint length) | ||
| 283 | { | ||
| 284 | int status; | ||
| 285 | |||
| 286 | u8 *tmp_buf, *tmp_ptr; | ||
| 287 | u8 *ptr; | ||
| 288 | bool ascii = func & ~0xf; | ||
| 289 | func &= 0x7; | ||
| 290 | |||
| 291 | if (!card) | ||
| 292 | card = l_card; | ||
| 293 | |||
| 294 | status = brcmf_sdioh_cis_read(card->sdioh, func, cis, length); | ||
| 295 | |||
| 296 | if (ascii) { | ||
| 297 | /* Move binary bits to tmp and format them | ||
| 298 | into the provided buffer. */ | ||
| 299 | tmp_buf = kmalloc(length, GFP_ATOMIC); | ||
| 300 | if (tmp_buf == NULL) { | ||
| 301 | BRCMF_SD_ERROR(("%s: out of memory\n", __func__)); | ||
| 302 | return -ENOMEM; | ||
| 303 | } | ||
| 304 | memcpy(tmp_buf, cis, length); | ||
| 305 | for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); | ||
| 306 | tmp_ptr++) { | ||
| 307 | ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff); | ||
| 308 | if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0) | ||
| 309 | ptr += sprintf((char *)ptr, "\n"); | ||
| 310 | } | ||
| 311 | kfree(tmp_buf); | ||
| 312 | } | ||
| 313 | |||
| 314 | return status; | ||
| 315 | } | ||
| 316 | |||
| 317 | static int | ||
| 318 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_card *card, u32 address) | ||
| 319 | { | ||
| 320 | int err = 0; | ||
| 321 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, | ||
| 322 | (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); | ||
| 323 | if (!err) | ||
| 324 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 325 | SBSDIO_FUNC1_SBADDRMID, | ||
| 326 | (address >> 16) & SBSDIO_SBADDRMID_MASK, | ||
| 327 | &err); | ||
| 328 | if (!err) | ||
| 329 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 330 | SBSDIO_FUNC1_SBADDRHIGH, | ||
| 331 | (address >> 24) & SBSDIO_SBADDRHIGH_MASK, | ||
| 332 | &err); | ||
| 333 | |||
| 334 | return err; | ||
| 335 | } | ||
| 336 | |||
| 337 | u32 brcmf_sdcard_reg_read(struct brcmf_sdio_card *card, u32 addr, uint size) | ||
| 338 | { | ||
| 339 | int status; | ||
| 340 | u32 word = 0; | ||
| 341 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | ||
| 342 | |||
| 343 | BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, ", __func__, addr)); | ||
| 344 | |||
| 345 | if (!card) | ||
| 346 | card = l_card; | ||
| 347 | |||
| 348 | if (bar0 != card->sbwad) { | ||
| 349 | if (brcmf_sdcard_set_sbaddr_window(card, bar0)) | ||
| 350 | return 0xFFFFFFFF; | ||
| 351 | |||
| 352 | card->sbwad = bar0; | ||
| 353 | } | ||
| 354 | |||
| 355 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
| 356 | if (size == 4) | ||
| 357 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
| 358 | |||
| 359 | status = brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, | ||
| 360 | SDIOH_READ, SDIO_FUNC_1, addr, &word, size); | ||
| 361 | |||
| 362 | card->regfail = (status != 0); | ||
| 363 | |||
| 364 | BRCMF_SD_INFO(("u32data = 0x%x\n", word)); | ||
| 365 | |||
| 366 | /* if ok, return appropriately masked word */ | ||
| 367 | if (status == 0) { | ||
| 368 | switch (size) { | ||
| 369 | case sizeof(u8): | ||
| 370 | return word & 0xff; | ||
| 371 | case sizeof(u16): | ||
| 372 | return word & 0xffff; | ||
| 373 | case sizeof(u32): | ||
| 374 | return word; | ||
| 375 | default: | ||
| 376 | card->regfail = true; | ||
| 377 | |||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | /* otherwise, bad sdio access or invalid size */ | ||
| 382 | BRCMF_SD_ERROR(("%s: error reading addr 0x%04x size %d\n", __func__, | ||
| 383 | addr, size)); | ||
| 384 | return 0xFFFFFFFF; | ||
| 385 | } | ||
| 386 | |||
| 387 | u32 brcmf_sdcard_reg_write(struct brcmf_sdio_card *card, u32 addr, uint size, | ||
| 388 | u32 data) | ||
| 389 | { | ||
| 390 | int status; | ||
| 391 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | ||
| 392 | int err = 0; | ||
| 393 | |||
| 394 | BRCMF_SD_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", | ||
| 395 | __func__, addr, size * 8, data)); | ||
| 396 | |||
| 397 | if (!card) | ||
| 398 | card = l_card; | ||
| 399 | |||
| 400 | if (bar0 != card->sbwad) { | ||
| 401 | err = brcmf_sdcard_set_sbaddr_window(card, bar0); | ||
| 402 | if (err) | ||
| 403 | return err; | ||
| 404 | |||
| 405 | card->sbwad = bar0; | ||
| 406 | } | ||
| 407 | |||
| 408 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
| 409 | if (size == 4) | ||
| 410 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
| 411 | status = | ||
| 412 | brcmf_sdioh_request_word(card->sdioh, SDIOH_CMD_TYPE_NORMAL, | ||
| 413 | SDIOH_WRITE, SDIO_FUNC_1, addr, &data, size); | ||
| 414 | card->regfail = (status != 0); | ||
| 415 | |||
| 416 | if (status == 0) | ||
| 417 | return 0; | ||
| 418 | |||
| 419 | BRCMF_SD_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n", | ||
| 420 | __func__, data, addr, size)); | ||
| 421 | return 0xFFFFFFFF; | ||
| 422 | } | ||
| 423 | |||
| 424 | bool brcmf_sdcard_regfail(struct brcmf_sdio_card *card) | ||
| 425 | { | ||
| 426 | return card->regfail; | ||
| 427 | } | ||
| 428 | |||
| 429 | int | ||
| 430 | brcmf_sdcard_recv_buf(struct brcmf_sdio_card *card, u32 addr, uint fn, | ||
| 431 | uint flags, | ||
| 432 | u8 *buf, uint nbytes, struct sk_buff *pkt, | ||
| 433 | void (*complete)(void *handle, int status, | ||
| 434 | bool sync_waiting), | ||
| 435 | void *handle) | ||
| 436 | { | ||
| 437 | int status; | ||
| 438 | uint incr_fix; | ||
| 439 | uint width; | ||
| 440 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | ||
| 441 | int err = 0; | ||
| 442 | |||
| 443 | BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", | ||
| 444 | __func__, fn, addr, nbytes)); | ||
| 445 | |||
| 446 | /* Async not implemented yet */ | ||
| 447 | if (flags & SDIO_REQ_ASYNC) | ||
| 448 | return -ENOTSUPP; | ||
| 449 | |||
| 450 | if (bar0 != card->sbwad) { | ||
| 451 | err = brcmf_sdcard_set_sbaddr_window(card, bar0); | ||
| 452 | if (err) | ||
| 453 | return err; | ||
| 454 | |||
| 455 | card->sbwad = bar0; | ||
| 456 | } | ||
| 457 | |||
| 458 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
| 459 | |||
| 460 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; | ||
| 461 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | ||
| 462 | if (width == 4) | ||
| 463 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
| 464 | |||
| 465 | status = brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO, | ||
| 466 | incr_fix, SDIOH_READ, fn, addr, width, nbytes, buf, pkt); | ||
| 467 | |||
| 468 | return status; | ||
| 469 | } | ||
| 470 | |||
| 471 | int | ||
| 472 | brcmf_sdcard_send_buf(struct brcmf_sdio_card *card, u32 addr, uint fn, | ||
| 473 | uint flags, u8 *buf, uint nbytes, void *pkt, | ||
| 474 | void (*complete)(void *handle, int status, | ||
| 475 | bool sync_waiting), | ||
| 476 | void *handle) | ||
| 477 | { | ||
| 478 | uint incr_fix; | ||
| 479 | uint width; | ||
| 480 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | ||
| 481 | int err = 0; | ||
| 482 | |||
| 483 | BRCMF_SD_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", | ||
| 484 | __func__, fn, addr, nbytes)); | ||
| 485 | |||
| 486 | /* Async not implemented yet */ | ||
| 487 | if (flags & SDIO_REQ_ASYNC) | ||
| 488 | return -ENOTSUPP; | ||
| 489 | |||
| 490 | if (bar0 != card->sbwad) { | ||
| 491 | err = brcmf_sdcard_set_sbaddr_window(card, bar0); | ||
| 492 | if (err) | ||
| 493 | return err; | ||
| 494 | |||
| 495 | card->sbwad = bar0; | ||
| 496 | } | ||
| 497 | |||
| 498 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
| 499 | |||
| 500 | incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; | ||
| 501 | width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; | ||
| 502 | if (width == 4) | ||
| 503 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
| 504 | |||
| 505 | return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO, | ||
| 506 | incr_fix, SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt); | ||
| 507 | } | ||
| 508 | |||
| 509 | int brcmf_sdcard_rwdata(struct brcmf_sdio_card *card, uint rw, u32 addr, | ||
| 510 | u8 *buf, uint nbytes) | ||
| 511 | { | ||
| 512 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
| 513 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
| 514 | |||
| 515 | return brcmf_sdioh_request_buffer(card->sdioh, SDIOH_DATA_PIO, | ||
| 516 | SDIOH_DATA_INC, (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1, | ||
| 517 | addr, 4, nbytes, buf, NULL); | ||
| 518 | } | ||
| 519 | |||
| 520 | int brcmf_sdcard_abort(struct brcmf_sdio_card *card, uint fn) | ||
| 521 | { | ||
| 522 | return brcmf_sdioh_abort(card->sdioh, fn); | ||
| 523 | } | ||
| 524 | |||
| 525 | int brcmf_sdcard_query_device(struct brcmf_sdio_card *card) | ||
| 526 | { | ||
| 527 | card->vendevid = (PCI_VENDOR_ID_BROADCOM << 16) | 0; | ||
| 528 | return card->vendevid; | ||
| 529 | } | ||
| 530 | |||
| 531 | u32 brcmf_sdcard_cur_sbwad(struct brcmf_sdio_card *card) | ||
| 532 | { | ||
| 533 | if (!card) | ||
| 534 | card = l_card; | ||
| 535 | |||
| 536 | return card->sbwad; | ||
| 537 | } | ||
| 538 | |||
| 539 | int brcmf_sdio_probe(struct device *dev) | ||
| 540 | { | ||
| 541 | struct sdio_hc *sdhc = NULL; | ||
| 542 | u32 regs = 0; | ||
| 543 | struct brcmf_sdio_card *card = NULL; | ||
| 544 | int irq = 0; | ||
| 545 | u32 vendevid; | ||
| 546 | unsigned long irq_flags = 0; | ||
| 547 | |||
| 548 | /* allocate SDIO Host Controller state info */ | ||
| 549 | sdhc = kzalloc(sizeof(struct sdio_hc), GFP_ATOMIC); | ||
| 550 | if (!sdhc) { | ||
| 551 | SDLX_MSG(("%s: out of memory\n", __func__)); | ||
| 552 | goto err; | ||
| 553 | } | ||
| 554 | sdhc->dev = (void *)dev; | ||
| 555 | |||
| 556 | card = brcmf_sdcard_attach((void *)0, ®s, irq); | ||
| 557 | if (!card) { | ||
| 558 | SDLX_MSG(("%s: attach failed\n", __func__)); | ||
| 559 | goto err; | ||
| 560 | } | ||
| 561 | |||
| 562 | sdhc->card = card; | ||
| 563 | sdhc->oob_irq = irq; | ||
| 564 | sdhc->oob_flags = irq_flags; | ||
| 565 | sdhc->oob_irq_registered = false; /* to make sure.. */ | ||
| 566 | |||
| 567 | /* chain SDIO Host Controller info together */ | ||
| 568 | sdhc->next = sdhcinfo; | ||
| 569 | sdhcinfo = sdhc; | ||
| 570 | /* Read the vendor/device ID from the CIS */ | ||
| 571 | vendevid = brcmf_sdcard_query_device(card); | ||
| 572 | |||
| 573 | /* try to attach to the target device */ | ||
| 574 | sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF), | ||
| 575 | 0, 0, 0, 0, regs, card); | ||
| 576 | if (!sdhc->ch) { | ||
| 577 | SDLX_MSG(("%s: device attach failed\n", __func__)); | ||
| 578 | goto err; | ||
| 579 | } | ||
| 580 | |||
| 581 | return 0; | ||
| 582 | |||
| 583 | /* error handling */ | ||
| 584 | err: | ||
| 585 | if (sdhc) { | ||
| 586 | if (sdhc->card) | ||
| 587 | brcmf_sdcard_detach(sdhc->card); | ||
| 588 | kfree(sdhc); | ||
| 589 | } | ||
| 590 | |||
| 591 | return -ENODEV; | ||
| 592 | } | ||
| 593 | |||
| 594 | int brcmf_sdio_remove(struct device *dev) | ||
| 595 | { | ||
| 596 | struct sdio_hc *sdhc, *prev; | ||
| 597 | |||
| 598 | sdhc = sdhcinfo; | ||
| 599 | drvinfo.detach(sdhc->ch); | ||
| 600 | brcmf_sdcard_detach(sdhc->card); | ||
| 601 | /* find the SDIO Host Controller state for this pdev | ||
| 602 | and take it out from the list */ | ||
| 603 | for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { | ||
| 604 | if (sdhc->dev == (void *)dev) { | ||
| 605 | if (prev) | ||
| 606 | prev->next = sdhc->next; | ||
| 607 | else | ||
| 608 | sdhcinfo = NULL; | ||
| 609 | break; | ||
| 610 | } | ||
| 611 | prev = sdhc; | ||
| 612 | } | ||
| 613 | if (!sdhc) { | ||
| 614 | SDLX_MSG(("%s: failed\n", __func__)); | ||
| 615 | return 0; | ||
| 616 | } | ||
| 617 | |||
| 618 | /* release SDIO Host Controller info */ | ||
| 619 | kfree(sdhc); | ||
| 620 | return 0; | ||
| 621 | } | ||
| 622 | |||
| 623 | int brcmf_sdio_register(struct brcmf_sdioh_driver *driver) | ||
| 624 | { | ||
| 625 | drvinfo = *driver; | ||
| 626 | |||
| 627 | SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n")); | ||
| 628 | return brcmf_sdio_function_init(); | ||
| 629 | } | ||
| 630 | |||
| 631 | void brcmf_sdio_unregister(void) | ||
| 632 | { | ||
| 633 | brcmf_sdio_function_cleanup(); | ||
| 634 | } | ||
| 635 | |||
| 636 | void brcmf_sdio_wdtmr_enable(bool enable) | ||
| 637 | { | ||
| 638 | if (enable) | ||
| 639 | brcmf_sdbrcm_wd_timer(sdhcinfo->ch, brcmf_watchdog_ms); | ||
| 640 | else | ||
| 641 | brcmf_sdbrcm_wd_timer(sdhcinfo->ch, 0); | ||
| 642 | } | ||
| @@ -1,1196 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | #include <linux/types.h> | ||
| 17 | #include <linux/netdevice.h> | ||
| 18 | #include <linux/mmc/sdio.h> | ||
| 19 | #include <linux/mmc/core.h> | ||
| 20 | #include <linux/mmc/sdio_func.h> | ||
| 21 | #include <linux/mmc/sdio_ids.h> | ||
| 22 | #include <linux/mmc/card.h> | ||
| 23 | #include <linux/suspend.h> | ||
| 24 | #include <linux/errno.h> | ||
| 25 | #include <linux/sched.h> /* request_irq() */ | ||
| 26 | #include <net/cfg80211.h> | ||
| 27 | |||
| 28 | #include <defs.h> | ||
| 29 | #include <brcm_hw_ids.h> | ||
| 30 | #include <brcmu_utils.h> | ||
| 31 | #include <brcmu_wifi.h> | ||
| 32 | #include "sdio_host.h" | ||
| 33 | #include "dhd.h" | ||
| 34 | #include "dhd_dbg.h" | ||
| 35 | #include "wl_cfg80211.h" | ||
| 36 | |||
| 37 | #define BLOCK_SIZE_64 64 | ||
| 38 | #define BLOCK_SIZE_512 512 | ||
| 39 | #define BLOCK_SIZE_4318 64 | ||
| 40 | #define BLOCK_SIZE_4328 512 | ||
| 41 | |||
| 42 | /* private bus modes */ | ||
| 43 | #define SDIOH_MODE_SD4 2 | ||
| 44 | |||
| 45 | #define CLIENT_INTR 0x100 /* Get rid of this! */ | ||
| 46 | |||
| 47 | #if !defined(SDIO_VENDOR_ID_BROADCOM) | ||
| 48 | #define SDIO_VENDOR_ID_BROADCOM 0x02d0 | ||
| 49 | #endif /* !defined(SDIO_VENDOR_ID_BROADCOM) */ | ||
| 50 | |||
| 51 | #define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000 | ||
| 52 | |||
| 53 | #define DMA_ALIGN_MASK 0x03 | ||
| 54 | |||
| 55 | #if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) | ||
| 56 | #define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */ | ||
| 57 | #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */ | ||
| 58 | #if !defined(SDIO_DEVICE_ID_BROADCOM_4325) | ||
| 59 | #define SDIO_DEVICE_ID_BROADCOM_4325 0x0493 | ||
| 60 | #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */ | ||
| 61 | #if !defined(SDIO_DEVICE_ID_BROADCOM_4329) | ||
| 62 | #define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 | ||
| 63 | #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */ | ||
| 64 | #if !defined(SDIO_DEVICE_ID_BROADCOM_4319) | ||
| 65 | #define SDIO_DEVICE_ID_BROADCOM_4319 0x4319 | ||
| 66 | #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */ | ||
| 67 | |||
| 68 | /* Common msglevel constants */ | ||
| 69 | #define SDH_ERROR_VAL 0x0001 /* Error */ | ||
| 70 | #define SDH_TRACE_VAL 0x0002 /* Trace */ | ||
| 71 | #define SDH_INFO_VAL 0x0004 /* Info */ | ||
| 72 | #define SDH_DEBUG_VAL 0x0008 /* Debug */ | ||
| 73 | #define SDH_DATA_VAL 0x0010 /* Data */ | ||
| 74 | #define SDH_CTRL_VAL 0x0020 /* Control Regs */ | ||
| 75 | #define SDH_LOG_VAL 0x0040 /* Enable bcmlog */ | ||
| 76 | #define SDH_DMA_VAL 0x0080 /* DMA */ | ||
| 77 | |||
| 78 | #ifdef BCMDBG | ||
| 79 | #define sd_err(x) \ | ||
| 80 | do { \ | ||
| 81 | if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \ | ||
| 82 | printk x; \ | ||
| 83 | } while (0) | ||
| 84 | #define sd_trace(x) \ | ||
| 85 | do { \ | ||
| 86 | if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \ | ||
| 87 | printk x; \ | ||
| 88 | } while (0) | ||
| 89 | #define sd_info(x) \ | ||
| 90 | do { \ | ||
| 91 | if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \ | ||
| 92 | printk x; \ | ||
| 93 | } while (0) | ||
| 94 | #define sd_debug(x) \ | ||
| 95 | do { \ | ||
| 96 | if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \ | ||
| 97 | printk x; \ | ||
| 98 | } while (0) | ||
| 99 | #define sd_data(x) \ | ||
| 100 | do { \ | ||
| 101 | if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \ | ||
| 102 | printk x; \ | ||
| 103 | } while (0) | ||
| 104 | #define sd_ctrl(x) \ | ||
| 105 | do { \ | ||
| 106 | if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \ | ||
| 107 | printk x; \ | ||
| 108 | } while (0) | ||
| 109 | #else | ||
| 110 | #define sd_err(x) | ||
| 111 | #define sd_trace(x) | ||
| 112 | #define sd_info(x) | ||
| 113 | #define sd_debug(x) | ||
| 114 | #define sd_data(x) | ||
| 115 | #define sd_ctrl(x) | ||
| 116 | #endif | ||
| 117 | |||
| 118 | struct sdos_info { | ||
| 119 | struct sdioh_info *sd; | ||
| 120 | spinlock_t lock; | ||
| 121 | }; | ||
| 122 | |||
| 123 | static void brcmf_sdioh_irqhandler(struct sdio_func *func); | ||
| 124 | static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func); | ||
| 125 | static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr); | ||
| 126 | static int brcmf_ops_sdio_probe(struct sdio_func *func, | ||
| 127 | const struct sdio_device_id *id); | ||
| 128 | static void brcmf_ops_sdio_remove(struct sdio_func *func); | ||
| 129 | |||
| 130 | #ifdef CONFIG_PM | ||
| 131 | static int brcmf_sdio_suspend(struct device *dev); | ||
| 132 | static int brcmf_sdio_resume(struct device *dev); | ||
| 133 | #endif /* CONFIG_PM */ | ||
| 134 | |||
| 135 | uint sd_f2_blocksize = 512; /* Default blocksize */ | ||
| 136 | |||
| 137 | uint sd_msglevel = 0x01; | ||
| 138 | |||
| 139 | /* module param defaults */ | ||
| 140 | static int clockoverride; | ||
| 141 | |||
| 142 | module_param(clockoverride, int, 0644); | ||
| 143 | MODULE_PARM_DESC(clockoverride, "SDIO card clock override"); | ||
| 144 | |||
| 145 | struct brcmf_sdmmc_instance *gInstance; | ||
| 146 | |||
| 147 | struct device sdmmc_dev; | ||
| 148 | |||
| 149 | /* devices we support, null terminated */ | ||
| 150 | static const struct sdio_device_id brcmf_sdmmc_ids[] = { | ||
| 151 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT)}, | ||
| 152 | {SDIO_DEVICE | ||
| 153 | (SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB)}, | ||
| 154 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325)}, | ||
| 155 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, | ||
| 156 | {SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319)}, | ||
| 157 | { /* end: all zeroes */ }, | ||
| 158 | }; | ||
| 159 | |||
| 160 | #ifdef CONFIG_PM | ||
| 161 | static const struct dev_pm_ops brcmf_sdio_pm_ops = { | ||
| 162 | .suspend = brcmf_sdio_suspend, | ||
| 163 | .resume = brcmf_sdio_resume, | ||
| 164 | }; | ||
| 165 | #endif /* CONFIG_PM */ | ||
| 166 | |||
| 167 | static struct sdio_driver brcmf_sdmmc_driver = { | ||
| 168 | .probe = brcmf_ops_sdio_probe, | ||
| 169 | .remove = brcmf_ops_sdio_remove, | ||
| 170 | .name = "brcmfmac", | ||
| 171 | .id_table = brcmf_sdmmc_ids, | ||
| 172 | #ifdef CONFIG_PM | ||
| 173 | .drv = { | ||
| 174 | .pm = &brcmf_sdio_pm_ops, | ||
| 175 | }, | ||
| 176 | #endif /* CONFIG_PM */ | ||
| 177 | }; | ||
| 178 | |||
| 179 | MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); | ||
| 180 | |||
| 181 | BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait); | ||
| 182 | BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_word_wait); | ||
| 183 | BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); | ||
| 184 | BRCMF_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); | ||
| 185 | |||
| 186 | static int | ||
| 187 | brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr, | ||
| 188 | int regsize, u32 *data); | ||
| 189 | |||
| 190 | static int brcmf_sdioh_enablefuncs(struct sdioh_info *sd) | ||
| 191 | { | ||
| 192 | int err_ret; | ||
| 193 | u32 fbraddr; | ||
| 194 | u8 func; | ||
| 195 | |||
| 196 | sd_trace(("%s\n", __func__)); | ||
| 197 | |||
| 198 | /* Get the Card's common CIS address */ | ||
| 199 | sd->com_cis_ptr = brcmf_sdioh_get_cisaddr(sd, SDIO_CCCR_CIS); | ||
| 200 | sd->func_cis_ptr[0] = sd->com_cis_ptr; | ||
| 201 | sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__, | ||
| 202 | sd->com_cis_ptr)); | ||
| 203 | |||
| 204 | /* Get the Card's function CIS (for each function) */ | ||
| 205 | for (fbraddr = SDIO_FBR_BASE(1), func = 1; | ||
| 206 | func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { | ||
| 207 | sd->func_cis_ptr[func] = | ||
| 208 | brcmf_sdioh_get_cisaddr(sd, SDIO_FBR_CIS + fbraddr); | ||
| 209 | sd_info(("%s: Function %d CIS Ptr = 0x%x\n", __func__, func, | ||
| 210 | sd->func_cis_ptr[func])); | ||
| 211 | } | ||
| 212 | |||
| 213 | sd->func_cis_ptr[0] = sd->com_cis_ptr; | ||
| 214 | sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __func__, | ||
| 215 | sd->com_cis_ptr)); | ||
| 216 | |||
| 217 | /* Enable Function 1 */ | ||
| 218 | sdio_claim_host(gInstance->func[1]); | ||
| 219 | err_ret = sdio_enable_func(gInstance->func[1]); | ||
| 220 | sdio_release_host(gInstance->func[1]); | ||
| 221 | if (err_ret) { | ||
| 222 | sd_err(("brcmf_sdioh_enablefuncs: Failed to enable F1 " | ||
| 223 | "Err: 0x%08x\n", err_ret)); | ||
| 224 | } | ||
| 225 | |||
| 226 | return false; | ||
| 227 | } | ||
| 228 | |||
| 229 | /* | ||
| 230 | * Public entry points & extern's | ||
| 231 | */ | ||
| 232 | struct sdioh_info *brcmf_sdioh_attach(void *bar0, uint irq) | ||
| 233 | { | ||
| 234 | struct sdioh_info *sd; | ||
| 235 | int err_ret; | ||
| 236 | |||
| 237 | sd_trace(("%s\n", __func__)); | ||
| 238 | |||
| 239 | if (gInstance == NULL) { | ||
| 240 | sd_err(("%s: SDIO Device not present\n", __func__)); | ||
| 241 | return NULL; | ||
| 242 | } | ||
| 243 | |||
| 244 | sd = kzalloc(sizeof(struct sdioh_info), GFP_ATOMIC); | ||
| 245 | if (sd == NULL) { | ||
| 246 | sd_err(("sdioh_attach: out of memory\n")); | ||
| 247 | return NULL; | ||
| 248 | } | ||
| 249 | if (brcmf_sdioh_osinit(sd) != 0) { | ||
| 250 | sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__)); | ||
| 251 | kfree(sd); | ||
| 252 | return NULL; | ||
| 253 | } | ||
| 254 | |||
| 255 | sd->num_funcs = 2; | ||
| 256 | sd->use_client_ints = true; | ||
| 257 | sd->client_block_size[0] = 64; | ||
| 258 | |||
| 259 | gInstance->sd = sd; | ||
| 260 | |||
| 261 | /* Claim host controller */ | ||
| 262 | sdio_claim_host(gInstance->func[1]); | ||
| 263 | |||
| 264 | sd->client_block_size[1] = 64; | ||
| 265 | err_ret = sdio_set_block_size(gInstance->func[1], 64); | ||
| 266 | if (err_ret) | ||
| 267 | sd_err(("brcmf_sdioh_attach: Failed to set F1 blocksize\n")); | ||
| 268 | |||
| 269 | /* Release host controller F1 */ | ||
| 270 | sdio_release_host(gInstance->func[1]); | ||
| 271 | |||
| 272 | if (gInstance->func[2]) { | ||
| 273 | /* Claim host controller F2 */ | ||
| 274 | sdio_claim_host(gInstance->func[2]); | ||
| 275 | |||
| 276 | sd->client_block_size[2] = sd_f2_blocksize; | ||
| 277 | err_ret = | ||
| 278 | sdio_set_block_size(gInstance->func[2], sd_f2_blocksize); | ||
| 279 | if (err_ret) | ||
| 280 | sd_err(("brcmf_sdioh_attach: Failed to set F2 blocksize" | ||
| 281 | " to %d\n", sd_f2_blocksize)); | ||
| 282 | |||
| 283 | /* Release host controller F2 */ | ||
| 284 | sdio_release_host(gInstance->func[2]); | ||
| 285 | } | ||
| 286 | |||
| 287 | brcmf_sdioh_enablefuncs(sd); | ||
| 288 | |||
| 289 | sd_trace(("%s: Done\n", __func__)); | ||
| 290 | return sd; | ||
| 291 | } | ||
| 292 | |||
| 293 | extern int brcmf_sdioh_detach(struct sdioh_info *sd) | ||
| 294 | { | ||
| 295 | sd_trace(("%s\n", __func__)); | ||
| 296 | |||
| 297 | if (sd) { | ||
| 298 | |||
| 299 | /* Disable Function 2 */ | ||
| 300 | sdio_claim_host(gInstance->func[2]); | ||
| 301 | sdio_disable_func(gInstance->func[2]); | ||
| 302 | sdio_release_host(gInstance->func[2]); | ||
| 303 | |||
| 304 | /* Disable Function 1 */ | ||
| 305 | sdio_claim_host(gInstance->func[1]); | ||
| 306 | sdio_disable_func(gInstance->func[1]); | ||
| 307 | sdio_release_host(gInstance->func[1]); | ||
| 308 | |||
| 309 | /* deregister irq */ | ||
| 310 | brcmf_sdioh_osfree(sd); | ||
| 311 | |||
| 312 | kfree(sd); | ||
| 313 | } | ||
| 314 | return 0; | ||
| 315 | } | ||
| 316 | |||
| 317 | /* Configure callback to client when we receive client interrupt */ | ||
| 318 | extern int | ||
| 319 | brcmf_sdioh_interrupt_register(struct sdioh_info *sd, void (*fn)(void *), | ||
| 320 | void *argh) | ||
| 321 | { | ||
| 322 | sd_trace(("%s: Entering\n", __func__)); | ||
| 323 | if (fn == NULL) { | ||
| 324 | sd_err(("%s: interrupt handler is NULL, not registering\n", | ||
| 325 | __func__)); | ||
| 326 | return -EINVAL; | ||
| 327 | } | ||
| 328 | |||
| 329 | sd->intr_handler = fn; | ||
| 330 | sd->intr_handler_arg = argh; | ||
| 331 | sd->intr_handler_valid = true; | ||
| 332 | |||
| 333 | /* register and unmask irq */ | ||
| 334 | if (gInstance->func[2]) { | ||
| 335 | sdio_claim_host(gInstance->func[2]); | ||
| 336 | sdio_claim_irq(gInstance->func[2], brcmf_sdioh_irqhandler_f2); | ||
| 337 | sdio_release_host(gInstance->func[2]); | ||
| 338 | } | ||
| 339 | |||
| 340 | if (gInstance->func[1]) { | ||
| 341 | sdio_claim_host(gInstance->func[1]); | ||
| 342 | sdio_claim_irq(gInstance->func[1], brcmf_sdioh_irqhandler); | ||
| 343 | sdio_release_host(gInstance->func[1]); | ||
| 344 | } | ||
| 345 | |||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | |||
| 349 | extern int brcmf_sdioh_interrupt_deregister(struct sdioh_info *sd) | ||
| 350 | { | ||
| 351 | sd_trace(("%s: Entering\n", __func__)); | ||
| 352 | |||
| 353 | if (gInstance->func[1]) { | ||
| 354 | /* register and unmask irq */ | ||
| 355 | sdio_claim_host(gInstance->func[1]); | ||
| 356 | sdio_release_irq(gInstance->func[1]); | ||
| 357 | sdio_release_host(gInstance->func[1]); | ||
| 358 | } | ||
| 359 | |||
| 360 | if (gInstance->func[2]) { | ||
| 361 | /* Claim host controller F2 */ | ||
| 362 | sdio_claim_host(gInstance->func[2]); | ||
| 363 | sdio_release_irq(gInstance->func[2]); | ||
| 364 | /* Release host controller F2 */ | ||
| 365 | sdio_release_host(gInstance->func[2]); | ||
| 366 | } | ||
| 367 | |||
| 368 | sd->intr_handler_valid = false; | ||
| 369 | sd->intr_handler = NULL; | ||
| 370 | sd->intr_handler_arg = NULL; | ||
| 371 | |||
| 372 | return 0; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* IOVar table */ | ||
| 376 | enum { | ||
| 377 | IOV_MSGLEVEL = 1, | ||
| 378 | IOV_BLOCKSIZE, | ||
| 379 | IOV_USEINTS, | ||
| 380 | IOV_NUMINTS, | ||
| 381 | IOV_DEVREG, | ||
| 382 | IOV_HCIREGS, | ||
| 383 | IOV_RXCHAIN | ||
| 384 | }; | ||
| 385 | |||
| 386 | const struct brcmu_iovar sdioh_iovars[] = { | ||
| 387 | {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0}, | ||
| 388 | {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0},/* ((fn << 16) | | ||
| 389 | size) */ | ||
| 390 | {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0}, | ||
| 391 | {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0}, | ||
| 392 | {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)} | ||
| 393 | , | ||
| 394 | {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0} | ||
| 395 | , | ||
| 396 | {NULL, 0, 0, 0, 0} | ||
| 397 | }; | ||
| 398 | |||
| 399 | int | ||
| 400 | brcmf_sdioh_iovar_op(struct sdioh_info *si, const char *name, | ||
| 401 | void *params, int plen, void *arg, int len, bool set) | ||
| 402 | { | ||
| 403 | const struct brcmu_iovar *vi = NULL; | ||
| 404 | int bcmerror = 0; | ||
| 405 | int val_size; | ||
| 406 | s32 int_val = 0; | ||
| 407 | bool bool_val; | ||
| 408 | u32 actionid; | ||
| 409 | |||
| 410 | if (name == NULL || len <= 0) | ||
| 411 | return -EINVAL; | ||
| 412 | |||
| 413 | /* Set does not take qualifiers */ | ||
| 414 | if (set && (params || plen)) | ||
| 415 | return -EINVAL; | ||
| 416 | |||
| 417 | /* Get must have return space;*/ | ||
| 418 | if (!set && !(arg && len)) | ||
| 419 | return -EINVAL; | ||
| 420 | |||
| 421 | sd_trace(("%s: Enter (%s %s)\n", __func__, (set ? "set" : "get"), | ||
| 422 | name)); | ||
| 423 | |||
| 424 | vi = brcmu_iovar_lookup(sdioh_iovars, name); | ||
| 425 | if (vi == NULL) { | ||
| 426 | bcmerror = -ENOTSUPP; | ||
| 427 | goto exit; | ||
| 428 | } | ||
| 429 | |||
| 430 | bcmerror = brcmu_iovar_lencheck(vi, arg, len, set); | ||
| 431 | if (bcmerror != 0) | ||
| 432 | goto exit; | ||
| 433 | |||
| 434 | /* Set up params so get and set can share the convenience variables */ | ||
| 435 | if (params == NULL) { | ||
| 436 | params = arg; | ||
| 437 | plen = len; | ||
| 438 | } | ||
| 439 | |||
| 440 | if (vi->type == IOVT_VOID) | ||
| 441 | val_size = 0; | ||
| 442 | else if (vi->type == IOVT_BUFFER) | ||
| 443 | val_size = len; | ||
| 444 | else | ||
| 445 | val_size = sizeof(int); | ||
| 446 | |||
| 447 | if (plen >= (int)sizeof(int_val)) | ||
| 448 | memcpy(&int_val, params, sizeof(int_val)); | ||
| 449 | |||
| 450 | bool_val = (int_val != 0) ? true : false; | ||
| 451 | |||
| 452 | actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); | ||
| 453 | switch (actionid) { | ||
| 454 | case IOV_GVAL(IOV_MSGLEVEL): | ||
| 455 | int_val = (s32) sd_msglevel; | ||
| 456 | memcpy(arg, &int_val, val_size); | ||
| 457 | break; | ||
| 458 | |||
| 459 | case IOV_SVAL(IOV_MSGLEVEL): | ||
| 460 | sd_msglevel = int_val; | ||
| 461 | break; | ||
| 462 | |||
| 463 | case IOV_GVAL(IOV_BLOCKSIZE): | ||
| 464 | if ((u32) int_val > si->num_funcs) { | ||
| 465 | bcmerror = -EINVAL; | ||
| 466 | break; | ||
| 467 | } | ||
| 468 | int_val = (s32) si->client_block_size[int_val]; | ||
| 469 | memcpy(arg, &int_val, val_size); | ||
| 470 | break; | ||
| 471 | |||
| 472 | case IOV_SVAL(IOV_BLOCKSIZE): | ||
| 473 | { | ||
| 474 | uint func = ((u32) int_val >> 16); | ||
| 475 | uint blksize = (u16) int_val; | ||
| 476 | uint maxsize; | ||
| 477 | |||
| 478 | if (func > si->num_funcs) { | ||
| 479 | bcmerror = -EINVAL; | ||
| 480 | break; | ||
| 481 | } | ||
| 482 | |||
| 483 | switch (func) { | ||
| 484 | case 0: | ||
| 485 | maxsize = 32; | ||
| 486 | break; | ||
| 487 | case 1: | ||
| 488 | maxsize = BLOCK_SIZE_4318; | ||
| 489 | break; | ||
| 490 | case 2: | ||
| 491 | maxsize = BLOCK_SIZE_4328; | ||
| 492 | break; | ||
| 493 | default: | ||
| 494 | maxsize = 0; | ||
| 495 | } | ||
| 496 | if (blksize > maxsize) { | ||
| 497 | bcmerror = -EINVAL; | ||
| 498 | break; | ||
| 499 | } | ||
| 500 | if (!blksize) | ||
| 501 | blksize = maxsize; | ||
| 502 | |||
| 503 | /* Now set it */ | ||
| 504 | si->client_block_size[func] = blksize; | ||
| 505 | |||
| 506 | break; | ||
| 507 | } | ||
| 508 | |||
| 509 | case IOV_GVAL(IOV_RXCHAIN): | ||
| 510 | int_val = false; | ||
| 511 | memcpy(arg, &int_val, val_size); | ||
| 512 | break; | ||
| 513 | |||
| 514 | case IOV_GVAL(IOV_USEINTS): | ||
| 515 | int_val = (s32) si->use_client_ints; | ||
| 516 | memcpy(arg, &int_val, val_size); | ||
| 517 | break; | ||
| 518 | |||
| 519 | case IOV_SVAL(IOV_USEINTS): | ||
| 520 | si->use_client_ints = (bool) int_val; | ||
| 521 | if (si->use_client_ints) | ||
| 522 | si->intmask |= CLIENT_INTR; | ||
| 523 | else | ||
| 524 | si->intmask &= ~CLIENT_INTR; | ||
| 525 | |||
| 526 | break; | ||
| 527 | |||
| 528 | case IOV_GVAL(IOV_NUMINTS): | ||
| 529 | int_val = (s32) si->intrcount; | ||
| 530 | memcpy(arg, &int_val, val_size); | ||
| 531 | break; | ||
| 532 | |||
| 533 | case IOV_GVAL(IOV_DEVREG): | ||
| 534 | { | ||
| 535 | struct brcmf_sdreg *sd_ptr = | ||
| 536 | (struct brcmf_sdreg *) params; | ||
| 537 | u8 data = 0; | ||
| 538 | |||
| 539 | if (brcmf_sdioh_cfg_read | ||
| 540 | (si, sd_ptr->func, sd_ptr->offset, &data)) { | ||
| 541 | bcmerror = -EIO; | ||
| 542 | break; | ||
| 543 | } | ||
| 544 | |||
| 545 | int_val = (int)data; | ||
| 546 | memcpy(arg, &int_val, sizeof(int_val)); | ||
| 547 | break; | ||
| 548 | } | ||
| 549 | |||
| 550 | case IOV_SVAL(IOV_DEVREG): | ||
| 551 | { | ||
| 552 | struct brcmf_sdreg *sd_ptr = | ||
| 553 | (struct brcmf_sdreg *) params; | ||
| 554 | u8 data = (u8) sd_ptr->value; | ||
| 555 | |||
| 556 | if (brcmf_sdioh_cfg_write | ||
| 557 | (si, sd_ptr->func, sd_ptr->offset, &data)) { | ||
| 558 | bcmerror = -EIO; | ||
| 559 | break; | ||
| 560 | } | ||
| 561 | break; | ||
| 562 | } | ||
| 563 | |||
| 564 | default: | ||
| 565 | bcmerror = -ENOTSUPP; | ||
| 566 | break; | ||
| 567 | } | ||
| 568 | exit: | ||
| 569 | |||
| 570 | return bcmerror; | ||
| 571 | } | ||
| 572 | |||
| 573 | extern int | ||
| 574 | brcmf_sdioh_cfg_read(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data) | ||
| 575 | { | ||
| 576 | int status; | ||
| 577 | /* No lock needed since brcmf_sdioh_request_byte does locking */ | ||
| 578 | status = brcmf_sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); | ||
| 579 | return status; | ||
| 580 | } | ||
| 581 | |||
| 582 | extern int | ||
| 583 | brcmf_sdioh_cfg_write(struct sdioh_info *sd, uint fnc_num, u32 addr, u8 *data) | ||
| 584 | { | ||
| 585 | /* No lock needed since brcmf_sdioh_request_byte does locking */ | ||
| 586 | int status; | ||
| 587 | status = brcmf_sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); | ||
| 588 | return status; | ||
| 589 | } | ||
| 590 | |||
| 591 | static int brcmf_sdioh_get_cisaddr(struct sdioh_info *sd, u32 regaddr) | ||
| 592 | { | ||
| 593 | /* read 24 bits and return valid 17 bit addr */ | ||
| 594 | int i; | ||
| 595 | u32 scratch, regdata; | ||
| 596 | u8 *ptr = (u8 *)&scratch; | ||
| 597 | for (i = 0; i < 3; i++) { | ||
| 598 | if ((brcmf_sdioh_card_regread(sd, 0, regaddr, 1, ®data)) != | ||
| 599 | SUCCESS) | ||
| 600 | sd_err(("%s: Can't read!\n", __func__)); | ||
| 601 | |||
| 602 | *ptr++ = (u8) regdata; | ||
| 603 | regaddr++; | ||
| 604 | } | ||
| 605 | |||
| 606 | /* Only the lower 17-bits are valid */ | ||
| 607 | scratch = le32_to_cpu(scratch); | ||
| 608 | scratch &= 0x0001FFFF; | ||
| 609 | return scratch; | ||
| 610 | } | ||
| 611 | |||
| 612 | extern int | ||
| 613 | brcmf_sdioh_cis_read(struct sdioh_info *sd, uint func, u8 *cisd, u32 length) | ||
| 614 | { | ||
| 615 | u32 count; | ||
| 616 | int offset; | ||
| 617 | u32 foo; | ||
| 618 | u8 *cis = cisd; | ||
| 619 | |||
| 620 | sd_trace(("%s: Func = %d\n", __func__, func)); | ||
| 621 | |||
| 622 | if (!sd->func_cis_ptr[func]) { | ||
| 623 | memset(cis, 0, length); | ||
| 624 | sd_err(("%s: no func_cis_ptr[%d]\n", __func__, func)); | ||
| 625 | return -ENOTSUPP; | ||
| 626 | } | ||
| 627 | |||
| 628 | sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __func__, func, | ||
| 629 | sd->func_cis_ptr[func])); | ||
| 630 | |||
| 631 | for (count = 0; count < length; count++) { | ||
| 632 | offset = sd->func_cis_ptr[func] + count; | ||
| 633 | if (brcmf_sdioh_card_regread(sd, 0, offset, 1, &foo) < 0) { | ||
| 634 | sd_err(("%s: regread failed: Can't read CIS\n", | ||
| 635 | __func__)); | ||
| 636 | return -EIO; | ||
| 637 | } | ||
| 638 | |||
| 639 | *cis = (u8) (foo & 0xff); | ||
| 640 | cis++; | ||
| 641 | } | ||
| 642 | |||
| 643 | return 0; | ||
| 644 | } | ||
| 645 | |||
| 646 | extern int | ||
| 647 | brcmf_sdioh_request_byte(struct sdioh_info *sd, uint rw, uint func, | ||
| 648 | uint regaddr, u8 *byte) | ||
| 649 | { | ||
| 650 | int err_ret; | ||
| 651 | |||
| 652 | sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __func__, rw, func, | ||
| 653 | regaddr)); | ||
| 654 | |||
| 655 | BRCMF_PM_RESUME_WAIT(sdioh_request_byte_wait); | ||
| 656 | BRCMF_PM_RESUME_RETURN_ERROR(-EIO); | ||
| 657 | if (rw) { /* CMD52 Write */ | ||
| 658 | if (func == 0) { | ||
| 659 | /* Can only directly write to some F0 registers. | ||
| 660 | * Handle F2 enable | ||
| 661 | * as a special case. | ||
| 662 | */ | ||
| 663 | if (regaddr == SDIO_CCCR_IOEx) { | ||
| 664 | if (gInstance->func[2]) { | ||
| 665 | sdio_claim_host(gInstance->func[2]); | ||
| 666 | if (*byte & SDIO_FUNC_ENABLE_2) { | ||
| 667 | /* Enable Function 2 */ | ||
| 668 | err_ret = | ||
| 669 | sdio_enable_func | ||
| 670 | (gInstance->func[2]); | ||
| 671 | if (err_ret) | ||
| 672 | sd_err(("request_byte: " | ||
| 673 | "enable F2 " | ||
| 674 | "failed:%d\n", | ||
| 675 | err_ret)); | ||
| 676 | } else { | ||
| 677 | /* Disable Function 2 */ | ||
| 678 | err_ret = | ||
| 679 | sdio_disable_func | ||
| 680 | (gInstance->func[2]); | ||
| 681 | if (err_ret) | ||
| 682 | sd_err(("request_byte: " | ||
| 683 | "Disab F2 " | ||
| 684 | "failed:%d\n", | ||
| 685 | err_ret)); | ||
| 686 | } | ||
| 687 | sdio_release_host(gInstance->func[2]); | ||
| 688 | } | ||
| 689 | } | ||
| 690 | /* to allow abort command through F1 */ | ||
| 691 | else if (regaddr == SDIO_CCCR_ABORT) { | ||
| 692 | sdio_claim_host(gInstance->func[func]); | ||
| 693 | /* | ||
| 694 | * this sdio_f0_writeb() can be replaced | ||
| 695 | * with another api | ||
| 696 | * depending upon MMC driver change. | ||
| 697 | * As of this time, this is temporaray one | ||
| 698 | */ | ||
| 699 | sdio_writeb(gInstance->func[func], *byte, | ||
| 700 | regaddr, &err_ret); | ||
| 701 | sdio_release_host(gInstance->func[func]); | ||
| 702 | } else if (regaddr < 0xF0) { | ||
| 703 | sd_err(("brcmf: F0 Wr:0x%02x: write " | ||
| 704 | "disallowed\n", regaddr)); | ||
| 705 | } else { | ||
| 706 | /* Claim host controller, perform F0 write, | ||
| 707 | and release */ | ||
| 708 | sdio_claim_host(gInstance->func[func]); | ||
| 709 | sdio_f0_writeb(gInstance->func[func], *byte, | ||
| 710 | regaddr, &err_ret); | ||
| 711 | sdio_release_host(gInstance->func[func]); | ||
| 712 | } | ||
| 713 | } else { | ||
| 714 | /* Claim host controller, perform Fn write, | ||
| 715 | and release */ | ||
| 716 | sdio_claim_host(gInstance->func[func]); | ||
| 717 | sdio_writeb(gInstance->func[func], *byte, regaddr, | ||
| 718 | &err_ret); | ||
| 719 | sdio_release_host(gInstance->func[func]); | ||
| 720 | } | ||
| 721 | } else { /* CMD52 Read */ | ||
| 722 | /* Claim host controller, perform Fn read, and release */ | ||
| 723 | sdio_claim_host(gInstance->func[func]); | ||
| 724 | |||
| 725 | if (func == 0) { | ||
| 726 | *byte = | ||
| 727 | sdio_f0_readb(gInstance->func[func], regaddr, | ||
| 728 | &err_ret); | ||
| 729 | } else { | ||
| 730 | *byte = | ||
| 731 | sdio_readb(gInstance->func[func], regaddr, | ||
| 732 | &err_ret); | ||
| 733 | } | ||
| 734 | |||
| 735 | sdio_release_host(gInstance->func[func]); | ||
| 736 | } | ||
| 737 | |||
| 738 | if (err_ret) | ||
| 739 | sd_err(("brcmf: Failed to %s byte F%d:@0x%05x=%02x, " | ||
| 740 | "Err: %d\n", rw ? "Write" : "Read", func, regaddr, | ||
| 741 | *byte, err_ret)); | ||
| 742 | |||
| 743 | return err_ret; | ||
| 744 | } | ||
| 745 | |||
| 746 | extern int | ||
| 747 | brcmf_sdioh_request_word(struct sdioh_info *sd, uint cmd_type, uint rw, | ||
| 748 | uint func, uint addr, u32 *word, uint nbytes) | ||
| 749 | { | ||
| 750 | int err_ret = -EIO; | ||
| 751 | |||
| 752 | if (func == 0) { | ||
| 753 | sd_err(("%s: Only CMD52 allowed to F0.\n", __func__)); | ||
| 754 | return -EINVAL; | ||
| 755 | } | ||
| 756 | |||
| 757 | sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", | ||
| 758 | __func__, cmd_type, rw, func, addr, nbytes)); | ||
| 759 | |||
| 760 | BRCMF_PM_RESUME_WAIT(sdioh_request_word_wait); | ||
| 761 | BRCMF_PM_RESUME_RETURN_ERROR(-EIO); | ||
| 762 | /* Claim host controller */ | ||
| 763 | sdio_claim_host(gInstance->func[func]); | ||
| 764 | |||
| 765 | if (rw) { /* CMD52 Write */ | ||
| 766 | if (nbytes == 4) { | ||
| 767 | sdio_writel(gInstance->func[func], *word, addr, | ||
| 768 | &err_ret); | ||
| 769 | } else if (nbytes == 2) { | ||
| 770 | sdio_writew(gInstance->func[func], (*word & 0xFFFF), | ||
| 771 | addr, &err_ret); | ||
| 772 | } else { | ||
| 773 | sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes)); | ||
| 774 | } | ||
| 775 | } else { /* CMD52 Read */ | ||
| 776 | if (nbytes == 4) { | ||
| 777 | *word = | ||
| 778 | sdio_readl(gInstance->func[func], addr, &err_ret); | ||
| 779 | } else if (nbytes == 2) { | ||
| 780 | *word = | ||
| 781 | sdio_readw(gInstance->func[func], addr, | ||
| 782 | &err_ret) & 0xFFFF; | ||
| 783 | } else { | ||
| 784 | sd_err(("%s: Invalid nbytes: %d\n", __func__, nbytes)); | ||
| 785 | } | ||
| 786 | } | ||
| 787 | |||
| 788 | /* Release host controller */ | ||
| 789 | sdio_release_host(gInstance->func[func]); | ||
| 790 | |||
| 791 | if (err_ret) { | ||
| 792 | sd_err(("brcmf: Failed to %s word, Err: 0x%08x\n", | ||
| 793 | rw ? "Write" : "Read", err_ret)); | ||
| 794 | } | ||
| 795 | |||
| 796 | return err_ret; | ||
| 797 | } | ||
| 798 | |||
| 799 | static int | ||
| 800 | brcmf_sdioh_request_packet(struct sdioh_info *sd, uint fix_inc, uint write, | ||
| 801 | uint func, uint addr, struct sk_buff *pkt) | ||
| 802 | { | ||
| 803 | bool fifo = (fix_inc == SDIOH_DATA_FIX); | ||
| 804 | u32 SGCount = 0; | ||
| 805 | int err_ret = 0; | ||
| 806 | |||
| 807 | struct sk_buff *pnext; | ||
| 808 | |||
| 809 | sd_trace(("%s: Enter\n", __func__)); | ||
| 810 | |||
| 811 | BRCMF_PM_RESUME_WAIT(sdioh_request_packet_wait); | ||
| 812 | BRCMF_PM_RESUME_RETURN_ERROR(-EIO); | ||
| 813 | |||
| 814 | /* Claim host controller */ | ||
| 815 | sdio_claim_host(gInstance->func[func]); | ||
| 816 | for (pnext = pkt; pnext; pnext = pnext->next) { | ||
| 817 | uint pkt_len = pnext->len; | ||
| 818 | pkt_len += 3; | ||
| 819 | pkt_len &= 0xFFFFFFFC; | ||
| 820 | |||
| 821 | if ((write) && (!fifo)) { | ||
| 822 | err_ret = sdio_memcpy_toio(gInstance->func[func], addr, | ||
| 823 | ((u8 *) (pnext->data)), | ||
| 824 | pkt_len); | ||
| 825 | } else if (write) { | ||
| 826 | err_ret = sdio_memcpy_toio(gInstance->func[func], addr, | ||
| 827 | ((u8 *) (pnext->data)), | ||
| 828 | pkt_len); | ||
| 829 | } else if (fifo) { | ||
| 830 | err_ret = sdio_readsb(gInstance->func[func], | ||
| 831 | ((u8 *) (pnext->data)), | ||
| 832 | addr, pkt_len); | ||
| 833 | } else { | ||
| 834 | err_ret = sdio_memcpy_fromio(gInstance->func[func], | ||
| 835 | ((u8 *) (pnext->data)), | ||
| 836 | addr, pkt_len); | ||
| 837 | } | ||
| 838 | |||
| 839 | if (err_ret) { | ||
| 840 | sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d," | ||
| 841 | "ERR=0x%08x\n", __func__, | ||
| 842 | (write) ? "TX" : "RX", | ||
| 843 | pnext, SGCount, addr, pkt_len, err_ret)); | ||
| 844 | } else { | ||
| 845 | sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", | ||
| 846 | __func__, | ||
| 847 | (write) ? "TX" : "RX", | ||
| 848 | pnext, SGCount, addr, pkt_len)); | ||
| 849 | } | ||
| 850 | |||
| 851 | if (!fifo) | ||
| 852 | addr += pkt_len; | ||
| 853 | SGCount++; | ||
| 854 | |||
| 855 | } | ||
| 856 | |||
| 857 | /* Release host controller */ | ||
| 858 | sdio_release_host(gInstance->func[func]); | ||
| 859 | |||
| 860 | sd_trace(("%s: Exit\n", __func__)); | ||
| 861 | return err_ret; | ||
| 862 | } | ||
| 863 | |||
| 864 | /* | ||
| 865 | * This function takes a buffer or packet, and fixes everything up | ||
| 866 | * so that in the end, a DMA-able packet is created. | ||
| 867 | * | ||
| 868 | * A buffer does not have an associated packet pointer, | ||
| 869 | * and may or may not be aligned. | ||
| 870 | * A packet may consist of a single packet, or a packet chain. | ||
| 871 | * If it is a packet chain, then all the packets in the chain | ||
| 872 | * must be properly aligned. | ||
| 873 | * | ||
| 874 | * If the packet data is not aligned, then there may only be | ||
| 875 | * one packet, and in this case, it is copied to a new | ||
| 876 | * aligned packet. | ||
| 877 | * | ||
| 878 | */ | ||
| 879 | extern int | ||
| 880 | brcmf_sdioh_request_buffer(struct sdioh_info *sd, uint pio_dma, uint fix_inc, | ||
| 881 | uint write, uint func, uint addr, uint reg_width, | ||
| 882 | uint buflen_u, u8 *buffer, struct sk_buff *pkt) | ||
| 883 | { | ||
| 884 | int Status; | ||
| 885 | struct sk_buff *mypkt = NULL; | ||
| 886 | |||
| 887 | sd_trace(("%s: Enter\n", __func__)); | ||
| 888 | |||
| 889 | BRCMF_PM_RESUME_WAIT(sdioh_request_buffer_wait); | ||
| 890 | BRCMF_PM_RESUME_RETURN_ERROR(-EIO); | ||
| 891 | /* Case 1: we don't have a packet. */ | ||
| 892 | if (pkt == NULL) { | ||
| 893 | sd_data(("%s: Creating new %s Packet, len=%d\n", | ||
| 894 | __func__, write ? "TX" : "RX", buflen_u)); | ||
| 895 | mypkt = brcmu_pkt_buf_get_skb(buflen_u); | ||
| 896 | if (!mypkt) { | ||
| 897 | sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n", | ||
| 898 | __func__, buflen_u)); | ||
| 899 | return -EIO; | ||
| 900 | } | ||
| 901 | |||
| 902 | /* For a write, copy the buffer data into the packet. */ | ||
| 903 | if (write) | ||
| 904 | memcpy(mypkt->data, buffer, buflen_u); | ||
| 905 | |||
| 906 | Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func, | ||
| 907 | addr, mypkt); | ||
| 908 | |||
| 909 | /* For a read, copy the packet data back to the buffer. */ | ||
| 910 | if (!write) | ||
| 911 | memcpy(buffer, mypkt->data, buflen_u); | ||
| 912 | |||
| 913 | brcmu_pkt_buf_free_skb(mypkt); | ||
| 914 | } else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) { | ||
| 915 | /* | ||
| 916 | * Case 2: We have a packet, but it is unaligned. | ||
| 917 | * In this case, we cannot have a chain (pkt->next == NULL) | ||
| 918 | */ | ||
| 919 | sd_data(("%s: Creating aligned %s Packet, len=%d\n", | ||
| 920 | __func__, write ? "TX" : "RX", pkt->len)); | ||
| 921 | mypkt = brcmu_pkt_buf_get_skb(pkt->len); | ||
| 922 | if (!mypkt) { | ||
| 923 | sd_err(("%s: brcmu_pkt_buf_get_skb failed: len %d\n", | ||
| 924 | __func__, pkt->len)); | ||
| 925 | return -EIO; | ||
| 926 | } | ||
| 927 | |||
| 928 | /* For a write, copy the buffer data into the packet. */ | ||
| 929 | if (write) | ||
| 930 | memcpy(mypkt->data, pkt->data, pkt->len); | ||
| 931 | |||
| 932 | Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func, | ||
| 933 | addr, mypkt); | ||
| 934 | |||
| 935 | /* For a read, copy the packet data back to the buffer. */ | ||
| 936 | if (!write) | ||
| 937 | memcpy(pkt->data, mypkt->data, mypkt->len); | ||
| 938 | |||
| 939 | brcmu_pkt_buf_free_skb(mypkt); | ||
| 940 | } else { /* case 3: We have a packet and | ||
| 941 | it is aligned. */ | ||
| 942 | sd_data(("%s: Aligned %s Packet, direct DMA\n", | ||
| 943 | __func__, write ? "Tx" : "Rx")); | ||
| 944 | Status = brcmf_sdioh_request_packet(sd, fix_inc, write, func, | ||
| 945 | addr, pkt); | ||
| 946 | } | ||
| 947 | |||
| 948 | return Status; | ||
| 949 | } | ||
| 950 | |||
| 951 | /* this function performs "abort" for both of host & device */ | ||
| 952 | extern int brcmf_sdioh_abort(struct sdioh_info *sd, uint func) | ||
| 953 | { | ||
| 954 | char t_func = (char)func; | ||
| 955 | sd_trace(("%s: Enter\n", __func__)); | ||
| 956 | |||
| 957 | /* issue abort cmd52 command through F0 */ | ||
| 958 | brcmf_sdioh_request_byte(sd, SDIOH_WRITE, SDIO_FUNC_0, SDIO_CCCR_ABORT, | ||
| 959 | &t_func); | ||
| 960 | |||
| 961 | sd_trace(("%s: Exit\n", __func__)); | ||
| 962 | return 0; | ||
| 963 | } | ||
| 964 | |||
| 965 | /* Disable device interrupt */ | ||
| 966 | void brcmf_sdioh_dev_intr_off(struct sdioh_info *sd) | ||
| 967 | { | ||
| 968 | sd_trace(("%s: %d\n", __func__, sd->use_client_ints)); | ||
| 969 | sd->intmask &= ~CLIENT_INTR; | ||
| 970 | } | ||
| 971 | |||
| 972 | /* Enable device interrupt */ | ||
| 973 | void brcmf_sdioh_dev_intr_on(struct sdioh_info *sd) | ||
| 974 | { | ||
| 975 | sd_trace(("%s: %d\n", __func__, sd->use_client_ints)); | ||
| 976 | sd->intmask |= CLIENT_INTR; | ||
| 977 | } | ||
| 978 | |||
| 979 | /* Read client card reg */ | ||
| 980 | int | ||
| 981 | brcmf_sdioh_card_regread(struct sdioh_info *sd, int func, u32 regaddr, | ||
| 982 | int regsize, u32 *data) | ||
| 983 | { | ||
| 984 | |||
| 985 | if ((func == 0) || (regsize == 1)) { | ||
| 986 | u8 temp = 0; | ||
| 987 | |||
| 988 | brcmf_sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp); | ||
| 989 | *data = temp; | ||
| 990 | *data &= 0xff; | ||
| 991 | sd_data(("%s: byte read data=0x%02x\n", __func__, *data)); | ||
| 992 | } else { | ||
| 993 | brcmf_sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, | ||
| 994 | regsize); | ||
| 995 | if (regsize == 2) | ||
| 996 | *data &= 0xffff; | ||
| 997 | |||
| 998 | sd_data(("%s: word read data=0x%08x\n", __func__, *data)); | ||
| 999 | } | ||
| 1000 | |||
| 1001 | return SUCCESS; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | static void brcmf_sdioh_irqhandler(struct sdio_func *func) | ||
| 1005 | { | ||
| 1006 | struct sdioh_info *sd; | ||
| 1007 | |||
| 1008 | sd_trace(("brcmf: ***IRQHandler\n")); | ||
| 1009 | sd = gInstance->sd; | ||
| 1010 | |||
| 1011 | sdio_release_host(gInstance->func[0]); | ||
| 1012 | |||
| 1013 | if (sd->use_client_ints) { | ||
| 1014 | sd->intrcount++; | ||
| 1015 | (sd->intr_handler) (sd->intr_handler_arg); | ||
| 1016 | } else { | ||
| 1017 | sd_err(("brcmf: ***IRQHandler\n")); | ||
| 1018 | |||
| 1019 | sd_err(("%s: Not ready for intr: enabled %d, handler %p\n", | ||
| 1020 | __func__, sd->client_intr_enabled, sd->intr_handler)); | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | sdio_claim_host(gInstance->func[0]); | ||
| 1024 | } | ||
| 1025 | |||
| 1026 | /* interrupt handler for F2 (dummy handler) */ | ||
| 1027 | static void brcmf_sdioh_irqhandler_f2(struct sdio_func *func) | ||
| 1028 | { | ||
| 1029 | struct sdioh_info *sd; | ||
| 1030 | |||
| 1031 | sd_trace(("brcmf: ***IRQHandlerF2\n")); | ||
| 1032 | |||
| 1033 | sd = gInstance->sd; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | static int brcmf_ops_sdio_probe(struct sdio_func *func, | ||
| 1037 | const struct sdio_device_id *id) | ||
| 1038 | { | ||
| 1039 | int ret = 0; | ||
| 1040 | static struct sdio_func sdio_func_0; | ||
| 1041 | sd_trace(("sdio_probe: %s Enter\n", __func__)); | ||
| 1042 | sd_trace(("sdio_probe: func->class=%x\n", func->class)); | ||
| 1043 | sd_trace(("sdio_vendor: 0x%04x\n", func->vendor)); | ||
| 1044 | sd_trace(("sdio_device: 0x%04x\n", func->device)); | ||
| 1045 | sd_trace(("Function#: 0x%04x\n", func->num)); | ||
| 1046 | |||
| 1047 | if (func->num == 1) { | ||
| 1048 | sdio_func_0.num = 0; | ||
| 1049 | sdio_func_0.card = func->card; | ||
| 1050 | gInstance->func[0] = &sdio_func_0; | ||
| 1051 | if (func->device == 0x4) { /* 4318 */ | ||
| 1052 | gInstance->func[2] = NULL; | ||
| 1053 | sd_trace(("NIC found, calling brcmf_sdio_probe...\n")); | ||
| 1054 | ret = brcmf_sdio_probe(&sdmmc_dev); | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | gInstance->func[func->num] = func; | ||
| 1059 | |||
| 1060 | if (func->num == 2) { | ||
| 1061 | brcmf_cfg80211_sdio_func(func); | ||
| 1062 | sd_trace(("F2 found, calling brcmf_sdio_probe...\n")); | ||
| 1063 | ret = brcmf_sdio_probe(&sdmmc_dev); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | return ret; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | static void brcmf_ops_sdio_remove(struct sdio_func *func) | ||
| 1070 | { | ||
| 1071 | sd_trace(("%s Enter\n", __func__)); | ||
| 1072 | sd_info(("func->class=%x\n", func->class)); | ||
| 1073 | sd_info(("sdio_vendor: 0x%04x\n", func->vendor)); | ||
| 1074 | sd_info(("sdio_device: 0x%04x\n", func->device)); | ||
| 1075 | sd_info(("Function#: 0x%04x\n", func->num)); | ||
| 1076 | |||
| 1077 | if (func->num == 2) { | ||
| 1078 | sd_trace(("F2 found, calling brcmf_sdio_remove...\n")); | ||
| 1079 | brcmf_sdio_remove(&sdmmc_dev); | ||
| 1080 | } | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | |||
| 1084 | #ifdef CONFIG_PM | ||
| 1085 | static int brcmf_sdio_suspend(struct device *dev) | ||
| 1086 | { | ||
| 1087 | mmc_pm_flag_t sdio_flags; | ||
| 1088 | int ret = 0; | ||
| 1089 | |||
| 1090 | sd_trace(("%s\n", __func__)); | ||
| 1091 | |||
| 1092 | sdio_flags = sdio_get_host_pm_caps(gInstance->func[1]); | ||
| 1093 | if (!(sdio_flags & MMC_PM_KEEP_POWER)) { | ||
| 1094 | sd_err(("Host can't keep power while suspended\n")); | ||
| 1095 | return -EINVAL; | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | ret = sdio_set_host_pm_flags(gInstance->func[1], MMC_PM_KEEP_POWER); | ||
| 1099 | if (ret) { | ||
| 1100 | sd_err(("Failed to set pm_flags\n")); | ||
| 1101 | return ret; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | brcmf_sdio_wdtmr_enable(false); | ||
| 1105 | |||
| 1106 | return ret; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | static int brcmf_sdio_resume(struct device *dev) | ||
| 1110 | { | ||
| 1111 | brcmf_sdio_wdtmr_enable(true); | ||
| 1112 | return 0; | ||
| 1113 | } | ||
| 1114 | #endif /* CONFIG_PM */ | ||
| 1115 | |||
| 1116 | int brcmf_sdioh_osinit(struct sdioh_info *sd) | ||
| 1117 | { | ||
| 1118 | struct sdos_info *sdos; | ||
| 1119 | |||
| 1120 | sdos = kmalloc(sizeof(struct sdos_info), GFP_ATOMIC); | ||
| 1121 | sd->sdos_info = (void *)sdos; | ||
| 1122 | if (sdos == NULL) | ||
| 1123 | return -ENOMEM; | ||
| 1124 | |||
| 1125 | sdos->sd = sd; | ||
| 1126 | spin_lock_init(&sdos->lock); | ||
| 1127 | return 0; | ||
| 1128 | } | ||
| 1129 | |||
| 1130 | void brcmf_sdioh_osfree(struct sdioh_info *sd) | ||
| 1131 | { | ||
| 1132 | struct sdos_info *sdos; | ||
| 1133 | |||
| 1134 | sdos = (struct sdos_info *)sd->sdos_info; | ||
| 1135 | kfree(sdos); | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | /* Interrupt enable/disable */ | ||
| 1139 | int brcmf_sdioh_interrupt_set(struct sdioh_info *sd, bool enable) | ||
| 1140 | { | ||
| 1141 | unsigned long flags; | ||
| 1142 | struct sdos_info *sdos; | ||
| 1143 | |||
| 1144 | sd_trace(("%s: %s\n", __func__, enable ? "Enabling" : "Disabling")); | ||
| 1145 | |||
| 1146 | sdos = (struct sdos_info *)sd->sdos_info; | ||
| 1147 | |||
| 1148 | if (enable && !(sd->intr_handler && sd->intr_handler_arg)) { | ||
| 1149 | sd_err(("%s: no handler registered, will not enable\n", | ||
| 1150 | __func__)); | ||
| 1151 | return -EINVAL; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | /* Ensure atomicity for enable/disable calls */ | ||
| 1155 | spin_lock_irqsave(&sdos->lock, flags); | ||
| 1156 | |||
| 1157 | sd->client_intr_enabled = enable; | ||
| 1158 | if (enable) | ||
| 1159 | brcmf_sdioh_dev_intr_on(sd); | ||
| 1160 | else | ||
| 1161 | brcmf_sdioh_dev_intr_off(sd); | ||
| 1162 | |||
| 1163 | spin_unlock_irqrestore(&sdos->lock, flags); | ||
| 1164 | |||
| 1165 | return 0; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | /* | ||
| 1169 | * module init | ||
| 1170 | */ | ||
| 1171 | int brcmf_sdio_function_init(void) | ||
| 1172 | { | ||
| 1173 | int error = 0; | ||
| 1174 | sd_trace(("brcmf_sdio_function_init: %s Enter\n", __func__)); | ||
| 1175 | |||
| 1176 | gInstance = kzalloc(sizeof(struct brcmf_sdmmc_instance), GFP_KERNEL); | ||
| 1177 | if (!gInstance) | ||
| 1178 | return -ENOMEM; | ||
| 1179 | |||
| 1180 | memset(&sdmmc_dev, 0, sizeof(sdmmc_dev)); | ||
| 1181 | error = sdio_register_driver(&brcmf_sdmmc_driver); | ||
| 1182 | |||
| 1183 | return error; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | /* | ||
| 1187 | * module cleanup | ||
| 1188 | */ | ||
| 1189 | void brcmf_sdio_function_cleanup(void) | ||
| 1190 | { | ||
| 1191 | sd_trace(("%s Enter\n", __func__)); | ||
| 1192 | |||
| 1193 | sdio_unregister_driver(&brcmf_sdmmc_driver); | ||
| 1194 | |||
| 1195 | kfree(gInstance); | ||
| 1196 | } | ||
| @@ -1,904 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | /**************** | ||
| 18 | * Common types * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _BRCMF_H_ | ||
| 22 | #define _BRCMF_H_ | ||
| 23 | |||
| 24 | #define BRCMF_VERSION_STR "4.218.248.5" | ||
| 25 | |||
| 26 | #define BRCMF_C_IOCTL_SMLEN 256 /* "small" ioctl buffer required */ | ||
| 27 | #define BRCMF_C_IOCTL_MEDLEN 1536 /* "med" ioctl buffer required */ | ||
| 28 | #define BRCMF_C_IOCTL_MAXLEN 8192 | ||
| 29 | |||
| 30 | #define BRCMF_C_UP 2 | ||
| 31 | #define BRCMF_C_SET_PROMISC 10 | ||
| 32 | #define BRCMF_C_GET_RATE 12 | ||
| 33 | #define BRCMF_C_GET_INFRA 19 | ||
| 34 | #define BRCMF_C_SET_INFRA 20 | ||
| 35 | #define BRCMF_C_GET_AUTH 21 | ||
| 36 | #define BRCMF_C_SET_AUTH 22 | ||
| 37 | #define BRCMF_C_GET_BSSID 23 | ||
| 38 | #define BRCMF_C_GET_SSID 25 | ||
| 39 | #define BRCMF_C_SET_SSID 26 | ||
| 40 | #define BRCMF_C_GET_CHANNEL 29 | ||
| 41 | #define BRCMF_C_GET_SRL 31 | ||
| 42 | #define BRCMF_C_GET_LRL 33 | ||
| 43 | #define BRCMF_C_GET_RADIO 37 | ||
| 44 | #define BRCMF_C_SET_RADIO 38 | ||
| 45 | #define BRCMF_C_GET_PHYTYPE 39 | ||
| 46 | #define BRCMF_C_SET_KEY 45 | ||
| 47 | #define BRCMF_C_SET_PASSIVE_SCAN 49 | ||
| 48 | #define BRCMF_C_SCAN 50 | ||
| 49 | #define BRCMF_C_SCAN_RESULTS 51 | ||
| 50 | #define BRCMF_C_DISASSOC 52 | ||
| 51 | #define BRCMF_C_REASSOC 53 | ||
| 52 | #define BRCMF_C_SET_ROAM_TRIGGER 55 | ||
| 53 | #define BRCMF_C_SET_ROAM_DELTA 57 | ||
| 54 | #define BRCMF_C_GET_DTIMPRD 77 | ||
| 55 | #define BRCMF_C_SET_COUNTRY 84 | ||
| 56 | #define BRCMF_C_GET_PM 85 | ||
| 57 | #define BRCMF_C_SET_PM 86 | ||
| 58 | #define BRCMF_C_GET_AP 117 | ||
| 59 | #define BRCMF_C_SET_AP 118 | ||
| 60 | #define BRCMF_C_GET_RSSI 127 | ||
| 61 | #define BRCMF_C_GET_WSEC 133 | ||
| 62 | #define BRCMF_C_SET_WSEC 134 | ||
| 63 | #define BRCMF_C_GET_PHY_NOISE 135 | ||
| 64 | #define BRCMF_C_GET_BSS_INFO 136 | ||
| 65 | #define BRCMF_C_SET_SCAN_CHANNEL_TIME 185 | ||
| 66 | #define BRCMF_C_SET_SCAN_UNASSOC_TIME 187 | ||
| 67 | #define BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON 201 | ||
| 68 | #define BRCMF_C_GET_VALID_CHANNELS 217 | ||
| 69 | #define BRCMF_C_GET_KEY_PRIMARY 235 | ||
| 70 | #define BRCMF_C_SET_KEY_PRIMARY 236 | ||
| 71 | #define BRCMF_C_SET_SCAN_PASSIVE_TIME 258 | ||
| 72 | #define BRCMF_C_GET_VAR 262 | ||
| 73 | #define BRCMF_C_SET_VAR 263 | ||
| 74 | |||
| 75 | /* phy types (returned by WLC_GET_PHYTPE) */ | ||
| 76 | #define WLC_PHY_TYPE_A 0 | ||
| 77 | #define WLC_PHY_TYPE_B 1 | ||
| 78 | #define WLC_PHY_TYPE_G 2 | ||
| 79 | #define WLC_PHY_TYPE_N 4 | ||
| 80 | #define WLC_PHY_TYPE_LP 5 | ||
| 81 | #define WLC_PHY_TYPE_SSN 6 | ||
| 82 | #define WLC_PHY_TYPE_HT 7 | ||
| 83 | #define WLC_PHY_TYPE_LCN 8 | ||
| 84 | #define WLC_PHY_TYPE_NULL 0xf | ||
| 85 | |||
| 86 | #define BRCMF_PKT_FILTER_FIXED_LEN offsetof(struct brcmf_pkt_filter, u) | ||
| 87 | #define BRCMF_PKT_FILTER_PATTERN_FIXED_LEN \ | ||
| 88 | offsetof(struct brcmf_pkt_filter_pattern, mask_and_pattern) | ||
| 89 | |||
| 90 | #define BRCMF_EVENTING_MASK_LEN 16 | ||
| 91 | |||
| 92 | #define TOE_TX_CSUM_OL 0x00000001 | ||
| 93 | #define TOE_RX_CSUM_OL 0x00000002 | ||
| 94 | |||
| 95 | /* maximum channels returned by the get valid channels iovar */ | ||
| 96 | #define WL_NUMCHANNELS 64 | ||
| 97 | |||
| 98 | #define BRCMF_BSS_INFO_VERSION 108 /* current ver of brcmf_bss_info struct */ | ||
| 99 | |||
| 100 | /* size of brcmf_scan_params not including variable length array */ | ||
| 101 | #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64 | ||
| 102 | |||
| 103 | /* masks for channel and ssid count */ | ||
| 104 | #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff | ||
| 105 | #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 | ||
| 106 | |||
| 107 | #define BRCMF_SCAN_ACTION_START 1 | ||
| 108 | #define BRCMF_SCAN_ACTION_CONTINUE 2 | ||
| 109 | #define WL_SCAN_ACTION_ABORT 3 | ||
| 110 | |||
| 111 | #define BRCMF_ISCAN_REQ_VERSION 1 | ||
| 112 | |||
| 113 | /* brcmf_iscan_results status values */ | ||
| 114 | #define BRCMF_SCAN_RESULTS_SUCCESS 0 | ||
| 115 | #define BRCMF_SCAN_RESULTS_PARTIAL 1 | ||
| 116 | #define BRCMF_SCAN_RESULTS_PENDING 2 | ||
| 117 | #define BRCMF_SCAN_RESULTS_ABORTED 3 | ||
| 118 | #define BRCMF_SCAN_RESULTS_NO_MEM 4 | ||
| 119 | |||
| 120 | #define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ | ||
| 121 | #define BRCMF_PRIMARY_KEY (1 << 1) /* primary (ie tx) key */ | ||
| 122 | #define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ | ||
| 123 | #define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ | ||
| 124 | #define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ | ||
| 125 | |||
| 126 | /* For supporting multiple interfaces */ | ||
| 127 | #define BRCMF_MAX_IFS 16 | ||
| 128 | #define BRCMF_DEL_IF -0xe | ||
| 129 | #define BRCMF_BAD_IF -0xf | ||
| 130 | |||
| 131 | #define DOT11_BSSTYPE_ANY 2 | ||
| 132 | #define DOT11_MAX_DEFAULT_KEYS 4 | ||
| 133 | |||
| 134 | #define BRCMF_EVENT_MSG_LINK 0x01 | ||
| 135 | #define BRCMF_EVENT_MSG_FLUSHTXQ 0x02 | ||
| 136 | #define BRCMF_EVENT_MSG_GROUP 0x04 | ||
| 137 | |||
| 138 | struct brcmf_event_msg { | ||
| 139 | u16 version; | ||
| 140 | u16 flags; | ||
| 141 | u32 event_type; | ||
| 142 | u32 status; | ||
| 143 | u32 reason; | ||
| 144 | u32 auth_type; | ||
| 145 | u32 datalen; | ||
| 146 | u8 addr[ETH_ALEN]; | ||
| 147 | char ifname[IFNAMSIZ]; | ||
| 148 | } __packed; | ||
| 149 | |||
| 150 | struct brcm_ethhdr { | ||
| 151 | u16 subtype; | ||
| 152 | u16 length; | ||
| 153 | u8 version; | ||
| 154 | u8 oui[3]; | ||
| 155 | u16 usr_subtype; | ||
| 156 | } __packed; | ||
| 157 | |||
| 158 | struct brcmf_event { | ||
| 159 | struct ethhdr eth; | ||
| 160 | struct brcm_ethhdr hdr; | ||
| 161 | struct brcmf_event_msg msg; | ||
| 162 | } __packed; | ||
| 163 | |||
| 164 | struct dngl_stats { | ||
| 165 | unsigned long rx_packets; /* total packets received */ | ||
| 166 | unsigned long tx_packets; /* total packets transmitted */ | ||
| 167 | unsigned long rx_bytes; /* total bytes received */ | ||
| 168 | unsigned long tx_bytes; /* total bytes transmitted */ | ||
| 169 | unsigned long rx_errors; /* bad packets received */ | ||
| 170 | unsigned long tx_errors; /* packet transmit problems */ | ||
| 171 | unsigned long rx_dropped; /* packets dropped by dongle */ | ||
| 172 | unsigned long tx_dropped; /* packets dropped by dongle */ | ||
| 173 | unsigned long multicast; /* multicast packets received */ | ||
| 174 | }; | ||
| 175 | |||
| 176 | #define BRCMF_E_SET_SSID 0 | ||
| 177 | #define BRCMF_E_JOIN 1 | ||
| 178 | #define BRCMF_E_START 2 | ||
| 179 | #define BRCMF_E_AUTH 3 | ||
| 180 | #define BRCMF_E_AUTH_IND 4 | ||
| 181 | #define BRCMF_E_DEAUTH 5 | ||
| 182 | #define BRCMF_E_DEAUTH_IND 6 | ||
| 183 | #define BRCMF_E_ASSOC 7 | ||
| 184 | #define BRCMF_E_ASSOC_IND 8 | ||
| 185 | #define BRCMF_E_REASSOC 9 | ||
| 186 | #define BRCMF_E_REASSOC_IND 10 | ||
| 187 | #define BRCMF_E_DISASSOC 11 | ||
| 188 | #define BRCMF_E_DISASSOC_IND 12 | ||
| 189 | #define BRCMF_E_QUIET_START 13 | ||
| 190 | #define BRCMF_E_QUIET_END 14 | ||
| 191 | #define BRCMF_E_BEACON_RX 15 | ||
| 192 | #define BRCMF_E_LINK 16 | ||
| 193 | #define BRCMF_E_MIC_ERROR 17 | ||
| 194 | #define BRCMF_E_NDIS_LINK 18 | ||
| 195 | #define BRCMF_E_ROAM 19 | ||
| 196 | #define BRCMF_E_TXFAIL 20 | ||
| 197 | #define BRCMF_E_PMKID_CACHE 21 | ||
| 198 | #define BRCMF_E_RETROGRADE_TSF 22 | ||
| 199 | #define BRCMF_E_PRUNE 23 | ||
| 200 | #define BRCMF_E_AUTOAUTH 24 | ||
| 201 | #define BRCMF_E_EAPOL_MSG 25 | ||
| 202 | #define BRCMF_E_SCAN_COMPLETE 26 | ||
| 203 | #define BRCMF_E_ADDTS_IND 27 | ||
| 204 | #define BRCMF_E_DELTS_IND 28 | ||
| 205 | #define BRCMF_E_BCNSENT_IND 29 | ||
| 206 | #define BRCMF_E_BCNRX_MSG 30 | ||
| 207 | #define BRCMF_E_BCNLOST_MSG 31 | ||
| 208 | #define BRCMF_E_ROAM_PREP 32 | ||
| 209 | #define BRCMF_E_PFN_NET_FOUND 33 | ||
| 210 | #define BRCMF_E_PFN_NET_LOST 34 | ||
| 211 | #define BRCMF_E_RESET_COMPLETE 35 | ||
| 212 | #define BRCMF_E_JOIN_START 36 | ||
| 213 | #define BRCMF_E_ROAM_START 37 | ||
| 214 | #define BRCMF_E_ASSOC_START 38 | ||
| 215 | #define BRCMF_E_IBSS_ASSOC 39 | ||
| 216 | #define BRCMF_E_RADIO 40 | ||
| 217 | #define BRCMF_E_PSM_WATCHDOG 41 | ||
| 218 | #define BRCMF_E_PROBREQ_MSG 44 | ||
| 219 | #define BRCMF_E_SCAN_CONFIRM_IND 45 | ||
| 220 | #define BRCMF_E_PSK_SUP 46 | ||
| 221 | #define BRCMF_E_COUNTRY_CODE_CHANGED 47 | ||
| 222 | #define BRCMF_E_EXCEEDED_MEDIUM_TIME 48 | ||
| 223 | #define BRCMF_E_ICV_ERROR 49 | ||
| 224 | #define BRCMF_E_UNICAST_DECODE_ERROR 50 | ||
| 225 | #define BRCMF_E_MULTICAST_DECODE_ERROR 51 | ||
| 226 | #define BRCMF_E_TRACE 52 | ||
| 227 | #define BRCMF_E_IF 54 | ||
| 228 | #define BRCMF_E_RSSI 56 | ||
| 229 | #define BRCMF_E_PFN_SCAN_COMPLETE 57 | ||
| 230 | #define BRCMF_E_EXTLOG_MSG 58 | ||
| 231 | #define BRCMF_E_ACTION_FRAME 59 | ||
| 232 | #define BRCMF_E_ACTION_FRAME_COMPLETE 60 | ||
| 233 | #define BRCMF_E_PRE_ASSOC_IND 61 | ||
| 234 | #define BRCMF_E_PRE_REASSOC_IND 62 | ||
| 235 | #define BRCMF_E_CHANNEL_ADOPTED 63 | ||
| 236 | #define BRCMF_E_AP_STARTED 64 | ||
| 237 | #define BRCMF_E_DFS_AP_STOP 65 | ||
| 238 | #define BRCMF_E_DFS_AP_RESUME 66 | ||
| 239 | #define BRCMF_E_RESERVED1 67 | ||
| 240 | #define BRCMF_E_RESERVED2 68 | ||
| 241 | #define BRCMF_E_ESCAN_RESULT 69 | ||
| 242 | #define BRCMF_E_ACTION_FRAME_OFF_CHAN_COMPLETE 70 | ||
| 243 | #define BRCMF_E_DCS_REQUEST 73 | ||
| 244 | |||
| 245 | #define BRCMF_E_FIFO_CREDIT_MAP 74 | ||
| 246 | |||
| 247 | #define BRCMF_E_LAST 75 | ||
| 248 | |||
| 249 | #define BRCMF_E_STATUS_SUCCESS 0 | ||
| 250 | #define BRCMF_E_STATUS_FAIL 1 | ||
| 251 | #define BRCMF_E_STATUS_TIMEOUT 2 | ||
| 252 | #define BRCMF_E_STATUS_NO_NETWORKS 3 | ||
| 253 | #define BRCMF_E_STATUS_ABORT 4 | ||
| 254 | #define BRCMF_E_STATUS_NO_ACK 5 | ||
| 255 | #define BRCMF_E_STATUS_UNSOLICITED 6 | ||
| 256 | #define BRCMF_E_STATUS_ATTEMPT 7 | ||
| 257 | #define BRCMF_E_STATUS_PARTIAL 8 | ||
| 258 | #define BRCMF_E_STATUS_NEWSCAN 9 | ||
| 259 | #define BRCMF_E_STATUS_NEWASSOC 10 | ||
| 260 | #define BRCMF_E_STATUS_11HQUIET 11 | ||
| 261 | #define BRCMF_E_STATUS_SUPPRESS 12 | ||
| 262 | #define BRCMF_E_STATUS_NOCHANS 13 | ||
| 263 | #define BRCMF_E_STATUS_CS_ABORT 15 | ||
| 264 | #define BRCMF_E_STATUS_ERROR 16 | ||
| 265 | |||
| 266 | #define BRCMF_E_REASON_INITIAL_ASSOC 0 | ||
| 267 | #define BRCMF_E_REASON_LOW_RSSI 1 | ||
| 268 | #define BRCMF_E_REASON_DEAUTH 2 | ||
| 269 | #define BRCMF_E_REASON_DISASSOC 3 | ||
| 270 | #define BRCMF_E_REASON_BCNS_LOST 4 | ||
| 271 | #define BRCMF_E_REASON_MINTXRATE 9 | ||
| 272 | #define BRCMF_E_REASON_TXFAIL 10 | ||
| 273 | |||
| 274 | #define BRCMF_E_REASON_FAST_ROAM_FAILED 5 | ||
| 275 | #define BRCMF_E_REASON_DIRECTED_ROAM 6 | ||
| 276 | #define BRCMF_E_REASON_TSPEC_REJECTED 7 | ||
| 277 | #define BRCMF_E_REASON_BETTER_AP 8 | ||
| 278 | |||
| 279 | #define BRCMF_E_PRUNE_ENCR_MISMATCH 1 | ||
| 280 | #define BRCMF_E_PRUNE_BCAST_BSSID 2 | ||
| 281 | #define BRCMF_E_PRUNE_MAC_DENY 3 | ||
| 282 | #define BRCMF_E_PRUNE_MAC_NA 4 | ||
| 283 | #define BRCMF_E_PRUNE_REG_PASSV 5 | ||
| 284 | #define BRCMF_E_PRUNE_SPCT_MGMT 6 | ||
| 285 | #define BRCMF_E_PRUNE_RADAR 7 | ||
| 286 | #define BRCMF_E_RSN_MISMATCH 8 | ||
| 287 | #define BRCMF_E_PRUNE_NO_COMMON_RATES 9 | ||
| 288 | #define BRCMF_E_PRUNE_BASIC_RATES 10 | ||
| 289 | #define BRCMF_E_PRUNE_CIPHER_NA 12 | ||
| 290 | #define BRCMF_E_PRUNE_KNOWN_STA 13 | ||
| 291 | #define BRCMF_E_PRUNE_WDS_PEER 15 | ||
| 292 | #define BRCMF_E_PRUNE_QBSS_LOAD 16 | ||
| 293 | #define BRCMF_E_PRUNE_HOME_AP 17 | ||
| 294 | |||
| 295 | #define BRCMF_E_SUP_OTHER 0 | ||
| 296 | #define BRCMF_E_SUP_DECRYPT_KEY_DATA 1 | ||
| 297 | #define BRCMF_E_SUP_BAD_UCAST_WEP128 2 | ||
| 298 | #define BRCMF_E_SUP_BAD_UCAST_WEP40 3 | ||
| 299 | #define BRCMF_E_SUP_UNSUP_KEY_LEN 4 | ||
| 300 | #define BRCMF_E_SUP_PW_KEY_CIPHER 5 | ||
| 301 | #define BRCMF_E_SUP_MSG3_TOO_MANY_IE 6 | ||
| 302 | #define BRCMF_E_SUP_MSG3_IE_MISMATCH 7 | ||
| 303 | #define BRCMF_E_SUP_NO_INSTALL_FLAG 8 | ||
| 304 | #define BRCMF_E_SUP_MSG3_NO_GTK 9 | ||
| 305 | #define BRCMF_E_SUP_GRP_KEY_CIPHER 10 | ||
| 306 | #define BRCMF_E_SUP_GRP_MSG1_NO_GTK 11 | ||
| 307 | #define BRCMF_E_SUP_GTK_DECRYPT_FAIL 12 | ||
| 308 | #define BRCMF_E_SUP_SEND_FAIL 13 | ||
| 309 | #define BRCMF_E_SUP_DEAUTH 14 | ||
| 310 | |||
| 311 | #define BRCMF_E_IF_ADD 1 | ||
| 312 | #define BRCMF_E_IF_DEL 2 | ||
| 313 | #define BRCMF_E_IF_CHANGE 3 | ||
| 314 | |||
| 315 | #define BRCMF_E_IF_ROLE_STA 0 | ||
| 316 | #define BRCMF_E_IF_ROLE_AP 1 | ||
| 317 | #define BRCMF_E_IF_ROLE_WDS 2 | ||
| 318 | |||
| 319 | #define BRCMF_E_LINK_BCN_LOSS 1 | ||
| 320 | #define BRCMF_E_LINK_DISASSOC 2 | ||
| 321 | #define BRCMF_E_LINK_ASSOC_REC 3 | ||
| 322 | #define BRCMF_E_LINK_BSSCFG_DIS 4 | ||
| 323 | |||
| 324 | /* The level of bus communication with the dongle */ | ||
| 325 | enum brcmf_bus_state { | ||
| 326 | BRCMF_BUS_DOWN, /* Not ready for frame transfers */ | ||
| 327 | BRCMF_BUS_LOAD, /* Download access only (CPU reset) */ | ||
| 328 | BRCMF_BUS_DATA /* Ready for frame transfers */ | ||
| 329 | }; | ||
| 330 | |||
| 331 | /* Pattern matching filter. Specifies an offset within received packets to | ||
| 332 | * start matching, the pattern to match, the size of the pattern, and a bitmask | ||
| 333 | * that indicates which bits within the pattern should be matched. | ||
| 334 | */ | ||
| 335 | struct brcmf_pkt_filter_pattern { | ||
| 336 | u32 offset; /* Offset within received packet to start pattern matching. | ||
| 337 | * Offset '0' is the first byte of the ethernet header. | ||
| 338 | */ | ||
| 339 | u32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ | ||
| 340 | u8 mask_and_pattern[1]; /* Variable length mask and pattern data. mask starts | ||
| 341 | * at offset 0. Pattern immediately follows mask. | ||
| 342 | */ | ||
| 343 | }; | ||
| 344 | |||
| 345 | /* IOVAR "pkt_filter_add" parameter. Used to install packet filters. */ | ||
| 346 | struct brcmf_pkt_filter { | ||
| 347 | u32 id; /* Unique filter id, specified by app. */ | ||
| 348 | u32 type; /* Filter type (WL_PKT_FILTER_TYPE_xxx). */ | ||
| 349 | u32 negate_match; /* Negate the result of filter matches */ | ||
| 350 | union { /* Filter definitions */ | ||
| 351 | struct brcmf_pkt_filter_pattern pattern; /* Filter pattern */ | ||
| 352 | } u; | ||
| 353 | }; | ||
| 354 | |||
| 355 | /* IOVAR "pkt_filter_enable" parameter. */ | ||
| 356 | struct brcmf_pkt_filter_enable { | ||
| 357 | u32 id; /* Unique filter id */ | ||
| 358 | u32 enable; /* Enable/disable bool */ | ||
| 359 | }; | ||
| 360 | |||
| 361 | /* BSS info structure | ||
| 362 | * Applications MUST CHECK ie_offset field and length field to access IEs and | ||
| 363 | * next bss_info structure in a vector (in struct brcmf_scan_results) | ||
| 364 | */ | ||
| 365 | struct brcmf_bss_info { | ||
| 366 | u32 version; /* version field */ | ||
| 367 | u32 length; /* byte length of data in this record, | ||
| 368 | * starting at version and including IEs | ||
| 369 | */ | ||
| 370 | u8 BSSID[ETH_ALEN]; | ||
| 371 | u16 beacon_period; /* units are Kusec */ | ||
| 372 | u16 capability; /* Capability information */ | ||
| 373 | u8 SSID_len; | ||
| 374 | u8 SSID[32]; | ||
| 375 | struct { | ||
| 376 | uint count; /* # rates in this set */ | ||
| 377 | u8 rates[16]; /* rates in 500kbps units w/hi bit set if basic */ | ||
| 378 | } rateset; /* supported rates */ | ||
| 379 | chanspec_t chanspec; /* chanspec for bss */ | ||
| 380 | u16 atim_window; /* units are Kusec */ | ||
| 381 | u8 dtim_period; /* DTIM period */ | ||
| 382 | s16 RSSI; /* receive signal strength (in dBm) */ | ||
| 383 | s8 phy_noise; /* noise (in dBm) */ | ||
| 384 | |||
| 385 | u8 n_cap; /* BSS is 802.11N Capable */ | ||
| 386 | u32 nbss_cap; /* 802.11N BSS Capabilities (based on HT_CAP_*) */ | ||
| 387 | u8 ctl_ch; /* 802.11N BSS control channel number */ | ||
| 388 | u32 reserved32[1]; /* Reserved for expansion of BSS properties */ | ||
| 389 | u8 flags; /* flags */ | ||
| 390 | u8 reserved[3]; /* Reserved for expansion of BSS properties */ | ||
| 391 | u8 basic_mcs[MCSSET_LEN]; /* 802.11N BSS required MCS set */ | ||
| 392 | |||
| 393 | u16 ie_offset; /* offset at which IEs start, from beginning */ | ||
| 394 | u32 ie_length; /* byte length of Information Elements */ | ||
| 395 | s16 SNR; /* average SNR of during frame reception */ | ||
| 396 | /* Add new fields here */ | ||
| 397 | /* variable length Information Elements */ | ||
| 398 | }; | ||
| 399 | |||
| 400 | struct brcmf_ssid { | ||
| 401 | u32 SSID_len; | ||
| 402 | unsigned char SSID[32]; | ||
| 403 | }; | ||
| 404 | |||
| 405 | struct brcmf_scan_params { | ||
| 406 | struct brcmf_ssid ssid; /* default: {0, ""} */ | ||
| 407 | u8 bssid[ETH_ALEN]; /* default: bcast */ | ||
| 408 | s8 bss_type; /* default: any, | ||
| 409 | * DOT11_BSSTYPE_ANY/INFRASTRUCTURE/INDEPENDENT | ||
| 410 | */ | ||
| 411 | u8 scan_type; /* flags, 0 use default */ | ||
| 412 | s32 nprobes; /* -1 use default, number of probes per channel */ | ||
| 413 | s32 active_time; /* -1 use default, dwell time per channel for | ||
| 414 | * active scanning | ||
| 415 | */ | ||
| 416 | s32 passive_time; /* -1 use default, dwell time per channel | ||
| 417 | * for passive scanning | ||
| 418 | */ | ||
| 419 | s32 home_time; /* -1 use default, dwell time for the home channel | ||
| 420 | * between channel scans | ||
| 421 | */ | ||
| 422 | s32 channel_num; /* count of channels and ssids that follow | ||
| 423 | * | ||
| 424 | * low half is count of channels in | ||
| 425 | * channel_list, 0 means default (use all | ||
| 426 | * available channels) | ||
| 427 | * | ||
| 428 | * high half is entries in struct brcmf_ssid | ||
| 429 | * array that follows channel_list, aligned for | ||
| 430 | * s32 (4 bytes) meaning an odd channel count | ||
| 431 | * implies a 2-byte pad between end of | ||
| 432 | * channel_list and first ssid | ||
| 433 | * | ||
| 434 | * if ssid count is zero, single ssid in the | ||
| 435 | * fixed parameter portion is assumed, otherwise | ||
| 436 | * ssid in the fixed portion is ignored | ||
| 437 | */ | ||
| 438 | u16 channel_list[1]; /* list of chanspecs */ | ||
| 439 | }; | ||
| 440 | |||
| 441 | /* incremental scan struct */ | ||
| 442 | struct brcmf_iscan_params { | ||
| 443 | u32 version; | ||
| 444 | u16 action; | ||
| 445 | u16 scan_duration; | ||
| 446 | struct brcmf_scan_params params; | ||
| 447 | }; | ||
| 448 | |||
| 449 | /* 3 fields + size of brcmf_scan_params, not including variable length array */ | ||
| 450 | #define BRCMF_ISCAN_PARAMS_FIXED_SIZE \ | ||
| 451 | (offsetof(struct brcmf_iscan_params, params) + \ | ||
| 452 | sizeof(struct brcmf_ssid)) | ||
| 453 | |||
| 454 | struct brcmf_scan_results { | ||
| 455 | u32 buflen; | ||
| 456 | u32 version; | ||
| 457 | u32 count; | ||
| 458 | struct brcmf_bss_info bss_info[1]; | ||
| 459 | }; | ||
| 460 | |||
| 461 | /* used for association with a specific BSSID and chanspec list */ | ||
| 462 | struct brcmf_assoc_params { | ||
| 463 | u8 bssid[ETH_ALEN]; /* 00:00:00:00:00:00: broadcast scan */ | ||
| 464 | s32 chanspec_num; /* 0: all available channels, | ||
| 465 | * otherwise count of chanspecs in chanspec_list | ||
| 466 | */ | ||
| 467 | chanspec_t chanspec_list[1]; /* list of chanspecs */ | ||
| 468 | }; | ||
| 469 | #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ | ||
| 470 | (sizeof(struct brcmf_assoc_params) - sizeof(chanspec_t)) | ||
| 471 | |||
| 472 | /* used for join with or without a specific bssid and channel list */ | ||
| 473 | struct brcmf_join_params { | ||
| 474 | struct brcmf_ssid ssid; | ||
| 475 | struct brcmf_assoc_params params; | ||
| 476 | }; | ||
| 477 | |||
| 478 | /* size of brcmf_scan_results not including variable length array */ | ||
| 479 | #define BRCMF_SCAN_RESULTS_FIXED_SIZE \ | ||
| 480 | (sizeof(struct brcmf_scan_results) - sizeof(struct brcmf_bss_info)) | ||
| 481 | |||
| 482 | /* incremental scan results struct */ | ||
| 483 | struct brcmf_iscan_results { | ||
| 484 | u32 status; | ||
| 485 | struct brcmf_scan_results results; | ||
| 486 | }; | ||
| 487 | |||
| 488 | /* size of brcmf_iscan_results not including variable length array */ | ||
| 489 | #define BRCMF_ISCAN_RESULTS_FIXED_SIZE \ | ||
| 490 | (BRCMF_SCAN_RESULTS_FIXED_SIZE + \ | ||
| 491 | offsetof(struct brcmf_iscan_results, results)) | ||
| 492 | |||
| 493 | struct brcmf_wsec_key { | ||
| 494 | u32 index; /* key index */ | ||
| 495 | u32 len; /* key length */ | ||
| 496 | u8 data[WLAN_MAX_KEY_LEN]; /* key data */ | ||
| 497 | u32 pad_1[18]; | ||
| 498 | u32 algo; /* CRYPTO_ALGO_AES_CCM, CRYPTO_ALGO_WEP128, etc */ | ||
| 499 | u32 flags; /* misc flags */ | ||
| 500 | u32 pad_2[2]; | ||
| 501 | int pad_3; | ||
| 502 | int iv_initialized; /* has IV been initialized already? */ | ||
| 503 | int pad_4; | ||
| 504 | /* Rx IV */ | ||
| 505 | struct { | ||
| 506 | u32 hi; /* upper 32 bits of IV */ | ||
| 507 | u16 lo; /* lower 16 bits of IV */ | ||
| 508 | } rxiv; | ||
| 509 | u32 pad_5[2]; | ||
| 510 | u8 ea[ETH_ALEN]; /* per station */ | ||
| 511 | }; | ||
| 512 | |||
| 513 | /* Used to get specific STA parameters */ | ||
| 514 | struct brcmf_scb_val { | ||
| 515 | u32 val; | ||
| 516 | u8 ea[ETH_ALEN]; | ||
| 517 | }; | ||
| 518 | |||
| 519 | /* channel encoding */ | ||
| 520 | struct brcmf_channel_info { | ||
| 521 | int hw_channel; | ||
| 522 | int target_channel; | ||
| 523 | int scan_channel; | ||
| 524 | }; | ||
| 525 | |||
| 526 | /* Linux network driver ioctl encoding */ | ||
| 527 | struct brcmf_ioctl { | ||
| 528 | uint cmd; /* common ioctl definition */ | ||
| 529 | void *buf; /* pointer to user buffer */ | ||
| 530 | uint len; /* length of user buffer */ | ||
| 531 | u8 set; /* get or set request (optional) */ | ||
| 532 | uint used; /* bytes read or written (optional) */ | ||
| 533 | uint needed; /* bytes needed (optional) */ | ||
| 534 | }; | ||
| 535 | |||
| 536 | /* Forward decls for struct brcmf_pub (see below) */ | ||
| 537 | struct brcmf_bus; /* device bus info */ | ||
| 538 | struct brcmf_proto; /* device communication protocol info */ | ||
| 539 | struct brcmf_info; /* device driver info */ | ||
| 540 | |||
| 541 | /* Common structure for module and instance linkage */ | ||
| 542 | struct brcmf_pub { | ||
| 543 | /* Linkage ponters */ | ||
| 544 | struct brcmf_bus *bus; | ||
| 545 | struct brcmf_proto *prot; | ||
| 546 | struct brcmf_info *info; | ||
| 547 | |||
| 548 | /* Internal brcmf items */ | ||
| 549 | bool up; /* Driver up/down (to OS) */ | ||
| 550 | bool txoff; /* Transmit flow-controlled */ | ||
| 551 | bool dongle_reset; /* true = DEVRESET put dongle into reset */ | ||
| 552 | enum brcmf_bus_state busstate; | ||
| 553 | uint hdrlen; /* Total BRCMF header length (proto + bus) */ | ||
| 554 | uint maxctl; /* Max size rxctl request from proto to bus */ | ||
| 555 | uint rxsz; /* Rx buffer size bus module should use */ | ||
| 556 | u8 wme_dp; /* wme discard priority */ | ||
| 557 | |||
| 558 | /* Dongle media info */ | ||
| 559 | bool iswl; /* Dongle-resident driver is wl */ | ||
| 560 | unsigned long drv_version; /* Version of dongle-resident driver */ | ||
| 561 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ | ||
| 562 | struct dngl_stats dstats; /* Stats for dongle-based data */ | ||
| 563 | |||
| 564 | /* Additional stats for the bus level */ | ||
| 565 | unsigned long tx_packets; /* Data packets sent to dongle */ | ||
| 566 | unsigned long tx_multicast; /* Multicast data packets sent to dongle */ | ||
| 567 | unsigned long tx_errors; /* Errors in sending data to dongle */ | ||
| 568 | unsigned long tx_ctlpkts; /* Control packets sent to dongle */ | ||
| 569 | unsigned long tx_ctlerrs; /* Errors sending control frames to dongle */ | ||
| 570 | unsigned long rx_packets; /* Packets sent up the network interface */ | ||
| 571 | unsigned long rx_multicast; /* Multicast packets sent up the network | ||
| 572 | interface */ | ||
| 573 | unsigned long rx_errors; /* Errors processing rx data packets */ | ||
| 574 | unsigned long rx_ctlpkts; /* Control frames processed from dongle */ | ||
| 575 | unsigned long rx_ctlerrs; /* Errors in processing rx control frames */ | ||
| 576 | unsigned long rx_dropped; /* Packets dropped locally (no memory) */ | ||
| 577 | unsigned long rx_flushed; /* Packets flushed due to | ||
| 578 | unscheduled sendup thread */ | ||
| 579 | unsigned long wd_dpc_sched; /* Number of times dpc scheduled by | ||
| 580 | watchdog timer */ | ||
| 581 | |||
| 582 | unsigned long rx_readahead_cnt; /* Number of packets where header read-ahead | ||
| 583 | was used. */ | ||
| 584 | unsigned long tx_realloc; /* Number of tx packets we had to realloc for | ||
| 585 | headroom */ | ||
| 586 | unsigned long fc_packets; /* Number of flow control pkts recvd */ | ||
| 587 | |||
| 588 | /* Last error return */ | ||
| 589 | int bcmerror; | ||
| 590 | uint tickcnt; | ||
| 591 | |||
| 592 | /* Last error from dongle */ | ||
| 593 | int dongle_error; | ||
| 594 | |||
| 595 | /* Suspend disable flag flag */ | ||
| 596 | int suspend_disable_flag; /* "1" to disable all extra powersaving | ||
| 597 | during suspend */ | ||
| 598 | int in_suspend; /* flag set to 1 when early suspend called */ | ||
| 599 | int dtim_skip; /* dtim skip , default 0 means wake each dtim */ | ||
| 600 | |||
| 601 | /* Pkt filter defination */ | ||
| 602 | char *pktfilter[100]; | ||
| 603 | int pktfilter_count; | ||
| 604 | |||
| 605 | u8 country_code[BRCM_CNTRY_BUF_SZ]; | ||
| 606 | char eventmask[BRCMF_EVENTING_MASK_LEN]; | ||
| 607 | |||
| 608 | }; | ||
| 609 | |||
| 610 | struct brcmf_if_event { | ||
| 611 | u8 ifidx; | ||
| 612 | u8 action; | ||
| 613 | u8 flags; | ||
| 614 | u8 bssidx; | ||
| 615 | }; | ||
| 616 | |||
| 617 | struct brcmf_timeout { | ||
| 618 | u32 limit; /* Expiration time (usec) */ | ||
| 619 | u32 increment; /* Current expiration increment (usec) */ | ||
| 620 | u32 elapsed; /* Current elapsed time (usec) */ | ||
| 621 | u32 tick; /* O/S tick time (usec) */ | ||
| 622 | }; | ||
| 623 | |||
| 624 | struct bcmevent_name { | ||
| 625 | uint event; | ||
| 626 | const char *name; | ||
| 627 | }; | ||
| 628 | |||
| 629 | #if defined(CONFIG_PM_SLEEP) | ||
| 630 | extern atomic_t brcmf_mmc_suspend; | ||
| 631 | #define BRCMF_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); | ||
| 632 | #define _BRCMF_PM_RESUME_WAIT(a, b) do { \ | ||
| 633 | int retry = 0; \ | ||
| 634 | while (atomic_read(&brcmf_mmc_suspend) && retry++ != b) { \ | ||
| 635 | wait_event_timeout(a, false, HZ/100); \ | ||
| 636 | } \ | ||
| 637 | } while (0) | ||
| 638 | #define BRCMF_PM_RESUME_WAIT(a) _BRCMF_PM_RESUME_WAIT(a, 30) | ||
| 639 | #define BRCMF_PM_RESUME_RETURN_ERROR(a) \ | ||
| 640 | do { if (atomic_read(&brcmf_mmc_suspend)) return a; } while (0) | ||
| 641 | |||
| 642 | #define BRCMF_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); | ||
| 643 | #define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \ | ||
| 644 | uint countdown = (us) + 9999; \ | ||
| 645 | while ((exp) && (countdown >= 10000)) { \ | ||
| 646 | wait_event_timeout(a, false, HZ/100); \ | ||
| 647 | countdown -= 10000; \ | ||
| 648 | } \ | ||
| 649 | } while (0) | ||
| 650 | |||
| 651 | #else | ||
| 652 | |||
| 653 | #define BRCMF_PM_RESUME_WAIT_INIT(a) | ||
| 654 | #define BRCMF_PM_RESUME_WAIT(a) | ||
| 655 | #define BRCMF_PM_RESUME_RETURN_ERROR(a) | ||
| 656 | |||
| 657 | #define BRCMF_SPINWAIT_SLEEP_INIT(a) | ||
| 658 | #define BRCMF_SPINWAIT_SLEEP(a, exp, us) do { \ | ||
| 659 | uint countdown = (us) + 9; \ | ||
| 660 | while ((exp) && (countdown >= 10)) { \ | ||
| 661 | udelay(10); \ | ||
| 662 | countdown -= 10; \ | ||
| 663 | } \ | ||
| 664 | } while (0) | ||
| 665 | |||
| 666 | #endif /* defined(CONFIG_PM_SLEEP) */ | ||
| 667 | |||
| 668 | /* | ||
| 669 | * Insmod parameters for debug/test | ||
| 670 | */ | ||
| 671 | |||
| 672 | /* Use interrupts */ | ||
| 673 | extern uint brcmf_intr; | ||
| 674 | |||
| 675 | /* Use polling */ | ||
| 676 | extern uint brcmf_poll; | ||
| 677 | |||
| 678 | /* ARP offload agent mode */ | ||
| 679 | extern uint brcmf_arp_mode; | ||
| 680 | |||
| 681 | /* ARP offload enable */ | ||
| 682 | extern uint brcmf_arp_enable; | ||
| 683 | |||
| 684 | /* Pkt filte enable control */ | ||
| 685 | extern uint brcmf_pkt_filter_enable; | ||
| 686 | |||
| 687 | /* Pkt filter init setup */ | ||
| 688 | extern uint brcmf_pkt_filter_init; | ||
| 689 | |||
| 690 | /* Pkt filter mode control */ | ||
| 691 | extern uint brcmf_master_mode; | ||
| 692 | |||
| 693 | /* Roaming mode control */ | ||
| 694 | extern uint brcmf_roam; | ||
| 695 | |||
| 696 | /* Roaming mode control */ | ||
| 697 | extern uint brcmf_radio_up; | ||
| 698 | |||
| 699 | /* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */ | ||
| 700 | extern int brcmf_idletime; | ||
| 701 | #define BRCMF_IDLETIME_TICKS 1 | ||
| 702 | |||
| 703 | /* SDIO Drive Strength */ | ||
| 704 | extern uint brcmf_sdiod_drive_strength; | ||
| 705 | |||
| 706 | /* Override to force tx queueing all the time */ | ||
| 707 | extern uint brcmf_force_tx_queueing; | ||
| 708 | |||
| 709 | #ifdef SDTEST | ||
| 710 | /* Echo packet generator (SDIO), pkts/s */ | ||
| 711 | extern uint brcmf_pktgen; | ||
| 712 | |||
| 713 | /* Echo packet len (0 => sawtooth, max 1800) */ | ||
| 714 | extern uint brcmf_pktgen_len; | ||
| 715 | #define BRCMF_MAX_PKTGEN_LEN 1800 | ||
| 716 | #endif | ||
| 717 | |||
| 718 | extern const struct bcmevent_name bcmevent_names[]; | ||
| 719 | extern const int bcmevent_names_size; | ||
| 720 | |||
| 721 | |||
| 722 | static inline void MUTEX_LOCK_INIT(struct brcmf_pub *drvr) | ||
| 723 | { | ||
| 724 | } | ||
| 725 | |||
| 726 | static inline void MUTEX_LOCK(struct brcmf_pub *drvr) | ||
| 727 | { | ||
| 728 | } | ||
| 729 | |||
| 730 | static inline void MUTEX_UNLOCK(struct brcmf_pub *drvr) | ||
| 731 | { | ||
| 732 | } | ||
| 733 | |||
| 734 | static inline void MUTEX_LOCK_SOFTAP_SET_INIT(struct brcmf_pub *drvr) | ||
| 735 | { | ||
| 736 | } | ||
| 737 | |||
| 738 | static inline void MUTEX_LOCK_SOFTAP_SET(struct brcmf_pub *drvr) | ||
| 739 | { | ||
| 740 | } | ||
| 741 | |||
| 742 | static inline void MUTEX_UNLOCK_SOFTAP_SET(struct brcmf_pub *drvr) | ||
| 743 | { | ||
| 744 | } | ||
| 745 | |||
| 746 | static inline void MUTEX_LOCK_WL_SCAN_SET_INIT(void) | ||
| 747 | { | ||
| 748 | } | ||
| 749 | |||
| 750 | static inline void MUTEX_LOCK_WL_SCAN_SET(void) | ||
| 751 | { | ||
| 752 | } | ||
| 753 | |||
| 754 | static inline void MUTEX_UNLOCK_WL_SCAN_SET(void) | ||
| 755 | { | ||
| 756 | } | ||
| 757 | |||
| 758 | /* Indication from bus module regarding presence/insertion of dongle. | ||
| 759 | * Return struct brcmf_pub pointer, used as handle to OS module in later calls. | ||
| 760 | * Returned structure should have bus and prot pointers filled in. | ||
| 761 | * bus_hdrlen specifies required headroom for bus module header. | ||
| 762 | */ | ||
| 763 | extern struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, | ||
| 764 | uint bus_hdrlen); | ||
| 765 | extern int brcmf_net_attach(struct brcmf_pub *drvr, int idx); | ||
| 766 | extern int brcmf_netdev_wait_pend8021x(struct net_device *dev); | ||
| 767 | |||
| 768 | /* Indication from bus module regarding removal/absence of dongle */ | ||
| 769 | extern void brcmf_detach(struct brcmf_pub *drvr); | ||
| 770 | |||
| 771 | /* Indication from bus module to change flow-control state */ | ||
| 772 | extern void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool on); | ||
| 773 | |||
| 774 | extern bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, | ||
| 775 | struct sk_buff *pkt, int prec); | ||
| 776 | |||
| 777 | /* Receive frame for delivery to OS. Callee disposes of rxp. */ | ||
| 778 | extern void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, | ||
| 779 | struct sk_buff *rxp, int numpkt); | ||
| 780 | |||
| 781 | /* Return pointer to interface name */ | ||
| 782 | extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); | ||
| 783 | |||
| 784 | /* Notify tx completion */ | ||
| 785 | extern void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, | ||
| 786 | bool success); | ||
| 787 | |||
| 788 | /* Query ioctl */ | ||
| 789 | extern int brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, | ||
| 790 | uint cmd, void *buf, uint len); | ||
| 791 | |||
| 792 | /* OS independent layer functions */ | ||
| 793 | extern int brcmf_os_proto_block(struct brcmf_pub *drvr); | ||
| 794 | extern int brcmf_os_proto_unblock(struct brcmf_pub *drvr); | ||
| 795 | extern int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition, | ||
| 796 | bool *pending); | ||
| 797 | extern int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr); | ||
| 798 | extern unsigned int brcmf_os_get_ioctl_resp_timeout(void); | ||
| 799 | extern void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec); | ||
| 800 | #ifdef BCMDBG | ||
| 801 | extern int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size); | ||
| 802 | #endif /* BCMDBG */ | ||
| 803 | |||
| 804 | extern void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec); | ||
| 805 | extern int brcmf_timeout_expired(struct brcmf_timeout *tmo); | ||
| 806 | |||
| 807 | extern int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name); | ||
| 808 | extern int brcmf_c_host_event(struct brcmf_info *drvr_priv, int *idx, | ||
| 809 | void *pktdata, struct brcmf_event_msg *, | ||
| 810 | void **data_ptr); | ||
| 811 | |||
| 812 | extern void brcmf_c_init(void); | ||
| 813 | |||
| 814 | extern int brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, | ||
| 815 | char *name, u8 *mac_addr, u32 flags, u8 bssidx); | ||
| 816 | extern void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx); | ||
| 817 | |||
| 818 | /* Send packet to dongle via data channel */ | ||
| 819 | extern int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx,\ | ||
| 820 | struct sk_buff *pkt); | ||
| 821 | |||
| 822 | extern int brcmf_bus_devreset(struct brcmf_pub *drvr, u8 flag); | ||
| 823 | extern int brcmf_bus_start(struct brcmf_pub *drvr); | ||
| 824 | |||
| 825 | extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); | ||
| 826 | extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, | ||
| 827 | int enable, int master_mode); | ||
| 828 | |||
| 829 | /* Linux network driver ioctl encoding */ | ||
| 830 | struct brcmf_c_ioctl { | ||
| 831 | uint cmd; /* common ioctl definition */ | ||
| 832 | void *buf; /* pointer to user buffer */ | ||
| 833 | uint len; /* length of user buffer */ | ||
| 834 | bool set; /* get or set request (optional) */ | ||
| 835 | uint used; /* bytes read or written (optional) */ | ||
| 836 | uint needed; /* bytes needed (optional) */ | ||
| 837 | uint driver; /* to identify target driver */ | ||
| 838 | }; | ||
| 839 | |||
| 840 | /* per-driver magic numbers */ | ||
| 841 | #define BRCMF_IOCTL_MAGIC 0x00444944 | ||
| 842 | |||
| 843 | /* bump this number if you change the ioctl interface */ | ||
| 844 | #define BRCMF_IOCTL_VERSION 1 | ||
| 845 | #define BRCMF_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ | ||
| 846 | |||
| 847 | /* common ioctl definitions */ | ||
| 848 | #define BRCMF_GET_MAGIC 0 | ||
| 849 | #define BRCMF_GET_VERSION 1 | ||
| 850 | #define BRCMF_GET_VAR 2 | ||
| 851 | #define BRCMF_SET_VAR 3 | ||
| 852 | |||
| 853 | /* message levels */ | ||
| 854 | #define BRCMF_ERROR_VAL 0x0001 | ||
| 855 | #define BRCMF_TRACE_VAL 0x0002 | ||
| 856 | #define BRCMF_INFO_VAL 0x0004 | ||
| 857 | #define BRCMF_DATA_VAL 0x0008 | ||
| 858 | #define BRCMF_CTL_VAL 0x0010 | ||
| 859 | #define BRCMF_TIMER_VAL 0x0020 | ||
| 860 | #define BRCMF_HDRS_VAL 0x0040 | ||
| 861 | #define BRCMF_BYTES_VAL 0x0080 | ||
| 862 | #define BRCMF_INTR_VAL 0x0100 | ||
| 863 | #define BRCMF_GLOM_VAL 0x0400 | ||
| 864 | #define BRCMF_EVENT_VAL 0x0800 | ||
| 865 | #define BRCMF_BTA_VAL 0x1000 | ||
| 866 | #define BRCMF_ISCAN_VAL 0x2000 | ||
| 867 | |||
| 868 | #ifdef SDTEST | ||
| 869 | /* For pktgen iovar */ | ||
| 870 | struct brcmf_pktgen { | ||
| 871 | uint version; /* To allow structure change tracking */ | ||
| 872 | uint freq; /* Max ticks between tx/rx attempts */ | ||
| 873 | uint count; /* Test packets to send/rcv each attempt */ | ||
| 874 | uint print; /* Print counts every <print> attempts */ | ||
| 875 | uint total; /* Total packets (or bursts) */ | ||
| 876 | uint minlen; /* Minimum length of packets to send */ | ||
| 877 | uint maxlen; /* Maximum length of packets to send */ | ||
| 878 | uint numsent; /* Count of test packets sent */ | ||
| 879 | uint numrcvd; /* Count of test packets received */ | ||
| 880 | uint numfail; /* Count of test send failures */ | ||
| 881 | uint mode; /* Test mode (type of test packets) */ | ||
| 882 | uint stop; /* Stop after this many tx failures */ | ||
| 883 | }; | ||
| 884 | |||
| 885 | /* Version in case structure changes */ | ||
| 886 | #define BRCMF_PKTGEN_VERSION 2 | ||
| 887 | |||
| 888 | /* Type of test packets to use */ | ||
| 889 | #define BRCMF_PKTGEN_ECHO 1 /* Send echo requests */ | ||
| 890 | #define BRCMF_PKTGEN_SEND 2 /* Send discard packets */ | ||
| 891 | #define BRCMF_PKTGEN_RXBURST 3 /* Request dongle send N packets */ | ||
| 892 | #define BRCMF_PKTGEN_RECV 4 /* Continuous rx from continuous | ||
| 893 | tx dongle */ | ||
| 894 | #endif /* SDTEST */ | ||
| 895 | |||
| 896 | /* Enter idle immediately (no timeout) */ | ||
| 897 | #define BRCMF_IDLE_IMMEDIATE (-1) | ||
| 898 | |||
| 899 | /* Values for idleclock iovar: other values are the sd_divisor to use | ||
| 900 | when idle */ | ||
| 901 | #define BRCMF_IDLE_ACTIVE 0 /* Do not request any SD clock change | ||
| 902 | when idle */ | ||
| 903 | |||
| 904 | #endif /* _BRCMF_H_ */ | ||
| @@ -1,78 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _BRCMF_BUS_H_ | ||
| 18 | #define _BRCMF_BUS_H_ | ||
| 19 | |||
| 20 | /* Packet alignment for most efficient SDIO (can change based on platform) */ | ||
| 21 | #ifndef BRCMF_SDALIGN | ||
| 22 | #define BRCMF_SDALIGN 32 | ||
| 23 | #endif | ||
| 24 | #if !ISPOWEROF2(BRCMF_SDALIGN) | ||
| 25 | #error BRCMF_SDALIGN is not a power of 2! | ||
| 26 | #endif | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Exported from brcmf bus module (brcmf_usb, brcmf_sdio) | ||
| 30 | */ | ||
| 31 | |||
| 32 | /* dongle ram module parameter */ | ||
| 33 | extern int brcmf_dongle_memsize; | ||
| 34 | |||
| 35 | /* Tx/Rx bounds module parameters */ | ||
| 36 | extern uint brcmf_txbound; | ||
| 37 | extern uint brcmf_rxbound; | ||
| 38 | |||
| 39 | /* Watchdog timer interval */ | ||
| 40 | extern uint brcmf_watchdog_ms; | ||
| 41 | |||
| 42 | /* Indicate (dis)interest in finding dongles. */ | ||
| 43 | extern int brcmf_bus_register(void); | ||
| 44 | extern void brcmf_bus_unregister(void); | ||
| 45 | |||
| 46 | /* Stop bus module: clear pending frames, disable data flow */ | ||
| 47 | extern void brcmf_sdbrcm_bus_stop(struct brcmf_bus *bus, bool enforce_mutex); | ||
| 48 | |||
| 49 | /* Initialize bus module: prepare for communication w/dongle */ | ||
| 50 | extern int brcmf_sdbrcm_bus_init(struct brcmf_pub *drvr, bool enforce_mutex); | ||
| 51 | |||
| 52 | /* Send a data frame to the dongle. Callee disposes of txp. */ | ||
| 53 | extern int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *txp); | ||
| 54 | |||
| 55 | /* Send/receive a control message to/from the dongle. | ||
| 56 | * Expects caller to enforce a single outstanding transaction. | ||
| 57 | */ | ||
| 58 | extern int | ||
| 59 | brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); | ||
| 60 | |||
| 61 | extern int | ||
| 62 | brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen); | ||
| 63 | |||
| 64 | /* Check for and handle local prot-specific iovar commands */ | ||
| 65 | extern int brcmf_sdbrcm_bus_iovar_op(struct brcmf_pub *drvr, const char *name, | ||
| 66 | void *params, int plen, void *arg, int len, | ||
| 67 | bool set); | ||
| 68 | |||
| 69 | /* Add bus dump output to a buffer */ | ||
| 70 | extern void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, | ||
| 71 | struct brcmu_strbuf *strbuf); | ||
| 72 | |||
| 73 | /* Clear any bus counters */ | ||
| 74 | extern void brcmf_bus_clearcounts(struct brcmf_pub *drvr); | ||
| 75 | |||
| 76 | extern void brcmf_sdbrcm_wd_timer(struct brcmf_bus *bus, uint wdtick); | ||
| 77 | |||
| 78 | #endif /* _BRCMF_BUS_H_ */ | ||
| @@ -1,502 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/types.h> | ||
| 18 | #include <linux/netdevice.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <defs.h> | ||
| 21 | |||
| 22 | #include <brcmu_utils.h> | ||
| 23 | #include <brcmu_wifi.h> | ||
| 24 | |||
| 25 | #include "dhd.h" | ||
| 26 | #include "dhd_proto.h" | ||
| 27 | #include "dhd_bus.h" | ||
| 28 | #include "dhd_dbg.h" | ||
| 29 | |||
| 30 | struct brcmf_proto_cdc_ioctl { | ||
| 31 | u32 cmd; /* ioctl command value */ | ||
| 32 | u32 len; /* lower 16: output buflen; | ||
| 33 | * upper 16: input buflen (excludes header) */ | ||
| 34 | u32 flags; /* flag defns given below */ | ||
| 35 | u32 status; /* status code returned from the device */ | ||
| 36 | }; | ||
| 37 | |||
| 38 | /* Max valid buffer size that can be sent to the dongle */ | ||
| 39 | #define CDC_MAX_MSG_SIZE (ETH_FRAME_LEN+ETH_FCS_LEN) | ||
| 40 | |||
| 41 | /* CDC flag definitions */ | ||
| 42 | #define CDCF_IOC_ERROR 0x01 /* 1=ioctl cmd failed */ | ||
| 43 | #define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */ | ||
| 44 | #define CDCF_IOC_IF_MASK 0xF000 /* I/F index */ | ||
| 45 | #define CDCF_IOC_IF_SHIFT 12 | ||
| 46 | #define CDCF_IOC_ID_MASK 0xFFFF0000 /* id an ioctl pairing */ | ||
| 47 | #define CDCF_IOC_ID_SHIFT 16 /* ID Mask shift bits */ | ||
| 48 | #define CDC_IOC_ID(flags) \ | ||
| 49 | (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT) | ||
| 50 | #define CDC_SET_IF_IDX(hdr, idx) \ | ||
| 51 | ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \ | ||
| 52 | ((idx) << CDCF_IOC_IF_SHIFT))) | ||
| 53 | |||
| 54 | /* | ||
| 55 | * BDC header - Broadcom specific extension of CDC. | ||
| 56 | * Used on data packets to convey priority across USB. | ||
| 57 | */ | ||
| 58 | #define BDC_HEADER_LEN 4 | ||
| 59 | #define BDC_PROTO_VER 1 /* Protocol version */ | ||
| 60 | #define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ | ||
| 61 | #define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ | ||
| 62 | #define BDC_FLAG_SUM_GOOD 0x04 /* Good RX checksums */ | ||
| 63 | #define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ | ||
| 64 | #define BDC_PRIORITY_MASK 0x7 | ||
| 65 | #define BDC_FLAG2_IF_MASK 0x0f /* packet rx interface in APSTA */ | ||
| 66 | #define BDC_FLAG2_IF_SHIFT 0 | ||
| 67 | |||
| 68 | #define BDC_GET_IF_IDX(hdr) \ | ||
| 69 | ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) | ||
| 70 | #define BDC_SET_IF_IDX(hdr, idx) \ | ||
| 71 | ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \ | ||
| 72 | ((idx) << BDC_FLAG2_IF_SHIFT))) | ||
| 73 | |||
| 74 | struct brcmf_proto_bdc_header { | ||
| 75 | u8 flags; | ||
| 76 | u8 priority; /* 802.1d Priority, 4:7 flow control info for usb */ | ||
| 77 | u8 flags2; | ||
| 78 | u8 rssi; | ||
| 79 | }; | ||
| 80 | |||
| 81 | |||
| 82 | #define RETRIES 2 /* # of retries to retrieve matching ioctl response */ | ||
| 83 | #define BUS_HEADER_LEN (16+BRCMF_SDALIGN) /* Must be atleast SDPCM_RESERVE | ||
| 84 | * (amount of header tha might be added) | ||
| 85 | * plus any space that might be needed | ||
| 86 | * for alignment padding. | ||
| 87 | */ | ||
| 88 | #define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for | ||
| 89 | * round off at the end of buffer | ||
| 90 | */ | ||
| 91 | |||
| 92 | struct brcmf_proto { | ||
| 93 | u16 reqid; | ||
| 94 | u8 pending; | ||
| 95 | u32 lastcmd; | ||
| 96 | u8 bus_header[BUS_HEADER_LEN]; | ||
| 97 | struct brcmf_proto_cdc_ioctl msg; | ||
| 98 | unsigned char buf[BRCMF_C_IOCTL_MAXLEN + ROUND_UP_MARGIN]; | ||
| 99 | }; | ||
| 100 | |||
| 101 | static int brcmf_proto_cdc_msg(struct brcmf_pub *drvr) | ||
| 102 | { | ||
| 103 | struct brcmf_proto *prot = drvr->prot; | ||
| 104 | int len = le32_to_cpu(prot->msg.len) + | ||
| 105 | sizeof(struct brcmf_proto_cdc_ioctl); | ||
| 106 | |||
| 107 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 108 | |||
| 109 | /* NOTE : cdc->msg.len holds the desired length of the buffer to be | ||
| 110 | * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area | ||
| 111 | * is actually sent to the dongle | ||
| 112 | */ | ||
| 113 | if (len > CDC_MAX_MSG_SIZE) | ||
| 114 | len = CDC_MAX_MSG_SIZE; | ||
| 115 | |||
| 116 | /* Send request */ | ||
| 117 | return brcmf_sdbrcm_bus_txctl(drvr->bus, (unsigned char *)&prot->msg, | ||
| 118 | len); | ||
| 119 | } | ||
| 120 | |||
| 121 | static int brcmf_proto_cdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len) | ||
| 122 | { | ||
| 123 | int ret; | ||
| 124 | struct brcmf_proto *prot = drvr->prot; | ||
| 125 | |||
| 126 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 127 | |||
| 128 | do { | ||
| 129 | ret = brcmf_sdbrcm_bus_rxctl(drvr->bus, | ||
| 130 | (unsigned char *)&prot->msg, | ||
| 131 | len + sizeof(struct brcmf_proto_cdc_ioctl)); | ||
| 132 | if (ret < 0) | ||
| 133 | break; | ||
| 134 | } while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id); | ||
| 135 | |||
| 136 | return ret; | ||
| 137 | } | ||
| 138 | |||
| 139 | int | ||
| 140 | brcmf_proto_cdc_query_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
| 141 | void *buf, uint len) | ||
| 142 | { | ||
| 143 | struct brcmf_proto *prot = drvr->prot; | ||
| 144 | struct brcmf_proto_cdc_ioctl *msg = &prot->msg; | ||
| 145 | void *info; | ||
| 146 | int ret = 0, retries = 0; | ||
| 147 | u32 id, flags = 0; | ||
| 148 | |||
| 149 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 150 | BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len)); | ||
| 151 | |||
| 152 | /* Respond "bcmerror" and "bcmerrorstr" with local cache */ | ||
| 153 | if (cmd == BRCMF_C_GET_VAR && buf) { | ||
| 154 | if (!strcmp((char *)buf, "bcmerrorstr")) { | ||
| 155 | strncpy((char *)buf, "bcm_error", | ||
| 156 | BCME_STRLEN); | ||
| 157 | goto done; | ||
| 158 | } else if (!strcmp((char *)buf, "bcmerror")) { | ||
| 159 | *(int *)buf = drvr->dongle_error; | ||
| 160 | goto done; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl)); | ||
| 165 | |||
| 166 | msg->cmd = cpu_to_le32(cmd); | ||
| 167 | msg->len = cpu_to_le32(len); | ||
| 168 | msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT); | ||
| 169 | CDC_SET_IF_IDX(msg, ifidx); | ||
| 170 | msg->flags = cpu_to_le32(msg->flags); | ||
| 171 | |||
| 172 | if (buf) | ||
| 173 | memcpy(prot->buf, buf, len); | ||
| 174 | |||
| 175 | ret = brcmf_proto_cdc_msg(drvr); | ||
| 176 | if (ret < 0) { | ||
| 177 | BRCMF_ERROR(("brcmf_proto_cdc_query_ioctl: brcmf_proto_cdc_msg " | ||
| 178 | "failed w/status %d\n", ret)); | ||
| 179 | goto done; | ||
| 180 | } | ||
| 181 | |||
| 182 | retry: | ||
| 183 | /* wait for interrupt and get first fragment */ | ||
| 184 | ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); | ||
| 185 | if (ret < 0) | ||
| 186 | goto done; | ||
| 187 | |||
| 188 | flags = le32_to_cpu(msg->flags); | ||
| 189 | id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT; | ||
| 190 | |||
| 191 | if ((id < prot->reqid) && (++retries < RETRIES)) | ||
| 192 | goto retry; | ||
| 193 | if (id != prot->reqid) { | ||
| 194 | BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n", | ||
| 195 | brcmf_ifname(drvr, ifidx), __func__, id, | ||
| 196 | prot->reqid)); | ||
| 197 | ret = -EINVAL; | ||
| 198 | goto done; | ||
| 199 | } | ||
| 200 | |||
| 201 | /* Check info buffer */ | ||
| 202 | info = (void *)&msg[1]; | ||
| 203 | |||
| 204 | /* Copy info buffer */ | ||
| 205 | if (buf) { | ||
| 206 | if (ret < (int)len) | ||
| 207 | len = ret; | ||
| 208 | memcpy(buf, info, len); | ||
| 209 | } | ||
| 210 | |||
| 211 | /* Check the ERROR flag */ | ||
| 212 | if (flags & CDCF_IOC_ERROR) { | ||
| 213 | ret = le32_to_cpu(msg->status); | ||
| 214 | /* Cache error from dongle */ | ||
| 215 | drvr->dongle_error = ret; | ||
| 216 | } | ||
| 217 | |||
| 218 | done: | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, uint cmd, | ||
| 223 | void *buf, uint len) | ||
| 224 | { | ||
| 225 | struct brcmf_proto *prot = drvr->prot; | ||
| 226 | struct brcmf_proto_cdc_ioctl *msg = &prot->msg; | ||
| 227 | int ret = 0; | ||
| 228 | u32 flags, id; | ||
| 229 | |||
| 230 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 231 | BRCMF_CTL(("%s: cmd %d len %d\n", __func__, cmd, len)); | ||
| 232 | |||
| 233 | memset(msg, 0, sizeof(struct brcmf_proto_cdc_ioctl)); | ||
| 234 | |||
| 235 | msg->cmd = cpu_to_le32(cmd); | ||
| 236 | msg->len = cpu_to_le32(len); | ||
| 237 | msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET; | ||
| 238 | CDC_SET_IF_IDX(msg, ifidx); | ||
| 239 | msg->flags = cpu_to_le32(msg->flags); | ||
| 240 | |||
| 241 | if (buf) | ||
| 242 | memcpy(prot->buf, buf, len); | ||
| 243 | |||
| 244 | ret = brcmf_proto_cdc_msg(drvr); | ||
| 245 | if (ret < 0) | ||
| 246 | goto done; | ||
| 247 | |||
| 248 | ret = brcmf_proto_cdc_cmplt(drvr, prot->reqid, len); | ||
| 249 | if (ret < 0) | ||
| 250 | goto done; | ||
| 251 | |||
| 252 | flags = le32_to_cpu(msg->flags); | ||
| 253 | id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT; | ||
| 254 | |||
| 255 | if (id != prot->reqid) { | ||
| 256 | BRCMF_ERROR(("%s: %s: unexpected request id %d (expected %d)\n", | ||
| 257 | brcmf_ifname(drvr, ifidx), __func__, id, | ||
| 258 | prot->reqid)); | ||
| 259 | ret = -EINVAL; | ||
| 260 | goto done; | ||
| 261 | } | ||
| 262 | |||
| 263 | /* Check the ERROR flag */ | ||
| 264 | if (flags & CDCF_IOC_ERROR) { | ||
| 265 | ret = le32_to_cpu(msg->status); | ||
| 266 | /* Cache error from dongle */ | ||
| 267 | drvr->dongle_error = ret; | ||
| 268 | } | ||
| 269 | |||
| 270 | done: | ||
| 271 | return ret; | ||
| 272 | } | ||
| 273 | |||
| 274 | int | ||
| 275 | brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, struct brcmf_ioctl *ioc, | ||
| 276 | void *buf, int len) | ||
| 277 | { | ||
| 278 | struct brcmf_proto *prot = drvr->prot; | ||
| 279 | int ret = -1; | ||
| 280 | |||
| 281 | if (drvr->busstate == BRCMF_BUS_DOWN) { | ||
| 282 | BRCMF_ERROR(("%s : bus is down. we have nothing to do\n", | ||
| 283 | __func__)); | ||
| 284 | return ret; | ||
| 285 | } | ||
| 286 | brcmf_os_proto_block(drvr); | ||
| 287 | |||
| 288 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 289 | |||
| 290 | if (len > BRCMF_C_IOCTL_MAXLEN) | ||
| 291 | goto done; | ||
| 292 | |||
| 293 | if (prot->pending == true) { | ||
| 294 | BRCMF_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) " | ||
| 295 | "lastcmd=0x%x (%lu)\n", | ||
| 296 | ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd, | ||
| 297 | (unsigned long)prot->lastcmd)); | ||
| 298 | if ((ioc->cmd == BRCMF_C_SET_VAR) || | ||
| 299 | (ioc->cmd == BRCMF_C_GET_VAR)) | ||
| 300 | BRCMF_TRACE(("iovar cmd=%s\n", (char *)buf)); | ||
| 301 | |||
| 302 | goto done; | ||
| 303 | } | ||
| 304 | |||
| 305 | prot->pending = true; | ||
| 306 | prot->lastcmd = ioc->cmd; | ||
| 307 | if (ioc->set) | ||
| 308 | ret = brcmf_proto_cdc_set_ioctl(drvr, ifidx, ioc->cmd, | ||
| 309 | buf, len); | ||
| 310 | else { | ||
| 311 | ret = brcmf_proto_cdc_query_ioctl(drvr, ifidx, ioc->cmd, | ||
| 312 | buf, len); | ||
| 313 | if (ret > 0) | ||
| 314 | ioc->used = ret - sizeof(struct brcmf_proto_cdc_ioctl); | ||
| 315 | } | ||
| 316 | |||
| 317 | /* Too many programs assume ioctl() returns 0 on success */ | ||
| 318 | if (ret >= 0) | ||
| 319 | ret = 0; | ||
| 320 | else { | ||
| 321 | struct brcmf_proto_cdc_ioctl *msg = &prot->msg; | ||
| 322 | /* len == needed when set/query fails from dongle */ | ||
| 323 | ioc->needed = le32_to_cpu(msg->len); | ||
| 324 | } | ||
| 325 | |||
| 326 | /* Intercept the wme_dp ioctl here */ | ||
| 327 | if (!ret && ioc->cmd == BRCMF_C_SET_VAR && | ||
| 328 | !strcmp(buf, "wme_dp")) { | ||
| 329 | int slen, val = 0; | ||
| 330 | |||
| 331 | slen = strlen("wme_dp") + 1; | ||
| 332 | if (len >= (int)(slen + sizeof(int))) | ||
| 333 | memcpy(&val, (char *)buf + slen, sizeof(int)); | ||
| 334 | drvr->wme_dp = (u8) le32_to_cpu(val); | ||
| 335 | } | ||
| 336 | |||
| 337 | prot->pending = false; | ||
| 338 | |||
| 339 | done: | ||
| 340 | brcmf_os_proto_unblock(drvr); | ||
| 341 | |||
| 342 | return ret; | ||
| 343 | } | ||
| 344 | |||
| 345 | #define PKTSUMNEEDED(skb) \ | ||
| 346 | (((struct sk_buff *)(skb))->ip_summed == CHECKSUM_PARTIAL) | ||
| 347 | #define PKTSETSUMGOOD(skb, x) \ | ||
| 348 | (((struct sk_buff *)(skb))->ip_summed = \ | ||
| 349 | ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) | ||
| 350 | |||
| 351 | void brcmf_proto_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf) | ||
| 352 | { | ||
| 353 | brcmu_bprintf(strbuf, "Protocol CDC: reqid %d\n", drvr->prot->reqid); | ||
| 354 | } | ||
| 355 | |||
| 356 | void brcmf_proto_hdrpush(struct brcmf_pub *drvr, int ifidx, | ||
| 357 | struct sk_buff *pktbuf) | ||
| 358 | { | ||
| 359 | struct brcmf_proto_bdc_header *h; | ||
| 360 | |||
| 361 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 362 | |||
| 363 | /* Push BDC header used to convey priority for buses that don't */ | ||
| 364 | |||
| 365 | skb_push(pktbuf, BDC_HEADER_LEN); | ||
| 366 | |||
| 367 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); | ||
| 368 | |||
| 369 | h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); | ||
| 370 | if (PKTSUMNEEDED(pktbuf)) | ||
| 371 | h->flags |= BDC_FLAG_SUM_NEEDED; | ||
| 372 | |||
| 373 | h->priority = (pktbuf->priority & BDC_PRIORITY_MASK); | ||
| 374 | h->flags2 = 0; | ||
| 375 | h->rssi = 0; | ||
| 376 | BDC_SET_IF_IDX(h, ifidx); | ||
| 377 | } | ||
| 378 | |||
| 379 | int brcmf_proto_hdrpull(struct brcmf_pub *drvr, int *ifidx, | ||
| 380 | struct sk_buff *pktbuf) | ||
| 381 | { | ||
| 382 | struct brcmf_proto_bdc_header *h; | ||
| 383 | |||
| 384 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 385 | |||
| 386 | /* Pop BDC header used to convey priority for buses that don't */ | ||
| 387 | |||
| 388 | if (pktbuf->len < BDC_HEADER_LEN) { | ||
| 389 | BRCMF_ERROR(("%s: rx data too short (%d < %d)\n", __func__, | ||
| 390 | pktbuf->len, BDC_HEADER_LEN)); | ||
| 391 | return -EBADE; | ||
| 392 | } | ||
| 393 | |||
| 394 | h = (struct brcmf_proto_bdc_header *)(pktbuf->data); | ||
| 395 | |||
| 396 | *ifidx = BDC_GET_IF_IDX(h); | ||
| 397 | if (*ifidx >= BRCMF_MAX_IFS) { | ||
| 398 | BRCMF_ERROR(("%s: rx data ifnum out of range (%d)\n", | ||
| 399 | __func__, *ifidx)); | ||
| 400 | return -EBADE; | ||
| 401 | } | ||
| 402 | |||
| 403 | if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != | ||
| 404 | BDC_PROTO_VER) { | ||
| 405 | BRCMF_ERROR(("%s: non-BDC packet received, flags 0x%x\n", | ||
| 406 | brcmf_ifname(drvr, *ifidx), h->flags)); | ||
| 407 | return -EBADE; | ||
| 408 | } | ||
| 409 | |||
| 410 | if (h->flags & BDC_FLAG_SUM_GOOD) { | ||
| 411 | BRCMF_INFO(("%s: BDC packet received with good rx-csum, " | ||
| 412 | "flags 0x%x\n", | ||
| 413 | brcmf_ifname(drvr, *ifidx), h->flags)); | ||
| 414 | PKTSETSUMGOOD(pktbuf, true); | ||
| 415 | } | ||
| 416 | |||
| 417 | pktbuf->priority = h->priority & BDC_PRIORITY_MASK; | ||
| 418 | |||
| 419 | skb_pull(pktbuf, BDC_HEADER_LEN); | ||
| 420 | |||
| 421 | return 0; | ||
| 422 | } | ||
| 423 | |||
| 424 | int brcmf_proto_attach(struct brcmf_pub *drvr) | ||
| 425 | { | ||
| 426 | struct brcmf_proto *cdc; | ||
| 427 | |||
| 428 | cdc = kzalloc(sizeof(struct brcmf_proto), GFP_ATOMIC); | ||
| 429 | if (!cdc) { | ||
| 430 | BRCMF_ERROR(("%s: kmalloc failed\n", __func__)); | ||
| 431 | goto fail; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* ensure that the msg buf directly follows the cdc msg struct */ | ||
| 435 | if ((unsigned long)(&cdc->msg + 1) != (unsigned long)cdc->buf) { | ||
| 436 | BRCMF_ERROR(("struct brcmf_proto is not correctly defined\n")); | ||
| 437 | goto fail; | ||
| 438 | } | ||
| 439 | |||
| 440 | drvr->prot = cdc; | ||
| 441 | drvr->hdrlen += BDC_HEADER_LEN; | ||
| 442 | drvr->maxctl = BRCMF_C_IOCTL_MAXLEN + | ||
| 443 | sizeof(struct brcmf_proto_cdc_ioctl) + ROUND_UP_MARGIN; | ||
| 444 | return 0; | ||
| 445 | |||
| 446 | fail: | ||
| 447 | kfree(cdc); | ||
| 448 | return -ENOMEM; | ||
| 449 | } | ||
| 450 | |||
| 451 | /* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ | ||
| 452 | void brcmf_proto_detach(struct brcmf_pub *drvr) | ||
| 453 | { | ||
| 454 | kfree(drvr->prot); | ||
| 455 | drvr->prot = NULL; | ||
| 456 | } | ||
| 457 | |||
| 458 | void brcmf_proto_dstats(struct brcmf_pub *drvr) | ||
| 459 | { | ||
| 460 | /* No stats from dongle added yet, copy bus stats */ | ||
| 461 | drvr->dstats.tx_packets = drvr->tx_packets; | ||
| 462 | drvr->dstats.tx_errors = drvr->tx_errors; | ||
| 463 | drvr->dstats.rx_packets = drvr->rx_packets; | ||
| 464 | drvr->dstats.rx_errors = drvr->rx_errors; | ||
| 465 | drvr->dstats.rx_dropped = drvr->rx_dropped; | ||
| 466 | drvr->dstats.multicast = drvr->rx_multicast; | ||
| 467 | return; | ||
| 468 | } | ||
| 469 | |||
| 470 | int brcmf_proto_init(struct brcmf_pub *drvr) | ||
| 471 | { | ||
| 472 | int ret = 0; | ||
| 473 | char buf[128]; | ||
| 474 | |||
| 475 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 476 | |||
| 477 | brcmf_os_proto_block(drvr); | ||
| 478 | |||
| 479 | /* Get the device MAC address */ | ||
| 480 | strcpy(buf, "cur_etheraddr"); | ||
| 481 | ret = brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, | ||
| 482 | buf, sizeof(buf)); | ||
| 483 | if (ret < 0) { | ||
| 484 | brcmf_os_proto_unblock(drvr); | ||
| 485 | return ret; | ||
| 486 | } | ||
| 487 | memcpy(drvr->mac, buf, ETH_ALEN); | ||
| 488 | |||
| 489 | brcmf_os_proto_unblock(drvr); | ||
| 490 | |||
| 491 | ret = brcmf_c_preinit_ioctls(drvr); | ||
| 492 | |||
| 493 | /* Always assumes wl for now */ | ||
| 494 | drvr->iswl = true; | ||
| 495 | |||
| 496 | return ret; | ||
| 497 | } | ||
| 498 | |||
| 499 | void brcmf_proto_stop(struct brcmf_pub *drvr) | ||
| 500 | { | ||
| 501 | /* Nothing to do for CDC */ | ||
| 502 | } | ||
| @@ -1,1196 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | #include <linux/kernel.h> | ||
| 17 | #include <linux/string.h> | ||
| 18 | #include <linux/sched.h> | ||
| 19 | #include <linux/netdevice.h> | ||
| 20 | #include <asm/unaligned.h> | ||
| 21 | #include <defs.h> | ||
| 22 | #include <brcmu_wifi.h> | ||
| 23 | #include <brcmu_utils.h> | ||
| 24 | #include "dhd.h" | ||
| 25 | #include "dhd_bus.h" | ||
| 26 | #include "dhd_proto.h" | ||
| 27 | #include "dhd_dbg.h" | ||
| 28 | |||
| 29 | #define BRCM_OUI "\x00\x10\x18" | ||
| 30 | #define DOT11_OUI_LEN 3 | ||
| 31 | #define BCMILCP_BCM_SUBTYPE_EVENT 1 | ||
| 32 | #define PKTFILTER_BUF_SIZE 2048 | ||
| 33 | |||
| 34 | int brcmf_msg_level; | ||
| 35 | |||
| 36 | #define MSGTRACE_VERSION 1 | ||
| 37 | |||
| 38 | #ifdef BCMDBG | ||
| 39 | const char brcmf_version[] = | ||
| 40 | "Dongle Host Driver, version " BRCMF_VERSION_STR "\nCompiled on " __DATE__ | ||
| 41 | " at " __TIME__; | ||
| 42 | #else | ||
| 43 | const char brcmf_version[] = "Dongle Host Driver, version " BRCMF_VERSION_STR; | ||
| 44 | #endif | ||
| 45 | |||
| 46 | /* IOVar table */ | ||
| 47 | enum { | ||
| 48 | IOV_VERSION = 1, | ||
| 49 | IOV_MSGLEVEL, | ||
| 50 | IOV_BCMERRORSTR, | ||
| 51 | IOV_BCMERROR, | ||
| 52 | IOV_DUMP, | ||
| 53 | IOV_CLEARCOUNTS, | ||
| 54 | IOV_LOGDUMP, | ||
| 55 | IOV_LOGCAL, | ||
| 56 | IOV_LOGSTAMP, | ||
| 57 | IOV_GPIOOB, | ||
| 58 | IOV_IOCTLTIMEOUT, | ||
| 59 | IOV_LAST | ||
| 60 | }; | ||
| 61 | |||
| 62 | const struct brcmu_iovar brcmf_iovars[] = { | ||
| 63 | {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(brcmf_version)} | ||
| 64 | , | ||
| 65 | #ifdef BCMDBG | ||
| 66 | {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0} | ||
| 67 | , | ||
| 68 | #endif /* BCMDBG */ | ||
| 69 | {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN} | ||
| 70 | , | ||
| 71 | {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0} | ||
| 72 | , | ||
| 73 | {"dump", IOV_DUMP, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN} | ||
| 74 | , | ||
| 75 | {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0} | ||
| 76 | , | ||
| 77 | {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0} | ||
| 78 | , | ||
| 79 | {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0} | ||
| 80 | , | ||
| 81 | {NULL, 0, 0, 0, 0} | ||
| 82 | }; | ||
| 83 | |||
| 84 | /* Message trace header */ | ||
| 85 | struct msgtrace_hdr { | ||
| 86 | u8 version; | ||
| 87 | u8 spare; | ||
| 88 | u16 len; /* Len of the trace */ | ||
| 89 | u32 seqnum; /* Sequence number of message. Useful | ||
| 90 | * if the messsage has been lost | ||
| 91 | * because of DMA error or a bus reset | ||
| 92 | * (ex: SDIO Func2) | ||
| 93 | */ | ||
| 94 | u32 discarded_bytes; /* Number of discarded bytes because of | ||
| 95 | trace overflow */ | ||
| 96 | u32 discarded_printf; /* Number of discarded printf | ||
| 97 | because of trace overflow */ | ||
| 98 | } __packed; | ||
| 99 | |||
| 100 | void brcmf_c_init(void) | ||
| 101 | { | ||
| 102 | /* Init global variables at run-time, not as part of the declaration. | ||
| 103 | * This is required to support init/de-init of the driver. | ||
| 104 | * Initialization | ||
| 105 | * of globals as part of the declaration results in non-deterministic | ||
| 106 | * behaviour since the value of the globals may be different on the | ||
| 107 | * first time that the driver is initialized vs subsequent | ||
| 108 | * initializations. | ||
| 109 | */ | ||
| 110 | brcmf_msg_level = BRCMF_ERROR_VAL; | ||
| 111 | } | ||
| 112 | |||
| 113 | static int brcmf_c_dump(struct brcmf_pub *drvr, char *buf, int buflen) | ||
| 114 | { | ||
| 115 | struct brcmu_strbuf b; | ||
| 116 | struct brcmu_strbuf *strbuf = &b; | ||
| 117 | |||
| 118 | brcmu_binit(strbuf, buf, buflen); | ||
| 119 | |||
| 120 | /* Base info */ | ||
| 121 | brcmu_bprintf(strbuf, "%s\n", brcmf_version); | ||
| 122 | brcmu_bprintf(strbuf, "\n"); | ||
| 123 | brcmu_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n", | ||
| 124 | drvr->up, drvr->txoff, drvr->busstate); | ||
| 125 | brcmu_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n", | ||
| 126 | drvr->hdrlen, drvr->maxctl, drvr->rxsz); | ||
| 127 | brcmu_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %pM\n", | ||
| 128 | drvr->iswl, drvr->drv_version, &drvr->mac); | ||
| 129 | brcmu_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", drvr->bcmerror, | ||
| 130 | drvr->tickcnt); | ||
| 131 | |||
| 132 | brcmu_bprintf(strbuf, "dongle stats:\n"); | ||
| 133 | brcmu_bprintf(strbuf, | ||
| 134 | "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n", | ||
| 135 | drvr->dstats.tx_packets, drvr->dstats.tx_bytes, | ||
| 136 | drvr->dstats.tx_errors, drvr->dstats.tx_dropped); | ||
| 137 | brcmu_bprintf(strbuf, | ||
| 138 | "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n", | ||
| 139 | drvr->dstats.rx_packets, drvr->dstats.rx_bytes, | ||
| 140 | drvr->dstats.rx_errors, drvr->dstats.rx_dropped); | ||
| 141 | brcmu_bprintf(strbuf, "multicast %ld\n", drvr->dstats.multicast); | ||
| 142 | |||
| 143 | brcmu_bprintf(strbuf, "bus stats:\n"); | ||
| 144 | brcmu_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n", | ||
| 145 | drvr->tx_packets, drvr->tx_multicast, drvr->tx_errors); | ||
| 146 | brcmu_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n", | ||
| 147 | drvr->tx_ctlpkts, drvr->tx_ctlerrs); | ||
| 148 | brcmu_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld\n", | ||
| 149 | drvr->rx_packets, drvr->rx_multicast, drvr->rx_errors); | ||
| 150 | brcmu_bprintf(strbuf, | ||
| 151 | "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n", | ||
| 152 | drvr->rx_ctlpkts, drvr->rx_ctlerrs, drvr->rx_dropped, | ||
| 153 | drvr->rx_flushed); | ||
| 154 | brcmu_bprintf(strbuf, | ||
| 155 | "rx_readahead_cnt %ld tx_realloc %ld fc_packets %ld\n", | ||
| 156 | drvr->rx_readahead_cnt, drvr->tx_realloc, drvr->fc_packets); | ||
| 157 | brcmu_bprintf(strbuf, "wd_dpc_sched %ld\n", drvr->wd_dpc_sched); | ||
| 158 | brcmu_bprintf(strbuf, "\n"); | ||
| 159 | |||
| 160 | /* Add any prot info */ | ||
| 161 | brcmf_proto_dump(drvr, strbuf); | ||
| 162 | brcmu_bprintf(strbuf, "\n"); | ||
| 163 | |||
| 164 | /* Add any bus info */ | ||
| 165 | brcmf_sdbrcm_bus_dump(drvr, strbuf); | ||
| 166 | |||
| 167 | return !strbuf->size ? -EOVERFLOW : 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | static int | ||
| 171 | brcmf_c_doiovar(struct brcmf_pub *drvr, const struct brcmu_iovar *vi, | ||
| 172 | u32 actionid, const char *name, void *params, int plen, | ||
| 173 | void *arg, int len, int val_size) | ||
| 174 | { | ||
| 175 | int bcmerror = 0; | ||
| 176 | s32 int_val = 0; | ||
| 177 | |||
| 178 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 179 | |||
| 180 | bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid)); | ||
| 181 | if (bcmerror != 0) | ||
| 182 | goto exit; | ||
| 183 | |||
| 184 | if (plen >= (int)sizeof(int_val)) | ||
| 185 | memcpy(&int_val, params, sizeof(int_val)); | ||
| 186 | |||
| 187 | switch (actionid) { | ||
| 188 | case IOV_GVAL(IOV_VERSION): | ||
| 189 | /* Need to have checked buffer length */ | ||
| 190 | strncpy((char *)arg, brcmf_version, len); | ||
| 191 | break; | ||
| 192 | |||
| 193 | case IOV_GVAL(IOV_MSGLEVEL): | ||
| 194 | int_val = (s32) brcmf_msg_level; | ||
| 195 | memcpy(arg, &int_val, val_size); | ||
| 196 | break; | ||
| 197 | |||
| 198 | case IOV_SVAL(IOV_MSGLEVEL): | ||
| 199 | brcmf_msg_level = int_val; | ||
| 200 | break; | ||
| 201 | |||
| 202 | case IOV_GVAL(IOV_BCMERRORSTR): | ||
| 203 | strncpy((char *)arg, "bcm_error", | ||
| 204 | BCME_STRLEN); | ||
| 205 | ((char *)arg)[BCME_STRLEN - 1] = 0x00; | ||
| 206 | break; | ||
| 207 | |||
| 208 | case IOV_GVAL(IOV_BCMERROR): | ||
| 209 | int_val = (s32) drvr->bcmerror; | ||
| 210 | memcpy(arg, &int_val, val_size); | ||
| 211 | break; | ||
| 212 | |||
| 213 | case IOV_GVAL(IOV_DUMP): | ||
| 214 | bcmerror = brcmf_c_dump(drvr, arg, len); | ||
| 215 | break; | ||
| 216 | |||
| 217 | case IOV_SVAL(IOV_CLEARCOUNTS): | ||
| 218 | drvr->tx_packets = drvr->rx_packets = 0; | ||
| 219 | drvr->tx_errors = drvr->rx_errors = 0; | ||
| 220 | drvr->tx_ctlpkts = drvr->rx_ctlpkts = 0; | ||
| 221 | drvr->tx_ctlerrs = drvr->rx_ctlerrs = 0; | ||
| 222 | drvr->rx_dropped = 0; | ||
| 223 | drvr->rx_readahead_cnt = 0; | ||
| 224 | drvr->tx_realloc = 0; | ||
| 225 | drvr->wd_dpc_sched = 0; | ||
| 226 | memset(&drvr->dstats, 0, sizeof(drvr->dstats)); | ||
| 227 | brcmf_bus_clearcounts(drvr); | ||
| 228 | break; | ||
| 229 | |||
| 230 | case IOV_GVAL(IOV_IOCTLTIMEOUT):{ | ||
| 231 | int_val = (s32) brcmf_os_get_ioctl_resp_timeout(); | ||
| 232 | memcpy(arg, &int_val, sizeof(int_val)); | ||
| 233 | break; | ||
| 234 | } | ||
| 235 | |||
| 236 | case IOV_SVAL(IOV_IOCTLTIMEOUT):{ | ||
| 237 | if (int_val <= 0) | ||
| 238 | bcmerror = -EINVAL; | ||
| 239 | else | ||
| 240 | brcmf_os_set_ioctl_resp_timeout((unsigned int) | ||
| 241 | int_val); | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | |||
| 245 | default: | ||
| 246 | bcmerror = -ENOTSUPP; | ||
| 247 | break; | ||
| 248 | } | ||
| 249 | |||
| 250 | exit: | ||
| 251 | return bcmerror; | ||
| 252 | } | ||
| 253 | |||
| 254 | bool brcmf_c_prec_enq(struct brcmf_pub *drvr, struct pktq *q, | ||
| 255 | struct sk_buff *pkt, int prec) | ||
| 256 | { | ||
| 257 | struct sk_buff *p; | ||
| 258 | int eprec = -1; /* precedence to evict from */ | ||
| 259 | bool discard_oldest; | ||
| 260 | |||
| 261 | /* Fast case, precedence queue is not full and we are also not | ||
| 262 | * exceeding total queue length | ||
| 263 | */ | ||
| 264 | if (!pktq_pfull(q, prec) && !pktq_full(q)) { | ||
| 265 | brcmu_pktq_penq(q, prec, pkt); | ||
| 266 | return true; | ||
| 267 | } | ||
| 268 | |||
| 269 | /* Determine precedence from which to evict packet, if any */ | ||
| 270 | if (pktq_pfull(q, prec)) | ||
| 271 | eprec = prec; | ||
| 272 | else if (pktq_full(q)) { | ||
| 273 | p = brcmu_pktq_peek_tail(q, &eprec); | ||
| 274 | if (eprec > prec) | ||
| 275 | return false; | ||
| 276 | } | ||
| 277 | |||
| 278 | /* Evict if needed */ | ||
| 279 | if (eprec >= 0) { | ||
| 280 | /* Detect queueing to unconfigured precedence */ | ||
| 281 | discard_oldest = AC_BITMAP_TST(drvr->wme_dp, eprec); | ||
| 282 | if (eprec == prec && !discard_oldest) | ||
| 283 | return false; /* refuse newer (incoming) packet */ | ||
| 284 | /* Evict packet according to discard policy */ | ||
| 285 | p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : | ||
| 286 | brcmu_pktq_pdeq_tail(q, eprec); | ||
| 287 | if (p == NULL) { | ||
| 288 | BRCMF_ERROR(("%s: brcmu_pktq_penq() failed, oldest %d.", | ||
| 289 | __func__, discard_oldest)); | ||
| 290 | } | ||
| 291 | brcmu_pkt_buf_free_skb(p); | ||
| 292 | } | ||
| 293 | |||
| 294 | /* Enqueue */ | ||
| 295 | p = brcmu_pktq_penq(q, prec, pkt); | ||
| 296 | if (p == NULL) { | ||
| 297 | BRCMF_ERROR(("%s: brcmu_pktq_penq() failed.", __func__)); | ||
| 298 | } | ||
| 299 | |||
| 300 | return p != NULL; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int | ||
| 304 | brcmf_c_iovar_op(struct brcmf_pub *drvr, const char *name, | ||
| 305 | void *params, int plen, void *arg, int len, bool set) | ||
| 306 | { | ||
| 307 | int bcmerror = 0; | ||
| 308 | int val_size; | ||
| 309 | const struct brcmu_iovar *vi = NULL; | ||
| 310 | u32 actionid; | ||
| 311 | |||
| 312 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 313 | |||
| 314 | if (name == NULL || len <= 0) | ||
| 315 | return -EINVAL; | ||
| 316 | |||
| 317 | /* Set does not take qualifiers */ | ||
| 318 | if (set && (params || plen)) | ||
| 319 | return -EINVAL; | ||
| 320 | |||
| 321 | /* Get must have return space;*/ | ||
| 322 | if (!set && !(arg && len)) | ||
| 323 | return -EINVAL; | ||
| 324 | |||
| 325 | vi = brcmu_iovar_lookup(brcmf_iovars, name); | ||
| 326 | if (vi == NULL) { | ||
| 327 | bcmerror = -ENOTSUPP; | ||
| 328 | goto exit; | ||
| 329 | } | ||
| 330 | |||
| 331 | BRCMF_CTL(("%s: %s %s, len %d plen %d\n", __func__, | ||
| 332 | name, (set ? "set" : "get"), len, plen)); | ||
| 333 | |||
| 334 | /* set up 'params' pointer in case this is a set command so that | ||
| 335 | * the convenience int and bool code can be common to set and get | ||
| 336 | */ | ||
| 337 | if (params == NULL) { | ||
| 338 | params = arg; | ||
| 339 | plen = len; | ||
| 340 | } | ||
| 341 | |||
| 342 | if (vi->type == IOVT_VOID) | ||
| 343 | val_size = 0; | ||
| 344 | else if (vi->type == IOVT_BUFFER) | ||
| 345 | val_size = len; | ||
| 346 | else | ||
| 347 | /* all other types are integer sized */ | ||
| 348 | val_size = sizeof(int); | ||
| 349 | |||
| 350 | actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); | ||
| 351 | bcmerror = | ||
| 352 | brcmf_c_doiovar(drvr, vi, actionid, name, params, plen, arg, len, | ||
| 353 | val_size); | ||
| 354 | |||
| 355 | exit: | ||
| 356 | return bcmerror; | ||
| 357 | } | ||
| 358 | |||
| 359 | int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc, void *buf, | ||
| 360 | uint buflen) | ||
| 361 | { | ||
| 362 | int bcmerror = 0; | ||
| 363 | |||
| 364 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 365 | |||
| 366 | if (!buf) | ||
| 367 | return -EINVAL; | ||
| 368 | |||
| 369 | switch (ioc->cmd) { | ||
| 370 | case BRCMF_GET_MAGIC: | ||
| 371 | if (buflen < sizeof(int)) | ||
| 372 | bcmerror = -EOVERFLOW; | ||
| 373 | else | ||
| 374 | *(int *)buf = BRCMF_IOCTL_MAGIC; | ||
| 375 | break; | ||
| 376 | |||
| 377 | case BRCMF_GET_VERSION: | ||
| 378 | if (buflen < sizeof(int)) | ||
| 379 | bcmerror = -EOVERFLOW; | ||
| 380 | else | ||
| 381 | *(int *)buf = BRCMF_IOCTL_VERSION; | ||
| 382 | break; | ||
| 383 | |||
| 384 | case BRCMF_GET_VAR: | ||
| 385 | case BRCMF_SET_VAR:{ | ||
| 386 | char *arg; | ||
| 387 | uint arglen; | ||
| 388 | |||
| 389 | /* scan past the name to any arguments */ | ||
| 390 | for (arg = buf, arglen = buflen; *arg && arglen; | ||
| 391 | arg++, arglen--) | ||
| 392 | ; | ||
| 393 | |||
| 394 | if (*arg) { | ||
| 395 | bcmerror = -EOVERFLOW; | ||
| 396 | break; | ||
| 397 | } | ||
| 398 | |||
| 399 | /* account for the NUL terminator */ | ||
| 400 | arg++, arglen--; | ||
| 401 | |||
| 402 | /* call with the appropriate arguments */ | ||
| 403 | if (ioc->cmd == BRCMF_GET_VAR) | ||
| 404 | bcmerror = brcmf_c_iovar_op(drvr, buf, arg, | ||
| 405 | arglen, buf, buflen, IOV_GET); | ||
| 406 | else | ||
| 407 | bcmerror = | ||
| 408 | brcmf_c_iovar_op(drvr, buf, NULL, 0, arg, | ||
| 409 | arglen, IOV_SET); | ||
| 410 | if (bcmerror != -ENOTSUPP) | ||
| 411 | break; | ||
| 412 | |||
| 413 | /* if still not found, try bus module */ | ||
| 414 | if (ioc->cmd == BRCMF_GET_VAR) | ||
| 415 | bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr, | ||
| 416 | buf, arg, arglen, buf, buflen, | ||
| 417 | IOV_GET); | ||
| 418 | else | ||
| 419 | bcmerror = brcmf_sdbrcm_bus_iovar_op(drvr, | ||
| 420 | buf, NULL, 0, arg, arglen, | ||
| 421 | IOV_SET); | ||
| 422 | |||
| 423 | break; | ||
| 424 | } | ||
| 425 | |||
| 426 | default: | ||
| 427 | bcmerror = -ENOTSUPP; | ||
| 428 | } | ||
| 429 | |||
| 430 | return bcmerror; | ||
| 431 | } | ||
| 432 | |||
| 433 | #ifdef SHOW_EVENTS | ||
| 434 | static void | ||
| 435 | brcmf_c_show_host_event(struct brcmf_event_msg *event, void *event_data) | ||
| 436 | { | ||
| 437 | uint i, status, reason; | ||
| 438 | bool group = false, flush_txq = false, link = false; | ||
| 439 | char *auth_str, *event_name; | ||
| 440 | unsigned char *buf; | ||
| 441 | char err_msg[256], eabuf[ETHER_ADDR_STR_LEN]; | ||
| 442 | static struct { | ||
| 443 | uint event; | ||
| 444 | char *event_name; | ||
| 445 | } event_names[] = { | ||
| 446 | { | ||
| 447 | BRCMF_E_SET_SSID, "SET_SSID"}, { | ||
| 448 | BRCMF_E_JOIN, "JOIN"}, { | ||
| 449 | BRCMF_E_START, "START"}, { | ||
| 450 | BRCMF_E_AUTH, "AUTH"}, { | ||
| 451 | BRCMF_E_AUTH_IND, "AUTH_IND"}, { | ||
| 452 | BRCMF_E_DEAUTH, "DEAUTH"}, { | ||
| 453 | BRCMF_E_DEAUTH_IND, "DEAUTH_IND"}, { | ||
| 454 | BRCMF_E_ASSOC, "ASSOC"}, { | ||
| 455 | BRCMF_E_ASSOC_IND, "ASSOC_IND"}, { | ||
| 456 | BRCMF_E_REASSOC, "REASSOC"}, { | ||
| 457 | BRCMF_E_REASSOC_IND, "REASSOC_IND"}, { | ||
| 458 | BRCMF_E_DISASSOC, "DISASSOC"}, { | ||
| 459 | BRCMF_E_DISASSOC_IND, "DISASSOC_IND"}, { | ||
| 460 | BRCMF_E_QUIET_START, "START_QUIET"}, { | ||
| 461 | BRCMF_E_QUIET_END, "END_QUIET"}, { | ||
| 462 | BRCMF_E_BEACON_RX, "BEACON_RX"}, { | ||
| 463 | BRCMF_E_LINK, "LINK"}, { | ||
| 464 | BRCMF_E_MIC_ERROR, "MIC_ERROR"}, { | ||
| 465 | BRCMF_E_NDIS_LINK, "NDIS_LINK"}, { | ||
| 466 | BRCMF_E_ROAM, "ROAM"}, { | ||
| 467 | BRCMF_E_TXFAIL, "TXFAIL"}, { | ||
| 468 | BRCMF_E_PMKID_CACHE, "PMKID_CACHE"}, { | ||
| 469 | BRCMF_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, { | ||
| 470 | BRCMF_E_PRUNE, "PRUNE"}, { | ||
| 471 | BRCMF_E_AUTOAUTH, "AUTOAUTH"}, { | ||
| 472 | BRCMF_E_EAPOL_MSG, "EAPOL_MSG"}, { | ||
| 473 | BRCMF_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, { | ||
| 474 | BRCMF_E_ADDTS_IND, "ADDTS_IND"}, { | ||
| 475 | BRCMF_E_DELTS_IND, "DELTS_IND"}, { | ||
| 476 | BRCMF_E_BCNSENT_IND, "BCNSENT_IND"}, { | ||
| 477 | BRCMF_E_BCNRX_MSG, "BCNRX_MSG"}, { | ||
| 478 | BRCMF_E_BCNLOST_MSG, "BCNLOST_MSG"}, { | ||
| 479 | BRCMF_E_ROAM_PREP, "ROAM_PREP"}, { | ||
| 480 | BRCMF_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, { | ||
| 481 | BRCMF_E_PFN_NET_LOST, "PNO_NET_LOST"}, { | ||
| 482 | BRCMF_E_RESET_COMPLETE, "RESET_COMPLETE"}, { | ||
| 483 | BRCMF_E_JOIN_START, "JOIN_START"}, { | ||
| 484 | BRCMF_E_ROAM_START, "ROAM_START"}, { | ||
| 485 | BRCMF_E_ASSOC_START, "ASSOC_START"}, { | ||
| 486 | BRCMF_E_IBSS_ASSOC, "IBSS_ASSOC"}, { | ||
| 487 | BRCMF_E_RADIO, "RADIO"}, { | ||
| 488 | BRCMF_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, { | ||
| 489 | BRCMF_E_PROBREQ_MSG, "PROBREQ_MSG"}, { | ||
| 490 | BRCMF_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, { | ||
| 491 | BRCMF_E_PSK_SUP, "PSK_SUP"}, { | ||
| 492 | BRCMF_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, { | ||
| 493 | BRCMF_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, { | ||
| 494 | BRCMF_E_ICV_ERROR, "ICV_ERROR"}, { | ||
| 495 | BRCMF_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, { | ||
| 496 | BRCMF_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, { | ||
| 497 | BRCMF_E_TRACE, "TRACE"}, { | ||
| 498 | BRCMF_E_ACTION_FRAME, "ACTION FRAME"}, { | ||
| 499 | BRCMF_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, { | ||
| 500 | BRCMF_E_IF, "IF"}, { | ||
| 501 | BRCMF_E_RSSI, "RSSI"}, { | ||
| 502 | BRCMF_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"} | ||
| 503 | }; | ||
| 504 | uint event_type, flags, auth_type, datalen; | ||
| 505 | event_type = be32_to_cpu(event->event_type); | ||
| 506 | flags = be16_to_cpu(event->flags); | ||
| 507 | status = be32_to_cpu(event->status); | ||
| 508 | reason = be32_to_cpu(event->reason); | ||
| 509 | auth_type = be32_to_cpu(event->auth_type); | ||
| 510 | datalen = be32_to_cpu(event->datalen); | ||
| 511 | /* debug dump of event messages */ | ||
| 512 | sprintf(eabuf, "%pM", event->addr); | ||
| 513 | |||
| 514 | event_name = "UNKNOWN"; | ||
| 515 | for (i = 0; i < ARRAY_SIZE(event_names); i++) { | ||
| 516 | if (event_names[i].event == event_type) | ||
| 517 | event_name = event_names[i].event_name; | ||
| 518 | } | ||
| 519 | |||
| 520 | BRCMF_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type)); | ||
| 521 | BRCMF_EVENT(("flags 0x%04x, status %d, reason %d, auth_type %d" | ||
| 522 | " MAC %s\n", flags, status, reason, auth_type, eabuf)); | ||
| 523 | |||
| 524 | if (flags & BRCMF_EVENT_MSG_LINK) | ||
| 525 | link = true; | ||
| 526 | if (flags & BRCMF_EVENT_MSG_GROUP) | ||
| 527 | group = true; | ||
| 528 | if (flags & BRCMF_EVENT_MSG_FLUSHTXQ) | ||
| 529 | flush_txq = true; | ||
| 530 | |||
| 531 | switch (event_type) { | ||
| 532 | case BRCMF_E_START: | ||
| 533 | case BRCMF_E_DEAUTH: | ||
| 534 | case BRCMF_E_DISASSOC: | ||
| 535 | BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); | ||
| 536 | break; | ||
| 537 | |||
| 538 | case BRCMF_E_ASSOC_IND: | ||
| 539 | case BRCMF_E_REASSOC_IND: | ||
| 540 | BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); | ||
| 541 | break; | ||
| 542 | |||
| 543 | case BRCMF_E_ASSOC: | ||
| 544 | case BRCMF_E_REASSOC: | ||
| 545 | if (status == BRCMF_E_STATUS_SUCCESS) { | ||
| 546 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n", | ||
| 547 | event_name, eabuf)); | ||
| 548 | } else if (status == BRCMF_E_STATUS_TIMEOUT) { | ||
| 549 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n", | ||
| 550 | event_name, eabuf)); | ||
| 551 | } else if (status == BRCMF_E_STATUS_FAIL) { | ||
| 552 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, FAILURE," | ||
| 553 | " reason %d\n", event_name, eabuf, | ||
| 554 | (int)reason)); | ||
| 555 | } else { | ||
| 556 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, unexpected status " | ||
| 557 | "%d\n", event_name, eabuf, (int)status)); | ||
| 558 | } | ||
| 559 | break; | ||
| 560 | |||
| 561 | case BRCMF_E_DEAUTH_IND: | ||
| 562 | case BRCMF_E_DISASSOC_IND: | ||
| 563 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name, | ||
| 564 | eabuf, (int)reason)); | ||
| 565 | break; | ||
| 566 | |||
| 567 | case BRCMF_E_AUTH: | ||
| 568 | case BRCMF_E_AUTH_IND: | ||
| 569 | if (auth_type == WLAN_AUTH_OPEN) | ||
| 570 | auth_str = "Open System"; | ||
| 571 | else if (auth_type == WLAN_AUTH_SHARED_KEY) | ||
| 572 | auth_str = "Shared Key"; | ||
| 573 | else { | ||
| 574 | sprintf(err_msg, "AUTH unknown: %d", (int)auth_type); | ||
| 575 | auth_str = err_msg; | ||
| 576 | } | ||
| 577 | if (event_type == BRCMF_E_AUTH_IND) { | ||
| 578 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name, | ||
| 579 | eabuf, auth_str)); | ||
| 580 | } else if (status == BRCMF_E_STATUS_SUCCESS) { | ||
| 581 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n", | ||
| 582 | event_name, eabuf, auth_str)); | ||
| 583 | } else if (status == BRCMF_E_STATUS_TIMEOUT) { | ||
| 584 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n", | ||
| 585 | event_name, eabuf, auth_str)); | ||
| 586 | } else if (status == BRCMF_E_STATUS_FAIL) { | ||
| 587 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, " | ||
| 588 | "reason %d\n", | ||
| 589 | event_name, eabuf, auth_str, (int)reason)); | ||
| 590 | } | ||
| 591 | |||
| 592 | break; | ||
| 593 | |||
| 594 | case BRCMF_E_JOIN: | ||
| 595 | case BRCMF_E_ROAM: | ||
| 596 | case BRCMF_E_SET_SSID: | ||
| 597 | if (status == BRCMF_E_STATUS_SUCCESS) { | ||
| 598 | BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, | ||
| 599 | eabuf)); | ||
| 600 | } else if (status == BRCMF_E_STATUS_FAIL) { | ||
| 601 | BRCMF_EVENT(("MACEVENT: %s, failed\n", event_name)); | ||
| 602 | } else if (status == BRCMF_E_STATUS_NO_NETWORKS) { | ||
| 603 | BRCMF_EVENT(("MACEVENT: %s, no networks found\n", | ||
| 604 | event_name)); | ||
| 605 | } else { | ||
| 606 | BRCMF_EVENT(("MACEVENT: %s, unexpected status %d\n", | ||
| 607 | event_name, (int)status)); | ||
| 608 | } | ||
| 609 | break; | ||
| 610 | |||
| 611 | case BRCMF_E_BEACON_RX: | ||
| 612 | if (status == BRCMF_E_STATUS_SUCCESS) { | ||
| 613 | BRCMF_EVENT(("MACEVENT: %s, SUCCESS\n", event_name)); | ||
| 614 | } else if (status == BRCMF_E_STATUS_FAIL) { | ||
| 615 | BRCMF_EVENT(("MACEVENT: %s, FAIL\n", event_name)); | ||
| 616 | } else { | ||
| 617 | BRCMF_EVENT(("MACEVENT: %s, status %d\n", event_name, | ||
| 618 | status)); | ||
| 619 | } | ||
| 620 | break; | ||
| 621 | |||
| 622 | case BRCMF_E_LINK: | ||
| 623 | BRCMF_EVENT(("MACEVENT: %s %s\n", event_name, | ||
| 624 | link ? "UP" : "DOWN")); | ||
| 625 | break; | ||
| 626 | |||
| 627 | case BRCMF_E_MIC_ERROR: | ||
| 628 | BRCMF_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n", | ||
| 629 | event_name, eabuf, group, flush_txq)); | ||
| 630 | break; | ||
| 631 | |||
| 632 | case BRCMF_E_ICV_ERROR: | ||
| 633 | case BRCMF_E_UNICAST_DECODE_ERROR: | ||
| 634 | case BRCMF_E_MULTICAST_DECODE_ERROR: | ||
| 635 | BRCMF_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); | ||
| 636 | break; | ||
| 637 | |||
| 638 | case BRCMF_E_TXFAIL: | ||
| 639 | BRCMF_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf)); | ||
| 640 | break; | ||
| 641 | |||
| 642 | case BRCMF_E_SCAN_COMPLETE: | ||
| 643 | case BRCMF_E_PMKID_CACHE: | ||
| 644 | BRCMF_EVENT(("MACEVENT: %s\n", event_name)); | ||
| 645 | break; | ||
| 646 | |||
| 647 | case BRCMF_E_PFN_NET_FOUND: | ||
| 648 | case BRCMF_E_PFN_NET_LOST: | ||
| 649 | case BRCMF_E_PFN_SCAN_COMPLETE: | ||
| 650 | BRCMF_EVENT(("PNOEVENT: %s\n", event_name)); | ||
| 651 | break; | ||
| 652 | |||
| 653 | case BRCMF_E_PSK_SUP: | ||
| 654 | case BRCMF_E_PRUNE: | ||
| 655 | BRCMF_EVENT(("MACEVENT: %s, status %d, reason %d\n", | ||
| 656 | event_name, (int)status, (int)reason)); | ||
| 657 | break; | ||
| 658 | |||
| 659 | case BRCMF_E_TRACE: | ||
| 660 | { | ||
| 661 | static u32 seqnum_prev; | ||
| 662 | struct msgtrace_hdr hdr; | ||
| 663 | u32 nblost; | ||
| 664 | char *s, *p; | ||
| 665 | |||
| 666 | buf = (unsigned char *) event_data; | ||
| 667 | memcpy(&hdr, buf, sizeof(struct msgtrace_hdr)); | ||
| 668 | |||
| 669 | if (hdr.version != MSGTRACE_VERSION) { | ||
| 670 | BRCMF_ERROR( | ||
| 671 | ("\nMACEVENT: %s [unsupported version --> " | ||
| 672 | "brcmf version:%d dongle version:%d]\n", | ||
| 673 | event_name, MSGTRACE_VERSION, hdr.version) | ||
| 674 | ); | ||
| 675 | /* Reset datalen to avoid display below */ | ||
| 676 | datalen = 0; | ||
| 677 | break; | ||
| 678 | } | ||
| 679 | |||
| 680 | /* There are 2 bytes available at the end of data */ | ||
| 681 | *(buf + sizeof(struct msgtrace_hdr) | ||
| 682 | + be16_to_cpu(hdr.len)) = '\0'; | ||
| 683 | |||
| 684 | if (be32_to_cpu(hdr.discarded_bytes) | ||
| 685 | || be32_to_cpu(hdr.discarded_printf)) { | ||
| 686 | BRCMF_ERROR( | ||
| 687 | ("\nWLC_E_TRACE: [Discarded traces in dongle -->" | ||
| 688 | "discarded_bytes %d discarded_printf %d]\n", | ||
| 689 | be32_to_cpu(hdr.discarded_bytes), | ||
| 690 | be32_to_cpu(hdr.discarded_printf))); | ||
| 691 | } | ||
| 692 | |||
| 693 | nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1; | ||
| 694 | if (nblost > 0) { | ||
| 695 | BRCMF_ERROR( | ||
| 696 | ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n", | ||
| 697 | be32_to_cpu(hdr.seqnum), nblost)); | ||
| 698 | } | ||
| 699 | seqnum_prev = be32_to_cpu(hdr.seqnum); | ||
| 700 | |||
| 701 | /* Display the trace buffer. Advance from \n to \n to | ||
| 702 | * avoid display big | ||
| 703 | * printf (issue with Linux printk ) | ||
| 704 | */ | ||
| 705 | p = (char *)&buf[sizeof(struct msgtrace_hdr)]; | ||
| 706 | while ((s = strstr(p, "\n")) != NULL) { | ||
| 707 | *s = '\0'; | ||
| 708 | printk(KERN_DEBUG"%s\n", p); | ||
| 709 | p = s + 1; | ||
| 710 | } | ||
| 711 | printk(KERN_DEBUG "%s\n", p); | ||
| 712 | |||
| 713 | /* Reset datalen to avoid display below */ | ||
| 714 | datalen = 0; | ||
| 715 | } | ||
| 716 | break; | ||
| 717 | |||
| 718 | case BRCMF_E_RSSI: | ||
| 719 | BRCMF_EVENT(("MACEVENT: %s %d\n", event_name, | ||
| 720 | be32_to_cpu(*((int *)event_data)))); | ||
| 721 | break; | ||
| 722 | |||
| 723 | default: | ||
| 724 | BRCMF_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, " | ||
| 725 | "auth %d\n", event_name, event_type, eabuf, | ||
| 726 | (int)status, (int)reason, (int)auth_type)); | ||
| 727 | break; | ||
| 728 | } | ||
| 729 | |||
| 730 | /* show any appended data */ | ||
| 731 | if (datalen) { | ||
| 732 | buf = (unsigned char *) event_data; | ||
| 733 | BRCMF_EVENT((" data (%d) : ", datalen)); | ||
| 734 | for (i = 0; i < datalen; i++) | ||
| 735 | BRCMF_EVENT((" 0x%02x ", *buf++)); | ||
| 736 | BRCMF_EVENT(("\n")); | ||
| 737 | } | ||
| 738 | } | ||
| 739 | #endif /* SHOW_EVENTS */ | ||
| 740 | |||
| 741 | int | ||
| 742 | brcmf_c_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, | ||
| 743 | struct brcmf_event_msg *event, void **data_ptr) | ||
| 744 | { | ||
| 745 | /* check whether packet is a BRCM event pkt */ | ||
| 746 | struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata; | ||
| 747 | char *event_data; | ||
| 748 | u32 type, status; | ||
| 749 | u16 flags; | ||
| 750 | int evlen; | ||
| 751 | |||
| 752 | if (memcmp(BRCM_OUI, &pvt_data->hdr.oui[0], DOT11_OUI_LEN)) { | ||
| 753 | BRCMF_ERROR(("%s: mismatched OUI, bailing\n", __func__)); | ||
| 754 | return -EBADE; | ||
| 755 | } | ||
| 756 | |||
| 757 | /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ | ||
| 758 | if (get_unaligned_be16(&pvt_data->hdr.usr_subtype) != | ||
| 759 | BCMILCP_BCM_SUBTYPE_EVENT) { | ||
| 760 | BRCMF_ERROR(("%s: mismatched subtype, bailing\n", __func__)); | ||
| 761 | return -EBADE; | ||
| 762 | } | ||
| 763 | |||
| 764 | *data_ptr = &pvt_data[1]; | ||
| 765 | event_data = *data_ptr; | ||
| 766 | |||
| 767 | /* memcpy since BRCM event pkt may be unaligned. */ | ||
| 768 | memcpy(event, &pvt_data->msg, sizeof(struct brcmf_event_msg)); | ||
| 769 | |||
| 770 | type = get_unaligned_be32(&event->event_type); | ||
| 771 | flags = get_unaligned_be16(&event->flags); | ||
| 772 | status = get_unaligned_be32(&event->status); | ||
| 773 | evlen = get_unaligned_be32(&event->datalen) + | ||
| 774 | sizeof(struct brcmf_event); | ||
| 775 | |||
| 776 | switch (type) { | ||
| 777 | case BRCMF_E_IF: | ||
| 778 | { | ||
| 779 | struct brcmf_if_event *ifevent = | ||
| 780 | (struct brcmf_if_event *) event_data; | ||
| 781 | BRCMF_TRACE(("%s: if event\n", __func__)); | ||
| 782 | |||
| 783 | if (ifevent->ifidx > 0 && | ||
| 784 | ifevent->ifidx < BRCMF_MAX_IFS) { | ||
| 785 | if (ifevent->action == BRCMF_E_IF_ADD) | ||
| 786 | brcmf_add_if(drvr_priv, ifevent->ifidx, | ||
| 787 | NULL, event->ifname, | ||
| 788 | pvt_data->eth.h_dest, | ||
| 789 | ifevent->flags, | ||
| 790 | ifevent->bssidx); | ||
| 791 | else | ||
| 792 | brcmf_del_if(drvr_priv, ifevent->ifidx); | ||
| 793 | } else { | ||
| 794 | BRCMF_ERROR(("%s: Invalid ifidx %d for %s\n", | ||
| 795 | __func__, ifevent->ifidx, | ||
| 796 | event->ifname)); | ||
| 797 | } | ||
| 798 | } | ||
| 799 | /* send up the if event: btamp user needs it */ | ||
| 800 | *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); | ||
| 801 | break; | ||
| 802 | |||
| 803 | /* These are what external supplicant/authenticator wants */ | ||
| 804 | case BRCMF_E_LINK: | ||
| 805 | case BRCMF_E_ASSOC_IND: | ||
| 806 | case BRCMF_E_REASSOC_IND: | ||
| 807 | case BRCMF_E_DISASSOC_IND: | ||
| 808 | case BRCMF_E_MIC_ERROR: | ||
| 809 | default: | ||
| 810 | /* Fall through: this should get _everything_ */ | ||
| 811 | |||
| 812 | *ifidx = brcmf_ifname2idx(drvr_priv, event->ifname); | ||
| 813 | BRCMF_TRACE(("%s: MAC event %d, flags %x, status %x\n", | ||
| 814 | __func__, type, flags, status)); | ||
| 815 | |||
| 816 | /* put it back to BRCMF_E_NDIS_LINK */ | ||
| 817 | if (type == BRCMF_E_NDIS_LINK) { | ||
| 818 | u32 temp; | ||
| 819 | |||
| 820 | temp = get_unaligned_be32(&event->event_type); | ||
| 821 | BRCMF_TRACE(("Converted to WLC_E_LINK type %d\n", | ||
| 822 | temp)); | ||
| 823 | |||
| 824 | temp = be32_to_cpu(BRCMF_E_NDIS_LINK); | ||
| 825 | memcpy((void *)(&pvt_data->msg.event_type), &temp, | ||
| 826 | sizeof(pvt_data->msg.event_type)); | ||
| 827 | } | ||
| 828 | break; | ||
| 829 | } | ||
| 830 | |||
| 831 | #ifdef SHOW_EVENTS | ||
| 832 | brcmf_c_show_host_event(event, event_data); | ||
| 833 | #endif /* SHOW_EVENTS */ | ||
| 834 | |||
| 835 | return 0; | ||
| 836 | } | ||
| 837 | |||
| 838 | /* Convert user's input in hex pattern to byte-size mask */ | ||
| 839 | static int brcmf_c_pattern_atoh(char *src, char *dst) | ||
| 840 | { | ||
| 841 | int i; | ||
| 842 | if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { | ||
| 843 | BRCMF_ERROR(("Mask invalid format. Needs to start with 0x\n")); | ||
| 844 | return -1; | ||
| 845 | } | ||
| 846 | src = src + 2; /* Skip past 0x */ | ||
| 847 | if (strlen(src) % 2 != 0) { | ||
| 848 | BRCMF_ERROR(("Mask invalid format. Length must be even.\n")); | ||
| 849 | return -1; | ||
| 850 | } | ||
| 851 | for (i = 0; *src != '\0'; i++) { | ||
| 852 | char num[3]; | ||
| 853 | strncpy(num, src, 2); | ||
| 854 | num[2] = '\0'; | ||
| 855 | dst[i] = (u8) simple_strtoul(num, NULL, 16); | ||
| 856 | src += 2; | ||
| 857 | } | ||
| 858 | return i; | ||
| 859 | } | ||
| 860 | |||
| 861 | void | ||
| 862 | brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, | ||
| 863 | int master_mode) | ||
| 864 | { | ||
| 865 | char *argv[8]; | ||
| 866 | int i = 0; | ||
| 867 | const char *str; | ||
| 868 | int buf_len; | ||
| 869 | int str_len; | ||
| 870 | char *arg_save = 0, *arg_org = 0; | ||
| 871 | int rc; | ||
| 872 | char buf[128]; | ||
| 873 | struct brcmf_pkt_filter_enable enable_parm; | ||
| 874 | struct brcmf_pkt_filter_enable *pkt_filterp; | ||
| 875 | |||
| 876 | arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); | ||
| 877 | if (!arg_save) { | ||
| 878 | BRCMF_ERROR(("%s: kmalloc failed\n", __func__)); | ||
| 879 | goto fail; | ||
| 880 | } | ||
| 881 | arg_org = arg_save; | ||
| 882 | memcpy(arg_save, arg, strlen(arg) + 1); | ||
| 883 | |||
| 884 | argv[i] = strsep(&arg_save, " "); | ||
| 885 | |||
| 886 | i = 0; | ||
| 887 | if (NULL == argv[i]) { | ||
| 888 | BRCMF_ERROR(("No args provided\n")); | ||
| 889 | goto fail; | ||
| 890 | } | ||
| 891 | |||
| 892 | str = "pkt_filter_enable"; | ||
| 893 | str_len = strlen(str); | ||
| 894 | strncpy(buf, str, str_len); | ||
| 895 | buf[str_len] = '\0'; | ||
| 896 | buf_len = str_len + 1; | ||
| 897 | |||
| 898 | pkt_filterp = (struct brcmf_pkt_filter_enable *) (buf + str_len + 1); | ||
| 899 | |||
| 900 | /* Parse packet filter id. */ | ||
| 901 | enable_parm.id = simple_strtoul(argv[i], NULL, 0); | ||
| 902 | |||
| 903 | /* Parse enable/disable value. */ | ||
| 904 | enable_parm.enable = enable; | ||
| 905 | |||
| 906 | buf_len += sizeof(enable_parm); | ||
| 907 | memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm)); | ||
| 908 | |||
| 909 | /* Enable/disable the specified filter. */ | ||
| 910 | rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); | ||
| 911 | rc = rc >= 0 ? 0 : rc; | ||
| 912 | if (rc) | ||
| 913 | BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", | ||
| 914 | __func__, arg, rc)); | ||
| 915 | else | ||
| 916 | BRCMF_TRACE(("%s: successfully added pktfilter %s\n", | ||
| 917 | __func__, arg)); | ||
| 918 | |||
| 919 | /* Contorl the master mode */ | ||
| 920 | brcmu_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, | ||
| 921 | sizeof(buf)); | ||
| 922 | rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, | ||
| 923 | sizeof(buf)); | ||
| 924 | rc = rc >= 0 ? 0 : rc; | ||
| 925 | if (rc) | ||
| 926 | BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", | ||
| 927 | __func__, arg, rc)); | ||
| 928 | |||
| 929 | fail: | ||
| 930 | kfree(arg_org); | ||
| 931 | } | ||
| 932 | |||
| 933 | void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) | ||
| 934 | { | ||
| 935 | const char *str; | ||
| 936 | struct brcmf_pkt_filter pkt_filter; | ||
| 937 | struct brcmf_pkt_filter *pkt_filterp; | ||
| 938 | int buf_len; | ||
| 939 | int str_len; | ||
| 940 | int rc; | ||
| 941 | u32 mask_size; | ||
| 942 | u32 pattern_size; | ||
| 943 | char *argv[8], *buf = 0; | ||
| 944 | int i = 0; | ||
| 945 | char *arg_save = 0, *arg_org = 0; | ||
| 946 | |||
| 947 | arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); | ||
| 948 | if (!arg_save) { | ||
| 949 | BRCMF_ERROR(("%s: kmalloc failed\n", __func__)); | ||
| 950 | goto fail; | ||
| 951 | } | ||
| 952 | |||
| 953 | arg_org = arg_save; | ||
| 954 | |||
| 955 | buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); | ||
| 956 | if (!buf) { | ||
| 957 | BRCMF_ERROR(("%s: kmalloc failed\n", __func__)); | ||
| 958 | goto fail; | ||
| 959 | } | ||
| 960 | |||
| 961 | strcpy(arg_save, arg); | ||
| 962 | |||
| 963 | argv[i] = strsep(&arg_save, " "); | ||
| 964 | while (argv[i++]) | ||
| 965 | argv[i] = strsep(&arg_save, " "); | ||
| 966 | |||
| 967 | i = 0; | ||
| 968 | if (NULL == argv[i]) { | ||
| 969 | BRCMF_ERROR(("No args provided\n")); | ||
| 970 | goto fail; | ||
| 971 | } | ||
| 972 | |||
| 973 | str = "pkt_filter_add"; | ||
| 974 | strcpy(buf, str); | ||
| 975 | str_len = strlen(str); | ||
| 976 | buf_len = str_len + 1; | ||
| 977 | |||
| 978 | pkt_filterp = (struct brcmf_pkt_filter *) (buf + str_len + 1); | ||
| 979 | |||
| 980 | /* Parse packet filter id. */ | ||
| 981 | pkt_filter.id = simple_strtoul(argv[i], NULL, 0); | ||
| 982 | |||
| 983 | if (NULL == argv[++i]) { | ||
| 984 | BRCMF_ERROR(("Polarity not provided\n")); | ||
| 985 | goto fail; | ||
| 986 | } | ||
| 987 | |||
| 988 | /* Parse filter polarity. */ | ||
| 989 | pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0); | ||
| 990 | |||
| 991 | if (NULL == argv[++i]) { | ||
| 992 | BRCMF_ERROR(("Filter type not provided\n")); | ||
| 993 | goto fail; | ||
| 994 | } | ||
| 995 | |||
| 996 | /* Parse filter type. */ | ||
| 997 | pkt_filter.type = simple_strtoul(argv[i], NULL, 0); | ||
| 998 | |||
| 999 | if (NULL == argv[++i]) { | ||
| 1000 | BRCMF_ERROR(("Offset not provided\n")); | ||
| 1001 | goto fail; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | /* Parse pattern filter offset. */ | ||
| 1005 | pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0); | ||
| 1006 | |||
| 1007 | if (NULL == argv[++i]) { | ||
| 1008 | BRCMF_ERROR(("Bitmask not provided\n")); | ||
| 1009 | goto fail; | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | /* Parse pattern filter mask. */ | ||
| 1013 | mask_size = | ||
| 1014 | brcmf_c_pattern_atoh | ||
| 1015 | (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern); | ||
| 1016 | |||
| 1017 | if (NULL == argv[++i]) { | ||
| 1018 | BRCMF_ERROR(("Pattern not provided\n")); | ||
| 1019 | goto fail; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | /* Parse pattern filter pattern. */ | ||
| 1023 | pattern_size = | ||
| 1024 | brcmf_c_pattern_atoh(argv[i], | ||
| 1025 | (char *)&pkt_filterp->u.pattern. | ||
| 1026 | mask_and_pattern[mask_size]); | ||
| 1027 | |||
| 1028 | if (mask_size != pattern_size) { | ||
| 1029 | BRCMF_ERROR(("Mask and pattern not the same size\n")); | ||
| 1030 | goto fail; | ||
| 1031 | } | ||
| 1032 | |||
| 1033 | pkt_filter.u.pattern.size_bytes = mask_size; | ||
| 1034 | buf_len += BRCMF_PKT_FILTER_FIXED_LEN; | ||
| 1035 | buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); | ||
| 1036 | |||
| 1037 | /* Keep-alive attributes are set in local | ||
| 1038 | * variable (keep_alive_pkt), and | ||
| 1039 | ** then memcpy'ed into buffer (keep_alive_pktp) since there is no | ||
| 1040 | ** guarantee that the buffer is properly aligned. | ||
| 1041 | */ | ||
| 1042 | memcpy((char *)pkt_filterp, | ||
| 1043 | &pkt_filter, | ||
| 1044 | BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN); | ||
| 1045 | |||
| 1046 | rc = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); | ||
| 1047 | rc = rc >= 0 ? 0 : rc; | ||
| 1048 | |||
| 1049 | if (rc) | ||
| 1050 | BRCMF_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", | ||
| 1051 | __func__, arg, rc)); | ||
| 1052 | else | ||
| 1053 | BRCMF_TRACE(("%s: successfully added pktfilter %s\n", | ||
| 1054 | __func__, arg)); | ||
| 1055 | |||
| 1056 | fail: | ||
| 1057 | kfree(arg_org); | ||
| 1058 | |||
| 1059 | kfree(buf); | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) | ||
| 1063 | { | ||
| 1064 | char iovbuf[32]; | ||
| 1065 | int retcode; | ||
| 1066 | |||
| 1067 | brcmu_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); | ||
| 1068 | retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, | ||
| 1069 | iovbuf, sizeof(iovbuf)); | ||
| 1070 | retcode = retcode >= 0 ? 0 : retcode; | ||
| 1071 | if (retcode) | ||
| 1072 | BRCMF_TRACE(("%s: failed to set ARP offload mode to 0x%x, " | ||
| 1073 | "retcode = %d\n", __func__, arp_mode, retcode)); | ||
| 1074 | else | ||
| 1075 | BRCMF_TRACE(("%s: successfully set ARP offload mode to 0x%x\n", | ||
| 1076 | __func__, arp_mode)); | ||
| 1077 | } | ||
| 1078 | |||
| 1079 | void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) | ||
| 1080 | { | ||
| 1081 | char iovbuf[32]; | ||
| 1082 | int retcode; | ||
| 1083 | |||
| 1084 | brcmu_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf)); | ||
| 1085 | retcode = brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, | ||
| 1086 | iovbuf, sizeof(iovbuf)); | ||
| 1087 | retcode = retcode >= 0 ? 0 : retcode; | ||
| 1088 | if (retcode) | ||
| 1089 | BRCMF_TRACE(("%s: failed to enabe ARP offload to %d, " | ||
| 1090 | "retcode = %d\n", __func__, arp_enable, retcode)); | ||
| 1091 | else | ||
| 1092 | BRCMF_TRACE(("%s: successfully enabed ARP offload to %d\n", | ||
| 1093 | __func__, arp_enable)); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr) | ||
| 1097 | { | ||
| 1098 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for | ||
| 1099 | "event_msgs" + '\0' + bitvec */ | ||
| 1100 | uint up = 0; | ||
| 1101 | char buf[128], *ptr; | ||
| 1102 | uint power_mode = PM_FAST; | ||
| 1103 | u32 dongle_align = BRCMF_SDALIGN; | ||
| 1104 | u32 glom = 0; | ||
| 1105 | uint bcn_timeout = 3; | ||
| 1106 | int scan_assoc_time = 40; | ||
| 1107 | int scan_unassoc_time = 40; | ||
| 1108 | int i; | ||
| 1109 | |||
| 1110 | brcmf_os_proto_block(drvr); | ||
| 1111 | |||
| 1112 | /* Set Country code */ | ||
| 1113 | if (drvr->country_code[0] != 0) { | ||
| 1114 | if (brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_COUNTRY, | ||
| 1115 | drvr->country_code, | ||
| 1116 | sizeof(drvr->country_code)) < 0) { | ||
| 1117 | BRCMF_ERROR(("%s: country code setting failed\n", | ||
| 1118 | __func__)); | ||
| 1119 | } | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | /* query for 'ver' to get version info from firmware */ | ||
| 1123 | memset(buf, 0, sizeof(buf)); | ||
| 1124 | ptr = buf; | ||
| 1125 | brcmu_mkiovar("ver", 0, 0, buf, sizeof(buf)); | ||
| 1126 | brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf)); | ||
| 1127 | strsep(&ptr, "\n"); | ||
| 1128 | /* Print fw version info */ | ||
| 1129 | BRCMF_ERROR(("Firmware version = %s\n", buf)); | ||
| 1130 | |||
| 1131 | /* Set PowerSave mode */ | ||
| 1132 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_PM, (char *)&power_mode, | ||
| 1133 | sizeof(power_mode)); | ||
| 1134 | |||
| 1135 | /* Match Host and Dongle rx alignment */ | ||
| 1136 | brcmu_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, | ||
| 1137 | sizeof(iovbuf)); | ||
| 1138 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | ||
| 1139 | sizeof(iovbuf)); | ||
| 1140 | |||
| 1141 | /* disable glom option per default */ | ||
| 1142 | brcmu_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); | ||
| 1143 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | ||
| 1144 | sizeof(iovbuf)); | ||
| 1145 | |||
| 1146 | /* Setup timeout if Beacons are lost and roam is off to report | ||
| 1147 | link down */ | ||
| 1148 | brcmu_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, | ||
| 1149 | sizeof(iovbuf)); | ||
| 1150 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | ||
| 1151 | sizeof(iovbuf)); | ||
| 1152 | |||
| 1153 | /* Enable/Disable build-in roaming to allowed ext supplicant to take | ||
| 1154 | of romaing */ | ||
| 1155 | brcmu_mkiovar("roam_off", (char *)&brcmf_roam, 4, | ||
| 1156 | iovbuf, sizeof(iovbuf)); | ||
| 1157 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | ||
| 1158 | sizeof(iovbuf)); | ||
| 1159 | |||
| 1160 | /* Force STA UP */ | ||
| 1161 | if (brcmf_radio_up) | ||
| 1162 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_UP, (char *)&up, | ||
| 1163 | sizeof(up)); | ||
| 1164 | |||
| 1165 | /* Setup event_msgs */ | ||
| 1166 | brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, | ||
| 1167 | iovbuf, sizeof(iovbuf)); | ||
| 1168 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | ||
| 1169 | sizeof(iovbuf)); | ||
| 1170 | |||
| 1171 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, | ||
| 1172 | (char *)&scan_assoc_time, sizeof(scan_assoc_time)); | ||
| 1173 | brcmf_proto_cdc_set_ioctl(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, | ||
| 1174 | (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); | ||
| 1175 | |||
| 1176 | /* Set and enable ARP offload feature */ | ||
| 1177 | if (brcmf_arp_enable) | ||
| 1178 | brcmf_c_arp_offload_set(drvr, brcmf_arp_mode); | ||
| 1179 | brcmf_c_arp_offload_enable(drvr, brcmf_arp_enable); | ||
| 1180 | |||
| 1181 | /* Set up pkt filter */ | ||
| 1182 | if (brcmf_pkt_filter_enable) { | ||
| 1183 | for (i = 0; i < drvr->pktfilter_count; i++) { | ||
| 1184 | brcmf_c_pktfilter_offload_set(drvr, | ||
| 1185 | drvr->pktfilter[i]); | ||
| 1186 | brcmf_c_pktfilter_offload_enable(drvr, | ||
| 1187 | drvr->pktfilter[i], | ||
| 1188 | brcmf_pkt_filter_init, | ||
| 1189 | brcmf_master_mode); | ||
| 1190 | } | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | brcmf_os_proto_unblock(drvr); | ||
| 1194 | |||
| 1195 | return 0; | ||
| 1196 | } | ||
| @@ -1,70 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _BRCMF_DBG_H_ | ||
| 18 | #define _BRCMF_DBG_H_ | ||
| 19 | |||
| 20 | #if defined(BCMDBG) | ||
| 21 | |||
| 22 | #define BRCMF_ERROR(args) \ | ||
| 23 | do {if ((brcmf_msg_level & BRCMF_ERROR_VAL) && (net_ratelimit())) \ | ||
| 24 | printk args; } while (0) | ||
| 25 | #define BRCMF_TRACE(args) do {if (brcmf_msg_level & BRCMF_TRACE_VAL) \ | ||
| 26 | printk args; } while (0) | ||
| 27 | #define BRCMF_INFO(args) do {if (brcmf_msg_level & BRCMF_INFO_VAL) \ | ||
| 28 | printk args; } while (0) | ||
| 29 | #define BRCMF_DATA(args) do {if (brcmf_msg_level & BRCMF_DATA_VAL) \ | ||
| 30 | printk args; } while (0) | ||
| 31 | #define BRCMF_CTL(args) do {if (brcmf_msg_level & BRCMF_CTL_VAL) \ | ||
| 32 | printk args; } while (0) | ||
| 33 | #define BRCMF_TIMER(args) do {if (brcmf_msg_level & BRCMF_TIMER_VAL) \ | ||
| 34 | printk args; } while (0) | ||
| 35 | #define BRCMF_INTR(args) do {if (brcmf_msg_level & BRCMF_INTR_VAL) \ | ||
| 36 | printk args; } while (0) | ||
| 37 | #define BRCMF_GLOM(args) do {if (brcmf_msg_level & BRCMF_GLOM_VAL) \ | ||
| 38 | printk args; } while (0) | ||
| 39 | #define BRCMF_EVENT(args) do {if (brcmf_msg_level & BRCMF_EVENT_VAL) \ | ||
| 40 | printk args; } while (0) | ||
| 41 | |||
| 42 | #define BRCMF_DATA_ON() (brcmf_msg_level & BRCMF_DATA_VAL) | ||
| 43 | #define BRCMF_CTL_ON() (brcmf_msg_level & BRCMF_CTL_VAL) | ||
| 44 | #define BRCMF_HDRS_ON() (brcmf_msg_level & BRCMF_HDRS_VAL) | ||
| 45 | #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) | ||
| 46 | #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) | ||
| 47 | |||
| 48 | #else /* (defined BCMDBG) || (defined BCMDBG) */ | ||
| 49 | |||
| 50 | #define BRCMF_ERROR(args) do {if (net_ratelimit()) printk args; } while (0) | ||
| 51 | #define BRCMF_TRACE(args) | ||
| 52 | #define BRCMF_INFO(args) | ||
| 53 | #define BRCMF_DATA(args) | ||
| 54 | #define BRCMF_CTL(args) | ||
| 55 | #define BRCMF_TIMER(args) | ||
| 56 | #define BRCMF_INTR(args) | ||
| 57 | #define BRCMF_GLOM(args) | ||
| 58 | #define BRCMF_EVENT(args) | ||
| 59 | |||
| 60 | #define BRCMF_DATA_ON() 0 | ||
| 61 | #define BRCMF_CTL_ON() 0 | ||
| 62 | #define BRCMF_HDRS_ON() 0 | ||
| 63 | #define BRCMF_BYTES_ON() 0 | ||
| 64 | #define BRCMF_GLOM_ON() 0 | ||
| 65 | |||
| 66 | #endif /* defined(BCMDBG) */ | ||
| 67 | |||
| 68 | extern int brcmf_msg_level; | ||
| 69 | |||
| 70 | #endif /* _BRCMF_DBG_H_ */ | ||
| @@ -1,1736 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/kthread.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/skbuff.h> | ||
| 22 | #include <linux/netdevice.h> | ||
| 23 | #include <linux/etherdevice.h> | ||
| 24 | #include <linux/mmc/sdio_func.h> | ||
| 25 | #include <linux/random.h> | ||
| 26 | #include <linux/spinlock.h> | ||
| 27 | #include <linux/ethtool.h> | ||
| 28 | #include <linux/fcntl.h> | ||
| 29 | #include <linux/fs.h> | ||
| 30 | #include <linux/uaccess.h> | ||
| 31 | #include <linux/interrupt.h> | ||
| 32 | #include <linux/hardirq.h> | ||
| 33 | #include <net/cfg80211.h> | ||
| 34 | #include <defs.h> | ||
| 35 | #include <brcmu_utils.h> | ||
| 36 | #include <brcmu_wifi.h> | ||
| 37 | |||
| 38 | #include "dhd.h" | ||
| 39 | #include "dhd_bus.h" | ||
| 40 | #include "dhd_proto.h" | ||
| 41 | #include "dhd_dbg.h" | ||
| 42 | #include "wl_cfg80211.h" | ||
| 43 | #include "bcmchip.h" | ||
| 44 | |||
| 45 | #if defined(CONFIG_PM_SLEEP) | ||
| 46 | #include <linux/suspend.h> | ||
| 47 | atomic_t brcmf_mmc_suspend; | ||
| 48 | #endif /* defined(CONFIG_PM_SLEEP) */ | ||
| 49 | |||
| 50 | MODULE_AUTHOR("Broadcom Corporation"); | ||
| 51 | MODULE_DESCRIPTION("Broadcom 802.11n wireless LAN fullmac driver."); | ||
| 52 | MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards"); | ||
| 53 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 54 | |||
| 55 | |||
| 56 | /* Interface control information */ | ||
| 57 | struct brcmf_if { | ||
| 58 | struct brcmf_info *info; /* back pointer to brcmf_info */ | ||
| 59 | /* OS/stack specifics */ | ||
| 60 | struct net_device *net; | ||
| 61 | struct net_device_stats stats; | ||
| 62 | int idx; /* iface idx in dongle */ | ||
| 63 | int state; /* interface state */ | ||
| 64 | uint subunit; /* subunit */ | ||
| 65 | u8 mac_addr[ETH_ALEN]; /* assigned MAC address */ | ||
| 66 | bool attached; /* Delayed attachment when unset */ | ||
| 67 | bool txflowcontrol; /* Per interface flow control indicator */ | ||
| 68 | char name[IFNAMSIZ]; /* linux interface name */ | ||
| 69 | }; | ||
| 70 | |||
| 71 | /* Local private structure (extension of pub) */ | ||
| 72 | struct brcmf_info { | ||
| 73 | struct brcmf_pub pub; | ||
| 74 | |||
| 75 | /* OS/stack specifics */ | ||
| 76 | struct brcmf_if *iflist[BRCMF_MAX_IFS]; | ||
| 77 | |||
| 78 | struct semaphore proto_sem; | ||
| 79 | wait_queue_head_t ioctl_resp_wait; | ||
| 80 | |||
| 81 | /* Thread to issue ioctl for multicast */ | ||
| 82 | struct task_struct *sysioc_tsk; | ||
| 83 | struct semaphore sysioc_sem; | ||
| 84 | bool set_multicast; | ||
| 85 | bool set_macaddress; | ||
| 86 | u8 macvalue[ETH_ALEN]; | ||
| 87 | atomic_t pend_8021x_cnt; | ||
| 88 | }; | ||
| 89 | |||
| 90 | /* Error bits */ | ||
| 91 | module_param(brcmf_msg_level, int, 0); | ||
| 92 | |||
| 93 | /* Spawn a thread for system ioctls (set mac, set mcast) */ | ||
| 94 | uint brcmf_sysioc = true; | ||
| 95 | module_param(brcmf_sysioc, uint, 0); | ||
| 96 | |||
| 97 | /* ARP offload agent mode : Enable ARP Host Auto-Reply | ||
| 98 | and ARP Peer Auto-Reply */ | ||
| 99 | uint brcmf_arp_mode = 0xb; | ||
| 100 | module_param(brcmf_arp_mode, uint, 0); | ||
| 101 | |||
| 102 | /* ARP offload enable */ | ||
| 103 | uint brcmf_arp_enable = true; | ||
| 104 | module_param(brcmf_arp_enable, uint, 0); | ||
| 105 | |||
| 106 | /* Global Pkt filter enable control */ | ||
| 107 | uint brcmf_pkt_filter_enable = true; | ||
| 108 | module_param(brcmf_pkt_filter_enable, uint, 0); | ||
| 109 | |||
| 110 | /* Pkt filter init setup */ | ||
| 111 | uint brcmf_pkt_filter_init; | ||
| 112 | module_param(brcmf_pkt_filter_init, uint, 0); | ||
| 113 | |||
| 114 | /* Pkt filter mode control */ | ||
| 115 | uint brcmf_master_mode = true; | ||
| 116 | module_param(brcmf_master_mode, uint, 0); | ||
| 117 | |||
| 118 | module_param(brcmf_dongle_memsize, int, 0); | ||
| 119 | |||
| 120 | /* Contorl fw roaming */ | ||
| 121 | uint brcmf_roam = 1; | ||
| 122 | |||
| 123 | /* Control radio state */ | ||
| 124 | uint brcmf_radio_up = 1; | ||
| 125 | |||
| 126 | /* Network inteface name */ | ||
| 127 | char iface_name[IFNAMSIZ] = "wlan"; | ||
| 128 | module_param_string(iface_name, iface_name, IFNAMSIZ, 0); | ||
| 129 | |||
| 130 | /* The following are specific to the SDIO dongle */ | ||
| 131 | |||
| 132 | /* IOCTL response timeout */ | ||
| 133 | int brcmf_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT; | ||
| 134 | |||
| 135 | /* Idle timeout for backplane clock */ | ||
| 136 | int brcmf_idletime = BRCMF_IDLETIME_TICKS; | ||
| 137 | module_param(brcmf_idletime, int, 0); | ||
| 138 | |||
| 139 | /* Use polling */ | ||
| 140 | uint brcmf_poll; | ||
| 141 | module_param(brcmf_poll, uint, 0); | ||
| 142 | |||
| 143 | /* Use interrupts */ | ||
| 144 | uint brcmf_intr = true; | ||
| 145 | module_param(brcmf_intr, uint, 0); | ||
| 146 | |||
| 147 | /* SDIO Drive Strength (in milliamps) */ | ||
| 148 | uint brcmf_sdiod_drive_strength = 6; | ||
| 149 | module_param(brcmf_sdiod_drive_strength, uint, 0); | ||
| 150 | |||
| 151 | /* Tx/Rx bounds */ | ||
| 152 | module_param(brcmf_txbound, uint, 0); | ||
| 153 | module_param(brcmf_rxbound, uint, 0); | ||
| 154 | |||
| 155 | #ifdef SDTEST | ||
| 156 | /* Echo packet generator (pkts/s) */ | ||
| 157 | uint brcmf_pktgen; | ||
| 158 | module_param(brcmf_pktgen, uint, 0); | ||
| 159 | |||
| 160 | /* Echo packet len (0 => sawtooth, max 2040) */ | ||
| 161 | uint brcmf_pktgen_len; | ||
| 162 | module_param(brcmf_pktgen_len, uint, 0); | ||
| 163 | #endif | ||
| 164 | |||
| 165 | static int brcmf_toe_get(struct brcmf_info *drvr_priv, int idx, u32 *toe_ol); | ||
| 166 | static int brcmf_toe_set(struct brcmf_info *drvr_priv, int idx, u32 toe_ol); | ||
| 167 | static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, | ||
| 168 | struct brcmf_event_msg *event_ptr, | ||
| 169 | void **data_ptr); | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Generalized timeout mechanism. Uses spin sleep with exponential | ||
| 173 | * back-off until | ||
| 174 | * the sleep time reaches one jiffy, then switches over to task delay. Usage: | ||
| 175 | * | ||
| 176 | * brcmf_timeout_start(&tmo, usec); | ||
| 177 | * while (!brcmf_timeout_expired(&tmo)) | ||
| 178 | * if (poll_something()) | ||
| 179 | * break; | ||
| 180 | * if (brcmf_timeout_expired(&tmo)) | ||
| 181 | * fatal(); | ||
| 182 | */ | ||
| 183 | |||
| 184 | void brcmf_timeout_start(struct brcmf_timeout *tmo, uint usec) | ||
| 185 | { | ||
| 186 | tmo->limit = usec; | ||
| 187 | tmo->increment = 0; | ||
| 188 | tmo->elapsed = 0; | ||
| 189 | tmo->tick = 1000000 / HZ; | ||
| 190 | } | ||
| 191 | |||
| 192 | int brcmf_timeout_expired(struct brcmf_timeout *tmo) | ||
| 193 | { | ||
| 194 | /* Does nothing the first call */ | ||
| 195 | if (tmo->increment == 0) { | ||
| 196 | tmo->increment = 1; | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | if (tmo->elapsed >= tmo->limit) | ||
| 201 | return 1; | ||
| 202 | |||
| 203 | /* Add the delay that's about to take place */ | ||
| 204 | tmo->elapsed += tmo->increment; | ||
| 205 | |||
| 206 | if (tmo->increment < tmo->tick) { | ||
| 207 | udelay(tmo->increment); | ||
| 208 | tmo->increment *= 2; | ||
| 209 | if (tmo->increment > tmo->tick) | ||
| 210 | tmo->increment = tmo->tick; | ||
| 211 | } else { | ||
| 212 | wait_queue_head_t delay_wait; | ||
| 213 | DECLARE_WAITQUEUE(wait, current); | ||
| 214 | int pending; | ||
| 215 | init_waitqueue_head(&delay_wait); | ||
| 216 | add_wait_queue(&delay_wait, &wait); | ||
| 217 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 218 | schedule_timeout(1); | ||
| 219 | pending = signal_pending(current); | ||
| 220 | remove_wait_queue(&delay_wait, &wait); | ||
| 221 | set_current_state(TASK_RUNNING); | ||
| 222 | if (pending) | ||
| 223 | return 1; /* Interrupted */ | ||
| 224 | } | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static int brcmf_net2idx(struct brcmf_info *drvr_priv, struct net_device *net) | ||
| 230 | { | ||
| 231 | int i = 0; | ||
| 232 | |||
| 233 | while (i < BRCMF_MAX_IFS) { | ||
| 234 | if (drvr_priv->iflist[i] && (drvr_priv->iflist[i]->net == net)) | ||
| 235 | return i; | ||
| 236 | i++; | ||
| 237 | } | ||
| 238 | |||
| 239 | return BRCMF_BAD_IF; | ||
| 240 | } | ||
| 241 | |||
| 242 | int brcmf_ifname2idx(struct brcmf_info *drvr_priv, char *name) | ||
| 243 | { | ||
| 244 | int i = BRCMF_MAX_IFS; | ||
| 245 | |||
| 246 | if (name == NULL || *name == '\0') | ||
| 247 | return 0; | ||
| 248 | |||
| 249 | while (--i > 0) | ||
| 250 | if (drvr_priv->iflist[i] | ||
| 251 | && !strncmp(drvr_priv->iflist[i]->name, name, IFNAMSIZ)) | ||
| 252 | break; | ||
| 253 | |||
| 254 | BRCMF_TRACE(("%s: return idx %d for \"%s\"\n", __func__, i, name)); | ||
| 255 | |||
| 256 | return i; /* default - the primary interface */ | ||
| 257 | } | ||
| 258 | |||
| 259 | char *brcmf_ifname(struct brcmf_pub *drvr, int ifidx) | ||
| 260 | { | ||
| 261 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 262 | |||
| 263 | if (ifidx < 0 || ifidx >= BRCMF_MAX_IFS) { | ||
| 264 | BRCMF_ERROR(("%s: ifidx %d out of range\n", __func__, ifidx)); | ||
| 265 | return "<if_bad>"; | ||
| 266 | } | ||
| 267 | |||
| 268 | if (drvr_priv->iflist[ifidx] == NULL) { | ||
| 269 | BRCMF_ERROR(("%s: null i/f %d\n", __func__, ifidx)); | ||
| 270 | return "<if_null>"; | ||
| 271 | } | ||
| 272 | |||
| 273 | if (drvr_priv->iflist[ifidx]->net) | ||
| 274 | return drvr_priv->iflist[ifidx]->net->name; | ||
| 275 | |||
| 276 | return "<if_none>"; | ||
| 277 | } | ||
| 278 | |||
| 279 | static void _brcmf_set_multicast_list(struct brcmf_info *drvr_priv, int ifidx) | ||
| 280 | { | ||
| 281 | struct net_device *dev; | ||
| 282 | struct netdev_hw_addr *ha; | ||
| 283 | u32 allmulti, cnt; | ||
| 284 | |||
| 285 | struct brcmf_ioctl ioc; | ||
| 286 | char *buf, *bufp; | ||
| 287 | uint buflen; | ||
| 288 | int ret; | ||
| 289 | |||
| 290 | dev = drvr_priv->iflist[ifidx]->net; | ||
| 291 | cnt = netdev_mc_count(dev); | ||
| 292 | |||
| 293 | /* Determine initial value of allmulti flag */ | ||
| 294 | allmulti = (dev->flags & IFF_ALLMULTI) ? true : false; | ||
| 295 | |||
| 296 | /* Send down the multicast list first. */ | ||
| 297 | |||
| 298 | buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETH_ALEN); | ||
| 299 | bufp = buf = kmalloc(buflen, GFP_ATOMIC); | ||
| 300 | if (!bufp) { | ||
| 301 | BRCMF_ERROR(("%s: out of memory for mcast_list, cnt %d\n", | ||
| 302 | brcmf_ifname(&drvr_priv->pub, ifidx), cnt)); | ||
| 303 | return; | ||
| 304 | } | ||
| 305 | |||
| 306 | strcpy(bufp, "mcast_list"); | ||
| 307 | bufp += strlen("mcast_list") + 1; | ||
| 308 | |||
| 309 | cnt = cpu_to_le32(cnt); | ||
| 310 | memcpy(bufp, &cnt, sizeof(cnt)); | ||
| 311 | bufp += sizeof(cnt); | ||
| 312 | |||
| 313 | netdev_for_each_mc_addr(ha, dev) { | ||
| 314 | if (!cnt) | ||
| 315 | break; | ||
| 316 | memcpy(bufp, ha->addr, ETH_ALEN); | ||
| 317 | bufp += ETH_ALEN; | ||
| 318 | cnt--; | ||
| 319 | } | ||
| 320 | |||
| 321 | memset(&ioc, 0, sizeof(ioc)); | ||
| 322 | ioc.cmd = BRCMF_C_SET_VAR; | ||
| 323 | ioc.buf = buf; | ||
| 324 | ioc.len = buflen; | ||
| 325 | ioc.set = true; | ||
| 326 | |||
| 327 | ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); | ||
| 328 | if (ret < 0) { | ||
| 329 | BRCMF_ERROR(("%s: set mcast_list failed, cnt %d\n", | ||
| 330 | brcmf_ifname(&drvr_priv->pub, ifidx), cnt)); | ||
| 331 | allmulti = cnt ? true : allmulti; | ||
| 332 | } | ||
| 333 | |||
| 334 | kfree(buf); | ||
| 335 | |||
| 336 | /* Now send the allmulti setting. This is based on the setting in the | ||
| 337 | * net_device flags, but might be modified above to be turned on if we | ||
| 338 | * were trying to set some addresses and dongle rejected it... | ||
| 339 | */ | ||
| 340 | |||
| 341 | buflen = sizeof("allmulti") + sizeof(allmulti); | ||
| 342 | buf = kmalloc(buflen, GFP_ATOMIC); | ||
| 343 | if (!buf) { | ||
| 344 | BRCMF_ERROR(("%s: out of memory for allmulti\n", | ||
| 345 | brcmf_ifname(&drvr_priv->pub, ifidx))); | ||
| 346 | return; | ||
| 347 | } | ||
| 348 | allmulti = cpu_to_le32(allmulti); | ||
| 349 | |||
| 350 | if (!brcmu_mkiovar | ||
| 351 | ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) { | ||
| 352 | BRCMF_ERROR(("%s: mkiovar failed for allmulti, datalen %d " | ||
| 353 | "buflen %u\n", | ||
| 354 | brcmf_ifname(&drvr_priv->pub, ifidx), | ||
| 355 | (int)sizeof(allmulti), buflen)); | ||
| 356 | kfree(buf); | ||
| 357 | return; | ||
| 358 | } | ||
| 359 | |||
| 360 | memset(&ioc, 0, sizeof(ioc)); | ||
| 361 | ioc.cmd = BRCMF_C_SET_VAR; | ||
| 362 | ioc.buf = buf; | ||
| 363 | ioc.len = buflen; | ||
| 364 | ioc.set = true; | ||
| 365 | |||
| 366 | ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); | ||
| 367 | if (ret < 0) { | ||
| 368 | BRCMF_ERROR(("%s: set allmulti %d failed\n", | ||
| 369 | brcmf_ifname(&drvr_priv->pub, ifidx), | ||
| 370 | le32_to_cpu(allmulti))); | ||
| 371 | } | ||
| 372 | |||
| 373 | kfree(buf); | ||
| 374 | |||
| 375 | /* Finally, pick up the PROMISC flag as well, like the NIC | ||
| 376 | driver does */ | ||
| 377 | |||
| 378 | allmulti = (dev->flags & IFF_PROMISC) ? true : false; | ||
| 379 | allmulti = cpu_to_le32(allmulti); | ||
| 380 | |||
| 381 | memset(&ioc, 0, sizeof(ioc)); | ||
| 382 | ioc.cmd = BRCMF_C_SET_PROMISC; | ||
| 383 | ioc.buf = &allmulti; | ||
| 384 | ioc.len = sizeof(allmulti); | ||
| 385 | ioc.set = true; | ||
| 386 | |||
| 387 | ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); | ||
| 388 | if (ret < 0) { | ||
| 389 | BRCMF_ERROR(("%s: set promisc %d failed\n", | ||
| 390 | brcmf_ifname(&drvr_priv->pub, ifidx), | ||
| 391 | le32_to_cpu(allmulti))); | ||
| 392 | } | ||
| 393 | } | ||
| 394 | |||
| 395 | static int _brcmf_set_mac_address(struct brcmf_info *drvr_priv, int ifidx, u8 *addr) | ||
| 396 | { | ||
| 397 | char buf[32]; | ||
| 398 | struct brcmf_ioctl ioc; | ||
| 399 | int ret; | ||
| 400 | |||
| 401 | BRCMF_TRACE(("%s enter\n", __func__)); | ||
| 402 | if (!brcmu_mkiovar | ||
| 403 | ("cur_etheraddr", (char *)addr, ETH_ALEN, buf, 32)) { | ||
| 404 | BRCMF_ERROR(("%s: mkiovar failed for cur_etheraddr\n", | ||
| 405 | brcmf_ifname(&drvr_priv->pub, ifidx))); | ||
| 406 | return -1; | ||
| 407 | } | ||
| 408 | memset(&ioc, 0, sizeof(ioc)); | ||
| 409 | ioc.cmd = BRCMF_C_SET_VAR; | ||
| 410 | ioc.buf = buf; | ||
| 411 | ioc.len = 32; | ||
| 412 | ioc.set = true; | ||
| 413 | |||
| 414 | ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); | ||
| 415 | if (ret < 0) { | ||
| 416 | BRCMF_ERROR(("%s: set cur_etheraddr failed\n", | ||
| 417 | brcmf_ifname(&drvr_priv->pub, ifidx))); | ||
| 418 | } else { | ||
| 419 | memcpy(drvr_priv->iflist[ifidx]->net->dev_addr, addr, ETH_ALEN); | ||
| 420 | } | ||
| 421 | |||
| 422 | return ret; | ||
| 423 | } | ||
| 424 | |||
| 425 | #ifdef SOFTAP | ||
| 426 | extern struct net_device *ap_net_dev; | ||
| 427 | #endif | ||
| 428 | |||
| 429 | /* Virtual interfaces only ((ifp && ifp->info && ifp->idx == true) */ | ||
| 430 | static void brcmf_op_if(struct brcmf_if *ifp) | ||
| 431 | { | ||
| 432 | struct brcmf_info *drvr_priv; | ||
| 433 | int ret = 0, err = 0; | ||
| 434 | |||
| 435 | drvr_priv = ifp->info; | ||
| 436 | |||
| 437 | BRCMF_TRACE(("%s: idx %d, state %d\n", __func__, ifp->idx, ifp->state)); | ||
| 438 | |||
| 439 | switch (ifp->state) { | ||
| 440 | case BRCMF_E_IF_ADD: | ||
| 441 | /* | ||
| 442 | * Delete the existing interface before overwriting it | ||
| 443 | * in case we missed the BRCMF_E_IF_DEL event. | ||
| 444 | */ | ||
| 445 | if (ifp->net != NULL) { | ||
| 446 | BRCMF_ERROR(("%s: ERROR: netdev:%s already exists, " | ||
| 447 | "try free & unregister\n", | ||
| 448 | __func__, ifp->net->name)); | ||
| 449 | netif_stop_queue(ifp->net); | ||
| 450 | unregister_netdev(ifp->net); | ||
| 451 | free_netdev(ifp->net); | ||
| 452 | } | ||
| 453 | /* Allocate etherdev, including space for private structure */ | ||
| 454 | ifp->net = alloc_etherdev(sizeof(drvr_priv)); | ||
| 455 | if (!ifp->net) { | ||
| 456 | BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__)); | ||
| 457 | ret = -ENOMEM; | ||
| 458 | } | ||
| 459 | if (ret == 0) { | ||
| 460 | strcpy(ifp->net->name, ifp->name); | ||
| 461 | memcpy(netdev_priv(ifp->net), &drvr_priv, sizeof(drvr_priv)); | ||
| 462 | err = brcmf_net_attach(&drvr_priv->pub, ifp->idx); | ||
| 463 | if (err != 0) { | ||
| 464 | BRCMF_ERROR(("%s: brcmf_net_attach failed, " | ||
| 465 | "err %d\n", | ||
| 466 | __func__, err)); | ||
| 467 | ret = -EOPNOTSUPP; | ||
| 468 | } else { | ||
| 469 | #ifdef SOFTAP | ||
| 470 | /* semaphore that the soft AP CODE | ||
| 471 | waits on */ | ||
| 472 | extern struct semaphore ap_eth_sema; | ||
| 473 | |||
| 474 | /* save ptr to wl0.1 netdev for use | ||
| 475 | in wl_iw.c */ | ||
| 476 | ap_net_dev = ifp->net; | ||
| 477 | /* signal to the SOFTAP 'sleeper' thread, | ||
| 478 | wl0.1 is ready */ | ||
| 479 | up(&ap_eth_sema); | ||
| 480 | #endif | ||
| 481 | BRCMF_TRACE(("\n ==== pid:%x, net_device for " | ||
| 482 | "if:%s created ===\n\n", | ||
| 483 | current->pid, ifp->net->name)); | ||
| 484 | ifp->state = 0; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | break; | ||
| 488 | case BRCMF_E_IF_DEL: | ||
| 489 | if (ifp->net != NULL) { | ||
| 490 | BRCMF_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n", | ||
| 491 | __func__)); | ||
| 492 | netif_stop_queue(ifp->net); | ||
| 493 | unregister_netdev(ifp->net); | ||
| 494 | ret = BRCMF_DEL_IF; /* Make sure the free_netdev() | ||
| 495 | is called */ | ||
| 496 | } | ||
| 497 | break; | ||
| 498 | default: | ||
| 499 | BRCMF_ERROR(("%s: bad op %d\n", __func__, ifp->state)); | ||
| 500 | break; | ||
| 501 | } | ||
| 502 | |||
| 503 | if (ret < 0) { | ||
| 504 | if (ifp->net) | ||
| 505 | free_netdev(ifp->net); | ||
| 506 | |||
| 507 | drvr_priv->iflist[ifp->idx] = NULL; | ||
| 508 | kfree(ifp); | ||
| 509 | #ifdef SOFTAP | ||
| 510 | if (ifp->net == ap_net_dev) | ||
| 511 | ap_net_dev = NULL; /* NULL SOFTAP global | ||
| 512 | wl0.1 as well */ | ||
| 513 | #endif /* SOFTAP */ | ||
| 514 | } | ||
| 515 | } | ||
| 516 | |||
| 517 | static int _brcmf_sysioc_thread(void *data) | ||
| 518 | { | ||
| 519 | struct brcmf_info *drvr_priv = (struct brcmf_info *) data; | ||
| 520 | int i; | ||
| 521 | #ifdef SOFTAP | ||
| 522 | bool in_ap = false; | ||
| 523 | #endif | ||
| 524 | |||
| 525 | allow_signal(SIGTERM); | ||
| 526 | |||
| 527 | while (down_interruptible(&drvr_priv->sysioc_sem) == 0) { | ||
| 528 | if (kthread_should_stop()) | ||
| 529 | break; | ||
| 530 | for (i = 0; i < BRCMF_MAX_IFS; i++) { | ||
| 531 | struct brcmf_if *ifentry = drvr_priv->iflist[i]; | ||
| 532 | if (ifentry) { | ||
| 533 | #ifdef SOFTAP | ||
| 534 | in_ap = (ap_net_dev != NULL); | ||
| 535 | #endif /* SOFTAP */ | ||
| 536 | if (ifentry->state) | ||
| 537 | brcmf_op_if(ifentry); | ||
| 538 | #ifdef SOFTAP | ||
| 539 | if (drvr_priv->iflist[i] == NULL) { | ||
| 540 | BRCMF_TRACE(("\n\n %s: interface %d " | ||
| 541 | "removed!\n", __func__, | ||
| 542 | i)); | ||
| 543 | continue; | ||
| 544 | } | ||
| 545 | |||
| 546 | if (in_ap && drvr_priv->set_macaddress) { | ||
| 547 | BRCMF_TRACE(("attempt to set MAC for" | ||
| 548 | " %s in AP Mode," | ||
| 549 | " blocked.\n", | ||
| 550 | ifentry->net->name)); | ||
| 551 | drvr_priv->set_macaddress = false; | ||
| 552 | continue; | ||
| 553 | } | ||
| 554 | |||
| 555 | if (in_ap && drvr_priv->set_multicast) { | ||
| 556 | BRCMF_TRACE(("attempt to set MULTICAST " | ||
| 557 | "list for %s in AP Mode, " | ||
| 558 | "blocked.\n", | ||
| 559 | ifentry->net->name)); | ||
| 560 | drvr_priv->set_multicast = false; | ||
| 561 | continue; | ||
| 562 | } | ||
| 563 | #endif /* SOFTAP */ | ||
| 564 | if (drvr_priv->set_multicast) { | ||
| 565 | drvr_priv->set_multicast = false; | ||
| 566 | _brcmf_set_multicast_list(drvr_priv, i); | ||
| 567 | } | ||
| 568 | if (drvr_priv->set_macaddress) { | ||
| 569 | drvr_priv->set_macaddress = false; | ||
| 570 | _brcmf_set_mac_address(drvr_priv, i, | ||
| 571 | drvr_priv->macvalue); | ||
| 572 | } | ||
| 573 | } | ||
| 574 | } | ||
| 575 | } | ||
| 576 | return 0; | ||
| 577 | } | ||
| 578 | |||
| 579 | static int brcmf_netdev_set_mac_address(struct net_device *dev, void *addr) | ||
| 580 | { | ||
| 581 | int ret = 0; | ||
| 582 | |||
| 583 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev); | ||
| 584 | struct sockaddr *sa = (struct sockaddr *)addr; | ||
| 585 | int ifidx; | ||
| 586 | |||
| 587 | ifidx = brcmf_net2idx(drvr_priv, dev); | ||
| 588 | if (ifidx == BRCMF_BAD_IF) | ||
| 589 | return -1; | ||
| 590 | |||
| 591 | memcpy(&drvr_priv->macvalue, sa->sa_data, ETH_ALEN); | ||
| 592 | drvr_priv->set_macaddress = true; | ||
| 593 | up(&drvr_priv->sysioc_sem); | ||
| 594 | |||
| 595 | return ret; | ||
| 596 | } | ||
| 597 | |||
| 598 | static void brcmf_netdev_set_multicast_list(struct net_device *dev) | ||
| 599 | { | ||
| 600 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(dev); | ||
| 601 | int ifidx; | ||
| 602 | |||
| 603 | ifidx = brcmf_net2idx(drvr_priv, dev); | ||
| 604 | if (ifidx == BRCMF_BAD_IF) | ||
| 605 | return; | ||
| 606 | |||
| 607 | drvr_priv->set_multicast = true; | ||
| 608 | up(&drvr_priv->sysioc_sem); | ||
| 609 | } | ||
| 610 | |||
| 611 | int brcmf_sendpkt(struct brcmf_pub *drvr, int ifidx, struct sk_buff *pktbuf) | ||
| 612 | { | ||
| 613 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 614 | |||
| 615 | /* Reject if down */ | ||
| 616 | if (!drvr->up || (drvr->busstate == BRCMF_BUS_DOWN)) | ||
| 617 | return -ENODEV; | ||
| 618 | |||
| 619 | /* Update multicast statistic */ | ||
| 620 | if (pktbuf->len >= ETH_ALEN) { | ||
| 621 | u8 *pktdata = (u8 *) (pktbuf->data); | ||
| 622 | struct ethhdr *eh = (struct ethhdr *)pktdata; | ||
| 623 | |||
| 624 | if (is_multicast_ether_addr(eh->h_dest)) | ||
| 625 | drvr->tx_multicast++; | ||
| 626 | if (ntohs(eh->h_proto) == ETH_P_PAE) | ||
| 627 | atomic_inc(&drvr_priv->pend_8021x_cnt); | ||
| 628 | } | ||
| 629 | |||
| 630 | /* If the protocol uses a data header, apply it */ | ||
| 631 | brcmf_proto_hdrpush(drvr, ifidx, pktbuf); | ||
| 632 | |||
| 633 | /* Use bus module to send data frame */ | ||
| 634 | return brcmf_sdbrcm_bus_txdata(drvr->bus, pktbuf); | ||
| 635 | } | ||
| 636 | |||
| 637 | static int brcmf_netdev_start_xmit(struct sk_buff *skb, struct net_device *net) | ||
| 638 | { | ||
| 639 | int ret; | ||
| 640 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net); | ||
| 641 | int ifidx; | ||
| 642 | |||
| 643 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 644 | |||
| 645 | /* Reject if down */ | ||
| 646 | if (!drvr_priv->pub.up || (drvr_priv->pub.busstate == BRCMF_BUS_DOWN)) { | ||
| 647 | BRCMF_ERROR(("%s: xmit rejected pub.up=%d busstate=%d\n", | ||
| 648 | __func__, drvr_priv->pub.up, | ||
| 649 | drvr_priv->pub.busstate)); | ||
| 650 | netif_stop_queue(net); | ||
| 651 | return -ENODEV; | ||
| 652 | } | ||
| 653 | |||
| 654 | ifidx = brcmf_net2idx(drvr_priv, net); | ||
| 655 | if (ifidx == BRCMF_BAD_IF) { | ||
| 656 | BRCMF_ERROR(("%s: bad ifidx %d\n", __func__, ifidx)); | ||
| 657 | netif_stop_queue(net); | ||
| 658 | return -ENODEV; | ||
| 659 | } | ||
| 660 | |||
| 661 | /* Make sure there's enough room for any header */ | ||
| 662 | if (skb_headroom(skb) < drvr_priv->pub.hdrlen) { | ||
| 663 | struct sk_buff *skb2; | ||
| 664 | |||
| 665 | BRCMF_INFO(("%s: insufficient headroom\n", | ||
| 666 | brcmf_ifname(&drvr_priv->pub, ifidx))); | ||
| 667 | drvr_priv->pub.tx_realloc++; | ||
| 668 | skb2 = skb_realloc_headroom(skb, drvr_priv->pub.hdrlen); | ||
| 669 | dev_kfree_skb(skb); | ||
| 670 | skb = skb2; | ||
| 671 | if (skb == NULL) { | ||
| 672 | BRCMF_ERROR(("%s: skb_realloc_headroom failed\n", | ||
| 673 | brcmf_ifname(&drvr_priv->pub, ifidx))); | ||
| 674 | ret = -ENOMEM; | ||
| 675 | goto done; | ||
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | ret = brcmf_sendpkt(&drvr_priv->pub, ifidx, skb); | ||
| 680 | |||
| 681 | done: | ||
| 682 | if (ret) | ||
| 683 | drvr_priv->pub.dstats.tx_dropped++; | ||
| 684 | else | ||
| 685 | drvr_priv->pub.tx_packets++; | ||
| 686 | |||
| 687 | /* Return ok: we always eat the packet */ | ||
| 688 | return 0; | ||
| 689 | } | ||
| 690 | |||
| 691 | void brcmf_txflowcontrol(struct brcmf_pub *drvr, int ifidx, bool state) | ||
| 692 | { | ||
| 693 | struct net_device *net; | ||
| 694 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 695 | |||
| 696 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 697 | |||
| 698 | drvr->txoff = state; | ||
| 699 | net = drvr_priv->iflist[ifidx]->net; | ||
| 700 | if (state == ON) | ||
| 701 | netif_stop_queue(net); | ||
| 702 | else | ||
| 703 | netif_wake_queue(net); | ||
| 704 | } | ||
| 705 | |||
| 706 | void brcmf_rx_frame(struct brcmf_pub *drvr, int ifidx, struct sk_buff *skb, | ||
| 707 | int numpkt) | ||
| 708 | { | ||
| 709 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 710 | unsigned char *eth; | ||
| 711 | uint len; | ||
| 712 | void *data; | ||
| 713 | struct sk_buff *pnext, *save_pktbuf; | ||
| 714 | int i; | ||
| 715 | struct brcmf_if *ifp; | ||
| 716 | struct brcmf_event_msg event; | ||
| 717 | |||
| 718 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 719 | |||
| 720 | save_pktbuf = skb; | ||
| 721 | |||
| 722 | for (i = 0; skb && i < numpkt; i++, skb = pnext) { | ||
| 723 | |||
| 724 | pnext = skb->next; | ||
| 725 | skb->next = NULL; | ||
| 726 | |||
| 727 | /* Get the protocol, maintain skb around eth_type_trans() | ||
| 728 | * The main reason for this hack is for the limitation of | ||
| 729 | * Linux 2.4 where 'eth_type_trans' uses the | ||
| 730 | * 'net->hard_header_len' | ||
| 731 | * to perform skb_pull inside vs ETH_HLEN. Since to avoid | ||
| 732 | * coping of the packet coming from the network stack to add | ||
| 733 | * BDC, Hardware header etc, during network interface | ||
| 734 | * registration | ||
| 735 | * we set the 'net->hard_header_len' to ETH_HLEN + extra space | ||
| 736 | * required | ||
| 737 | * for BDC, Hardware header etc. and not just the ETH_HLEN | ||
| 738 | */ | ||
| 739 | eth = skb->data; | ||
| 740 | len = skb->len; | ||
| 741 | |||
| 742 | ifp = drvr_priv->iflist[ifidx]; | ||
| 743 | if (ifp == NULL) | ||
| 744 | ifp = drvr_priv->iflist[0]; | ||
| 745 | |||
| 746 | skb->dev = ifp->net; | ||
| 747 | skb->protocol = eth_type_trans(skb, skb->dev); | ||
| 748 | |||
| 749 | if (skb->pkt_type == PACKET_MULTICAST) | ||
| 750 | drvr_priv->pub.rx_multicast++; | ||
| 751 | |||
| 752 | skb->data = eth; | ||
| 753 | skb->len = len; | ||
| 754 | |||
| 755 | /* Strip header, count, deliver upward */ | ||
| 756 | skb_pull(skb, ETH_HLEN); | ||
| 757 | |||
| 758 | /* Process special event packets and then discard them */ | ||
| 759 | if (ntohs(skb->protocol) == ETH_P_LINK_CTL) | ||
| 760 | brcmf_host_event(drvr_priv, &ifidx, | ||
| 761 | skb_mac_header(skb), | ||
| 762 | &event, &data); | ||
| 763 | |||
| 764 | if (drvr_priv->iflist[ifidx] && | ||
| 765 | !drvr_priv->iflist[ifidx]->state) | ||
| 766 | ifp = drvr_priv->iflist[ifidx]; | ||
| 767 | |||
| 768 | if (ifp->net) | ||
| 769 | ifp->net->last_rx = jiffies; | ||
| 770 | |||
| 771 | drvr->dstats.rx_bytes += skb->len; | ||
| 772 | drvr->rx_packets++; /* Local count */ | ||
| 773 | |||
| 774 | if (in_interrupt()) { | ||
| 775 | netif_rx(skb); | ||
| 776 | } else { | ||
| 777 | /* If the receive is not processed inside an ISR, | ||
| 778 | * the softirqd must be woken explicitly to service | ||
| 779 | * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled | ||
| 780 | * by netif_rx_ni(), but in earlier kernels, we need | ||
| 781 | * to do it manually. | ||
| 782 | */ | ||
| 783 | netif_rx_ni(skb); | ||
| 784 | } | ||
| 785 | } | ||
| 786 | } | ||
| 787 | |||
| 788 | void brcmf_txcomplete(struct brcmf_pub *drvr, struct sk_buff *txp, bool success) | ||
| 789 | { | ||
| 790 | uint ifidx; | ||
| 791 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 792 | struct ethhdr *eh; | ||
| 793 | u16 type; | ||
| 794 | |||
| 795 | brcmf_proto_hdrpull(drvr, &ifidx, txp); | ||
| 796 | |||
| 797 | eh = (struct ethhdr *)(txp->data); | ||
| 798 | type = ntohs(eh->h_proto); | ||
| 799 | |||
| 800 | if (type == ETH_P_PAE) | ||
| 801 | atomic_dec(&drvr_priv->pend_8021x_cnt); | ||
| 802 | |||
| 803 | } | ||
| 804 | |||
| 805 | static struct net_device_stats *brcmf_netdev_get_stats(struct net_device *net) | ||
| 806 | { | ||
| 807 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net); | ||
| 808 | struct brcmf_if *ifp; | ||
| 809 | int ifidx; | ||
| 810 | |||
| 811 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 812 | |||
| 813 | ifidx = brcmf_net2idx(drvr_priv, net); | ||
| 814 | if (ifidx == BRCMF_BAD_IF) | ||
| 815 | return NULL; | ||
| 816 | |||
| 817 | ifp = drvr_priv->iflist[ifidx]; | ||
| 818 | |||
| 819 | if (drvr_priv->pub.up) { | ||
| 820 | /* Use the protocol to get dongle stats */ | ||
| 821 | brcmf_proto_dstats(&drvr_priv->pub); | ||
| 822 | } | ||
| 823 | |||
| 824 | /* Copy dongle stats to net device stats */ | ||
| 825 | ifp->stats.rx_packets = drvr_priv->pub.dstats.rx_packets; | ||
| 826 | ifp->stats.tx_packets = drvr_priv->pub.dstats.tx_packets; | ||
| 827 | ifp->stats.rx_bytes = drvr_priv->pub.dstats.rx_bytes; | ||
| 828 | ifp->stats.tx_bytes = drvr_priv->pub.dstats.tx_bytes; | ||
| 829 | ifp->stats.rx_errors = drvr_priv->pub.dstats.rx_errors; | ||
| 830 | ifp->stats.tx_errors = drvr_priv->pub.dstats.tx_errors; | ||
| 831 | ifp->stats.rx_dropped = drvr_priv->pub.dstats.rx_dropped; | ||
| 832 | ifp->stats.tx_dropped = drvr_priv->pub.dstats.tx_dropped; | ||
| 833 | ifp->stats.multicast = drvr_priv->pub.dstats.multicast; | ||
| 834 | |||
| 835 | return &ifp->stats; | ||
| 836 | } | ||
| 837 | |||
| 838 | /* Retrieve current toe component enables, which are kept | ||
| 839 | as a bitmap in toe_ol iovar */ | ||
| 840 | static int brcmf_toe_get(struct brcmf_info *drvr_priv, int ifidx, u32 *toe_ol) | ||
| 841 | { | ||
| 842 | struct brcmf_ioctl ioc; | ||
| 843 | char buf[32]; | ||
| 844 | int ret; | ||
| 845 | |||
| 846 | memset(&ioc, 0, sizeof(ioc)); | ||
| 847 | |||
| 848 | ioc.cmd = BRCMF_C_GET_VAR; | ||
| 849 | ioc.buf = buf; | ||
| 850 | ioc.len = (uint) sizeof(buf); | ||
| 851 | ioc.set = false; | ||
| 852 | |||
| 853 | strcpy(buf, "toe_ol"); | ||
| 854 | ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); | ||
| 855 | if (ret < 0) { | ||
| 856 | /* Check for older dongle image that doesn't support toe_ol */ | ||
| 857 | if (ret == -EIO) { | ||
| 858 | BRCMF_ERROR(("%s: toe not supported by device\n", | ||
| 859 | brcmf_ifname(&drvr_priv->pub, ifidx))); | ||
| 860 | return -EOPNOTSUPP; | ||
| 861 | } | ||
| 862 | |||
| 863 | BRCMF_INFO(("%s: could not get toe_ol: ret=%d\n", | ||
| 864 | brcmf_ifname(&drvr_priv->pub, ifidx), ret)); | ||
| 865 | return ret; | ||
| 866 | } | ||
| 867 | |||
| 868 | memcpy(toe_ol, buf, sizeof(u32)); | ||
| 869 | return 0; | ||
| 870 | } | ||
| 871 | |||
| 872 | /* Set current toe component enables in toe_ol iovar, | ||
| 873 | and set toe global enable iovar */ | ||
| 874 | static int brcmf_toe_set(struct brcmf_info *drvr_priv, int ifidx, u32 toe_ol) | ||
| 875 | { | ||
| 876 | struct brcmf_ioctl ioc; | ||
| 877 | char buf[32]; | ||
| 878 | int toe, ret; | ||
| 879 | |||
| 880 | memset(&ioc, 0, sizeof(ioc)); | ||
| 881 | |||
| 882 | ioc.cmd = BRCMF_C_SET_VAR; | ||
| 883 | ioc.buf = buf; | ||
| 884 | ioc.len = (uint) sizeof(buf); | ||
| 885 | ioc.set = true; | ||
| 886 | |||
| 887 | /* Set toe_ol as requested */ | ||
| 888 | |||
| 889 | strcpy(buf, "toe_ol"); | ||
| 890 | memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(u32)); | ||
| 891 | |||
| 892 | ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); | ||
| 893 | if (ret < 0) { | ||
| 894 | BRCMF_ERROR(("%s: could not set toe_ol: ret=%d\n", | ||
| 895 | brcmf_ifname(&drvr_priv->pub, ifidx), ret)); | ||
| 896 | return ret; | ||
| 897 | } | ||
| 898 | |||
| 899 | /* Enable toe globally only if any components are enabled. */ | ||
| 900 | |||
| 901 | toe = (toe_ol != 0); | ||
| 902 | |||
| 903 | strcpy(buf, "toe"); | ||
| 904 | memcpy(&buf[sizeof("toe")], &toe, sizeof(u32)); | ||
| 905 | |||
| 906 | ret = brcmf_proto_ioctl(&drvr_priv->pub, ifidx, &ioc, ioc.buf, ioc.len); | ||
| 907 | if (ret < 0) { | ||
| 908 | BRCMF_ERROR(("%s: could not set toe: ret=%d\n", | ||
| 909 | brcmf_ifname(&drvr_priv->pub, ifidx), ret)); | ||
| 910 | return ret; | ||
| 911 | } | ||
| 912 | |||
| 913 | return 0; | ||
| 914 | } | ||
| 915 | |||
| 916 | static void brcmf_ethtool_get_drvinfo(struct net_device *net, | ||
| 917 | struct ethtool_drvinfo *info) | ||
| 918 | { | ||
| 919 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net); | ||
| 920 | |||
| 921 | sprintf(info->driver, KBUILD_MODNAME); | ||
| 922 | sprintf(info->version, "%lu", drvr_priv->pub.drv_version); | ||
| 923 | sprintf(info->fw_version, "%s", BCM4329_FW_NAME); | ||
| 924 | sprintf(info->bus_info, "%s", | ||
| 925 | dev_name(&brcmf_cfg80211_get_sdio_func()->dev)); | ||
| 926 | } | ||
| 927 | |||
| 928 | struct ethtool_ops brcmf_ethtool_ops = { | ||
| 929 | .get_drvinfo = brcmf_ethtool_get_drvinfo | ||
| 930 | }; | ||
| 931 | |||
| 932 | static int brcmf_ethtool(struct brcmf_info *drvr_priv, void *uaddr) | ||
| 933 | { | ||
| 934 | struct ethtool_drvinfo info; | ||
| 935 | char drvname[sizeof(info.driver)]; | ||
| 936 | u32 cmd; | ||
| 937 | struct ethtool_value edata; | ||
| 938 | u32 toe_cmpnt, csum_dir; | ||
| 939 | int ret; | ||
| 940 | |||
| 941 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 942 | |||
| 943 | /* all ethtool calls start with a cmd word */ | ||
| 944 | if (copy_from_user(&cmd, uaddr, sizeof(u32))) | ||
| 945 | return -EFAULT; | ||
| 946 | |||
| 947 | switch (cmd) { | ||
| 948 | case ETHTOOL_GDRVINFO: | ||
| 949 | /* Copy out any request driver name */ | ||
| 950 | if (copy_from_user(&info, uaddr, sizeof(info))) | ||
| 951 | return -EFAULT; | ||
| 952 | strncpy(drvname, info.driver, sizeof(info.driver)); | ||
| 953 | drvname[sizeof(info.driver) - 1] = '\0'; | ||
| 954 | |||
| 955 | /* clear struct for return */ | ||
| 956 | memset(&info, 0, sizeof(info)); | ||
| 957 | info.cmd = cmd; | ||
| 958 | |||
| 959 | /* if requested, identify ourselves */ | ||
| 960 | if (strcmp(drvname, "?dhd") == 0) { | ||
| 961 | sprintf(info.driver, "dhd"); | ||
| 962 | strcpy(info.version, BRCMF_VERSION_STR); | ||
| 963 | } | ||
| 964 | |||
| 965 | /* otherwise, require dongle to be up */ | ||
| 966 | else if (!drvr_priv->pub.up) { | ||
| 967 | BRCMF_ERROR(("%s: dongle is not up\n", __func__)); | ||
| 968 | return -ENODEV; | ||
| 969 | } | ||
| 970 | |||
| 971 | /* finally, report dongle driver type */ | ||
| 972 | else if (drvr_priv->pub.iswl) | ||
| 973 | sprintf(info.driver, "wl"); | ||
| 974 | else | ||
| 975 | sprintf(info.driver, "xx"); | ||
| 976 | |||
| 977 | sprintf(info.version, "%lu", drvr_priv->pub.drv_version); | ||
| 978 | if (copy_to_user(uaddr, &info, sizeof(info))) | ||
| 979 | return -EFAULT; | ||
| 980 | BRCMF_CTL(("%s: given %*s, returning %s\n", __func__, | ||
| 981 | (int)sizeof(drvname), drvname, info.driver)); | ||
| 982 | break; | ||
| 983 | |||
| 984 | /* Get toe offload components from dongle */ | ||
| 985 | case ETHTOOL_GRXCSUM: | ||
| 986 | case ETHTOOL_GTXCSUM: | ||
| 987 | ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); | ||
| 988 | if (ret < 0) | ||
| 989 | return ret; | ||
| 990 | |||
| 991 | csum_dir = | ||
| 992 | (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; | ||
| 993 | |||
| 994 | edata.cmd = cmd; | ||
| 995 | edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; | ||
| 996 | |||
| 997 | if (copy_to_user(uaddr, &edata, sizeof(edata))) | ||
| 998 | return -EFAULT; | ||
| 999 | break; | ||
| 1000 | |||
| 1001 | /* Set toe offload components in dongle */ | ||
| 1002 | case ETHTOOL_SRXCSUM: | ||
| 1003 | case ETHTOOL_STXCSUM: | ||
| 1004 | if (copy_from_user(&edata, uaddr, sizeof(edata))) | ||
| 1005 | return -EFAULT; | ||
| 1006 | |||
| 1007 | /* Read the current settings, update and write back */ | ||
| 1008 | ret = brcmf_toe_get(drvr_priv, 0, &toe_cmpnt); | ||
| 1009 | if (ret < 0) | ||
| 1010 | return ret; | ||
| 1011 | |||
| 1012 | csum_dir = | ||
| 1013 | (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; | ||
| 1014 | |||
| 1015 | if (edata.data != 0) | ||
| 1016 | toe_cmpnt |= csum_dir; | ||
| 1017 | else | ||
| 1018 | toe_cmpnt &= ~csum_dir; | ||
| 1019 | |||
| 1020 | ret = brcmf_toe_set(drvr_priv, 0, toe_cmpnt); | ||
| 1021 | if (ret < 0) | ||
| 1022 | return ret; | ||
| 1023 | |||
| 1024 | /* If setting TX checksum mode, tell Linux the new mode */ | ||
| 1025 | if (cmd == ETHTOOL_STXCSUM) { | ||
| 1026 | if (edata.data) | ||
| 1027 | drvr_priv->iflist[0]->net->features |= | ||
| 1028 | NETIF_F_IP_CSUM; | ||
| 1029 | else | ||
| 1030 | drvr_priv->iflist[0]->net->features &= | ||
| 1031 | ~NETIF_F_IP_CSUM; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | break; | ||
| 1035 | |||
| 1036 | default: | ||
| 1037 | return -EOPNOTSUPP; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | return 0; | ||
| 1041 | } | ||
| 1042 | |||
| 1043 | static int brcmf_netdev_ioctl_entry(struct net_device *net, struct ifreq *ifr, | ||
| 1044 | int cmd) | ||
| 1045 | { | ||
| 1046 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net); | ||
| 1047 | struct brcmf_c_ioctl ioc; | ||
| 1048 | int bcmerror = 0; | ||
| 1049 | int buflen = 0; | ||
| 1050 | void *buf = NULL; | ||
| 1051 | uint driver = 0; | ||
| 1052 | int ifidx; | ||
| 1053 | bool is_set_key_cmd; | ||
| 1054 | |||
| 1055 | ifidx = brcmf_net2idx(drvr_priv, net); | ||
| 1056 | BRCMF_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __func__, ifidx, cmd)); | ||
| 1057 | |||
| 1058 | if (ifidx == BRCMF_BAD_IF) | ||
| 1059 | return -1; | ||
| 1060 | |||
| 1061 | if (cmd == SIOCETHTOOL) | ||
| 1062 | return brcmf_ethtool(drvr_priv, (void *)ifr->ifr_data); | ||
| 1063 | |||
| 1064 | if (cmd != SIOCDEVPRIVATE) | ||
| 1065 | return -EOPNOTSUPP; | ||
| 1066 | |||
| 1067 | memset(&ioc, 0, sizeof(ioc)); | ||
| 1068 | |||
| 1069 | /* Copy the ioc control structure part of ioctl request */ | ||
| 1070 | if (copy_from_user(&ioc, ifr->ifr_data, sizeof(struct brcmf_ioctl))) { | ||
| 1071 | bcmerror = -EINVAL; | ||
| 1072 | goto done; | ||
| 1073 | } | ||
| 1074 | |||
| 1075 | /* Copy out any buffer passed */ | ||
| 1076 | if (ioc.buf) { | ||
| 1077 | buflen = min_t(int, ioc.len, BRCMF_IOCTL_MAXLEN); | ||
| 1078 | /* optimization for direct ioctl calls from kernel */ | ||
| 1079 | /* | ||
| 1080 | if (segment_eq(get_fs(), KERNEL_DS)) { | ||
| 1081 | buf = ioc.buf; | ||
| 1082 | } else { | ||
| 1083 | */ | ||
| 1084 | { | ||
| 1085 | buf = kmalloc(buflen, GFP_ATOMIC); | ||
| 1086 | if (!buf) { | ||
| 1087 | bcmerror = -ENOMEM; | ||
| 1088 | goto done; | ||
| 1089 | } | ||
| 1090 | if (copy_from_user(buf, ioc.buf, buflen)) { | ||
| 1091 | bcmerror = -EINVAL; | ||
| 1092 | goto done; | ||
| 1093 | } | ||
| 1094 | } | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | /* To differentiate read 4 more byes */ | ||
| 1098 | if ((copy_from_user(&driver, (char *)ifr->ifr_data + | ||
| 1099 | sizeof(struct brcmf_ioctl), sizeof(uint)) != 0)) { | ||
| 1100 | bcmerror = -EINVAL; | ||
| 1101 | goto done; | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | if (!capable(CAP_NET_ADMIN)) { | ||
| 1105 | bcmerror = -EPERM; | ||
| 1106 | goto done; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | /* check for local brcmf ioctl and handle it */ | ||
| 1110 | if (driver == BRCMF_IOCTL_MAGIC) { | ||
| 1111 | bcmerror = brcmf_c_ioctl((void *)&drvr_priv->pub, &ioc, buf, buflen); | ||
| 1112 | if (bcmerror) | ||
| 1113 | drvr_priv->pub.bcmerror = bcmerror; | ||
| 1114 | goto done; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | /* send to dongle (must be up, and wl) */ | ||
| 1118 | if ((drvr_priv->pub.busstate != BRCMF_BUS_DATA)) { | ||
| 1119 | BRCMF_ERROR(("%s DONGLE_DOWN,__func__\n", __func__)); | ||
| 1120 | bcmerror = -EIO; | ||
| 1121 | goto done; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | if (!drvr_priv->pub.iswl) { | ||
| 1125 | bcmerror = -EIO; | ||
| 1126 | goto done; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | /* | ||
| 1130 | * Intercept BRCMF_C_SET_KEY IOCTL - serialize M4 send and | ||
| 1131 | * set key IOCTL to prevent M4 encryption. | ||
| 1132 | */ | ||
| 1133 | is_set_key_cmd = ((ioc.cmd == BRCMF_C_SET_KEY) || | ||
| 1134 | ((ioc.cmd == BRCMF_C_SET_VAR) && | ||
| 1135 | !(strncmp("wsec_key", ioc.buf, 9))) || | ||
| 1136 | ((ioc.cmd == BRCMF_C_SET_VAR) && | ||
| 1137 | !(strncmp("bsscfg:wsec_key", ioc.buf, 15)))); | ||
| 1138 | if (is_set_key_cmd) | ||
| 1139 | brcmf_netdev_wait_pend8021x(net); | ||
| 1140 | |||
| 1141 | bcmerror = | ||
| 1142 | brcmf_proto_ioctl(&drvr_priv->pub, ifidx, (struct brcmf_ioctl *)&ioc, | ||
| 1143 | buf, buflen); | ||
| 1144 | |||
| 1145 | done: | ||
| 1146 | if (!bcmerror && buf && ioc.buf) { | ||
| 1147 | if (copy_to_user(ioc.buf, buf, buflen)) | ||
| 1148 | bcmerror = -EFAULT; | ||
| 1149 | } | ||
| 1150 | |||
| 1151 | kfree(buf); | ||
| 1152 | |||
| 1153 | if (bcmerror > 0) | ||
| 1154 | bcmerror = 0; | ||
| 1155 | |||
| 1156 | return bcmerror; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | static int brcmf_netdev_stop(struct net_device *net) | ||
| 1160 | { | ||
| 1161 | #if !defined(IGNORE_ETH0_DOWN) | ||
| 1162 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net); | ||
| 1163 | |||
| 1164 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1165 | brcmf_cfg80211_down(); | ||
| 1166 | if (drvr_priv->pub.up == 0) | ||
| 1167 | return 0; | ||
| 1168 | |||
| 1169 | /* Set state and stop OS transmissions */ | ||
| 1170 | drvr_priv->pub.up = 0; | ||
| 1171 | netif_stop_queue(net); | ||
| 1172 | #else | ||
| 1173 | BRCMF_ERROR(("BYPASS %s:due to BRCM compilation: under investigation\n", | ||
| 1174 | __func__)); | ||
| 1175 | #endif /* !defined(IGNORE_ETH0_DOWN) */ | ||
| 1176 | |||
| 1177 | return 0; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | static int brcmf_netdev_open(struct net_device *net) | ||
| 1181 | { | ||
| 1182 | struct brcmf_info *drvr_priv = *(struct brcmf_info **) netdev_priv(net); | ||
| 1183 | u32 toe_ol; | ||
| 1184 | int ifidx = brcmf_net2idx(drvr_priv, net); | ||
| 1185 | s32 ret = 0; | ||
| 1186 | |||
| 1187 | BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx)); | ||
| 1188 | |||
| 1189 | if (ifidx == 0) { /* do it only for primary eth0 */ | ||
| 1190 | |||
| 1191 | /* try to bring up bus */ | ||
| 1192 | ret = brcmf_bus_start(&drvr_priv->pub); | ||
| 1193 | if (ret != 0) { | ||
| 1194 | BRCMF_ERROR(("%s: failed with code %d\n", | ||
| 1195 | __func__, ret)); | ||
| 1196 | return -1; | ||
| 1197 | } | ||
| 1198 | atomic_set(&drvr_priv->pend_8021x_cnt, 0); | ||
| 1199 | |||
| 1200 | memcpy(net->dev_addr, drvr_priv->pub.mac, ETH_ALEN); | ||
| 1201 | |||
| 1202 | /* Get current TOE mode from dongle */ | ||
| 1203 | if (brcmf_toe_get(drvr_priv, ifidx, &toe_ol) >= 0 | ||
| 1204 | && (toe_ol & TOE_TX_CSUM_OL) != 0) | ||
| 1205 | drvr_priv->iflist[ifidx]->net->features |= | ||
| 1206 | NETIF_F_IP_CSUM; | ||
| 1207 | else | ||
| 1208 | drvr_priv->iflist[ifidx]->net->features &= | ||
| 1209 | ~NETIF_F_IP_CSUM; | ||
| 1210 | } | ||
| 1211 | /* Allow transmit calls */ | ||
| 1212 | netif_start_queue(net); | ||
| 1213 | drvr_priv->pub.up = 1; | ||
| 1214 | if (unlikely(brcmf_cfg80211_up())) { | ||
| 1215 | BRCMF_ERROR(("%s: failed to bring up cfg80211\n", | ||
| 1216 | __func__)); | ||
| 1217 | return -1; | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | return ret; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | int | ||
| 1224 | brcmf_add_if(struct brcmf_info *drvr_priv, int ifidx, void *handle, char *name, | ||
| 1225 | u8 *mac_addr, u32 flags, u8 bssidx) | ||
| 1226 | { | ||
| 1227 | struct brcmf_if *ifp; | ||
| 1228 | |||
| 1229 | BRCMF_TRACE(("%s: idx %d, handle->%p\n", __func__, ifidx, handle)); | ||
| 1230 | |||
| 1231 | ifp = drvr_priv->iflist[ifidx]; | ||
| 1232 | if (!ifp) { | ||
| 1233 | ifp = kmalloc(sizeof(struct brcmf_if), GFP_ATOMIC); | ||
| 1234 | if (!ifp) { | ||
| 1235 | BRCMF_ERROR(("%s: OOM - struct brcmf_if\n", __func__)); | ||
| 1236 | return -ENOMEM; | ||
| 1237 | } | ||
| 1238 | } | ||
| 1239 | |||
| 1240 | memset(ifp, 0, sizeof(struct brcmf_if)); | ||
| 1241 | ifp->info = drvr_priv; | ||
| 1242 | drvr_priv->iflist[ifidx] = ifp; | ||
| 1243 | strlcpy(ifp->name, name, IFNAMSIZ); | ||
| 1244 | if (mac_addr != NULL) | ||
| 1245 | memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); | ||
| 1246 | |||
| 1247 | if (handle == NULL) { | ||
| 1248 | ifp->state = BRCMF_E_IF_ADD; | ||
| 1249 | ifp->idx = ifidx; | ||
| 1250 | up(&drvr_priv->sysioc_sem); | ||
| 1251 | } else | ||
| 1252 | ifp->net = (struct net_device *)handle; | ||
| 1253 | |||
| 1254 | return 0; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | void brcmf_del_if(struct brcmf_info *drvr_priv, int ifidx) | ||
| 1258 | { | ||
| 1259 | struct brcmf_if *ifp; | ||
| 1260 | |||
| 1261 | BRCMF_TRACE(("%s: idx %d\n", __func__, ifidx)); | ||
| 1262 | |||
| 1263 | ifp = drvr_priv->iflist[ifidx]; | ||
| 1264 | if (!ifp) { | ||
| 1265 | BRCMF_ERROR(("%s: Null interface\n", __func__)); | ||
| 1266 | return; | ||
| 1267 | } | ||
| 1268 | |||
| 1269 | ifp->state = BRCMF_E_IF_DEL; | ||
| 1270 | ifp->idx = ifidx; | ||
| 1271 | up(&drvr_priv->sysioc_sem); | ||
| 1272 | } | ||
| 1273 | |||
| 1274 | struct brcmf_pub *brcmf_attach(struct brcmf_bus *bus, uint bus_hdrlen) | ||
| 1275 | { | ||
| 1276 | struct brcmf_info *drvr_priv = NULL; | ||
| 1277 | struct net_device *net; | ||
| 1278 | |||
| 1279 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1280 | |||
| 1281 | /* Allocate etherdev, including space for private structure */ | ||
| 1282 | net = alloc_etherdev(sizeof(drvr_priv)); | ||
| 1283 | if (!net) { | ||
| 1284 | BRCMF_ERROR(("%s: OOM - alloc_etherdev\n", __func__)); | ||
| 1285 | goto fail; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | /* Allocate primary brcmf_info */ | ||
| 1289 | drvr_priv = kzalloc(sizeof(struct brcmf_info), GFP_ATOMIC); | ||
| 1290 | if (!drvr_priv) { | ||
| 1291 | BRCMF_ERROR(("%s: OOM - alloc brcmf_info\n", __func__)); | ||
| 1292 | goto fail; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | /* | ||
| 1296 | * Save the brcmf_info into the priv | ||
| 1297 | */ | ||
| 1298 | memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv)); | ||
| 1299 | |||
| 1300 | /* Set network interface name if it was provided as module parameter */ | ||
| 1301 | if (iface_name[0]) { | ||
| 1302 | int len; | ||
| 1303 | char ch; | ||
| 1304 | strncpy(net->name, iface_name, IFNAMSIZ); | ||
| 1305 | net->name[IFNAMSIZ - 1] = 0; | ||
| 1306 | len = strlen(net->name); | ||
| 1307 | ch = net->name[len - 1]; | ||
| 1308 | if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) | ||
| 1309 | strcat(net->name, "%d"); | ||
| 1310 | } | ||
| 1311 | |||
| 1312 | if (brcmf_add_if(drvr_priv, 0, (void *)net, net->name, NULL, 0, 0) == | ||
| 1313 | BRCMF_BAD_IF) | ||
| 1314 | goto fail; | ||
| 1315 | |||
| 1316 | net->netdev_ops = NULL; | ||
| 1317 | sema_init(&drvr_priv->proto_sem, 1); | ||
| 1318 | /* Initialize other structure content */ | ||
| 1319 | init_waitqueue_head(&drvr_priv->ioctl_resp_wait); | ||
| 1320 | |||
| 1321 | /* Link to info module */ | ||
| 1322 | drvr_priv->pub.info = drvr_priv; | ||
| 1323 | |||
| 1324 | /* Link to bus module */ | ||
| 1325 | drvr_priv->pub.bus = bus; | ||
| 1326 | drvr_priv->pub.hdrlen = bus_hdrlen; | ||
| 1327 | |||
| 1328 | /* Attach and link in the protocol */ | ||
| 1329 | if (brcmf_proto_attach(&drvr_priv->pub) != 0) { | ||
| 1330 | BRCMF_ERROR(("brcmf_prot_attach failed\n")); | ||
| 1331 | goto fail; | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | /* Attach and link in the cfg80211 */ | ||
| 1335 | if (unlikely(brcmf_cfg80211_attach(net, &drvr_priv->pub))) { | ||
| 1336 | BRCMF_ERROR(("wl_cfg80211_attach failed\n")); | ||
| 1337 | goto fail; | ||
| 1338 | } | ||
| 1339 | |||
| 1340 | if (brcmf_sysioc) { | ||
| 1341 | sema_init(&drvr_priv->sysioc_sem, 0); | ||
| 1342 | drvr_priv->sysioc_tsk = kthread_run(_brcmf_sysioc_thread, drvr_priv, | ||
| 1343 | "_brcmf_sysioc"); | ||
| 1344 | if (IS_ERR(drvr_priv->sysioc_tsk)) { | ||
| 1345 | printk(KERN_WARNING | ||
| 1346 | "_brcmf_sysioc thread failed to start\n"); | ||
| 1347 | drvr_priv->sysioc_tsk = NULL; | ||
| 1348 | } | ||
| 1349 | } else | ||
| 1350 | drvr_priv->sysioc_tsk = NULL; | ||
| 1351 | |||
| 1352 | /* | ||
| 1353 | * Save the brcmf_info into the priv | ||
| 1354 | */ | ||
| 1355 | memcpy(netdev_priv(net), &drvr_priv, sizeof(drvr_priv)); | ||
| 1356 | |||
| 1357 | #if defined(CONFIG_PM_SLEEP) | ||
| 1358 | atomic_set(&brcmf_mmc_suspend, false); | ||
| 1359 | #endif /* defined(CONFIG_PM_SLEEP) */ | ||
| 1360 | return &drvr_priv->pub; | ||
| 1361 | |||
| 1362 | fail: | ||
| 1363 | if (net) | ||
| 1364 | free_netdev(net); | ||
| 1365 | if (drvr_priv) | ||
| 1366 | brcmf_detach(&drvr_priv->pub); | ||
| 1367 | |||
| 1368 | return NULL; | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | int brcmf_bus_start(struct brcmf_pub *drvr) | ||
| 1372 | { | ||
| 1373 | int ret = -1; | ||
| 1374 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 1375 | /* Room for "event_msgs" + '\0' + bitvec */ | ||
| 1376 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; | ||
| 1377 | |||
| 1378 | BRCMF_TRACE(("%s:\n", __func__)); | ||
| 1379 | |||
| 1380 | /* Bring up the bus */ | ||
| 1381 | ret = brcmf_sdbrcm_bus_init(&drvr_priv->pub, true); | ||
| 1382 | if (ret != 0) { | ||
| 1383 | BRCMF_ERROR(("%s, brcmf_sdbrcm_bus_init failed %d\n", __func__, | ||
| 1384 | ret)); | ||
| 1385 | return ret; | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | /* If bus is not ready, can't come up */ | ||
| 1389 | if (drvr_priv->pub.busstate != BRCMF_BUS_DATA) { | ||
| 1390 | BRCMF_ERROR(("%s failed bus is not ready\n", __func__)); | ||
| 1391 | return -ENODEV; | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | brcmu_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, | ||
| 1395 | iovbuf, sizeof(iovbuf)); | ||
| 1396 | brcmf_proto_cdc_query_ioctl(drvr, 0, BRCMF_C_GET_VAR, iovbuf, | ||
| 1397 | sizeof(iovbuf)); | ||
| 1398 | memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); | ||
| 1399 | |||
| 1400 | setbit(drvr->eventmask, BRCMF_E_SET_SSID); | ||
| 1401 | setbit(drvr->eventmask, BRCMF_E_PRUNE); | ||
| 1402 | setbit(drvr->eventmask, BRCMF_E_AUTH); | ||
| 1403 | setbit(drvr->eventmask, BRCMF_E_REASSOC); | ||
| 1404 | setbit(drvr->eventmask, BRCMF_E_REASSOC_IND); | ||
| 1405 | setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND); | ||
| 1406 | setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND); | ||
| 1407 | setbit(drvr->eventmask, BRCMF_E_DISASSOC); | ||
| 1408 | setbit(drvr->eventmask, BRCMF_E_JOIN); | ||
| 1409 | setbit(drvr->eventmask, BRCMF_E_ASSOC_IND); | ||
| 1410 | setbit(drvr->eventmask, BRCMF_E_PSK_SUP); | ||
| 1411 | setbit(drvr->eventmask, BRCMF_E_LINK); | ||
| 1412 | setbit(drvr->eventmask, BRCMF_E_NDIS_LINK); | ||
| 1413 | setbit(drvr->eventmask, BRCMF_E_MIC_ERROR); | ||
| 1414 | setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE); | ||
| 1415 | setbit(drvr->eventmask, BRCMF_E_TXFAIL); | ||
| 1416 | setbit(drvr->eventmask, BRCMF_E_JOIN_START); | ||
| 1417 | setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE); | ||
| 1418 | |||
| 1419 | /* enable dongle roaming event */ | ||
| 1420 | |||
| 1421 | drvr->pktfilter_count = 1; | ||
| 1422 | /* Setup filter to allow only unicast */ | ||
| 1423 | drvr->pktfilter[0] = "100 0 0 0 0x01 0x00"; | ||
| 1424 | |||
| 1425 | /* Bus is ready, do any protocol initialization */ | ||
| 1426 | ret = brcmf_proto_init(&drvr_priv->pub); | ||
| 1427 | if (ret < 0) | ||
| 1428 | return ret; | ||
| 1429 | |||
| 1430 | return 0; | ||
| 1431 | } | ||
| 1432 | |||
| 1433 | static struct net_device_ops brcmf_netdev_ops_pri = { | ||
| 1434 | .ndo_open = brcmf_netdev_open, | ||
| 1435 | .ndo_stop = brcmf_netdev_stop, | ||
| 1436 | .ndo_get_stats = brcmf_netdev_get_stats, | ||
| 1437 | .ndo_do_ioctl = brcmf_netdev_ioctl_entry, | ||
| 1438 | .ndo_start_xmit = brcmf_netdev_start_xmit, | ||
| 1439 | .ndo_set_mac_address = brcmf_netdev_set_mac_address, | ||
| 1440 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list, | ||
| 1441 | }; | ||
| 1442 | |||
| 1443 | int brcmf_net_attach(struct brcmf_pub *drvr, int ifidx) | ||
| 1444 | { | ||
| 1445 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 1446 | struct net_device *net; | ||
| 1447 | u8 temp_addr[ETH_ALEN] = { | ||
| 1448 | 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33}; | ||
| 1449 | |||
| 1450 | BRCMF_TRACE(("%s: ifidx %d\n", __func__, ifidx)); | ||
| 1451 | |||
| 1452 | net = drvr_priv->iflist[ifidx]->net; | ||
| 1453 | net->netdev_ops = &brcmf_netdev_ops_pri; | ||
| 1454 | |||
| 1455 | /* | ||
| 1456 | * We have to use the primary MAC for virtual interfaces | ||
| 1457 | */ | ||
| 1458 | if (ifidx != 0) { | ||
| 1459 | /* for virtual interfaces use the primary MAC */ | ||
| 1460 | memcpy(temp_addr, drvr_priv->pub.mac, ETH_ALEN); | ||
| 1461 | |||
| 1462 | } | ||
| 1463 | |||
| 1464 | if (ifidx == 1) { | ||
| 1465 | BRCMF_TRACE(("%s ACCESS POINT MAC:\n", __func__)); | ||
| 1466 | /* ACCESSPOINT INTERFACE CASE */ | ||
| 1467 | temp_addr[0] |= 0X02; /* set bit 2 , | ||
| 1468 | - Locally Administered address */ | ||
| 1469 | |||
| 1470 | } | ||
| 1471 | net->hard_header_len = ETH_HLEN + drvr_priv->pub.hdrlen; | ||
| 1472 | net->ethtool_ops = &brcmf_ethtool_ops; | ||
| 1473 | |||
| 1474 | drvr_priv->pub.rxsz = net->mtu + net->hard_header_len + | ||
| 1475 | drvr_priv->pub.hdrlen; | ||
| 1476 | |||
| 1477 | memcpy(net->dev_addr, temp_addr, ETH_ALEN); | ||
| 1478 | |||
| 1479 | if (register_netdev(net) != 0) { | ||
| 1480 | BRCMF_ERROR(("%s: couldn't register the net device\n", | ||
| 1481 | __func__)); | ||
| 1482 | goto fail; | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | BRCMF_INFO(("%s: Broadcom Dongle Host Driver\n", net->name)); | ||
| 1486 | |||
| 1487 | return 0; | ||
| 1488 | |||
| 1489 | fail: | ||
| 1490 | net->netdev_ops = NULL; | ||
| 1491 | return -EBADE; | ||
| 1492 | } | ||
| 1493 | |||
| 1494 | static void brcmf_bus_detach(struct brcmf_pub *drvr) | ||
| 1495 | { | ||
| 1496 | struct brcmf_info *drvr_priv; | ||
| 1497 | |||
| 1498 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1499 | |||
| 1500 | if (drvr) { | ||
| 1501 | drvr_priv = drvr->info; | ||
| 1502 | if (drvr_priv) { | ||
| 1503 | /* Stop the protocol module */ | ||
| 1504 | brcmf_proto_stop(&drvr_priv->pub); | ||
| 1505 | |||
| 1506 | /* Stop the bus module */ | ||
| 1507 | brcmf_sdbrcm_bus_stop(drvr_priv->pub.bus, true); | ||
| 1508 | } | ||
| 1509 | } | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | void brcmf_detach(struct brcmf_pub *drvr) | ||
| 1513 | { | ||
| 1514 | struct brcmf_info *drvr_priv; | ||
| 1515 | |||
| 1516 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1517 | |||
| 1518 | if (drvr) { | ||
| 1519 | drvr_priv = drvr->info; | ||
| 1520 | if (drvr_priv) { | ||
| 1521 | struct brcmf_if *ifp; | ||
| 1522 | int i; | ||
| 1523 | |||
| 1524 | for (i = 1; i < BRCMF_MAX_IFS; i++) | ||
| 1525 | if (drvr_priv->iflist[i]) | ||
| 1526 | brcmf_del_if(drvr_priv, i); | ||
| 1527 | |||
| 1528 | ifp = drvr_priv->iflist[0]; | ||
| 1529 | if (ifp->net->netdev_ops == &brcmf_netdev_ops_pri) { | ||
| 1530 | brcmf_netdev_stop(ifp->net); | ||
| 1531 | unregister_netdev(ifp->net); | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | if (drvr_priv->sysioc_tsk) { | ||
| 1535 | send_sig(SIGTERM, drvr_priv->sysioc_tsk, 1); | ||
| 1536 | kthread_stop(drvr_priv->sysioc_tsk); | ||
| 1537 | drvr_priv->sysioc_tsk = NULL; | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | brcmf_bus_detach(drvr); | ||
| 1541 | |||
| 1542 | if (drvr->prot) | ||
| 1543 | brcmf_proto_detach(drvr); | ||
| 1544 | |||
| 1545 | brcmf_cfg80211_detach(); | ||
| 1546 | |||
| 1547 | free_netdev(ifp->net); | ||
| 1548 | kfree(ifp); | ||
| 1549 | kfree(drvr_priv); | ||
| 1550 | } | ||
| 1551 | } | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | static void __exit brcmf_module_cleanup(void) | ||
| 1555 | { | ||
| 1556 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1557 | |||
| 1558 | brcmf_bus_unregister(); | ||
| 1559 | } | ||
| 1560 | |||
| 1561 | static int __init brcmf_module_init(void) | ||
| 1562 | { | ||
| 1563 | int error; | ||
| 1564 | |||
| 1565 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1566 | |||
| 1567 | error = brcmf_bus_register(); | ||
| 1568 | |||
| 1569 | if (error) { | ||
| 1570 | BRCMF_ERROR(("%s: brcmf_bus_register failed\n", __func__)); | ||
| 1571 | goto failed; | ||
| 1572 | } | ||
| 1573 | return 0; | ||
| 1574 | |||
| 1575 | failed: | ||
| 1576 | return -EINVAL; | ||
| 1577 | } | ||
| 1578 | |||
| 1579 | module_init(brcmf_module_init); | ||
| 1580 | module_exit(brcmf_module_cleanup); | ||
| 1581 | |||
| 1582 | int brcmf_os_proto_block(struct brcmf_pub *drvr) | ||
| 1583 | { | ||
| 1584 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 1585 | |||
| 1586 | if (drvr_priv) { | ||
| 1587 | down(&drvr_priv->proto_sem); | ||
| 1588 | return 1; | ||
| 1589 | } | ||
| 1590 | return 0; | ||
| 1591 | } | ||
| 1592 | |||
| 1593 | int brcmf_os_proto_unblock(struct brcmf_pub *drvr) | ||
| 1594 | { | ||
| 1595 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 1596 | |||
| 1597 | if (drvr_priv) { | ||
| 1598 | up(&drvr_priv->proto_sem); | ||
| 1599 | return 1; | ||
| 1600 | } | ||
| 1601 | |||
| 1602 | return 0; | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | unsigned int brcmf_os_get_ioctl_resp_timeout(void) | ||
| 1606 | { | ||
| 1607 | return (unsigned int)brcmf_ioctl_timeout_msec; | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | void brcmf_os_set_ioctl_resp_timeout(unsigned int timeout_msec) | ||
| 1611 | { | ||
| 1612 | brcmf_ioctl_timeout_msec = (int)timeout_msec; | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | int brcmf_os_ioctl_resp_wait(struct brcmf_pub *drvr, uint *condition, | ||
| 1616 | bool *pending) | ||
| 1617 | { | ||
| 1618 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 1619 | DECLARE_WAITQUEUE(wait, current); | ||
| 1620 | int timeout = brcmf_ioctl_timeout_msec; | ||
| 1621 | |||
| 1622 | /* Convert timeout in millsecond to jiffies */ | ||
| 1623 | timeout = timeout * HZ / 1000; | ||
| 1624 | |||
| 1625 | /* Wait until control frame is available */ | ||
| 1626 | add_wait_queue(&drvr_priv->ioctl_resp_wait, &wait); | ||
| 1627 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 1628 | |||
| 1629 | while (!(*condition) && (!signal_pending(current) && timeout)) | ||
| 1630 | timeout = schedule_timeout(timeout); | ||
| 1631 | |||
| 1632 | if (signal_pending(current)) | ||
| 1633 | *pending = true; | ||
| 1634 | |||
| 1635 | set_current_state(TASK_RUNNING); | ||
| 1636 | remove_wait_queue(&drvr_priv->ioctl_resp_wait, &wait); | ||
| 1637 | |||
| 1638 | return timeout; | ||
| 1639 | } | ||
| 1640 | |||
| 1641 | int brcmf_os_ioctl_resp_wake(struct brcmf_pub *drvr) | ||
| 1642 | { | ||
| 1643 | struct brcmf_info *drvr_priv = drvr->info; | ||
| 1644 | |||
| 1645 | if (waitqueue_active(&drvr_priv->ioctl_resp_wait)) | ||
| 1646 | wake_up_interruptible(&drvr_priv->ioctl_resp_wait); | ||
| 1647 | |||
| 1648 | return 0; | ||
| 1649 | } | ||
| 1650 | |||
| 1651 | static int brcmf_host_event(struct brcmf_info *drvr_priv, int *ifidx, void *pktdata, | ||
| 1652 | struct brcmf_event_msg *event, void **data) | ||
| 1653 | { | ||
| 1654 | int bcmerror = 0; | ||
| 1655 | |||
| 1656 | bcmerror = brcmf_c_host_event(drvr_priv, ifidx, pktdata, event, data); | ||
| 1657 | if (bcmerror != 0) | ||
| 1658 | return bcmerror; | ||
| 1659 | |||
| 1660 | if (drvr_priv->iflist[*ifidx]->net) | ||
| 1661 | brcmf_cfg80211_event(drvr_priv->iflist[*ifidx]->net, | ||
| 1662 | event, *data); | ||
| 1663 | |||
| 1664 | return bcmerror; | ||
| 1665 | } | ||
| 1666 | |||
| 1667 | int brcmf_netdev_reset(struct net_device *dev, u8 flag) | ||
| 1668 | { | ||
| 1669 | struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev); | ||
| 1670 | |||
| 1671 | brcmf_bus_devreset(&drvr_priv->pub, flag); | ||
| 1672 | |||
| 1673 | return 1; | ||
| 1674 | } | ||
| 1675 | |||
| 1676 | static int brcmf_get_pend_8021x_cnt(struct brcmf_info *drvr_priv) | ||
| 1677 | { | ||
| 1678 | return atomic_read(&drvr_priv->pend_8021x_cnt); | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | #define MAX_WAIT_FOR_8021X_TX 10 | ||
| 1682 | |||
| 1683 | int brcmf_netdev_wait_pend8021x(struct net_device *dev) | ||
| 1684 | { | ||
| 1685 | struct brcmf_info *drvr_priv = *(struct brcmf_info **)netdev_priv(dev); | ||
| 1686 | int timeout = 10 * HZ / 1000; | ||
| 1687 | int ntimes = MAX_WAIT_FOR_8021X_TX; | ||
| 1688 | int pend = brcmf_get_pend_8021x_cnt(drvr_priv); | ||
| 1689 | |||
| 1690 | while (ntimes && pend) { | ||
| 1691 | if (pend) { | ||
| 1692 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 1693 | schedule_timeout(timeout); | ||
| 1694 | set_current_state(TASK_RUNNING); | ||
| 1695 | ntimes--; | ||
| 1696 | } | ||
| 1697 | pend = brcmf_get_pend_8021x_cnt(drvr_priv); | ||
| 1698 | } | ||
| 1699 | return pend; | ||
| 1700 | } | ||
| 1701 | |||
| 1702 | #ifdef BCMDBG | ||
| 1703 | int brcmf_write_to_file(struct brcmf_pub *drvr, u8 *buf, int size) | ||
| 1704 | { | ||
| 1705 | int ret = 0; | ||
| 1706 | struct file *fp; | ||
| 1707 | mm_segment_t old_fs; | ||
| 1708 | loff_t pos = 0; | ||
| 1709 | |||
| 1710 | /* change to KERNEL_DS address limit */ | ||
| 1711 | old_fs = get_fs(); | ||
| 1712 | set_fs(KERNEL_DS); | ||
| 1713 | |||
| 1714 | /* open file to write */ | ||
| 1715 | fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640); | ||
| 1716 | if (!fp) { | ||
| 1717 | BRCMF_ERROR(("%s: open file error\n", __func__)); | ||
| 1718 | ret = -1; | ||
| 1719 | goto exit; | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | /* Write buf to file */ | ||
| 1723 | fp->f_op->write(fp, buf, size, &pos); | ||
| 1724 | |||
| 1725 | exit: | ||
| 1726 | /* free buf before return */ | ||
| 1727 | kfree(buf); | ||
| 1728 | /* close file before return */ | ||
| 1729 | if (fp) | ||
| 1730 | filp_close(fp, current->files); | ||
| 1731 | /* restore previous address limit */ | ||
| 1732 | set_fs(old_fs); | ||
| 1733 | |||
| 1734 | return ret; | ||
| 1735 | } | ||
| 1736 | #endif /* BCMDBG */ | ||
| @@ -1,75 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #ifndef _BRCMF_PROTO_H_ | ||
| 18 | #define _BRCMF_PROTO_H_ | ||
| 19 | |||
| 20 | #ifndef IOCTL_RESP_TIMEOUT | ||
| 21 | #define IOCTL_RESP_TIMEOUT 2000 /* In milli second */ | ||
| 22 | #endif | ||
| 23 | |||
| 24 | #ifndef IOCTL_CHIP_ACTIVE_TIMEOUT | ||
| 25 | #define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */ | ||
| 26 | #endif | ||
| 27 | |||
| 28 | /* | ||
| 29 | * Exported from the brcmf protocol module (brcmf_cdc) | ||
| 30 | */ | ||
| 31 | |||
| 32 | /* Linkage, sets prot link and updates hdrlen in pub */ | ||
| 33 | extern int brcmf_proto_attach(struct brcmf_pub *drvr); | ||
| 34 | |||
| 35 | /* Unlink, frees allocated protocol memory (including brcmf_proto) */ | ||
| 36 | extern void brcmf_proto_detach(struct brcmf_pub *drvr); | ||
| 37 | |||
| 38 | /* Initialize protocol: sync w/dongle state. | ||
| 39 | * Sets dongle media info (iswl, drv_version, mac address). | ||
| 40 | */ | ||
| 41 | extern int brcmf_proto_init(struct brcmf_pub *drvr); | ||
| 42 | |||
| 43 | /* Stop protocol: sync w/dongle state. */ | ||
| 44 | extern void brcmf_proto_stop(struct brcmf_pub *drvr); | ||
| 45 | |||
| 46 | /* Add any protocol-specific data header. | ||
| 47 | * Caller must reserve prot_hdrlen prepend space. | ||
| 48 | */ | ||
| 49 | extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, | ||
| 50 | struct sk_buff *txp); | ||
| 51 | |||
| 52 | /* Remove any protocol-specific data header. */ | ||
| 53 | extern int brcmf_proto_hdrpull(struct brcmf_pub *, int *ifidx, | ||
| 54 | struct sk_buff *rxp); | ||
| 55 | |||
| 56 | /* Use protocol to issue ioctl to dongle */ | ||
| 57 | extern int brcmf_proto_ioctl(struct brcmf_pub *drvr, int ifidx, | ||
| 58 | struct brcmf_ioctl *ioc, void *buf, int len); | ||
| 59 | |||
| 60 | /* Add prot dump output to a buffer */ | ||
| 61 | extern void brcmf_proto_dump(struct brcmf_pub *drvr, | ||
| 62 | struct brcmu_strbuf *strbuf); | ||
| 63 | |||
| 64 | /* Update local copy of dongle statistics */ | ||
| 65 | extern void brcmf_proto_dstats(struct brcmf_pub *drvr); | ||
| 66 | |||
| 67 | extern int brcmf_c_ioctl(struct brcmf_pub *drvr, struct brcmf_c_ioctl *ioc, | ||
| 68 | void *buf, uint buflen); | ||
| 69 | |||
| 70 | extern int brcmf_c_preinit_ioctls(struct brcmf_pub *drvr); | ||
| 71 | |||
| 72 | extern int brcmf_proto_cdc_set_ioctl(struct brcmf_pub *drvr, int ifidx, | ||
| 73 | uint cmd, void *buf, uint len); | ||
| 74 | |||
| 75 | #endif /* _BRCMF_PROTO_H_ */ | ||
| @@ -1,6772 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2010 Broadcom Corporation | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
| 11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
| 13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
| 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/types.h> | ||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/kthread.h> | ||
| 20 | #include <linux/printk.h> | ||
| 21 | #include <linux/pci_ids.h> | ||
| 22 | #include <linux/netdevice.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/sched.h> | ||
| 25 | #include <linux/mmc/sdio.h> | ||
| 26 | #include <linux/mmc/sdio_func.h> | ||
| 27 | #include <linux/semaphore.h> | ||
| 28 | #include <linux/firmware.h> | ||
| 29 | #include <asm/unaligned.h> | ||
| 30 | #include <defs.h> | ||
| 31 | #include <brcmu_wifi.h> | ||
| 32 | #include <brcmu_utils.h> | ||
| 33 | #include <brcm_hw_ids.h> | ||
| 34 | #include <soc.h> | ||
| 35 | #include "sdio_host.h" | ||
| 36 | |||
| 37 | /* register access macros */ | ||
| 38 | #ifndef __BIG_ENDIAN | ||
| 39 | #ifndef __mips__ | ||
| 40 | #define R_REG(r, typ) \ | ||
| 41 | brcmf_sdcard_reg_read(NULL, (r), sizeof(typ)) | ||
| 42 | #else /* __mips__ */ | ||
| 43 | #define R_REG(r, typ) \ | ||
| 44 | ({ \ | ||
| 45 | __typeof(*(r)) __osl_v; \ | ||
| 46 | __asm__ __volatile__("sync"); \ | ||
| 47 | __osl_v = brcmf_sdcard_reg_read(NULL, (r),\ | ||
| 48 | sizeof(typ)); \ | ||
| 49 | __asm__ __volatile__("sync"); \ | ||
| 50 | __osl_v; \ | ||
| 51 | }) | ||
| 52 | #endif /* __mips__ */ | ||
| 53 | |||
| 54 | #else /* __BIG_ENDIAN */ | ||
| 55 | #define R_REG(r, typ) \ | ||
| 56 | brcmf_sdcard_reg_read(NULL, (r), sizeof(typ)) | ||
| 57 | #endif /* __BIG_ENDIAN */ | ||
| 58 | |||
| 59 | #define OR_REG(r, v, typ) \ | ||
| 60 | brcmf_sdcard_reg_write(NULL, (r), sizeof(typ), R_REG(r, typ) | (v)) | ||
| 61 | |||
| 62 | #ifdef BCMDBG | ||
| 63 | |||
| 64 | /* ARM trap handling */ | ||
| 65 | |||
| 66 | /* Trap types defined by ARM (see arminc.h) */ | ||
| 67 | |||
| 68 | #if defined(__ARM_ARCH_4T__) | ||
| 69 | #define MAX_TRAP_TYPE (TR_FIQ + 1) | ||
| 70 | #elif defined(__ARM_ARCH_7M__) | ||
| 71 | #define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS) | ||
| 72 | #endif /* __ARM_ARCH_7M__ */ | ||
| 73 | |||
| 74 | /* The trap structure is defined here as offsets for assembly */ | ||
| 75 | #define TR_TYPE 0x00 | ||
| 76 | #define TR_EPC 0x04 | ||
| 77 | #define TR_CPSR 0x08 | ||
| 78 | #define TR_SPSR 0x0c | ||
| 79 | #define TR_REGS 0x10 | ||
| 80 | #define TR_REG(n) (TR_REGS + (n) * 4) | ||
| 81 | #define TR_SP TR_REG(13) | ||
| 82 | #define TR_LR TR_REG(14) | ||
| 83 | #define TR_PC TR_REG(15) | ||
| 84 | |||
| 85 | #define TRAP_T_SIZE 80 | ||
| 86 | |||
| 87 | struct brcmf_trap { | ||
| 88 | u32 type; | ||
| 89 | u32 epc; | ||
| 90 | u32 cpsr; | ||
| 91 | u32 spsr; | ||
| 92 | u32 r0; | ||
| 93 | u32 r1; | ||
| 94 | u32 r2; | ||
| 95 | u32 r3; | ||
| 96 | u32 r4; | ||
| 97 | u32 r5; | ||
| 98 | u32 r6; | ||
| 99 | u32 r7; | ||
| 100 | u32 r8; | ||
| 101 | u32 r9; | ||
| 102 | u32 r10; | ||
| 103 | u32 r11; | ||
| 104 | u32 r12; | ||
| 105 | u32 r13; | ||
| 106 | u32 r14; | ||
| 107 | u32 pc; | ||
| 108 | }; | ||
| 109 | |||
| 110 | #define CBUF_LEN (128) | ||
| 111 | |||
| 112 | struct rte_log { | ||
| 113 | u32 buf; /* Can't be pointer on (64-bit) hosts */ | ||
| 114 | uint buf_size; | ||
| 115 | uint idx; | ||
| 116 | char *_buf_compat; /* Redundant pointer for backward compat. */ | ||
| 117 | }; | ||
| 118 | |||
| 119 | struct rte_console { | ||
| 120 | /* Virtual UART | ||
| 121 | * When there is no UART (e.g. Quickturn), | ||
| 122 | * the host should write a complete | ||
| 123 | * input line directly into cbuf and then write | ||
| 124 | * the length into vcons_in. | ||
| 125 | * This may also be used when there is a real UART | ||
| 126 | * (at risk of conflicting with | ||
| 127 | * the real UART). vcons_out is currently unused. | ||
| 128 | */ | ||
| 129 | volatile uint vcons_in; | ||
| 130 | volatile uint vcons_out; | ||
| 131 | |||
| 132 | /* Output (logging) buffer | ||
| 133 | * Console output is written to a ring buffer log_buf at index log_idx. | ||
| 134 | * The host may read the output when it sees log_idx advance. | ||
| 135 | * Output will be lost if the output wraps around faster than the host | ||
| 136 | * polls. | ||
| 137 | */ | ||
| 138 | struct rte_log log; | ||
| 139 | |||
| 140 | /* Console input line buffer | ||
| 141 | * Characters are read one at a time into cbuf | ||
| 142 | * until <CR> is received, then | ||
| 143 | * the buffer is processed as a command line. | ||
| 144 | * Also used for virtual UART. | ||
| 145 | */ | ||
| 146 | uint cbuf_idx; | ||
| 147 | char cbuf[CBUF_LEN]; | ||
| 148 | }; | ||
| 149 | |||
| 150 | #endif /* BCMDBG */ | ||
| 151 | #include <chipcommon.h> | ||
| 152 | |||
| 153 | #include "dhd.h" | ||
| 154 | #include "dhd_bus.h" | ||
| 155 | #include "dhd_proto.h" | ||
| 156 | #include "dhd_dbg.h" | ||
| 157 | #include <bcmchip.h> | ||
| 158 | |||
| 159 | #define TXQLEN 2048 /* bulk tx queue length */ | ||
| 160 | #define TXHI (TXQLEN - 256) /* turn on flow control above TXHI */ | ||
| 161 | #define TXLOW (TXHI - 256) /* turn off flow control below TXLOW */ | ||
| 162 | #define PRIOMASK 7 | ||
| 163 | |||
| 164 | #define TXRETRIES 2 /* # of retries for tx frames */ | ||
| 165 | |||
| 166 | #define BRCMF_RXBOUND 50 /* Default for max rx frames in | ||
| 167 | one scheduling */ | ||
| 168 | |||
| 169 | #define BRCMF_TXBOUND 20 /* Default for max tx frames in | ||
| 170 | one scheduling */ | ||
| 171 | |||
| 172 | #define BRCMF_TXMINMAX 1 /* Max tx frames if rx still pending */ | ||
| 173 | |||
| 174 | #define MEMBLOCK 2048 /* Block size used for downloading | ||
| 175 | of dongle image */ | ||
| 176 | #define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold | ||
| 177 | biggest possible glom */ | ||
| 178 | |||
| 179 | #ifndef BRCMF_FIRSTREAD | ||
| 180 | #define BRCMF_FIRSTREAD 32 | ||
| 181 | #endif | ||
| 182 | |||
| 183 | #if !ISPOWEROF2(BRCMF_FIRSTREAD) | ||
| 184 | #error BRCMF_FIRSTREAD is not a power of 2! | ||
| 185 | #endif | ||
| 186 | |||
| 187 | /* SBSDIO_DEVICE_CTL */ | ||
| 188 | #define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when | ||
| 189 | * receiving CMD53 | ||
| 190 | */ | ||
| 191 | #define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is | ||
| 192 | * synchronous to the sdio clock | ||
| 193 | */ | ||
| 194 | #define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host | ||
| 195 | * except the chipActive (rev 8) | ||
| 196 | */ | ||
| 197 | #define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put | ||
| 198 | * external pads in tri-state; requires | ||
| 199 | * sdio bus power cycle to clear (rev 9) | ||
| 200 | */ | ||
| 201 | #define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */ | ||
| 202 | #define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ | ||
| 203 | #define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ | ||
| 204 | #define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ | ||
| 205 | |||
| 206 | /* SBSDIO_FUNC1_CHIPCLKCSR */ | ||
| 207 | #define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */ | ||
| 208 | #define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */ | ||
| 209 | #define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */ | ||
| 210 | #define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */ | ||
| 211 | #define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */ | ||
| 212 | #define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */ | ||
| 213 | #define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */ | ||
| 214 | #define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */ | ||
| 215 | |||
| 216 | #define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) | ||
| 217 | #define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) | ||
| 218 | #define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) | ||
| 219 | #define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) | ||
| 220 | #define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \ | ||
| 221 | (alponly ? 1 : SBSDIO_HTAV(regval))) | ||
| 222 | /* direct(mapped) cis space */ | ||
| 223 | #define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */ | ||
| 224 | #define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */ | ||
| 225 | #define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */ | ||
| 226 | |||
| 227 | #define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple, | ||
| 228 | * link bytes | ||
| 229 | */ | ||
| 230 | |||
| 231 | /* intstatus */ | ||
| 232 | #define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */ | ||
| 233 | #define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */ | ||
| 234 | #define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */ | ||
| 235 | #define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */ | ||
| 236 | #define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */ | ||
| 237 | #define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */ | ||
| 238 | #define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */ | ||
| 239 | #define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */ | ||
| 240 | #define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */ | ||
| 241 | #define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */ | ||
| 242 | #define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */ | ||
| 243 | #define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */ | ||
| 244 | #define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */ | ||
| 245 | #define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */ | ||
| 246 | #define I_PC (1 << 10) /* descriptor error */ | ||
| 247 | #define I_PD (1 << 11) /* data error */ | ||
| 248 | #define I_DE (1 << 12) /* Descriptor protocol Error */ | ||
| 249 | #define I_RU (1 << 13) /* Receive descriptor Underflow */ | ||
| 250 | #define I_RO (1 << 14) /* Receive fifo Overflow */ | ||
| 251 | #define I_XU (1 << 15) /* Transmit fifo Underflow */ | ||
| 252 | #define I_RI (1 << 16) /* Receive Interrupt */ | ||
| 253 | #define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */ | ||
| 254 | #define I_XMTDATA_AVAIL (1 << 23) /* bits in fifo */ | ||
| 255 | #define I_XI (1 << 24) /* Transmit Interrupt */ | ||
| 256 | #define I_RF_TERM (1 << 25) /* Read Frame Terminate */ | ||
| 257 | #define I_WF_TERM (1 << 26) /* Write Frame Terminate */ | ||
| 258 | #define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */ | ||
| 259 | #define I_SBINT (1 << 28) /* sbintstatus Interrupt */ | ||
| 260 | #define I_CHIPACTIVE (1 << 29) /* chip from doze to active state */ | ||
| 261 | #define I_SRESET (1 << 30) /* CCCR RES interrupt */ | ||
| 262 | #define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */ | ||
| 263 | #define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) | ||
| 264 | #define I_DMA (I_RI | I_XI | I_ERRORS) | ||
| 265 | |||
| 266 | /* corecontrol */ | ||
| 267 | #define CC_CISRDY (1 << 0) /* CIS Ready */ | ||
| 268 | #define CC_BPRESEN (1 << 1) /* CCCR RES signal */ | ||
| 269 | #define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */ | ||
| 270 | #define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation */ | ||
| 271 | #define CC_XMTDATAAVAIL_MODE (1 << 4) | ||
| 272 | #define CC_XMTDATAAVAIL_CTRL (1 << 5) | ||
| 273 | |||
| 274 | /* SDA_FRAMECTRL */ | ||
| 275 | #define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */ | ||
| 276 | #define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */ | ||
| 277 | #define SFC_CRC4WOOS (1 << 2) /* CRC error for write out of sync */ | ||
| 278 | #define SFC_ABORTALL (1 << 3) /* Abort all in-progress frames */ | ||
| 279 | |||
| 280 | /* HW frame tag */ | ||
| 281 | #define SDPCM_FRAMETAG_LEN 4 /* 2 bytes len, 2 bytes check val */ | ||
| 282 | |||
| 283 | /* Total length of frame header for dongle protocol */ | ||
| 284 | #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) | ||
| 285 | #ifdef SDTEST | ||
| 286 | #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + BRCMF_SDALIGN) | ||
| 287 | #else | ||
| 288 | #define SDPCM_RESERVE (SDPCM_HDRLEN + BRCMF_SDALIGN) | ||
| 289 | #endif | ||
| 290 | |||
| 291 | /* | ||
| 292 | * Software allocation of To SB Mailbox resources | ||
| 293 | */ | ||
| 294 | |||
| 295 | /* tosbmailbox bits corresponding to intstatus bits */ | ||
| 296 | #define SMB_NAK (1 << 0) /* Frame NAK */ | ||
| 297 | #define SMB_INT_ACK (1 << 1) /* Host Interrupt ACK */ | ||
| 298 | #define SMB_USE_OOB (1 << 2) /* Use OOB Wakeup */ | ||
| 299 | #define SMB_DEV_INT (1 << 3) /* Miscellaneous Interrupt */ | ||
| 300 | |||
| 301 | /* tosbmailboxdata */ | ||
| 302 | #define SMB_DATA_VERSION_SHIFT 16 /* host protocol version */ | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Software allocation of To Host Mailbox resources | ||
| 306 | */ | ||
| 307 | |||
| 308 | /* intstatus bits */ | ||
| 309 | #define I_HMB_FC_STATE I_HMB_SW0 /* Flow Control State */ | ||
| 310 | #define I_HMB_FC_CHANGE I_HMB_SW1 /* Flow Control State Changed */ | ||
| 311 | #define I_HMB_FRAME_IND I_HMB_SW2 /* Frame Indication */ | ||
| 312 | #define I_HMB_HOST_INT I_HMB_SW3 /* Miscellaneous Interrupt */ | ||
| 313 | |||
| 314 | /* tohostmailboxdata */ | ||
| 315 | #define HMB_DATA_NAKHANDLED 1 /* retransmit NAK'd frame */ | ||
| 316 | #define HMB_DATA_DEVREADY 2 /* talk to host after enable */ | ||
| 317 | #define HMB_DATA_FC 4 /* per prio flowcontrol update flag */ | ||
| 318 | #define HMB_DATA_FWREADY 8 /* fw ready for protocol activity */ | ||
| 319 | |||
| 320 | #define HMB_DATA_FCDATA_MASK 0xff000000 | ||
| 321 | #define HMB_DATA_FCDATA_SHIFT 24 | ||
| 322 | |||
| 323 | #define HMB_DATA_VERSION_MASK 0x00ff0000 | ||
| 324 | #define HMB_DATA_VERSION_SHIFT 16 | ||
| 325 | |||
| 326 | /* | ||
| 327 | * Software-defined protocol header | ||
| 328 | */ | ||
| 329 | |||
| 330 | /* Current protocol version */ | ||
| 331 | #define SDPCM_PROT_VERSION 4 | ||
| 332 | |||
| 333 | /* SW frame header */ | ||
| 334 | #define SDPCM_PACKET_SEQUENCE(p) (((u8 *)p)[0] & 0xff) | ||
| 335 | |||
| 336 | #define SDPCM_CHANNEL_MASK 0x00000f00 | ||
| 337 | #define SDPCM_CHANNEL_SHIFT 8 | ||
| 338 | #define SDPCM_PACKET_CHANNEL(p) (((u8 *)p)[1] & 0x0f) | ||
| 339 | |||
| 340 | #define SDPCM_NEXTLEN_OFFSET 2 | ||
| 341 | |||
| 342 | /* Data Offset from SOF (HW Tag, SW Tag, Pad) */ | ||
| 343 | #define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ | ||
| 344 | #define SDPCM_DOFFSET_VALUE(p) (((u8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) | ||
| 345 | #define SDPCM_DOFFSET_MASK 0xff000000 | ||
| 346 | #define SDPCM_DOFFSET_SHIFT 24 | ||
| 347 | #define SDPCM_FCMASK_OFFSET 4 /* Flow control */ | ||
| 348 | #define SDPCM_FCMASK_VALUE(p) (((u8 *)p)[SDPCM_FCMASK_OFFSET] & 0xff) | ||
| 349 | #define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ | ||
| 350 | #define SDPCM_WINDOW_VALUE(p) (((u8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) | ||
| 351 | |||
| 352 | #define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ | ||
| 353 | |||
| 354 | /* logical channel numbers */ | ||
| 355 | #define SDPCM_CONTROL_CHANNEL 0 /* Control channel Id */ | ||
| 356 | #define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ | ||
| 357 | #define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ | ||
| 358 | #define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets */ | ||
| 359 | #define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ | ||
| 360 | |||
| 361 | #define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for 8bit frame seq */ | ||
| 362 | |||
| 363 | #define SDPCM_GLOMDESC(p) (((u8 *)p)[1] & 0x80) | ||
| 364 | |||
| 365 | /* For TEST_CHANNEL packets, define another 4-byte header */ | ||
| 366 | #define SDPCM_TEST_HDRLEN 4 /* | ||
| 367 | * Generally: Cmd(1), Ext(1), Len(2); | ||
| 368 | * Semantics of Ext byte depend on | ||
| 369 | * command. Len is current or requested | ||
| 370 | * frame length, not including test | ||
| 371 | * header; sent little-endian. | ||
| 372 | */ | ||
| 373 | #define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext:pattern id. */ | ||
| 374 | #define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext:pattern id. */ | ||
| 375 | #define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext:pattern id. */ | ||
| 376 | #define SDPCM_TEST_BURST 0x04 /* | ||
| 377 | * Receiver to send a burst. | ||
| 378 | * Ext is a frame count | ||
| 379 | */ | ||
| 380 | #define SDPCM_TEST_SEND 0x05 /* | ||
| 381 | * Receiver sets send mode. | ||
| 382 | * Ext is boolean on/off | ||
| 383 | */ | ||
| 384 | |||
| 385 | /* Handy macro for filling in datagen packets with a pattern */ | ||
| 386 | #define SDPCM_TEST_FILL(byteno, id) ((u8)(id + byteno)) | ||
| 387 | |||
| 388 | /* | ||
| 389 | * Shared structure between dongle and the host. | ||
| 390 | * The structure contains pointers to trap or assert information. | ||
| 391 | */ | ||
| 392 | #define SDPCM_SHARED_VERSION 0x0002 | ||
| 393 | #define SDPCM_SHARED_VERSION_MASK 0x00FF | ||
| 394 | #define SDPCM_SHARED_ASSERT_BUILT 0x0100 | ||
| 395 | #define SDPCM_SHARED_ASSERT 0x0200 | ||
| 396 | #define SDPCM_SHARED_TRAP 0x0400 | ||
| 397 | |||
| 398 | |||
| 399 | /* Space for header read, limit for data packets */ | ||
| 400 | #ifndef MAX_HDR_READ | ||
| 401 | #define MAX_HDR_READ 32 | ||
| 402 | #endif | ||
| 403 | #if !ISPOWEROF2(MAX_HDR_READ) | ||
| 404 | #error MAX_HDR_READ is not a power of 2! | ||
| 405 | #endif | ||
| 406 | |||
| 407 | #define MAX_RX_DATASZ 2048 | ||
| 408 | |||
| 409 | /* Maximum milliseconds to wait for F2 to come up */ | ||
| 410 | #define BRCMF_WAIT_F2RDY 3000 | ||
| 411 | |||
| 412 | /* Bump up limit on waiting for HT to account for first startup; | ||
| 413 | * if the image is doing a CRC calculation before programming the PMU | ||
| 414 | * for HT availability, it could take a couple hundred ms more, so | ||
| 415 | * max out at a 1 second (1000000us). | ||
| 416 | */ | ||
| 417 | #if (PMU_MAX_TRANSITION_DLY <= 1000000) | ||
| 418 | #undef PMU_MAX_TRANSITION_DLY | ||
| 419 | #define PMU_MAX_TRANSITION_DLY 1000000 | ||
| 420 | #endif | ||
| 421 | |||
| 422 | /* Value for ChipClockCSR during initial setup */ | ||
| 423 | #define BRCMF_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | \ | ||
| 424 | SBSDIO_ALP_AVAIL_REQ) | ||
| 425 | |||
| 426 | /* Flags for SDH calls */ | ||
| 427 | #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) | ||
| 428 | |||
| 429 | /* sbimstate */ | ||
| 430 | #define SBIM_IBE 0x20000 /* inbanderror */ | ||
| 431 | #define SBIM_TO 0x40000 /* timeout */ | ||
| 432 | #define SBIM_BY 0x01800000 /* busy (sonics >= 2.3) */ | ||
| 433 | #define SBIM_RJ 0x02000000 /* reject (sonics >= 2.3) */ | ||
| 434 | |||
| 435 | /* sbtmstatelow */ | ||
| 436 | #define SBTML_RESET 0x0001 /* reset */ | ||
| 437 | #define SBTML_REJ_MASK 0x0006 /* reject field */ | ||
| 438 | #define SBTML_REJ 0x0002 /* reject */ | ||
| 439 | #define SBTML_TMPREJ 0x0004 /* temporary reject, for error recovery */ | ||
| 440 | |||
| 441 | #define SBTML_SICF_SHIFT 16 /* Shift to locate the SI control flags in sbtml */ | ||
| 442 | |||
| 443 | /* sbtmstatehigh */ | ||
| 444 | #define SBTMH_SERR 0x0001 /* serror */ | ||
| 445 | #define SBTMH_INT 0x0002 /* interrupt */ | ||
| 446 | #define SBTMH_BUSY 0x0004 /* busy */ | ||
| 447 | #define SBTMH_TO 0x0020 /* timeout (sonics >= 2.3) */ | ||
| 448 | |||
| 449 | #define SBTMH_SISF_SHIFT 16 /* Shift to locate the SI status flags in sbtmh */ | ||
| 450 | |||
| 451 | /* sbidlow */ | ||
| 452 | #define SBIDL_INIT 0x80 /* initiator */ | ||
| 453 | |||
| 454 | /* sbidhigh */ | ||
| 455 | #define SBIDH_RC_MASK 0x000f /* revision code */ | ||
| 456 | #define SBIDH_RCE_MASK 0x7000 /* revision code extension field */ | ||
| 457 | #define SBIDH_RCE_SHIFT 8 | ||
| 458 | #define SBCOREREV(sbidh) \ | ||
| 459 | ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) | ||
| 460 | #define SBIDH_CC_MASK 0x8ff0 /* core code */ | ||
| 461 | #define SBIDH_CC_SHIFT 4 | ||
| 462 | #define SBIDH_VC_MASK 0xffff0000 /* vendor code */ | ||
| 463 | #define SBIDH_VC_SHIFT 16 | ||
| 464 | |||
| 465 | /* | ||
| 466 | * Conversion of 802.1D priority to precedence level | ||
| 467 | */ | ||
| 468 | #define PRIO2PREC(prio) \ | ||
| 469 | (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \ | ||
| 470 | ((prio^2)) : (prio)) | ||
| 471 | |||
| 472 | BRCMF_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); | ||
| 473 | |||
| 474 | /* | ||
| 475 | * Core reg address translation. | ||
| 476 | * Both macro's returns a 32 bits byte address on the backplane bus. | ||
| 477 | */ | ||
| 478 | #define CORE_CC_REG(base, field) (base + offsetof(chipcregs_t, field)) | ||
| 479 | #define CORE_BUS_REG(base, field) \ | ||
| 480 | (base + offsetof(struct sdpcmd_regs, field)) | ||
| 481 | #define CORE_SB(base, field) \ | ||
| 482 | (base + SBCONFIGOFF + offsetof(struct sbconfig, field)) | ||
| 483 | |||
| 484 | /* core registers */ | ||
| 485 | struct sdpcmd_regs { | ||
| 486 | u32 corecontrol; /* 0x00, rev8 */ | ||
| 487 | u32 corestatus; /* rev8 */ | ||
| 488 | u32 PAD[1]; | ||
| 489 | u32 biststatus; /* rev8 */ | ||
| 490 | |||
| 491 | /* PCMCIA access */ | ||
| 492 | u16 pcmciamesportaladdr; /* 0x010, rev8 */ | ||
| 493 | u16 PAD[1]; | ||
| 494 | u16 pcmciamesportalmask; /* rev8 */ | ||
| 495 | u16 PAD[1]; | ||
| 496 | u16 pcmciawrframebc; /* rev8 */ | ||
| 497 | u16 PAD[1]; | ||
| 498 | u16 pcmciaunderflowtimer; /* rev8 */ | ||
| 499 | u16 PAD[1]; | ||
| 500 | |||
| 501 | /* interrupt */ | ||
| 502 | u32 intstatus; /* 0x020, rev8 */ | ||
| 503 | u32 hostintmask; /* rev8 */ | ||
| 504 | u32 intmask; /* rev8 */ | ||
| 505 | u32 sbintstatus; /* rev8 */ | ||
| 506 | u32 sbintmask; /* rev8 */ | ||
| 507 | u32 funcintmask; /* rev4 */ | ||
| 508 | u32 PAD[2]; | ||
| 509 | u32 tosbmailbox; /* 0x040, rev8 */ | ||
| 510 | u32 tohostmailbox; /* rev8 */ | ||
| 511 | u32 tosbmailboxdata; /* rev8 */ | ||
| 512 | u32 tohostmailboxdata; /* rev8 */ | ||
| 513 | |||
| 514 | /* synchronized access to registers in SDIO clock domain */ | ||
| 515 | u32 sdioaccess; /* 0x050, rev8 */ | ||
| 516 | u32 PAD[3]; | ||
| 517 | |||
| 518 | /* PCMCIA frame control */ | ||
| 519 | u8 pcmciaframectrl; /* 0x060, rev8 */ | ||
| 520 | u8 PAD[3]; | ||
| 521 | u8 pcmciawatermark; /* rev8 */ | ||
| 522 | u8 PAD[155]; | ||
| 523 | |||
| 524 | /* interrupt batching control */ | ||
| 525 | u32 intrcvlazy; /* 0x100, rev8 */ | ||
| 526 | u32 PAD[3]; | ||
| 527 | |||
| 528 | /* counters */ | ||
| 529 | u32 cmd52rd; /* 0x110, rev8 */ | ||
| 530 | u32 cmd52wr; /* rev8 */ | ||
| 531 | u32 cmd53rd; /* rev8 */ | ||
| 532 | u32 cmd53wr; /* rev8 */ | ||
| 533 | u32 abort; /* rev8 */ | ||
| 534 | u32 datacrcerror; /* rev8 */ | ||
| 535 | u32 rdoutofsync; /* rev8 */ | ||
| 536 | u32 wroutofsync; /* rev8 */ | ||
| 537 | u32 writebusy; /* rev8 */ | ||
| 538 | u32 readwait; /* rev8 */ | ||
| 539 | u32 readterm; /* rev8 */ | ||
| 540 | u32 writeterm; /* rev8 */ | ||
| 541 | u32 PAD[40]; | ||
| 542 | u32 clockctlstatus; /* rev8 */ | ||
| 543 | u32 PAD[7]; | ||
| 544 | |||
| 545 | u32 PAD[128]; /* DMA engines */ | ||
| 546 | |||
| 547 | /* SDIO/PCMCIA CIS region */ | ||
| 548 | char cis[512]; /* 0x400-0x5ff, rev6 */ | ||
| 549 | |||
| 550 | /* PCMCIA function control registers */ | ||
| 551 | char pcmciafcr[256]; /* 0x600-6ff, rev6 */ | ||
| 552 | u16 PAD[55]; | ||
| 553 | |||
| 554 | /* PCMCIA backplane access */ | ||
| 555 | u16 backplanecsr; /* 0x76E, rev6 */ | ||
| 556 | u16 backplaneaddr0; /* rev6 */ | ||
| 557 | u16 backplaneaddr1; /* rev6 */ | ||
| 558 | u16 backplaneaddr2; /* rev6 */ | ||
| 559 | u16 backplaneaddr3; /* rev6 */ | ||
| 560 | u16 backplanedata0; /* rev6 */ | ||
| 561 | u16 backplanedata1; /* rev6 */ | ||
| 562 | u16 backplanedata2; /* rev6 */ | ||
| 563 | u16 backplanedata3; /* rev6 */ | ||
| 564 | u16 PAD[31]; | ||
| 565 | |||
| 566 | /* sprom "size" & "blank" info */ | ||
| 567 | u16 spromstatus; /* 0x7BE, rev2 */ | ||
| 568 | u32 PAD[464]; | ||
| 569 | |||
| 570 | u16 PAD[0x80]; | ||
| 571 | }; | ||
| 572 | |||
| 573 | #ifdef BCMDBG | ||
| 574 | /* Device console log buffer state */ | ||
| 575 | struct brcmf_console { | ||
| 576 | uint count; /* Poll interval msec counter */ | ||
| 577 | uint log_addr; /* Log struct address (fixed) */ | ||
| 578 | struct rte_log log; /* Log struct (host copy) */ | ||
| 579 | uint bufsize; /* Size of log buffer */ | ||
| 580 | u8 *buf; /* Log buffer (host copy) */ | ||
| 581 | uint last; /* Last buffer read index */ | ||
| 582 | }; | ||
| 583 | #endif /* BCMDBG */ | ||
| 584 | |||
| 585 | struct sdpcm_shared { | ||
| 586 | u32 flags; | ||
| 587 | u32 trap_addr; | ||
| 588 | u32 assert_exp_addr; | ||
| 589 | u32 assert_file_addr; | ||
| 590 | u32 assert_line; | ||
| 591 | u32 console_addr; /* Address of struct rte_console */ | ||
| 592 | u32 msgtrace_addr; | ||
| 593 | u8 tag[32]; | ||
| 594 | }; | ||
| 595 | |||
| 596 | |||
| 597 | /* misc chip info needed by some of the routines */ | ||
| 598 | struct chip_info { | ||
| 599 | u32 chip; | ||
| 600 | u32 chiprev; | ||
| 601 | u32 cccorebase; | ||
| 602 | u32 ccrev; | ||
| 603 | u32 cccaps; | ||
| 604 | u32 buscorebase; /* 32 bits backplane bus address */ | ||
| 605 | u32 buscorerev; | ||
| 606 | u32 buscoretype; | ||
| 607 | u32 ramcorebase; | ||
| 608 | u32 armcorebase; | ||
| 609 | u32 pmurev; | ||
| 610 | u32 ramsize; | ||
| 611 | }; | ||
| 612 | |||
| 613 | /* Private data for SDIO bus interaction */ | ||
| 614 | struct brcmf_bus { | ||
| 615 | struct brcmf_pub *drvr; | ||
| 616 | |||
| 617 | struct brcmf_sdio_card *card; /* Handle for sdio card calls */ | ||
| 618 | struct chip_info *ci; /* Chip info struct */ | ||
| 619 | char *vars; /* Variables (from CIS and/or other) */ | ||
| 620 | uint varsz; /* Size of variables buffer */ | ||
| 621 | |||
| 622 | u32 ramsize; /* Size of RAM in SOCRAM (bytes) */ | ||
| 623 | u32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */ | ||
| 624 | |||
| 625 | u32 bus; /* gSPI or SDIO bus */ | ||
| 626 | u32 hostintmask; /* Copy of Host Interrupt Mask */ | ||
| 627 | u32 intstatus; /* Intstatus bits (events) pending */ | ||
| 628 | bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ | ||
| 629 | bool fcstate; /* State of dongle flow-control */ | ||
| 630 | |||
| 631 | u16 cl_devid; /* cached devid for brcmf_sdio_probe_attach() */ | ||
| 632 | |||
| 633 | uint blocksize; /* Block size of SDIO transfers */ | ||
| 634 | uint roundup; /* Max roundup limit */ | ||
| 635 | |||
| 636 | struct pktq txq; /* Queue length used for flow-control */ | ||
| 637 | u8 flowcontrol; /* per prio flow control bitmask */ | ||
| 638 | u8 tx_seq; /* Transmit sequence number (next) */ | ||
| 639 | u8 tx_max; /* Maximum transmit sequence allowed */ | ||
| 640 | |||
| 641 | u8 hdrbuf[MAX_HDR_READ + BRCMF_SDALIGN]; | ||
| 642 | u8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ | ||
| 643 | u16 nextlen; /* Next Read Len from last header */ | ||
| 644 | u8 rx_seq; /* Receive sequence number (expected) */ | ||
| 645 | bool rxskip; /* Skip receive (awaiting NAK ACK) */ | ||
| 646 | |||
| 647 | struct sk_buff *glomd; /* Packet containing glomming descriptor */ | ||
| 648 | struct sk_buff *glom; /* Packet chain for glommed superframe */ | ||
| 649 | uint glomerr; /* Glom packet read errors */ | ||
| 650 | |||
| 651 | u8 *rxbuf; /* Buffer for receiving control packets */ | ||
| 652 | uint rxblen; /* Allocated length of rxbuf */ | ||
| 653 | u8 *rxctl; /* Aligned pointer into rxbuf */ | ||
| 654 | u8 *databuf; /* Buffer for receiving big glom packet */ | ||
| 655 | u8 *dataptr; /* Aligned pointer into databuf */ | ||
| 656 | uint rxlen; /* Length of valid data in buffer */ | ||
| 657 | |||
| 658 | u8 sdpcm_ver; /* Bus protocol reported by dongle */ | ||
| 659 | |||
| 660 | bool intr; /* Use interrupts */ | ||
| 661 | bool poll; /* Use polling */ | ||
| 662 | bool ipend; /* Device interrupt is pending */ | ||
| 663 | bool intdis; /* Interrupts disabled by isr */ | ||
| 664 | uint intrcount; /* Count of device interrupt callbacks */ | ||
| 665 | uint lastintrs; /* Count as of last watchdog timer */ | ||
| 666 | uint spurious; /* Count of spurious interrupts */ | ||
| 667 | uint pollrate; /* Ticks between device polls */ | ||
| 668 | uint polltick; /* Tick counter */ | ||
| 669 | uint pollcnt; /* Count of active polls */ | ||
| 670 | |||
| 671 | #ifdef BCMDBG | ||
| 672 | struct brcmf_console console; /* Console output polling support */ | ||
| 673 | uint console_addr; /* Console address from shared struct */ | ||
| 674 | #endif /* BCMDBG */ | ||
| 675 | |||
| 676 | uint regfails; /* Count of R_REG failures */ | ||
| 677 | |||
| 678 | uint clkstate; /* State of sd and backplane clock(s) */ | ||
| 679 | bool activity; /* Activity flag for clock down */ | ||
| 680 | s32 idletime; /* Control for activity timeout */ | ||
| 681 | s32 idlecount; /* Activity timeout counter */ | ||
| 682 | s32 idleclock; /* How to set bus driver when idle */ | ||
| 683 | s32 sd_rxchain; | ||
| 684 | bool use_rxchain; /* If brcmf should use PKT chains */ | ||
| 685 | bool sleeping; /* Is SDIO bus sleeping? */ | ||
| 686 | bool rxflow_mode; /* Rx flow control mode */ | ||
| 687 | bool rxflow; /* Is rx flow control on */ | ||
| 688 | bool alp_only; /* Don't use HT clock (ALP only) */ | ||
| 689 | /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ | ||
| 690 | bool usebufpool; | ||
| 691 | |||
| 692 | #ifdef SDTEST | ||
| 693 | /* external loopback */ | ||
| 694 | bool ext_loop; | ||
| 695 | u8 loopid; | ||
| 696 | |||
| 697 | /* pktgen configuration */ | ||
| 698 | uint pktgen_freq; /* Ticks between bursts */ | ||
| 699 | uint pktgen_count; /* Packets to send each burst */ | ||
| 700 | uint pktgen_print; /* Bursts between count displays */ | ||
| 701 | uint pktgen_total; /* Stop after this many */ | ||
| 702 | uint pktgen_minlen; /* Minimum packet data len */ | ||
| 703 | uint pktgen_maxlen; /* Maximum packet data len */ | ||
| 704 | uint pktgen_mode; /* Configured mode: tx, rx, or echo */ | ||
| 705 | uint pktgen_stop; /* Number of tx failures causing stop */ | ||
| 706 | |||
| 707 | /* active pktgen fields */ | ||
| 708 | uint pktgen_tick; /* Tick counter for bursts */ | ||
| 709 | uint pktgen_ptick; /* Burst counter for printing */ | ||
| 710 | uint pktgen_sent; /* Number of test packets generated */ | ||
| 711 | uint pktgen_rcvd; /* Number of test packets received */ | ||
| 712 | uint pktgen_fail; /* Number of failed send attempts */ | ||
| 713 | u16 pktgen_len; /* Length of next packet to send */ | ||
| 714 | #endif /* SDTEST */ | ||
| 715 | |||
| 716 | /* Some additional counters */ | ||
| 717 | uint tx_sderrs; /* Count of tx attempts with sd errors */ | ||
| 718 | uint fcqueued; /* Tx packets that got queued */ | ||
| 719 | uint rxrtx; /* Count of rtx requests (NAK to dongle) */ | ||
| 720 | uint rx_toolong; /* Receive frames too long to receive */ | ||
| 721 | uint rxc_errors; /* SDIO errors when reading control frames */ | ||
| 722 | uint rx_hdrfail; /* SDIO errors on header reads */ | ||
| 723 | uint rx_badhdr; /* Bad received headers (roosync?) */ | ||
| 724 | uint rx_badseq; /* Mismatched rx sequence number */ | ||
| 725 | uint fc_rcvd; /* Number of flow-control events received */ | ||
| 726 | uint fc_xoff; /* Number which turned on flow-control */ | ||
| 727 | uint fc_xon; /* Number which turned off flow-control */ | ||
| 728 | uint rxglomfail; /* Failed deglom attempts */ | ||
| 729 | uint rxglomframes; /* Number of glom frames (superframes) */ | ||
| 730 | uint rxglompkts; /* Number of packets from glom frames */ | ||
| 731 | uint f2rxhdrs; /* Number of header reads */ | ||
| 732 | uint f2rxdata; /* Number of frame data reads */ | ||
| 733 | uint f2txdata; /* Number of f2 frame writes */ | ||
| 734 | uint f1regdata; /* Number of f1 register accesses */ | ||
| 735 | |||
| 736 | u8 *ctrl_frame_buf; | ||
| 737 | u32 ctrl_frame_len; | ||
| 738 | bool ctrl_frame_stat; | ||
| 739 | |||
| 740 | spinlock_t txqlock; | ||
| 741 | wait_queue_head_t ctrl_wait; | ||
| 742 | |||
| 743 | struct timer_list timer; | ||
| 744 | struct completion watchdog_wait; | ||
| 745 | struct task_struct *watchdog_tsk; | ||
| 746 | bool wd_timer_valid; | ||
| 747 | |||
| 748 | struct tasklet_struct tasklet; | ||
| 749 | struct task_struct *dpc_tsk; | ||
| 750 | struct completion dpc_wait; | ||
| 751 | |||
| 752 | bool threads_only; | ||
| 753 | struct semaphore sdsem; | ||
| 754 | spinlock_t sdlock; | ||
| 755 | |||
| 756 | const char *fw_name; | ||
| 757 | const struct firmware *firmware; | ||
| 758 | const char *nv_name; | ||
| 759 | u32 fw_ptr; | ||
| 760 | }; | ||
| 761 | |||
| 762 | struct sbconfig { | ||
| 763 | u32 PAD[2]; | ||
| 764 | u32 sbipsflag; /* initiator port ocp slave flag */ | ||
| 765 | u32 PAD[3]; | ||
| 766 | u32 sbtpsflag; /* target port ocp slave flag */ | ||
| 767 | u32 PAD[11]; | ||
| 768 | u32 sbtmerrloga; /* (sonics >= 2.3) */ | ||
| 769 | u32 PAD; | ||
| 770 | u32 sbtmerrlog; /* (sonics >= 2.3) */ | ||
| 771 | u32 PAD[3]; | ||
| 772 | u32 sbadmatch3; /* address match3 */ | ||
| 773 | u32 PAD; | ||
| 774 | u32 sbadmatch2; /* address match2 */ | ||
| 775 | u32 PAD; | ||
| 776 | u32 sbadmatch1; /* address match1 */ | ||
| 777 | u32 PAD[7]; | ||
| 778 | u32 sbimstate; /* initiator agent state */ | ||
| 779 | u32 sbintvec; /* interrupt mask */ | ||
| 780 | u32 sbtmstatelow; /* target state */ | ||
| 781 | u32 sbtmstatehigh; /* target state */ | ||
| 782 | u32 sbbwa0; /* bandwidth allocation table0 */ | ||
| 783 | u32 PAD; | ||
| 784 | u32 sbimconfiglow; /* initiator configuration */ | ||
| 785 | u32 sbimconfighigh; /* initiator configuration */ | ||
| 786 | u32 sbadmatch0; /* address match0 */ | ||
| 787 | u32 PAD; | ||
| 788 | u32 sbtmconfiglow; /* target configuration */ | ||
| 789 | u32 sbtmconfighigh; /* target configuration */ | ||
| 790 | u32 sbbconfig; /* broadcast configuration */ | ||
| 791 | u32 PAD; | ||
| 792 | u32 sbbstate; /* broadcast state */ | ||
| 793 | u32 PAD[3]; | ||
| 794 | u32 sbactcnfg; /* activate configuration */ | ||
| 795 | u32 PAD[3]; | ||
| 796 | u32 sbflagst; /* current sbflags */ | ||
| 797 | u32 PAD[3]; | ||
| 798 | u32 sbidlow; /* identification */ | ||
| 799 | u32 sbidhigh; /* identification */ | ||
| 800 | }; | ||
| 801 | |||
| 802 | /* clkstate */ | ||
| 803 | #define CLK_NONE 0 | ||
| 804 | #define CLK_SDONLY 1 | ||
| 805 | #define CLK_PENDING 2 /* Not used yet */ | ||
| 806 | #define CLK_AVAIL 3 | ||
| 807 | |||
| 808 | #define BRCMF_NOPMU(brcmf) (false) | ||
| 809 | |||
| 810 | #ifdef BCMDBG | ||
| 811 | static int qcount[NUMPRIO]; | ||
| 812 | static int tx_packets[NUMPRIO]; | ||
| 813 | #endif /* BCMDBG */ | ||
| 814 | |||
| 815 | /* Deferred transmit */ | ||
| 816 | uint brcmf_deferred_tx = 1; | ||
| 817 | module_param(brcmf_deferred_tx, uint, 0); | ||
| 818 | |||
| 819 | /* Watchdog thread priority, -1 to use kernel timer */ | ||
| 820 | int brcmf_watchdog_prio = 97; | ||
| 821 | module_param(brcmf_watchdog_prio, int, 0); | ||
| 822 | |||
| 823 | /* Watchdog interval */ | ||
| 824 | uint brcmf_watchdog_ms = 10; | ||
| 825 | module_param(brcmf_watchdog_ms, uint, 0); | ||
| 826 | |||
| 827 | /* DPC thread priority, -1 to use tasklet */ | ||
| 828 | int brcmf_dpc_prio = 98; | ||
| 829 | module_param(brcmf_dpc_prio, int, 0); | ||
| 830 | |||
| 831 | #ifdef BCMDBG | ||
| 832 | /* Console poll interval */ | ||
| 833 | uint brcmf_console_ms; | ||
| 834 | module_param(brcmf_console_ms, uint, 0); | ||
| 835 | #endif /* BCMDBG */ | ||
| 836 | |||
| 837 | /* Tx/Rx bounds */ | ||
| 838 | uint brcmf_txbound; | ||
| 839 | uint brcmf_rxbound; | ||
| 840 | uint brcmf_txminmax; | ||
| 841 | |||
| 842 | /* override the RAM size if possible */ | ||
| 843 | #define DONGLE_MIN_MEMSIZE (128 * 1024) | ||
| 844 | int brcmf_dongle_memsize; | ||
| 845 | |||
| 846 | static bool brcmf_alignctl; | ||
| 847 | |||
| 848 | static bool sd1idle; | ||
| 849 | |||
| 850 | static bool retrydata; | ||
| 851 | #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) | ||
| 852 | |||
| 853 | static const uint watermark = 8; | ||
| 854 | static const uint firstread = BRCMF_FIRSTREAD; | ||
| 855 | |||
| 856 | /* Retry count for register access failures */ | ||
| 857 | static const uint retry_limit = 2; | ||
| 858 | |||
| 859 | /* Force even SD lengths (some host controllers mess up on odd bytes) */ | ||
| 860 | static bool forcealign; | ||
| 861 | |||
| 862 | #define ALIGNMENT 4 | ||
| 863 | |||
| 864 | #define PKTALIGN(_p, _len, _align) \ | ||
| 865 | do { \ | ||
| 866 | uint datalign; \ | ||
| 867 | datalign = (unsigned long)((_p)->data); \ | ||
| 868 | datalign = roundup(datalign, (_align)) - datalign; \ | ||
| 869 | if (datalign) \ | ||
| 870 | skb_pull((_p), datalign); \ | ||
| 871 | __skb_trim((_p), (_len)); \ | ||
| 872 | } while (0) | ||
| 873 | |||
| 874 | /* Limit on rounding up frames */ | ||
| 875 | static const uint max_roundup = 512; | ||
| 876 | |||
| 877 | /* Try doing readahead */ | ||
| 878 | static bool brcmf_readahead; | ||
| 879 | |||
| 880 | /* To check if there's window offered */ | ||
| 881 | #define DATAOK(bus) \ | ||
| 882 | (((u8)(bus->tx_max - bus->tx_seq) != 0) && \ | ||
| 883 | (((u8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) | ||
| 884 | |||
| 885 | /* | ||
| 886 | * Reads a register in the SDIO hardware block. This block occupies a series of | ||
| 887 | * adresses on the 32 bit backplane bus. | ||
| 888 | */ | ||
| 889 | static void | ||
| 890 | r_sdreg32(struct brcmf_bus *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) | ||
| 891 | { | ||
| 892 | *retryvar = 0; | ||
| 893 | do { | ||
| 894 | *regvar = R_REG(bus->ci->buscorebase + reg_offset, u32); | ||
| 895 | } while (brcmf_sdcard_regfail(bus->card) && | ||
| 896 | (++(*retryvar) <= retry_limit)); | ||
| 897 | if (*retryvar) { | ||
| 898 | bus->regfails += (*retryvar-1); | ||
| 899 | if (*retryvar > retry_limit) { | ||
| 900 | BRCMF_ERROR(("FAILED READ %Xh\n", reg_offset)); | ||
| 901 | *regvar = 0; | ||
| 902 | } | ||
| 903 | } | ||
| 904 | } | ||
| 905 | |||
| 906 | static void | ||
| 907 | w_sdreg32(struct brcmf_bus *bus, u32 regval, u32 reg_offset, u32 *retryvar) | ||
| 908 | { | ||
| 909 | *retryvar = 0; | ||
| 910 | do { | ||
| 911 | brcmf_sdcard_reg_write(NULL, bus->ci->buscorebase + reg_offset, | ||
| 912 | sizeof(u32), regval); | ||
| 913 | } while (brcmf_sdcard_regfail(bus->card) && | ||
| 914 | (++(*retryvar) <= retry_limit)); | ||
| 915 | if (*retryvar) { | ||
| 916 | bus->regfails += (*retryvar-1); | ||
| 917 | if (*retryvar > retry_limit) | ||
| 918 | BRCMF_ERROR(("FAILED REGISTER WRITE" | ||
| 919 | " %Xh\n", reg_offset)); | ||
| 920 | } | ||
| 921 | } | ||
| 922 | |||
| 923 | #define BRCMF_BUS SDIO_BUS | ||
| 924 | |||
| 925 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) | ||
| 926 | |||
| 927 | #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) | ||
| 928 | |||
| 929 | #ifdef SDTEST | ||
| 930 | static void brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, void *pkt, uint seq); | ||
| 931 | static void brcmf_sdbrcm_sdtest_set(struct brcmf_bus *bus, bool start); | ||
| 932 | #endif | ||
| 933 | |||
| 934 | #ifdef BCMDBG | ||
| 935 | static int brcmf_sdbrcm_bus_console_in(struct brcmf_pub *drvr, | ||
| 936 | unsigned char *msg, uint msglen); | ||
| 937 | static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size); | ||
| 938 | static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus); | ||
| 939 | #endif /* BCMDBG */ | ||
| 940 | static int brcmf_sdbrcm_download_state(struct brcmf_bus *bus, bool enter); | ||
| 941 | |||
| 942 | static void brcmf_sdbrcm_release(struct brcmf_bus *bus); | ||
| 943 | static void brcmf_sdbrcm_release_malloc(struct brcmf_bus *bus); | ||
| 944 | static void brcmf_sdbrcm_disconnect(void *ptr); | ||
| 945 | static bool brcmf_sdbrcm_chipmatch(u16 chipid); | ||
| 946 | static bool brcmf_sdbrcm_probe_attach(struct brcmf_bus *bus, void *card, | ||
| 947 | u32 regsva, u16 devid); | ||
| 948 | static bool brcmf_sdbrcm_probe_malloc(struct brcmf_bus *bus, void *card); | ||
| 949 | static bool brcmf_sdbrcm_probe_init(struct brcmf_bus *bus, void *card); | ||
| 950 | static void brcmf_sdbrcm_release_dongle(struct brcmf_bus *bus); | ||
| 951 | |||
| 952 | static uint brcmf_process_nvram_vars(char *varbuf, uint len); | ||
| 953 | |||
| 954 | static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size); | ||
| 955 | static int brcmf_sdbrcm_send_buf(struct brcmf_bus *bus, u32 addr, uint fn, | ||
| 956 | uint flags, u8 *buf, uint nbytes, | ||
| 957 | struct sk_buff *pkt, | ||
| 958 | void (*complete)(void *handle, int status, | ||
| 959 | bool sync_waiting), | ||
| 960 | void *handle); | ||
| 961 | |||
| 962 | static bool brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus, void *card); | ||
| 963 | static int _brcmf_sdbrcm_download_firmware(struct brcmf_bus *bus); | ||
| 964 | |||
| 965 | static int brcmf_sdbrcm_download_code_file(struct brcmf_bus *bus); | ||
| 966 | static int brcmf_sdbrcm_download_nvram(struct brcmf_bus *bus); | ||
| 967 | |||
| 968 | static void | ||
| 969 | brcmf_sdbrcm_chip_disablecore(struct brcmf_sdio_card *card, u32 corebase); | ||
| 970 | |||
| 971 | static int brcmf_sdbrcm_chip_attach(struct brcmf_bus *bus, u32 regs); | ||
| 972 | |||
| 973 | static void | ||
| 974 | brcmf_sdbrcm_chip_resetcore(struct brcmf_sdio_card *card, u32 corebase); | ||
| 975 | |||
| 976 | static void brcmf_sdbrcm_sdiod_drive_strength_init(struct brcmf_bus *bus, | ||
| 977 | u32 drivestrength); | ||
| 978 | static void brcmf_sdbrcm_chip_detach(struct brcmf_bus *bus); | ||
| 979 | static void brcmf_sdbrcm_wait_for_event(struct brcmf_bus *bus, bool *lockvar); | ||
| 980 | static void brcmf_sdbrcm_wait_event_wakeup(struct brcmf_bus *bus); | ||
| 981 | static void brcmf_sdbrcm_watchdog(unsigned long data); | ||
| 982 | static int brcmf_sdbrcm_watchdog_thread(void *data); | ||
| 983 | static int brcmf_sdbrcm_dpc_thread(void *data); | ||
| 984 | static void brcmf_sdbrcm_dpc_tasklet(unsigned long data); | ||
| 985 | static void brcmf_sdbrcm_sched_dpc(struct brcmf_bus *bus); | ||
| 986 | static void brcmf_sdbrcm_sdlock(struct brcmf_bus *bus); | ||
| 987 | static void brcmf_sdbrcm_sdunlock(struct brcmf_bus *bus); | ||
| 988 | static int brcmf_sdbrcm_get_image(char *buf, int len, struct brcmf_bus *bus); | ||
| 989 | |||
| 990 | /* Packet free applicable unconditionally for sdio and sdspi. | ||
| 991 | * Conditional if bufpool was present for gspi bus. | ||
| 992 | */ | ||
| 993 | static void brcmf_sdbrcm_pktfree2(struct brcmf_bus *bus, struct sk_buff *pkt) | ||
| 994 | { | ||
| 995 | if ((bus->bus != SPI_BUS) || bus->usebufpool) | ||
| 996 | brcmu_pkt_buf_free_skb(pkt); | ||
| 997 | } | ||
| 998 | |||
| 999 | static void brcmf_sdbrcm_setmemsize(struct brcmf_bus *bus, int mem_size) | ||
| 1000 | { | ||
| 1001 | s32 min_size = DONGLE_MIN_MEMSIZE; | ||
| 1002 | /* Restrict the memsize to user specified limit */ | ||
| 1003 | BRCMF_ERROR(("user: Restrict the dongle ram size to %d, min %d\n", | ||
| 1004 | brcmf_dongle_memsize, min_size)); | ||
| 1005 | if ((brcmf_dongle_memsize > min_size) && | ||
| 1006 | (brcmf_dongle_memsize < (s32) bus->orig_ramsize)) | ||
| 1007 | bus->ramsize = brcmf_dongle_memsize; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | static int brcmf_sdbrcm_set_siaddr_window(struct brcmf_bus *bus, u32 address) | ||
| 1011 | { | ||
| 1012 | int err = 0; | ||
| 1013 | brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, | ||
| 1014 | (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); | ||
| 1015 | if (!err) | ||
| 1016 | brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, | ||
| 1017 | SBSDIO_FUNC1_SBADDRMID, | ||
| 1018 | (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); | ||
| 1019 | if (!err) | ||
| 1020 | brcmf_sdcard_cfg_write(bus->card, SDIO_FUNC_1, | ||
| 1021 | SBSDIO_FUNC1_SBADDRHIGH, | ||
| 1022 | (address >> 24) & SBSDIO_SBADDRHIGH_MASK, | ||
| 1023 | &err); | ||
| 1024 | return err; | ||
| 1025 | } | ||
| 1026 | |||
| 1027 | /* Turn backplane clock on or off */ | ||
| 1028 | static int brcmf_sdbrcm_htclk(struct brcmf_bus *bus, bool on, bool pendok) | ||
| 1029 | { | ||
| 1030 | int err; | ||
| 1031 | u8 clkctl, clkreq, devctl; | ||
| 1032 | struct brcmf_sdio_card *card; | ||
| 1033 | |||
| 1034 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1035 | |||
| 1036 | clkctl = 0; | ||
| 1037 | card = bus->card; | ||
| 1038 | |||
| 1039 | if (on) { | ||
| 1040 | /* Request HT Avail */ | ||
| 1041 | clkreq = | ||
| 1042 | bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; | ||
| 1043 | |||
| 1044 | if ((bus->ci->chip == BCM4329_CHIP_ID) | ||
| 1045 | && (bus->ci->chiprev == 0)) | ||
| 1046 | clkreq |= SBSDIO_FORCE_ALP; | ||
| 1047 | |||
| 1048 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1049 | SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); | ||
| 1050 | if (err) { | ||
| 1051 | BRCMF_ERROR(("%s: HT Avail request error: %d\n", | ||
| 1052 | __func__, err)); | ||
| 1053 | return -EBADE; | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | if (pendok && ((bus->ci->buscoretype == PCMCIA_CORE_ID) | ||
| 1057 | && (bus->ci->buscorerev == 9))) { | ||
| 1058 | u32 dummy, retries; | ||
| 1059 | r_sdreg32(bus, &dummy, | ||
| 1060 | offsetof(struct sdpcmd_regs, clockctlstatus), | ||
| 1061 | &retries); | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | /* Check current status */ | ||
| 1065 | clkctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, | ||
| 1066 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | ||
| 1067 | if (err) { | ||
| 1068 | BRCMF_ERROR(("%s: HT Avail read error: %d\n", | ||
| 1069 | __func__, err)); | ||
| 1070 | return -EBADE; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | /* Go to pending and await interrupt if appropriate */ | ||
| 1074 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { | ||
| 1075 | /* Allow only clock-available interrupt */ | ||
| 1076 | devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, | ||
| 1077 | SBSDIO_DEVICE_CTL, &err); | ||
| 1078 | if (err) { | ||
| 1079 | BRCMF_ERROR(("%s: Devctl error setting CA:" | ||
| 1080 | " %d\n", __func__, err)); | ||
| 1081 | return -EBADE; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; | ||
| 1085 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1086 | SBSDIO_DEVICE_CTL, devctl, &err); | ||
| 1087 | BRCMF_INFO(("CLKCTL: set PENDING\n")); | ||
| 1088 | bus->clkstate = CLK_PENDING; | ||
| 1089 | |||
| 1090 | return 0; | ||
| 1091 | } else if (bus->clkstate == CLK_PENDING) { | ||
| 1092 | /* Cancel CA-only interrupt filter */ | ||
| 1093 | devctl = | ||
| 1094 | brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, | ||
| 1095 | SBSDIO_DEVICE_CTL, &err); | ||
| 1096 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | ||
| 1097 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1098 | SBSDIO_DEVICE_CTL, devctl, &err); | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | /* Otherwise, wait here (polling) for HT Avail */ | ||
| 1102 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { | ||
| 1103 | BRCMF_SPINWAIT_SLEEP(sdioh_spinwait_sleep, | ||
| 1104 | ((clkctl = | ||
| 1105 | brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, | ||
| 1106 | SBSDIO_FUNC1_CHIPCLKCSR, | ||
| 1107 | &err)), | ||
| 1108 | !SBSDIO_CLKAV(clkctl, bus->alp_only)), | ||
| 1109 | PMU_MAX_TRANSITION_DLY); | ||
| 1110 | } | ||
| 1111 | if (err) { | ||
| 1112 | BRCMF_ERROR(("%s: HT Avail request error: %d\n", | ||
| 1113 | __func__, err)); | ||
| 1114 | return -EBADE; | ||
| 1115 | } | ||
| 1116 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { | ||
| 1117 | BRCMF_ERROR(("%s: HT Avail timeout (%d): " | ||
| 1118 | "clkctl 0x%02x\n", __func__, | ||
| 1119 | PMU_MAX_TRANSITION_DLY, clkctl)); | ||
| 1120 | return -EBADE; | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | /* Mark clock available */ | ||
| 1124 | bus->clkstate = CLK_AVAIL; | ||
| 1125 | BRCMF_INFO(("CLKCTL: turned ON\n")); | ||
| 1126 | |||
| 1127 | #if defined(BCMDBG) | ||
| 1128 | if (bus->alp_only != true) { | ||
| 1129 | if (SBSDIO_ALPONLY(clkctl)) { | ||
| 1130 | BRCMF_ERROR(("%s: HT Clock should be on.\n", | ||
| 1131 | __func__)); | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | #endif /* defined (BCMDBG) */ | ||
| 1135 | |||
| 1136 | bus->activity = true; | ||
| 1137 | } else { | ||
| 1138 | clkreq = 0; | ||
| 1139 | |||
| 1140 | if (bus->clkstate == CLK_PENDING) { | ||
| 1141 | /* Cancel CA-only interrupt filter */ | ||
| 1142 | devctl = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, | ||
| 1143 | SBSDIO_DEVICE_CTL, &err); | ||
| 1144 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | ||
| 1145 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1146 | SBSDIO_DEVICE_CTL, devctl, &err); | ||
| 1147 | } | ||
| 1148 | |||
| 1149 | bus->clkstate = CLK_SDONLY; | ||
| 1150 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1151 | SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); | ||
| 1152 | BRCMF_INFO(("CLKCTL: turned OFF\n")); | ||
| 1153 | if (err) { | ||
| 1154 | BRCMF_ERROR(("%s: Failed access turning clock off:" | ||
| 1155 | " %d\n", __func__, err)); | ||
| 1156 | return -EBADE; | ||
| 1157 | } | ||
| 1158 | } | ||
| 1159 | return 0; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | /* Change idle/active SD state */ | ||
| 1163 | static int brcmf_sdbrcm_sdclk(struct brcmf_bus *bus, bool on) | ||
| 1164 | { | ||
| 1165 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1166 | |||
| 1167 | if (on) | ||
| 1168 | bus->clkstate = CLK_SDONLY; | ||
| 1169 | else | ||
| 1170 | bus->clkstate = CLK_NONE; | ||
| 1171 | |||
| 1172 | return 0; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | /* Transition SD and backplane clock readiness */ | ||
| 1176 | static int brcmf_sdbrcm_clkctl(struct brcmf_bus *bus, uint target, bool pendok) | ||
| 1177 | { | ||
| 1178 | #ifdef BCMDBG | ||
| 1179 | uint oldstate = bus->clkstate; | ||
| 1180 | #endif /* BCMDBG */ | ||
| 1181 | |||
| 1182 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1183 | |||
| 1184 | /* Early exit if we're already there */ | ||
| 1185 | if (bus->clkstate == target) { | ||
| 1186 | if (target == CLK_AVAIL) { | ||
| 1187 | brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms); | ||
| 1188 | bus->activity = true; | ||
| 1189 | } | ||
| 1190 | return 0; | ||
| 1191 | } | ||
| 1192 | |||
| 1193 | switch (target) { | ||
| 1194 | case CLK_AVAIL: | ||
| 1195 | /* Make sure SD clock is available */ | ||
| 1196 | if (bus->clkstate == CLK_NONE) | ||
| 1197 | brcmf_sdbrcm_sdclk(bus, true); | ||
| 1198 | /* Now request HT Avail on the backplane */ | ||
| 1199 | brcmf_sdbrcm_htclk(bus, true, pendok); | ||
| 1200 | brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms); | ||
| 1201 | bus->activity = true; | ||
| 1202 | break; | ||
| 1203 | |||
| 1204 | case CLK_SDONLY: | ||
| 1205 | /* Remove HT request, or bring up SD clock */ | ||
| 1206 | if (bus->clkstate == CLK_NONE) | ||
| 1207 | brcmf_sdbrcm_sdclk(bus, true); | ||
| 1208 | else if (bus->clkstate == CLK_AVAIL) | ||
| 1209 | brcmf_sdbrcm_htclk(bus, false, false); | ||
| 1210 | else | ||
| 1211 | BRCMF_ERROR(("brcmf_sdbrcm_clkctl: request for %d -> %d" | ||
| 1212 | "\n", bus->clkstate, target)); | ||
| 1213 | brcmf_sdbrcm_wd_timer(bus, brcmf_watchdog_ms); | ||
| 1214 | break; | ||
| 1215 | |||
| 1216 | case CLK_NONE: | ||
| 1217 | /* Make sure to remove HT request */ | ||
| 1218 | if (bus->clkstate == CLK_AVAIL) | ||
| 1219 | brcmf_sdbrcm_htclk(bus, false, false); | ||
| 1220 | /* Now remove the SD clock */ | ||
| 1221 | brcmf_sdbrcm_sdclk(bus, false); | ||
| 1222 | brcmf_sdbrcm_wd_timer(bus, 0); | ||
| 1223 | break; | ||
| 1224 | } | ||
| 1225 | #ifdef BCMDBG | ||
| 1226 | BRCMF_INFO(("brcmf_sdbrcm_clkctl: %d -> %d\n", | ||
| 1227 | oldstate, bus->clkstate)); | ||
| 1228 | #endif /* BCMDBG */ | ||
| 1229 | |||
| 1230 | return 0; | ||
| 1231 | } | ||
| 1232 | |||
| 1233 | int brcmf_sdbrcm_bussleep(struct brcmf_bus *bus, bool sleep) | ||
| 1234 | { | ||
| 1235 | struct brcmf_sdio_card *card = bus->card; | ||
| 1236 | uint retries = 0; | ||
| 1237 | |||
| 1238 | BRCMF_INFO(("brcmf_sdbrcm_bussleep: request %s (currently %s)\n", | ||
| 1239 | (sleep ? "SLEEP" : "WAKE"), | ||
| 1240 | (bus->sleeping ? "SLEEP" : "WAKE"))); | ||
| 1241 | |||
| 1242 | /* Done if we're already in the requested state */ | ||
| 1243 | if (sleep == bus->sleeping) | ||
| 1244 | return 0; | ||
| 1245 | |||
| 1246 | /* Going to sleep: set the alarm and turn off the lights... */ | ||
| 1247 | if (sleep) { | ||
| 1248 | /* Don't sleep if something is pending */ | ||
| 1249 | if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) | ||
| 1250 | return -EBUSY; | ||
| 1251 | |||
| 1252 | /* Disable SDIO interrupts (no longer interested) */ | ||
| 1253 | brcmf_sdcard_intr_disable(bus->card); | ||
| 1254 | |||
| 1255 | /* Make sure the controller has the bus up */ | ||
| 1256 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
| 1257 | |||
| 1258 | /* Tell device to start using OOB wakeup */ | ||
| 1259 | w_sdreg32(bus, SMB_USE_OOB, | ||
| 1260 | offsetof(struct sdpcmd_regs, tosbmailbox), &retries); | ||
| 1261 | if (retries > retry_limit) | ||
| 1262 | BRCMF_ERROR(("CANNOT SIGNAL CHIP, " | ||
| 1263 | "WILL NOT WAKE UP!!\n")); | ||
| 1264 | |||
| 1265 | /* Turn off our contribution to the HT clock request */ | ||
| 1266 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | ||
| 1267 | |||
| 1268 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1269 | SBSDIO_FUNC1_CHIPCLKCSR, | ||
| 1270 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); | ||
| 1271 | |||
| 1272 | /* Isolate the bus */ | ||
| 1273 | if (bus->ci->chip != BCM4329_CHIP_ID | ||
| 1274 | && bus->ci->chip != BCM4319_CHIP_ID) { | ||
| 1275 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1276 | SBSDIO_DEVICE_CTL, | ||
| 1277 | SBSDIO_DEVCTL_PADS_ISO, NULL); | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | /* Change state */ | ||
| 1281 | bus->sleeping = true; | ||
| 1282 | |||
| 1283 | } else { | ||
| 1284 | /* Waking up: bus power up is ok, set local state */ | ||
| 1285 | |||
| 1286 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1287 | SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | ||
| 1288 | |||
| 1289 | /* Force pad isolation off if possible | ||
| 1290 | (in case power never toggled) */ | ||
| 1291 | if ((bus->ci->buscoretype == PCMCIA_CORE_ID) | ||
| 1292 | && (bus->ci->buscorerev >= 10)) | ||
| 1293 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1294 | SBSDIO_DEVICE_CTL, 0, NULL); | ||
| 1295 | |||
| 1296 | /* Make sure the controller has the bus up */ | ||
| 1297 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
| 1298 | |||
| 1299 | /* Send misc interrupt to indicate OOB not needed */ | ||
| 1300 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata), | ||
| 1301 | &retries); | ||
| 1302 | if (retries <= retry_limit) | ||
| 1303 | w_sdreg32(bus, SMB_DEV_INT, | ||
| 1304 | offsetof(struct sdpcmd_regs, tosbmailbox), | ||
| 1305 | &retries); | ||
| 1306 | |||
| 1307 | if (retries > retry_limit) | ||
| 1308 | BRCMF_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n")); | ||
| 1309 | |||
| 1310 | /* Make sure we have SD bus access */ | ||
| 1311 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | ||
| 1312 | |||
| 1313 | /* Change state */ | ||
| 1314 | bus->sleeping = false; | ||
| 1315 | |||
| 1316 | /* Enable interrupts again */ | ||
| 1317 | if (bus->intr && (bus->drvr->busstate == BRCMF_BUS_DATA)) { | ||
| 1318 | bus->intdis = false; | ||
| 1319 | brcmf_sdcard_intr_enable(bus->card); | ||
| 1320 | } | ||
| 1321 | } | ||
| 1322 | |||
| 1323 | return 0; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | #define BUS_WAKE(bus) \ | ||
| 1327 | do { \ | ||
| 1328 | if ((bus)->sleeping) \ | ||
| 1329 | brcmf_sdbrcm_bussleep((bus), false); \ | ||
| 1330 | } while (0); | ||
| 1331 | |||
| 1332 | /* Writes a HW/SW header into the packet and sends it. */ | ||
| 1333 | /* Assumes: (a) header space already there, (b) caller holds lock */ | ||
| 1334 | static int brcmf_sdbrcm_txpkt(struct brcmf_bus *bus, struct sk_buff *pkt, uint chan, | ||
| 1335 | bool free_pkt) | ||
| 1336 | { | ||
| 1337 | int ret; | ||
| 1338 | u8 *frame; | ||
| 1339 | u16 len, pad = 0; | ||
| 1340 | u32 swheader; | ||
| 1341 | uint retries = 0; | ||
| 1342 | struct brcmf_sdio_card *card; | ||
| 1343 | struct sk_buff *new; | ||
| 1344 | int i; | ||
| 1345 | |||
| 1346 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1347 | |||
| 1348 | card = bus->card; | ||
| 1349 | |||
| 1350 | if (bus->drvr->dongle_reset) { | ||
| 1351 | ret = -EPERM; | ||
| 1352 | goto done; | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | frame = (u8 *) (pkt->data); | ||
| 1356 | |||
| 1357 | /* Add alignment padding, allocate new packet if needed */ | ||
| 1358 | pad = ((unsigned long)frame % BRCMF_SDALIGN); | ||
| 1359 | if (pad) { | ||
| 1360 | if (skb_headroom(pkt) < pad) { | ||
| 1361 | BRCMF_INFO(("%s: insufficient headroom %d for %d pad\n", | ||
| 1362 | __func__, skb_headroom(pkt), pad)); | ||
| 1363 | bus->drvr->tx_realloc++; | ||
| 1364 | new = brcmu_pkt_buf_get_skb(pkt->len + BRCMF_SDALIGN); | ||
| 1365 | if (!new) { | ||
| 1366 | BRCMF_ERROR(("%s: couldn't allocate new " | ||
| 1367 | "%d-byte packet\n", __func__, | ||
| 1368 | pkt->len + BRCMF_SDALIGN)); | ||
| 1369 | ret = -ENOMEM; | ||
| 1370 | goto done; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | PKTALIGN(new, pkt->len, BRCMF_SDALIGN); | ||
| 1374 | memcpy(new->data, pkt->data, pkt->len); | ||
| 1375 | if (free_pkt) | ||
| 1376 | brcmu_pkt_buf_free_skb(pkt); | ||
| 1377 | /* free the pkt if canned one is not used */ | ||
| 1378 | free_pkt = true; | ||
| 1379 | pkt = new; | ||
| 1380 | frame = (u8 *) (pkt->data); | ||
| 1381 | /* precondition: (frame % BRCMF_SDALIGN) == 0) */ | ||
| 1382 | pad = 0; | ||
| 1383 | } else { | ||
| 1384 | skb_push(pkt, pad); | ||
| 1385 | frame = (u8 *) (pkt->data); | ||
| 1386 | /* precondition: pad + SDPCM_HDRLEN <= pkt->len */ | ||
| 1387 | memset(frame, 0, pad + SDPCM_HDRLEN); | ||
| 1388 | } | ||
| 1389 | } | ||
| 1390 | /* precondition: pad < BRCMF_SDALIGN */ | ||
| 1391 | |||
| 1392 | /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ | ||
| 1393 | len = (u16) (pkt->len); | ||
| 1394 | *(u16 *) frame = cpu_to_le16(len); | ||
| 1395 | *(((u16 *) frame) + 1) = cpu_to_le16(~len); | ||
| 1396 | |||
| 1397 | /* Software tag: channel, sequence number, data offset */ | ||
| 1398 | swheader = | ||
| 1399 | ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | | ||
| 1400 | (((pad + | ||
| 1401 | SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); | ||
| 1402 | |||
| 1403 | put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); | ||
| 1404 | put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); | ||
| 1405 | |||
| 1406 | #ifdef BCMDBG | ||
| 1407 | tx_packets[pkt->priority]++; | ||
| 1408 | if (BRCMF_BYTES_ON() && | ||
| 1409 | (((BRCMF_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || | ||
| 1410 | (BRCMF_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { | ||
| 1411 | printk(KERN_DEBUG "Tx Frame:\n"); | ||
| 1412 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, frame, len); | ||
| 1413 | } else if (BRCMF_HDRS_ON()) { | ||
| 1414 | printk(KERN_DEBUG "TxHdr:\n"); | ||
| 1415 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, | ||
| 1416 | frame, min_t(u16, len, 16)); | ||
| 1417 | } | ||
| 1418 | #endif | ||
| 1419 | |||
| 1420 | /* Raise len to next SDIO block to eliminate tail command */ | ||
| 1421 | if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { | ||
| 1422 | u16 pad = bus->blocksize - (len % bus->blocksize); | ||
| 1423 | if ((pad <= bus->roundup) && (pad < bus->blocksize)) | ||
| 1424 | len += pad; | ||
| 1425 | } else if (len % BRCMF_SDALIGN) { | ||
| 1426 | len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | /* Some controllers have trouble with odd bytes -- round to even */ | ||
| 1430 | if (forcealign && (len & (ALIGNMENT - 1))) { | ||
| 1431 | len = roundup(len, ALIGNMENT); | ||
| 1432 | } | ||
| 1433 | |||
| 1434 | do { | ||
| 1435 | ret = brcmf_sdbrcm_send_buf(bus, brcmf_sdcard_cur_sbwad(card), | ||
| 1436 | SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL); | ||
| 1437 | bus->f2txdata++; | ||
| 1438 | |||
| 1439 | if (ret < 0) { | ||
| 1440 | /* On failure, abort the command | ||
| 1441 | and terminate the frame */ | ||
| 1442 | BRCMF_INFO(("%s: sdio error %d, abort command and " | ||
| 1443 | "terminate frame.\n", __func__, ret)); | ||
| 1444 | bus->tx_sderrs++; | ||
| 1445 | |||
| 1446 | brcmf_sdcard_abort(card, SDIO_FUNC_2); | ||
| 1447 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1448 | SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, | ||
| 1449 | NULL); | ||
| 1450 | bus->f1regdata++; | ||
| 1451 | |||
| 1452 | for (i = 0; i < 3; i++) { | ||
| 1453 | u8 hi, lo; | ||
| 1454 | hi = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, | ||
| 1455 | SBSDIO_FUNC1_WFRAMEBCHI, | ||
| 1456 | NULL); | ||
| 1457 | lo = brcmf_sdcard_cfg_read(card, SDIO_FUNC_1, | ||
| 1458 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
| 1459 | NULL); | ||
| 1460 | bus->f1regdata += 2; | ||
| 1461 | if ((hi == 0) && (lo == 0)) | ||
| 1462 | break; | ||
| 1463 | } | ||
| 1464 | |||
| 1465 | } | ||
| 1466 | if (ret == 0) | ||
| 1467 | bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; | ||
| 1468 | |||
| 1469 | } while ((ret < 0) && retrydata && retries++ < TXRETRIES); | ||
| 1470 | |||
| 1471 | done: | ||
| 1472 | /* restore pkt buffer pointer before calling tx complete routine */ | ||
| 1473 | skb_pull(pkt, SDPCM_HDRLEN + pad); | ||
| 1474 | brcmf_sdbrcm_sdunlock(bus); | ||
| 1475 | brcmf_txcomplete(bus->drvr, pkt, ret != 0); | ||
| 1476 | brcmf_sdbrcm_sdlock(bus); | ||
| 1477 | |||
| 1478 | if (free_pkt) | ||
| 1479 | brcmu_pkt_buf_free_skb(pkt); | ||
| 1480 | |||
| 1481 | return ret; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | int brcmf_sdbrcm_bus_txdata(struct brcmf_bus *bus, struct sk_buff *pkt) | ||
| 1485 | { | ||
| 1486 | int ret = -EBADE; | ||
| 1487 | uint datalen, prec; | ||
| 1488 | |||
| 1489 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1490 | |||
| 1491 | datalen = pkt->len; | ||
| 1492 | |||
| 1493 | #ifdef SDTEST | ||
| 1494 | /* Push the test header if doing loopback */ | ||
| 1495 | if (bus->ext_loop) { | ||
| 1496 | u8 *data; | ||
| 1497 | skb_push(pkt, SDPCM_TEST_HDRLEN); | ||
| 1498 | data = pkt->data; | ||
| 1499 | *data++ = SDPCM_TEST_ECHOREQ; | ||
| 1500 | *data++ = (u8) bus->loopid++; | ||
| 1501 | *data++ = (datalen >> 0); | ||
| 1502 | *data++ = (datalen >> 8); | ||
| 1503 | datalen += SDPCM_TEST_HDRLEN; | ||
| 1504 | } | ||
| 1505 | #endif /* SDTEST */ | ||
| 1506 | |||
| 1507 | /* Add space for the header */ | ||
| 1508 | skb_push(pkt, SDPCM_HDRLEN); | ||
| 1509 | /* precondition: IS_ALIGNED((unsigned long)(pkt->data), 2) */ | ||
| 1510 | |||
| 1511 | prec = PRIO2PREC((pkt->priority & PRIOMASK)); | ||
| 1512 | |||
| 1513 | /* Check for existing queue, current flow-control, | ||
| 1514 | pending event, or pending clock */ | ||
| 1515 | if (brcmf_deferred_tx || bus->fcstate || pktq_len(&bus->txq) | ||
| 1516 | || bus->dpc_sched || (!DATAOK(bus)) | ||
| 1517 | || (bus->flowcontrol & NBITVAL(prec)) | ||
| 1518 | || (bus->clkstate != CLK_AVAIL)) { | ||
| 1519 | BRCMF_TRACE(("%s: deferring pktq len %d\n", __func__, | ||
| 1520 | pktq_len(&bus->txq))); | ||
| 1521 | bus->fcqueued++; | ||
| 1522 | |||
| 1523 | /* Priority based enq */ | ||
| 1524 | spin_lock_bh(&bus->txqlock); | ||
| 1525 | if (brcmf_c_prec_enq(bus->drvr, &bus->txq, pkt, prec) == false) { | ||
| 1526 | skb_pull(pkt, SDPCM_HDRLEN); | ||
| 1527 | brcmf_txcomplete(bus->drvr, pkt, false); | ||
| 1528 | brcmu_pkt_buf_free_skb(pkt); | ||
| 1529 | BRCMF_ERROR(("%s: out of bus->txq !!!\n", __func__)); | ||
| 1530 | ret = -ENOSR; | ||
| 1531 | } else { | ||
| 1532 | ret = 0; | ||
| 1533 | } | ||
| 1534 | spin_unlock_bh(&bus->txqlock); | ||
| 1535 | |||
| 1536 | if (pktq_len(&bus->txq) >= TXHI) | ||
| 1537 | brcmf_txflowcontrol(bus->drvr, 0, ON); | ||
| 1538 | |||
| 1539 | #ifdef BCMDBG | ||
| 1540 | if (pktq_plen(&bus->txq, prec) > qcount[prec]) | ||
| 1541 | qcount[prec] = pktq_plen(&bus->txq, prec); | ||
| 1542 | #endif | ||
| 1543 | /* Schedule DPC if needed to send queued packet(s) */ | ||
| 1544 | if (brcmf_deferred_tx && !bus->dpc_sched) { | ||
| 1545 | bus->dpc_sched = true; | ||
| 1546 | brcmf_sdbrcm_sched_dpc(bus); | ||
| 1547 | } | ||
| 1548 | } else { | ||
| 1549 | /* Lock: we're about to use shared data/code (and SDIO) */ | ||
| 1550 | brcmf_sdbrcm_sdlock(bus); | ||
| 1551 | |||
| 1552 | /* Otherwise, send it now */ | ||
| 1553 | BUS_WAKE(bus); | ||
| 1554 | /* Make sure back plane ht clk is on, no pending allowed */ | ||
| 1555 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, true); | ||
| 1556 | |||
| 1557 | #ifndef SDTEST | ||
| 1558 | BRCMF_TRACE(("%s: calling txpkt\n", __func__)); | ||
| 1559 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); | ||
| 1560 | #else | ||
| 1561 | ret = brcmf_sdbrcm_txpkt(bus, pkt, | ||
| 1562 | (bus->ext_loop ? SDPCM_TEST_CHANNEL : | ||
| 1563 | SDPCM_DATA_CHANNEL), true); | ||
| 1564 | #endif | ||
| 1565 | if (ret) | ||
| 1566 | bus->drvr->tx_errors++; | ||
| 1567 | else | ||
| 1568 | bus->drvr->dstats.tx_bytes += datalen; | ||
| 1569 | |||
| 1570 | if (bus->idletime == BRCMF_IDLE_IMMEDIATE && | ||
| 1571 | !bus->dpc_sched) { | ||
| 1572 | bus->activity = false; | ||
| 1573 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | ||
| 1574 | } | ||
| 1575 | |||
| 1576 | brcmf_sdbrcm_sdunlock(bus); | ||
| 1577 | } | ||
| 1578 | |||
| 1579 | return ret; | ||
| 1580 | } | ||
| 1581 | |||
| 1582 | static uint brcmf_sdbrcm_sendfromq(struct brcmf_bus *bus, uint maxframes) | ||
| 1583 | { | ||
| 1584 | struct sk_buff *pkt; | ||
| 1585 | u32 intstatus = 0; | ||
| 1586 | uint retries = 0; | ||
| 1587 | int ret = 0, prec_out; | ||
| 1588 | uint cnt = 0; | ||
| 1589 | uint datalen; | ||
| 1590 | u8 tx_prec_map; | ||
| 1591 | |||
| 1592 | struct brcmf_pub *drvr = bus->drvr; | ||
| 1593 | |||
| 1594 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1595 | |||
| 1596 | tx_prec_map = ~bus->flowcontrol; | ||
| 1597 | |||
| 1598 | /* Send frames until the limit or some other event */ | ||
| 1599 | for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) { | ||
| 1600 | spin_lock_bh(&bus->txqlock); | ||
| 1601 | pkt = brcmu_pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); | ||
| 1602 | if (pkt == NULL) { | ||
| 1603 | spin_unlock_bh(&bus->txqlock); | ||
| 1604 | break; | ||
| 1605 | } | ||
| 1606 | spin_unlock_bh(&bus->txqlock); | ||
| 1607 | datalen = pkt->len - SDPCM_HDRLEN; | ||
| 1608 | |||
| 1609 | #ifndef SDTEST | ||
| 1610 | ret = brcmf_sdbrcm_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, true); | ||
| 1611 | #else | ||
| 1612 | ret = brcmf_sdbrcm_txpkt(bus, pkt, | ||
| 1613 | (bus->ext_loop ? SDPCM_TEST_CHANNEL : | ||
| 1614 | SDPCM_DATA_CHANNEL), true); | ||
| 1615 | #endif | ||
| 1616 | if (ret) | ||
| 1617 | bus->drvr->tx_errors++; | ||
| 1618 | else | ||
| 1619 | bus->drvr->dstats.tx_bytes += datalen; | ||
| 1620 | |||
| 1621 | /* In poll mode, need to check for other events */ | ||
| 1622 | if (!bus->intr && cnt) { | ||
| 1623 | /* Check device status, signal pending interrupt */ | ||
| 1624 | r_sdreg32(bus, &intstatus, | ||
| 1625 | offsetof(struct sdpcmd_regs, intstatus), | ||
| 1626 | &retries); | ||
| 1627 | bus->f2txdata++; | ||
| 1628 | if (brcmf_sdcard_regfail(bus->card)) | ||
| 1629 | break; | ||
| 1630 | if (intstatus & bus->hostintmask) | ||
| 1631 | bus->ipend = true; | ||
| 1632 | } | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | /* Deflow-control stack if needed */ | ||
| 1636 | if (drvr->up && (drvr->busstate == BRCMF_BUS_DATA) && | ||
| 1637 | drvr->txoff && (pktq_len(&bus->txq) < TXLOW)) | ||
| 1638 | brcmf_txflowcontrol(drvr, 0, OFF); | ||
| 1639 | |||
| 1640 | return cnt; | ||
| 1641 | } | ||
| 1642 | |||
| 1643 | int | ||
| 1644 | brcmf_sdbrcm_bus_txctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) | ||
| 1645 | { | ||
| 1646 | u8 *frame; | ||
| 1647 | u16 len; | ||
| 1648 | u32 swheader; | ||
| 1649 | uint retries = 0; | ||
| 1650 | struct brcmf_sdio_card *card = bus->card; | ||
| 1651 | u8 doff = 0; | ||
| 1652 | int ret = -1; | ||
| 1653 | int i; | ||
| 1654 | |||
| 1655 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1656 | |||
| 1657 | if (bus->drvr->dongle_reset) | ||
| 1658 | return -EIO; | ||
| 1659 | |||
| 1660 | /* Back the pointer to make a room for bus header */ | ||
| 1661 | frame = msg - SDPCM_HDRLEN; | ||
| 1662 | len = (msglen += SDPCM_HDRLEN); | ||
| 1663 | |||
| 1664 | /* Add alignment padding (optional for ctl frames) */ | ||
| 1665 | if (brcmf_alignctl) { | ||
| 1666 | doff = ((unsigned long)frame % BRCMF_SDALIGN); | ||
| 1667 | if (doff) { | ||
| 1668 | frame -= doff; | ||
| 1669 | len += doff; | ||
| 1670 | msglen += doff; | ||
| 1671 | memset(frame, 0, doff + SDPCM_HDRLEN); | ||
| 1672 | } | ||
| 1673 | /* precondition: doff < BRCMF_SDALIGN */ | ||
| 1674 | } | ||
| 1675 | doff += SDPCM_HDRLEN; | ||
| 1676 | |||
| 1677 | /* Round send length to next SDIO block */ | ||
| 1678 | if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { | ||
| 1679 | u16 pad = bus->blocksize - (len % bus->blocksize); | ||
| 1680 | if ((pad <= bus->roundup) && (pad < bus->blocksize)) | ||
| 1681 | len += pad; | ||
| 1682 | } else if (len % BRCMF_SDALIGN) { | ||
| 1683 | len += BRCMF_SDALIGN - (len % BRCMF_SDALIGN); | ||
| 1684 | } | ||
| 1685 | |||
| 1686 | /* Satisfy length-alignment requirements */ | ||
| 1687 | if (forcealign && (len & (ALIGNMENT - 1))) | ||
| 1688 | len = roundup(len, ALIGNMENT); | ||
| 1689 | |||
| 1690 | /* precondition: IS_ALIGNED((unsigned long)frame, 2) */ | ||
| 1691 | |||
| 1692 | /* Need to lock here to protect txseq and SDIO tx calls */ | ||
| 1693 | brcmf_sdbrcm_sdlock(bus); | ||
| 1694 | |||
| 1695 | BUS_WAKE(bus); | ||
| 1696 | |||
| 1697 | /* Make sure backplane clock is on */ | ||
| 1698 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
| 1699 | |||
| 1700 | /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ | ||
| 1701 | *(u16 *) frame = cpu_to_le16((u16) msglen); | ||
| 1702 | *(((u16 *) frame) + 1) = cpu_to_le16(~msglen); | ||
| 1703 | |||
| 1704 | /* Software tag: channel, sequence number, data offset */ | ||
| 1705 | swheader = | ||
| 1706 | ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & | ||
| 1707 | SDPCM_CHANNEL_MASK) | ||
| 1708 | | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & | ||
| 1709 | SDPCM_DOFFSET_MASK); | ||
| 1710 | put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN); | ||
| 1711 | put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); | ||
| 1712 | |||
| 1713 | if (!DATAOK(bus)) { | ||
| 1714 | BRCMF_INFO(("%s: No bus credit bus->tx_max %d," | ||
| 1715 | " bus->tx_seq %d\n", __func__, | ||
| 1716 | bus->tx_max, bus->tx_seq)); | ||
| 1717 | bus->ctrl_frame_stat = true; | ||
| 1718 | /* Send from dpc */ | ||
| 1719 | bus->ctrl_frame_buf = frame; | ||
| 1720 | bus->ctrl_frame_len = len; | ||
| 1721 | |||
| 1722 | brcmf_sdbrcm_wait_for_event(bus, &bus->ctrl_frame_stat); | ||
| 1723 | |||
| 1724 | if (bus->ctrl_frame_stat == false) { | ||
| 1725 | BRCMF_INFO(("%s: ctrl_frame_stat == false\n", | ||
| 1726 | __func__)); | ||
| 1727 | ret = 0; | ||
| 1728 | } else { | ||
| 1729 | BRCMF_INFO(("%s: ctrl_frame_stat == true\n", __func__)); | ||
| 1730 | ret = -1; | ||
| 1731 | } | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | if (ret == -1) { | ||
| 1735 | #ifdef BCMDBG | ||
| 1736 | if (BRCMF_BYTES_ON() && BRCMF_CTL_ON()) { | ||
| 1737 | printk(KERN_DEBUG "Tx Frame:\n"); | ||
| 1738 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, | ||
| 1739 | frame, len); | ||
| 1740 | } else if (BRCMF_HDRS_ON()) { | ||
| 1741 | printk(KERN_DEBUG "TxHdr:\n"); | ||
| 1742 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, | ||
| 1743 | frame, min_t(u16, len, 16)); | ||
| 1744 | } | ||
| 1745 | #endif | ||
| 1746 | |||
| 1747 | do { | ||
| 1748 | bus->ctrl_frame_stat = false; | ||
| 1749 | ret = brcmf_sdbrcm_send_buf(bus, | ||
| 1750 | brcmf_sdcard_cur_sbwad(card), SDIO_FUNC_2, | ||
| 1751 | F2SYNC, frame, len, NULL, NULL, NULL); | ||
| 1752 | |||
| 1753 | if (ret < 0) { | ||
| 1754 | /* On failure, abort the command and | ||
| 1755 | terminate the frame */ | ||
| 1756 | BRCMF_INFO(("%s: sdio error %d, abort command " | ||
| 1757 | "and terminate frame.\n", | ||
| 1758 | __func__, ret)); | ||
| 1759 | bus->tx_sderrs++; | ||
| 1760 | |||
| 1761 | brcmf_sdcard_abort(card, SDIO_FUNC_2); | ||
| 1762 | |||
| 1763 | brcmf_sdcard_cfg_write(card, SDIO_FUNC_1, | ||
| 1764 | SBSDIO_FUNC1_FRAMECTRL, | ||
| 1765 | SFC_WF_TERM, NULL); | ||
| 1766 | bus->f1regdata++; | ||
| 1767 | |||
| 1768 | for (i = 0; i < 3; i++) { | ||
| 1769 | u8 hi, lo; | ||
| 1770 | hi = brcmf_sdcard_cfg_read(card, | ||
| 1771 | SDIO_FUNC_1, | ||
| 1772 | SBSDIO_FUNC1_WFRAMEBCHI, | ||
| 1773 | NULL); | ||
| 1774 | lo = brcmf_sdcard_cfg_read(card, | ||
| 1775 | SDIO_FUNC_1, | ||
| 1776 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
| 1777 | NULL); | ||
| 1778 | bus->f1regdata += 2; | ||
| 1779 | if ((hi == 0) && (lo == 0)) | ||
| 1780 | break; | ||
| 1781 | } | ||
| 1782 | |||
| 1783 | } | ||
| 1784 | if (ret == 0) { | ||
| 1785 | bus->tx_seq = | ||
| 1786 | (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; | ||
| 1787 | } | ||
| 1788 | } while ((ret < 0) && retries++ < TXRETRIES); | ||
| 1789 | } | ||
| 1790 | |||
| 1791 | if ((bus->idletime == BRCMF_IDLE_IMMEDIATE) && !bus->dpc_sched) { | ||
| 1792 | bus->activity = false; | ||
| 1793 | brcmf_sdbrcm_clkctl(bus, CLK_NONE, true); | ||
| 1794 | } | ||
| 1795 | |||
| 1796 | brcmf_sdbrcm_sdunlock(bus); | ||
| 1797 | |||
| 1798 | if (ret) | ||
| 1799 | bus->drvr->tx_ctlerrs++; | ||
| 1800 | else | ||
| 1801 | bus->drvr->tx_ctlpkts++; | ||
| 1802 | |||
| 1803 | return ret ? -EIO : 0; | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | int brcmf_sdbrcm_bus_rxctl(struct brcmf_bus *bus, unsigned char *msg, uint msglen) | ||
| 1807 | { | ||
| 1808 | int timeleft; | ||
| 1809 | uint rxlen = 0; | ||
| 1810 | bool pending; | ||
| 1811 | |||
| 1812 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 1813 | |||
| 1814 | if (bus->drvr->dongle_reset) | ||
| 1815 | return -EIO; | ||
| 1816 | |||
| 1817 | /* Wait until control frame is available */ | ||
| 1818 | timeleft = brcmf_os_ioctl_resp_wait(bus->drvr, &bus->rxlen, &pending); | ||
| 1819 | |||
| 1820 | brcmf_sdbrcm_sdlock(bus); | ||
| 1821 | rxlen = bus->rxlen; | ||
| 1822 | memcpy(msg, bus->rxctl, min(msglen, rxlen)); | ||
| 1823 | bus->rxlen = 0; | ||
| 1824 | brcmf_sdbrcm_sdunlock(bus); | ||
| 1825 | |||
| 1826 | if (rxlen) { | ||
| 1827 | BRCMF_CTL(("%s: resumed on rxctl frame, got %d expected %d\n", | ||
| 1828 | __func__, rxlen, msglen)); | ||
| 1829 | } else if (timeleft == 0) { | ||
| 1830 | BRCMF_ERROR(("%s: resumed on timeout\n", __func__)); | ||
| 1831 | #ifdef BCMDBG | ||
| 1832 | brcmf_sdbrcm_sdlock(bus); | ||
| 1833 | brcmf_sdbrcm_checkdied(bus, NULL, 0); | ||
| 1834 | brcmf_sdbrcm_sdunlock(bus); | ||
| 1835 | #endif /* BCMDBG */ | ||
| 1836 | } else if (pending == true) { | ||
| 1837 | BRCMF_CTL(("%s: cancelled\n", __func__)); | ||
| 1838 | return -ERESTARTSYS; | ||
| 1839 | } else { | ||
| 1840 | BRCMF_CTL(("%s: resumed for unknown reason?\n", __func__)); | ||
| 1841 | #ifdef BCMDBG | ||
| 1842 | brcmf_sdbrcm_sdlock(bus); | ||
| 1843 | brcmf_sdbrcm_checkdied(bus, NULL, 0); | ||
| 1844 | brcmf_sdbrcm_sdunlock(bus); | ||
| 1845 | #endif /* BCMDBG */ | ||
| 1846 | } | ||
| 1847 | |||
| 1848 | if (rxlen) | ||
| 1849 | bus->drvr->rx_ctlpkts++; | ||
| 1850 | else | ||
| 1851 | bus->drvr->rx_ctlerrs++; | ||
| 1852 | |||
| 1853 | return rxlen ? (int)rxlen : -ETIMEDOUT; | ||
| 1854 | } | ||
| 1855 | |||
| 1856 | /* IOVar table */ | ||
| 1857 | enum { | ||
| 1858 | IOV_INTR = 1, | ||
| 1859 | IOV_POLLRATE, | ||
| 1860 | IOV_SDREG, | ||
| 1861 | IOV_SBREG, | ||
| 1862 | IOV_SDCIS, | ||
| 1863 | IOV_MEMBYTES, | ||
| 1864 | IOV_MEMSIZE, | ||
| 1865 | #ifdef BCMDBG | ||
| 1866 | IOV_CHECKDIED, | ||
| 1867 | IOV_CONS, | ||
| 1868 | IOV_DCONSOLE_POLL, | ||
| 1869 | #endif | ||
| 1870 | IOV_DOWNLOAD, | ||
| 1871 | IOV_FORCEEVEN, | ||
| 1872 | IOV_SDIOD_DRIVE, | ||
| 1873 | IOV_READAHEAD, | ||
| 1874 | IOV_SDRXCHAIN, | ||
| 1875 | IOV_ALIGNCTL, | ||
| 1876 | IOV_SDALIGN, | ||
| 1877 | IOV_DEVRESET, | ||
| 1878 | IOV_CPU, | ||
| 1879 | #ifdef SDTEST | ||
| 1880 | IOV_PKTGEN, | ||
| 1881 | IOV_EXTLOOP, | ||
| 1882 | #endif /* SDTEST */ | ||
| 1883 | IOV_SPROM, | ||
| 1884 | IOV_TXBOUND, | ||
| 1885 | IOV_RXBOUND, | ||
| 1886 | IOV_TXMINMAX, | ||
| 1887 | IOV_IDLETIME, | ||
| 1888 | IOV_IDLECLOCK, | ||
| 1889 | IOV_SD1IDLE, | ||
| 1890 | IOV_SLEEP, | ||
| 1891 | IOV_WDTICK, | ||
| 1892 | IOV_VARS | ||
| 1893 | }; | ||
| 1894 | |||
| 1895 | const struct brcmu_iovar brcmf_sdio_iovars[] = { | ||
| 1896 | {"intr", IOV_INTR, 0, IOVT_BOOL, 0}, | ||
| 1897 | {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0}, | ||
| 1898 | {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0}, | ||
| 1899 | {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0}, | ||
| 1900 | {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0}, | ||
| 1901 | {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0}, | ||
| 1902 | {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int)}, | ||
| 1903 | {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0}, | ||
| 1904 | {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0}, | ||
| 1905 | {"vars", IOV_VARS, 0, IOVT_BUFFER, 0}, | ||
| 1906 | {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0}, | ||
| 1907 | {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0}, | ||
| 1908 | {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0}, | ||
| 1909 | {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0}, | ||
| 1910 | {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0}, | ||
| 1911 | {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0}, | ||
| 1912 | {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0}, | ||
| 1913 | #ifdef BCMDBG | ||
| 1914 | {"cons", IOV_CONS, 0, IOVT_BUFFER, 0} | ||
| 1915 | , | ||
| 1916 | {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0} | ||
| 1917 | , | ||
| 1918 | {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)} | ||
| 1919 | , | ||
| 1920 | {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(struct brcmf_sdreg)} | ||
| 1921 | , | ||
| 1922 | {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, BRCMF_IOCTL_MAXLEN} | ||
| 1923 | , | ||
| 1924 | {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0} | ||
| 1925 | , | ||
| 1926 | {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0} | ||
| 1927 | , | ||
| 1928 | {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0} | ||
| 1929 | , | ||
| 1930 | {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0} | ||
| 1931 | , | ||
| 1932 | {"cpu", IOV_CPU, 0, IOVT_BOOL, 0} | ||
| 1933 | , | ||
| 1934 | {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0} | ||
| 1935 | , | ||
| 1936 | #endif /* BCMDBG */ | ||
| 1937 | #ifdef SDTEST | ||
| 1938 | {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0} | ||
| 1939 | , | ||
| 1940 | {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(struct brcmf_pktgen)} | ||
| 1941 | , | ||
| 1942 | #endif /* SDTEST */ | ||
| 1943 | |||
| 1944 | {NULL, 0, 0, 0, 0} | ||
| 1945 | }; | ||
| 1946 | |||
| 1947 | static void | ||
| 1948 | brcmf_dump_pct(struct brcmu_strbuf *strbuf, char *desc, uint num, uint div) | ||
| 1949 | { | ||
| 1950 | uint q1, q2; | ||
| 1951 | |||
| 1952 | if (!div) { | ||
| 1953 | brcmu_bprintf(strbuf, "%s N/A", desc); | ||
| 1954 | } else { | ||
| 1955 | q1 = num / div; | ||
| 1956 | q2 = (100 * (num - (q1 * div))) / div; | ||
| 1957 | brcmu_bprintf(strbuf, "%s %d.%02d", desc, q1, q2); | ||
| 1958 | } | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | void brcmf_sdbrcm_bus_dump(struct brcmf_pub *drvr, struct brcmu_strbuf *strbuf) | ||
| 1962 | { | ||
| 1963 | struct brcmf_bus *bus = drvr->bus; | ||
| 1964 | |||
| 1965 | brcmu_bprintf(strbuf, "Bus SDIO structure:\n"); | ||
| 1966 | brcmu_bprintf(strbuf, | ||
| 1967 | "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n", | ||
| 1968 | bus->hostintmask, bus->intstatus, bus->sdpcm_ver); | ||
| 1969 | brcmu_bprintf(strbuf, | ||
| 1970 | "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n", | ||
| 1971 | bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, | ||
| 1972 | bus->rxskip, bus->rxlen, bus->rx_seq); | ||
| 1973 | brcmu_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n", | ||
| 1974 | bus->intr, bus->intrcount, bus->lastintrs, bus->spurious); | ||
| 1975 | brcmu_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n", | ||
| 1976 | bus->pollrate, bus->pollcnt, bus->regfails); | ||
| 1977 | |||
| 1978 | brcmu_bprintf(strbuf, "\nAdditional counters:\n"); | ||
| 1979 | brcmu_bprintf(strbuf, | ||
| 1980 | "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n", | ||
| 1981 | bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong, | ||
| 1982 | bus->rxc_errors); | ||
| 1983 | brcmu_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n", | ||
| 1984 | bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq); | ||
| 1985 | brcmu_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", | ||
| 1986 | bus->fc_rcvd, bus->fc_xoff, bus->fc_xon); | ||
| 1987 | brcmu_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n", | ||
| 1988 | bus->rxglomfail, bus->rxglomframes, bus->rxglompkts); | ||
| 1989 | brcmu_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs" | ||
| 1990 | " %d\n", | ||
| 1991 | (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, | ||
| 1992 | bus->f2rxdata, bus->f2txdata, bus->f1regdata); | ||
| 1993 | { | ||
| 1994 | brcmf_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->drvr->rx_packets, | ||
| 1995 | (bus->f2rxhdrs + bus->f2rxdata)); | ||
| 1996 | brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->rx_packets, | ||
| 1997 | bus->f1regdata); | ||
| 1998 | brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->rx_packets, | ||
| 1999 | (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata)); | ||
| 2000 | brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->rx_packets, | ||
| 2001 | bus->intrcount); | ||
| 2002 | brcmu_bprintf(strbuf, "\n"); | ||
| 2003 | |||
| 2004 | brcmf_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts), | ||
| 2005 | bus->drvr->rx_packets); | ||
| 2006 | brcmf_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, | ||
| 2007 | bus->rxglomframes); | ||
| 2008 | brcmu_bprintf(strbuf, "\n"); | ||
| 2009 | |||
| 2010 | brcmf_dump_pct(strbuf, "Tx: pkts/f2wr", bus->drvr->tx_packets, | ||
| 2011 | bus->f2txdata); | ||
| 2012 | brcmf_dump_pct(strbuf, ", pkts/f1sd", bus->drvr->tx_packets, | ||
| 2013 | bus->f1regdata); | ||
| 2014 | brcmf_dump_pct(strbuf, ", pkts/sd", bus->drvr->tx_packets, | ||
| 2015 | (bus->f2txdata + bus->f1regdata)); | ||
| 2016 | brcmf_dump_pct(strbuf, ", pkts/int", bus->drvr->tx_packets, | ||
| 2017 | bus->intrcount); | ||
| 2018 | brcmu_bprintf(strbuf, "\n"); | ||
| 2019 | |||
| 2020 | brcmf_dump_pct(strbuf, "Total: pkts/f2rw", | ||
| 2021 | (bus->drvr->tx_packets + bus->drvr->rx_packets), | ||
| 2022 | (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata)); | ||
| 2023 | brcmf_dump_pct(strbuf, ", pkts/f1sd", | ||
| 2024 | (bus->drvr->tx_packets + bus->drvr->rx_packets), | ||
| 2025 | bus->f1regdata); | ||
| 2026 | brcmf_dump_pct(strbuf, ", pkts/sd", | ||
| 2027 | (bus->drvr->tx_packets + bus->drvr->rx_packets), | ||
| 2028 | (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + | ||
| 2029 | bus->f1regdata)); | ||
| 2030 | brcmf_dump_pct(strbuf, ", pkts/int", | ||
| 2031 | (bus->drvr->tx_packets + bus->drvr->rx_packets), | ||
| 2032 | bus->intrcount); | ||
| 2033 | brcmu_bprintf(strbuf, "\n\n"); | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | #ifdef SDTEST | ||
| 2037 | if (bus->pktgen_count) { | ||
| 2038 | brcmu_bprintf(strbuf, "pktgen config and count:\n"); | ||
| 2039 | brcmu_bprintf(strbuf, | ||
| 2040 | "freq %d count %d print %d total %d min %d len %d\n", | ||
| 2041 | bus->pktgen_freq, bus->pktgen_count, | ||
| 2042 | bus->pktgen_print, bus->pktgen_total, | ||
| 2043 | bus->pktgen_minlen, bus->pktgen_maxlen); | ||
| 2044 | brcmu_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n", | ||
| 2045 | bus->pktgen_sent, bus->pktgen_rcvd, | ||
| 2046 | bus->pktgen_fail); | ||
| 2047 | } | ||
| 2048 | #endif /* SDTEST */ | ||
| 2049 | #ifdef BCMDBG | ||
| 2050 | brcmu_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n", | ||
| 2051 | bus->dpc_sched, " not "); | ||
| 2052 | brcmu_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize, | ||
| 2053 | bus->roundup); | ||
| 2054 | #endif /* BCMDBG */ | ||
| 2055 | brcmu_bprintf(strbuf, | ||
| 2056 | "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n", | ||
| 2057 | bus->clkstate, bus->activity, bus->idletime, bus->idlecount, | ||
| 2058 | bus->sleeping); | ||
| 2059 | } | ||
| 2060 | |||
| 2061 | void brcmf_bus_clearcounts(struct brcmf_pub *drvr) | ||
| 2062 | { | ||
| 2063 | struct brcmf_bus *bus = (struct brcmf_bus *) drvr->bus; | ||
| 2064 | |||
| 2065 | bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0; | ||
| 2066 | bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0; | ||
| 2067 | bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0; | ||
| 2068 | bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0; | ||
| 2069 | bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0; | ||
| 2070 | bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0; | ||
| 2071 | } | ||
| 2072 | |||
| 2073 | #ifdef SDTEST | ||
| 2074 | static int brcmf_sdbrcm_pktgen_get(struct brcmf_bus *bus, u8 *arg) | ||
| 2075 | { | ||
| 2076 | struct brcmf_pktgen pktgen; | ||
| 2077 | |||
| 2078 | pktgen.version = BRCMF_PKTGEN_VERSION; | ||
| 2079 | pktgen.freq = bus->pktgen_freq; | ||
| 2080 | pktgen.count = bus->pktgen_count; | ||
| 2081 | pktgen.print = bus->pktgen_print; | ||
| 2082 | pktgen.total = bus->pktgen_total; | ||
| 2083 | pktgen.minlen = bus->pktgen_minlen; | ||
| 2084 | pktgen.maxlen = bus->pktgen_maxlen; | ||
| 2085 | pktgen.numsent = bus->pktgen_sent; | ||
| 2086 | pktgen.numrcvd = bus->pktgen_rcvd; | ||
| 2087 | pktgen.numfail = bus->pktgen_fail; | ||
| 2088 | pktgen.mode = bus->pktgen_mode; | ||
| 2089 | pktgen.stop = bus->pktgen_stop; | ||
| 2090 | |||
| 2091 | memcpy(arg, &pktgen, sizeof(pktgen)); | ||
| 2092 | |||
| 2093 | return 0; | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | static int brcmf_sdbrcm_pktgen_set(struct brcmf_bus *bus, u8 *arg) | ||
| 2097 | { | ||
| 2098 | struct brcmf_pktgen pktgen; | ||
| 2099 | uint oldcnt, oldmode; | ||
| 2100 | |||
| 2101 | memcpy(&pktgen, arg, sizeof(pktgen)); | ||
| 2102 | if (pktgen.version != BRCMF_PKTGEN_VERSION) | ||
| 2103 | return -EINVAL; | ||
| 2104 | |||
| 2105 | oldcnt = bus->pktgen_count; | ||
| 2106 | oldmode = bus->pktgen_mode; | ||
| 2107 | |||
| 2108 | bus->pktgen_freq = pktgen.freq; | ||
| 2109 | bus->pktgen_count = pktgen.count; | ||
| 2110 | bus->pktgen_print = pktgen.print; | ||
| 2111 | bus->pktgen_total = pktgen.total; | ||
| 2112 | bus->pktgen_minlen = pktgen.minlen; | ||
| 2113 | bus->pktgen_maxlen = pktgen.maxlen; | ||
| 2114 | bus->pktgen_mode = pktgen.mode; | ||
| 2115 | bus->pktgen_stop = pktgen.stop; | ||
| 2116 | |||
| 2117 | bus->pktgen_tick = bus->pktgen_ptick = 0; | ||
| 2118 | bus->pktgen_len = max(bus->pktgen_len, bus->pktgen_minlen); | ||
| 2119 | bus->pktgen_len = min(bus->pktgen_len, bus->pktgen_maxlen); | ||
| 2120 | |||
| 2121 | /* Clear counts for a new pktgen (mode change, or was stopped) */ | ||
| 2122 | if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) | ||
| 2123 | bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0; | ||
| 2124 | |||
| 2125 | return 0; | ||
| 2126 | } | ||
| 2127 | #endif /* SDTEST */ | ||
| 2128 | |||
| 2129 | static int | ||
| 2130 | brcmf_sdbrcm_membytes(struct brcmf_bus *bus, bool write, u32 address, u8 *data, | ||
| 2131 | uint size) | ||
| 2132 | { | ||
| 2133 | int bcmerror = 0; | ||
| 2134 | u32 sdaddr; | ||
| 2135 | uint dsize; | ||
| 2136 | |||
| 2137 | /* Determine initial transfer parameters */ | ||
| 2138 | sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; | ||
| 2139 | if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) | ||
| 2140 | dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); | ||
| 2141 | else | ||
| 2142 | dsize = size; | ||
| 2143 | |||
| 2144 | /* Set the backplane window to include the start address */ | ||
| 2145 | bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address); | ||
| 2146 | if (bcmerror) { | ||
| 2147 | BRCMF_ERROR(("%s: window change failed\n", __func__)); | ||
| 2148 | goto xfer_done; | ||
| 2149 | } | ||
| 2150 | |||
| 2151 | /* Do the transfer(s) */ | ||
| 2152 | while (size) { | ||
| 2153 | BRCMF_INFO(("%s: %s %d bytes at offset 0x%08x in window" | ||
| 2154 | " 0x%08x\n", __func__, (write ? "write" : "read"), | ||
| 2155 | dsize, sdaddr, (address & SBSDIO_SBWINDOW_MASK))); | ||
| 2156 | bcmerror = | ||
| 2157 | brcmf_sdcard_rwdata(bus->card, write, sdaddr, data, dsize); | ||
| 2158 | if (bcmerror) { | ||
| 2159 | BRCMF_ERROR(("%s: membytes transfer failed\n", | ||
| 2160 | __func__)); | ||
| 2161 | break; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | /* Adjust for next transfer (if any) */ | ||
| 2165 | size -= dsize; | ||
| 2166 | if (size) { | ||
| 2167 | data += dsize; | ||
| 2168 | address += dsize; | ||
| 2169 | bcmerror = brcmf_sdbrcm_set_siaddr_window(bus, address); | ||
| 2170 | if (bcmerror) { | ||
| 2171 | BRCMF_ERROR(("%s: window change failed\n", | ||
| 2172 | __func__)); | ||
| 2173 | break; | ||
| 2174 | } | ||
| 2175 | sdaddr = 0; | ||
| 2176 | dsize = min_t(uint, SBSDIO_SB_OFT_ADDR_LIMIT, size); | ||
| 2177 | } | ||
| 2178 | } | ||
| 2179 | |||
| 2180 | xfer_done: | ||
| 2181 | /* Return the window to backplane enumeration space for core access */ | ||
| 2182 | if (brcmf_sdbrcm_set_siaddr_window(bus, | ||
| 2183 | brcmf_sdcard_cur_sbwad(bus->card))) { | ||
| 2184 | BRCMF_ERROR(("%s: FAILED to set window back to 0x%x\n", | ||
| 2185 | __func__, brcmf_sdcard_cur_sbwad(bus->card))); | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | return bcmerror; | ||
| 2189 | } | ||
| 2190 | |||
| 2191 | #ifdef BCMDBG | ||
| 2192 | static int brcmf_sdbrcm_readshared(struct brcmf_bus *bus, struct sdpcm_shared *sh) | ||
| 2193 | { | ||
| 2194 | u32 addr; | ||
| 2195 | int rv; | ||
| 2196 | |||
| 2197 | /* Read last word in memory to determine address of | ||
| 2198 | sdpcm_shared structure */ | ||
| 2199 | rv = brcmf_sdbrcm_membytes(bus, false, bus->ramsize - 4, (u8 *)&addr, | ||
| 2200 | 4); | ||
| 2201 | if (rv < 0) | ||
| 2202 | return rv; | ||
| 2203 | |||
| 2204 | addr = le32_to_cpu(addr); | ||
| 2205 | |||
| 2206 | BRCMF_INFO(("sdpcm_shared address 0x%08X\n", addr)); | ||
| 2207 | |||
| 2208 | /* | ||
| 2209 | * Check if addr is valid. | ||
| 2210 | * NVRAM length at the end of memory should have been overwritten. | ||
| 2211 | */ | ||
| 2212 | if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) { | ||
| 2213 | BRCMF_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n", | ||
| 2214 | __func__, addr)); | ||
| 2215 | return -EBADE; | ||
| 2216 | } | ||
| 2217 | |||
| 2218 | /* Read rte_shared structure */ | ||
| 2219 | rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *) sh, | ||
| 2220 | sizeof(struct sdpcm_shared)); | ||
| 2221 | if (rv < 0) | ||
| 2222 | return rv; | ||
| 2223 | |||
| 2224 | /* Endianness */ | ||
| 2225 | sh->flags = le32_to_cpu(sh->flags); | ||
| 2226 | sh->trap_addr = le32_to_cpu(sh->trap_addr); | ||
| 2227 | sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr); | ||
| 2228 | sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr); | ||
| 2229 | sh->assert_line = le32_to_cpu(sh->assert_line); | ||
| 2230 | sh->console_addr = le32_to_cpu(sh->console_addr); | ||
| 2231 | sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr); | ||
| 2232 | |||
| 2233 | if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { | ||
| 2234 | BRCMF_ERROR(("%s: sdpcm_shared version %d in brcmf " | ||
| 2235 | "is different than sdpcm_shared version %d in dongle\n", | ||
| 2236 | __func__, SDPCM_SHARED_VERSION, | ||
| 2237 | sh->flags & SDPCM_SHARED_VERSION_MASK)); | ||
| 2238 | return -EBADE; | ||
| 2239 | } | ||
| 2240 | |||
| 2241 | return 0; | ||
| 2242 | } | ||
| 2243 | |||
| 2244 | static int brcmf_sdbrcm_checkdied(struct brcmf_bus *bus, u8 *data, uint size) | ||
| 2245 | { | ||
| 2246 | int bcmerror = 0; | ||
| 2247 | uint msize = 512; | ||
| 2248 | char *mbuffer = NULL; | ||
| 2249 | uint maxstrlen = 256; | ||
| 2250 | char *str = NULL; | ||
| 2251 | struct brcmf_trap tr; | ||
| 2252 | struct sdpcm_shared sdpcm_shared; | ||
| 2253 | struct brcmu_strbuf strbuf; | ||
| 2254 | |||
| 2255 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 2256 | |||
| 2257 | if (data == NULL) { | ||
| 2258 | /* | ||
| 2259 | * Called after a rx ctrl timeout. "data" is NULL. | ||
| 2260 | * allocate memory to trace the trap or assert. | ||
| 2261 | */ | ||
| 2262 | size = msize; | ||
| 2263 | mbuffer = data = kmalloc(msize, GFP_ATOMIC); | ||
| 2264 | if (mbuffer == NULL) { | ||
| 2265 | BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__, | ||
| 2266 | msize)); | ||
| 2267 | bcmerror = -ENOMEM; | ||
| 2268 | goto done; | ||
| 2269 | } | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | str = kmalloc(maxstrlen, GFP_ATOMIC); | ||
| 2273 | if (str == NULL) { | ||
| 2274 | BRCMF_ERROR(("%s: kmalloc(%d) failed\n", __func__, maxstrlen)); | ||
| 2275 | bcmerror = -ENOMEM; | ||
| 2276 | goto done; | ||
| 2277 | } | ||
| 2278 | |||
| 2279 | bcmerror = brcmf_sdbrcm_readshared(bus, &sdpcm_shared); | ||
| 2280 | if (bcmerror < 0) | ||
| 2281 | goto done; | ||
| 2282 | |||
| 2283 | brcmu_binit(&strbuf, data, size); | ||
| 2284 | |||
| 2285 | brcmu_bprintf(&strbuf, | ||
| 2286 | "msgtrace address : 0x%08X\nconsole address : 0x%08X\n", | ||
| 2287 | sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr); | ||
| 2288 | |||
| 2289 | if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { | ||
| 2290 | /* NOTE: Misspelled assert is intentional - DO NOT FIX. | ||
| 2291 | * (Avoids conflict with real asserts for programmatic | ||
| 2292 | * parsing of output.) | ||
| 2293 | */ | ||
| 2294 | brcmu_bprintf(&strbuf, "Assrt not built in dongle\n"); | ||
| 2295 | } | ||
| 2296 | |||
| 2297 | if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) == | ||
| 2298 | 0) { | ||
| 2299 | /* NOTE: Misspelled assert is intentional - DO NOT FIX. | ||
| 2300 | * (Avoids conflict with real asserts for programmatic | ||
| 2301 | * parsing of output.) | ||
| 2302 | */ | ||
| 2303 | brcmu_bprintf(&strbuf, "No trap%s in dongle", | ||
| 2304 | (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) | ||
| 2305 | ? "/assrt" : ""); | ||
| 2306 | } else { | ||
| 2307 | if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) { | ||
| 2308 | /* Download assert */ | ||
| 2309 | brcmu_bprintf(&strbuf, "Dongle assert"); | ||
| 2310 | if (sdpcm_shared.assert_exp_addr != 0) { | ||
| 2311 | str[0] = '\0'; | ||
| 2312 | bcmerror = brcmf_sdbrcm_membytes(bus, false, | ||
| 2313 | sdpcm_shared.assert_exp_addr, | ||
| 2314 | (u8 *) str, maxstrlen); | ||
| 2315 | if (bcmerror < 0) | ||
| 2316 | goto done; | ||
| 2317 | |||
| 2318 | str[maxstrlen - 1] = '\0'; | ||
| 2319 | brcmu_bprintf(&strbuf, " expr \"%s\"", str); | ||
| 2320 | } | ||
| 2321 | |||
| 2322 | if (sdpcm_shared.assert_file_addr != 0) { | ||
| 2323 | str[0] = '\0'; | ||
| 2324 | bcmerror = brcmf_sdbrcm_membytes(bus, false, | ||
| 2325 | sdpcm_shared.assert_file_addr, | ||
| 2326 | (u8 *) str, maxstrlen); | ||
| 2327 | if (bcmerror < 0) | ||
| 2328 | goto done; | ||
| 2329 | |||
| 2330 | str[maxstrlen - 1] = '\0'; | ||
| 2331 | brcmu_bprintf(&strbuf, " file \"%s\"", str); | ||
| 2332 | } | ||
| 2333 | |||
| 2334 | brcmu_bprintf(&strbuf, " line %d ", | ||
| 2335 | sdpcm_shared.assert_line); | ||
| 2336 | } | ||
| 2337 | |||
| 2338 | if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { | ||
| 2339 | bcmerror = brcmf_sdbrcm_membytes(bus, false, | ||
| 2340 | sdpcm_shared.trap_addr, (u8 *)&tr, | ||
| 2341 | sizeof(struct brcmf_trap)); | ||
| 2342 | if (bcmerror < 0) | ||
| 2343 | goto done; | ||
| 2344 | |||
| 2345 | brcmu_bprintf(&strbuf, | ||
| 2346 | "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x," | ||
| 2347 | "lp 0x%x, rpc 0x%x Trap offset 0x%x, " | ||
| 2348 | "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n", | ||
| 2349 | tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13, | ||
| 2350 | tr.r14, tr.pc, sdpcm_shared.trap_addr, | ||
| 2351 | tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5, | ||
| 2352 | tr.r6, tr.r7); | ||
| 2353 | } | ||
| 2354 | } | ||
| 2355 | |||
| 2356 | if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) | ||
| 2357 | BRCMF_ERROR(("%s: %s\n", __func__, strbuf.origbuf)); | ||
| 2358 | |||
| 2359 | #ifdef BCMDBG | ||
| 2360 | if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { | ||
| 2361 | /* Mem dump to a file on device */ | ||
| 2362 | brcmf_sdbrcm_mem_dump(bus); | ||
| 2363 | } | ||
| 2364 | #endif /* BCMDBG */ | ||
| 2365 | |||
| 2366 | done: | ||
| 2367 | kfree(mbuffer); | ||
| 2368 | kfree(str); | ||
| 2369 | |||
| 2370 | return bcmerror; | ||
| 2371 | } | ||
| 2372 | |||
| 2373 | static int brcmf_sdbrcm_mem_dump(struct brcmf_bus *bus) | ||
| 2374 | { | ||
| 2375 | int ret = 0; | ||
| 2376 | int size; /* Full mem size */ | ||
| 2377 | int start = 0; /* Start address */ | ||
| 2378 | int read_size = 0; /* Read size of each iteration */ | ||
| 2379 | u8 *buf = NULL, *databuf = NULL; | ||
| 2380 | |||
| 2381 | /* Get full mem size */ | ||
| 2382 | size = bus->ramsize; | ||
| 2383 | buf = kmalloc(size, GFP_ATOMIC); | ||
| 2384 | if (!buf) { | ||
| 2385 | BRCMF_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size)); | ||
| 2386 | return -1; | ||
| 2387 | } | ||
| 2388 | |||
| 2389 | /* Read mem content */ | ||
| 2390 | printk(KERN_DEBUG "Dump dongle memory"); | ||
| 2391 | databuf = buf; | ||
| 2392 | while (size) { | ||
| 2393 | read_size = min(MEMBLOCK, size); | ||
| 2394 | ret = brcmf_sdbrcm_membytes(bus, false, start, databuf, | ||
| 2395 | read_size); | ||
| 2396 | if (ret) { | ||
| 2397 | BRCMF_ERROR(("%s: Error membytes %d\n", __func__, ret)); | ||
| 2398 | kfree(buf); | ||
| 2399 | return -1; | ||
| 2400 | } | ||
| 2401 | printk("."); | ||
| 2402 | |||
| 2403 | /* Decrement size and increment start address */ | ||
| 2404 | size -= read_size; | ||
| 2405 | start += read_size; | ||
| 2406 | databuf += read_size; | ||
| 2407 | } | ||
| 2408 | printk(KERN_DEBUG "Done\n"); | ||
| 2409 | |||
| 2410 | /* free buf before return !!! */ | ||
| 2411 | if (brcmf_write_to_file(bus->drvr, buf, bus->ramsize)) { | ||
| 2412 | BRCMF_ERROR(("%s: Error writing to files\n", __func__)); | ||
| 2413 | return -1; | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | /* buf free handled in brcmf_write_to_file, not here */ | ||
| 2417 | return 0; | ||
| 2418 | } | ||
| 2419 | |||
| 2420 | #define CONSOLE_LINE_MAX 192 | ||
| 2421 | |||
| 2422 | static int brcmf_sdbrcm_readconsole(struct brcmf_bus *bus) | ||
| 2423 | { | ||
| 2424 | struct brcmf_console *c = &bus->console; | ||
| 2425 | u8 line[CONSOLE_LINE_MAX], ch; | ||
| 2426 | u32 n, idx, addr; | ||
| 2427 | int rv; | ||
| 2428 | |||
| 2429 | /* Don't do anything until FWREADY updates console address */ | ||
| 2430 | if (bus->console_addr == 0) | ||
| 2431 | return 0; | ||
| 2432 | |||
| 2433 | /* Read console log struct */ | ||
| 2434 | addr = bus->console_addr + offsetof(struct rte_console, log); | ||
| 2435 | rv = brcmf_sdbrcm_membytes(bus, false, addr, (u8 *)&c->log, | ||
| 2436 | sizeof(c->log)); | ||
| 2437 | if (rv < 0) | ||
| 2438 | return rv; | ||
| 2439 | |||
| 2440 | /* Allocate console buffer (one time only) */ | ||
| 2441 | if (c->buf == NULL) { | ||
| 2442 | c->bufsize = le32_to_cpu(c->log.buf_size); | ||
| 2443 | c->buf = kmalloc(c->bufsize, GFP_ATOMIC); | ||
| 2444 | if (c->buf == NULL) | ||
| 2445 | return -ENOMEM; | ||
| 2446 | } | ||
| 2447 | |||
| 2448 | idx = le32_to_cpu(c->log.idx); | ||
| 2449 | |||
| 2450 | /* Protect against corrupt value */ | ||
| 2451 | if (idx > c->bufsize) | ||
| 2452 | return -EBADE; | ||
| 2453 | |||
| 2454 | /* Skip reading the console buffer if the index pointer | ||
| 2455 | has not moved */ | ||
| 2456 | if (idx == c->last) | ||
| 2457 | return 0; | ||
| 2458 | |||
| 2459 | /* Read the console buffer */ | ||
| 2460 | addr = le32_to_cpu(c->log.buf); | ||
| 2461 | rv = brcmf_sdbrcm_membytes(bus, false, addr, c->buf, c->bufsize); | ||
| 2462 | if (rv < 0) | ||
| 2463 | return rv; | ||
| 2464 | |||
| 2465 | while (c->last != idx) { | ||
| 2466 | for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) { | ||
| 2467 | if (c->last == idx) { | ||
| 2468 | /* This would output a partial line. | ||
| 2469 | * Instead, back up | ||
| 2470 | * the buffer pointer and output this | ||
| 2471 | * line next time around. | ||
| 2472 | */ | ||
| 2473 | if (c->last >= n) | ||
| 2474 | c->last -= n; | ||
| 2475 | else | ||
| 2476 | c->last = c->bufsize - n; | ||
| 2477 | goto break2; | ||
| 2478 | } | ||
| 2479 | ch = c->buf[c->last]; | ||
| 2480 | c->last = (c->last + 1) % c->bufsize; | ||
| 2481 | if (ch == '\n') | ||
| 2482 | break; | ||
| 2483 | line[n] = ch; | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | if (n > 0) { | ||
| 2487 | if (line[n - 1] == '\r') | ||
| 2488 | n--; | ||
| 2489 | line[n] = 0; | ||
| 2490 | printk(KERN_DEBUG "CONSOLE: %s\n", line); | ||
| 2491 | } | ||
| 2492 | } | ||
| 2493 | break2: | ||
| 2494 | |||
| 2495 | return 0; | ||
| 2496 | } | ||
| 2497 | #endif /* BCMDBG */ | ||
| 2498 | |||
| 2499 | int brcmf_sdbrcm_downloadvars(struct brcmf_bus *bus, void *arg, int len) | ||
| 2500 | { | ||
| 2501 | int bcmerror = 0; | ||
| 2502 | |||
| 2503 | BRCMF_TRACE(("%s: Enter\n", __func__)); | ||
| 2504 | |||
| 2505 | /* Basic sanity checks */ | ||
| 2506 | if (bus->drvr->up) { | ||
| 2507 | bcmerror = -EISCONN; | ||
| 2508 | goto err; | ||
| 2509 | } | ||
| 2510 | if (!len) { | ||
| 2511 | bcmerror = -EOVERFLOW; | ||
| 2512 | goto err; | ||
| 2513 | } | ||
| 2514 | |||
| 2515 | /* Free the old ones and replace with passed variables */ | ||
| 2516 | kfree(bus->vars); | ||
| 2517 | |||
| 2518 | bus->vars = kmalloc(len, GFP_ATOMIC); | ||
| 2519 | bus->varsz = bus->vars ? len : 0; | ||
| 2520 | if (bus->vars == NULL) { | ||
| 2521 | bcmerror = -ENOMEM; | ||
| 2522 | goto err; | ||
| 2523 | } | ||
| 2524 | |||
| 2525 | /* Copy the passed variables, which should include the | ||
| 2526 | terminating double-null */ | ||
| 2527 | memcpy(bus->vars, arg, bus->varsz); | ||
| 2528 | err: | ||
| 2529 | return bcmerror; | ||
| 2530 | } | ||
| 2531 | |||
| 2532 | static int | ||
| 2533 | brcmf_sdbrcm_doiovar(struct brcmf_bus *bus, const struct brcmu_iovar *vi, u32 actionid, | ||
| 2534 | const char *name, void *params, int plen, void *arg, int len, | ||
| 2535 | int val_size) | ||
| 2536 | { | ||
| 2537 | int bcmerror = 0; | ||
| 2538 | s32 int_val = 0; | ||
| 2539 | bool bool_val = 0; | ||
| 2540 | |||
| 2541 | BRCMF_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p " | ||
| 2542 | "len %d val_size %d\n", __func__, actionid, name, params, | ||
| 2543 | plen, arg, len, val_size)); | ||
| 2544 | |||
| 2545 | bcmerror = brcmu_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid)); | ||
| 2546 | if (bcmerror != 0) | ||
| 2547 | goto exit; | ||
| 2548 | |||
| 2549 | if (plen >= (int)sizeof(int_val)) | ||
| 2550 | memcpy(&int_val, params, sizeof(int_val)); | ||
| 2551 | |||
| 2552 | bool_val = (int_val != 0) ? true : false; | ||
| 2553 | |||
| 2554 | /* Some ioctls use the bus */ | ||
| 2555 | brcmf_sdbrcm_sdlock(bus); | ||
| 2556 | |||
| 2557 | /* Check if dongle is in reset. If so, only allow DEVRESET iovars */ | ||
| 2558 | if (bus->drvr->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) || | ||
| 2559 | actionid == IOV_GVAL(IOV_DEVRESET))) { | ||
| 2560 | bcmerror = -EPERM; | ||
| 2561 | goto exit; | ||
| 2562 | } | ||
| 2563 | |||
| 2564 | /* Handle sleep stuff before any clock mucking */ | ||
| 2565 | if (vi->varid == IOV_SLEEP) { | ||
| 2566 | if (IOV_ISSET(actionid)) { | ||
| 2567 | bcmerror = brcmf_sdbrcm_bussleep(bus, bool_val); | ||
| 2568 | } else { | ||
| 2569 | int_val = (s32) bus->sleeping; | ||
| 2570 | memcpy(arg, &int_val, val_size); | ||
| 2571 | } | ||
| 2572 | goto exit; | ||
| 2573 | } | ||
| 2574 | |||
| 2575 | /* Request clock to allow SDIO accesses */ | ||
| 2576 | if (!bus->drvr->dongle_reset) { | ||
| 2577 | BUS_WAKE(bus); | ||
| 2578 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | ||
| 2579 | } | ||
| 2580 | |||
| 2581 | switch (actionid) { | ||
| 2582 | case IOV_GVAL(IOV_INTR): | ||
| 2583 | int_val = (s32) bus->intr; | ||
| 2584 | memcpy(arg, &int_val, val_size); | ||
| 2585 | break; | ||
| 2586 | |||
| 2587 | case IOV_SVAL(IOV_INTR): | ||
| 2588 | bus->intr = bool_val; | ||
| 2589 | bus->intdis = false; | ||
| 2590 | if (bus->drvr->up) { | ||
| 2591 | BRCMF_INTR(("%s: %s SDIO interrupts\n", __func__, | ||
| 2592 | bus->intr ? "enable" : "disable")); | ||
| 2593 | if (bus->intr) { | ||
| 2594 | brcmf_sdcard_intr_enable(bus->card); | ||
| 2595 | } else { | ||
| 2596 | brcmf_sdcard_intr_disable(bus->card); | ||
| 2597 | } | ||
| 2598 | } | ||
| 2599 | break; | ||
| 2600 | |||
| 2601 | case IOV_GVAL(IOV_POLLRATE): | ||
| 2602 | int_val = (s32) bus->pollrate; | ||
| 2603 | memcpy(arg, &int_val, val_size); | ||
| 2604 | break; | ||
| 2605 | |||
| 2606 | case IOV_SVAL(IOV_POLLRATE): | ||
| 2607 | bus->pollrate = (uint) int_val; | ||
| 2608 | bus->poll = (bus->pollrate != 0); | ||
| 2609 | break; | ||
| 2610 | |||
| 2611 | case IOV_GVAL(IOV_IDLETIME): | ||
| 2612 | int_val = bus->idletime; | ||
| 2613 | memcpy(arg, &int_val, val_size); | ||
| 2614 | break; | ||
| 2615 | |||
| 2616 | case IOV_SVAL(IOV_IDLETIME): | ||
| 2617 | if ((int_val < 0) && (int_val != BRCMF_IDLE_IMMEDIATE)) | ||
| 2618 | bcmerror = -EINVAL; | ||
| 2619 | else | ||
| 2620 | bus->idletime = int_val; | ||
| 2621 | break; | ||
| 2622 | |||
| 2623 | case IOV_GVAL(IOV_IDLECLOCK): | ||
4149 more lines aren’t shown here.
This diff is large: its 348 lines aren’t shown here.
This diff is large: its 4153 lines aren’t shown here.
This diff is large: its 357 lines aren’t shown here.
This diff is large: its 59 lines aren’t shown here.
This diff is large: its 2280 lines aren’t shown here.
This diff is large: its 585 lines aren’t shown here.
This diff is large: its 276 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 1220 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 312 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 3594 lines aren’t shown here.
This diff is large: its 175 lines aren’t shown here.
This diff is large: its 1560 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 1776 lines aren’t shown here.
This diff is large: its 1918 lines aren’t shown here.
This diff is large: its 251 lines aren’t shown here.
This diff is large: its 1940 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 6103 lines aren’t shown here.
This diff is large: its 1026 lines aren’t shown here.
This diff is large: its 851 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 546 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 3226 lines aren’t shown here.
This diff is large: its 295 lines aren’t shown here.
This diff is large: its 1236 lines aren’t shown here.
This diff is large: its 5295 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 29083 lines aren’t shown here.
This diff is large: its 295 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 1534 lines aren’t shown here.
This diff is large: its 168 lines aren’t shown here.
This diff is large: its 3639 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 10630 lines aren’t shown here.
This diff is large: its 41 lines aren’t shown here.
This diff is large: its 219 lines aren’t shown here.
This diff is large: its 165 lines aren’t shown here.
This diff is large: its 475 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 666 lines aren’t shown here.
This diff is large: its 499 lines aren’t shown here.
This diff is large: its 174 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 1238 lines aren’t shown here.
This diff is large: its 35 lines aren’t shown here.
This diff is large: its 478 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 400 lines aren’t shown here.
This diff is large: its 116 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 788 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 302 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 282 lines aren’t shown here.
This diff is large: its 113 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 80 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 2881 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 585 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 112 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 557 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 174 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 99 lines aren’t shown here.
This diff is large: its 1834 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 82 lines aren’t shown here.
This diff is large: its 267 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 62 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 28 lines aren’t shown here.
This diff is large: its 1435 lines aren’t shown here.
This diff is large: its 408 lines aren’t shown here.
This diff is large: its 655 lines aren’t shown here.
This diff is large: its 980 lines aren’t shown here.
This diff is large: its 459 lines aren’t shown here.
This diff is large: its 181 lines aren’t shown here.
This diff is large: its 1153 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 798 lines aren’t shown here.
This diff is large: its 151 lines aren’t shown here.
This diff is large: its 5515 lines aren’t shown here.
This diff is large: its 1731 lines aren’t shown here.
This diff is large: its 244 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 849 lines aren’t shown here.
This diff is large: its 481 lines aren’t shown here.
This diff is large: its 687 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 83 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 73 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 178 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 166 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 126 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 150 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 50 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 1027 lines aren’t shown here.
This diff is large: its 1031 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 335 lines aren’t shown here.
This diff is large: its 731 lines aren’t shown here.
This diff is large: its 278 lines aren’t shown here.
This diff is large: its 417 lines aren’t shown here.
This diff is large: its 565 lines aren’t shown here.
This diff is large: its 1078 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 1055 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 88 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 110 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 107 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 221 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 120 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 597 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 390 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 265 lines aren’t shown here.
This diff is large: its 314 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 283 lines aren’t shown here.
This diff is large: its 288 lines aren’t shown here.
This diff is large: its 214 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 813 lines aren’t shown here.
This diff is large: its 587 lines aren’t shown here.
This diff is large: its 1180 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 998 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 1309 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 158 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 282 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 197 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 451 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 174 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 675 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 461 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 144 lines aren’t shown here.
This diff is large: its 152 lines aren’t shown here.
This diff is large: its 14 lines aren’t shown here.
This diff is large: its 1010 lines aren’t shown here.
This diff is large: its 180 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 102 lines aren’t shown here.
This diff is large: its 101 lines aren’t shown here.
This diff is large: its 658 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 566 lines aren’t shown here.
This diff is large: its 157 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 166 lines aren’t shown here.
This diff is large: its 229 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 677 lines aren’t shown here.
This diff is large: its 560 lines aren’t shown here.
This diff is large: its 808 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 69 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 10 lines aren’t shown here.
This diff is large: its 464 lines aren’t shown here.
This diff is large: its 582 lines aren’t shown here.
This diff is large: its 183 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 162 lines aren’t shown here.
This diff is large: its 223 lines aren’t shown here.
This diff is large: its 391 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 84 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 114 lines aren’t shown here.
This diff is large: its 16 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 197 lines aren’t shown here.
This diff is large: its 186 lines aren’t shown here.
This diff is large: its 213 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
This diff is large: its 95 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 411 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 442 lines aren’t shown here.
This diff is large: its 64 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 218 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 546 lines aren’t shown here.
This diff is large: its 109 lines aren’t shown here.
This diff is large: its 207 lines aren’t shown here.
This diff is large: its 191 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 815 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 903 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 636 lines aren’t shown here.
This diff is large: its 1322 lines aren’t shown here.
This diff is large: its 597 lines aren’t shown here.
This diff is large: its 365 lines aren’t shown here.
This diff is large: its 191 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 174 lines aren’t shown here.
This diff is large: its 632 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 416 lines aren’t shown here.
This diff is large: its 210 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 91 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 167 lines aren’t shown here.
This diff is large: its 139 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 33 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 7 lines aren’t shown here.
This diff is large: its 189 lines aren’t shown here.
This diff is large: its 178 lines aren’t shown here.
This diff is large: its 337 lines aren’t shown here.
This diff is large: its 125 lines aren’t shown here.
This diff is large: its 289 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 188 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 208 lines aren’t shown here.
This diff is large: its 188 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 86 lines aren’t shown here.
This diff is large: its 24 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 1897 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 60 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 141 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 79 lines aren’t shown here.
This diff is large: its 297 lines aren’t shown here.
This diff is large: its 31 lines aren’t shown here.
This diff is large: its 5 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 328 lines aren’t shown here.
This diff is large: its 1155 lines aren’t shown here.
This diff is large: its 266 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 483 lines aren’t shown here.
This diff is large: its 169 lines aren’t shown here.
This diff is large: its 104 lines aren’t shown here.
This diff is large: its 21 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 27 lines aren’t shown here.
This diff is large: its 34 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 3 lines aren’t shown here.
This diff is large: its 217 lines aren’t shown here.
This diff is large: its 156 lines aren’t shown here.
This diff is large: its 219 lines aren’t shown here.
This diff is large: its 103 lines aren’t shown here.
This diff is large: its 2637 lines aren’t shown here.
This diff is large: its 353 lines aren’t shown here.
This diff is large: its 2677 lines aren’t shown here.
This diff is large: its 3279 lines aren’t shown here.
This diff is large: its 956 lines aren’t shown here.
This diff is large: its 873 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 677 lines aren’t shown here.
This diff is large: its 484 lines aren’t shown here.
This diff is large: its 1733 lines aren’t shown here.
This diff is large: its 583 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 628 lines aren’t shown here.
This diff is large: its 340 lines aren’t shown here.
This diff is large: its 142 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 411 lines aren’t shown here.
This diff is large: its 307 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 678 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 1149 lines aren’t shown here.
This diff is large: its 419 lines aren’t shown here.
This diff is large: its 160 lines aren’t shown here.
This diff is large: its 5040 lines aren’t shown here.
This diff is large: its 2396 lines aren’t shown here.
This diff is large: its 63 lines aren’t shown here.
This diff is large: its 2555 lines aren’t shown here.
This diff is large: its 229 lines aren’t shown here.
This diff is large: its 349 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 701 lines aren’t shown here.
This diff is large: its 3337 lines aren’t shown here.
This diff is large: its 52 lines aren’t shown here.
This diff is large: its 1638 lines aren’t shown here.
This diff is large: its 121 lines aren’t shown here.
This diff is large: its 853 lines aren’t shown here.
This diff is large: its 1164 lines aren’t shown here.
This diff is large: its 19 lines aren’t shown here.
This diff is large: its 124 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 445 lines aren’t shown here.
This diff is large: its 208 lines aren’t shown here.
This diff is large: its 352 lines aren’t shown here.
This diff is large: its 2226 lines aren’t shown here.
This diff is large: its 132 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 567 lines aren’t shown here.
This diff is large: its 476 lines aren’t shown here.
This diff is large: its 1076 lines aren’t shown here.
This diff is large: its 445 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 549 lines aren’t shown here.
This diff is large: its 305 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 3199 lines aren’t shown here.
This diff is large: its 1125 lines aren’t shown here.
This diff is large: its 247 lines aren’t shown here.
This diff is large: its 1109 lines aren’t shown here.
This diff is large: its 300 lines aren’t shown here.
This diff is large: its 2996 lines aren’t shown here.
This diff is large: its 325 lines aren’t shown here.
This diff is large: its 140 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 54 lines aren’t shown here.
This diff is large: its 98 lines aren’t shown here.
This diff is large: its 105 lines aren’t shown here.
This diff is large: its 137 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 311 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 1334 lines aren’t shown here.
This diff is large: its 32 lines aren’t shown here.
This diff is large: its 3145 lines aren’t shown here.
This diff is large: its 239 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 393 lines aren’t shown here.
This diff is large: its 605 lines aren’t shown here.
This diff is large: its 243 lines aren’t shown here.
This diff is large: its 161 lines aren’t shown here.
This diff is large: its 290 lines aren’t shown here.
This diff is large: its 2721 lines aren’t shown here.
This diff is large: its 3742 lines aren’t shown here.
This diff is large: its 757 lines aren’t shown here.
This diff is large: its 968 lines aren’t shown here.
This diff is large: its 877 lines aren’t shown here.
This diff is large: its 123 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 12 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 51 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 53 lines aren’t shown here.
This diff is large: its 56 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 100 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 106 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 25 lines aren’t shown here.
This diff is large: its 111 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 90 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 68 lines aren’t shown here.
This diff is large: its 49 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 367 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 240 lines aren’t shown here.
This diff is large: its 127 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 772 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 115 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 22 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 93 lines aren’t shown here.
This diff is large: its 40 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 74 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 29 lines aren’t shown here.
This diff is large: its 61 lines aren’t shown here.
This diff is large: its 37 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 6 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 4192 lines aren’t shown here.
This diff is large: its 264 lines aren’t shown here.
This diff is large: its 643 lines aren’t shown here.
This diff is large: its 42 lines aren’t shown here.
This diff is large: its 968 lines aren’t shown here.
This diff is large: its 206 lines aren’t shown here.
This diff is large: its 987 lines aren’t shown here.
This diff is large: its 882 lines aren’t shown here.
This diff is large: its 1168 lines aren’t shown here.
This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.