int
uether_rxbuf(struct usb_ether *ue, struct usb_page_cache *pc, 
    unsigned int offset, unsigned int len)
{
	struct ifnet *ifp = ue->ue_ifp;
	struct mbuf *m;

	UE_LOCK_ASSERT(ue, MA_OWNED);

	if (len < ETHER_HDR_LEN || len > MCLBYTES - ETHER_ALIGN)
		return (1);

	m = uether_newbuf();
	if (m == NULL) {
		ifp->if_ierrors++;
		return (ENOMEM);
	}

	usbd_copy_out(pc, offset, mtod(m, uint8_t *), len);

	/* finalize mbuf */
	ifp->if_ipackets++;
	m->m_pkthdr.rcvif = ifp;
	m->m_pkthdr.len = m->m_len = len;

	/* enqueue for later when the lock can be released */
	_IF_ENQUEUE(&ue->ue_rxq, m);
	return (0);
}
static void
ue_queue_command(struct usb_ether *ue,
    usb_proc_callback_t *fn,
    struct usb_proc_msg *t0, struct usb_proc_msg *t1)
{
	struct usb_ether_cfg_task *task;

	UE_LOCK_ASSERT(ue, MA_OWNED);

	if (usb_proc_is_gone(&ue->ue_tq)) {
		return;         /* nothing to do */
	}
	/* 
	 * NOTE: The task cannot get executed before we drop the
	 * "sc_mtx" mutex. It is safe to update fields in the message
	 * structure after that the message got queued.
	 */
	task = (struct usb_ether_cfg_task *)
	  usb_proc_msignal(&ue->ue_tq, t0, t1);

	/* Setup callback and self pointers */
	task->hdr.pm_callback = fn;
	task->ue = ue;

	/*
	 * Start and stop must be synchronous!
	 */
	if ((fn == ue_start_task) || (fn == ue_stop_task))
		usb_proc_mwait(&ue->ue_tq, t0, t1);
}
static void
ue_stop_task(struct usb_proc_msg *_task)
{
	struct usb_ether_cfg_task *task =
	    (struct usb_ether_cfg_task *)_task;
	struct usb_ether *ue = task->ue;

	UE_LOCK_ASSERT(ue, MA_OWNED);

	usb_callout_stop(&ue->ue_watchdog);

	ue->ue_methods->ue_stop(ue);
}
int
uether_rxmbuf(struct usb_ether *ue, struct mbuf *m, 
    unsigned int len)
{
	struct ifnet *ifp = ue->ue_ifp;

	UE_LOCK_ASSERT(ue, MA_OWNED);

	/* finalize mbuf */
	ifp->if_ipackets++;
	m->m_pkthdr.rcvif = ifp;
	m->m_pkthdr.len = m->m_len = len;

	/* enqueue for later when the lock can be released */
	_IF_ENQUEUE(&ue->ue_rxq, m);
	return (0);
}
Exemple #5
0
int
uether_rxmbuf(struct usb_ether *ue, struct mbuf *m, 
    unsigned int len)
{
	struct ifnet *ifp = uether_getifp(ue);

	UE_LOCK_ASSERT(ue);

	/* finalize mbuf */
	IFNET_STAT_INC(ifp, ipackets, 1);
	m->m_pkthdr.rcvif = ifp;
	m->m_pkthdr.len = m->m_len = len;

	/* enqueue for later when the lock can be released */
	IF_ENQUEUE(&ue->ue_rxq, m);
	return (0);
}
static void
ue_start_task(struct usb_proc_msg *_task)
{
	struct usb_ether_cfg_task *task =
	    (struct usb_ether_cfg_task *)_task;
	struct usb_ether *ue = task->ue;
	struct ifnet *ifp = ue->ue_ifp;

	UE_LOCK_ASSERT(ue, MA_OWNED);

	ue->ue_methods->ue_init(ue);

	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
		return;

	if (ue->ue_methods->ue_tick != NULL)
		usb_callout_reset(&ue->ue_watchdog, hz, ue_watchdog, ue);
}
void
uether_rxflush(struct usb_ether *ue)
{
	struct ifnet *ifp = ue->ue_ifp;
	struct mbuf *m;

	UE_LOCK_ASSERT(ue, MA_OWNED);

	for (;;) {
		_IF_DEQUEUE(&ue->ue_rxq, m);
		if (m == NULL)
			break;

		/*
		 * The USB xfer has been resubmitted so its safe to unlock now.
		 */
		UE_UNLOCK(ue);
		ifp->if_input(ifp, m);
		UE_LOCK(ue);
	}
}