Ejemplo n.º 1
0
/* receives two messages:
 *   0: checkpoint queue (set stop to next packet)
 *   1: dequeue until stop */
static int queue_change(struct Qdisc* sch, struct compatnlattr* opt)
{
    struct queue_sched_data *q = qdisc_priv(sch);
    struct tc_queue_qopt* msg;
    /*
    struct timeval tv;
    */

    if (!opt || compatnllen(opt) < sizeof(*msg))
        return -EINVAL;

    msg = compatnldata(opt);

    if (msg->action == TCQ_CHECKPOINT) {
        /* reset stop */
        q->stop = NULL;
    } else if (msg->action == TCQ_DEQUEUE) {
        /* dequeue */
        sch->flags &= ~TCQ_F_THROTTLED;
#ifdef OLDKERNEL
        netif_schedule(sch->dev);
#else
        netif_schedule_queue(sch->dev_queue);
#endif
        /*
        do_gettimeofday(&tv);
        printk("queue release at %lu.%06lu (%d bytes)\n", tv.tv_sec, tv.tv_usec,
              sch->qstats.backlog);
        */
    } else {
        return -EINVAL;
    }

    return 0;
}
Ejemplo n.º 2
0
static void tbf_watchdog(unsigned long arg)
{
	struct Qdisc *sch = (struct Qdisc*)arg;

	sch->flags &= ~TCQ_F_THROTTLED;
	netif_schedule(sch->dev);
}
Ejemplo n.º 3
0
static void ag71xx_phy_link_adjust(struct net_device *dev)
{
	struct ag71xx *ag = netdev_priv(dev);
	struct phy_device *phydev = ag->phy_dev;
	unsigned long flags;
	int status_change = 0;

	spin_lock_irqsave(&ag->lock, flags);

	if (phydev->link) {
		if (ag->duplex != phydev->duplex
		    || ag->speed != phydev->speed) {
			status_change = 1;
		}
	}

	if (phydev->link != ag->link) {
		if (phydev->link)
			netif_schedule(dev);

		status_change = 1;
	}

	ag->link = phydev->link;
	ag->duplex = phydev->duplex;
	ag->speed = phydev->speed;

	if (status_change)
		ag71xx_phy_link_update(ag);

	spin_unlock_irqrestore(&ag->lock, flags);
}
Ejemplo n.º 4
0
static void netem_watchdog(unsigned long arg)
{
	struct Qdisc *sch = (struct Qdisc *)arg;

	pr_debug("netem_watchdog qlen=%d\n", sch->q.qlen);
	sch->flags &= ~TCQ_F_THROTTLED;
	netif_schedule(sch->dev);
}
Ejemplo n.º 5
0
Archivo: imq.c Proyecto: cilynx/dd-wrt
static int imq_nf_queue(struct sk_buff *skb, struct nf_info *info, unsigned queue_num, void *data)
{
	struct net_device *dev;
	struct net_device_stats *stats;
	struct sk_buff *skb2 = NULL;
	struct Qdisc *q;
	unsigned int index = skb->imq_flags&IMQ_F_IFMASK;
	int ret = -1;

	if (index > numdevs)
		return -1;

	dev = imq_devs + index;
	if (!(dev->flags & IFF_UP)) {
		skb->imq_flags = 0;
		nf_reinject(skb, info, NF_ACCEPT);
		return 0;
	}
	dev->last_rx = jiffies;

	if (skb->destructor) {
		skb2 = skb;
		skb = skb_clone(skb, GFP_ATOMIC);
		if (!skb)
			return -1;
	}
	skb->nf_info = info;

	stats = (struct net_device_stats *)dev->priv;
	stats->rx_bytes+= skb->len;
	stats->rx_packets++;

	spin_lock_bh(&dev->queue_lock);
	q = dev->qdisc;
	if (q->enqueue) {
		q->enqueue(skb_get(skb), q);
		if (skb_shared(skb)) {
			skb->destructor = imq_skb_destructor;
			kfree_skb(skb);
			ret = 0;
		}
	}
	if (spin_is_locked(&dev->_xmit_lock))
		netif_schedule(dev);
	else
		while (!netif_queue_stopped(dev) && qdisc_restart1(dev) < 0)
			/* NOTHING */;

	spin_unlock_bh(&dev->queue_lock);

	if (skb2)
		kfree_skb(ret ? skb : skb2);

	return ret;
}
Ejemplo n.º 6
0
static inline int dev_requeue_skb(struct sk_buff *skb, struct net_device *dev,
				  struct Qdisc *q)
{
	if (unlikely(skb->next))
		dev->gso_skb = skb;
	else
		q->ops->requeue(skb, q);

	netif_schedule(dev);
	return 0;
}
Ejemplo n.º 7
0
/*-----------------------------------------------------------------------------
 *  generic link-change handler - should be sufficient for most cases
 *-----------------------------------------------------------------------------*/
static void generic_adjust_link(struct  net_device *dev)
{
       struct fs_enet_private *fep = netdev_priv(dev);
       struct phy_device *phydev = fep->phydev;
       int new_state = 0;
	
       if (phydev->link) {
		
               /* adjust to duplex mode */
               if (phydev->duplex != fep->oldduplex){
                       new_state = 1;
                       fep->oldduplex = phydev->duplex;
               }

               if (phydev->speed != fep->oldspeed) {
                       new_state = 1;
                       fep->oldspeed = phydev->speed;
               }

               if (!fep->oldlink) {
                       new_state = 1;
                       fep->oldlink = 1;
                       netif_schedule(dev);
                       netif_carrier_on(dev);
                       netif_start_queue(dev);
               }

               if (new_state)
                       fep->ops->restart(dev);

       } else if (fep->oldlink) {
               new_state = 1;
               fep->oldlink = 0;
               fep->oldspeed = 0;
               fep->oldduplex = -1;
               netif_carrier_off(dev);
               netif_stop_queue(dev);
       }

       if (new_state && netif_msg_link(fep))
               phy_print_status(phydev);
}
Ejemplo n.º 8
0
/* Kick device.

   Returns:  0  - queue is empty or throttled.
	    >0  - queue is not empty.

   NOTE: Called under dev->queue_lock with locally disabled BH.
*/
static inline int qdisc_restart(struct net_device *dev)
{
	struct Qdisc *q = dev->qdisc;
	struct sk_buff *skb;

	/* Dequeue packet */
	if (((skb = dev->gso_skb)) || ((skb = q->dequeue(q)))) {
		unsigned nolock = (dev->features & NETIF_F_LLTX);

		dev->gso_skb = NULL;

		/*
		 * When the driver has LLTX set it does its own locking
		 * in start_xmit. No need to add additional overhead by
		 * locking again. These checks are worth it because
		 * even uncongested locks can be quite expensive.
		 * The driver can do trylock like here too, in case
		 * of lock congestion it should return -1 and the packet
		 * will be requeued.
		 */
		if (!nolock) {
			if (!netif_tx_trylock(dev)) {
			collision:
				/* So, someone grabbed the driver. */

				/* It may be transient configuration error,
				   when hard_start_xmit() recurses. We detect
				   it by checking xmit owner and drop the
				   packet when deadloop is detected.
				*/
				if (dev->xmit_lock_owner == smp_processor_id()) {
					kfree_skb(skb);
					if (net_ratelimit())
						printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
					goto out;
				}
				__get_cpu_var(netdev_rx_stat).cpu_collision++;
				goto requeue;
			}
		}

		{
			/* And release queue */
			spin_unlock(&dev->queue_lock);

			if (!netif_queue_stopped(dev)) {
				int ret;

				ret = dev_hard_start_xmit(skb, dev);
				if (ret == NETDEV_TX_OK) {
					if (!nolock) {
						netif_tx_unlock(dev);
					}
					spin_lock(&dev->queue_lock);
					q = dev->qdisc;
					goto out;
				}
				if (ret == NETDEV_TX_LOCKED && nolock) {
					spin_lock(&dev->queue_lock);
					q = dev->qdisc;
					goto collision;
				}
			}

			/* NETDEV_TX_BUSY - we need to requeue */
			/* Release the driver */
			if (!nolock) {
				netif_tx_unlock(dev);
			}
			spin_lock(&dev->queue_lock);
			q = dev->qdisc;
		}

		/* Device kicked us out :(
		   This is possible in three cases:

		   0. driver is locked
		   1. fastroute is enabled
		   2. device cannot determine busy state
		      before start of transmission (f.e. dialout)
		   3. device is buggy (ppp)
		 */

requeue:
		if (unlikely(q == &noop_qdisc))
			kfree_skb(skb);
		else if (skb->next)
			dev->gso_skb = skb;
		else
			q->ops->requeue(skb, q);
		netif_schedule(dev);
	}
	return 0;

out:
	BUG_ON((int) q->q.qlen < 0);
	return q->q.qlen;
}
Ejemplo n.º 9
0
int qdisc_restart(struct net_device *dev)
{
	struct Qdisc *q = dev->qdisc;
	struct sk_buff *skb;

	/* Dequeue packet */
	if ((skb = q->dequeue(q)) != NULL) {
		if (spin_trylock(&dev->xmit_lock)) {
			/* Remember that the driver is grabbed by us. */
			dev->xmit_lock_owner = smp_processor_id();

			/* And release queue */
			spin_unlock(&dev->queue_lock);

			if (!netif_queue_stopped(dev)) {
				if (netdev_nit
#if defined(CONFIG_IMQ) || defined(CONFIG_IMQ_MODULE)
				    && !(skb->imq_flags & IMQ_F_ENQUEUE)
#endif
				    )
					dev_queue_xmit_nit(skb, dev);

				if (dev->hard_start_xmit(skb, dev) == 0) {
					dev->xmit_lock_owner = -1;
					spin_unlock(&dev->xmit_lock);

					spin_lock(&dev->queue_lock);
					return -1;
				}
			}

			/* Release the driver */
			dev->xmit_lock_owner = -1;
			spin_unlock(&dev->xmit_lock);
			spin_lock(&dev->queue_lock);
			q = dev->qdisc;
		} else {
			/* So, someone grabbed the driver. */

			/* It may be transient configuration error,
			   when hard_start_xmit() recurses. We detect
			   it by checking xmit owner and drop the
			   packet when deadloop is detected.
			 */
			if (dev->xmit_lock_owner == smp_processor_id()) {
				kfree_skb(skb);
				if (net_ratelimit())
					printk(KERN_DEBUG "Dead loop on netdevice %s, fix it urgently!\n", dev->name);
				return -1;
			}
			netdev_rx_stat[smp_processor_id()].cpu_collision++;
		}

		/* Device kicked us out :(
		   This is possible in three cases:

		   0. driver is locked
		   1. fastroute is enabled
		   2. device cannot determine busy state
		      before start of transmission (f.e. dialout)
		   3. device is buggy (ppp)
		 */

		q->ops->requeue(skb, q);
		netif_schedule(dev);
		return 1;
	}
	return q->q.qlen;
}
Ejemplo n.º 10
0
static void bfin_mac_adjust_link(struct net_device *dev)
{
	struct bfin_mac_local *lp = netdev_priv(dev);
	struct phy_device *phydev = lp->phydev;
	unsigned long flags;
	int new_state = 0;

	spin_lock_irqsave(&lp->lock, flags);
	if (phydev->link) {
		/* Now we make sure that we can be in full duplex mode.
		 * If not, we operate in half-duplex mode. */
		if (phydev->duplex != lp->old_duplex) {
			u32 opmode = bfin_read_EMAC_OPMODE();
			new_state = 1;

			if (phydev->duplex)
				opmode |= FDMODE;
			else
				opmode &= ~(FDMODE);

			bfin_write_EMAC_OPMODE(opmode);
			lp->old_duplex = phydev->duplex;
		}

		if (phydev->speed != lp->old_speed) {
#if defined(CONFIG_BFIN_MAC_RMII)
			u32 opmode = bfin_read_EMAC_OPMODE();
			switch (phydev->speed) {
			case 10:
				opmode |= RMII_10;
				break;
			case 100:
				opmode &= ~(RMII_10);
				break;
			default:
				printk(KERN_WARNING
					"%s: Ack!  Speed (%d) is not 10/100!\n",
					DRV_NAME, phydev->speed);
				break;
			}
			bfin_write_EMAC_OPMODE(opmode);
#endif

			new_state = 1;
			lp->old_speed = phydev->speed;
		}

		if (!lp->old_link) {
			new_state = 1;
			lp->old_link = 1;
			netif_schedule(dev);
		}
	} else if (lp->old_link) {
		new_state = 1;
		lp->old_link = 0;
		lp->old_speed = 0;
		lp->old_duplex = -1;
	}

	if (new_state) {
		u32 opmode = bfin_read_EMAC_OPMODE();
		phy_print_status(phydev);
		pr_debug("EMAC_OPMODE = 0x%08x\n", opmode);
	}

	spin_unlock_irqrestore(&lp->lock, flags);
}
Ejemplo n.º 11
0
static void
au1000_adjust_link(struct net_device *dev)
{
	struct au1000_private *aup = (struct au1000_private *) dev->priv;
	struct phy_device *phydev = aup->phy_dev;
	unsigned long flags;

	int status_change = 0;

	BUG_ON(!aup->phy_dev);

	spin_lock_irqsave(&aup->lock, flags);

	if (phydev->link && (aup->old_speed != phydev->speed)) {
		// speed changed

		switch(phydev->speed) {
		case SPEED_10:
		case SPEED_100:
			break;
		default:
			printk(KERN_WARNING
			       "%s: Speed (%d) is not 10/100 ???\n",
			       dev->name, phydev->speed);
			break;
		}

		aup->old_speed = phydev->speed;

		status_change = 1;
	}

	if (phydev->link && (aup->old_duplex != phydev->duplex)) {
		// duplex mode changed

		/* switching duplex mode requires to disable rx and tx! */
		hard_stop(dev);

		if (DUPLEX_FULL == phydev->duplex)
			aup->mac->control = ((aup->mac->control
					     | MAC_FULL_DUPLEX)
					     & ~MAC_DISABLE_RX_OWN);
		else
			aup->mac->control = ((aup->mac->control
					      & ~MAC_FULL_DUPLEX)
					     | MAC_DISABLE_RX_OWN);
		au_sync_delay(1);

		enable_rx_tx(dev);
		aup->old_duplex = phydev->duplex;

		status_change = 1;
	}

	if(phydev->link != aup->old_link) {
		// link state changed

		if (phydev->link) // link went up
			netif_schedule(dev);
		else { // link went down
			aup->old_speed = 0;
			aup->old_duplex = -1;
		}

		aup->old_link = phydev->link;
		status_change = 1;
	}

	spin_unlock_irqrestore(&aup->lock, flags);

	if (status_change) {
		if (phydev->link)
			printk(KERN_INFO "%s: link up (%d/%s)\n",
			       dev->name, phydev->speed,
			       DUPLEX_FULL == phydev->duplex ? "Full" : "Half");
		else
			printk(KERN_INFO "%s: link down\n", dev->name);
	}
}