示例#1
0
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	int ret;
	int flag = 0;
	unsigned long timeout;

	pr_debug("Starting secondary CPU %d\n", cpu);

	/* Set preset_lpj to avoid subsequent lpj recalculations */
	preset_lpj = loops_per_jiffy;

	if (cpu > 0 && cpu < ARRAY_SIZE(cold_boot_flags))
		flag = cold_boot_flags[cpu];
	else
		__WARN();

	if (per_cpu(cold_boot_done, cpu) == false) {
		ret = scm_set_boot_addr((void *)
					virt_to_phys(msm_secondary_startup),
					flag);
		if (ret == 0)
			release_secondary(cpu);
		else
			printk(KERN_DEBUG "Failed to set secondary core boot "
					  "address\n");
		per_cpu(cold_boot_done, cpu) = true;
	}

	/*
	 * set synchronisation state between this boot processor
	 * and the secondary one
	 */
	spin_lock(&boot_lock);

	/*
	 * The secondary processor is waiting to be released from
	 * the holding pen - release it, then wait for it to flag
	 * that it has been released by resetting pen_release.
	 *
	 * Note that "pen_release" is the hardware CPU ID, whereas
	 * "cpu" is Linux's internal ID.
	 */
	write_pen_release(cpu_logical_map(cpu));

	/*
	 * Send the secondary CPU a soft interrupt, thereby causing
	 * the boot monitor to read the system wide flags register,
	 * and branch to the address found there.
	 */
	gic_raise_softirq(cpumask_of(cpu), 1);

	timeout = jiffies + (1 * HZ);
	while (time_before(jiffies, timeout)) {
		smp_rmb();
		if (pen_release == -1)
			break;

		udelay(10);
	}

	/*
	 * now the secondary core is starting up let it run its
	 * calibrations, then wait for it to finish
	 */
	spin_unlock(&boot_lock);

	return pen_release != -1 ? -ENOSYS : 0;
}
示例#2
0
static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr)
{
	int len;
	int dlen;
	int icount = 0;
	struct net_device *dev;
	elp_device *adapter;
	int timeout;

	dev = dev_id;
	adapter = (elp_device *) dev->priv;
	
	spin_lock(&adapter->lock);

	do {
		/*
		 * has a DMA transfer finished?
		 */
		if (inb_status(dev->base_addr) & DONE) {
			if (!adapter->dmaing) {
				printk("%s: phantom DMA completed\n", dev->name);
			}
			if (elp_debug >= 3) {
				printk("%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));
			}

			outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR), dev);
			if (adapter->current_dma.direction) {
				dev_kfree_skb_irq(adapter->current_dma.skb);
			} else {
				struct sk_buff *skb = adapter->current_dma.skb;
				if (skb) {
					if (adapter->current_dma.target) {
				  	/* have already done the skb_put() */
				  	memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);
					}
					skb->protocol = eth_type_trans(skb,dev);
					adapter->stats.rx_bytes += skb->len;
					netif_rx(skb);
					dev->last_rx = jiffies;
				}
			}
			adapter->dmaing = 0;
			if (adapter->rx_backlog.in != adapter->rx_backlog.out) {
				int t = adapter->rx_backlog.length[adapter->rx_backlog.out];
				adapter->rx_backlog.out = backlog_next(adapter->rx_backlog.out);
				if (elp_debug >= 2)
					printk("%s: receiving backlogged packet (%d)\n", dev->name, t);
				receive_packet(dev, t);
			} else {
				adapter->busy = 0;
			}
		} else {
			/* has one timed out? */
			check_3c505_dma(dev);
		}

		/*
		 * receive a PCB from the adapter
		 */
		timeout = jiffies + 3*HZ/100;
		while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) {
			if (receive_pcb(dev, &adapter->irx_pcb)) {
				switch (adapter->irx_pcb.command) 
				{
				case 0:
					break;
					/*
					 * received a packet - this must be handled fast
					 */
				case 0xff:
				case CMD_RECEIVE_PACKET_COMPLETE:
					/* if the device isn't open, don't pass packets up the stack */
					if (!netif_running(dev))
						break;
					len = adapter->irx_pcb.data.rcv_resp.pkt_len;
					dlen = adapter->irx_pcb.data.rcv_resp.buf_len;
					if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {
						printk(KERN_ERR "%s: interrupt - packet not received correctly\n", dev->name);
					} else {
						if (elp_debug >= 3) {
							printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);
						}
						if (adapter->irx_pcb.command == 0xff) {
							if (elp_debug >= 2)
								printk("%s: adding packet to backlog (len = %d)\n", dev->name, dlen);
							adapter->rx_backlog.length[adapter->rx_backlog.in] = dlen;
							adapter->rx_backlog.in = backlog_next(adapter->rx_backlog.in);
						} else {
							receive_packet(dev, dlen);
						}
						if (elp_debug >= 3)
							printk("%s: packet received\n", dev->name);
					}
					break;

					/*
					 * 82586 configured correctly
					 */
				case CMD_CONFIGURE_82586_RESPONSE:
					adapter->got[CMD_CONFIGURE_82586] = 1;
					if (elp_debug >= 3)
						printk("%s: interrupt - configure response received\n", dev->name);
					break;

					/*
					 * Adapter memory configuration
					 */
				case CMD_CONFIGURE_ADAPTER_RESPONSE:
					adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1;
					if (elp_debug >= 3)
						printk("%s: Adapter memory configuration %s.\n", dev->name,
						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
					break;

					/*
					 * Multicast list loading
					 */
				case CMD_LOAD_MULTICAST_RESPONSE:
					adapter->got[CMD_LOAD_MULTICAST_LIST] = 1;
					if (elp_debug >= 3)
						printk("%s: Multicast address list loading %s.\n", dev->name,
						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
					break;

					/*
					 * Station address setting
					 */
				case CMD_SET_ADDRESS_RESPONSE:
					adapter->got[CMD_SET_STATION_ADDRESS] = 1;
					if (elp_debug >= 3)
						printk("%s: Ethernet address setting %s.\n", dev->name,
						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");
					break;


					/*
					 * received board statistics
					 */
				case CMD_NETWORK_STATISTICS_RESPONSE:
					adapter->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv;
					adapter->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit;
					adapter->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC;
					adapter->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align;
					adapter->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun;
					adapter->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res;
					adapter->got[CMD_NETWORK_STATISTICS] = 1;
					if (elp_debug >= 3)
						printk("%s: interrupt - statistics response received\n", dev->name);
					break;

					/*
					 * sent a packet
					 */
				case CMD_TRANSMIT_PACKET_COMPLETE:
					if (elp_debug >= 3)
						printk("%s: interrupt - packet sent\n", dev->name);
					if (!netif_running(dev))
						break;
					switch (adapter->irx_pcb.data.xmit_resp.c_stat) {
					case 0xffff:
						adapter->stats.tx_aborted_errors++;
						printk(KERN_INFO "%s: transmit timed out, network cable problem?\n", dev->name);
						break;
					case 0xfffe:
						adapter->stats.tx_fifo_errors++;
						printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name);
						break;
					}
					netif_wake_queue(dev);
					break;

					/*
					 * some unknown PCB
					 */
				default:
					printk(KERN_DEBUG "%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command);
					break;
				}
			} else {
				printk("%s: failed to read PCB on interrupt\n", dev->name);
				adapter_reset(dev);
			}
		}

	} while (icount++ < 5 && (inb_status(dev->base_addr) & (ACRF | DONE)));

	prime_rx(dev);

	/*
	 * indicate no longer in interrupt routine
	 */
	spin_unlock(&adapter->lock);
}
示例#3
0
/*
 * alua_rtpg - Evaluate REPORT TARGET GROUP STATES
 * @sdev: the device to be evaluated.
 *
 * Evaluate the Target Port Group State.
 * Returns SCSI_DH_DEV_OFFLINED if the path is
 * found to be unusable.
 */
static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
{
    struct scsi_sense_hdr sense_hdr;
    int len, k, off, valid_states = 0;
    unsigned char *ucp;
    unsigned err;
    unsigned long expiry, interval = 1000;

    expiry = round_jiffies_up(jiffies + ALUA_FAILOVER_TIMEOUT);
retry:
    err = submit_rtpg(sdev, h);

    if (err == SCSI_DH_IO && h->senselen > 0) {
        err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
                                   &sense_hdr);
        if (!err)
            return SCSI_DH_IO;

        err = alua_check_sense(sdev, &sense_hdr);
        if (err == ADD_TO_MLQUEUE && time_before(jiffies, expiry))
            goto retry;
        sdev_printk(KERN_INFO, sdev,
                    "%s: rtpg sense code %02x/%02x/%02x\n",
                    ALUA_DH_NAME, sense_hdr.sense_key,
                    sense_hdr.asc, sense_hdr.ascq);
        err = SCSI_DH_IO;
    }
    if (err != SCSI_DH_OK)
        return err;

    len = (h->buff[0] << 24) + (h->buff[1] << 16) +
          (h->buff[2] << 8) + h->buff[3] + 4;

    if (len > h->bufflen) {
        /* Resubmit with the correct length */
        if (realloc_buffer(h, len)) {
            sdev_printk(KERN_WARNING, sdev,
                        "%s: kmalloc buffer failed\n",__func__);
            /* Temporary failure, bypass */
            return SCSI_DH_DEV_TEMP_BUSY;
        }
        goto retry;
    }

    for (k = 4, ucp = h->buff + 4; k < len; k += off, ucp += off) {
        if (h->group_id == (ucp[2] << 8) + ucp[3]) {
            h->state = ucp[0] & 0x0f;
            valid_states = ucp[1];
        }
        off = 8 + (ucp[7] * 4);
    }

    sdev_printk(KERN_INFO, sdev,
                "%s: port group %02x state %c supports %c%c%c%c%c%c%c\n",
                ALUA_DH_NAME, h->group_id, print_alua_state(h->state),
                valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
                valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
                valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
                valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
                valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
                valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
                valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');

    switch (h->state) {
    case TPGS_STATE_TRANSITIONING:
        if (time_before(jiffies, expiry)) {
            /* State transition, retry */
            interval *= 2;
            msleep(interval);
            goto retry;
        }
        /* Transitioning time exceeded, set port to standby */
        err = SCSI_DH_RETRY;
        h->state = TPGS_STATE_STANDBY;
        break;
    case TPGS_STATE_OFFLINE:
    case TPGS_STATE_UNAVAILABLE:
        /* Path unusable for unavailable/offline */
        err = SCSI_DH_DEV_OFFLINED;
        break;
    default:
        /* Useable path if active */
        err = SCSI_DH_OK;
        break;
    }
    return err;
}
示例#4
0
static int __init elp_sense(struct net_device *dev)
{
	int timeout;
	int addr = dev->base_addr;
	const char *name = dev->name;
	unsigned long flags;
	byte orig_HSR;

	if (!request_region(addr, ELP_IO_EXTENT, "3c505"))
		return -ENODEV;

	orig_HSR = inb_status(addr);

	if (elp_debug > 0)
		printk(search_msg, name, addr);

	if (orig_HSR == 0xff) {
		if (elp_debug > 0)
			printk(notfound_msg, 1);
		goto out;
	}
	/* Enable interrupts - we need timers! */
	save_flags(flags);
	sti();

	/* Wait for a while; the adapter may still be booting up */
	if (elp_debug > 0)
		printk(stilllooking_msg);

	if (orig_HSR & DIR) {
		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
		outb(0, dev->base_addr + PORT_CONTROL);
		timeout = jiffies + 30*HZ/100;
		while (time_before(jiffies, timeout));
		restore_flags(flags);
		if (inb_status(addr) & DIR) {
			if (elp_debug > 0)
				printk(notfound_msg, 2);
			goto out;
		}
	} else {
		/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */
		outb(DIR, dev->base_addr + PORT_CONTROL);
		timeout = jiffies + 30*HZ/100;
		while (time_before(jiffies, timeout));
		restore_flags(flags);
		if (!(inb_status(addr) & DIR)) {
			if (elp_debug > 0)
				printk(notfound_msg, 3);
			goto out;
		}
	}
	/*
	 * It certainly looks like a 3c505.
	 */
	if (elp_debug > 0)
		printk(found_msg);

	return 0;
out:
	release_region(addr, ELP_IO_EXTENT);
	return -ENODEV;
}
示例#5
0
static int send_pcb(struct net_device *dev, pcb_struct * pcb)
{
	int i;
	int timeout;
	elp_device *adapter = dev->priv;

	check_3c505_dma(dev);

	if (adapter->dmaing && adapter->current_dma.direction == 0)
		return FALSE;

	/* Avoid contention */
	if (test_and_set_bit(1, &adapter->send_pcb_semaphore)) {
		if (elp_debug >= 3) {
			printk("%s: send_pcb entered while threaded\n", dev->name);
		}
		return FALSE;
	}
	/*
	 * load each byte into the command register and
	 * wait for the HCRE bit to indicate the adapter
	 * had read the byte
	 */
	set_hsf(dev, 0);

	if (send_pcb_slow(dev->base_addr, pcb->command))
		goto abort;

	cli();

	if (send_pcb_fast(dev->base_addr, pcb->length))
		goto sti_abort;

	for (i = 0; i < pcb->length; i++) {
		if (send_pcb_fast(dev->base_addr, pcb->data.raw[i]))
			goto sti_abort;
	}

	outb_control(adapter->hcr_val | 3, dev);	/* signal end of PCB */
	outb_command(2 + pcb->length, dev->base_addr);

	/* now wait for the acknowledgement */
	sti();

	for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {
		switch (GET_ASF(dev->base_addr)) {
		case ASF_PCB_ACK:
			adapter->send_pcb_semaphore = 0;
			return TRUE;
			break;
		case ASF_PCB_NAK:
#ifdef ELP_DEBUG
			printk(KERN_DEBUG "%s: send_pcb got NAK\n", dev->name);
#endif
			goto abort;
			break;
		}
	}

	if (elp_debug >= 1)
		printk("%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr));

      sti_abort:
	sti();
      abort:
	adapter->send_pcb_semaphore = 0;
	return FALSE;
}
int xhci_bus_resume(struct usb_hcd *hcd)
{
	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
	int max_ports, port_index;
	__le32 __iomem **port_array;
	struct xhci_bus_state *bus_state;
	u32 temp;
	unsigned long flags;

	max_ports = xhci_get_ports(hcd, &port_array);
	bus_state = &xhci->bus_state[hcd_index(hcd)];

	if (time_before(jiffies, bus_state->next_statechange))
		msleep(5);

	spin_lock_irqsave(&xhci->lock, flags);
	if (!HCD_HW_ACCESSIBLE(hcd)) {
		spin_unlock_irqrestore(&xhci->lock, flags);
		return -ESHUTDOWN;
	}

	/* delay the irqs */
	temp = xhci_readl(xhci, &xhci->op_regs->command);
	temp &= ~CMD_EIE;
	xhci_writel(xhci, temp, &xhci->op_regs->command);

	port_index = max_ports;
	while (port_index--) {
		/* Check whether need resume ports. If needed
		   resume port and disable remote wakeup */
		u32 temp;
		int slot_id;

		temp = xhci_readl(xhci, port_array[port_index]);
		if (DEV_SUPERSPEED(temp))
			temp &= ~(PORT_RWC_BITS | PORT_CEC | PORT_WAKE_BITS);
		else
			temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
		if (test_bit(port_index, &bus_state->bus_suspended) &&
		    (temp & PORT_PLS_MASK)) {
			if (DEV_SUPERSPEED(temp)) {
				xhci_set_link_state(xhci, port_array,
							port_index, XDEV_U0);
			} else {
				xhci_set_link_state(xhci, port_array,
						port_index, XDEV_RESUME);

				spin_unlock_irqrestore(&xhci->lock, flags);
				msleep(20);
				spin_lock_irqsave(&xhci->lock, flags);

				xhci_set_link_state(xhci, port_array,
							port_index, XDEV_U0);
			}
			/* wait for the port to enter U0 and report port link
			 * state change.
			 */
			spin_unlock_irqrestore(&xhci->lock, flags);
			msleep(20);
			spin_lock_irqsave(&xhci->lock, flags);

			/* Clear PLC */
			xhci_test_and_clear_bit(xhci, port_array, port_index,
						PORT_PLC);

			slot_id = xhci_find_slot_id_by_port(hcd,
					xhci, port_index + 1);
			if (slot_id)
				xhci_ring_device(xhci, slot_id);
		} else {
			xhci_writel(xhci, temp, port_array[port_index]);
			if (xhci->quirks & XHCI_PORTSC_DELAY)
				ndelay(100);
		}

		if (hcd->speed != HCD_USB3) {
			if (xhci->quirks & XHCI_PORTSC_DELAY)
				ndelay(100);
		}
	}

	(void) xhci_readl(xhci, &xhci->op_regs->command);

	bus_state->next_statechange = jiffies + msecs_to_jiffies(5);
	/* re-enable irqs */
	temp = xhci_readl(xhci, &xhci->op_regs->command);
	temp |= CMD_EIE;
	xhci_writel(xhci, temp, &xhci->op_regs->command);
	temp = xhci_readl(xhci, &xhci->op_regs->command);

	spin_unlock_irqrestore(&xhci->lock, flags);
	return 0;
}
示例#7
0
static void ipgre_err(struct sk_buff *skb, u32 info)
{

/* All the routers (except for Linux) return only
   8 bytes of packet payload. It means, that precise relaying of
   ICMP in the real Internet is absolutely infeasible.

   Moreover, Cisco "wise men" put GRE key to the third word
   in GRE header. It makes impossible maintaining even soft state for keyed
   GRE tunnels with enabled checksum. Tell them "thank you".

   Well, I wonder, rfc1812 was written by Cisco employee,
   what the hell these idiots break standrads established
   by themself???
 */

	struct iphdr *iph = (struct iphdr *)skb->data;
	__be16	     *p = (__be16*)(skb->data+(iph->ihl<<2));
	int grehlen = (iph->ihl<<2) + 4;
	const int type = icmp_hdr(skb)->type;
	const int code = icmp_hdr(skb)->code;
	struct ip_tunnel *t;
	__be16 flags;

	flags = p[0];
	if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) {
		if (flags&(GRE_VERSION|GRE_ROUTING))
			return;
		if (flags&GRE_KEY) {
			grehlen += 4;
			if (flags&GRE_CSUM)
				grehlen += 4;
		}
	}

	/* If only 8 bytes returned, keyed message will be dropped here */
	if (skb_headlen(skb) < grehlen)
		return;

	switch (type) {
	default:
	case ICMP_PARAMETERPROB:
		return;

	case ICMP_DEST_UNREACH:
		switch (code) {
		case ICMP_SR_FAILED:
		case ICMP_PORT_UNREACH:
			/* Impossible event. */
			return;
		case ICMP_FRAG_NEEDED:
			/* Soft state for pmtu is maintained by IP core. */
			return;
		default:
			/* All others are translated to HOST_UNREACH.
			   rfc2003 contains "deep thoughts" about NET_UNREACH,
			   I believe they are just ether pollution. --ANK
			 */
			break;
		}
		break;
	case ICMP_TIME_EXCEEDED:
		if (code != ICMP_EXC_TTL)
			return;
		break;
	}

	read_lock(&ipgre_lock);
	t = ipgre_tunnel_lookup(skb->dev, iph->daddr, iph->saddr,
				flags & GRE_KEY ?
				*(((__be32 *)p) + (grehlen / 4) - 1) : 0,
				p[1]);
	if (t == NULL || t->parms.iph.daddr == 0 ||
	    ipv4_is_multicast(t->parms.iph.daddr))
		goto out;

	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
		goto out;

	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
		t->err_count++;
	else
		t->err_count = 1;
	t->err_time = jiffies;
out:
	read_unlock(&ipgre_lock);
	return;
}
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	unsigned long timeout;

	/*
                                                         
                         
  */
	spin_lock(&boot_lock);

	/*
                                                          
                                                          
                                                       
   
                                                           
                                 
  */
	write_pen_release(cpu_logical_map(cpu));

	if (!(__raw_readl(S5P_ARM_CORE1_STATUS) & S5P_CORE_LOCAL_PWR_EN)) {
		__raw_writel(S5P_CORE_LOCAL_PWR_EN,
			     S5P_ARM_CORE1_CONFIGURATION);

		timeout = 10;

		/*                                 */
		while ((__raw_readl(S5P_ARM_CORE1_STATUS)
			& S5P_CORE_LOCAL_PWR_EN) != S5P_CORE_LOCAL_PWR_EN) {
			if (timeout-- == 0)
				break;

			mdelay(1);
		}

		if (timeout == 0) {
			printk(KERN_ERR "cpu1 power enable failed");
			spin_unlock(&boot_lock);
			return -ETIMEDOUT;
		}
	}
	/*
                                                            
                                                            
                                          
  */

	timeout = jiffies + (1 * HZ);
	while (time_before(jiffies, timeout)) {
		smp_rmb();

		__raw_writel(virt_to_phys(exynos4_secondary_startup),
			CPU1_BOOT_REG);
		gic_raise_softirq(cpumask_of(cpu), 1);

		if (pen_release == -1)
			break;

		udelay(10);
	}

	/*
                                                        
                                            
  */
	spin_unlock(&boot_lock);

	return pen_release != -1 ? -ENOSYS : 0;
}
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
		    const struct iphdr *tnl_params)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
	const struct iphdr *inner_iph;
	struct iphdr *iph;
	struct flowi4 fl4;
	u8     tos, ttl;
	__be16 df;
	struct rtable *rt;		/* Route to the other host */
	struct net_device *tdev;	/* Device to other host */
	unsigned int max_headroom;	/* The extra header space needed */
	__be32 dst;

	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);

	memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
	dst = tnl_params->daddr;
	if (dst == 0) {
		/* NBMA tunnel */

		if (skb_dst(skb) == NULL) {
			dev->stats.tx_fifo_errors++;
			goto tx_error;
		}

		if (skb->protocol == htons(ETH_P_IP)) {
			rt = skb_rtable(skb);
			dst = rt_nexthop(rt, inner_iph->daddr);
		}
#if IS_ENABLED(CONFIG_IPV6)
		else if (skb->protocol == htons(ETH_P_IPV6)) {
			const struct in6_addr *addr6;
			struct neighbour *neigh;
			bool do_tx_error_icmp;
			int addr_type;

			neigh = dst_neigh_lookup(skb_dst(skb),
						 &ipv6_hdr(skb)->daddr);
			if (neigh == NULL)
				goto tx_error;

			addr6 = (const struct in6_addr *)&neigh->primary_key;
			addr_type = ipv6_addr_type(addr6);

			if (addr_type == IPV6_ADDR_ANY) {
				addr6 = &ipv6_hdr(skb)->daddr;
				addr_type = ipv6_addr_type(addr6);
			}

			if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
				do_tx_error_icmp = true;
			else {
				do_tx_error_icmp = false;
				dst = addr6->s6_addr32[3];
			}
			neigh_release(neigh);
			if (do_tx_error_icmp)
				goto tx_error_icmp;
		}
#endif
		else
			goto tx_error;
	}

	tos = tnl_params->tos;
	if (tos & 0x1) {
		tos &= ~0x1;
		if (skb->protocol == htons(ETH_P_IP))
			tos = inner_iph->tos;
		else if (skb->protocol == htons(ETH_P_IPV6))
			tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
	}

	rt = ip_route_output_tunnel(dev_net(dev), &fl4,
				    tunnel->parms.iph.protocol,
				    dst, tnl_params->saddr,
				    tunnel->parms.o_key,
				    RT_TOS(tos),
				    tunnel->parms.link);
	if (IS_ERR(rt)) {
		dev->stats.tx_carrier_errors++;
		goto tx_error;
	}
	tdev = rt->dst.dev;

	if (tdev == dev) {
		ip_rt_put(rt);
		dev->stats.collisions++;
		goto tx_error;
	}


	if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off)) {
		ip_rt_put(rt);
		goto tx_error;
	}

	if (tunnel->err_count > 0) {
		if (time_before(jiffies,
				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
			tunnel->err_count--;

			memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
			dst_link_failure(skb);
		} else
			tunnel->err_count = 0;
	}

	ttl = tnl_params->ttl;
	if (ttl == 0) {
		if (skb->protocol == htons(ETH_P_IP))
			ttl = inner_iph->ttl;
#if IS_ENABLED(CONFIG_IPV6)
		else if (skb->protocol == htons(ETH_P_IPV6))
			ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
#endif
		else
			ttl = ip4_dst_hoplimit(&rt->dst);
	}

	df = tnl_params->frag_off;
	if (skb->protocol == htons(ETH_P_IP))
		df |= (inner_iph->frag_off&htons(IP_DF));

	max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr)
					       + rt->dst.header_len;
	if (max_headroom > dev->needed_headroom)
		dev->needed_headroom = max_headroom;

	if (skb_cow_head(skb, dev->needed_headroom)) {
		dev->stats.tx_dropped++;
		dev_kfree_skb(skb);
		return;
	}

	skb_dst_drop(skb);
	skb_dst_set(skb, &rt->dst);

	/* Push down and install the IP header. */
	skb_push(skb, sizeof(struct iphdr));
	skb_reset_network_header(skb);

	iph = ip_hdr(skb);
	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);

	iph->version	=	4;
	iph->ihl	=	sizeof(struct iphdr) >> 2;
	iph->frag_off	=	df;
	iph->protocol	=	tnl_params->protocol;
	iph->tos	=	ip_tunnel_ecn_encap(tos, inner_iph, skb);
	iph->daddr	=	fl4.daddr;
	iph->saddr	=	fl4.saddr;
	iph->ttl	=	ttl;
	__ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1);

	iptunnel_xmit(skb, dev);
	return;

#if IS_ENABLED(CONFIG_IPV6)
tx_error_icmp:
	dst_link_failure(skb);
#endif
tx_error:
	dev->stats.tx_errors++;
	dev_kfree_skb(skb);
}
示例#10
0
int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
{
	unsigned long timeout;
	int ret;

	/*
	 * Set synchronisation state between this boot processor
	 * and the secondary one
	 */
	spin_lock(&boot_lock);

	watchdog_save();

	ret = exynos_power_up_cpu(cpu);
	if (ret) {
		spin_unlock(&boot_lock);
		return ret;
	}

	/*
	 * The secondary processor is waiting to be released from
	 * the holding pen - release it, then wait for it to flag
	 * that it has been released by resetting pen_release.
	 *
	 * Note that "pen_release" is the hardware CPU ID, whereas
	 * "cpu" is Linux's internal ID.
	 */
	write_pen_release(cpu_logical_map(cpu));

	/*
	 * Send the secondary CPU a soft interrupt, thereby causing
	 * the boot monitor to read the system wide flags register,
	 * and branch to the address found there.
	 */

	timeout = jiffies + (1 * HZ);
	while (time_before(jiffies, timeout)) {
		smp_rmb();

#ifdef CONFIG_ARM_TRUSTZONE
		if (soc_is_exynos4210() || soc_is_exynos4212() ||
			soc_is_exynos5250())
			exynos_smc(SMC_CMD_CPU1BOOT, 0, 0, 0);
		else if (soc_is_exynos4412())
			exynos_smc(SMC_CMD_CPU1BOOT, cpu, 0, 0);
#endif
		__raw_writel(virt_to_phys(exynos4_secondary_startup),
			cpu_boot_info[cpu].boot_base);

		watchdog_restore();

		if (soc_is_exynos5410())
			dsb_sev();
		else
			arm_send_ping_ipi(cpu);

		if (pen_release == -1)
			break;

		udelay(10);
	}

	/*
	 * now the secondary core is starting up let it run its
	 * calibrations, then wait for it to finish
	 */
	spin_unlock(&boot_lock);

	return pen_release != -1 ? -ENOSYS : 0;
}
示例#11
0
int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
{
	struct ivtv *itv = s->itv;
	DECLARE_WAITQUEUE(wait, current);
	int cap_type;
	int stopmode;

	if (s->v4l2dev == NULL)
		return -EINVAL;

	/* This function assumes that you are allowed to stop the capture
	   and that we are actually capturing */

	IVTV_DEBUG_INFO("Stop Capture\n");

	if (s->type == IVTV_DEC_STREAM_TYPE_VOUT)
		return 0;
	if (atomic_read(&itv->capturing) == 0)
		return 0;

	switch (s->type) {
	case IVTV_ENC_STREAM_TYPE_YUV:
		cap_type = 1;
		break;
	case IVTV_ENC_STREAM_TYPE_PCM:
		cap_type = 1;
		break;
	case IVTV_ENC_STREAM_TYPE_VBI:
		cap_type = 1;
		break;
	case IVTV_ENC_STREAM_TYPE_MPG:
	default:
		cap_type = 0;
		break;
	}

	/* Stop Capture Mode */
	if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
		stopmode = 0;
	} else {
		stopmode = 1;
	}

	/* end_capture */
	/* when: 0 =  end of GOP  1 = NOW!, type: 0 = mpeg, subtype: 3 = video+audio */
	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);

	if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
		if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
			/* only run these if we're shutting down the last cap */
			unsigned long duration;
			unsigned long then = jiffies;

			add_wait_queue(&itv->eos_waitq, &wait);

			set_current_state(TASK_INTERRUPTIBLE);

			/* wait 2s for EOS interrupt */
			while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
				time_before(jiffies,
					    then + msecs_to_jiffies(2000))) {
				schedule_timeout(msecs_to_jiffies(10));
			}

			/* To convert jiffies to ms, we must multiply by 1000
			 * and divide by HZ.  To avoid runtime division, we
			 * convert this to multiplication by 1000/HZ.
			 * Since integer division truncates, we get the best
			 * accuracy if we do a rounding calculation of the constant.
			 * Think of the case where HZ is 1024.
			 */
			duration = ((1000 + HZ / 2) / HZ) * (jiffies - then);

			if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) {
				IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name);
				IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration);
			} else {
				IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
			}
			set_current_state(TASK_RUNNING);
			remove_wait_queue(&itv->eos_waitq, &wait);
			set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
		}

		/* Handle any pending interrupts */
		ivtv_msleep_timeout(100, 1);
	}

	atomic_dec(&itv->capturing);

	/* Clear capture and no-read bits */
	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);

	if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);

	if (atomic_read(&itv->capturing) > 0) {
		return 0;
	}

	/* Set the following Interrupt mask bits for capture */
	ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
	del_timer(&itv->dma_timer);

	/* event notification (off) */
	if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
		/* type: 0 = refresh */
		/* on/off: 0 = off, intr: 0x10000000, mbox_id: -1: none */
		ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
	}

	wake_up(&s->waitq);

	return 0;
}
示例#12
0
static int gk20a_ltc_cbc_ctrl(struct gk20a *g, enum gk20a_cbc_op op,
			      u32 min, u32 max)
{
	int err = 0;
	struct gr_gk20a *gr = &g->gr;
	u32 fbp, slice, ctrl1, val, hw_op = 0;
	unsigned long end_jiffies = jiffies +
		msecs_to_jiffies(gk20a_get_gr_idle_timeout(g));
	u32 delay = GR_IDLE_CHECK_DEFAULT;
	u32 slices_per_fbp =
		ltc_ltcs_ltss_cbc_param_slices_per_fbp_v(
			gk20a_readl(g, ltc_ltcs_ltss_cbc_param_r()));

	gk20a_dbg_fn("");

	if (gr->compbit_store.size == 0)
		return 0;

	mutex_lock(&g->mm.l2_op_lock);

	if (op == gk20a_cbc_op_clear) {
		gk20a_writel(g, ltc_ltcs_ltss_cbc_ctrl2_r(),
			     ltc_ltcs_ltss_cbc_ctrl2_clear_lower_bound_f(min));
		gk20a_writel(g, ltc_ltcs_ltss_cbc_ctrl3_r(),
			     ltc_ltcs_ltss_cbc_ctrl3_clear_upper_bound_f(max));
		hw_op = ltc_ltcs_ltss_cbc_ctrl1_clear_active_f();
	} else if (op == gk20a_cbc_op_clean) {
		hw_op = ltc_ltcs_ltss_cbc_ctrl1_clean_active_f();
	} else if (op == gk20a_cbc_op_invalidate) {
		hw_op = ltc_ltcs_ltss_cbc_ctrl1_invalidate_active_f();
	} else {
		BUG_ON(1);
	}

	gk20a_writel(g, ltc_ltcs_ltss_cbc_ctrl1_r(),
		     gk20a_readl(g, ltc_ltcs_ltss_cbc_ctrl1_r()) | hw_op);

	for (fbp = 0; fbp < gr->num_fbps; fbp++) {
		for (slice = 0; slice < slices_per_fbp; slice++) {

			delay = GR_IDLE_CHECK_DEFAULT;

			ctrl1 = ltc_ltc0_lts0_cbc_ctrl1_r() +
				fbp * proj_ltc_stride_v() +
				slice * proj_lts_stride_v();

			do {
				val = gk20a_readl(g, ctrl1);
				if (!(val & hw_op))
					break;

				usleep_range(delay, delay * 2);
				delay = min_t(u32, delay << 1,
					GR_IDLE_CHECK_MAX);

			} while (time_before(jiffies, end_jiffies) ||
					!tegra_platform_is_silicon());

			if (!time_before(jiffies, end_jiffies)) {
				gk20a_err(dev_from_gk20a(g),
					   "comp tag clear timeout\n");
				err = -EBUSY;
				goto out;
			}
		}
	}
out:
	mutex_unlock(&g->mm.l2_op_lock);
	return 0;
}
示例#13
0
static void __exit rin_exit(void)
{
	int i;
	struct net_device *dev;
	struct rin_st *sl;
	unsigned long timeout = jiffies + HZ;
	int busy = 0;

	if (rin_devs == NULL)
		return;

	/* First of all: check for active disciplines and hangup them.
	 */
	do {
		if (busy)
			msleep_interruptible(100);

		busy = 0;
		for (i = 0; i < rin_maxdev; i++) {
			dev = rin_devs[i];
			if (!dev)
				continue;
			sl = netdev_priv(dev);
			spin_lock_bh(&sl->lock);
			if (sl->tty) {
				busy++;
				tty_hangup(sl->tty);
			}
			spin_unlock_bh(&sl->lock);
		}
	} while (busy && time_before(jiffies, timeout));


	for (i = 0; i < rin_maxdev; i++) {
		dev = rin_devs[i];
		if (!dev)
			continue;
		rin_devs[i] = NULL;

		sl = netdev_priv(dev);
		if (sl->tty) {
			printk(KERN_ERR "%s: tty discipline still running\n",
			       dev->name);
			/* Intentionally leak the control block. */
			dev->destructor = NULL;
		}

		unregister_netdev(dev);
	}

	kfree(rin_devs);
	rin_devs = NULL;

	i = tty_unregister_ldisc(N_RIN);
	if (i != 0) {
		printk(KERN_ERR "RIN: can't unregister line discipline (err = %d)\n", i);
}
	if (rin_tx_wq)	{
               	flush_workqueue(rin_tx_wq);
		destroy_workqueue(rin_tx_wq);
		rin_tx_wq = NULL;
	}
}
示例#14
0
u64 ipath_snap_cntr(struct ipath_devdata *dd, ipath_creg creg)
{
	u32 val, reg64 = 0;
	u64 val64;
	unsigned long t0, t1;
	u64 ret;

	t0 = jiffies;
	/* If fast increment counters are only 32 bits, snapshot them,
	 * and maintain them as 64bit values in the driver */
	if (!(dd->ipath_flags & IPATH_32BITCOUNTERS) &&
	    (creg == dd->ipath_cregs->cr_wordsendcnt ||
	     creg == dd->ipath_cregs->cr_wordrcvcnt ||
	     creg == dd->ipath_cregs->cr_pktsendcnt ||
	     creg == dd->ipath_cregs->cr_pktrcvcnt)) {
		val64 = ipath_read_creg(dd, creg);
		val = val64 == ~0ULL ? ~0U : 0;
		reg64 = 1;
	} else			/* val64 just to keep gcc quiet... */
		val64 = val = ipath_read_creg32(dd, creg);
	/*
	 * See if a second has passed.  This is just a way to detect things
	 * that are quite broken.  Normally this should take just a few
	 * cycles (the check is for long enough that we don't care if we get
	 * pre-empted.)  An Opteron HT O read timeout is 4 seconds with
	 * normal NB values
	 */
	t1 = jiffies;
	if (time_before(t0 + HZ, t1) && val == -1) {
		ipath_dev_err(dd, "Error!  Read counter 0x%x timed out\n",
			      creg);
		ret = 0ULL;
		goto bail;
	}
	if (reg64) {
		ret = val64;
		goto bail;
	}

	if (creg == dd->ipath_cregs->cr_wordsendcnt) {
		if (val != dd->ipath_lastsword) {
			dd->ipath_sword += val - dd->ipath_lastsword;
			dd->ipath_lastsword = val;
		}
		val64 = dd->ipath_sword;
	} else if (creg == dd->ipath_cregs->cr_wordrcvcnt) {
		if (val != dd->ipath_lastrword) {
			dd->ipath_rword += val - dd->ipath_lastrword;
			dd->ipath_lastrword = val;
		}
		val64 = dd->ipath_rword;
	} else if (creg == dd->ipath_cregs->cr_pktsendcnt) {
		if (val != dd->ipath_lastspkts) {
			dd->ipath_spkts += val - dd->ipath_lastspkts;
			dd->ipath_lastspkts = val;
		}
		val64 = dd->ipath_spkts;
	} else if (creg == dd->ipath_cregs->cr_pktrcvcnt) {
		if (val != dd->ipath_lastrpkts) {
			dd->ipath_rpkts += val - dd->ipath_lastrpkts;
			dd->ipath_lastrpkts = val;
		}
		val64 = dd->ipath_rpkts;
	} else
		val64 = (u64) val;

	ret = val64;

bail:
	return ret;
}
static void musb_port_reset(struct musb *musb, bool do_reset)
{
	u8		power;
	void __iomem	*mbase = musb->mregs;

#ifdef CONFIG_USB_MUSB_OTG
	if (musb->xceiv->state == OTG_STATE_B_IDLE) {
		DBG(2, "HNP: Returning from HNP; no hub reset from b_idle\n");
		musb->port1_status &= ~USB_PORT_STAT_RESET;
		return;
	}
#endif

	if (!is_host_active(musb))
		return;

	/* NOTE:  caller guarantees it will turn off the reset when
	 * the appropriate amount of time has passed
	 */
	power = musb_readb(mbase, MUSB_POWER);
	if (do_reset) {

		/*
		 * If RESUME is set, we must make sure it stays minimum 20 ms.
		 * Then we must clear RESUME and wait a bit to let musb start
		 * generating SOFs. If we don't do this, OPT HS A 6.8 tests
		 * fail with "Error! Did not receive an SOF before suspend
		 * detected".
		 */
		if (power &  MUSB_POWER_RESUME) {
			while (time_before(jiffies, musb->rh_timer))
				msleep(1);
			musb_writeb(mbase, MUSB_POWER,
				power & ~MUSB_POWER_RESUME);
			msleep(1);
		}

		musb->ignore_disconnect = true;
		power &= 0xf0;
		musb_writeb(mbase, MUSB_POWER,
				power | MUSB_POWER_RESET);

		musb->port1_status |= USB_PORT_STAT_RESET;
		musb->port1_status &= ~USB_PORT_STAT_ENABLE;
		musb->rh_timer = jiffies + msecs_to_jiffies(50);
	} else {
		DBG(4, "root port reset stopped\n");
		musb_writeb(mbase, MUSB_POWER,
				power & ~MUSB_POWER_RESET);

		musb->ignore_disconnect = false;

		power = musb_readb(mbase, MUSB_POWER);
		if (power & MUSB_POWER_HSMODE) {
			DBG(4, "high-speed device connected\n");
			musb->port1_status |= USB_PORT_STAT_HIGH_SPEED;
		}

		musb->port1_status &= ~USB_PORT_STAT_RESET;
		musb->port1_status |= USB_PORT_STAT_ENABLE
					| (USB_PORT_STAT_C_RESET << 16)
					| (USB_PORT_STAT_C_ENABLE << 16);
		usb_hcd_poll_rh_status(musb_to_hcd(musb));

		musb->vbuserr_retry = VBUSERR_RETRY_COUNT;
	}
}
示例#16
0
static void do_profiler_stats(const struct b2r2_blt_request * const req,
	const struct b2r2_blt_profiling_info * const info)
{
	s32 blt_px;
	s32 blt_time;
	s32 blt_mpix_per_second;

	if (time_before(jiffies, profiler_stats.sampling_start_time_jiffies)) {
		/* Flush cached entries */
		clear_profiling_info(cache, BLIT_CACHE_SIZE, req);
		return;
	}

	/* Save fastest and slowest blit */
	blt_px = info->pixels;
	blt_time = nsec_2_usec((s32)(info->nsec_active_in_cpu +
			info->nsec_active_in_b2r2));
	blt_mpix_per_second = get_mpix_per_second(blt_px, blt_time);

	if (blt_mpix_per_second <= profiler_stats.min_mpix_per_second) {
		profiler_stats.min_mpix_per_second = blt_mpix_per_second;
		memcpy(&profiler_stats.min_blt_request,
			&req->user_req,
			sizeof(profiler_stats.min_blt_request));
		memcpy(&profiler_stats.min_blt_profiling_info,
			info,
			sizeof(struct b2r2_blt_profiling_info));
	}

	if (blt_mpix_per_second >= profiler_stats.max_mpix_per_second) {
		profiler_stats.max_mpix_per_second = blt_mpix_per_second;
		memcpy(&profiler_stats.max_blt_request,
			&req->user_req,
			sizeof(profiler_stats.max_blt_request));
		memcpy(&profiler_stats.max_blt_profiling_info,
			info,
			sizeof(struct b2r2_blt_profiling_info));
	}

	profiler_stats.num_pixels[info->core_id] += blt_px;
	profiler_stats.num_usecs[info->core_id] += blt_time;

	/* Save stats to cache */
	if (!request_complete(cache, BLIT_CACHE_SIZE, req, info)) {
		save_profiling_info(cache, BLIT_CACHE_SIZE, info);
		return;
	}

	/* Calculate the stats for the entire blit job */
	blt_px = get_accumulated_pixels(cache, BLIT_CACHE_SIZE,
			req, info);
	blt_time = get_accumulated_usecs(cache, BLIT_CACHE_SIZE,
			req, info);

	/* Flush cached entries */
	clear_profiling_info(cache, BLIT_CACHE_SIZE, req);

	/* Accumulate stats */
	profiler_stats.accumulated_num_pixels += blt_px;
	profiler_stats.accumulated_num_usecs += blt_time;
	profiler_stats.num_blts_done++;

	/* Print stats when we reach the configured number of blits to use */
	if (profiler_stats.num_blts_done >= profiler_stats_blts_used) {
		print_profiler_stats();
		reset_profiler_stats();

		/*
		 * The printouts initiated above can disturb the next
		 * measurement so we delay it two seconds to give the
		 * printouts a chance to finish.
		 */
		profiler_stats.sampling_start_time_jiffies =
				jiffies + (2 * HZ);
	}
}
int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
{
	struct ivtv *itv = s->itv;
	DECLARE_WAITQUEUE(wait, current);
	int cap_type;
	int stopmode;

	if (s->vdev == NULL)
		return -EINVAL;


	IVTV_DEBUG_INFO("Stop Capture\n");

	if (s->type == IVTV_DEC_STREAM_TYPE_VOUT)
		return 0;
	if (atomic_read(&itv->capturing) == 0)
		return 0;

	switch (s->type) {
	case IVTV_ENC_STREAM_TYPE_YUV:
		cap_type = 1;
		break;
	case IVTV_ENC_STREAM_TYPE_PCM:
		cap_type = 1;
		break;
	case IVTV_ENC_STREAM_TYPE_VBI:
		cap_type = 1;
		break;
	case IVTV_ENC_STREAM_TYPE_MPG:
	default:
		cap_type = 0;
		break;
	}

	
	if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
		stopmode = 0;
	} else {
		stopmode = 1;
	}

	
	
	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, stopmode, cap_type, s->subtype);

	if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) {
		if (s->type == IVTV_ENC_STREAM_TYPE_MPG && gop_end) {
			
			unsigned long duration;
			unsigned long then = jiffies;

			add_wait_queue(&itv->eos_waitq, &wait);

			set_current_state(TASK_INTERRUPTIBLE);

			
			while (!test_bit(IVTV_F_I_EOS, &itv->i_flags) &&
				time_before(jiffies,
					    then + msecs_to_jiffies(2000))) {
				schedule_timeout(msecs_to_jiffies(10));
			}

			duration = ((1000 + HZ / 2) / HZ) * (jiffies - then);

			if (!test_bit(IVTV_F_I_EOS, &itv->i_flags)) {
				IVTV_DEBUG_WARN("%s: EOS interrupt not received! stopping anyway.\n", s->name);
				IVTV_DEBUG_WARN("%s: waited %lu ms.\n", s->name, duration);
			} else {
				IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
			}
			set_current_state(TASK_RUNNING);
			remove_wait_queue(&itv->eos_waitq, &wait);
			set_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
		}

		
		ivtv_msleep_timeout(100, 0);
	}

	atomic_dec(&itv->capturing);

	
	clear_bit(IVTV_F_S_STREAMING, &s->s_flags);

	if (s->type == IVTV_ENC_STREAM_TYPE_VBI)
		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VBI_CAP);

	if (atomic_read(&itv->capturing) > 0) {
		return 0;
	}

	cx2341x_handler_set_busy(&itv->cxhdl, 0);

	
	ivtv_set_irq_mask(itv, IVTV_IRQ_MASK_CAPTURE);
	del_timer(&itv->dma_timer);

	
	if (test_and_clear_bit(IVTV_F_I_DIG_RST, &itv->i_flags)) {
		
		
		ivtv_vapi(itv, CX2341X_ENC_SET_EVENT_NOTIFICATION, 4, 0, 0, IVTV_IRQ_ENC_VIM_RST, -1);
		ivtv_set_irq_mask(itv, IVTV_IRQ_ENC_VIM_RST);
	}

	ivtv_vapi(itv, CX2341X_ENC_STOP_CAPTURE, 3, 1, 2, 7);

	wake_up(&s->waitq);

	return 0;
}
struct net_device * __init ltpc_probe(void)
{
	struct net_device *dev;
	int err = -ENOMEM;
	int x=0,y=0;
	int autoirq;
	unsigned long f;
	unsigned long timeout;

	dev = alloc_ltalkdev(sizeof(struct ltpc_private));
	if (!dev)
		goto out;

	/* probe for the I/O port address */
	
	if (io != 0x240 && request_region(0x220,8,"ltpc")) {
		x = inb_p(0x220+6);
		if ( (x!=0xff) && (x>=0xf0) ) {
			io = 0x220;
			goto got_port;
		}
		release_region(0x220,8);
	}
	if (io != 0x220 && request_region(0x240,8,"ltpc")) {
		y = inb_p(0x240+6);
		if ( (y!=0xff) && (y>=0xf0) ){ 
			io = 0x240;
			goto got_port;
		}
		release_region(0x240,8);
	} 

	/* give up in despair */
	printk(KERN_ERR "LocalTalk card not found; 220 = %02x, 240 = %02x.\n", x,y);
	err = -ENODEV;
	goto out1;

 got_port:
	/* probe for the IRQ line */
	if (irq < 2) {
		unsigned long irq_mask;

		irq_mask = probe_irq_on();
		/* reset the interrupt line */
		inb_p(io+7);
		inb_p(io+7);
		/* trigger an interrupt (I hope) */
		inb_p(io+6);
		mdelay(2);
		autoirq = probe_irq_off(irq_mask);

		if (autoirq == 0) {
			printk(KERN_ERR "ltpc: probe at %#x failed to detect IRQ line.\n", io);
		} else {
			irq = autoirq;
		}
	}

	/* allocate a DMA buffer */
	ltdmabuf = (unsigned char *) dma_mem_alloc(1000);
	if (!ltdmabuf) {
		printk(KERN_ERR "ltpc: mem alloc failed\n");
		err = -ENOMEM;
		goto out2;
	}

	ltdmacbuf = &ltdmabuf[800];

	if(debug & DEBUG_VERBOSE) {
		printk("ltdmabuf pointer %08lx\n",(unsigned long) ltdmabuf);
	}

	/* reset the card */

	inb_p(io+1);
	inb_p(io+3);

	msleep(20);

	inb_p(io+0);
	inb_p(io+2);
	inb_p(io+7); /* clear reset */
	inb_p(io+4); 
	inb_p(io+5);
	inb_p(io+5); /* enable dma */
	inb_p(io+6); /* tri-state interrupt line */

	ssleep(1);
	
	/* now, figure out which dma channel we're using, unless it's
	   already been specified */
	/* well, 0 is a legal DMA channel, but the LTPC card doesn't
	   use it... */
	dma = ltpc_probe_dma(io, dma);
	if (!dma) {  /* no dma channel */
		printk(KERN_ERR "No DMA channel found on ltpc card.\n");
		err = -ENODEV;
		goto out3;
	}

	/* print out friendly message */
	if(irq)
		printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, IR%d, DMA%d.\n",io,irq,dma);
	else
		printk(KERN_INFO "Apple/Farallon LocalTalk-PC card at %03x, DMA%d.  Using polled mode.\n",io,dma);

	dev->netdev_ops = &ltpc_netdev;
	dev->base_addr = io;
	dev->irq = irq;
	dev->dma = dma;

	/* the card will want to send a result at this point */
	/* (I think... leaving out this part makes the kernel crash,
           so I put it back in...) */

	f=claim_dma_lock();
	disable_dma(dma);
	clear_dma_ff(dma);
	set_dma_mode(dma,DMA_MODE_READ);
	set_dma_addr(dma,virt_to_bus(ltdmabuf));
	set_dma_count(dma,0x100);
	enable_dma(dma);
	release_dma_lock(f);

	(void) inb_p(io+3);
	(void) inb_p(io+2);
	timeout = jiffies+100*HZ/100;

	while(time_before(jiffies, timeout)) {
		if( 0xf9 == inb_p(io+6))
			break;
		schedule();
	}

	if(debug & DEBUG_VERBOSE) {
		printk("setting up timer and irq\n");
	}

	/* grab it and don't let go :-) */
	if (irq && request_irq( irq, ltpc_interrupt, 0, "ltpc", dev) >= 0)
	{
		(void) inb_p(io+7);  /* enable interrupts from board */
		(void) inb_p(io+7);  /* and reset irq line */
	} else {
		if( irq )
			printk(KERN_ERR "ltpc: IRQ already in use, using polled mode.\n");
		dev->irq = 0;
		/* polled mode -- 20 times per second */
		/* this is really, really slow... should it poll more often? */
		init_timer(&ltpc_timer);
		ltpc_timer.function=ltpc_poll;
		ltpc_timer.data = (unsigned long) dev;

		ltpc_timer.expires = jiffies + HZ/20;
		add_timer(&ltpc_timer);
	}
	err = register_netdev(dev);
	if (err)
		goto out4;

	return NULL;
out4:
	del_timer_sync(&ltpc_timer);
	if (dev->irq)
		free_irq(dev->irq, dev);
out3:
	free_pages((unsigned long)ltdmabuf, get_order(1000));
out2:
	release_region(io, 8);
out1:
	free_netdev(dev);
out:
	return ERR_PTR(err);
}
示例#19
0
文件: smpboot.c 项目: Sysreq/linux
/*
 * Report back to the Boot Processor.
 * Running on AP.
 */
static void __cpuinit smp_callin(void)
{
	int cpuid, phys_id;
	unsigned long timeout;

	/*
	 * If waken up by an INIT in an 82489DX configuration
	 * we may get here before an INIT-deassert IPI reaches
	 * our local APIC.  We have to wait for the IPI or we'll
	 * lock up on an APIC access.
	 */
	if (apic->wait_for_init_deassert)
		apic->wait_for_init_deassert(&init_deasserted);

	/*
	 * (This works even if the APIC is not enabled.)
	 */
	phys_id = read_apic_id();
	cpuid = smp_processor_id();
	if (cpumask_test_cpu(cpuid, cpu_callin_mask)) {
		panic("%s: phys CPU#%d, CPU#%d already present??\n", __func__,
					phys_id, cpuid);
	}
	pr_debug("CPU#%d (phys ID: %d) waiting for CALLOUT\n", cpuid, phys_id);

	/*
	 * STARTUP IPIs are fragile beasts as they might sometimes
	 * trigger some glue motherboard logic. Complete APIC bus
	 * silence for 1 second, this overestimates the time the
	 * boot CPU is spending to send the up to 2 STARTUP IPIs
	 * by a factor of two. This should be enough.
	 */

	/*
	 * Waiting 2s total for startup (udelay is not yet working)
	 */
	timeout = jiffies + 2*HZ;
	while (time_before(jiffies, timeout)) {
		/*
		 * Has the boot CPU finished it's STARTUP sequence?
		 */
		if (cpumask_test_cpu(cpuid, cpu_callout_mask))
			break;
		cpu_relax();
	}

	if (!time_before(jiffies, timeout)) {
		panic("%s: CPU%d started up but did not get a callout!\n",
		      __func__, cpuid);
	}

	/*
	 * the boot CPU has finished the init stage and is spinning
	 * on callin_map until we finish. We are free to set up this
	 * CPU, first the APIC. (this is probably redundant on most
	 * boards)
	 */

	pr_debug("CALLIN, before setup_local_APIC().\n");
	if (apic->smp_callin_clear_local_apic)
		apic->smp_callin_clear_local_apic();
	setup_local_APIC();
	end_local_APIC_setup();

	/*
	 * Need to setup vector mappings before we enable interrupts.
	 */
	setup_vector_irq(smp_processor_id());

	/*
	 * Save our processor parameters. Note: this information
	 * is needed for clock calibration.
	 */
	smp_store_cpu_info(cpuid);

	/*
	 * Get our bogomips.
	 * Update loops_per_jiffy in cpu_data. Previous call to
	 * smp_store_cpu_info() stored a value that is close but not as
	 * accurate as the value just calculated.
	 */
	calibrate_delay();
	cpu_data(cpuid).loops_per_jiffy = loops_per_jiffy;
	pr_debug("Stack at about %p\n", &cpuid);

	/*
	 * This must be done before setting cpu_online_mask
	 * or calling notify_cpu_starting.
	 */
	set_cpu_sibling_map(raw_smp_processor_id());
	wmb();

	notify_cpu_starting(cpuid);

	/*
	 * Allow the master to continue.
	 */
	cpumask_set_cpu(cpuid, cpu_callin_mask);
}
static int __init ltpc_probe_dma(int base, int dma)
{
	int want = (dma == 3) ? 2 : (dma == 1) ? 1 : 3;
  	unsigned long timeout;
  	unsigned long f;
  
  	if (want & 1) {
		if (request_dma(1,"ltpc")) {
			want &= ~1;
		} else {
			f=claim_dma_lock();
			disable_dma(1);
			clear_dma_ff(1);
			set_dma_mode(1,DMA_MODE_WRITE);
			set_dma_addr(1,virt_to_bus(ltdmabuf));
			set_dma_count(1,sizeof(struct lt_mem));
			enable_dma(1);
			release_dma_lock(f);
		}
	}
	if (want & 2) {
		if (request_dma(3,"ltpc")) {
			want &= ~2;
		} else {
			f=claim_dma_lock();
			disable_dma(3);
			clear_dma_ff(3);
			set_dma_mode(3,DMA_MODE_WRITE);
			set_dma_addr(3,virt_to_bus(ltdmabuf));
			set_dma_count(3,sizeof(struct lt_mem));
			enable_dma(3);
			release_dma_lock(f);
		}
	}
	/* set up request */

	/* FIXME -- do timings better! */

	ltdmabuf[0] = LT_READMEM;
	ltdmabuf[1] = 1;  /* mailbox */
	ltdmabuf[2] = 0; ltdmabuf[3] = 0;  /* address */
	ltdmabuf[4] = 0; ltdmabuf[5] = 1;  /* read 0x0100 bytes */
	ltdmabuf[6] = 0; /* dunno if this is necessary */

	inb_p(io+1);
	inb_p(io+0);
	timeout = jiffies+100*HZ/100;
	while(time_before(jiffies, timeout)) {
		if ( 0xfa == inb_p(io+6) ) break;
	}

	inb_p(io+3);
	inb_p(io+2);
	while(time_before(jiffies, timeout)) {
		if ( 0xfb == inb_p(io+6) ) break;
	}

	/* release the other dma channel (if we opened both of them) */

	if ((want & 2) && (get_dma_residue(3)==sizeof(struct lt_mem))) {
		want &= ~2;
		free_dma(3);
	}

	if ((want & 1) && (get_dma_residue(1)==sizeof(struct lt_mem))) {
		want &= ~1;
		free_dma(1);
	}

	if (!want)
		return 0;

	return (want & 2) ? 3 : 1;
}
示例#21
0
static int s5p_ehci_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev);
	struct usb_hcd *hcd = s5p_ehci->hcd;
	struct ehci_hcd *ehci = hcd_to_ehci(hcd);

	clk_enable(s5p_ehci->clk);

	s5p_ehci_phy_init(pdev);

	/* if EHCI was off, hcd was removed */
	if (!s5p_ehci->power_on) {
		dev_info(dev, "Nothing to do for the device (power off)\n");
		return 0;
	}

	if (time_before(jiffies, ehci->next_statechange))
		usleep_range(10000, 11000);

	/* Mark hardware accessible again as we are out of D3 state by now */
	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
		int	mask = INTR_MASK;

		if (!hcd->self.root_hub->do_remote_wakeup)
			mask &= ~STS_PCD;
		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
		ehci_readl(ehci, &ehci->regs->intr_enable);
		return 0;
	}

	ehci_dbg(ehci, "lost power, restarting\n");
	usb_root_hub_lost_power(hcd->self.root_hub);

	(void) ehci_halt(ehci);
	(void) ehci_reset(ehci);

	/* emptying the schedule aborts any urbs */
	spin_lock_irq(&ehci->lock);
	if (ehci->reclaim)
		end_unlink_async(ehci);
	ehci_work(ehci);
	spin_unlock_irq(&ehci->lock);

	ehci_writel(ehci, ehci->command, &ehci->regs->command);
	ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
	ehci_readl(ehci, &ehci->regs->command);	/* unblock posted writes */

	/* here we "know" root ports should always stay powered */
	ehci_port_power(ehci, 1);

	hcd->state = HC_STATE_SUSPENDED;

	/* Update runtime PM status and clear runtime_error */
	pm_runtime_disable(dev);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);

	/* Prevent device from runtime suspend during resume time */
	pm_runtime_get_sync(dev);

#if defined(CONFIG_LINK_DEVICE_HSIC) || defined(CONFIG_LINK_DEVICE_USB) \
	|| defined(CONFIG_MDM_HSIC_PM)
	pm_runtime_mark_last_busy(&hcd->self.root_hub->dev);
#endif
	return 0;
}
示例#22
0
文件: inode.c 项目: piastry/etercifs
int cifs_revalidate(struct dentry *direntry)
{
	int xid;
	int rc = 0, wbrc = 0;
	char *full_path;
	struct cifs_sb_info *cifs_sb;
	struct cifsInodeInfo *cifsInode;
	loff_t local_size;
	struct timespec local_mtime;
	int invalidate_inode = FALSE;

	if (direntry->d_inode == NULL)
		return -ENOENT;

	cifsInode = CIFS_I(direntry->d_inode);

	if (cifsInode == NULL)
		return -ENOENT;

	/* no sense revalidating inode info on file that no one can write */
	if (CIFS_I(direntry->d_inode)->clientCanCacheRead)
		return rc;

	xid = GetXid();

	cifs_sb = CIFS_SB(direntry->d_sb);

	/* can not safely grab the rename sem here if rename calls revalidate
	   since that would deadlock */
	full_path = build_path_from_dentry(direntry);
	if (full_path == NULL) {
		FreeXid(xid);
		return -ENOMEM;
	}
	cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld "
		 "jiffies %ld", full_path, direntry->d_inode,
		 direntry->d_inode->i_count.counter, direntry,
		 direntry->d_time, jiffies));

	if (cifsInode->time == 0) {
		/* was set to zero previously to force revalidate */
	} else if (time_before(jiffies, cifsInode->time + HZ) &&
		   lookupCacheEnabled) {
		if ((S_ISREG(direntry->d_inode->i_mode) == 0) ||
		    (direntry->d_inode->i_nlink == 1)) {
			kfree(full_path);
			FreeXid(xid);
			return rc;
		} else {
			cFYI(1, ("Have to revalidate file due to hardlinks"));
		}
	}

	/* save mtime and size */
	local_mtime = direntry->d_inode->i_mtime;
	local_size = direntry->d_inode->i_size;

	if (cifs_sb->tcon->unix_ext) {
		rc = cifs_get_inode_info_unix(&direntry->d_inode, full_path,
					      direntry->d_sb, xid);
		if (rc) {
			cFYI(1, ("error on getting revalidate info %d", rc));
/*			if (rc != -ENOENT)
				rc = 0; */	/* BB should we cache info on
						   certain errors? */
		}
	} else {
		rc = cifs_get_inode_info(&direntry->d_inode, full_path, NULL,
					 direntry->d_sb, xid, NULL);
		if (rc) {
			cFYI(1, ("error on getting revalidate info %d", rc));
/*			if (rc != -ENOENT)
				rc = 0; */	/* BB should we cache info on
						   certain errors? */
		}
	}
	/* should we remap certain errors, access denied?, to zero */

	/* if not oplocked, we invalidate inode pages if mtime or file size
	   had changed on server */

	if (timespec_equal(&local_mtime, &direntry->d_inode->i_mtime) &&
	    (local_size == direntry->d_inode->i_size)) {
		cFYI(1, ("cifs_revalidate - inode unchanged"));
	} else {
		/* file may have changed on server */
		if (cifsInode->clientCanCacheRead) {
			/* no need to invalidate inode pages since we were the
			   only ones who could have modified the file and the
			   server copy is staler than ours */
		} else {
			invalidate_inode = TRUE;
		}
	}

	/* can not grab this sem since kernel filesys locking documentation
	   indicates i_mutex may be taken by the kernel on lookup and rename
	   which could deadlock if we grab the i_mutex here as well */
/*	mutex_lock(&direntry->d_inode->i_mutex);*/
	/* need to write out dirty pages here  */
	if (direntry->d_inode->i_mapping) {
		/* do we need to lock inode until after invalidate completes
		   below? */
		wbrc = filemap_fdatawrite(direntry->d_inode->i_mapping);
		if (wbrc)
			CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
	}
	if (invalidate_inode) {
	/* shrink_dcache not necessary now that cifs dentry ops
	are exported for negative dentries */
/*		if (S_ISDIR(direntry->d_inode->i_mode))
			shrink_dcache_parent(direntry); */
		if (S_ISREG(direntry->d_inode->i_mode)) {
			if (direntry->d_inode->i_mapping)
				wbrc = filemap_fdatawait(direntry->d_inode->i_mapping);
				if (wbrc)
					CIFS_I(direntry->d_inode)->write_behind_rc = wbrc;
			cFYI(1, ("Invalidating read ahead data on "
				 "closed file"));
			invalidate_remote_inode(direntry->d_inode);
		}
	}
/*	mutex_unlock(&direntry->d_inode->i_mutex); */

	kfree(full_path);
	FreeXid(xid);
	return rc;
}
示例#23
0
int __init elplus_probe(struct net_device *dev)
{
	elp_device *adapter;
	int i, tries, tries1, timeout, okay;
	unsigned long cookie = 0;

	SET_MODULE_OWNER(dev);

	/*
	 *  setup adapter structure
	 */

	dev->base_addr = elp_autodetect(dev);
	if (!(dev->base_addr))
		return -ENODEV;

	/*
	 * setup ptr to adapter specific information
	 */
	adapter = (elp_device *) (dev->priv = kmalloc(sizeof(elp_device), GFP_KERNEL));
	if (adapter == NULL) {
		printk("%s: out of memory\n", dev->name);
		return -ENODEV;
        }

	adapter->send_pcb_semaphore = 0;

	for (tries1 = 0; tries1 < 3; tries1++) {
		outb_control((adapter->hcr_val | CMDE) & ~DIR, dev);
		/* First try to write just one byte, to see if the card is
		 * responding at all normally.
		 */
		timeout = jiffies + 5*HZ/100;
		okay = 0;
		while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
		if ((inb_status(dev->base_addr) & HCRE)) {
			outb_command(0, dev->base_addr);	/* send a spurious byte */
			timeout = jiffies + 5*HZ/100;
			while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
			if (inb_status(dev->base_addr) & HCRE)
				okay = 1;
		}
		if (!okay) {
			/* Nope, it's ignoring the command register.  This means that
			 * either it's still booting up, or it's died.
			 */
			printk("%s: command register wouldn't drain, ", dev->name);
			if ((inb_status(dev->base_addr) & 7) == 3) {
				/* If the adapter status is 3, it *could* still be booting.
				 * Give it the benefit of the doubt for 10 seconds.
				 */
				printk("assuming 3c505 still starting\n");
				timeout = jiffies + 10*HZ;
				while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7));
				if (inb_status(dev->base_addr) & 7) {
					printk("%s: 3c505 failed to start\n", dev->name);
				} else {
					okay = 1;  /* It started */
				}
			} else {
				/* Otherwise, it must just be in a strange
				 * state.  We probably need to kick it.
				 */
				printk("3c505 is sulking\n");
			}
		}
		for (tries = 0; tries < 5 && okay; tries++) {

			/*
			 * Try to set the Ethernet address, to make sure that the board
			 * is working.
			 */
			adapter->tx_pcb.command = CMD_STATION_ADDRESS;
			adapter->tx_pcb.length = 0;
			cookie = probe_irq_on();
			if (!send_pcb(dev, &adapter->tx_pcb)) {
				printk("%s: could not send first PCB\n", dev->name);
				probe_irq_off(cookie);
				continue;
			}
			if (!receive_pcb(dev, &adapter->rx_pcb)) {
				printk("%s: could not read first PCB\n", dev->name);
				probe_irq_off(cookie);
				continue;
			}
			if ((adapter->rx_pcb.command != CMD_ADDRESS_RESPONSE) ||
			    (adapter->rx_pcb.length != 6)) {
				printk("%s: first PCB wrong (%d, %d)\n", dev->name, adapter->rx_pcb.command, adapter->rx_pcb.length);
				probe_irq_off(cookie);
				continue;
			}
			goto okay;
		}
		/* It's broken.  Do a hard reset to re-initialise the board,
		 * and try again.
		 */
		printk(KERN_INFO "%s: resetting adapter\n", dev->name);
		outb_control(adapter->hcr_val | FLSH | ATTN, dev);
		outb_control(adapter->hcr_val & ~(FLSH | ATTN), dev);
	}
	printk("%s: failed to initialise 3c505\n", dev->name);
	release_region(dev->base_addr, ELP_IO_EXTENT);
	return -ENODEV;

      okay:
	if (dev->irq) {		/* Is there a preset IRQ? */
		int rpt = probe_irq_off(cookie);
		if (dev->irq != rpt) {
			printk("%s: warning, irq %d configured but %d detected\n", dev->name, dev->irq, rpt);
		}
		/* if dev->irq == probe_irq_off(cookie), all is well */
	} else		       /* No preset IRQ; just use what we can detect */
		dev->irq = probe_irq_off(cookie);
	switch (dev->irq) {    /* Legal, sane? */
	case 0:
		printk("%s: IRQ probe failed: check 3c505 jumpers.\n",
		       dev->name);
		return -ENODEV;
	case 1:
	case 6:
	case 8:
	case 13:
		printk("%s: Impossible IRQ %d reported by probe_irq_off().\n",
		       dev->name, dev->irq);
		return -ENODEV;
	}
	/*
	 *  Now we have the IRQ number so we can disable the interrupts from
	 *  the board until the board is opened.
	 */
	outb_control(adapter->hcr_val & ~CMDE, dev);

	/*
	 * copy Ethernet address into structure
	 */
	for (i = 0; i < 6; i++)
		dev->dev_addr[i] = adapter->rx_pcb.data.eth_addr[i];

	/* find a DMA channel */
	if (!dev->dma) {
		if (dev->mem_start) {
			dev->dma = dev->mem_start & 7;
		}
		else {
			printk(KERN_WARNING "%s: warning, DMA channel not specified, using default\n", dev->name);
			dev->dma = ELP_DMA;
		}
	}

	/*
	 * print remainder of startup message
	 */
	printk("%s: 3c505 at %#lx, irq %d, dma %d, ",
	       dev->name, dev->base_addr, dev->irq, dev->dma);
	printk("addr %02x:%02x:%02x:%02x:%02x:%02x, ",
	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);

	/*
	 * read more information from the adapter
	 */

	adapter->tx_pcb.command = CMD_ADAPTER_INFO;
	adapter->tx_pcb.length = 0;
	if (!send_pcb(dev, &adapter->tx_pcb) ||
	    !receive_pcb(dev, &adapter->rx_pcb) ||
	    (adapter->rx_pcb.command != CMD_ADAPTER_INFO_RESPONSE) ||
	    (adapter->rx_pcb.length != 10)) {
		printk("not responding to second PCB\n");
	}
	printk("rev %d.%d, %dk\n", adapter->rx_pcb.data.info.major_vers, adapter->rx_pcb.data.info.minor_vers, adapter->rx_pcb.data.info.RAM_sz);

	/*
	 * reconfigure the adapter memory to better suit our purposes
	 */
	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
	adapter->tx_pcb.length = 12;
	adapter->tx_pcb.data.memconf.cmd_q = 8;
	adapter->tx_pcb.data.memconf.rcv_q = 8;
	adapter->tx_pcb.data.memconf.mcast = 10;
	adapter->tx_pcb.data.memconf.frame = 10;
	adapter->tx_pcb.data.memconf.rcv_b = 10;
	adapter->tx_pcb.data.memconf.progs = 0;
	if (!send_pcb(dev, &adapter->tx_pcb) ||
	    !receive_pcb(dev, &adapter->rx_pcb) ||
	    (adapter->rx_pcb.command != CMD_CONFIGURE_ADAPTER_RESPONSE) ||
	    (adapter->rx_pcb.length != 2)) {
		printk("%s: could not configure adapter memory\n", dev->name);
	}
	if (adapter->rx_pcb.data.configure) {
		printk("%s: adapter configuration failed\n", dev->name);
	}

	/*
	 * initialise the device
	 */
	elp_init(dev);

	return 0;
}
示例#24
0
static s32 amvdec_loadmc(const u32 *p)
{
	ulong timeout;
	s32 ret = 0;

#ifdef AMVDEC_USE_STATIC_MEMORY
	if (mc_addr == NULL) {
#else
	{
#endif
		mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
	}

	if (!mc_addr)
		return -ENOMEM;

	memcpy(mc_addr, p, MC_SIZE);

	mc_addr_map = dma_map_single(amports_get_dma_device(),
		mc_addr, MC_SIZE, DMA_TO_DEVICE);

	WRITE_VREG(MPSR, 0);
	WRITE_VREG(CPSR, 0);

	/* Read CBUS register for timing */
	timeout = READ_VREG(MPSR);
	timeout = READ_VREG(MPSR);

	timeout = jiffies + HZ;

	WRITE_VREG(IMEM_DMA_ADR, mc_addr_map);
	WRITE_VREG(IMEM_DMA_COUNT, 0x1000);
	WRITE_VREG(IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

	while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
		if (time_before(jiffies, timeout))
			schedule();
		else {
			pr_err("vdec load mc error\n");
			ret = -EBUSY;
			break;
		}
	}

	dma_unmap_single(amports_get_dma_device(),
		mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
	kfree(mc_addr);
	mc_addr = NULL;
#endif

	return ret;
}

s32 amvdec_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	return am_loadmc_ex(type, name, def, &amvdec_loadmc);
}

static s32 amvdec2_loadmc(const u32 *p)
{
	if (has_vdec2()) {
		ulong timeout;
		s32 ret = 0;

#ifdef AMVDEC_USE_STATIC_MEMORY
		if (mc_addr == NULL) {
#else
		{
#endif
			mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
		}

		if (!mc_addr)
			return -ENOMEM;

		memcpy(mc_addr, p, MC_SIZE);

		mc_addr_map = dma_map_single(amports_get_dma_device(),
			mc_addr, MC_SIZE, DMA_TO_DEVICE);

		WRITE_VREG(VDEC2_MPSR, 0);
		WRITE_VREG(VDEC2_CPSR, 0);

		/* Read CBUS register for timing */
		timeout = READ_VREG(VDEC2_MPSR);
		timeout = READ_VREG(VDEC2_MPSR);

		timeout = jiffies + HZ;

		WRITE_VREG(VDEC2_IMEM_DMA_ADR, mc_addr_map);
		WRITE_VREG(VDEC2_IMEM_DMA_COUNT, 0x1000);
		WRITE_VREG(VDEC2_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

		while (READ_VREG(VDEC2_IMEM_DMA_CTRL) & 0x8000) {
			if (time_before(jiffies, timeout))
				schedule();
			else {
				pr_err("vdec2 load mc error\n");
				ret = -EBUSY;
				break;
			}
		}

		dma_unmap_single(amports_get_dma_device(),
			mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
		kfree(mc_addr);
		mc_addr = NULL;
#endif

		return ret;
	} else
		return 0;
}

s32 amvdec2_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	if (has_vdec2())
		return am_loadmc_ex(type, name, def, &amvdec2_loadmc);
	else
		return 0;
}

s32 amhcodec_loadmc(const u32 *p)
{
#ifdef AMVDEC_USE_STATIC_MEMORY
	if (mc_addr == NULL) {
#else
	{
#endif
		mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
	}

	if (!mc_addr)
		return -ENOMEM;

	memcpy(mc_addr, p, MC_SIZE);

	mc_addr_map = dma_map_single(amports_get_dma_device(),
			mc_addr, MC_SIZE, DMA_TO_DEVICE);

	WRITE_VREG(HCODEC_IMEM_DMA_ADR, mc_addr_map);
	WRITE_VREG(HCODEC_IMEM_DMA_COUNT, 0x100);
	WRITE_VREG(HCODEC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

	while (READ_VREG(HCODEC_IMEM_DMA_CTRL) & 0x8000)
		udelay(1000);

	dma_unmap_single(amports_get_dma_device(),
			mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
	kfree(mc_addr);
#endif

	return 0;
}

s32 amhcodec_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	return am_loadmc_ex(type, name, def, &amhcodec_loadmc);
}

static s32 amhevc_loadmc(const u32 *p)
{
	ulong timeout;
	s32 ret = 0;

	if (has_hevc_vdec()) {
#ifdef AMVDEC_USE_STATIC_MEMORY
		if (mc_addr == NULL) {
#else
		{
#endif
			mc_addr = kmalloc(MC_SIZE, GFP_KERNEL);
		}

		if (!mc_addr)
			return -ENOMEM;

		memcpy(mc_addr, p, MC_SIZE);

		mc_addr_map =
			dma_map_single(amports_get_dma_device(),
			mc_addr, MC_SIZE, DMA_TO_DEVICE);

		WRITE_VREG(HEVC_MPSR, 0);
		WRITE_VREG(HEVC_CPSR, 0);

		/* Read CBUS register for timing */
		timeout = READ_VREG(HEVC_MPSR);
		timeout = READ_VREG(HEVC_MPSR);

		timeout = jiffies + HZ;

		WRITE_VREG(HEVC_IMEM_DMA_ADR, mc_addr_map);
		WRITE_VREG(HEVC_IMEM_DMA_COUNT, 0x1000);
		WRITE_VREG(HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16)));

		while (READ_VREG(HEVC_IMEM_DMA_CTRL) & 0x8000) {
			if (time_before(jiffies, timeout))
				schedule();
			else {
				pr_err("vdec2 load mc error\n");
				ret = -EBUSY;
				break;
			}
		}

		dma_unmap_single(amports_get_dma_device(),
				mc_addr_map, MC_SIZE, DMA_TO_DEVICE);

#ifndef AMVDEC_USE_STATIC_MEMORY
		kfree(mc_addr);
		mc_addr = NULL;
#endif
	}

	return ret;
}

s32 amhevc_loadmc_ex(enum vformat_e type, const char *name, char *def)
{
	if (has_hevc_vdec())
		return am_loadmc_ex(type, name, def, &amhevc_loadmc);
	else
		return 0;
}

void amvdec_start(void)
{
#ifdef CONFIG_WAKELOCK
	amvdec_wake_lock();
#endif

	/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) {
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);

		WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET0, 0);

		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
	} else {
		/* #else */
		/* additional cbus dummy register reading for timing control */
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);

		WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);

		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
	}
	/* #endif */

	WRITE_VREG(MPSR, 0x0001);
}

void amvdec2_start(void)
{
	if (has_vdec2()) {
#ifdef CONFIG_WAKELOCK
		amvdec_wake_lock();
#endif

		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);

		WRITE_VREG(DOS_SW_RESET2, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET2, 0);

		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);
		READ_VREG(DOS_SW_RESET2);

		WRITE_VREG(VDEC2_MPSR, 0x0001);
	}
}

void amhcodec_start(void)
{
	WRITE_VREG(HCODEC_MPSR, 0x0001);
}

void amhevc_start(void)
{
	if (has_hevc_vdec()) {
#ifdef CONFIG_WAKELOCK
		amvdec_wake_lock();
#endif

		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);

		WRITE_VREG(DOS_SW_RESET3, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET3, 0);

		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);
		READ_VREG(DOS_SW_RESET3);

		WRITE_VREG(HEVC_MPSR, 0x0001);
	}
}

void amvdec_stop(void)
{
	ulong timeout = jiffies + HZ;

	WRITE_VREG(MPSR, 0);
	WRITE_VREG(CPSR, 0);

	while (READ_VREG(IMEM_DMA_CTRL) & 0x8000) {
		if (time_after(jiffies, timeout))
			break;
	}

	/* #if MESON_CPU_TYPE >= MESON_CPU_TYPE_MESON6 */
	if (get_cpu_type() >= MESON_CPU_MAJOR_ID_M6) {
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);

		WRITE_VREG(DOS_SW_RESET0, (1 << 12) | (1 << 11));
		WRITE_VREG(DOS_SW_RESET0, 0);

		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
		READ_VREG(DOS_SW_RESET0);
	} else {
		/* #else */
		WRITE_MPEG_REG(RESET0_REGISTER, RESET_VCPU | RESET_CCPU);

		/* additional cbus dummy register reading for timing control */
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
		READ_MPEG_REG(RESET0_REGISTER);
	}
	/* #endif */

#ifdef CONFIG_WAKELOCK
	amvdec_wake_unlock();
#endif
}
示例#25
0
static int receive_pcb(struct net_device *dev, pcb_struct * pcb)
{
	int i, j;
	int total_length;
	int stat;
	int timeout;

	elp_device *adapter = dev->priv;

	set_hsf(dev, 0);

	/* get the command code */
	timeout = jiffies + 2*HZ/100;
	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
	if (time_after_eq(jiffies, timeout)) {
		TIMEOUT_MSG(__LINE__);
		return FALSE;
	}
	pcb->command = inb_command(dev->base_addr);

	/* read the data length */
	timeout = jiffies + 3*HZ/100;
	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
	if (time_after_eq(jiffies, timeout)) {
		TIMEOUT_MSG(__LINE__);
		printk("%s: status %02x\n", dev->name, stat);
		return FALSE;
	}
	pcb->length = inb_command(dev->base_addr);

	if (pcb->length > MAX_PCB_DATA) {
		INVALID_PCB_MSG(pcb->length);
		adapter_reset(dev);
		return FALSE;
	}
	/* read the data */
	cli();
	i = 0;
	do {
		j = 0;
		while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && j++ < 20000);
		pcb->data.raw[i++] = inb_command(dev->base_addr);
		if (i > MAX_PCB_DATA)
			INVALID_PCB_MSG(i);
	} while ((stat & ASF_PCB_MASK) != ASF_PCB_END && j < 20000);
	sti();
	if (j >= 20000) {
		TIMEOUT_MSG(__LINE__);
		return FALSE;
	}
	/* woops, the last "data" byte was really the length! */
	total_length = pcb->data.raw[--i];

	/* safety check total length vs data length */
	if (total_length != (pcb->length + 2)) {
		if (elp_debug >= 2)
			printk("%s: mangled PCB received\n", dev->name);
		set_hsf(dev, HSF_PCB_NAK);
		return FALSE;
	}

	if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) {
		if (test_and_set_bit(0, (void *) &adapter->busy)) {
			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {
				set_hsf(dev, HSF_PCB_NAK);
				printk("%s: PCB rejected, transfer in progress and backlog full\n", dev->name);
				pcb->command = 0;
				return TRUE;
			} else {
				pcb->command = 0xff;
			}
		}
	}
	set_hsf(dev, HSF_PCB_ACK);
	return TRUE;
}
示例#26
0
static int c4_detect(avmcard *card)
{
	unsigned long stop, dummy;

	c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
	if (c4inmeml(card->mbase+PCI_OUT_INT_MASK) != 0x0c)
		return	1;

	c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM);

	stop = jiffies + HZ*10;
	while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) {
		if (!time_before(jiffies, stop))
			return 2;
		c4outmeml(card->mbase+DOORBELL, DBELL_ADDR);
		mb();
	}

	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0);
	c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0);

	c4outmeml(card->mbase+MAILBOX_0, 0x55aa55aa);
	if (c4inmeml(card->mbase+MAILBOX_0) != 0x55aa55aa) return 3;

	c4outmeml(card->mbase+MAILBOX_0, 0xaa55aa55);
	if (c4inmeml(card->mbase+MAILBOX_0) != 0xaa55aa55) return 4;

	if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_SA_MASK, 0)) return 5;
	if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_PCI_MASK, 0)) return 6;
	if (c4_poke(card, DC21285_ARMCSR_BASE+SA_CONTROL, SA_CTL_ALLRIGHT))
		return 7;
	if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_CYCLE, INIT_XBUS_CYCLE))
		return 8;
	if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_STROBE, INIT_XBUS_STROBE))
		return 8;
	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9;

        mdelay(1);

	if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10;
	if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11;
	if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12;
	if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13;

	if (c4_poke(card, DC21285_DRAM_A0MR+CAS_OFFSET, 0)) return 14;
	if (c4_poke(card, DC21285_DRAM_A1MR+CAS_OFFSET, 0)) return 15;
	if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16;
	if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17;

        mdelay(1);

	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF))
		return 18;

	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_0,DRAM_AD_SZ_DEF0))
		return 19;
	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_1,DRAM_AD_SZ_NULL))
		return 20;
	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_2,DRAM_AD_SZ_NULL))
		return 21;
	if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_3,DRAM_AD_SZ_NULL))
		return 22;

	/* Transputer test */
	
	if (   c4_poke(card, 0x000000, 0x11111111)
	    || c4_poke(card, 0x400000, 0x22222222)
	    || c4_poke(card, 0x800000, 0x33333333)
	    || c4_poke(card, 0xC00000, 0x44444444))
		return 23;

	if (   c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111
	    || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222
	    || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333
	    || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444)
		return 24;

	if (   c4_poke(card, 0x000000, 0x55555555)
	    || c4_poke(card, 0x400000, 0x66666666)
	    || c4_poke(card, 0x800000, 0x77777777)
	    || c4_poke(card, 0xC00000, 0x88888888))
		return 25;

	if (   c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555
	    || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666
	    || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777
	    || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888)
		return 26;

	return 0;
}
示例#27
0
static int elp_open(struct net_device *dev)
{
	elp_device *adapter;
	int retval;

	adapter = dev->priv;

	if (elp_debug >= 3)
		printk("%s: request to open device\n", dev->name);

	/*
	 * make sure we actually found the device
	 */
	if (adapter == NULL) {
		printk("%s: Opening a non-existent physical device\n", dev->name);
		return -EAGAIN;
	}
	/*
	 * disable interrupts on the board
	 */
	outb_control(0, dev);

	/*
	 * clear any pending interrupts
	 */
	inb_command(dev->base_addr);
	adapter_reset(dev);

	/*
	 * no receive PCBs active
	 */
	adapter->rx_active = 0;

	adapter->busy = 0;
	adapter->send_pcb_semaphore = 0;
	adapter->rx_backlog.in = 0;
	adapter->rx_backlog.out = 0;
	
	spin_lock_init(&adapter->lock);

	/*
	 * install our interrupt service routine
	 */
	if ((retval = request_irq(dev->irq, &elp_interrupt, 0, dev->name, dev))) {
		printk(KERN_ERR "%s: could not allocate IRQ%d\n", dev->name, dev->irq);
		return retval;
	}
	if ((retval = request_dma(dev->dma, dev->name))) {
		free_irq(dev->irq, dev);
		printk(KERN_ERR "%s: could not allocate DMA%d channel\n", dev->name, dev->dma);
		return retval;
	}
	adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE);
	if (!adapter->dma_buffer) {
		printk(KERN_ERR "%s: could not allocate DMA buffer\n", dev->name);
		free_dma(dev->dma);
		free_irq(dev->irq, dev);
		return -ENOMEM;
	}
	adapter->dmaing = 0;

	/*
	 * enable interrupts on the board
	 */
	outb_control(CMDE, dev);

	/*
	 * configure adapter memory: we need 10 multicast addresses, default==0
	 */
	if (elp_debug >= 3)
		printk(KERN_DEBUG "%s: sending 3c505 memory configuration command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;
	adapter->tx_pcb.data.memconf.cmd_q = 10;
	adapter->tx_pcb.data.memconf.rcv_q = 20;
	adapter->tx_pcb.data.memconf.mcast = 10;
	adapter->tx_pcb.data.memconf.frame = 20;
	adapter->tx_pcb.data.memconf.rcv_b = 20;
	adapter->tx_pcb.data.memconf.progs = 0;
	adapter->tx_pcb.length = sizeof(struct Memconf);
	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		printk("%s: couldn't send memory configuration command\n", dev->name);
	else {
		int timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}


	/*
	 * configure adapter to receive broadcast messages and wait for response
	 */
	if (elp_debug >= 3)
		printk("%s: sending 82586 configure command\n", dev->name);
	adapter->tx_pcb.command = CMD_CONFIGURE_82586;
	adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;
	adapter->tx_pcb.length = 2;
	adapter->got[CMD_CONFIGURE_82586] = 0;
	if (!send_pcb(dev, &adapter->tx_pcb))
		printk("%s: couldn't send 82586 configure command\n", dev->name);
	else {
		int timeout = jiffies + TIMEOUT;
		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
		if (time_after_eq(jiffies, timeout))
			TIMEOUT_MSG(__LINE__);
	}

	/* enable burst-mode DMA */
	/* outb(0x1, dev->base_addr + PORT_AUXDMA); */

	/*
	 * queue receive commands to provide buffering
	 */
	prime_rx(dev);
	if (elp_debug >= 3)
		printk("%s: %d receive PCBs active\n", dev->name, adapter->rx_active);

	/*
	 * device is now officially open!
	 */

	netif_start_queue(dev);
	return 0;
}
示例#28
0
文件: rx.c 项目: CSCLOG/beaglebone
static int rx_sync_cmd(struct aac_dev *dev, u32 command,
	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
{
	unsigned long start;
	int ok;
	/*
	 *	Write the command into Mailbox 0
	 */
	writel(command, &dev->IndexRegs->Mailbox[0]);
	/*
	 *	Write the parameters into Mailboxes 1 - 6
	 */
	writel(p1, &dev->IndexRegs->Mailbox[1]);
	writel(p2, &dev->IndexRegs->Mailbox[2]);
	writel(p3, &dev->IndexRegs->Mailbox[3]);
	writel(p4, &dev->IndexRegs->Mailbox[4]);
	/*
	 *	Clear the synch command doorbell to start on a clean slate.
	 */
	rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
	/*
	 *	Disable doorbell interrupts
	 */
	rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
	/*
	 *	Force the completion of the mask register write before issuing
	 *	the interrupt.
	 */
	rx_readb (dev, MUnit.OIMR);
	/*
	 *	Signal that there is a new synch command
	 */
	rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);

	ok = 0;
	start = jiffies;

	/*
	 *	Wait up to 30 seconds
	 */
	while (time_before(jiffies, start+30*HZ)) 
	{
		udelay(5);	/* Delay 5 microseconds to let Mon960 get info. */
		/*
		 *	Mon960 will set doorbell0 bit when it has completed the command.
		 */
		if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
			/*
			 *	Clear the doorbell.
			 */
			rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
			ok = 1;
			break;
		}
		/*
		 *	Yield the processor in case we are slow 
		 */
		msleep(1);
	}
	if (unlikely(ok != 1)) {
		/*
		 *	Restore interrupt mask even though we timed out
		 */
		aac_adapter_enable_int(dev);
		return -ETIMEDOUT;
	}
	/*
	 *	Pull the synch status from Mailbox 0.
	 */
	if (status)
		*status = readl(&dev->IndexRegs->Mailbox[0]);
	if (r1)
		*r1 = readl(&dev->IndexRegs->Mailbox[1]);
	if (r2)
		*r2 = readl(&dev->IndexRegs->Mailbox[2]);
	if (r3)
		*r3 = readl(&dev->IndexRegs->Mailbox[3]);
	if (r4)
		*r4 = readl(&dev->IndexRegs->Mailbox[4]);
	/*
	 *	Clear the synch command doorbell.
	 */
	rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
	/*
	 *	Restore interrupt mask
	 */
	aac_adapter_enable_int(dev);
	return 0;

}
示例#29
0
void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
		    const struct iphdr *tnl_params, u8 protocol)
{
	struct ip_tunnel *tunnel = netdev_priv(dev);
	const struct iphdr *inner_iph;
	struct flowi4 fl4;
	u8     tos, ttl;
	__be16 df;
	struct rtable *rt;		/* Route to the other host */
	unsigned int max_headroom;	/* The extra header space needed */
	__be32 dst;
	bool connected;

	inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
	connected = (tunnel->parms.iph.daddr != 0);

	dst = tnl_params->daddr;
	if (dst == 0) {
		/* NBMA tunnel */

		if (!skb_dst(skb)) {
			dev->stats.tx_fifo_errors++;
			goto tx_error;
		}

		if (skb->protocol == htons(ETH_P_IP)) {
			rt = skb_rtable(skb);
			dst = rt_nexthop(rt, inner_iph->daddr);
		}
#if IS_ENABLED(CONFIG_IPV6)
		else if (skb->protocol == htons(ETH_P_IPV6)) {
			const struct in6_addr *addr6;
			struct neighbour *neigh;
			bool do_tx_error_icmp;
			int addr_type;

			neigh = dst_neigh_lookup(skb_dst(skb),
						 &ipv6_hdr(skb)->daddr);
			if (!neigh)
				goto tx_error;

			addr6 = (const struct in6_addr *)&neigh->primary_key;
			addr_type = ipv6_addr_type(addr6);

			if (addr_type == IPV6_ADDR_ANY) {
				addr6 = &ipv6_hdr(skb)->daddr;
				addr_type = ipv6_addr_type(addr6);
			}

			if ((addr_type & IPV6_ADDR_COMPATv4) == 0)
				do_tx_error_icmp = true;
			else {
				do_tx_error_icmp = false;
				dst = addr6->s6_addr32[3];
			}
			neigh_release(neigh);
			if (do_tx_error_icmp)
				goto tx_error_icmp;
		}
#endif
		else
			goto tx_error;

		connected = false;
	}

	tos = tnl_params->tos;
	if (tos & 0x1) {
		tos &= ~0x1;
		if (skb->protocol == htons(ETH_P_IP)) {
			tos = inner_iph->tos;
			connected = false;
		} else if (skb->protocol == htons(ETH_P_IPV6)) {
			tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
			connected = false;
		}
	}

	init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
			 tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link);

	if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
		goto tx_error;

	rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL;

	if (!rt) {
		rt = ip_route_output_key(tunnel->net, &fl4);

		if (IS_ERR(rt)) {
			dev->stats.tx_carrier_errors++;
			goto tx_error;
		}
		if (connected)
			tunnel_dst_set(tunnel, &rt->dst, fl4.saddr);
	}

	if (rt->dst.dev == dev) {
		ip_rt_put(rt);
		dev->stats.collisions++;
		goto tx_error;
	}

	if (tnl_update_pmtu(dev, skb, rt, tnl_params->frag_off, inner_iph)) {
		ip_rt_put(rt);
		goto tx_error;
	}

	if (tunnel->err_count > 0) {
		if (time_before(jiffies,
				tunnel->err_time + IPTUNNEL_ERR_TIMEO)) {
			tunnel->err_count--;

			memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
			dst_link_failure(skb);
		} else
			tunnel->err_count = 0;
	}

	tos = ip_tunnel_ecn_encap(tos, inner_iph, skb);
	ttl = tnl_params->ttl;
	if (ttl == 0) {
		if (skb->protocol == htons(ETH_P_IP))
			ttl = inner_iph->ttl;
#if IS_ENABLED(CONFIG_IPV6)
		else if (skb->protocol == htons(ETH_P_IPV6))
			ttl = ((const struct ipv6hdr *)inner_iph)->hop_limit;
#endif
		else
			ttl = ip4_dst_hoplimit(&rt->dst);
	}

	df = tnl_params->frag_off;
	if (skb->protocol == htons(ETH_P_IP))
		df |= (inner_iph->frag_off&htons(IP_DF));

	max_headroom = LL_RESERVED_SPACE(rt->dst.dev) + sizeof(struct iphdr)
			+ rt->dst.header_len + ip_encap_hlen(&tunnel->encap);
	if (max_headroom > dev->needed_headroom)
		dev->needed_headroom = max_headroom;

	if (skb_cow_head(skb, dev->needed_headroom)) {
		ip_rt_put(rt);
		dev->stats.tx_dropped++;
		kfree_skb(skb);
		return;
	}

	iptunnel_xmit(NULL, rt, skb, fl4.saddr, fl4.daddr, protocol, tos, ttl,
		      df, !net_eq(tunnel->net, dev_net(dev)));
	return;

#if IS_ENABLED(CONFIG_IPV6)
tx_error_icmp:
	dst_link_failure(skb);
#endif
tx_error:
	dev->stats.tx_errors++;
	kfree_skb(skb);
}
示例#30
0
static void ipgre_err(struct sk_buff *skb, u32 info)
{

	/* All the routers (except for Linux) return only
	   8 bytes of packet payload. It means, that precise relaying of
	   ICMP in the real Internet is absolutely infeasible.

	   Moreover, Cisco "wise men" put GRE key to the third word
	   in GRE header. It makes impossible maintaining even soft
	   state for keyed GRE tunnels with enabled checksum. Tell
	   them "thank you".

	   Well, I wonder, rfc1812 was written by Cisco employee,
	   what the hell these idiots break standards established
	   by themselves???
	   */
	struct net *net = dev_net(skb->dev);
	struct ip_tunnel_net *itn;
	const struct iphdr *iph;
	const int type = icmp_hdr(skb)->type;
	const int code = icmp_hdr(skb)->code;
	struct ip_tunnel *t;
	struct tnl_ptk_info tpi;
	int hdr_len;
	bool csum_err = false;

	if (parse_gre_header(skb, &tpi, &csum_err, &hdr_len)) {
		if (!csum_err)          /* ignore csum errors. */
			return;
	}

	switch (type) {
	default:
	case ICMP_PARAMETERPROB:
		return;

	case ICMP_DEST_UNREACH:
		switch (code) {
		case ICMP_SR_FAILED:
		case ICMP_PORT_UNREACH:
			/* Impossible event. */
			return;
		default:
			/* All others are translated to HOST_UNREACH.
			   rfc2003 contains "deep thoughts" about NET_UNREACH,
			   I believe they are just ether pollution. --ANK
			 */
			break;
		}
		break;
	case ICMP_TIME_EXCEEDED:
		if (code != ICMP_EXC_TTL)
			return;
		break;

	case ICMP_REDIRECT:
		break;
	}

	if (tpi.proto == htons(ETH_P_TEB))
		itn = net_generic(net, gre_tap_net_id);
	else
		itn = net_generic(net, ipgre_net_id);

	iph = (const struct iphdr *)skb->data;
	t = ip_tunnel_lookup(itn, skb->dev->ifindex, tpi.flags,
			     iph->daddr, iph->saddr, tpi.key);

	if (t == NULL)
		return;

	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
		ipv4_update_pmtu(skb, dev_net(skb->dev), info,
				 t->parms.link, 0, IPPROTO_GRE, 0);
		return;
	}
	if (type == ICMP_REDIRECT) {
		ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
			      IPPROTO_GRE, 0);
		return;
	}
	if (t->parms.iph.daddr == 0 ||
	    ipv4_is_multicast(t->parms.iph.daddr))
		return;

	if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
		return;

	if (time_before(jiffies, t->err_time + IPTUNNEL_ERR_TIMEO))
		t->err_count++;
	else
		t->err_count = 1;
	t->err_time = jiffies;
}