Пример #1
0
static void hifDeviceRemoved(struct sdio_func *func)
{
    A_STATUS status = A_OK;
    HIF_DEVICE *device;
    int ret;
    AR_DEBUG_ASSERT(func != NULL);

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
    device = getHifDevice(func);
    if (device->claimedContext != NULL) {
        status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device);
    }
    do {
        if (device->is_suspend) {
            device->is_suspend = FALSE;
            break;
        }
        if (!IS_ERR(device->async_task)) {
            init_completion(&device->async_completion);
            device->async_shutdown = 1;
            up(&device->sem_async);
            wait_for_completion(&device->async_completion);
            device->async_task = NULL;
        }
        /* Disable the card */
        sdio_claim_host(device->func);
        ret = sdio_disable_func(device->func);
        sdio_release_host(device->func);
    } while (0);
    delHifDevice(device);
    AR_DEBUG_ASSERT(status == A_OK);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n"));
}
Пример #2
0
static void hifDeviceRemoved(struct sdio_func *func)
{
    A_STATUS status = A_OK;
    HIF_DEVICE *device;
    AR_DEBUG_ASSERT(func != NULL);

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
    device = getHifDevice(func);
    if (device->claimedContext != NULL) {
        status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device);
    }

    if (device->is_suspend) {
        device->is_suspend = FALSE;
    } else {
        if (hifDisableFunc(device, func)!=0) {
            status = A_ERROR;
        }
    }
    CleanupHIFScatterResources(device);
     
    delHifDevice(device);
    AR_DEBUG_ASSERT(status == A_OK);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n"));
}
Пример #3
0
SD_API_STATUS 
hifIRQHandler(SD_DEVICE_HANDLE hDevice, PVOID notUsed)
{
#ifndef CEPC
	A_STATUS         status;
    HIF_DEVICE      *device;
	A_BOOL			 callDSR;
#endif

    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifIRQHandler : Enter\n");

#ifndef CEPC
	/* Disable device interrupts */
	device = getHifDevice(hDevice);

	status = htcCallbacks.deviceInterruptDisabler(device, &callDSR);
	AR_DEBUG_ASSERT(status == A_OK);

	/* Call the DSR Handler if it is not a Spurious Interrupt */
	if (callDSR) {
		status = htcCallbacks.dsrHandler(device);
		AR_DEBUG_ASSERT(status == A_OK);
	}
#else
	NdisSetEvent(&hifIRQEvent);
#endif
	HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifIRQHandler : Exit\n");
	return SD_API_STATUS_SUCCESS;
}
Пример #4
0
static int hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func)
{
    int ret = 0;

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
    device = getHifDevice(func);
    if (!IS_ERR(device->async_task)) {
        init_completion(&device->async_completion);
        device->async_shutdown = 1;
        up(&device->sem_async);
        wait_for_completion(&device->async_completion);
        device->async_task = NULL;
    }
    /* Disable the card */
    sdio_claim_host(device->func);
    ret = sdio_disable_func(device->func);

    if (reset_sdio_on_unload) {
        /* reset the SDIO interface.  This is useful in automated testing where the card
         * does not need to be removed at the end of the test.  It is expected that the user will 
         * also unload/reload the host controller driver to force the bus driver to re-enumerate the slot */
        AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("AR6000: reseting SDIO card back to uninitialized state \n"));
        
        /* NOTE : sdio_f0_writeb() cannot be used here, that API only allows access
         *        to undefined registers in the range of: 0xF0-0xFF */
         
        ret = Func0_CMD52WriteByte(device->func->card, SDIO_CCCR_ABORT, (1 << 3)); 
        if (ret) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: reset failed : %d \n",ret));    
        }
    }

    sdio_release_host(device->func);
    return ret;
}
Пример #5
0
static int hifDeviceResume(struct device *dev)
{
    HIF_DEVICE *device;
    A_STATUS status = A_OK;
    struct sdio_func *func = dev_to_sdio_func(dev);
    device = getHifDevice(func);
    status = HIFDoDeviceResume(device);
    return A_SUCCESS(status) ? 0 : status;
}
Пример #6
0
void
hifDeviceRemoved(SD_DEVICE_HANDLE *handle)
{
    A_STATUS    status;
    HIF_DEVICE *device;

    device = getHifDevice(handle);
    status = htcCallbacks.deviceRemovedHandler(device);
    delHifDevice(handle);
    AR_DEBUG_ASSERT(status == A_OK);
	return;
}
Пример #7
0
static void
hifIRQHandler(struct sdio_func *func)
{
    A_STATUS status;
    HIF_DEVICE *device;
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n"));

    device = getHifDevice(func);
    /* release the host during ints so we can pick it back up when we process cmds */
    sdio_release_host(device->func);
    status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);
    sdio_claim_host(device->func);
    AR_DEBUG_ASSERT(status == A_OK || status == A_ECANCELED);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n"));
}
Пример #8
0
static void
hifISRHandler(CF_DEVICE_HANDLE cfHandle,A_BOOL *callDsr)
{
    A_STATUS    status;
    HIF_DEVICE *device;

    device = getHifDevice(cfHandle);
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifIsrHandler: Enter\n");

	status = htcCallbacks.deviceInterruptDisabler(device, callDsr);
	AR_DEBUG_ASSERT(status == A_OK);
        
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifIsrHandler: Exit\n");

    return;
}
Пример #9
0
static int hifDeviceSuspend(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
    A_STATUS status = A_OK;
    HIF_DEVICE *device;   
    device = getHifDevice(func);
    if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
        status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext);
    }
    if (status == A_OK) {
        int oldresetvalue = reset_sdio_on_unload;
        reset_sdio_on_unload = 1;
        hifDisableFunc(device, func);
        reset_sdio_on_unload = oldresetvalue;
        device->is_suspend = TRUE;
    } else if (status == A_EBUSY) {
        A_INT32 cnt = 10;
        A_UINT8 host_int_status;
	    do {            		    
		    while (atomic_read(&device->irqHandling)) {
			    /* wait until irq handler finished all the jobs */
			    schedule_timeout(HZ/10);
		    }
		    /* check if there is any pending irq due to force done */
		    host_int_status = 0;
		    status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS,
				    (A_UINT8 *)&host_int_status, sizeof(host_int_status),
				    HIF_RD_SYNC_BYTE_INC, NULL);
		    host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)) : 0;
		    if (host_int_status) {
			    schedule(); /* schedule for next dsrHandler */
		    }
	    } while (host_int_status && --cnt > 0);

        if (host_int_status && cnt == 0) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, 
                            ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n",
					        __FUNCTION__));
        }
#if 1
        status = A_OK; /* assume that sdio host controller will take care the power of wifi chip */
#else
        return -EBUSY; /* Return -EBUSY if customer use all android patch of mmc stack provided by us */ 
#endif 
    }
    return A_SUCCESS(status) ? 0 : status;
}
Пример #10
0
static int hifDeviceSuspend(struct device *dev)
{
	struct sdio_func *func = dev_to_sdio_func(dev);
    A_STATUS status = A_OK;
    HIF_DEVICE *device;   
    device = getHifDevice(func);
    if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
        status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext);
    }
    if (status == A_OK) {
        hifDisableFunc(device, func);
        device->is_suspend = TRUE;
    } else if (status == A_EBUSY) {
        status = A_OK; /* assume that sdio host controller will take care the power of wifi chip */
    }
    return A_SUCCESS(status) ? 0 : status;
}
Пример #11
0
static void
hifDSRHandler(CF_DEVICE_HANDLE cfHandle)
{
    A_STATUS    status;
    HIF_DEVICE *device;

	device = getHifDevice(cfHandle);
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifDsrHandler: Enter\n");

    status = htcCallbacks.dsrHandler(device);
    
    AR_DEBUG_ASSERT(status == A_OK);
    
	htcCallbacks.deviceInterruptEnabler(device);

    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifDsrHandler: Exit\n");
}
Пример #12
0
void
hifDeviceRemoved(SD_DEVICE_HANDLE *handle)
{
	A_STATUS    status;
	HIF_DEVICE *device;

	NDIS_DEBUG_PRINTF(1, "%s() : + Enter \r\n", __FUNCTION__);
	
	device = getHifDevice(handle);

	if (device->claimedContext != NULL) {
		status = osdrvCallbacks.deviceRemovedHandler(device->claimedContext, device);
	}

	delHifDevice(handle);
	AR_DEBUG_ASSERT(status == A_OK);
	return;
}
Пример #13
0
DWORD
hifIRQThread(LPVOID Context)
{
	SD_DEVICE_HANDLE hDevice = Context;
	A_STATUS         status;
    HIF_DEVICE      *device;

	if (hDevice == NULL) {
		return SD_API_STATUS_UNSUCCESSFUL;
	}
	while (1) {
		NdisWaitEvent(&hifIRQEvent, 0);
		NdisResetEvent(&hifIRQEvent);
		device = getHifDevice(hDevice);
		status = htcCallbacks.dsrHandler(device);
		AR_DEBUG_ASSERT(status == A_OK);
	} // while
    return SD_API_STATUS_SUCCESS;
}
Пример #14
0
static void
hifDeviceRemoved(CF_DEVICE_HANDLE cfHandle)
{
    A_STATUS status;
    HIF_DEVICE *device;

    device = getHifDevice(cfHandle);
    
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifDeviceRemoved: Enter\n");
    HIF_DEBUG_PRINTF(ATH_LOG_INF, "hifDeviceRemoved: Device = %p\n",device);

    /* Inform HTC */
    status = htcCallbacks.deviceRemovedHandler(device);
    
    delHifDevice(cfHandle);
    
    HIF_DEBUG_PRINTF(ATH_LOG_TRC, "hifDeviceRemoved: Exit\n");

    AR_DEBUG_ASSERT(status == A_OK);
}
Пример #15
0
SD_API_STATUS 
hifIRQHandler(SD_DEVICE_HANDLE hDevice, PVOID notUsed)
{
#ifndef CEPC
	A_STATUS         status = A_OK;
    HIF_DEVICE      *device = NULL;
//	A_BOOL			 callDSR;
#endif

	NDIS_DEBUG_PRINTF(DBG_TRACE, "hifIRQHandler : Enter\r\n");

	device = getHifDevice(hDevice);
#if USE_IRQ_THREAD
	

	SDIODisconnectInterrupt(device->handle);

	NdisSetEvent(&hifIRQEvent);
	
#else
	/* Disable device interrupts */
	SDIODisconnectInterrupt(device->handle);
	
#if 0	
	/* Call the DSR Handler if it is not a Spurious Interrupt */
	if (callDSR) 
#endif		
	{
		status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);	
		AR_DEBUG_ASSERT(status == A_OK);
	}
	
	SDIOConnectInterrupt(device->handle,hifIRQHandler);
		
#endif

	NDIS_DEBUG_PRINTF(0, "hifIRQHandler : Exit\r\n");	
	return SD_API_STATUS_SUCCESS;
}
Пример #16
0
static int hifDeviceResume(struct device *dev)
{
    struct task_struct* pTask;
    const char *taskName;
    int (*taskFunc)(void *);
	struct sdio_func *func = dev_to_sdio_func(dev);
    A_STATUS ret = A_OK;
    HIF_DEVICE *device;   
    device = getHifDevice(func);

    if (device->is_suspend) {
       /* enable the SDIO function */
        sdio_claim_host(func);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
        /* give us some time to enable, in ms */
        func->enable_timeout = 100;
#endif
        ret = sdio_enable_func(func);
        if (ret) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
					  __FUNCTION__, ret));
            sdio_release_host(func);
            return ret;
    }
        ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
        sdio_release_host(func);
        if (ret) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x  AR6K: 0x%X\n",
					  __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
            return ret;
        }
        device->is_suspend = FALSE;
        /* create async I/O thread */
        if (!device->async_task) {
            device->async_shutdown = 0;
            device->async_task = kthread_create(async_task,
                                           (void *)device,
                                           "AR6K Async");
           if (IS_ERR(device->async_task)) {
               AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
                return A_ERROR;
           }
           AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
           wake_up_process(device->async_task );    
        }
    }

    if (!device->claimedContext) {
        printk("WARNING!!! No claimedContext during resume wlan\n"); 
        taskFunc = startup_task;
        taskName = "AR6K startup";
    } else {
        taskFunc = resume_task;
        taskName = "AR6K resume";
    }
    /* create resume thread */
    pTask = kthread_create(taskFunc, (void *)device, taskName);
    if (IS_ERR(pTask)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create resume task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start resume task\n"));
    wake_up_process(pTask);
    return A_SUCCESS(ret) ? 0 : ret;
}
Пример #17
0
static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
{
    int ret;
    HIF_DEVICE * device;
    int count;
    struct task_struct* startup_task_struct;

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
		    ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X, Device ID: 0x%X, block size: 0x%X/0x%X\n",
		     func->num, func->vendor, func->device, func->max_blksize, func->cur_blksize));

    addHifDevice(func);
    device = getHifDevice(func);

    spin_lock_init(&device->lock);

    spin_lock_init(&device->asynclock);

        /* enable the SDIO function */
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: claim\n"));
    sdio_claim_host(func);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: enable\n"));

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
    /* give us some time to enable, in ms */
    func->enable_timeout = 100;
#endif

    ret = sdio_enable_func(func);
    if (ret) {

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X, timeout: %d\n",
					  __FUNCTION__, ret, func->enable_timeout));
#else

        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
					  __FUNCTION__, ret));
#endif
        sdio_release_host(func);
        return ret;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: set block size 0x%X\n", HIF_MBOX_BLOCK_SIZE));
    ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
    sdio_release_host(func);
    if (ret) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x  AR6K: 0x%X\n",
					  __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
        return ret;
    }
    /* Initialize the bus requests to be used later */
    A_MEMZERO(device->busRequest, sizeof(device->busRequest));
    for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
        sema_init(&device->busRequest[count].sem_req, 0);
        hifFreeBusRequest(device, &device->busRequest[count]);
    }

    /* create async I/O thread */
    device->async_shutdown = 0;
    device->async_task = kthread_create(async_task,
                                       (void *)device,
                                       "AR6K Async");
    if (IS_ERR(device->async_task)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
    sema_init(&device->sem_async, 0);
    wake_up_process(device->async_task );

    /* create startup thread */
    startup_task_struct = kthread_create(startup_task,
                                  (void *)device,
                                  "AR6K startup");
    if (IS_ERR(startup_task_struct)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create startup task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start startup task\n"));
    wake_up_process(startup_task_struct);

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: return %d\n", ret));
    return ret;
}
Пример #18
0
static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
{
    int ret;
    HIF_DEVICE * device;
    int count;
    struct task_struct* startup_task_struct;

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
		    ("AR6000: hifDeviceInserted, Function: 0x%X, Vendor ID: 0x%X, Device ID: 0x%X, block size: 0x%X/0x%X\n",
		     func->num, func->vendor, func->device, func->max_blksize, func->cur_blksize));

    addHifDevice(func);
    device = getHifDevice(func);

    spin_lock_init(&device->lock);

    spin_lock_init(&device->asynclock);
    
    DL_LIST_INIT(&device->ScatterReqHead);
    
    if (!nohifscattersupport) {
            /* try to allow scatter operation on all instances,
             * unless globally overridden */
        device->scatter_enabled = TRUE;
    }
    
        /* enable the SDIO function */
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: claim\n"));
    sdio_claim_host(func);
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: enable\n"));

    if ((id->device & MANUFACTURER_ID_AR6K_BASE_MASK) >= MANUFACTURER_ID_AR6003_BASE) {
        /* enable 4-bit ASYNC interrupt on AR6003 or later devices */    
        ret = Func0_CMD52WriteByte(func->card, CCCR_SDIO_IRQ_MODE_REG, SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
        if (ret) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("AR6000: failed to enable 4-bit ASYNC IRQ mode %d \n",ret));    
            sdio_release_host(func);
            return ret;
        }
        AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: 4-bit ASYNC IRQ mode enabled\n"));   
    }
    
    
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
    /* give us some time to enable, in ms */
    func->enable_timeout = 100;
#endif
    ret = sdio_enable_func(func);
    if (ret) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to enable AR6K: 0x%X\n",
					  __FUNCTION__, ret)); 
        sdio_release_host(func);
        return ret;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: set block size 0x%X\n", HIF_MBOX_BLOCK_SIZE));
    ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
    sdio_release_host(func);
    if (ret) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), Unable to set block size 0x%x  AR6K: 0x%X\n",
					  __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
        return ret;
    }
    /* Initialize the bus requests to be used later */
    A_MEMZERO(device->busRequest, sizeof(device->busRequest));
    for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
        sema_init(&device->busRequest[count].sem_req, 0);
        hifFreeBusRequest(device, &device->busRequest[count]);
    }

    /* create async I/O thread */
    device->async_shutdown = 0;
    device->async_task = kthread_create(async_task,
                                       (void *)device,
                                       "AR6K Async");
    if (IS_ERR(device->async_task)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create async task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start async task\n"));
    sema_init(&device->sem_async, 0);
    wake_up_process(device->async_task );

    /* create startup thread */
    startup_task_struct = kthread_create(startup_task,
                                  (void *)device,
                                  "AR6K startup");
    if (IS_ERR(startup_task_struct)) {
        AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("AR6000: %s(), to create startup task\n", __FUNCTION__));
        return A_ERROR;
    }
    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: start startup task\n"));
    wake_up_process(startup_task_struct);

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: return %d\n", ret));
    return ret;
}