예제 #1
0
static void
sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v)
{
	si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info;
	uint8 tmp;
	volatile uint32 dummy;
	uint32 intr_val = 0;


	/*
	 * compact flash only has 11 bits address, while we needs 12 bits address.
	 * MEM_SEG will be OR'd with other 11 bits address in hardware,
	 * so we program MEM_SEG with 12th bit when necessary(access sb regsiters).
	 * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special
	 */
	if (PCMCIA(sii)) {
		INTR_OFF(sii, intr_val);
		tmp = 1;
		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */
	}

	if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
		dummy = R_REG(sii->osh, sbr);
		BCM_REFERENCE(dummy);
		W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
		dummy = R_REG(sii->osh, sbr);
		BCM_REFERENCE(dummy);
		W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
	} else
예제 #2
0
uint
pcie_writereg(si_t *sih, sbpcieregs_t *pcieregs, uint addrtype, uint offset, uint val)
{
	osl_t   *osh = si_osh(sih);

	ASSERT(pcieregs != NULL);
	BCM_REFERENCE(osh);

	if ((BUSTYPE(sih->bustype) == SI_BUS) || PCIE_GEN1(sih)) {
		switch (addrtype) {
			case PCIE_CONFIGREGS:
				W_REG(osh, (&pcieregs->configaddr), offset);
				W_REG(osh, (&pcieregs->configdata), val);
				break;
			case PCIE_PCIEREGS:
				W_REG(osh, (&pcieregs->u.pcie1.pcieindaddr), offset);
				W_REG(osh, (&pcieregs->u.pcie1.pcieinddata), val);
				break;
			default:
				ASSERT(0);
				break;
		}
	}
	else if (PCIE_GEN2(sih)) {
		W_REG(osh, (&pcieregs->configaddr), offset);
		W_REG(osh, (&pcieregs->configdata), val);
	}
	return 0;
}
/*
 * This function runs a set of commands before running the wi-fi server
 * This is avoids packet drops and improves performance.
 * We run the following wl commands
 * up, mpc 0, wsec 0, slow_timer 999999, fast_timer 999999, glacial_timer 999999
 * legacylink 1, monitor 1.
 */
void remote_wifi_ser_init_cmds(void *wl)
{
	int err;
	char bigbuf[RWL_WIFI_BUF_LEN];
	uint len = 0, count;
	/* The array stores command, length and then data format */
	remote_wifi_cmds_t wifi_cmds[] = {
						{WLC_UP,  NULL, 0x0},
						{WLC_SET_VAR,  "mpc", 0},
						{WLC_SET_WSEC,  NULL, 0x0},
						{WLC_SET_VAR, "slow_timer", 999999},
						{WLC_SET_VAR, "fast_timer", 999999},
						{WLC_SET_VAR, "glacial_timer", 999999},
						{WLC_SET_MONITOR, NULL, 0x1},
						{WLC_SET_PM, NULL, 0x0}
	};

	for (count = 0; count < ARRAYSIZE(wifi_cmds); count++) {

		if (wifi_cmds[count].data == NULL)
			len = sizeof(int);
		else
			len = strlen(wifi_cmds[count].data) + 1 + sizeof(int);

		/* If the command length exceeds the buffer length continue
		 * executing the next command
		 */
		if (len > sizeof(bigbuf)) {
			DPRINT_ERR(ERR, "Err: command len exceeds buf len. Check"
				"initialization cmds\n");
			continue;
		}

		if (wifi_cmds[count].data != NULL) {
			strcpy(bigbuf, wifi_cmds[count].data);
			memcpy(&bigbuf[strlen(wifi_cmds[count].data)+1],
			(char*)&wifi_cmds[count].value, sizeof(int));
		} else {
			memcpy(&bigbuf[0], (char*)&wifi_cmds[count].value, sizeof(int));
		}
#ifdef WIN32
		/* Add OID base for NDIS commands */

		err = (int)ir_setinformation(wl, wifi_cmds[count].cmd + WL_OID_BASE,
		bigbuf, &len);
#endif

		if (wifi_cmds[count].cmd == WLC_UP)
			/* NULL needs to be passed to the driver if WL UP command needs to
			 * be executed Otherwise driver hangs
			 */
			err = wl_ioctl(wl, wifi_cmds[count].cmd,
				NULL, 0, TRUE);
		else
			err = wl_ioctl(wl, wifi_cmds[count].cmd,
			(void*)&bigbuf, len, TRUE);
		rwl_sleep(INIT_CMD_SLEEP);
	}
	BCM_REFERENCE(err);
}
예제 #4
0
/* Serialize ppr data of a bandwidth into the given buffer */
static uint ppr_serialize_block(const uint8 *pprbuf, uint8** buf, uint32 serflag)
{
	uint ret = 0;
#if (PPR_MAX_TX_CHAINS > 1)
	uint chain   = serflag & PPR_MAX_TX_CHAIN_MASK; /* chain number in serialized block */
	bool bf      = (serflag & PPR_BEAMFORMING) != 0;
#endif
	bcopy(pprbuf, *buf, PPR_CHAIN1_SIZE);
	*buf += PPR_CHAIN1_SIZE;
	ret  += PPR_CHAIN1_SIZE;
#if (PPR_MAX_TX_CHAINS > 1)
	BCM_REFERENCE(bf);
	if (chain > 1) {
		COPY_PPR_TOBUF(PPR_CHAIN2_FIRST, PPR_CHAIN2_SIZE);
	}
#if (PPR_MAX_TX_CHAINS > 2)
	if (chain > 2) {
		COPY_PPR_TOBUF(PPR_CHAIN3_FIRST, PPR_CHAIN3_SIZE);
	}
#endif
#ifdef WL_BEAMFORMING
	if (bf) {
		COPY_PPR_TOBUF(PPR_BF_CHAIN2_FIRST, PPR_BF_CHAIN2_SIZE);
	}
#if (PPR_MAX_TX_CHAINS > 2)
	if (bf && chain > 2) {
		COPY_PPR_TOBUF(PPR_BF_CHAIN3_FIRST, PPR_BF_CHAIN3_SIZE);
	}
#endif
#endif /* WL_BEAMFORMING */
#endif /* (PPR_MAX_TX_CHAINS > 1) */
	return ret;
}
예제 #5
0
/* Get a pointer to the power values for the given ofdm rate group for a given channel bandwidth */
static int8* ppr_get_ofdm_group(pprpbw_t* bw_pwrs, wl_tx_mode_t mode,
	wl_tx_chains_t tx_chains)
{
	int8* group_pwrs = NULL;
	BCM_REFERENCE(mode);
	switch (tx_chains) {
#if (PPR_MAX_TX_CHAINS > 1)
#if (PPR_MAX_TX_CHAINS > 2)
	case WL_TX_CHAINS_3:
#ifdef WL_BEAMFORMING
		if (mode == WL_TX_MODE_TXBF)
			group_pwrs = bw_pwrs->p_1x3txbf_ofdm;
		else
#endif
			group_pwrs = bw_pwrs->p_1x3cdd_ofdm;
		break;
#endif /* PPR_MAX_TX_CHAINS > 2 */
	case WL_TX_CHAINS_2:
#ifdef WL_BEAMFORMING
		if (mode == WL_TX_MODE_TXBF)
			group_pwrs = bw_pwrs->p_1x2txbf_ofdm;
		else
#endif
			group_pwrs = bw_pwrs->p_1x2cdd_ofdm;
		break;
#endif /* PPR_MAX_TX_CHAINS > 1 */
	case WL_TX_CHAINS_1:
		group_pwrs = bw_pwrs->p_1x1ofdm;
		break;
	default:
		ASSERT(0);
		break;
	}
	return group_pwrs;
}
예제 #6
0
static uint ppr_ser_size_by_flag(uint32 flag, wl_tx_bw_t bw)
{
	uint ret = PPR_CHAIN1_SIZE; /* at least 1 chain rates should be there */
	uint chain   = flag & PPR_MAX_TX_CHAIN_MASK;
	bool bf      = (flag & PPR_BEAMFORMING) != 0;
	BCM_REFERENCE(chain);
	BCM_REFERENCE(bf);
#if (PPR_MAX_TX_CHAINS > 1)
	if (chain > 1) {
		ret += PPR_CHAIN2_SIZE;
	}
#if (PPR_MAX_TX_CHAINS > 2)
	if (chain > 2) {
		ret += PPR_CHAIN3_SIZE;
	}
#endif

#ifdef WL_BEAMFORMING
	if (bf) {
		ret += PPR_BF_CHAIN2_SIZE;
	}
#if (PPR_MAX_TX_CHAINS > 2)
	if (bf && chain > 2) {
		ret += PPR_BF_CHAIN3_SIZE;
	}
#endif
#endif /* WL_BEAMFORMING */
#endif /* PPR_MAX_TX_CHAINS > 1 */
	switch (bw) {
	case WL_TX_BW_20:
		ret *= sizeof(ppr_bw_20_t)/sizeof(pprpbw_t);
		break;
	case WL_TX_BW_40:
		ret *= sizeof(ppr_bw_40_t)/sizeof(pprpbw_t);
		break;
	case WL_TX_BW_80:
		ret *= sizeof(ppr_bw_80_t)/sizeof(pprpbw_t);
		break;
	case WL_TX_BW_ALL:
		ret *= sizeof(ppr_bw_all_t)/sizeof(pprpbw_t);
		break;
	default:
		ASSERT(0);
	}
	return ret;

}
예제 #7
0
/* Destructor routine for opaque PPR struct */
void ppr_delete(osl_t *osh, ppr_t* pprptr)
{
	ASSERT((pprptr->ch_bw == WL_TX_BW_20) || (pprptr->ch_bw == WL_TX_BW_40) ||
		(pprptr->ch_bw == WL_TX_BW_80) ||
		(pprptr->ch_bw == WL_TX_BW_ALL));
#ifndef BCMDRIVER
	BCM_REFERENCE(osh);
	free(pprptr);
#else
	MFREE(osh, pprptr, (uint)ppr_size(pprptr->ch_bw));
#endif
}
예제 #8
0
void
bcm_rpc_tp_watchdog(rpc_tp_info_t *rpcb)
{
	static int old = 0;

	/* close agg periodically to avoid stale aggregation(include rpc_agg change) */
	bcm_rpc_tp_tx_agg_release(rpcb);

	RPC_TP_AGG(("agg delta %d\n", (rpcb->tp_tx_agg_cnt_sf - old)));

	old = rpcb->tp_tx_agg_cnt_sf;
	BCM_REFERENCE(old);
}
예제 #9
0
static void
sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v)
{
	uint8 tmp;
	volatile uint32 dummy;
	uint32 intr_val = 0;


	if (PCMCIA(sii)) {
		INTR_OFF(sii, intr_val);
		tmp = 1;
		OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1);
		sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); 
	}

	if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) {
		dummy = R_REG(sii->osh, sbr);
		BCM_REFERENCE(dummy);
		W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff));
		dummy = R_REG(sii->osh, sbr);
		BCM_REFERENCE(dummy);
		W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff));
	} else
예제 #10
0
osl_t *
osl_attach(void *pdev, uint bustype, bool pkttag)
{
    osl_t *osh;

    osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
    ASSERT(osh);

    bzero(osh, sizeof(osl_t));

    ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));

    osh->magic = OS_HANDLE_MAGIC;
    atomic_set(&osh->malloced, 0);
    osh->failed = 0;
    osh->dbgmem_list = NULL;
    spin_lock_init(&(osh->dbgmem_lock));
    osh->pdev = pdev;
    osh->pub.pkttag = pkttag;
    osh->bustype = bustype;

    switch (bustype) {
    case PCI_BUS:
    case SI_BUS:
    case PCMCIA_BUS:
        osh->pub.mmbus = TRUE;
        break;
    case JTAG_BUS:
    case SDIO_BUS:
    case USB_BUS:
    case SPI_BUS:
    case RPC_BUS:
        osh->pub.mmbus = FALSE;
        break;
    default:
        ASSERT(FALSE);
        break;
    }

    spin_lock_init(&(osh->pktalloc_lock));

#ifdef BCMDBG
    if (pkttag) {
        struct sk_buff *skb;
        BCM_REFERENCE(skb);
        ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb));
    }
#endif
    return osh;
}
예제 #11
0
/* Constructor routine for opaque PPR struct */
ppr_t* ppr_create(osl_t *osh, wl_tx_bw_t bw)
{
	ppr_t* pprptr;

	ASSERT((bw == WL_TX_BW_20) || (bw == WL_TX_BW_40) ||
		(bw == WL_TX_BW_80) ||
		(bw == WL_TX_BW_ALL));
#ifndef BCMDRIVER
	BCM_REFERENCE(osh);
	if ((pprptr = (ppr_t*)malloc((uint)ppr_size(bw))) != NULL) {
#else
	if ((pprptr = (ppr_t*)MALLOC(osh, (uint)ppr_size(bw))) != NULL) {
#endif
		ppr_init(pprptr, bw);
	}
	return pprptr;
}

/* Init flags in the memory block for serialization, the serializer will check
 * the flag to decide which ppr to be copied
 */
int ppr_init_ser_mem_by_bw(uint8* pbuf, wl_tx_bw_t bw, uint32 len)
{
	ppr_ser_mem_flag_t *pmflag;

	if (pbuf == NULL || ppr_ser_size_by_bw(bw) > len)
		return BCME_BADARG;

	pmflag = (ppr_ser_mem_flag_t *)pbuf;
	pmflag->magic_word = HTON32(PPR_SER_MEM_WORD);
	pmflag->flag   = HTON32(ppr_get_flag());

	/* init the memory */
	memset(pbuf + sizeof(*pmflag), (uint8)WL_RATE_DISABLED, len-sizeof(*pmflag));
	return BCME_OK;
}
inline void* MALLOCZ(void *o, size_t s) { BCM_REFERENCE(o); return calloc(1, s); }
예제 #13
0
/**
 * Translate non-xtlv 'wl counters' IOVar buffer received by old driver/FW to xtlv format.
 * Parameters:
 *	cntbuf: pointer to non-xtlv 'wl counters' IOVar buffer received by old driver/FW.
 *		Newly translated xtlv format is written to this pointer.
 *	buflen: length of the "cntbuf" without any padding.
 *	corerev: chip core revision of the driver/FW.
 */
int
wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, int buflen, uint32 corerev)
{
	wl_cnt_wlc_t *wlccnt = NULL;
	uint32 *macstat = NULL;
	xtlv_desc_t xtlv_desc[3];
	uint16 mcst_xtlv_id;
	int res = BCME_OK;
	wl_cnt_info_t *cntinfo = cntbuf;
	void *xtlvbuf_p = cntinfo->data;
	uint16 ver = cntinfo->version;
	uint16 xtlvbuflen = (uint16)buflen;
	uint16 src_max_idx;
#ifdef BCMDRIVER
	osl_t *osh = ctx;
#else
	BCM_REFERENCE(ctx);
#endif

	if (ver == WL_CNT_T_VERSION) {
		/* Already in xtlv format. */
		goto exit;
	}

#ifdef BCMDRIVER
	wlccnt = MALLOC(osh, sizeof(*wlccnt));
	macstat = MALLOC(osh, WL_CNT_MCST_STRUCT_SZ);
#else
	wlccnt = (wl_cnt_wlc_t *)malloc(sizeof(*wlccnt));
	macstat = (uint32 *)malloc(WL_CNT_MCST_STRUCT_SZ);
#endif
	if (!wlccnt) {
		printf("wl_cntbuf_to_xtlv_format malloc fail!\n");
		res = BCME_NOMEM;
		goto exit;
	}

	/* Check if the max idx in the struct exceeds the boundary of uint8 */
	if (NUM_OF_CNT_IN_WL_CNT_VER_6_T > ((uint8)(-1) + 1) ||
		NUM_OF_CNT_IN_WL_CNT_VER_11_T > ((uint8)(-1) + 1)) {
		printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
			" to be of uint16 instead of uint8\n");
		res = BCME_ERROR;
		goto exit;
	}

	/* Exclude version and length fields in either wlc_cnt_ver_6_t or wlc_cnt_ver_11_t */
	src_max_idx = (cntinfo->datalen - OFFSETOF(wl_cnt_info_t, data)) / sizeof(uint32);

	if (src_max_idx > (uint8)(-1)) {
		printf("wlcntverXXt_to_wlcntwlct and src_max_idx need"
			" to be of uint16 instead of uint8\n"
			"Try updating wl utility to the latest.\n");
		res = BCME_ERROR;
	}

	/* Copy wlc layer counters to wl_cnt_wlc_t */
	res = wl_copy_wlccnt(ver, (uint32 *)wlccnt, (uint32 *)cntinfo->data, (uint8)src_max_idx);
	if (res != BCME_OK) {
		printf("wl_copy_wlccnt fail!\n");
		goto exit;
	}

	/* Copy macstat counters to wl_cnt_wlc_t */
	if (ver == WL_CNT_VERSION_11) {
		res = wl_copy_macstat_ver11(macstat, (uint32 *)cntinfo->data);
		if (res != BCME_OK) {
			printf("wl_copy_macstat_ver11 fail!\n");
			goto exit;
		}
		if (corerev >= 40) {
			mcst_xtlv_id = WL_CNT_XTLV_GE40_UCODE_V1;
		} else {
			mcst_xtlv_id = WL_CNT_XTLV_LT40_UCODE_V1;
		}
	} else {
		res = wl_copy_macstat_upto_ver10(ver, macstat, (uint32 *)cntinfo->data);
		if (res != BCME_OK) {
			printf("wl_copy_macstat_upto_ver10 fail!\n");
			goto exit;
		}
		mcst_xtlv_id = WL_CNT_XTLV_CNTV_LE10_UCODE;
	}

	xtlv_desc[0].type = WL_CNT_XTLV_WLC;
	xtlv_desc[0].len = sizeof(*wlccnt);
	xtlv_desc[0].ptr = wlccnt;

	xtlv_desc[1].type = mcst_xtlv_id;
	xtlv_desc[1].len = WL_CNT_MCST_STRUCT_SZ;
	xtlv_desc[1].ptr = macstat;

	xtlv_desc[2].type = 0;
	xtlv_desc[2].len = 0;
	xtlv_desc[2].ptr = NULL;

	memset(cntbuf, 0, WL_CNTBUF_MAX_SIZE);

	res = bcm_pack_xtlv_buf_from_mem(&xtlvbuf_p, &xtlvbuflen,
		xtlv_desc, BCM_XTLV_OPTION_ALIGN32);
	cntinfo->datalen = (buflen - xtlvbuflen);
exit:
#ifdef BCMDRIVER
	if (wlccnt) {
		MFREE(osh, wlccnt, sizeof(*wlccnt));
	}
	if (macstat) {
		MFREE(osh, macstat, WL_CNT_MCST_STRUCT_SZ);
	}
#else
	if (wlccnt) {
		free(wlccnt);
	}
	if (macstat) {
		free(macstat);
	}
#endif
	return res;
}
예제 #14
0
static int dhd_wifi_platform_load_sdio(void)
{
	int i;
	int err = 0;
	wifi_adapter_info_t *adapter;

	BCM_REFERENCE(i);
	BCM_REFERENCE(adapter);
	/* Sanity check on the module parameters
	 * - Both watchdog and DPC as tasklets are ok
	 * - If both watchdog and DPC are threads, TX must be deferred
	 */
	if (!(dhd_watchdog_prio < 0 && dhd_dpc_prio < 0) &&
		!(dhd_watchdog_prio >= 0 && dhd_dpc_prio >= 0 && dhd_deferred_tx))
		return -EINVAL;

#if defined(BCMLXSDMMC)
	if (dhd_wifi_platdata == NULL) {
		DHD_ERROR(("DHD wifi platform data is required for Android build\n"));
		return -EINVAL;
	}

	sema_init(&dhd_registration_sem, 0);
	/* power up all adapters */
	for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
		bool chip_up = FALSE;
		int retry = POWERUP_MAX_RETRY;
		struct semaphore dhd_chipup_sem;

		adapter = &dhd_wifi_platdata->adapters[i];

		DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));
		DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
			adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path));
		DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
			adapter->bus_type, adapter->bus_num, adapter->slot_num));

		do {
			sema_init(&dhd_chipup_sem, 0);
			err = dhd_bus_reg_sdio_notify(&dhd_chipup_sem);
			if (err) {
				DHD_ERROR(("%s dhd_bus_reg_sdio_notify fail(%d)\n\n",
					__FUNCTION__, err));
				return err;
			}
			err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);
			if (err) {
				/* WL_REG_ON state unknown, Power off forcely */
				wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
				continue;
			} else {
				wifi_platform_bus_enumerate(adapter, TRUE);
				err = 0;
			}

			if (down_timeout(&dhd_chipup_sem, msecs_to_jiffies(POWERUP_WAIT_MS)) == 0) {
				dhd_bus_unreg_sdio_notify();
				chip_up = TRUE;
				break;
			}

			DHD_ERROR(("failed to power up %s, %d retry left\n", adapter->name, retry));
			dhd_bus_unreg_sdio_notify();
			wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
			wifi_platform_bus_enumerate(adapter, FALSE);
		} while (retry--);

		if (!chip_up) {
			DHD_ERROR(("failed to power up %s, max retry reached**\n", adapter->name));
			return -ENODEV;
		}

	}

	err = dhd_bus_register();

	if (err) {
		DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__));
		goto fail;
	}


	/*
	 * Wait till MMC sdio_register_driver callback called and made driver attach.
	 * It's needed to make sync up exit from dhd insmod  and
	 * Kernel MMC sdio device callback registration
	 */
	err = down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));
	if (err) {
		DHD_ERROR(("%s: sdio_register_driver timeout or error \n", __FUNCTION__));
		dhd_bus_unregister();
		goto fail;
	}

	return err;

fail:
	/* power down all adapters */
	for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
		adapter = &dhd_wifi_platdata->adapters[i];
		wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
		wifi_platform_bus_enumerate(adapter, FALSE);
	}
#else

	/* x86 bring-up PC needs no power-up operations */
	err = dhd_bus_register();

#endif 

	return err;
}
예제 #15
0
static int dhd_wifi_platform_load_pcie(void)
{
	int err = 0;
	int i;
	wifi_adapter_info_t *adapter;

	BCM_REFERENCE(i);
	BCM_REFERENCE(adapter);

	if (dhd_wifi_platdata == NULL) {
		err = dhd_bus_register();
	} else {
		if (dhd_download_fw_on_driverload) {
			/* power up all adapters */
			for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
				int retry = POWERUP_MAX_RETRY;
				adapter = &dhd_wifi_platdata->adapters[i];

				DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));
				DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
					adapter->irq_num, adapter->intr_flags, adapter->fw_path,
					adapter->nv_path));
				DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
					adapter->bus_type, adapter->bus_num, adapter->slot_num));

				do {
					err = wifi_platform_set_power(adapter,
						TRUE, WIFI_TURNON_DELAY);
					if (err) {
						DHD_ERROR(("failed to power up %s,"
							" %d retry left\n",
							adapter->name, retry));
						/* WL_REG_ON state unknown, Power off forcely */
						wifi_platform_set_power(adapter,
							FALSE, WIFI_TURNOFF_DELAY);
						continue;
					} else {
						err = wifi_platform_bus_enumerate(adapter, TRUE);
						if (err) {
							DHD_ERROR(("failed to enumerate bus %s, "
								"%d retry left\n",
								adapter->name, retry));
							wifi_platform_set_power(adapter, FALSE,
								WIFI_TURNOFF_DELAY);
						} else {
							break;
						}
					}
				} while (retry--);

				if (!retry) {
					DHD_ERROR(("failed to power up %s, max retry reached**\n",
						adapter->name));
					return -ENODEV;
				}
			}
		}

		err = dhd_bus_register();

		if (err) {
			DHD_ERROR(("%s: pcie_register_driver failed\n", __FUNCTION__));
			if (dhd_download_fw_on_driverload) {
				/* power down all adapters */
				for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
					adapter = &dhd_wifi_platdata->adapters[i];
					wifi_platform_bus_enumerate(adapter, FALSE);
					wifi_platform_set_power(adapter,
						FALSE, WIFI_TURNOFF_DELAY);
				}
			}
		}
	}

	return err;
}
예제 #16
0
static int
dbus_usb_doiovar(usb_info_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
                void *params, int plen, void *arg, int len, int val_size)
{
	int bcmerror = 0;
	int32 int_val = 0;
	bool bool_val = 0;

	DBUSTRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
	           __FUNCTION__, actionid, name, params, plen, arg, len, val_size));

	if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
		goto exit;

	if (plen >= (int)sizeof(int_val))
		bcopy(params, &int_val, sizeof(int_val));

	bool_val = (int_val != 0) ? TRUE : FALSE;

	switch (actionid) {

	case IOV_SVAL(IOV_MEMBYTES):
	case IOV_GVAL(IOV_MEMBYTES):
	{
		uint32 address;
		uint size, dsize;
		uint8 *data;

		bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));

		ASSERT(plen >= 2*sizeof(int));

		address = (uint32)int_val;
		BCM_REFERENCE(address);
		bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
		size = (uint)int_val;

		/* Do some validation */
		dsize = set ? plen - (2 * sizeof(int)) : len;
		if (dsize < size) {
			DBUSTRACE(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
			           __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
			bcmerror = BCME_BADARG;
			break;
		}
		DBUSTRACE(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
		          (set ? "write" : "read"), size, address));

		/* Generate the actual data pointer */
		data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;

		/* Call to do the transfer */
		bcmerror = dbus_usb_dl_writeimage(BUS_INFO(bus, usb_info_t), data, size);
	}
		break;


	case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):

		if (bool_val == TRUE) {
			bcmerror = dbus_usb_dlneeded(bus);
			dbus_usb_rdl_dwnld_state(BUS_INFO(bus, usb_info_t));
		} else {
			usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
			bcmerror = dbus_usb_dlrun(bus);
			usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
		}
		break;

	case IOV_SVAL(IOV_VARS):
		bcmerror = dhdusb_downloadvars(BUS_INFO(bus, usb_info_t), arg, len);
		break;

	default:
		bcmerror = BCME_UNSUPPORTED;
		break;
	}

exit:
	return bcmerror;
}
예제 #17
0
osl_t *
osl_attach(void *pdev, uint bustype, bool pkttag)
{
	osl_t *osh;

	osh = kmalloc(sizeof(osl_t), GFP_ATOMIC);
	ASSERT(osh);

	bzero(osh, sizeof(osl_t));

	/* Check that error map has the right number of entries in it */
	ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1));

	osh->magic = OS_HANDLE_MAGIC;
	atomic_set(&osh->malloced, 0);
	osh->failed = 0;
	osh->dbgmem_list = NULL;
	spin_lock_init(&(osh->dbgmem_lock));
	osh->pdev = pdev;
	osh->pub.pkttag = pkttag;
	osh->bustype = bustype;

	switch (bustype) {
		case PCI_BUS:
		case SI_BUS:
		case PCMCIA_BUS:
			osh->pub.mmbus = TRUE;
			break;
		case JTAG_BUS:
		case SDIO_BUS:
		case USB_BUS:
		case SPI_BUS:
		case RPC_BUS:
			osh->pub.mmbus = FALSE;
			break;
		default:
			ASSERT(FALSE);
			break;
	}

#if defined(DHD_USE_STATIC_BUF)
	if (!bcm_static_buf) {
		if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+
			STATIC_BUF_TOTAL_LEN))) {
			printk("can not alloc static buf!\n");
		}
		else
			printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf);


		sema_init(&bcm_static_buf->static_sem, 1);

		bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE;
	}

	if (!bcm_static_skb) {
		int i;
		void *skb_buff_ptr = 0;
		bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048);
		skb_buff_ptr = dhd_os_prealloc(osh, 4, 0);

		bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16);
		for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++)
			bcm_static_skb->pkt_use[i] = 0;

		sema_init(&bcm_static_skb->osl_pkt_sem, 1);
	}
#endif /* DHD_USE_STATIC_BUF */

	spin_lock_init(&(osh->pktalloc_lock));

#ifdef BCMDBG
	if (pkttag) {
		struct sk_buff *skb;
		BCM_REFERENCE(skb);
		ASSERT(OSL_PKTTAG_SZ <= sizeof(skb->cb));
	}
#endif
	return osh;
}
inline void MFREE(void *o, void *p, size_t s) { BCM_REFERENCE(o); BCM_REFERENCE(s); free(p); }