Esempio n. 1
0
/**
 * 	i2o_msg_post_wait_mem - Post and wait a message with DMA buffers
 *	@c: controller
 *	@m: message to post
 *	@timeout: time in seconds to wait
 *	@dma: i2o_dma struct of the DMA buffer to free on failure
 *
 * 	This API allows an OSM to post a message and then be told whether or
 *	not the system received a successful reply. If the message times out
 *	then the value '-ETIMEDOUT' is returned. This is a special case. In
 *	this situation the message may (should) complete at an indefinite time
 *	in the future. When it completes it will use the memory buffer
 *	attached to the request. If -ETIMEDOUT is returned then the memory
 *	buffer must not be freed. Instead the event completion will free them
 *	for you. In all other cases the buffer are your problem.
 *
 *	Returns 0 on success, negative error code on timeout or positive error
 *	code from reply.
 */
int i2o_msg_post_wait_mem(struct i2o_controller *c, u32 m, unsigned long
			  timeout, struct i2o_dma *dma)
{
	DECLARE_WAIT_QUEUE_HEAD(wq);
	struct i2o_exec_wait *wait;
	static u32 tcntxt = 0x80000000;
	struct i2o_message __iomem *msg = i2o_msg_in_to_virt(c, m);
	int rc = 0;

	wait = i2o_exec_wait_alloc();
	if (!wait)
		return -ENOMEM;

	if (tcntxt == 0xffffffff)
		tcntxt = 0x80000000;

	if (dma)
		wait->dma = *dma;

	/*
	 * Fill in the message initiator context and transaction context.
	 * We will only use transaction contexts >= 0x80000000 for POST WAIT,
	 * so we could find a POST WAIT reply easier in the reply handler.
	 */
	writel(i2o_exec_driver.context, &msg->u.s.icntxt);
	wait->tcntxt = tcntxt++;
	writel(wait->tcntxt, &msg->u.s.tcntxt);

	/*
	 * Post the message to the controller. At some point later it will
	 * return. If we time out before it returns then complete will be zero.
	 */
	i2o_msg_post(c, m);

	if (!wait->complete) {
		wait->wq = &wq;
		/*
		 * we add elements add the head, because if a entry in the list
		 * will never be removed, we have to iterate over it every time
		 */
		list_add(&wait->list, &i2o_exec_wait_list);

		wait_event_interruptible_timeout(wq, wait->complete,
						 timeout * HZ);

		wait->wq = NULL;
	}

	barrier();

	if (wait->complete) {
		rc = le32_to_cpu(wait->msg->body[0]) >> 24;
		i2o_flush_reply(c, wait->m);
		i2o_exec_wait_free(wait);
	} else {
Esempio n. 2
0
asmlinkage int sys_sleep_on_barrier(int bd, int tag) {
	//TODO MANAGE ERRNO
	DECLARE_WAIT_QUEUE_HEAD(waitQueue);

	if (barrier_addProcessOnTag(bd, tag, &waitQueue) != EXECUTION_OK) {
		return -1;
	}
	printk( PRINTK_DEBUG "interruptible_sleep_on(&waitQueue)\n");
	interruptible_sleep_on(&waitQueue);
	printk( PRINTK_DEBUG "waken up\n");
	if (signal_pending(current)) {
		printk( PRINTK_DEBUG "waken up by signal\n");
		if (barrier_removeProcessOnTag(bd, tag,
						(int) &waitQueue)!= EXECUTION_OK) {
			return -1;
		}
	}else{
		printk( PRINTK_DEBUG "waken up by syscall (maybe)\n");
	}

	return 0;
}
VOID RtmpOsUsbEmptyUrbCheck(
	IN	VOID				**ppWait,
	IN	NDIS_SPIN_LOCK		*pBulkInLock,
	IN	UCHAR				*pPendingRx)
{
	UINT32 i = 0;
	DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup); 
	DECLARE_WAITQUEUE(wait, current);


	/* ensure there are no more active urbs. */
	add_wait_queue (&unlink_wakeup, &wait);
	*ppWait = &unlink_wakeup;

	/* maybe wait for deletions to finish. */
	i = 0;
	/*while((i < 25) && atomic_read(&pAd->PendingRx) > 0) */
	while(i < 25)
	{
/*		unsigned long IrqFlags; */

		RTMP_SEM_LOCK(pBulkInLock);
		if (*pPendingRx == 0)
		{
			RTMP_SEM_UNLOCK(pBulkInLock);
			break;
		}
		RTMP_SEM_UNLOCK(pBulkInLock);
		
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
		msleep(UNLINK_TIMEOUT_MS);	/*Time in millisecond */
#else
		RTMPusecDelay(UNLINK_TIMEOUT_MS*1000);	/*Time in microsecond */
#endif
		i++;
	}
	*ppWait = NULL;
	remove_wait_queue (&unlink_wakeup, &wait); 
}
Esempio n. 4
0
static
int axusbnet_stop(struct net_device *net)
{
	struct usbnet		*dev = netdev_priv(net);
	struct driver_info	*info = dev->driver_info;
	int			temp;
	int			retval;
#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 18)
	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(unlink_wakeup);
#else
	DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
#endif
	DECLARE_WAITQUEUE(wait, current);

	netif_stop_queue(net);

	if (netif_msg_ifdown(dev))
		devinfo(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld",
			dev->stats.rx_packets, dev->stats.tx_packets,
			dev->stats.rx_errors, dev->stats.tx_errors);

	/* allow minidriver to stop correctly (wireless devices to turn off
	 * radio etc) */
	if (info->stop) {
		retval = info->stop(dev);
		if (retval < 0 && netif_msg_ifdown(dev))
			devinfo(dev,
				"stop fail (%d) usbnet usb-%s-%s, %s",
				retval,
				dev->udev->bus->bus_name, dev->udev->devpath,
				info->description);
	}

	if (!(info->flags & FLAG_AVOID_UNLINK_URBS)) {
		/* ensure there are no more active urbs */
		add_wait_queue(&unlink_wakeup, &wait);
		dev->wait = &unlink_wakeup;
		temp = unlink_urbs(dev, &dev->txq) +
			unlink_urbs(dev, &dev->rxq);

		/* maybe wait for deletions to finish. */
		while (!skb_queue_empty(&dev->rxq)
				&& !skb_queue_empty(&dev->txq)
				&& !skb_queue_empty(&dev->done)) {
			msleep(UNLINK_TIMEOUT_MS);
			if (netif_msg_ifdown(dev))
				devdbg(dev, "waited for %d urb completions",
				       temp);
		}
		dev->wait = NULL;
		remove_wait_queue(&unlink_wakeup, &wait);
	}

	usb_kill_urb(dev->interrupt);

	/* deferred work (task, timer, softirq) must also stop.
	 * can't flush_scheduled_work() until we drop rtnl (later),
	 * else workers could deadlock; so make workers a NOP.
	 */
	dev->flags = 0;
	del_timer_sync(&dev->delay);
	tasklet_kill(&dev->bh);

	return 0;
}
Esempio n. 5
0
asmlinkage void
do_page_fault(unsigned long address, struct pt_regs *regs,
	      int protection, int writeaccess)
{
	struct task_struct *tsk;
	struct mm_struct *mm;
	struct vm_area_struct * vma;
	siginfo_t info;
	int fault;
	unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;

	D(printk(KERN_DEBUG
		 "Page fault for %lX on %X at %lX, prot %d write %d\n",
		 address, smp_processor_id(), instruction_pointer(regs),
		 protection, writeaccess));

	tsk = current;

	/*
	 * We fault-in kernel-space virtual memory on-demand. The
	 * 'reference' page table is init_mm.pgd.
	 *
	 * NOTE! We MUST NOT take any locks for this case. We may
	 * be in an interrupt or a critical region, and should
	 * only copy the information from the master page table,
	 * nothing more.
	 *
	 * NOTE2: This is done so that, when updating the vmalloc
	 * mappings we don't have to walk all processes pgdirs and
	 * add the high mappings all at once. Instead we do it as they
	 * are used. However vmalloc'ed page entries have the PAGE_GLOBAL
	 * bit set so sometimes the TLB can use a lingering entry.
	 *
	 * This verifies that the fault happens in kernel space
	 * and that the fault was not a protection error (error_code & 1).
	 */

	if (address >= VMALLOC_START &&
	    !protection &&
	    !user_mode(regs))
		goto vmalloc_fault;

	/* When stack execution is not allowed we store the signal
	 * trampolines in the reserved cris_signal_return_page.
	 * Handle this in the exact same way as vmalloc (we know
	 * that the mapping is there and is valid so no need to
	 * call handle_mm_fault).
	 */
	if (cris_signal_return_page &&
	    address == cris_signal_return_page &&
	    !protection && user_mode(regs))
		goto vmalloc_fault;

	/* we can and should enable interrupts at this point */
	local_irq_enable();

	mm = tsk->mm;
	info.si_code = SEGV_MAPERR;

	/*
	 * If we're in an interrupt or "atomic" operation or have no
	 * user context, we must not take the fault.
	 */

	if (!mm || pagefault_disabled())
		goto no_context;

	if (user_mode(regs))
		flags |= FAULT_FLAG_USER;
retry:
	down_read(&mm->mmap_sem);
	vma = find_vma(mm, address);
	if (!vma)
		goto bad_area;
	if (vma->vm_start <= address)
		goto good_area;
	if (!(vma->vm_flags & VM_GROWSDOWN))
		goto bad_area;
	if (user_mode(regs)) {
		/*
		 * accessing the stack below usp is always a bug.
		 * we get page-aligned addresses so we can only check
		 * if we're within a page from usp, but that might be
		 * enough to catch brutal errors at least.
		 */
		if (address + PAGE_SIZE < rdusp())
			goto bad_area;
	}
	if (expand_stack(vma, address))
		goto bad_area;

	/*
	 * Ok, we have a good vm_area for this memory access, so
	 * we can handle it..
	 */

 good_area:
	info.si_code = SEGV_ACCERR;

	/* first do some preliminary protection checks */

	if (writeaccess == 2){
		if (!(vma->vm_flags & VM_EXEC))
			goto bad_area;
	} else if (writeaccess == 1) {
		if (!(vma->vm_flags & VM_WRITE))
			goto bad_area;
		flags |= FAULT_FLAG_WRITE;
	} else {
		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
			goto bad_area;
	}

	/*
	 * If for any reason at all we couldn't handle the fault,
	 * make sure we exit gracefully rather than endlessly redo
	 * the fault.
	 */

	fault = handle_mm_fault(mm, vma, address, flags);

	if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
		return;

	if (unlikely(fault & VM_FAULT_ERROR)) {
		if (fault & VM_FAULT_OOM)
			goto out_of_memory;
		else if (fault & VM_FAULT_SIGBUS)
			goto do_sigbus;
		BUG();
	}

	if (flags & FAULT_FLAG_ALLOW_RETRY) {
		if (fault & VM_FAULT_MAJOR)
			tsk->maj_flt++;
		else
			tsk->min_flt++;
		if (fault & VM_FAULT_RETRY) {
			flags &= ~FAULT_FLAG_ALLOW_RETRY;
			flags |= FAULT_FLAG_TRIED;

			/*
			 * No need to up_read(&mm->mmap_sem) as we would
			 * have already released it in __lock_page_or_retry
			 * in mm/filemap.c.
			 */

			goto retry;
		}
	}

	up_read(&mm->mmap_sem);
	return;

	/*
	 * Something tried to access memory that isn't in our memory map..
	 * Fix it, but check if it's kernel or user first..
	 */

 bad_area:
	up_read(&mm->mmap_sem);

 bad_area_nosemaphore:
	DPG(show_registers(regs));

	/* User mode accesses just cause a SIGSEGV */

	if (user_mode(regs)) {
		printk(KERN_NOTICE "%s (pid %d) segfaults for page "
			"address %08lx at pc %08lx\n",
			tsk->comm, tsk->pid,
			address, instruction_pointer(regs));

		/* With DPG on, we've already dumped registers above.  */
		DPG(if (0))
			show_registers(regs);

#ifdef CONFIG_NO_SEGFAULT_TERMINATION
		DECLARE_WAIT_QUEUE_HEAD(wq);
		wait_event_interruptible(wq, 0 == 1);
#else
		info.si_signo = SIGSEGV;
		info.si_errno = 0;
		/* info.si_code has been set above */
		info.si_addr = (void *)address;
		force_sig_info(SIGSEGV, &info, tsk);
#endif
		return;
	}

 no_context:

	/* Are we prepared to handle this kernel fault?
	 *
	 * (The kernel has valid exception-points in the source
	 *  when it accesses user-memory. When it fails in one
	 *  of those points, we find it in a table and do a jump
	 *  to some fixup code that loads an appropriate error
	 *  code)
	 */

	if (find_fixup_code(regs))
		return;

	/*
	 * Oops. The kernel tried to access some bad page. We'll have to
	 * terminate things with extreme prejudice.
	 */

	if (!oops_in_progress) {
		oops_in_progress = 1;
		if ((unsigned long) (address) < PAGE_SIZE)
			printk(KERN_ALERT "Unable to handle kernel NULL "
				"pointer dereference");
		else
			printk(KERN_ALERT "Unable to handle kernel access"
				" at virtual address %08lx\n", address);

		die_if_kernel("Oops", regs, (writeaccess << 1) | protection);
		oops_in_progress = 0;
	}

	do_exit(SIGKILL);

	/*
	 * We ran out of memory, or some other thing happened to us that made
	 * us unable to handle the page fault gracefully.
	 */

 out_of_memory:
	up_read(&mm->mmap_sem);
	if (!user_mode(regs))
		goto no_context;
	pagefault_out_of_memory();
	return;

 do_sigbus:
	up_read(&mm->mmap_sem);

	/*
	 * Send a sigbus, regardless of whether we were in kernel
	 * or user mode.
	 */
	info.si_signo = SIGBUS;
	info.si_errno = 0;
	info.si_code = BUS_ADRERR;
	info.si_addr = (void *)address;
	force_sig_info(SIGBUS, &info, tsk);

	/* Kernel mode? Handle exceptions or die */
	if (!user_mode(regs))
		goto no_context;
	return;

vmalloc_fault:
	{
		/*
		 * Synchronize this task's top level page-table
		 * with the 'reference' page table.
		 *
		 * Use current_pgd instead of tsk->active_mm->pgd
		 * since the latter might be unavailable if this
		 * code is executed in a misfortunately run irq
		 * (like inside schedule() between switch_mm and
		 *  switch_to...).
		 */

		int offset = pgd_index(address);
		pgd_t *pgd, *pgd_k;
		pud_t *pud, *pud_k;
		pmd_t *pmd, *pmd_k;
		pte_t *pte_k;

		pgd = (pgd_t *)per_cpu(current_pgd, smp_processor_id()) + offset;
		pgd_k = init_mm.pgd + offset;

		/* Since we're two-level, we don't need to do both
		 * set_pgd and set_pmd (they do the same thing). If
		 * we go three-level at some point, do the right thing
		 * with pgd_present and set_pgd here.
		 *
		 * Also, since the vmalloc area is global, we don't
		 * need to copy individual PTE's, it is enough to
		 * copy the pgd pointer into the pte page of the
		 * root task. If that is there, we'll find our pte if
		 * it exists.
		 */

		pud = pud_offset(pgd, address);
		pud_k = pud_offset(pgd_k, address);
		if (!pud_present(*pud_k))
			goto no_context;

		pmd = pmd_offset(pud, address);
		pmd_k = pmd_offset(pud_k, address);

		if (!pmd_present(*pmd_k))
			goto bad_area_nosemaphore;

		set_pmd(pmd, *pmd_k);

		/* Make sure the actual PTE exists as well to
		 * catch kernel vmalloc-area accesses to non-mapped
		 * addresses. If we don't do this, this will just
		 * silently loop forever.
		 */

		pte_k = pte_offset_kernel(pmd_k, address);
		if (!pte_present(*pte_k))
			goto no_context;

		return;
	}
}
Esempio n. 6
0
/*
========================================================================
Routine Description:
    Close raxx interface.

Arguments:
	*net_dev			the raxx interface pointer

Return Value:
    0					Open OK
	otherwise			Open Fail

Note:
	1. if open fail, kernel will not call the close function.
	2. Free memory for
		(1) Mlme Memory Handler:		MlmeHalt()
		(2) TX & RX:					RTMPFreeTxRxRingMemory()
		(3) BA Reordering: 				ba_reordering_resource_release()
========================================================================
*/
int rt28xx_close(struct net_device *dev)
{
	struct net_device *net_dev = (struct net_device *)dev;
	struct rt_rtmp_adapter *pAd = NULL;
	BOOLEAN Cancelled;
	u32 i = 0;

#ifdef RTMP_MAC_USB
	DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup);
	DECLARE_WAITQUEUE(wait, current);
#endif /* RTMP_MAC_USB // */

	GET_PAD_FROM_NET_DEV(pAd, net_dev);

	DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n"));

	Cancelled = FALSE;
	/* Sanity check for pAd */
	if (pAd == NULL)
		return 0;	/* close ok */

	{
#ifdef RTMP_MAC_PCI
		RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE);
#endif /* RTMP_MAC_PCI // */

		/* If dirver doesn't wake up firmware here, */
		/* NICLoadFirmware will hang forever when interface is up again. */
		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE)) {
			AsicForceWakeup(pAd, TRUE);
		}
#ifdef RTMP_MAC_USB
		RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
#endif /* RTMP_MAC_USB // */

		MlmeRadioOff(pAd);
#ifdef RTMP_MAC_PCI
		pAd->bPCIclkOff = FALSE;
#endif /* RTMP_MAC_PCI // */
	}

	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);

	for (i = 0; i < NUM_OF_TX_RING; i++) {
		while (pAd->DeQueueRunning[i] == TRUE) {
			DBGPRINT(RT_DEBUG_TRACE,
				 ("Waiting for TxQueue[%d] done..........\n",
				  i));
			RTMPusecDelay(1000);
		}
	}

#ifdef RTMP_MAC_USB
	/* ensure there are no more active urbs. */
	add_wait_queue(&unlink_wakeup, &wait);
	pAd->wait = &unlink_wakeup;

	/* maybe wait for deletions to finish. */
	i = 0;
	/*while((i < 25) && atomic_read(&pAd->PendingRx) > 0) */
	while (i < 25) {
		unsigned long IrqFlags;

		RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
		if (pAd->PendingRx == 0) {
			RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
			break;
		}
		RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);

		msleep(UNLINK_TIMEOUT_MS);	/*Time in millisecond */
		i++;
	}
	pAd->wait = NULL;
	remove_wait_queue(&unlink_wakeup, &wait);
#endif /* RTMP_MAC_USB // */

	/* Stop Mlme state machine */
	MlmeHalt(pAd);

	/* Close net tasklets */
	RtmpNetTaskExit(pAd);

	{
		MacTableReset(pAd);
	}

	MeasureReqTabExit(pAd);
	TpcReqTabExit(pAd);

	/* Close kernel threads */
	RtmpMgmtTaskExit(pAd);

#ifdef RTMP_MAC_PCI
	{
		BOOLEAN brc;
		/*      unsigned long                   Value; */

		if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE)) {
			RTMP_ASIC_INTERRUPT_DISABLE(pAd);
		}
		/* Receive packets to clear DMA index after disable interrupt. */
		/*RTMPHandleRxDoneInterrupt(pAd); */
		/* put to radio off to save power when driver unload.  After radiooff, can't write /read register.  So need to finish all */
		/* register access before Radio off. */

		brc = RT28xxPciAsicRadioOff(pAd, RTMP_HALT, 0);

/*In  solution 3 of 3090F, the bPCIclkOff will be set to TRUE after calling RT28xxPciAsicRadioOff */
		pAd->bPCIclkOff = FALSE;

		if (brc == FALSE) {
			DBGPRINT(RT_DEBUG_ERROR,
				 ("%s call RT28xxPciAsicRadioOff fail!\n",
				  __func__));
		}
	}

/*
	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_ACTIVE))
	{
		RTMP_ASIC_INTERRUPT_DISABLE(pAd);
	}

	// Disable Rx, register value supposed will remain after reset
	NICIssueReset(pAd);
*/
#endif /* RTMP_MAC_PCI // */

	/* Free IRQ */
	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE)) {
#ifdef RTMP_MAC_PCI
		/* Deregister interrupt function */
		RtmpOSIRQRelease(net_dev);
#endif /* RTMP_MAC_PCI // */
		RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
	}
	/* Free Ring or USB buffers */
	RTMPFreeTxRxRingMemory(pAd);

	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);

	/* Free BA reorder resource */
	ba_reordering_resource_release(pAd);

	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);

/*+++Modify by woody to solve the bulk fail+++*/
	{
	}

	DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n"));
	return 0;		/* close ok */
}				/* End of rt28xx_close */
Esempio n. 7
0
static ssize_t debugfs_run_write(struct file *filp, const char __user *ubuf,
				 size_t count, loff_t *offp)
{
	struct perf_ctx *perf = filp->private_data;
	int node, i;
	DECLARE_WAIT_QUEUE_HEAD(wq);

	if (wait_event_interruptible(perf->link_wq, perf->link_is_up))
		return -ENOLINK;

	if (perf->perf_threads == 0)
		return -EINVAL;

	if (!mutex_trylock(&perf->run_mutex))
		return -EBUSY;

	perf_clear_thread_status(perf);

	if (perf->perf_threads > MAX_THREADS) {
		perf->perf_threads = MAX_THREADS;
		pr_info("Reset total threads to: %u\n", MAX_THREADS);
	}

	/* no greater than 1M */
	if (seg_order > MAX_SEG_ORDER) {
		seg_order = MAX_SEG_ORDER;
		pr_info("Fix seg_order to %u\n", seg_order);
	}

	if (run_order < seg_order) {
		run_order = seg_order;
		pr_info("Fix run_order to %u\n", run_order);
	}

	node = dev_to_node(&perf->ntb->pdev->dev);
	atomic_set(&perf->tdone, 0);

	/* launch kernel thread */
	for (i = 0; i < perf->perf_threads; i++) {
		struct pthr_ctx *pctx;

		pctx = &perf->pthr_ctx[i];
		atomic_set(&pctx->dma_sync, 0);
		pctx->perf = perf;
		pctx->wq = &wq;
		pctx->thread =
			kthread_create_on_node(ntb_perf_thread,
					       (void *)pctx,
					       node, "ntb_perf %d", i);
		if (IS_ERR(pctx->thread)) {
			pctx->thread = NULL;
			goto err;
		} else {
			wake_up_process(pctx->thread);
		}
	}

	wait_event_interruptible(wq,
		atomic_read(&perf->tdone) == perf->perf_threads);

	threads_cleanup(perf);
	mutex_unlock(&perf->run_mutex);
	return count;

err:
	threads_cleanup(perf);
	mutex_unlock(&perf->run_mutex);
	return -ENXIO;
}
Esempio n. 8
0
/* The USB device was disconnected */
void auerisdn_disconnect(struct auerswald *cp)
{
	struct auerhisax *ahp;
	DECLARE_WAIT_QUEUE_HEAD(wqh);
	unsigned long flags;
	unsigned int u;
	int ret;
	unsigned int stop_bc;

	dbg("auerisdn_disconnect called");

	/* stop a running timer */
	del_timer_sync(&cp->isdn.dcopen_timer);

	/* first, stop the B channels */
	stop_bc = auerisdn_b_disconnect(cp);

	/* stop the D channels */
	auerisdn_d_l1l2(&cp->isdn, PH_DEACTIVATE | INDICATION, NULL);
	cp->isdn.dc_activated = 0;
	dbg("D-Channel disconnected");

	/* Wait a moment */
	sleep_on_timeout(&wqh, HZ / 10);

	/* Shut the connection to the hisax interface */
	ahp = cp->isdn.ahp;
	if (ahp) {
		dbg("closing connection to hisax interface");
		ahp->cp = NULL;
		cp->isdn.ahp = NULL;
		/* time of last closure */
		if (stop_bc)
			/* if we kill a running connection ... */
			ahp->last_close = jiffies;
		else
			ahp->last_close = 0;
	}

	/* Now free the memory */
	if (cp->isdn.intbi_urbp) {
		ret = usb_unlink_urb(cp->isdn.intbi_urbp);
		if (ret)
			dbg("B in: nonzero int unlink result received: %d",
			    ret);
		usb_free_urb(cp->isdn.intbi_urbp);
		cp->isdn.intbi_urbp = NULL;
	}
	kfree(cp->isdn.intbi_bufp);
	cp->isdn.intbi_bufp = NULL;
	
	if (cp->isdn.intbo_urbp) {
		cp->isdn.intbo_urbp->transfer_flags &= ~USB_ASYNC_UNLINK;
		ret = usb_unlink_urb(cp->isdn.intbo_urbp);
		if (ret)
			dbg("B out: nonzero int unlink result received: %d", ret);
		usb_free_urb(cp->isdn.intbo_urbp);
		cp->isdn.intbo_urbp = NULL;
	}
	kfree(cp->isdn.intbo_bufp);
	cp->isdn.intbo_bufp = NULL;

	/* Remove the rx and tx buffers */
	for (u = 0; u < AUISDN_BCHANNELS; u++) {
		kfree(cp->isdn.bc[u].rxbuf);
		cp->isdn.bc[u].rxbuf = NULL;
		spin_lock_irqsave(&cp->isdn.bc[u].txskb_lock, flags);
		if (cp->isdn.bc[u].txskb) {
			skb_pull(cp->isdn.bc[u].txskb,
				 cp->isdn.bc[u].txskb->len);
			dev_kfree_skb_any(cp->isdn.bc[u].txskb);
			cp->isdn.bc[u].txskb = NULL;
		}
		spin_unlock_irqrestore(&cp->isdn.bc[u].txskb_lock, flags);
	}

	/* Remove the D-channel connection */
	auerswald_removeservice(cp, &cp->isdn.dchannelservice);
}
Esempio n. 9
0
/*
========================================================================
Routine Description:
    Close raxx interface.

Arguments:
	*net_dev			the raxx interface pointer

Return Value:
    0					Open OK
	otherwise			Open Fail

Note:
	1. if open fail, kernel will not call the close function.
	2. Free memory for
		(1) Mlme Memory Handler:		MlmeHalt()
		(2) TX & RX:					RTMPFreeTxRxRingMemory()
		(3) BA Reordering: 				ba_reordering_resource_release()
========================================================================
*/
int rt28xx_close(IN PNET_DEV dev)
{
	struct net_device * net_dev = (struct net_device *)dev;
    RTMP_ADAPTER	*pAd = NULL;
	BOOLEAN 		Cancelled;
	UINT32			i = 0;
#ifdef RTMP_MAC_USB
	DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup); 
	DECLARE_WAITQUEUE(wait, current);

	//RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
#endif // RTMP_MAC_USB //

	GET_PAD_FROM_NET_DEV(pAd, net_dev);	

	DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n"));

#ifdef RT_CFG80211_SUPPORT
	CFG80211_UnRegister(pAd, net_dev);
#endif // RT_CFG80211_SUPPORT //


	Cancelled = FALSE;
	// Sanity check for pAd
	if (pAd == NULL)
		return 0; // close ok



#ifdef WDS_SUPPORT
	WdsDown(pAd);
#endif // WDS_SUPPORT //

#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
	{
#ifdef PCIE_PS_SUPPORT
		RTMPPCIeLinkCtrlValueRestore(pAd, RESTORE_CLOSE);
#endif // PCIE_PS_SUPPORT //

		// If dirver doesn't wake up firmware here,
		// NICLoadFirmware will hang forever when interface is up again.
		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
        {      
		    AsicForceWakeup(pAd, TRUE);
        }

#ifdef RTMP_MAC_USB
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
#endif // RTMP_MAC_USB //

		MlmeRadioOff(pAd);
	}
#endif // CONFIG_STA_SUPPORT //

	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);

	for (i = 0 ; i < NUM_OF_TX_RING; i++)
	{
		while (pAd->DeQueueRunning[i] == TRUE)
		{
			DBGPRINT(RT_DEBUG_TRACE, ("Waiting for TxQueue[%d] done..........\n", i));
			RTMPusecDelay(1000);
		}
	}
	
#ifdef RTMP_MAC_USB
	// ensure there are no more active urbs.
	add_wait_queue (&unlink_wakeup, &wait);
	pAd->wait = &unlink_wakeup;

	// maybe wait for deletions to finish.
	i = 0;
	//while((i < 25) && atomic_read(&pAd->PendingRx) > 0) 
	while(i < 25)
	{
		unsigned long IrqFlags;

		RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
		if (pAd->PendingRx == 0)
		{
			RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
			break;
		}
		RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
		
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
		msleep(UNLINK_TIMEOUT_MS);	//Time in millisecond
#else
		RTMPusecDelay(UNLINK_TIMEOUT_MS*1000);	//Time in microsecond
#endif
		i++;
	}
	pAd->wait = NULL;
	remove_wait_queue (&unlink_wakeup, &wait); 
#endif // RTMP_MAC_USB //


	// Stop Mlme state machine
	MlmeHalt(pAd);
	
	// Close net tasklets
	RtmpNetTaskExit(pAd);


#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
	{
		MacTableReset(pAd);
	}
#endif // CONFIG_STA_SUPPORT //


	MeasureReqTabExit(pAd);
	TpcReqTabExit(pAd);


	// Close kernel threads
	RtmpMgmtTaskExit(pAd);


	// Free IRQ
	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
	{
		RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
	}

	// Free Ring or USB buffers
	RTMPFreeTxRxRingMemory(pAd);

	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);

#ifdef DOT11_N_SUPPORT
	// Free BA reorder resource
	ba_reordering_resource_release(pAd);
#endif // DOT11_N_SUPPORT //
	
#ifdef CONFIG_STA_SUPPORT
#endif // CONFIG_STA_SUPPORT //

	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);

/*+++Modify by woody to solve the bulk fail+++*/
#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
	{
	}
#endif // CONFIG_STA_SUPPORT //

#ifdef VENDOR_FEATURE2_SUPPORT
	printk("Number of Packet Allocated = %d\n", pAd->NumOfPktAlloc);
	printk("Number of Packet Freed = %d\n", pAd->NumOfPktFree);
#endif // VENDOR_FEATURE2_SUPPORT //

	DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n"));
	return 0; // close ok
} /* End of rt28xx_close */
Esempio n. 10
0
/* Probe if this driver wants to serve an USB device

   This entry point is called whenever a new device is attached to the bus.
   Then the device driver has to create a new instance of its internal data
   structures for the new device.

   The  dev argument specifies the device context, which contains pointers
   to all USB descriptors. The  interface argument specifies the interface
   number. If a USB driver wants to bind itself to a particular device and
   interface it has to return a pointer. This pointer normally references
   the device driver's context structure.

   Probing normally is done by checking the vendor and product identifications
   or the class and subclass definitions. If they match the interface number
   is compared with the ones supported by the driver. When probing is done
   class based it might be necessary to parse some more USB descriptors because
   the device properties can differ in a wide range.
*/
static void *auerswald_probe(struct usb_device *usbdev, unsigned int ifnum,
			     const struct usb_device_id *id)
{
	struct auerswald *cp = NULL;
	DECLARE_WAIT_QUEUE_HEAD(wqh);
	unsigned int dtindex;
	unsigned int u = 0;
	char *pbuf;
	int ret;

	dbg("probe: vendor id 0x%x, device id 0x%x ifnum:%d",
	    usbdev->descriptor.idVendor, usbdev->descriptor.idProduct,
	    ifnum);

	/* See if the device offered us matches that we can accept */
	if (usbdev->descriptor.idVendor != ID_AUERSWALD)
		return NULL;

	/* we use only the first -and only- interface */
	if (ifnum != 0)
		return NULL;

	/* prevent module unloading while sleeping */
	MOD_INC_USE_COUNT;

	/* allocate memory for our device and intialize it */
	cp = kmalloc(sizeof(struct auerswald), GFP_KERNEL);
	if (cp == NULL) {
		err("out of memory");
		goto pfail;
	}

	/* Initialize device descriptor */
	memset(cp, 0, sizeof(struct auerswald));
	init_MUTEX(&cp->mutex);
	cp->usbdev = usbdev;
	auerchain_init(&cp->controlchain);
	auerbuf_init(&cp->bufctl);
	init_waitqueue_head(&cp->bufferwait);
	auerisdn_init_dev(cp);

	/* find a free slot in the device table */
	down(&auerdev_table_mutex);
	for (dtindex = 0; dtindex < AUER_MAX_DEVICES; ++dtindex) {
		if (auerdev_table[dtindex] == NULL)
			break;
	}
	if (dtindex >= AUER_MAX_DEVICES) {
		err("more than %d devices plugged in, can not handle this device", AUER_MAX_DEVICES);
		up(&auerdev_table_mutex);
		goto pfail;
	}

	/* Give the device a name */
	sprintf(cp->name, AU_PREFIX "%d", dtindex);

	/* Store the index */
	cp->dtindex = dtindex;
	auerdev_table[dtindex] = cp;
	up(&auerdev_table_mutex);

	/* initialize the devfs node for this device and register it */
	cp->devfs = devfs_register(usb_devfs_handle, cp->name,
				   DEVFS_FL_DEFAULT, USB_MAJOR,
				   AUER_MINOR_BASE + dtindex,
				   S_IFCHR | S_IRUGO | S_IWUGO,
				   &auerswald_fops, NULL);

	/* Get the usb version of the device */
	cp->version = cp->usbdev->descriptor.bcdDevice;
	dbg("Version is %X", cp->version);

	/* allow some time to settle the device */
	sleep_on_timeout(&wqh, HZ / 3);

	/* Try to get a suitable textual description of the device */
	/* Device name: */
	ret =
	    usb_string(cp->usbdev, AUSI_DEVICE, cp->dev_desc,
		       AUSI_DLEN - 1);
	if (ret >= 0) {
		u += ret;
		/* Append Serial Number */
		memcpy(&cp->dev_desc[u], ",Ser# ", 6);
		u += 6;
		ret =
		    usb_string(cp->usbdev, AUSI_SERIALNR, &cp->dev_desc[u],
			       AUSI_DLEN - u - 1);
		if (ret >= 0) {
			u += ret;
			/* Append subscriber number */
			memcpy(&cp->dev_desc[u], ", ", 2);
			u += 2;
			ret =
			    usb_string(cp->usbdev, AUSI_MSN,
				       &cp->dev_desc[u],
				       AUSI_DLEN - u - 1);
			if (ret >= 0) {
				u += ret;
			}
		}
	}
	cp->dev_desc[u] = '\0';
	info("device is a %s", cp->dev_desc);

	/* get the maximum allowed control transfer length */
	pbuf = (char *) kmalloc(2, GFP_KERNEL);	/* use an allocated buffer because of urb target */
	if (!pbuf) {
		err("out of memory");
		goto pfail;
	}
	ret = usb_control_msg(cp->usbdev,			/* pointer to device */
			      usb_rcvctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */
			      AUV_GETINFO,			/* USB message request value */
			      AUT_RREQ,				/* USB message request type value */
			      0,				/* USB message value */
			      AUDI_MBCTRANS,			/* USB message index value */
			      pbuf,				/* pointer to the receive buffer */
			      2,				/* length of the buffer */
			      HZ * 2);				/* time to wait for the message to complete before timing out */
	if (ret == 2) {
		cp->maxControlLength = le16_to_cpup(pbuf);
		kfree(pbuf);
		dbg("setup: max. allowed control transfersize is %d bytes",
		    cp->maxControlLength);
	} else {
		kfree(pbuf);
		err("setup: getting max. allowed control transfer length failed with error %d", ret);
		goto pfail;
	}
	/* allocate a chain for the control messages */
	if (auerchain_setup(&cp->controlchain, AUCH_ELEMENTS)) {
		err("out of memory");
		goto pfail;
	}

	/* allocate buffers for control messages */
	if (auerbuf_setup
	    (&cp->bufctl, AU_RBUFFERS * 2,
	     cp->maxControlLength + AUH_SIZE)) {
		err("out of memory");
		goto pfail;
	}

	/* start the interrupt endpoint */
	if (auerswald_int_open(cp)) {
		err("int endpoint failed");
		goto pfail;
	}

	/* Try to connect to hisax interface */
	if (auerisdn_probe(cp)) {
		err("hisax connect failed");
		goto pfail;
	}

	/* all OK */
	return cp;

	/* Error exit: clean up the memory */
      pfail:auerswald_delete(cp);
	MOD_DEC_USE_COUNT;
	return NULL;
}
Esempio n. 11
0
/*=======================================================================*/
aau_sgl_t *aau_get_buffer(u32 aau_context, int num_buf)
{
	sw_aau_t *sw_desc = NULL;
	sw_aau_t *sw_head = NULL;
	sw_aau_t *sw_prev = NULL;

	int retry = 10;
	int i;
	DECLARE_WAIT_QUEUE_HEAD(wait_q);

	if((num_buf > MAX_AAU_DESC) || (num_buf <= 0))
	{
		return NULL;
	}

	DPRINTK("Getting %d descriptors\n", num_buf);
	for(i = num_buf; i > 0; i--)
	{
		spin_lock_irq(&free_lock);
		if(!list_empty(&free_stack))
		{
			sw_desc = SW_ENTRY(free_stack.next);
			list_del(free_stack.next);
			spin_unlock_irq(&free_lock);
		}
		else
		{
			while(retry-- && !sw_desc)
			{
				spin_unlock_irq(&free_lock);
				interruptible_sleep_on_timeout(&wait_q, SLEEP_TIME);
				spin_lock_irq(&free_lock);
				if(!list_empty(&free_stack))
				{
					sw_desc = SW_ENTRY(free_stack.next);
					list_del(free_stack.next);
				}
				spin_unlock_irq(&free_lock);
			}

			sw_desc = sw_head;
			spin_lock_irq(&free_lock);
			while(sw_desc)
			{
				sw_desc->status = 0;
				sw_desc->head = NULL;
				sw_desc->tail = NULL;
				list_add(&sw_desc->link, &free_stack);
				sw_desc = (sw_aau_t *) sw_desc->next;
			}					/* end while */
			spin_unlock_irq(&dma_free_lock);
			return NULL;
		}						/* end else */

		if(sw_prev)
		{
			sw_prev->next = (aau_sgl_t *) sw_desc;
			sw_prev->aau_desc.NDA = sw_desc->aau_phys;
		}
		else
		{
			sw_head = sw_desc;
		}

		sw_prev = sw_desc;
	}							/* end for */

	sw_desc->aau_desc.NDA = 0;
	sw_desc->next = NULL;
	sw_desc->status = 0;
	return (aau_sgl_t *) sw_head;
}	
Esempio n. 12
0
/*=======================================================================*/
int aau_queue_buffer(u32 aau_context, aau_head_t * listhead)
{
	sw_aau_t *sw_desc = (sw_aau_t *) listhead->list;
	sw_aau_t *prev_desc = NULL;
	sw_aau_t *head = NULL;
	aau_head_t *sgl_head = listhead;
	int err = 0;
	int i;
	iop310_aau_t *aau = (iop310_aau_t *) aau_context;
	DECLARE_WAIT_QUEUE_HEAD(wait_q);

	DPRINTK("Entering aau_queue_buffer()\n");

	/* scan through entire user SGL */
	while(sw_desc)
	{
		sw_desc->sgl_head = (u32) listhead;

		/* we clean the cache for previous descriptor in chain */
		if(prev_desc)
		{
			prev_desc->aau_desc.NDA = sw_desc->aau_phys;
			cpu_dcache_clean_range((u32)&prev_desc->aau_desc,
			   (u32)&prev_desc->aau_desc + AAU_DESC_SIZE);
		}
		else
		{
			/* no previous descriptor, so we set this to be head */
			head = sw_desc;
		}

		sw_desc->head = head;
		/* set previous to current */
		prev_desc = sw_desc;

		/* put descriptor on process */
		spin_lock_irq(&aau->process_lock);
		list_add_tail(&sw_desc->link, &aau->process_q);
		spin_unlock_irq(&aau->process_lock);

		sw_desc = (sw_aau_t *)sw_desc->next;
	}
	DPRINTK("Done converting SGL to AAU Chain List\n");

	/* if our tail exists */
	if(prev_desc)
	{
		/* set the head pointer on tail */
		prev_desc->head = head;
		/* set the header pointer's tail to tail */
		head->tail = prev_desc;
		prev_desc->tail = prev_desc;

		/* clean cache for tail */
		cpu_dcache_clean_range((u32)&prev_desc->aau_desc, 
			(u32)&prev_desc->aau_desc + AAU_DESC_SIZE);

		DPRINTK("Starting AAU accelerator\n");
		/* start the AAU */
		DPRINTK("Starting at chain: 0x%x\n", (u32)head);
		if((err = aau_start(aau, head)) >= 0)
		{
			DPRINTK("ASR: %#x\n", *IOP310_AAUASR);
			if(!sgl_head->callback)
			{
				wait_event_interruptible(aau->wait_q, 
					(sgl_head->status & AAU_COMPLETE));
			}
			return 0;
		}
		else
		{
			DPRINTK("AAU start failed!\n");
			return err;
		}
	}

	return -EINVAL;
}
Esempio n. 13
0
static int usb_rtusb_close_device(
	IN	PRTMP_ADAPTER	pAd)
{
	int i = 0;
	int ret;
	
	DECLARE_WAIT_QUEUE_HEAD (unlink_wakeup); 
	DECLARE_WAITQUEUE (wait, current);

	DBGPRINT(RT_DEBUG_TRACE, "-->usb_rtusb_close_device \n");

	// ensure there are no more active urbs. 
	add_wait_queue (&unlink_wakeup, &wait);
	pAd->wait = &unlink_wakeup;

	// maybe wait for deletions to finish.
	while ((i < 25) && atomic_read(&pAd->PendingRx) > 0)
	{
#if LINUX_VERSION_CODE >KERNEL_VERSION(2,6,9)
		msleep(UNLINK_TIMEOUT_MS);
#endif
		i++;
	}

	pAd->wait = NULL;
	remove_wait_queue (&unlink_wakeup, &wait); 

	if (pAd->MLMEThr_pid >= 0) 
	{
		mlme_kill = 1;
		RTUSBMlmeUp(pAd);
		wmb(); // need to check
		ret = KILL_THREAD_PID (pAd->MLMEThr_pid, SIGTERM, 1);
		if (ret) 
		{
			printk (KERN_WARNING "%s: unable to Mlme thread \n", pAd->net_dev->name);
		}
		wait_for_completion (&pAd->MlmeThreadNotify);
		// reset mlme thread
		pAd->MLMEThr_pid = THREAD_PID_INIT_VALUE;
	}

	if (pAd->RTUSBCmdThr_pid>= 0) 
	{
		RTUSBCmd_kill = 1;
		RTUSBCMDUp(pAd);
		wmb(); // need to check
		ret = KILL_THREAD_PID (pAd->RTUSBCmdThr_pid, SIGTERM, 1);
		if (ret) 
		{
			printk (KERN_WARNING "%s: unable to RTUSBCmd thread \n", pAd->net_dev->name);
		}
		wait_for_completion (&pAd->CmdThreadNotify);
		// reset cmd thread
		pAd->RTUSBCmdThr_pid= THREAD_PID_INIT_VALUE;
	}

	RTUSBHalt(pAd, TRUE);
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
	tasklet_kill(&pAd->rx_bh);



	DBGPRINT(RT_DEBUG_TRACE,"<--usb_rtusb_close_device \n");

	return 0;
}
Esempio n. 14
0
static int p_ioctl(int index, struct inode* inode, struct file* filp, unsigned int cmd, unsigned long arg)
{
	context *ct = filp->private_data;
	pipe_file *pp = &(pipes[index]);
	tell_inf t_inf;
	size_inf s_inf;
#ifdef KRSA
	krsa_arg rsa;
	unsigned char *input = NULL, output[MAX_RSA_MODULUS_LEN];
	unsigned int inputlen = 0, outputlen = 0;
#endif
	int err = 0, ret = 0, i;

	if(!capable(CAP_SYS_ADMIN)) return -EPERM;

	if(_IOC_TYPE(cmd) != P_IOCMAGIC) return -ENOTTY;

	if(_IOC_DIR(cmd) & _IOC_READ) {
		err = !access_ok(VERIFY_WRITE, (void *)arg, _IOC_SIZE(cmd));
	}
	else if(_IOC_DIR(cmd) & _IOC_WRITE) {
		err = !access_ok(VERIFY_READ, (void *)arg, _IOC_SIZE(cmd));
	}
	if(err) return -EFAULT;

	Down(index);

	switch(cmd) {
	case P_IOCCLEAR:
		dev_flush(&(pp->device));
		for(i=0; i<=CONTEXT; i++) {
			((pp->ct)[i]).hotp = NULL;	
		}
		break;
	case P_IOCRESET:
		memset(pp->ct, 0, sizeof(context)*(CONTEXT+1));
#ifdef __PIPE_SELECT__
        pp->r_poll = 1;
        pp->r_pos = 0;
#endif
		for(i=0; i<=CONTEXT; i++) {
			((pp->ct)[i]).r_able = 1;
			((pp->ct)[i]).w_able = 1;
		}
		RELEASE(index) = 0; WRITERS(index) = 0;
		dev_flush(&(pp->device));
		(pp->device).ctp = pp->ct;
		(pp->device).pred = 2*BUFF_SIZE;
	#ifdef KERNEL_PIPE
		pipeType[index]=PIPE_TYPE_USER_THREAD;
	#endif
	
		break;
	case P_IOCSIZE:
		if(copy_from_user((char*)&s_inf, (char*)arg, sizeof(size_inf))) {
			ret = (-EFAULT); goto my_error;
		}
#ifndef	CONFIG_PROC_PIPE_64_BITS_SUPPORT
#ifndef CONFIG_PROC_PIPE_KERNEL_SUPPORT_64_BITS
		if(s_inf.mdas > 0xFFFFFFFFF || s_inf.idxs > 0xFFFFFFFF) {
			ret = (-EFAULT); goto my_error;
		}
#endif
		(pp->mda)->size = s_inf.mdas;
		(pp->idx)->size = s_inf.idxs;
#else	// !CONFIG_PROC_PIPE_64_BITS_SUPPORT
#if 0
		(pp->mda)->size = s_inf.mdas;
		(pp->idx)->size = s_inf.idxs;
#else
		(pp->mda)->size = 0; 
		(pp->idx)->size = 0;
#endif
		pp->mda_size = s_inf.mdas;
		pp->idx_size = s_inf.idxs;
#endif	// !CONFIG_PROC_PIPE_64_BITS_SUPPORT
		for(i=0; i<CONTEXT; i++) {
			((pp->ct)[i]).epos = s_inf.mdas;
		}
		((pp->ct)[CONTEXT]).bpos = s_inf.dats;
		((pp->ct)[CONTEXT]).epos = s_inf.dats + s_inf.idxs;
		((pp->ct)[CONTEXT]).seek = s_inf.dats;
		break;
	case P_IOCREVS:
		((pp->ct)[CONTEXT]).reverse = *((int*)arg);
		break;
	case P_IOCTELL:
		t_inf.seek = filp->f_pos;
		t_inf.size = (BPOS(ct))?(BUFF_SIZE):(SIZE(ct));
		if(copy_to_user((char*)arg, (char*)&t_inf, sizeof(tell_inf))) {
			ret = (-EFAULT); goto my_error;
		}
		break;
	case P_IOCRELS:
		RELEASE(index) = 1;
		wake_up_interruptible(&(RQ(index)));
		wake_up_interruptible(&(WQ(index)));
		break;
	case P_IOCPRED:
		(pp->device).pred = *((size_t*)arg);
		break;
#ifdef KRSA
	case P_IOCKRSA:
		if(copy_from_user((char*)&rsa, (char*)arg, sizeof(krsa_arg))) {
			ret = (-EFAULT); goto my_error;
		}
		if(!access_ok(VERIFY_READ, (void *)(rsa.len), sizeof(unsigned int))) {
			ret = (-EFAULT); goto my_error;
		}
		if(copy_from_user((char*)&inputlen, (char*)(rsa.len), sizeof(unsigned int))) {
			ret = (-EFAULT); goto my_error;
		}
		if(!(input = kmalloc(inputlen, GFP_KERNEL))) {
			ret = (-EFAULT); goto my_error;
		}
		if(!access_ok(VERIFY_READ, (void *)(rsa.buf), inputlen)) {
			ret = (-EFAULT); goto my_error;
		}
		if(copy_from_user((char*)input, (char*)(rsa.buf), inputlen)) {
			ret = (-EFAULT); goto my_error;
		}
		if(RSAPrivateBlock(output, &outputlen, input, inputlen, &(rsa.key))) {
			ret = (-EFAULT); goto my_error;
		}
		if(!access_ok(VERIFY_WRITE, (void *)(rsa.buf), outputlen)) {
			ret = (-EFAULT); goto my_error;
		}
		if(copy_to_user((char*)(rsa.buf), (char*)output, outputlen)) {
			ret = (-EFAULT); goto my_error;
		}
		if(!access_ok(VERIFY_WRITE, (void *)(rsa.len), sizeof(unsigned int))) {
			ret = (-EFAULT); goto my_error;
		}
		if(copy_to_user((char*)(rsa.len), (char*)&outputlen, sizeof(unsigned int))) {
			ret = (-EFAULT); goto my_error;
		}
		break;
#endif


	#ifdef KERNEL_PIPE
	case P_IOCPIPETYPE:
			{
				int val;

				get_user(val,(int *)arg);

				if(val<0) {
					ret= -EFAULT;
					break;
				}
				
				#ifdef NO_KERNEL_PIPE_THREAD
					if(val<=PIPE_TYPE_KERNEL_DIRECT)
				#else
					if(val<=PIPE_TYPE_KERNEL_THREAD)
				#endif
					pipeType[index]=val;
				 else
				 	ret= -EFAULT;
			}
		break;
	case P_IOCPIPESTART:
		{
		//	int len;
			kpipe_setup userPath;
			kpipe_setup *pipeSetup;
			pipe_thread *pipeThread;
			DECLARE_WAIT_QUEUE_HEAD(WQ);

			copy_from_user(&userPath,(kpipe_setup *)arg,sizeof(kpipe_setup));
			
			
			pipeSetup=pipeManage.threads[index].pipeSetup;
			pipeThread=&(pipeManage.threads[index]);

//select a default pipe type.
			if(pipeType[index]==PIPE_TYPE_USER_THREAD)
				pipeType[index]=defaultPipeType;
			if(pipeType[index]!=PIPE_TYPE_KERNEL_THREAD && pipeType[index]!=PIPE_TYPE_KERNEL_DIRECT)
				pipeType[index]=PIPE_TYPE_KERNEL_DIRECT;

	//pipe_type_kernel_direct doesn't support local file.
	#ifdef NO_KERNEL_PIPE_THREAD
			if(pipeType[index]==PIPE_TYPE_KERNEL_DIRECT) {
				if(userPath.type>PIPE_KP) {
					ret = -EFAULT;
					break;
					}
			}
		#endif
			
			if(*(pipeSetup->host)) //if it has used already? a.dma or a.index.
				pipeSetup++;
			if(*(pipeSetup->host)) {
				HDEBUG("no pipeSetup\n");
				ret = -EFAULT;
				break;
			}
				

			
			pipeThread->index = index;	//a or b.
			pipeSetup->index = index;
		//	copy_from_user(&pipeSetup->nums,&userPath.nums,1);
			pipeSetup->nums = userPath.nums;
			
		//	copy_from_user(&pipeSetup->size,&((kpipe_setup *)arg)->size,sizeof(int));
			 pipeSetup->size = userPath.size;
			 
		//	copy_from_user(&httpThread->type,&((kpipe_setup *)arg)->type,1);
			pipeThread->type = userPath.type;	//close or keep alive.
			
			memcpy(pipeSetup->host,userPath.host,16);

			memcpy(pipeSetup->procfile,userPath.procfile,16);
			
			if(!strcmp(pipeSetup->procfile+strlen("/proc/a."),"mda")) {
				
				pipeSetup->pathIndex = MEDIA_PATH_NUM;	//dma or index.
			} else {
				pipeSetup->pathIndex  = INDEX_PATH_NUM;
			}
			
		
		//	pipeSetup->host=HTTP_MALLOC(strlen(userPath->host)+1);
			pipeSetup->path=HTTP_MALLOC(userPath.pathSize);
		//	pipeSetup->sessionid=HTTP_MALLOC(((kpipe_setup *)arg)->sessionidSize);
			
			if(!pipeSetup->path) {
			// no memroy.
			}
			
			copy_from_user(pipeSetup->path,userPath.path,userPath.pathSize);
		
			if(userPath.sessionid){
				pipeSetup->sessionid=HTTP_MALLOC(userPath.sessionidSize);

				copy_from_user(pipeSetup->sessionid,userPath.sessionid,userPath.sessionidSize);
			}
			
		//	copy_from_user(&(pipeSetup->port),&userPath.port),sizeof(short));
			pipeSetup->port = userPath.port;
			
		//	copy_from_user(&(pipeSetup->protection),&(((kpipe_setup *)arg)->protection),sizeof(int));			
			pipeSetup->protection = userPath.protection;

			HDEBUG("ioctl:%s %d:%s\n",pipeSetup->host,pipeSetup->port,pipeSetup->path);
			
			//pipeManage.starts[index][pipeSetup->index].start=1;
		
			if(pipeType[index]==PIPE_TYPE_KERNEL_THREAD) {
				down_interruptible(&(pipeManage.semaphore));
				atomic_set(&(pipeManage.starts[index][pipeSetup->pathIndex]),1); //start kernel_thread.
			//to wakeup manage thread.
		
				while(pipeManage.change) {
					interruptible_sleep_on_timeout(&WQ,5);
				}
				pipeManage.change=1;
				up(&(pipeManage.semaphore));
				wake_up_interruptible(&(pipeManage.wq));
				
			}
		
	
		}
		
	
		break;
	case P_IOCPIPESTOP:
		{
		
			pipe_thread *thread=&(pipeManage.threads[index]);
			int i;
			DECLARE_WAIT_QUEUE_HEAD(WQ);	

			RELEASE(index) = 1;

		if(pipeType[index]==PIPE_TYPE_KERNEL_THREAD) {
			wake_up_interruptible(&(RQ(index)));
			wake_up_interruptible(&(WQ(index)));



			down_interruptible(&(pipeManage.semaphore));
			atomic_set(&(pipeManage.stops[index]),1);
				//to wakeup manage thread.
			while(pipeManage.change) {
					interruptible_sleep_on_timeout(&WQ,5);
			}
			pipeManage.change = 1;
			up(&(pipeManage.semaphore));
			wake_up_interruptible(&(pipeManage.wq));
			
		} 
		else {
			 	for(i=0;i<END_PATH_NUM;i++) {
				if(thread->pipeSetup[i].path) {
					HTTP_FREE(thread->pipeSetup[i].path);
					if(thread->pipeSetup[i].sessionid)
						HTTP_FREE(thread->pipeSetup[i].sessionid);
					memset(&(thread->pipeSetup[i]),0,sizeof(kpipe_setup));
				}
			}
		}	
	
			
		}
		break;
	#endif
	default:
		ret = (-ENOTTY);
	}
	
my_error:
#ifdef KRSA
	if(input) kfree(input);
#endif
	Up(index);
	return ret;
}
Esempio n. 15
0
static void bluecard_write_wakeup(bluecard_info_t *info)
{
	if (!info) {
		BT_ERR("Unknown device");
		return;
	}

	if (!test_bit(XMIT_SENDING_READY, &(info->tx_state)))
		return;

	if (test_and_set_bit(XMIT_SENDING, &(info->tx_state))) {
		set_bit(XMIT_WAKEUP, &(info->tx_state));
		return;
	}

	do {
		register unsigned int iobase = info->link.io.BasePort1;
		register unsigned int offset;
		register unsigned char command;
		register unsigned long ready_bit;
		register struct sk_buff *skb;
		register int len;

		clear_bit(XMIT_WAKEUP, &(info->tx_state));

		if (!(info->link.state & DEV_PRESENT))
			return;

		if (test_bit(XMIT_BUFFER_NUMBER, &(info->tx_state))) {
			if (!test_bit(XMIT_BUF_TWO_READY, &(info->tx_state)))
				break;
			offset = 0x10;
			command = REG_COMMAND_TX_BUF_TWO;
			ready_bit = XMIT_BUF_TWO_READY;
		} else {
			if (!test_bit(XMIT_BUF_ONE_READY, &(info->tx_state)))
				break;
			offset = 0x00;
			command = REG_COMMAND_TX_BUF_ONE;
			ready_bit = XMIT_BUF_ONE_READY;
		}

		if (!(skb = skb_dequeue(&(info->txq))))
			break;

		if (skb->pkt_type & 0x80) {
			/* Disable RTS */
			info->ctrl_reg |= REG_CONTROL_RTS;
			outb(info->ctrl_reg, iobase + REG_CONTROL);
		}

		/* Activate LED */
		bluecard_enable_activity_led(info);

		/* Send frame */
		len = bluecard_write(iobase, offset, skb->data, skb->len);

		/* Tell the FPGA to send the data */
		outb_p(command, iobase + REG_COMMAND);

		/* Mark the buffer as dirty */
		clear_bit(ready_bit, &(info->tx_state));

		if (skb->pkt_type & 0x80) {
			DECLARE_WAIT_QUEUE_HEAD(wq);
			DEFINE_WAIT(wait);

			unsigned char baud_reg;

			switch (skb->pkt_type) {
			case PKT_BAUD_RATE_460800:
				baud_reg = REG_CONTROL_BAUD_RATE_460800;
				break;
			case PKT_BAUD_RATE_230400:
				baud_reg = REG_CONTROL_BAUD_RATE_230400;
				break;
			case PKT_BAUD_RATE_115200:
				baud_reg = REG_CONTROL_BAUD_RATE_115200;
				break;
			case PKT_BAUD_RATE_57600:
				/* Fall through... */
			default:
				baud_reg = REG_CONTROL_BAUD_RATE_57600;
				break;
			}

			/* Wait until the command reaches the baseband */
			prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
			schedule_timeout(HZ/10);
			finish_wait(&wq, &wait);

			/* Set baud on baseband */
			info->ctrl_reg &= ~0x03;
			info->ctrl_reg |= baud_reg;
			outb(info->ctrl_reg, iobase + REG_CONTROL);

			/* Enable RTS */
			info->ctrl_reg &= ~REG_CONTROL_RTS;
			outb(info->ctrl_reg, iobase + REG_CONTROL);

			/* Wait before the next HCI packet can be send */
			prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
			schedule_timeout(HZ);
			finish_wait(&wq, &wait);
		}

		if (len == skb->len) {
			kfree_skb(skb);
		} else {
			skb_pull(skb, len);
			skb_queue_head(&(info->txq), skb);
		}

		info->hdev->stat.byte_tx += len;

		/* Change buffer */
		change_bit(XMIT_BUFFER_NUMBER, &(info->tx_state));

	} while (test_bit(XMIT_WAKEUP, &(info->tx_state)));

	clear_bit(XMIT_SENDING, &(info->tx_state));
}
Esempio n. 16
0
/* Connect to the HISAX interface. Returns 0 if successfull */
int auerisdn_probe(struct auerswald *cp)
{
	struct hisax_b_if *b_if[AUISDN_BCHANNELS];
	struct usb_endpoint_descriptor *ep;
	struct auerhisax *ahp;
	DECLARE_WAIT_QUEUE_HEAD(wqh);
	unsigned int u;
	unsigned char *ucp;
	unsigned int first_time;
	int ret;

	/* First allocate resources, then register hisax interface */

	/* Allocate RX buffers */
	for (u = 0; u < AUISDN_BCHANNELS; u++) {
		if (!cp->isdn.bc[u].rxbuf) {
			cp->isdn.bc[u].rxbuf =
			    (char *) kmalloc(AUISDN_RXSIZE, GFP_KERNEL);
			if (!cp->isdn.bc[u].rxbuf) {
				err("can't allocate buffer for B channel RX data");
				return -1;
			}
		}
	}

	/* Read out B-Channel output fifo size */
	ucp = kmalloc(32, GFP_KERNEL);
	if (!ucp) {
		err("Out of memory");
		return -3;
	}
	ret = usb_control_msg(cp->usbdev,			/* pointer to device */
			      usb_rcvctrlpipe(cp->usbdev, 0),	/* pipe to control endpoint */
			      AUV_GETINFO,			/* USB message request value */
			      AUT_RREQ,				/* USB message request type value */
			      0,				/* USB message value */
			      AUDI_OUTFSIZE,			/* USB message index value */
			      ucp,				/* pointer to the receive buffer */
			      32,				/* length of the buffer */
			      HZ * 2);				/* time to wait for the message to complete before timing out */
	if (ret < 4) {
		kfree(ucp);
		err("can't read TX Fifo sizes for B1,B2");
		return -4;
	}
	for (u = 0; u < AUISDN_BCHANNELS; u++) {
		ret = le16_to_cpup(ucp + u * 2);
		cp->isdn.bc[u].ofsize = ret;
		cp->isdn.bc[u].txfree = ret;
	}
	kfree(ucp);
	for (u = 0; u < AUISDN_BCHANNELS; u++) {
		dbg("B%d buffer size is %d", u, cp->isdn.bc[u].ofsize);
	}

	/* get the B channel output INT size */
	cp->isdn.intbo_endp = AU_IRQENDPBO;
	ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_OUT | AU_IRQENDPBO);
	if (!ep) {
		/* Some devices have another endpoint number here ... */
		cp->isdn.intbo_endp = AU_IRQENDPBO_2;
		ep = usb_epnum_to_ep_desc(cp->usbdev,
					  USB_DIR_OUT | AU_IRQENDPBO_2);
		if (!ep) {
			err("can't get B channel OUT endpoint");
			return -5;
		}
	}
	cp->isdn.outsize = ep->wMaxPacketSize;
	cp->isdn.outInterval = ep->bInterval;
	cp->isdn.usbdev = cp->usbdev;

	/* allocate the urb and data buffer */
	if (!cp->isdn.intbo_urbp) {
		cp->isdn.intbo_urbp = usb_alloc_urb(0);
		if (!cp->isdn.intbo_urbp) {
			err("can't allocate urb for B channel output endpoint");
			return -6;
		}
	}
	if (!cp->isdn.intbo_bufp) {
		cp->isdn.intbo_bufp =
		    (char *) kmalloc(cp->isdn.outsize, GFP_KERNEL);
		if (!cp->isdn.intbo_bufp) {
			err("can't allocate buffer for B channel output endpoint");
			return -7;
		}
	}

	/* get the B channel input INT size */
	ep = usb_epnum_to_ep_desc(cp->usbdev, USB_DIR_IN | AU_IRQENDPBI);
	if (!ep) {
		err("can't get B channel IN endpoint");
		return -8;
	}
	cp->isdn.insize = ep->wMaxPacketSize;

	/* allocate the urb and data buffer */
	if (!cp->isdn.intbi_urbp) {
		cp->isdn.intbi_urbp = usb_alloc_urb(0);
		if (!cp->isdn.intbi_urbp) {
			err("can't allocate urb for B channel input endpoint");
			return -9;
		}
	}
	if (!cp->isdn.intbi_bufp) {
		cp->isdn.intbi_bufp =
		    (char *) kmalloc(cp->isdn.insize, GFP_KERNEL);
		if (!cp->isdn.intbi_bufp) {
			err("can't allocate buffer for B channel input endpoint");
			return -10;
		}
	}

	/* setup urb */
	FILL_INT_URB(cp->isdn.intbi_urbp, cp->usbdev,
		     usb_rcvintpipe(cp->usbdev, AU_IRQENDPBI),
		     cp->isdn.intbi_bufp, cp->isdn.insize,
		     auerisdn_intbi_complete, cp, ep->bInterval);
	/* start the urb */
	cp->isdn.intbi_urbp->status = 0;	/* needed! */
	ret = usb_submit_urb(cp->isdn.intbi_urbp);
	if (ret < 0) {
		err("activation of B channel input int failed %d", ret);
		usb_free_urb(cp->isdn.intbi_urbp);
		cp->isdn.intbi_urbp = NULL;
		return -11;
	}

	/* request the D-channel service now */
	dbg("Requesting D channel now");
	cp->isdn.dchannelservice.id = AUH_DCHANNEL;
	if (auerswald_addservice(cp, &cp->isdn.dchannelservice)) {
		err("can not open D-channel");
		cp->isdn.dchannelservice.id = AUH_UNASSIGNED;
		return -2;
	}

	/* Find a free hisax interface */
	for (u = 0; u < AUER_MAX_DEVICES; u++) {
		ahp = &auerhisax_table[u];
		if (!ahp->cp) {
			first_time = (u == 0);
			goto ahp_found;
		}
	}
	/* no free interface found */
	return -12;

	/* we found a free hisax interface */
      ahp_found:
	/* Wait until ipppd timeout expired. The reason behind this ugly construct:
	   If we connect to a hisax device without waiting for ipppd we are not able
	   to make a new IP connection. */
	if (ahp->last_close) {
		unsigned long timeout = jiffies - ahp->last_close;
		if (timeout < AUISDN_IPTIMEOUT) {
			info("waiting for ipppd to timeout");
			sleep_on_timeout(&wqh, AUISDN_IPTIMEOUT - timeout);
		}
	}

	cp->isdn.ahp = ahp;
	u = ahp->hisax_registered;
	ahp->hisax_registered = 1;
	ahp->cp = cp;

	/* now do the registration */
	if (!u) {
		for (u = 0; u < AUISDN_BCHANNELS; u++) {
			b_if[u] = &ahp->hisax_b_if[u];
		}
		if (hisax_register
		    (&ahp->hisax_d_if, b_if, "auerswald_usb",
		     ISDN_PTYPE_EURO)) {
			err("hisax registration failed");
			ahp->cp = NULL;
			cp->isdn.ahp = NULL;
			ahp->hisax_registered = 0;
			return -13;
		}
		dbg("hisax interface registered");
	}

	/* send a D channel L1 activation indication to hisax */
	auerisdn_d_l1l2(&cp->isdn, PH_ACTIVATE | INDICATION, NULL);
	cp->isdn.dc_activated = 1;

	/* do another D channel activation for problematic devices */
	cp->isdn.dcopen_timer.expires = jiffies + HZ;
	dbg("add timer");
	add_timer(&cp->isdn.dcopen_timer);

	return 0;
}
Esempio n. 17
0
static void acpi_bus_osc_support(void)
{
	u32 capbuf[2];
	struct acpi_osc_context context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
		.cap.length = 8,
		.cap.pointer = capbuf,
	};
	acpi_handle handle;

	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) || \
	defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
#endif

#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
#endif
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;
	if (ACPI_SUCCESS(acpi_run_osc(handle, &context)))
		kfree(context.ret.pointer);
	/* do we need to check the returned cap? Sounds no */
}

/* --------------------------------------------------------------------------
                                Event Management
   -------------------------------------------------------------------------- */

#ifdef CONFIG_ACPI_PROC_EVENT
static DEFINE_SPINLOCK(acpi_bus_event_lock);

LIST_HEAD(acpi_bus_event_list);
DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue);

extern int event_is_open;

int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data)
{
	struct acpi_bus_event *event;
	unsigned long flags = 0;

	/* drop event on the floor if no one's listening */
	if (!event_is_open)
		return 0;

	event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC);
	if (!event)
		return -ENOMEM;

	strcpy(event->device_class, device_class);
	strcpy(event->bus_id, bus_id);
	event->type = type;
	event->data = data;

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
	list_add_tail(&event->node, &acpi_bus_event_list);
	spin_unlock_irqrestore(&acpi_bus_event_lock, flags);

	wake_up_interruptible(&acpi_bus_event_queue);

	return 0;

}

EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4);

int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data)
{
	if (!device)
		return -EINVAL;
	return acpi_bus_generate_proc_event4(device->pnp.device_class,
					     device->pnp.bus_id, type, data);
}

EXPORT_SYMBOL(acpi_bus_generate_proc_event);

int acpi_bus_receive_event(struct acpi_bus_event *event)
{
	unsigned long flags = 0;
	struct acpi_bus_event *entry = NULL;

	DECLARE_WAITQUEUE(wait, current);


	if (!event)
		return -EINVAL;

	if (list_empty(&acpi_bus_event_list)) {

		set_current_state(TASK_INTERRUPTIBLE);
		add_wait_queue(&acpi_bus_event_queue, &wait);

		if (list_empty(&acpi_bus_event_list))
			schedule();

		remove_wait_queue(&acpi_bus_event_queue, &wait);
		set_current_state(TASK_RUNNING);

		if (signal_pending(current))
			return -ERESTARTSYS;
	}

	spin_lock_irqsave(&acpi_bus_event_lock, flags);
	if (!list_empty(&acpi_bus_event_list)) {
		entry = list_entry(acpi_bus_event_list.next,
				   struct acpi_bus_event, node);
		list_del(&entry->node);
	}
Esempio n. 18
0
/*
========================================================================
Routine Description:
    Close raxx interface.

Arguments:
	*net_dev			the raxx interface pointer

Return Value:
    0					Open OK
	otherwise			Open Fail

Note:
	1. if open fail, kernel will not call the close function.
	2. Free memory for
		(1) Mlme Memory Handler:		MlmeHalt()
		(2) TX & RX:					RTMPFreeTxRxRingMemory()
		(3) BA Reordering: 				ba_reordering_resource_release()
========================================================================
*/
int rt28xx_close(IN PNET_DEV dev)
{
	struct net_device * net_dev = (struct net_device *)dev;
    RTMP_ADAPTER	*pAd = NULL;
	BOOLEAN 		Cancelled;
	UINT32			i = 0;
#ifdef RTMP_MAC_USB
	DECLARE_WAIT_QUEUE_HEAD(unlink_wakeup); 
	DECLARE_WAITQUEUE(wait, current);

	//RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
#endif // RTMP_MAC_USB //

	GET_PAD_FROM_NET_DEV(pAd, net_dev);	

	DBGPRINT(RT_DEBUG_TRACE, ("===> rt28xx_close\n"));

	Cancelled = FALSE;
	// Sanity check for pAd
	if (pAd == NULL)
		return 0; // close ok



#ifdef WDS_SUPPORT
	WdsDown(pAd);
#endif // WDS_SUPPORT //

#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
	{

		// If dirver doesn't wake up firmware here,
		// NICLoadFirmware will hang forever when interface is up again.
		if (OPSTATUS_TEST_FLAG(pAd, fOP_STATUS_DOZE))
        {      
		    AsicForceWakeup(pAd, TRUE);
        }

#ifdef QOS_DLS_SUPPORT
		// send DLS-TEAR_DOWN message, 
		if (pAd->CommonCfg.bDLSCapable)
		{
			UCHAR i;

			// tear down local dls table entry
			for (i=0; i<MAX_NUM_OF_INIT_DLS_ENTRY; i++)
			{
				if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
				{
					RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
					pAd->StaCfg.DLSEntry[i].Status	= DLS_NONE;
					pAd->StaCfg.DLSEntry[i].Valid	= FALSE;
				}
			}

			// tear down peer dls table entry
			for (i=MAX_NUM_OF_INIT_DLS_ENTRY; i<MAX_NUM_OF_DLS_ENTRY; i++)
			{
				if (pAd->StaCfg.DLSEntry[i].Valid && (pAd->StaCfg.DLSEntry[i].Status == DLS_FINISH))
				{
					RTMPSendDLSTearDownFrame(pAd, pAd->StaCfg.DLSEntry[i].MacAddr);
					pAd->StaCfg.DLSEntry[i].Status = DLS_NONE;
					pAd->StaCfg.DLSEntry[i].Valid	= FALSE;
				}
			}
			RTMP_MLME_HANDLER(pAd);
		}
#endif // QOS_DLS_SUPPORT //

		if (INFRA_ON(pAd) &&
			(!RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_NIC_NOT_EXIST)))
		{
			MLME_DISASSOC_REQ_STRUCT	DisReq;
			MLME_QUEUE_ELEM *MsgElem = (MLME_QUEUE_ELEM *) kmalloc(sizeof(MLME_QUEUE_ELEM), MEM_ALLOC_FLAG);
    
			if (MsgElem)
			{
			COPY_MAC_ADDR(DisReq.Addr, pAd->CommonCfg.Bssid);
			DisReq.Reason =  REASON_DEAUTH_STA_LEAVING;

			MsgElem->Machine = ASSOC_STATE_MACHINE;
			MsgElem->MsgType = MT2_MLME_DISASSOC_REQ;
			MsgElem->MsgLen = sizeof(MLME_DISASSOC_REQ_STRUCT);
			NdisMoveMemory(MsgElem->Msg, &DisReq, sizeof(MLME_DISASSOC_REQ_STRUCT));

			// Prevent to connect AP again in STAMlmePeriodicExec
			pAd->MlmeAux.AutoReconnectSsidLen= 32;
			NdisZeroMemory(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen);

			pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_DISASSOC;
			MlmeDisassocReqAction(pAd, MsgElem);
			kfree(MsgElem);
			}
			
			RTMPusecDelay(1000);
		}

#ifdef RTMP_MAC_USB
	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_REMOVE_IN_PROGRESS);
#endif // RTMP_MAC_USB //

		RTMPCancelTimer(&pAd->StaCfg.StaQuickResponeForRateUpTimer, &Cancelled);
		RTMPCancelTimer(&pAd->StaCfg.WpaDisassocAndBlockAssocTimer, &Cancelled);

#ifdef WPA_SUPPLICANT_SUPPORT
#ifndef NATIVE_WPA_SUPPLICANT_SUPPORT
		// send wireless event to wpa_supplicant for infroming interface down.
		RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, RT_INTERFACE_DOWN, NULL, NULL, 0);
#endif // NATIVE_WPA_SUPPLICANT_SUPPORT //
#endif // WPA_SUPPLICANT_SUPPORT //

		MlmeRadioOff(pAd);
	}
#endif // CONFIG_STA_SUPPORT //

	RTMP_SET_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);

	for (i = 0 ; i < NUM_OF_TX_RING; i++)
	{
		while (pAd->DeQueueRunning[i] == TRUE)
		{
			DBGPRINT(RT_DEBUG_TRACE, ("Waiting for TxQueue[%d] done..........\n", i));
			RTMPusecDelay(1000);
		}
	}
	
#ifdef RTMP_MAC_USB
	// ensure there are no more active urbs.
	add_wait_queue (&unlink_wakeup, &wait);
	pAd->wait = &unlink_wakeup;

	// maybe wait for deletions to finish.
	i = 0;
	//while((i < 25) && atomic_read(&pAd->PendingRx) > 0) 
	while(i < 25)
	{
		unsigned long IrqFlags;

		RTMP_IRQ_LOCK(&pAd->BulkInLock, IrqFlags);
		if (pAd->PendingRx == 0)
		{
			RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
			break;
		}
		RTMP_IRQ_UNLOCK(&pAd->BulkInLock, IrqFlags);
		
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
		msleep(UNLINK_TIMEOUT_MS);	//Time in millisecond
#else
		RTMPusecDelay(UNLINK_TIMEOUT_MS*1000);	//Time in microsecond
#endif
		i++;
	}
	pAd->wait = NULL;
	remove_wait_queue (&unlink_wakeup, &wait); 
#endif // RTMP_MAC_USB //


	// Stop Mlme state machine
	MlmeHalt(pAd);
	
	// Close net tasklets
	RtmpNetTaskExit(pAd);


#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
	{
		MacTableReset(pAd);
	}
#endif // CONFIG_STA_SUPPORT //


	MeasureReqTabExit(pAd);
	TpcReqTabExit(pAd);

#ifdef WSC_INCLUDED
#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
		WscStop(pAd,
				&pAd->StaCfg.WscControl);
#endif // CONFIG_STA_SUPPORT //

#ifdef OLD_DH_KEY
#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
		WSC_VFREE_KEY_MEM(pAd->StaCfg.WscControl.pPubKeyMem, pAd->StaCfg.WscControl.pSecKeyMem);
#endif // CONFIG_STA_SUPPORT //
#endif // OLD_DH_KEY //

#ifndef OLD_DH_KEY
	DH_freeall();
#endif // OLD_DH_KEY //

	/* WSC hardware push button function 0811 */
	WSC_HDR_BTN_Stop(pAd);
#endif // WSC_INCLUDED //

	// Close kernel threads
	RtmpMgmtTaskExit(pAd);


	// Free IRQ
	if (RTMP_TEST_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE))
	{
		RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_INTERRUPT_IN_USE);
	}

	// Free Ring or USB buffers
	RTMPFreeTxRxRingMemory(pAd);

	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_HALT_IN_PROGRESS);

#ifdef DOT11_N_SUPPORT
	// Free BA reorder resource
	ba_reordering_resource_release(pAd);
#endif // DOT11_N_SUPPORT //
	
#ifdef CONFIG_STA_SUPPORT
#endif // CONFIG_STA_SUPPORT //

	RTMP_CLEAR_FLAG(pAd, fRTMP_ADAPTER_START_UP);

/*+++Modify by woody to solve the bulk fail+++*/
#ifdef CONFIG_STA_SUPPORT
	IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
	{
#ifdef RT35xx
		if (IS_RT3572(pAd))
		{
			RT30xxWriteRFRegister(pAd, RF_R08, 0x00);
			AsicSendCommandToMcu(pAd, 0x30, 0xff, 0xff, 0x02);
		}
#endif // RT35xx //
	}
#endif // CONFIG_STA_SUPPORT //

	DBGPRINT(RT_DEBUG_TRACE, ("<=== rt28xx_close\n"));
	return 0; // close ok
} /* End of rt28xx_close */