示例#1
0
static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{
	static const struct ata_port_info info_82c700 = {
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.port_ops = &optidma_port_ops
	};
	static const struct ata_port_info info_82c700_udma = {
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.udma_mask = 0x07,
		.port_ops = &optiplus_port_ops
	};
	const struct ata_port_info *ppi[] = { &info_82c700, NULL };
	static int printed_version;
	int rc;

	if (!printed_version++)
		dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n");

	rc = pcim_enable_device(dev);
	if (rc)
		return rc;

	/* Fixed location chipset magic */
	inw(0x1F1);
	inw(0x1F1);
	pci_clock = inb(0x1F5) & 1;		/* 0 = 33Mhz, 1 = 25Mhz */

	if (optiplus_with_udma(dev))
		ppi[0] = &info_82c700_udma;

	return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL);
}

static const struct pci_device_id optidma[] = {
	{ PCI_VDEVICE(OPTI, 0xD568), },		/* Opti 82C700 */

	{ },
};

static struct pci_driver optidma_pci_driver = {
	.name 		= DRV_NAME,
	.id_table	= optidma,
	.probe 		= optidma_init_one,
	.remove		= ata_pci_remove_one,
#ifdef CONFIG_PM
	.suspend	= ata_pci_device_suspend,
	.resume		= ata_pci_device_resume,
#endif
};

static int __init optidma_init(void)
{
	return pci_register_driver(&optidma_pci_driver);
}

static void __exit optidma_exit(void)
{
	pci_unregister_driver(&optidma_pci_driver);
}

MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("low-level driver for Opti Firestar/Firestar Plus");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, optidma);
MODULE_VERSION(DRV_VERSION);

module_init(optidma_init);
module_exit(optidma_exit);
示例#2
0
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
							| WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "ALiM7101",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_SETOPTIONS:
	{
		int new_options, retval = -EINVAL;

		if (get_user(new_options, p))
			return -EFAULT;
		if (new_options & WDIOS_DISABLECARD) {
			wdt_turnoff();
			retval = 0;
		}
		if (new_options & WDIOS_ENABLECARD) {
			wdt_startup();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		wdt_keepalive();
		return 0;
	case WDIOC_SETTIMEOUT:
	{
		int new_timeout;

		if (get_user(new_timeout, p))
			return -EFAULT;
		/* arbitrary upper limit */
		if (new_timeout < 1 || new_timeout > 3600)
			return -EINVAL;
		timeout = new_timeout;
		wdt_keepalive();
		/* Fall through */
	}
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);
	default:
		return -ENOTTY;
	}
}

static const struct file_operations wdt_fops = {
	.owner		=	THIS_MODULE,
	.llseek		=	no_llseek,
	.write		=	fop_write,
	.open		=	fop_open,
	.release	=	fop_close,
	.unlocked_ioctl	=	fop_ioctl,
};

static struct miscdevice wdt_miscdev = {
	.minor	=	WATCHDOG_MINOR,
	.name	=	"watchdog",
	.fops	=	&wdt_fops,
};

static int wdt_restart_handle(struct notifier_block *this, unsigned long mode,
			      void *cmd)
{
	/*
	 * Cobalt devices have no way of rebooting themselves other
	 * than getting the watchdog to pull reset, so we restart the
	 * watchdog on reboot with no heartbeat.
	 */
	wdt_change(WDT_ENABLE);

	/* loop until the watchdog fires */
	while (true)
		;

	return NOTIFY_DONE;
}

static struct notifier_block wdt_restart_handler = {
	.notifier_call = wdt_restart_handle,
	.priority = 128,
};

/*
 *	Notifier for system down
 */

static int wdt_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wdt_turnoff();

	return NOTIFY_DONE;
}

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static void __exit alim7101_wdt_unload(void)
{
	wdt_turnoff();
	/* Deregister */
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	unregister_restart_handler(&wdt_restart_handler);
	pci_dev_put(alim7101_pmu);
}

static int __init alim7101_wdt_init(void)
{
	int rc = -EBUSY;
	struct pci_dev *ali1543_south;
	char tmp;

	pr_info("Steve Hill <*****@*****.**>\n");
	alim7101_pmu = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101,
		NULL);
	if (!alim7101_pmu) {
		pr_info("ALi M7101 PMU not present - WDT not set\n");
		return -EBUSY;
	}

	/* Set the WDT in the PMU to 1 second */
	pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, 0x02);

	ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533,
		NULL);
	if (!ali1543_south) {
		pr_info("ALi 1543 South-Bridge not present - WDT not set\n");
		goto err_out;
	}
	pci_read_config_byte(ali1543_south, 0x5e, &tmp);
	pci_dev_put(ali1543_south);
	if ((tmp & 0x1e) == 0x00) {
		if (!use_gpio) {
			pr_info("Detected old alim7101 revision 'a1d'.  If this is a cobalt board, set the 'use_gpio' module parameter.\n");
			goto err_out;
		}
		nowayout = 1;
	} else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) {
		pr_info("ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n");
		goto err_out;
	}

	if (timeout < 1 || timeout > 3600) {
		/* arbitrary upper limit */
		timeout = WATCHDOG_TIMEOUT;
		pr_info("timeout value must be 1 <= x <= 3600, using %d\n",
			timeout);
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc) {
		pr_err("cannot register reboot notifier (err=%d)\n", rc);
		goto err_out;
	}

	rc = register_restart_handler(&wdt_restart_handler);
	if (rc) {
		pr_err("cannot register restart handler (err=%d)\n", rc);
		goto err_out_reboot;
	}

	rc = misc_register(&wdt_miscdev);
	if (rc) {
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		       wdt_miscdev.minor, rc);
		goto err_out_restart;
	}

	if (nowayout)
		__module_get(THIS_MODULE);

	pr_info("WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);
	return 0;

err_out_restart:
	unregister_restart_handler(&wdt_restart_handler);
err_out_reboot:
	unregister_reboot_notifier(&wdt_notifier);
err_out:
	pci_dev_put(alim7101_pmu);
	return rc;
}

module_init(alim7101_wdt_init);
module_exit(alim7101_wdt_unload);

static const struct pci_device_id alim7101_pci_tbl[] __used = {
	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533) },
	{ PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) },
	{ }
};

MODULE_DEVICE_TABLE(pci, alim7101_pci_tbl);

MODULE_AUTHOR("Steve Hill");
MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver");
MODULE_LICENSE("GPL");
示例#3
0
static int sblock_thread(void *data)
{
	struct sblock_mgr *sblock = data;
	struct smsg mcmd, mrecv;
	int rval;
	int recovery = 0;
	struct sched_param param = {.sched_priority = 90};

	/*set the thread as a real time thread, and its priority is 90*/
	sched_setscheduler(current, SCHED_RR, &param);

	/* since the channel open may hang, we call it in the sblock thread */
	rval = smsg_ch_open(sblock->dst, sblock->channel, -1);
	if (rval != 0) {
		printk(KERN_ERR "Failed to open channel %d\n", sblock->channel);
		/* assign NULL to thread poniter as failed to open channel */
		sblock->thread = NULL;
		return rval;
	}

	/* handle the sblock events */
	while (!kthread_should_stop()) {

		/* monitor sblock recv smsg */
		smsg_set(&mrecv, sblock->channel, 0, 0, 0);
		rval = smsg_recv(sblock->dst, &mrecv, -1);
		if (rval == -EIO || rval == -ENODEV) {
		/* channel state is FREE */
			msleep(5);
			continue;
		}

		pr_debug("sblock thread recv msg: dst=%d, channel=%d, "
				"type=%d, flag=0x%04x, value=0x%08x\n",
				sblock->dst, sblock->channel,
				mrecv.type, mrecv.flag, mrecv.value);

		switch (mrecv.type) {
		case SMSG_TYPE_OPEN:
			/* handle channel recovery */
			if (recovery) {
				if (sblock->handler) {
					sblock->handler(SBLOCK_NOTIFY_CLOSE, sblock->data);
				}
				sblock_recover(sblock->dst, sblock->channel);
			}
			smsg_open_ack(sblock->dst, sblock->channel);
			break;
		case SMSG_TYPE_CLOSE:
			/* handle channel recovery */
			smsg_close_ack(sblock->dst, sblock->channel);
			if (sblock->handler) {
				sblock->handler(SBLOCK_NOTIFY_CLOSE, sblock->data);
			}
			sblock->state = SBLOCK_STATE_IDLE;
			break;
		case SMSG_TYPE_CMD:
			/* respond cmd done for sblock init */
			WARN_ON(mrecv.flag != SMSG_CMD_SBLOCK_INIT);
			smsg_set(&mcmd, sblock->channel, SMSG_TYPE_DONE,
					SMSG_DONE_SBLOCK_INIT, sblock->smem_addr);
			smsg_send(sblock->dst, &mcmd, -1);
			if (sblock->handler) {
				sblock->handler(SBLOCK_NOTIFY_OPEN, sblock->data);
			}
			sblock->state = SBLOCK_STATE_READY;
			recovery = 1;
			break;
		case SMSG_TYPE_EVENT:
			/* handle sblock send/release events */
			switch (mrecv.flag) {
			case SMSG_EVENT_SBLOCK_SEND:
				wake_up_interruptible_all(&sblock->ring->recvwait);
				if (sblock->handler) {
					sblock->handler(SBLOCK_NOTIFY_RECV, sblock->data);
				}
				break;
			case SMSG_EVENT_SBLOCK_RELEASE:
				wake_up_interruptible_all(&(sblock->ring->getwait));
				if (sblock->handler) {
					sblock->handler(SBLOCK_NOTIFY_GET, sblock->data);
				}
				break;
			default:
				rval = 1;
				break;
			}
			break;
		default:
			rval = 1;
			break;
		};
		if (rval) {
			printk(KERN_WARNING "non-handled sblock msg: %d-%d, %d, %d, %d\n",
					sblock->dst, sblock->channel,
					mrecv.type, mrecv.flag, mrecv.value);
			rval = 0;
		}
	}

	printk(KERN_WARNING "sblock %d-%d thread stop", sblock->dst, sblock->channel);
	return rval;
}

int sblock_create(uint8_t dst, uint8_t channel,
		uint32_t txblocknum, uint32_t txblocksize,
		uint32_t rxblocknum, uint32_t rxblocksize)
{
	struct sblock_mgr *sblock = NULL;
	volatile struct sblock_ring_header *ringhd = NULL;
	volatile struct sblock_ring_header *poolhd = NULL;
	uint32_t hsize;
	int i, result;

	sblock = kzalloc(sizeof(struct sblock_mgr) , GFP_KERNEL);
	if (!sblock) {
		return -ENOMEM;
	}

	sblock->state = SBLOCK_STATE_IDLE;
	sblock->dst = dst;
	sblock->channel = channel;
	sblock->txblksz = txblocksize;
	sblock->rxblksz = rxblocksize;
	sblock->txblknum = txblocknum;
	sblock->rxblknum = rxblocknum;


	/* allocate smem */
	hsize = sizeof(struct sblock_header);
	sblock->smem_size = hsize +						/* for header*/
		txblocknum * txblocksize + rxblocknum * rxblocksize + 		/* for blks */
		(txblocknum + rxblocknum) * sizeof(struct sblock_blks) + 	/* for ring*/
		(txblocknum + rxblocknum) * sizeof(struct sblock_blks); 	/* for pool*/

	sblock->smem_addr = smem_alloc(sblock->smem_size);
	if (!sblock->smem_addr) {
		printk(KERN_ERR "Failed to allocate smem for sblock\n");
		kfree(sblock);
		return -ENOMEM;
	}
	sblock->smem_virt = ioremap(sblock->smem_addr, sblock->smem_size);
	if (!sblock->smem_virt) {
		printk(KERN_ERR "Failed to map smem for sblock\n");
		smem_free(sblock->smem_addr, sblock->smem_size);
		kfree(sblock);
		return -EFAULT;
	}

	/* initialize ring and header */
	sblock->ring = kzalloc(sizeof(struct sblock_ring), GFP_KERNEL);
	if (!sblock->ring) {
		printk(KERN_ERR "Failed to allocate ring for sblock\n");
		iounmap(sblock->smem_virt);
		smem_free(sblock->smem_addr, sblock->smem_size);
		kfree(sblock);
		return -ENOMEM;
	}
	ringhd = (volatile struct sblock_ring_header *)(sblock->smem_virt);
	ringhd->txblk_addr = sblock->smem_addr + hsize;
	ringhd->txblk_count = txblocknum;
	ringhd->txblk_size = txblocksize;
	ringhd->txblk_rdptr = 0;
	ringhd->txblk_wrptr = 0;
	ringhd->txblk_blks = sblock->smem_addr + hsize +
		txblocknum * txblocksize + rxblocknum * rxblocksize;
	ringhd->rxblk_addr = ringhd->txblk_addr + txblocknum * txblocksize;
	ringhd->rxblk_count = rxblocknum;
	ringhd->rxblk_size = rxblocksize;
	ringhd->rxblk_rdptr = 0;
	ringhd->rxblk_wrptr = 0;
	ringhd->rxblk_blks = ringhd->txblk_blks + txblocknum * sizeof(struct sblock_blks);

	poolhd = (volatile struct sblock_ring_header *)(sblock->smem_virt + sizeof(struct sblock_ring_header));
	poolhd->txblk_addr = sblock->smem_addr + hsize;
	poolhd->txblk_count = txblocknum;
	poolhd->txblk_size = txblocksize;
	poolhd->txblk_rdptr = 0;
	poolhd->txblk_wrptr = 0;
	poolhd->txblk_blks = ringhd->rxblk_blks + rxblocknum * sizeof(struct sblock_blks);
	poolhd->rxblk_addr = ringhd->txblk_addr + txblocknum * txblocksize;
	poolhd->rxblk_count = rxblocknum;
	poolhd->rxblk_size = rxblocksize;
	poolhd->rxblk_rdptr = 0;
	poolhd->rxblk_wrptr = 0;
	poolhd->rxblk_blks = poolhd->txblk_blks + txblocknum * sizeof(struct sblock_blks);

	sblock->ring->txrecord = kzalloc(sizeof(int) * txblocknum, GFP_KERNEL);
	if (!sblock->ring->txrecord) {
		printk(KERN_ERR "Failed to allocate memory for txrecord\n");
		iounmap(sblock->smem_virt);
		smem_free(sblock->smem_addr, sblock->smem_size);
		kfree(sblock->ring);
		kfree(sblock);
		return -ENOMEM;
	}

	sblock->ring->rxrecord = kzalloc(sizeof(int) * rxblocknum, GFP_KERNEL);
	if (!sblock->ring->rxrecord) {
		printk(KERN_ERR "Failed to allocate memory for rxrecord\n");
		iounmap(sblock->smem_virt);
		smem_free(sblock->smem_addr, sblock->smem_size);
		kfree(sblock->ring->txrecord);
		kfree(sblock->ring);
		kfree(sblock);
		return -ENOMEM;
	}

	sblock->ring->header = sblock->smem_virt;
	sblock->ring->txblk_virt = sblock->smem_virt +
		(ringhd->txblk_addr - sblock->smem_addr);
	sblock->ring->r_txblks = sblock->smem_virt +
		(ringhd->txblk_blks - sblock->smem_addr);
	sblock->ring->rxblk_virt = sblock->smem_virt +
		(ringhd->rxblk_addr - sblock->smem_addr);
	sblock->ring->r_rxblks = sblock->smem_virt +
		(ringhd->rxblk_blks - sblock->smem_addr);
	sblock->ring->p_txblks = sblock->smem_virt +
		(poolhd->txblk_blks - sblock->smem_addr);
	sblock->ring->p_rxblks = sblock->smem_virt +
		(poolhd->rxblk_blks - sblock->smem_addr);


	for (i = 0; i < txblocknum; i++) {
		sblock->ring->p_txblks[i].addr = poolhd->txblk_addr + i * txblocksize;
		sblock->ring->p_txblks[i].length = txblocksize;
		sblock->ring->txrecord[i] = SBLOCK_BLK_STATE_DONE;
		poolhd->txblk_wrptr++;
	}
	for (i = 0; i < rxblocknum; i++) {
		sblock->ring->p_rxblks[i].addr = poolhd->rxblk_addr + i * rxblocksize;
		sblock->ring->p_rxblks[i].length = rxblocksize;
		sblock->ring->rxrecord[i] = SBLOCK_BLK_STATE_DONE;
		poolhd->rxblk_wrptr++;
	}

	init_waitqueue_head(&sblock->ring->getwait);
	init_waitqueue_head(&sblock->ring->recvwait);
	spin_lock_init(&sblock->ring->r_txlock);
	spin_lock_init(&sblock->ring->r_rxlock);
	spin_lock_init(&sblock->ring->p_txlock);
	spin_lock_init(&sblock->ring->p_rxlock);

	sblock->thread = kthread_create(sblock_thread, sblock,
			"sblock-%d-%d", dst, channel);
	if (IS_ERR(sblock->thread)) {
		printk(KERN_ERR "Failed to create kthread: sblock-%d-%d\n", dst, channel);
		iounmap(sblock->smem_virt);
		smem_free(sblock->smem_addr, sblock->smem_size);
		kfree(sblock->ring->txrecord);
		kfree(sblock->ring->rxrecord);
		kfree(sblock->ring);
		result = PTR_ERR(sblock->thread);
		kfree(sblock);
		return result;
	}

	sblocks[dst][channel]=sblock;
	wake_up_process(sblock->thread);

	return 0;
}

void sblock_destroy(uint8_t dst, uint8_t channel)
{
	struct sblock_mgr *sblock = sblocks[dst][channel];

	if (sblock == NULL) {
		return;
	}

	sblock->state = SBLOCK_STATE_IDLE;
	smsg_ch_close(dst, channel, -1);

	/* stop sblock thread if it's created successfully and still alive */
	if (!IS_ERR_OR_NULL(sblock->thread)) {
		kthread_stop(sblock->thread);
	}

	if (sblock->ring) {
		wake_up_interruptible_all(&sblock->ring->recvwait);
		wake_up_interruptible_all(&sblock->ring->getwait);
		if (sblock->ring->txrecord) {
			kfree(sblock->ring->txrecord);
		}
		if (sblock->ring->rxrecord) {
			kfree(sblock->ring->rxrecord);
		}
		kfree(sblock->ring);
	}
	if (sblock->smem_virt) {
		iounmap(sblock->smem_virt);
	}
	smem_free(sblock->smem_addr, sblock->smem_size);
	kfree(sblock);

	sblocks[dst][channel]=NULL;
}

int sblock_register_notifier(uint8_t dst, uint8_t channel,
		void (*handler)(int event, void *data), void *data)
{
	struct sblock_mgr *sblock = sblocks[dst][channel];

	if (!sblock) {
		printk(KERN_ERR "sblock-%d-%d not ready!\n", dst, channel);
		return -ENODEV;
	}
#ifndef CONFIG_SIPC_WCN
	if (sblock->handler) {
		printk(KERN_ERR "sblock handler already registered\n");
		return -EBUSY;
	}
#endif
	sblock->handler = handler;
	sblock->data = data;

	return 0;
}

int sblock_get(uint8_t dst, uint8_t channel, struct sblock *blk, int timeout)
{
	struct sblock_mgr *sblock = (struct sblock_mgr *)sblocks[dst][channel];
	struct sblock_ring *ring = NULL;
	volatile struct sblock_ring_header *ringhd = NULL;
	volatile struct sblock_ring_header *poolhd = NULL;
	int txpos, index;
	int rval = 0;
	unsigned long flags;

	if (!sblock || sblock->state != SBLOCK_STATE_READY) {
		printk(KERN_ERR "sblock-%d-%d not ready!\n", dst, channel);
		return sblock ? -EIO : -ENODEV;
	}

	ring = sblock->ring;
	ringhd = (volatile struct sblock_ring_header *)(&ring->header->ring);
	poolhd = (volatile struct sblock_ring_header *)(&ring->header->pool);

	if (poolhd->txblk_rdptr == poolhd->txblk_wrptr) {
		if (timeout == 0) {
			/* no wait */
			printk(KERN_WARNING "sblock_get %d-%d is empty!\n",
				dst, channel);
			rval = -ENODATA;
		} else if (timeout < 0) {
			/* wait forever */
			rval = wait_event_interruptible(ring->getwait,
					poolhd->txblk_rdptr != poolhd->txblk_wrptr ||
					sblock->state == SBLOCK_STATE_IDLE);
			if (rval < 0) {
				printk(KERN_WARNING "sblock_get wait interrupted!\n");
			}

			if (sblock->state == SBLOCK_STATE_IDLE) {
				printk(KERN_ERR "sblock_get sblock state is idle!\n");
				rval = -EIO;
			}
		} else {
			/* wait timeout */
			rval = wait_event_interruptible_timeout(ring->getwait,
					poolhd->txblk_rdptr != poolhd->txblk_wrptr ||
					sblock == SBLOCK_STATE_IDLE,
					timeout);
			if (rval < 0) {
				printk(KERN_WARNING "sblock_get wait interrupted!\n");
			} else if (rval == 0) {
				printk(KERN_WARNING "sblock_get wait timeout!\n");
				rval = -ETIME;
			}

			if(sblock->state == SBLOCK_STATE_IDLE) {
				printk(KERN_ERR "sblock_get sblock state is idle!\n");
				rval = -EIO;
			}
		}
	}

	if (rval < 0) {
		return rval;
	}

	/* multi-gotter may cause got failure */
	spin_lock_irqsave(&ring->p_txlock, flags);
	if (poolhd->txblk_rdptr != poolhd->txblk_wrptr &&
			sblock->state == SBLOCK_STATE_READY) {
		txpos = sblock_get_ringpos(poolhd->txblk_rdptr, poolhd->txblk_count);
		blk->addr = sblock->smem_virt + (ring->p_txblks[txpos].addr - sblock->smem_addr);
		blk->length = poolhd->txblk_size;
		poolhd->txblk_rdptr = poolhd->txblk_rdptr + 1;
		index = sblock_get_index((blk->addr - ring->txblk_virt), sblock->txblksz);
		ring->txrecord[index] = SBLOCK_BLK_STATE_PENDING;
	} else {
		rval = sblock->state == SBLOCK_STATE_READY ? -EAGAIN : -EIO;
	}
	spin_unlock_irqrestore(&ring->p_txlock, flags);

	return rval;
}

static int sblock_send_ex(uint8_t dst, uint8_t channel, struct sblock *blk, bool yell)
{
	struct sblock_mgr *sblock = (struct sblock_mgr *)sblocks[dst][channel];
	struct sblock_ring *ring;
	volatile struct sblock_ring_header *ringhd;
	struct smsg mevt;
	int txpos, index;
	int rval = 0;
	unsigned long flags;

	if (!sblock || sblock->state != SBLOCK_STATE_READY) {
		printk(KERN_ERR "sblock-%d-%d not ready!\n", dst, channel);
		return sblock ? -EIO : -ENODEV;
	}

	pr_debug("sblock_send: dst=%d, channel=%d, addr=%p, len=%d\n",
			dst, channel, blk->addr, blk->length);

	ring = sblock->ring;
	ringhd = (volatile struct sblock_ring_header *)(&ring->header->ring);

	spin_lock_irqsave(&ring->r_txlock, flags);

	txpos = sblock_get_ringpos(ringhd->txblk_wrptr, ringhd->txblk_count);
	ring->r_txblks[txpos].addr = blk->addr - sblock->smem_virt + sblock->smem_addr;
	ring->r_txblks[txpos].length = blk->length;
	pr_debug("sblock_send: channel=%d, wrptr=%d, txpos=%d, addr=%x\n",
			channel, ringhd->txblk_wrptr, txpos, ring->r_txblks[txpos].addr);
	ringhd->txblk_wrptr = ringhd->txblk_wrptr + 1;
	if (yell && sblock->state == SBLOCK_STATE_READY) {
		smsg_set(&mevt, channel, SMSG_TYPE_EVENT, SMSG_EVENT_SBLOCK_SEND, 0);
		rval = smsg_send(dst, &mevt, 0);
	}
	index = sblock_get_index((blk->addr - ring->txblk_virt), sblock->txblksz);
	ring->txrecord[index] = SBLOCK_BLK_STATE_DONE;

	spin_unlock_irqrestore(&ring->r_txlock, flags);

	return rval ;
}

int sblock_send(uint8_t dst, uint8_t channel, struct sblock *blk)
{
	return sblock_send_ex(dst, channel, blk, true);
}

int sblock_send_prepare(uint8_t dst, uint8_t channel, struct sblock *blk)
{
	return sblock_send_ex(dst, channel, blk, false);
}

int sblock_send_finish(uint8_t dst, uint8_t channel)
{
	struct sblock_mgr *sblock = (struct sblock_mgr *)sblocks[dst][channel];
	struct sblock_ring *ring;
	volatile struct sblock_ring_header *ringhd;
	struct smsg mevt;
	int rval;

	if (!sblock || sblock->state != SBLOCK_STATE_READY) {
		printk(KERN_ERR "sblock-%d-%d not ready!\n", dst, channel);
		return sblock ? -EIO : -ENODEV;
	}

	ring = sblock->ring;
	ringhd = (volatile struct sblock_ring_header *)(&ring->header->ring);

	if (ringhd->txblk_wrptr != ringhd->txblk_rdptr) {
		smsg_set(&mevt, channel, SMSG_TYPE_EVENT, SMSG_EVENT_SBLOCK_SEND, 0);
		rval = smsg_send(dst, &mevt, 0);
	}

	return rval;
}

int sblock_receive(uint8_t dst, uint8_t channel, struct sblock *blk, int timeout)
{
	struct sblock_mgr *sblock = sblocks[dst][channel];
	struct sblock_ring *ring;
	volatile struct sblock_ring_header *ringhd;
	int rxpos, index, rval = 0;
	unsigned long flags;

	if (!sblock || sblock->state != SBLOCK_STATE_READY) {
		printk(KERN_ERR "sblock-%d-%d not ready!\n", dst, channel);
		return sblock ? -EIO : -ENODEV;
	}

	ring = sblock->ring;
	ringhd = (volatile struct sblock_ring_header *)(&ring->header->ring);

	pr_debug("sblock_receive: dst=%d, channel=%d, timeout=%d\n",
			dst, channel, timeout);
	pr_debug("sblock_receive: channel=%d, wrptr=%d, rdptr=%d",
			channel, ringhd->rxblk_wrptr, ringhd->rxblk_rdptr);

	if (ringhd->rxblk_wrptr == ringhd->rxblk_rdptr) {
		if (timeout == 0) {
			/* no wait */
			pr_debug("sblock_receive %d-%d is empty!\n",
				dst, channel);
			rval = -ENODATA;
		} else if (timeout < 0) {
			/* wait forever */
			rval = wait_event_interruptible(ring->recvwait,
				ringhd->rxblk_wrptr != ringhd->rxblk_rdptr);
			if (rval < 0) {
				printk(KERN_WARNING "sblock_receive wait interrupted!\n");
			}

			if (sblock->state == SBLOCK_STATE_IDLE) {
				printk(KERN_ERR "sblock_receive sblock state is idle!\n");
				rval = -EIO;
			}

		} else {
			/* wait timeout */
			rval = wait_event_interruptible_timeout(ring->recvwait,
				ringhd->rxblk_wrptr != ringhd->rxblk_rdptr, timeout);
			if (rval < 0) {
				printk(KERN_WARNING "sblock_receive wait interrupted!\n");
			} else if (rval == 0) {
				printk(KERN_WARNING "sblock_receive wait timeout!\n");
				rval = -ETIME;
			}

			if (sblock->state == SBLOCK_STATE_IDLE) {
				printk(KERN_ERR "sblock_receive sblock state is idle!\n");
				rval = -EIO;
			}
		}
	}

	if (rval < 0) {
		return rval;
	}

	/* multi-receiver may cause recv failure */
	spin_lock_irqsave(&ring->r_rxlock, flags);

	if (ringhd->rxblk_wrptr != ringhd->rxblk_rdptr &&
			sblock->state == SBLOCK_STATE_READY) {
		rxpos = sblock_get_ringpos(ringhd->rxblk_rdptr, ringhd->rxblk_count);
		blk->addr = ring->r_rxblks[rxpos].addr - sblock->smem_addr + sblock->smem_virt;
		blk->length = ring->r_rxblks[rxpos].length;
		ringhd->rxblk_rdptr = ringhd->rxblk_rdptr + 1;
		pr_debug("sblock_receive: channel=%d, rxpos=%d, addr=%p, len=%d\n",
			channel, rxpos, blk->addr, blk->length);
		index = sblock_get_index((blk->addr - ring->rxblk_virt), sblock->rxblksz);
		ring->rxrecord[index] = SBLOCK_BLK_STATE_PENDING;
	} else {
		rval = sblock->state == SBLOCK_STATE_READY ? -EAGAIN : -EIO;
	}
	spin_unlock_irqrestore(&ring->r_rxlock, flags);

	return rval;
}

int sblock_get_free_count(uint8_t dst, uint8_t channel)
{
	struct sblock_mgr *sblock = (struct sblock_mgr *)sblocks[dst][channel];
	struct sblock_ring *ring = NULL;
	volatile struct sblock_ring_header *poolhd = NULL;
	int blk_count = 0;
	unsigned long flags;

	if (!sblock || sblock->state != SBLOCK_STATE_READY) {
		printk(KERN_ERR "sblock-%d-%d not ready!\n", dst, channel);
		return -ENODEV;
	}

	ring = sblock->ring;
	poolhd = (volatile struct sblock_ring_header *)(&ring->header->pool);

	spin_lock_irqsave(&ring->p_txlock, flags);
	blk_count = (int)(poolhd->txblk_wrptr - poolhd->txblk_rdptr);
	spin_unlock_irqrestore(&ring->p_txlock, flags);

	return blk_count;
}

int sblock_release(uint8_t dst, uint8_t channel, struct sblock *blk)
{
	struct sblock_mgr *sblock = (struct sblock_mgr *)sblocks[dst][channel];
	struct sblock_ring *ring = NULL;
	volatile struct sblock_ring_header *ringhd = NULL;
	volatile struct sblock_ring_header *poolhd = NULL;
	struct smsg mevt;
	unsigned long flags;
	int rxpos;
	int index;

	if (!sblock || sblock->state != SBLOCK_STATE_READY) {
		printk(KERN_ERR "sblock-%d-%d not ready!\n", dst, channel);
		return -ENODEV;
	}

	pr_debug("sblock_release: dst=%d, channel=%d, addr=%p, len=%d\n",
			dst, channel, blk->addr, blk->length);

	ring = sblock->ring;
	ringhd = (volatile struct sblock_ring_header *)(&ring->header->ring);
	poolhd = (volatile struct sblock_ring_header *)(&ring->header->pool);

	spin_lock_irqsave(&ring->p_rxlock, flags);
	rxpos = sblock_get_ringpos(poolhd->rxblk_wrptr, poolhd->rxblk_count);
	ring->p_rxblks[rxpos].addr = blk->addr - sblock->smem_virt + sblock->smem_addr;
	ring->p_rxblks[rxpos].length = poolhd->rxblk_size;
	poolhd->rxblk_wrptr = poolhd->rxblk_wrptr + 1;
	pr_debug("sblock_release: addr=%x\n", ring->p_rxblks[rxpos].addr);

	if((int)(poolhd->rxblk_wrptr - poolhd->rxblk_rdptr) == 1 &&
			sblock->state == SBLOCK_STATE_READY) {
		/* send smsg to notify the peer side */
		smsg_set(&mevt, channel, SMSG_TYPE_EVENT, SMSG_EVENT_SBLOCK_RELEASE, 0);
		smsg_send(dst, &mevt, -1);
	}

	index = sblock_get_index((blk->addr - ring->rxblk_virt), sblock->rxblksz);
	ring->rxrecord[index] = SBLOCK_BLK_STATE_DONE;

	spin_unlock_irqrestore(&ring->p_rxlock, flags);

	return 0;
}

#if defined(CONFIG_DEBUG_FS)
static int sblock_debug_show(struct seq_file *m, void *private)
{
	struct sblock_mgr *sblock = NULL;
	struct sblock_ring  *ring = NULL;
	volatile struct sblock_ring_header *ringhd = NULL;
	volatile struct sblock_ring_header *poolhd = NULL;
	int i, j;

	for (i = 0; i < SIPC_ID_NR; i++) {
		for (j=0;  j < SMSG_CH_NR; j++) {
			sblock = sblocks[i][j];
			if (!sblock) {
				continue;
			}
			ring = sblock->ring;
			ringhd = (volatile struct sblock_ring_header *)(&sblock->ring->header->ring);
			poolhd = (volatile struct sblock_ring_header *)(&sblock->ring->header->pool);

			seq_printf(m, "sblock dst 0x%0x, channel: 0x%0x, state: %d, smem_virt: 0x%0x, smem_addr: 0x%0x, smem_size: 0x%0x, txblksz: %d, rxblksz: %d \n",
				sblock->dst, sblock->channel, sblock->state,
				(uint32_t)sblock->smem_virt, sblock->smem_addr,
				sblock->smem_size, sblock->txblksz, sblock->rxblksz );
			seq_printf(m, "sblock ring: txblk_virt :0x%0x, rxblk_virt :0x%0x \n",
				(uint32_t)ring->txblk_virt, (uint32_t)ring->rxblk_virt);
			seq_printf(m, "sblock ring header: rxblk_addr :0x%0x, rxblk_rdptr :0x%0x, rxblk_wrptr :0x%0x, rxblk_size :%d, rxblk_count :%d, rxblk_blks: 0x%0x \n",
				ringhd->rxblk_addr, ringhd->rxblk_rdptr,
				ringhd->rxblk_wrptr, ringhd->rxblk_size,
				ringhd->rxblk_count, ringhd->rxblk_blks);
			seq_printf(m, "sblock ring header: txblk_addr :0x%0x, txblk_rdptr :0x%0x, txblk_wrptr :0x%0x, txblk_size :%d, txblk_count :%d, txblk_blks: 0x%0x \n",
				ringhd->txblk_addr, ringhd->txblk_rdptr,
				ringhd->txblk_wrptr, ringhd->txblk_size,
				ringhd->txblk_count, ringhd->txblk_blks );
			seq_printf(m, "sblock pool header: rxblk_addr :0x%0x, rxblk_rdptr :0x%0x, rxblk_wrptr :0x%0x, rxblk_size :%d, rxpool_count :%d, rxblk_blks: 0x%0x \n",
				poolhd->rxblk_addr, poolhd->rxblk_rdptr,
				poolhd->rxblk_wrptr, poolhd->rxblk_size,
				(int)(poolhd->rxblk_wrptr - poolhd->rxblk_rdptr),
				poolhd->rxblk_blks);
			seq_printf(m, "sblock pool header: txblk_addr :0x%0x, txblk_rdptr :0x%0x, txblk_wrptr :0x%0x, txblk_size :%d, txpool_count :%d, txblk_blks: 0x%0x \n",
				poolhd->txblk_addr, poolhd->txblk_rdptr,
				poolhd->txblk_wrptr, poolhd->txblk_size,
				(int)(poolhd->txblk_wrptr - poolhd->txblk_rdptr),
				poolhd->txblk_blks );
		}
	}
	return 0;

}

static int sblock_debug_open(struct inode *inode, struct file *file)
{
	return single_open(file, sblock_debug_show, inode->i_private);
}

static const struct file_operations sblock_debug_fops = {
	.open = sblock_debug_open,
	.read = seq_read,
	.llseek = seq_lseek,
	.release = single_release,
};

int  sblock_init_debugfs(void *root )
{
	if (!root)
		return -ENXIO;
	debugfs_create_file("sblock", S_IRUGO, (struct dentry *)root, NULL, &sblock_debug_fops);
	return 0;
}

#endif /* CONFIG_DEBUG_FS */

EXPORT_SYMBOL(sblock_put);
EXPORT_SYMBOL(sblock_create);
EXPORT_SYMBOL(sblock_destroy);
EXPORT_SYMBOL(sblock_register_notifier);
EXPORT_SYMBOL(sblock_get);
EXPORT_SYMBOL(sblock_send);
EXPORT_SYMBOL(sblock_send_prepare);
EXPORT_SYMBOL(sblock_send_finish);
EXPORT_SYMBOL(sblock_receive);
EXPORT_SYMBOL(sblock_get_free_count);
EXPORT_SYMBOL(sblock_release);

MODULE_AUTHOR("Chen Gaopeng");
MODULE_DESCRIPTION("SIPC/SBLOCK driver");
MODULE_LICENSE("GPL");
示例#4
0
static int axp20x_regulator_probe(struct platform_device *pdev)
{
	struct regulator_dev *rdev;
	struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
	const struct regulator_desc *regulators;
	struct regulator_config config = {
		.dev = pdev->dev.parent,
		.regmap = axp20x->regmap,
		.driver_data = axp20x,
	};
	int ret, i, nregulators;
	u32 workmode;
	const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name;
	const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name;

	switch (axp20x->variant) {
	case AXP202_ID:
	case AXP209_ID:
		regulators = axp20x_regulators;
		nregulators = AXP20X_REG_ID_MAX;
		break;
	case AXP221_ID:
	case AXP223_ID:
		regulators = axp22x_regulators;
		nregulators = AXP22X_REG_ID_MAX;
		break;
	default:
		dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
			axp20x->variant);
		return -EINVAL;
	}

	/* This only sets the dcdc freq. Ignore any errors */
	axp20x_regulator_parse_dt(pdev);

	for (i = 0; i < nregulators; i++) {
		const struct regulator_desc *desc = &regulators[i];
		struct regulator_desc *new_desc;

		/*
		 * Regulators DC1SW and DC5LDO are connected internally,
		 * so we have to handle their supply names separately.
		 *
		 * We always register the regulators in proper sequence,
		 * so the supply names are correctly read. See the last
		 * part of this loop to see where we save the DT defined
		 * name.
		 */
		if (regulators == axp22x_regulators) {
			if (i == AXP22X_DC1SW) {
				new_desc = devm_kzalloc(&pdev->dev,
							sizeof(*desc),
							GFP_KERNEL);
				*new_desc = regulators[i];
				new_desc->supply_name = axp22x_dc1_name;
				desc = new_desc;
			} else if (i == AXP22X_DC5LDO) {
				new_desc = devm_kzalloc(&pdev->dev,
							sizeof(*desc),
							GFP_KERNEL);
				*new_desc = regulators[i];
				new_desc->supply_name = axp22x_dc5_name;
				desc = new_desc;
			}
		}

		rdev = devm_regulator_register(&pdev->dev, desc, &config);
		if (IS_ERR(rdev)) {
			dev_err(&pdev->dev, "Failed to register %s\n",
				regulators[i].name);

			return PTR_ERR(rdev);
		}

		ret = of_property_read_u32(rdev->dev.of_node,
					   "x-powers,dcdc-workmode",
					   &workmode);
		if (!ret) {
			if (axp20x_set_dcdc_workmode(rdev, i, workmode))
				dev_err(&pdev->dev, "Failed to set workmode on %s\n",
					rdev->desc->name);
		}

		/*
		 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
		 */
		if (regulators == axp22x_regulators) {
			/* Can we use rdev->constraints->name instead? */
			if (i == AXP22X_DCDC1)
				of_property_read_string(rdev->dev.of_node,
							"regulator-name",
							&axp22x_dc1_name);
			else if (i == AXP22X_DCDC5)
				of_property_read_string(rdev->dev.of_node,
							"regulator-name",
							&axp22x_dc5_name);
		}
	}

	return 0;
}

static struct platform_driver axp20x_regulator_driver = {
	.probe	= axp20x_regulator_probe,
	.driver	= {
		.name		= "axp20x-regulator",
	},
};

module_platform_driver(axp20x_regulator_driver);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Carlo Caione <*****@*****.**>");
MODULE_DESCRIPTION("Regulator Driver for AXP20X PMIC");
MODULE_ALIAS("platform:axp20x-regulator");
static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
{
	const struct pm8xxx_keypad_platform_data *pdata =
					dev_get_platdata(&pdev->dev);
	const struct matrix_keymap_data *keymap_data;
	struct pmic8xxx_kp *kp;
	int rc;
	u8 ctrl_val;
	struct device *sec_key;

	struct pm_gpio kypd_drv = {
		.direction	= PM_GPIO_DIR_OUT,
		.output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN,
		.output_value	= 0,
		.pull		= PM_GPIO_PULL_NO,
		.vin_sel	= PM_GPIO_VIN_S4,
		.out_strength	= PM_GPIO_STRENGTH_LOW,
		.function	= PM_GPIO_FUNC_1,
		.inv_int_pol	= 1,
	};

	struct pm_gpio kypd_sns = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP_31P5,
		.vin_sel	= PM_GPIO_VIN_S4,
		.out_strength	= PM_GPIO_STRENGTH_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.inv_int_pol	= 1,
	};


	if (!pdata || !pdata->num_cols || !pdata->num_rows ||
		pdata->num_cols > PM8XXX_MAX_COLS ||
		pdata->num_rows > PM8XXX_MAX_ROWS ||
		pdata->num_cols < PM8XXX_MIN_COLS) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	if (!pdata->scan_delay_ms ||
		pdata->scan_delay_ms > MAX_SCAN_DELAY ||
		pdata->scan_delay_ms < MIN_SCAN_DELAY ||
		!is_power_of_2(pdata->scan_delay_ms)) {
		dev_err(&pdev->dev, "invalid keypad scan time supplied\n");
		return -EINVAL;
	}

	if (!pdata->row_hold_ns ||
		pdata->row_hold_ns > MAX_ROW_HOLD_DELAY ||
		pdata->row_hold_ns < MIN_ROW_HOLD_DELAY ||
		((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) {
		dev_err(&pdev->dev, "invalid keypad row hold time supplied\n");
		return -EINVAL;
	}

	if (!pdata->debounce_ms ||
		((pdata->debounce_ms % 5) != 0) ||
		pdata->debounce_ms > MAX_DEBOUNCE_TIME ||
		pdata->debounce_ms < MIN_DEBOUNCE_TIME) {
		dev_err(&pdev->dev, "invalid debounce time supplied\n");
		return -EINVAL;
	}

	keymap_data = pdata->keymap_data;
	if (!keymap_data) {
		dev_err(&pdev->dev, "no keymap data supplied\n");
		return -EINVAL;
	}

	kp = kzalloc(sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	platform_set_drvdata(pdev, kp);

	kp->pdata	= pdata;
	kp->dev		= &pdev->dev;

	kp->input = input_allocate_device();
	if (!kp->input) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		rc = -ENOMEM;
		goto err_alloc_device;
	}

	kp->key_sense_irq = platform_get_irq(pdev, 0);
	if (kp->key_sense_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad sense irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->key_stuck_irq = platform_get_irq(pdev, 1);
	if (kp->key_stuck_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->input->name = pdata->input_name ? : "PMIC8XXX keypad";
	kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0";

	kp->input->dev.parent	= &pdev->dev;

	kp->input->id.bustype	= BUS_I2C;
	kp->input->id.version	= 0x0001;
	kp->input->id.product	= 0x0001;
	kp->input->id.vendor	= 0x0001;

	kp->input->evbit[0]	= BIT_MASK(EV_KEY);

	if (pdata->rep)
		__set_bit(EV_REP, kp->input->evbit);

	kp->input->keycode	= kp->keycodes;
	kp->input->keycodemax	= PM8XXX_MATRIX_MAX_SIZE;
	kp->input->keycodesize	= sizeof(kp->keycodes);
	kp->input->open		= pmic8xxx_kp_open;
	kp->input->close	= pmic8xxx_kp_close;

	matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT,
					kp->input->keycode, kp->input->keybit);

	get_volumekey_matrix(keymap_data,
					&volup_matrix, &voldown_matrix);

	input_set_capability(kp->input, EV_MSC, MSC_SCAN);
	input_set_drvdata(kp->input, kp);

	/* initialize keypad state */
	memset(kp->keystate, 0xff, sizeof(kp->keystate));
	memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

	rc = pmic8xxx_kpd_init(kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to initialize keypad controller\n");
		goto err_get_irq;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start,
					pdata->num_cols, kp, &kypd_sns);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad sense lines\n");
		goto err_gpio_config;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start,
					pdata->num_rows, kp, &kypd_drv);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad drive lines\n");
		goto err_gpio_config;
	}

	rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad sense irq\n");
		goto err_get_irq;
	}

	rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
		goto err_req_stuck_irq;
	}

	rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n");
		goto err_pmic_reg_read;
	}

	rc = request_threaded_irq(MSM_GPIO_KEY_VOLUP_IRQ ,
		NULL, pmic8058_volume_up_irq, IRQF_TRIGGER_RISING |
		IRQF_TRIGGER_FALLING, "vol_up", kp);

	if (rc < 0) {
				dev_err(&pdev->dev, "failed to request vol_up irq\n");
		goto err_req_sense_irq;
	}

	rc = request_threaded_irq(MSM_GPIO_KEY_VOLDOWN_IRQ ,
		NULL, pmic8058_volume_down_irq, IRQF_TRIGGER_RISING |
		IRQF_TRIGGER_FALLING, "vol_down", kp);

	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request vol_down irq\n");
		goto err_req_sense_irq;
	}
	kp->ctrl_reg = ctrl_val;

#if defined CONFIG_MACH_VITAL2REFRESH


	gpio_tlmm_config(GPIO_CFG(MSM_HALL_IC, 1, GPIO_CFG_INPUT,
		GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE);

	input_set_capability(kp->input, EV_SW, SW_LID);

	if (gpio_get_value(MSM_HALL_IC)) {
		input_report_switch(kp->input, SW_LID, 1);
	}
	else {
		input_report_switch(kp->input, SW_LID, 0);
	}

	input_sync(kp->input);

	printk(KERN_INFO "[input_report_switch] slide_int - !gpio_hall_ic %s\n",
			gpio_get_value(MSM_HALL_IC) == 0 ? "OPEN" : "CLOSE");

	rc = request_threaded_irq(MSM_GPIO_TO_INT(MSM_HALL_IC), NULL,
		hall_ic_irq, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
							"hall_ic", kp);

	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request hall_ic irq\n");
		goto err_hall_ic_irq;
	}

#endif
	rc = input_register_device(kp->input);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to register keypad input device\n");
		goto err_pmic_reg_read;
	}

	sec_key = device_create(sec_class, NULL, 0, NULL, "sec_key");
	if (IS_ERR(sec_key))
		pr_err("Failed to create device(sec_key)!\n");

	rc = device_create_file(sec_key, &dev_attr_sec_key_pressed);
	if (rc) {
		pr_err("Failed to create device file - pressed(%s), err(%d)!\n",
				dev_attr_sec_key_pressed.attr.name, rc);
	}

	dev_set_drvdata(sec_key, kp);

	device_init_wakeup(&pdev->dev, pdata->wakeup);

	return 0;

err_pmic_reg_read:
	free_irq(kp->key_stuck_irq, kp);
err_req_stuck_irq:
	free_irq(kp->key_sense_irq, kp);
#if defined CONFIG_MACH_VITAL2REFRESH
err_hall_ic_irq:
#endif
err_req_sense_irq:
err_gpio_config:
err_get_irq:
	input_free_device(kp->input);
err_alloc_device:
	platform_set_drvdata(pdev, NULL);
	kfree(kp);
	return rc;
}

static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
{
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);

	device_init_wakeup(&pdev->dev, 0);
	free_irq(kp->key_stuck_irq, kp);
	free_irq(kp->key_sense_irq, kp);
	input_unregister_device(kp->input);
	kfree(kp);

	platform_set_drvdata(pdev, NULL);
	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int pmic8xxx_kp_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		enable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&input_dev->mutex);

#if defined CONFIG_MACH_VITAL2REFRESH
	enable_irq_wake(MSM_GPIO_TO_INT(MSM_HALL_IC));
	/* to wakeup in case of sleep */
#endif
		if (input_dev->users)
			pmic8xxx_kp_disable(kp);

		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}

static int pmic8xxx_kp_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		disable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&input_dev->mutex);

#if defined CONFIG_MACH_VITAL2REFRESH
	disable_irq_wake(MSM_GPIO_TO_INT(MSM_HALL_IC)); /* to match irq pair */
#endif
	if (input_dev->users)
		pmic8xxx_kp_enable(kp);
		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
			 pmic8xxx_kp_suspend, pmic8xxx_kp_resume);

static struct platform_driver pmic8xxx_kp_driver = {
	.probe		= pmic8xxx_kp_probe,
	.remove		= __devexit_p(pmic8xxx_kp_remove),
	.driver		= {
		.name = PM8XXX_KEYPAD_DEV_NAME,
		.owner = THIS_MODULE,
		.pm = &pm8xxx_kp_pm_ops,
	},
};

static int __init pmic8xxx_kp_init(void)
{
	return platform_driver_register(&pmic8xxx_kp_driver);
}
module_init(pmic8xxx_kp_init);

static void __exit pmic8xxx_kp_exit(void)
{
	platform_driver_unregister(&pmic8xxx_kp_driver);
}
module_exit(pmic8xxx_kp_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PMIC8XXX keypad driver");
MODULE_VERSION("1.0");
MODULE_ALIAS("platform:pmic8xxx_keypad");
MODULE_AUTHOR("Trilok Soni <*****@*****.**>");
/*
 * keypad controller should be initialized in the following sequence
 * only, otherwise it might get into FSM stuck state.
 *
 * - Initialize keypad control parameters, like no. of rows, columns,
 *   timing values etc.,
 * - configure rows and column gpios pull up/down.
 * - set irq edge type.
 * - enable the keypad controller.
 */
static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev)
{
	const struct pm8xxx_keypad_platform_data *pdata =
					dev_get_platdata(&pdev->dev);
	const struct matrix_keymap_data *keymap_data;
	struct pmic8xxx_kp *kp;
	int rc;
	u8 ctrl_val;

	struct pm_gpio kypd_drv = {
		.direction	= PM_GPIO_DIR_OUT,
		.output_buffer	= PM_GPIO_OUT_BUF_OPEN_DRAIN,
		.output_value	= 0,
		.pull		= PM_GPIO_PULL_NO,
		.vin_sel	= PM_GPIO_VIN_S4,
		.out_strength	= PM_GPIO_STRENGTH_LOW,
		.function	= PM_GPIO_FUNC_1,
		.inv_int_pol	= 1,
	};

	struct pm_gpio kypd_sns = {
		.direction	= PM_GPIO_DIR_IN,
		.pull		= PM_GPIO_PULL_UP_31P5,
		.vin_sel	= PM_GPIO_VIN_S4,
		.out_strength	= PM_GPIO_STRENGTH_NO,
		.function	= PM_GPIO_FUNC_NORMAL,
		.inv_int_pol	= 1,
	};


	if (!pdata || !pdata->num_cols || !pdata->num_rows ||
		pdata->num_cols > PM8XXX_MAX_COLS ||
		pdata->num_rows > PM8XXX_MAX_ROWS ||
		pdata->num_cols < PM8XXX_MIN_COLS) {
		dev_err(&pdev->dev, "invalid platform data\n");
		return -EINVAL;
	}

	if (!pdata->scan_delay_ms ||
		pdata->scan_delay_ms > MAX_SCAN_DELAY ||
		pdata->scan_delay_ms < MIN_SCAN_DELAY ||
		!is_power_of_2(pdata->scan_delay_ms)) {
		dev_err(&pdev->dev, "invalid keypad scan time supplied\n");
		return -EINVAL;
	}

	if (!pdata->row_hold_ns ||
		pdata->row_hold_ns > MAX_ROW_HOLD_DELAY ||
		pdata->row_hold_ns < MIN_ROW_HOLD_DELAY ||
		((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) {
		dev_err(&pdev->dev, "invalid keypad row hold time supplied\n");
		return -EINVAL;
	}

	if (!pdata->debounce_ms ||
		((pdata->debounce_ms % 5) != 0) ||
		pdata->debounce_ms > MAX_DEBOUNCE_TIME ||
		pdata->debounce_ms < MIN_DEBOUNCE_TIME) {
		dev_err(&pdev->dev, "invalid debounce time supplied\n");
		return -EINVAL;
	}

	keymap_data = pdata->keymap_data;
	if (!keymap_data) {
		dev_err(&pdev->dev, "no keymap data supplied\n");
		return -EINVAL;
	}

	kp = kzalloc(sizeof(*kp), GFP_KERNEL);
	if (!kp)
		return -ENOMEM;

	platform_set_drvdata(pdev, kp);

	kp->pdata	= pdata;
	kp->dev		= &pdev->dev;

	kp->input = input_allocate_device();
	if (!kp->input) {
		dev_err(&pdev->dev, "unable to allocate input device\n");
		rc = -ENOMEM;
		goto err_alloc_device;
	}

	kp->key_sense_irq = platform_get_irq(pdev, 0);
	if (kp->key_sense_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad sense irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->key_stuck_irq = platform_get_irq(pdev, 1);
	if (kp->key_stuck_irq < 0) {
		dev_err(&pdev->dev, "unable to get keypad stuck irq\n");
		rc = -ENXIO;
		goto err_get_irq;
	}

	kp->input->name = pdata->input_name ? : "PMIC8XXX keypad";
	kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0";

	kp->input->dev.parent	= &pdev->dev;

	kp->input->id.bustype	= BUS_I2C;
	kp->input->id.version	= 0x0001;
	kp->input->id.product	= 0x0001;
	kp->input->id.vendor	= 0x0001;

	kp->input->evbit[0]	= BIT_MASK(EV_KEY);

	if (pdata->rep)
		__set_bit(EV_REP, kp->input->evbit);

	kp->input->keycode	= kp->keycodes;
	kp->input->keycodemax	= PM8XXX_MATRIX_MAX_SIZE;
	kp->input->keycodesize	= sizeof(kp->keycodes);
	kp->input->open		= pmic8xxx_kp_open;
	kp->input->close	= pmic8xxx_kp_close;

	matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT,
					kp->input->keycode, kp->input->keybit);

	input_set_capability(kp->input, EV_MSC, MSC_SCAN);
	input_set_drvdata(kp->input, kp);

	/* initialize keypad state */
	memset(kp->keystate, 0xff, sizeof(kp->keystate));
	memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate));

	rc = pmic8xxx_kpd_init(kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to initialize keypad controller\n");
		goto err_get_irq;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start,
					pdata->num_cols, kp, &kypd_sns);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad sense lines\n");
		goto err_gpio_config;
	}

	rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start,
					pdata->num_rows, kp, &kypd_drv);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to configure keypad drive lines\n");
		goto err_gpio_config;
	}

	rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad sense irq\n");
		goto err_get_irq;
	}

	rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq,
				 IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to request keypad stuck irq\n");
		goto err_req_stuck_irq;
	}

	rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL);
	if (rc < 0) {
		dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n");
		goto err_pmic_reg_read;
	}

	kp->ctrl_reg = ctrl_val;

	rc = input_register_device(kp->input);
	if (rc < 0) {
		dev_err(&pdev->dev, "unable to register keypad input device\n");
		goto err_pmic_reg_read;
	}

	device_init_wakeup(&pdev->dev, pdata->wakeup);

	return 0;

err_pmic_reg_read:
	free_irq(kp->key_stuck_irq, kp);
err_req_stuck_irq:
	free_irq(kp->key_sense_irq, kp);
err_gpio_config:
err_get_irq:
	input_free_device(kp->input);
err_alloc_device:
	platform_set_drvdata(pdev, NULL);
	kfree(kp);
	return rc;
}

static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev)
{
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);

	device_init_wakeup(&pdev->dev, 0);
	free_irq(kp->key_stuck_irq, kp);
	free_irq(kp->key_sense_irq, kp);
	input_unregister_device(kp->input);
	kfree(kp);

	platform_set_drvdata(pdev, NULL);
	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int pmic8xxx_kp_suspend(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		enable_irq_wake(kp->key_sense_irq);
	} else {
		mutex_lock(&input_dev->mutex);

		if (input_dev->users)
			pmic8xxx_kp_disable(kp);

		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}

static int pmic8xxx_kp_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct pmic8xxx_kp *kp = platform_get_drvdata(pdev);
	struct input_dev *input_dev = kp->input;

	if (device_may_wakeup(dev)) {
		disable_irq_wake(kp->key_sense_irq);
		pmic8xxx_kp_enable(kp);
	} else {
		mutex_lock(&input_dev->mutex);

		if (input_dev->users)
			pmic8xxx_kp_enable(kp);

		mutex_unlock(&input_dev->mutex);
	}

	return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
			 pmic8xxx_kp_suspend, pmic8xxx_kp_resume);

static struct platform_driver pmic8xxx_kp_driver = {
	.probe		= pmic8xxx_kp_probe,
	.remove		= __devexit_p(pmic8xxx_kp_remove),
	.driver		= {
		.name = PM8XXX_KEYPAD_DEV_NAME,
		.owner = THIS_MODULE,
		.pm = &pm8xxx_kp_pm_ops,
	},
};

static int __init pmic8xxx_kp_init(void)
{
	return platform_driver_register(&pmic8xxx_kp_driver);
}
module_init(pmic8xxx_kp_init);

static void __exit pmic8xxx_kp_exit(void)
{
	platform_driver_unregister(&pmic8xxx_kp_driver);
}
module_exit(pmic8xxx_kp_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("PMIC8XXX keypad driver");
MODULE_VERSION("1.0");
MODULE_ALIAS("platform:pmic8xxx_keypad");
MODULE_AUTHOR("Trilok Soni <*****@*****.**>");
示例#7
0
static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
{
	static const struct ata_port_info info = {
		.flags		= ATA_FLAG_SLAVE_POSS,

		.pio_mask	= 0x1f,
		.mwdma_mask	= 0x07,
		.udma_mask 	= ATA_UDMA5,

		.port_ops	= &marvell_ops,
	};
	static const struct ata_port_info info_sata = {
		/* Slave possible as its magically mapped not real */
		.flags		= ATA_FLAG_SLAVE_POSS,

		.pio_mask	= 0x1f,
		.mwdma_mask	= 0x07,
		.udma_mask 	= ATA_UDMA6,

		.port_ops	= &marvell_ops,
	};
	const struct ata_port_info *ppi[] = { &info, &info_sata };

	if (pdev->device == 0x6101)
		ppi[1] = &ata_dummy_port_info;

	return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL);
}

static const struct pci_device_id marvell_pci_tbl[] = {
	{ PCI_DEVICE(0x11AB, 0x6101), },
	{ PCI_DEVICE(0x11AB, 0x6121), },
	{ PCI_DEVICE(0x11AB, 0x6123), },
	{ PCI_DEVICE(0x11AB, 0x6145), },
	{ }	/* terminate list */
};

static struct pci_driver marvell_pci_driver = {
	.name			= DRV_NAME,
	.id_table		= marvell_pci_tbl,
	.probe			= marvell_init_one,
	.remove			= ata_pci_remove_one,
#ifdef CONFIG_PM
	.suspend		= ata_pci_device_suspend,
	.resume			= ata_pci_device_resume,
#endif
};

static int __init marvell_init(void)
{
	return pci_register_driver(&marvell_pci_driver);
}

static void __exit marvell_exit(void)
{
	pci_unregister_driver(&marvell_pci_driver);
}

module_init(marvell_init);
module_exit(marvell_exit);

MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("SCSI low-level driver for Marvell ATA in legacy mode");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, marvell_pci_tbl);
MODULE_VERSION(DRV_VERSION);
示例#8
0
static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	unsigned long arg)
{
	static struct watchdog_info ident =
	{
		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "Acquire WDT",
	};

	switch(cmd)
	{
	case WDIOC_GETSUPPORT:
	  return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ? -EFAULT : 0;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
	  return put_user(0, (int *)arg);

	case WDIOC_KEEPALIVE:
	  acq_ping();
	  return 0;

	case WDIOC_GETTIMEOUT:
	  return put_user(WATCHDOG_TIMEOUT, (int *)arg);

	case WDIOC_SETOPTIONS:
	{
	    int options, retval = -EINVAL;

	    if (get_user(options, (int *)arg))
	      return -EFAULT;

	    if (options & WDIOS_DISABLECARD)
	    {
	      acq_stop();
	      retval = 0;
	    }

	    if (options & WDIOS_ENABLECARD)
	    {
	      acq_ping();
	      retval = 0;
	    }

	    return retval;
	}

	default:
	  return -ENOIOCTLCMD;
	}
}

static int acq_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &acq_is_open))
		return -EBUSY;

	if (nowayout)
		__module_get(THIS_MODULE);

	/* Activate */
	acq_ping();
	return 0;
}

static int acq_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		acq_stop();
	} else {
		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
		acq_ping();
	}
	clear_bit(0, &acq_is_open);
	expect_close = 0;
	return 0;
}

/*
 *	Notifier for system down
 */

static int acq_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT) {
		/* Turn the WDT off */
		acq_stop();
	}
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */

static struct file_operations acq_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= acq_write,
	.ioctl		= acq_ioctl,
	.open		= acq_open,
	.release	= acq_close,
};

static struct miscdevice acq_miscdev=
{
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &acq_fops,
};

/*
 *	The WDT card needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block acq_notifier =
{
	.notifier_call = acq_notify_sys,
	.next = NULL,
	.priority = 0,
};

static int __init acq_init(void)
{
	int ret;

	printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");

	if (wdt_stop != wdt_start) {
		if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
				wdt_stop);
			ret = -EIO;
			goto out;
		}
	}

	if (!request_region(wdt_start, 1, WATCHDOG_NAME)) {
		printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
			wdt_start);
		ret = -EIO;
		goto unreg_stop;
	}

        ret = register_reboot_notifier(&acq_notifier);
        if (ret != 0) {
                printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
                        ret);
                goto unreg_regions;
        }
                                                                                                 
        ret = misc_register(&acq_miscdev);
        if (ret != 0) {
                printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
                        WATCHDOG_MINOR, ret);
                goto unreg_reboot;
        }
                                                                                                 
        printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
                nowayout);
                                                                                                 
out:
        return ret;
unreg_reboot:
        unregister_reboot_notifier(&acq_notifier);
unreg_regions:
        release_region(wdt_start, 1);
unreg_stop:
        if (wdt_stop != wdt_start)
                release_region(wdt_stop, 1);
        goto out;
}

static void __exit acq_exit(void)
{
	misc_deregister(&acq_miscdev);
	unregister_reboot_notifier(&acq_notifier);
	if(wdt_stop != wdt_start)
		release_region(wdt_stop,1);
	release_region(wdt_start,1);
}

module_init(acq_init);
module_exit(acq_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Unkown");
MODULE_DESCRIPTION("Acquire Single Board Computer Watchdog Timer driver");
示例#9
0
static int
omap_wdt_ioctl(struct inode *inode, struct file *file,
	unsigned int cmd, unsigned long arg)
{
	int new_margin;
	static struct watchdog_info ident = {
		.identity = "OMAP Watchdog",
		.options = WDIOF_SETTIMEOUT,
		.firmware_version = 0,
	};

	switch (cmd) {
	default:
		return -ENOIOCTLCMD;
	case WDIOC_GETSUPPORT:
		return copy_to_user((struct watchdog_info __user *)arg, &ident,
				sizeof(ident));
	case WDIOC_GETSTATUS:
		return put_user(0, (int __user *)arg);
	case WDIOC_GETBOOTSTATUS:
		if (cpu_is_omap16xx())
			return put_user(omap_readw(ARM_SYSST),
					(int __user *)arg);
		if (cpu_is_omap24xx())
			return put_user(omap_prcm_get_reset_sources(),
					(int __user *)arg);
	case WDIOC_KEEPALIVE:
		omap_wdt_ping();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_margin, (int __user *)arg))
			return -EFAULT;
		omap_wdt_adjust_timeout(new_margin);

		omap_wdt_disable();
		omap_wdt_set_timeout();
		omap_wdt_enable();

		omap_wdt_ping();
		/* Fall */
	case WDIOC_GETTIMEOUT:
		return put_user(timer_margin, (int __user *)arg);
	}
}

static const struct file_operations omap_wdt_fops = {
	.owner = THIS_MODULE,
	.write = omap_wdt_write,
	.ioctl = omap_wdt_ioctl,
	.open = omap_wdt_open,
	.release = omap_wdt_release,
};

static struct miscdevice omap_wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &omap_wdt_fops
};

static int __init omap_wdt_probe(struct platform_device *pdev)
{
	struct resource *res, *mem;
	int ret;

	/* reserve static register mappings */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENOENT;

	mem = request_mem_region(res->start, res->end - res->start + 1,
				 pdev->name);
	if (mem == NULL)
		return -EBUSY;

	platform_set_drvdata(pdev, mem);

	omap_wdt_users = 0;

	if (cpu_is_omap16xx()) {
		armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
		if (IS_ERR(armwdt_ck)) {
			ret = PTR_ERR(armwdt_ck);
			armwdt_ck = NULL;
			goto fail;
		}
	}

	if (cpu_is_omap24xx()) {
		mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
		if (IS_ERR(mpu_wdt_ick)) {
			ret = PTR_ERR(mpu_wdt_ick);
			mpu_wdt_ick = NULL;
			goto fail;
		}
		mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
		if (IS_ERR(mpu_wdt_fck)) {
			ret = PTR_ERR(mpu_wdt_fck);
			mpu_wdt_fck = NULL;
			goto fail;
		}
	}

	omap_wdt_disable();
	omap_wdt_adjust_timeout(timer_margin);

	omap_wdt_miscdev.parent = &pdev->dev;
	ret = misc_register(&omap_wdt_miscdev);
	if (ret)
		goto fail;

	pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);

	/* autogate OCP interface clock */
	omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
	return 0;

fail:
	if (armwdt_ck)
		clk_put(armwdt_ck);
	if (mpu_wdt_ick)
		clk_put(mpu_wdt_ick);
	if (mpu_wdt_fck)
		clk_put(mpu_wdt_fck);
	release_resource(mem);
	return ret;
}

static void omap_wdt_shutdown(struct platform_device *pdev)
{
	omap_wdt_disable();
}

static int omap_wdt_remove(struct platform_device *pdev)
{
	struct resource *mem = platform_get_drvdata(pdev);
	misc_deregister(&omap_wdt_miscdev);
	release_resource(mem);
	if (armwdt_ck)
		clk_put(armwdt_ck);
	if (mpu_wdt_ick)
		clk_put(mpu_wdt_ick);
	if (mpu_wdt_fck)
		clk_put(mpu_wdt_fck);
	return 0;
}

#ifdef	CONFIG_PM

/* REVISIT ... not clear this is the best way to handle system suspend; and
 * it's very inappropriate for selective device suspend (e.g. suspending this
 * through sysfs rather than by stopping the watchdog daemon).  Also, this
 * may not play well enough with NOWAYOUT...
 */

static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
{
	if (omap_wdt_users)
		omap_wdt_disable();
	return 0;
}

static int omap_wdt_resume(struct platform_device *pdev)
{
	if (omap_wdt_users) {
		omap_wdt_enable();
		omap_wdt_ping();
	}
	return 0;
}

#else
#define	omap_wdt_suspend	NULL
#define	omap_wdt_resume		NULL
#endif

static struct platform_driver omap_wdt_driver = {
	.probe		= omap_wdt_probe,
	.remove		= omap_wdt_remove,
	.shutdown	= omap_wdt_shutdown,
	.suspend	= omap_wdt_suspend,
	.resume		= omap_wdt_resume,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= "omap_wdt",
	},
};

static int __init omap_wdt_init(void)
{
	return platform_driver_register(&omap_wdt_driver);
}

static void __exit omap_wdt_exit(void)
{
	platform_driver_unregister(&omap_wdt_driver);
}

module_init(omap_wdt_init);
module_exit(omap_wdt_exit);

MODULE_AUTHOR("George G. Davis");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
int __init i2c_dev_init(void)
{
    int res;

    printk(KERN_INFO "i2c-dev.o: i2c /dev entries driver module version %s (%s)\n", I2C_VERSION, I2C_DATE);

    i2cdev_initialized = 0;
#ifdef CONFIG_DEVFS_FS
    if (devfs_register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops)) {
#else
    if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
#endif
        printk(KERN_ERR "i2c-dev.o: unable to get major %d for i2c bus\n",
               I2C_MAJOR);
        return -EIO;
    }
#ifdef CONFIG_DEVFS_FS
    devfs_handle = devfs_mk_dir(NULL, "i2c", NULL);
#endif
    i2cdev_initialized ++;

    if ((res = i2c_add_driver(&i2cdev_driver))) {
        printk(KERN_ERR "i2c-dev.o: Driver registration failed, module not inserted.\n");
        i2cdev_cleanup();
        return res;
    }
    i2cdev_initialized ++;
    return 0;
}

int i2cdev_cleanup(void)
{
    int res;

    if (i2cdev_initialized >= 2) {
        if ((res = i2c_del_driver(&i2cdev_driver))) {
            printk("i2c-dev.o: Driver deregistration failed, "
                   "module not removed.\n");
            return res;
        }
        i2cdev_initialized --;
    }

    if (i2cdev_initialized >= 1) {
#ifdef CONFIG_DEVFS_FS
        devfs_unregister(devfs_handle);
        if ((res = devfs_unregister_chrdev(I2C_MAJOR, "i2c"))) {
#else
        if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) {
#endif
            printk("i2c-dev.o: unable to release major %d for i2c bus\n",
                   I2C_MAJOR);
            return res;
        }
        i2cdev_initialized --;
    }
    return 0;
}

EXPORT_NO_SYMBOLS;

#ifdef MODULE

MODULE_AUTHOR("Frodo Looijaard <*****@*****.**> and Simon G. Vogl <*****@*****.**>");
MODULE_DESCRIPTION("I2C /dev entries driver");
MODULE_LICENSE("GPL");

int init_module(void)
{
    return i2c_dev_init();
}

int cleanup_module(void)
{
    return i2cdev_cleanup();
}
示例#11
0
文件: act_police.c 项目: krzk/linux
static int tcf_act_police_dump(struct sk_buff *skb, struct tc_action *a,
			       int bind, int ref)
{
	unsigned char *b = skb_tail_pointer(skb);
	struct tcf_police *police = to_police(a);
	struct tc_police opt = {
		.index = police->tcf_index,
		.action = police->tcf_action,
		.mtu = police->tcfp_mtu,
		.burst = PSCHED_NS2TICKS(police->tcfp_burst),
		.refcnt = police->tcf_refcnt - ref,
		.bindcnt = police->tcf_bindcnt - bind,
	};
	struct tcf_t t;

	if (police->rate_present)
		psched_ratecfg_getrate(&opt.rate, &police->rate);
	if (police->peak_present)
		psched_ratecfg_getrate(&opt.peakrate, &police->peak);
	if (nla_put(skb, TCA_POLICE_TBF, sizeof(opt), &opt))
		goto nla_put_failure;
	if (police->tcfp_result &&
	    nla_put_u32(skb, TCA_POLICE_RESULT, police->tcfp_result))
		goto nla_put_failure;
	if (police->tcfp_ewma_rate &&
	    nla_put_u32(skb, TCA_POLICE_AVRATE, police->tcfp_ewma_rate))
		goto nla_put_failure;

	t.install = jiffies_to_clock_t(jiffies - police->tcf_tm.install);
	t.lastuse = jiffies_to_clock_t(jiffies - police->tcf_tm.lastuse);
	t.firstuse = jiffies_to_clock_t(jiffies - police->tcf_tm.firstuse);
	t.expires = jiffies_to_clock_t(police->tcf_tm.expires);
	if (nla_put_64bit(skb, TCA_POLICE_TM, sizeof(t), &t, TCA_POLICE_PAD))
		goto nla_put_failure;

	return skb->len;

nla_put_failure:
	nlmsg_trim(skb, b);
	return -1;
}

static int tcf_police_search(struct net *net, struct tc_action **a, u32 index,
			     struct netlink_ext_ack *extack)
{
	struct tc_action_net *tn = net_generic(net, police_net_id);

	return tcf_idr_search(tn, a, index);
}

MODULE_AUTHOR("Alexey Kuznetsov");
MODULE_DESCRIPTION("Policing actions");
MODULE_LICENSE("GPL");

static struct tc_action_ops act_police_ops = {
	.kind		=	"police",
	.type		=	TCA_ID_POLICE,
	.owner		=	THIS_MODULE,
	.act		=	tcf_act_police,
	.dump		=	tcf_act_police_dump,
	.init		=	tcf_act_police_init,
	.walk		=	tcf_act_police_walker,
	.lookup		=	tcf_police_search,
	.size		=	sizeof(struct tcf_police),
};

static __net_init int police_init_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, police_net_id);

	return tc_action_net_init(tn, &act_police_ops);
}

static void __net_exit police_exit_net(struct list_head *net_list)
{
	tc_action_net_exit(net_list, police_net_id);
}

static struct pernet_operations police_net_ops = {
	.init = police_init_net,
	.exit_batch = police_exit_net,
	.id   = &police_net_id,
	.size = sizeof(struct tc_action_net),
};

static int __init police_init_module(void)
{
	return tcf_register_action(&act_police_ops, &police_net_ops);
}

static void __exit police_cleanup_module(void)
{
	tcf_unregister_action(&act_police_ops, &police_net_ops);
}

module_init(police_init_module);
module_exit(police_cleanup_module);
示例#12
0
static int cdfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, struct vfsmount *mnt) {
  return get_sb_bdev(fs_type, flags, dev_name, data, cdfs_fill_super, mnt);
#else
static struct super_block *cdfs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) {
  return get_sb_bdev(fs_type, flags, dev_name, data, cdfs_fill_super);
#endif
}

static struct file_system_type cdfs_fs_type = {
  .owner    = THIS_MODULE,
  .name     = "cdfs",
  .get_sb   = cdfs_get_sb,
  .kill_sb  = kill_block_super,
  .fs_flags = FS_REQUIRES_DEV
};
#endif

/******************************************************/

MODULE_AUTHOR("Michiel Ronsse ([email protected])");
MODULE_DESCRIPTION("CDfs: a CD filesystem");
MODULE_LICENSE("GPL"); 

#ifdef OLD_KERNEL
EXPORT_NO_SYMBOLS;
#endif

/******************************************************************/

static int __init cdfs_init(void) {
  int err;
  PRINT("init_module (insmod)\n");

  printk(FSNAME" "VERSION" loaded.\n");
 
  // register file system
  err = register_filesystem(&cdfs_fs_type);
  if (err < 0) return err;

  // register /proc entry
  if ((cdfs_proc_entry = create_proc_entry(FSNAME, 0, NULL )))
    cdfs_proc_entry->proc_fops = &proc_cdfs_operations;
  cdfs_proc_cd=NULL;

  // start kernel thread
  if ((kcdfsd_pid = kernel_thread(kcdfsd_thread, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND)) >0 ) {
    return 0;
  } else {
    printk(FSNAME" kernel_thread failed.\n");
    if (cdfs_proc_entry) remove_proc_entry(FSNAME, NULL);
    unregister_filesystem(&cdfs_fs_type);
    return -1;
  }
}

/******************************************************************/

static void __exit cdfs_exit(void) {
  PRINT("cleanup_module (rmmod)\n");
  kcdfsd_cleanup_thread();
  if (cdfs_proc_entry) remove_proc_entry(FSNAME, NULL);
  unregister_filesystem(&cdfs_fs_type);
}
示例#13
0
static int
mxc_wdt_ioctl(struct inode *inode, struct file *file,
	      unsigned int cmd, unsigned long arg)
{
	int new_margin;
	int bootr;

	static struct watchdog_info ident = {
		.identity = "MXC Watchdog",
		.options = WDIOF_SETTIMEOUT,
		.firmware_version = 0,
	};

	switch (cmd) {
	default:
		return -ENOIOCTLCMD;
	case WDIOC_GETSUPPORT:
		return copy_to_user((struct watchdog_info __user *)arg, &ident,
				    sizeof(ident));
	case WDIOC_GETSTATUS:
		return put_user(0, (int __user *)arg);
	case WDIOC_GETBOOTSTATUS:
		bootr = mxc_wdt_get_bootreason(wdt_base_reg);
		return put_user(bootr, (int __user *)arg);
	case WDIOC_KEEPALIVE:
		mxc_wdt_ping(wdt_base_reg);
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_margin, (int __user *)arg))
			return -EFAULT;

		mxc_wdt_adjust_timeout(new_margin);
		mxc_wdt_disable(wdt_base_reg);
		mxc_wdt_set_timeout(wdt_base_reg);
		mxc_wdt_enable(wdt_base_reg);
		mxc_wdt_ping(wdt_base_reg);
		return 0;

	case WDIOC_GETTIMEOUT:
		mxc_wdt_ping(wdt_base_reg);
		new_margin = mxc_wdt_get_timeout(wdt_base_reg);
		return put_user(new_margin, (int __user *)arg);
	}
}

static struct file_operations mxc_wdt_fops = {
	.owner = THIS_MODULE,
	.write = mxc_wdt_write,
	.ioctl = mxc_wdt_ioctl,
	.open = mxc_wdt_open,
	.release = mxc_wdt_release,
};

static struct miscdevice mxc_wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &mxc_wdt_fops
};

static int __init mxc_wdt_probe(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct resource *res, *mem;
	int ret;

	/* reserve static register mappings */
	res = platform_get_resource(pdev, IORESOURCE_MEM, dev_num);
	if (!res)
		return -ENOENT;

	mem = request_mem_region(res->start, res->end - res->start + 1,
				 pdev->name);
	if (mem == NULL)
		return -EBUSY;

	dev_set_drvdata(dev, mem);

	wdt_base_reg = IO_ADDRESS(res->start);
	mxc_wdt_disable(wdt_base_reg);
	mxc_wdt_adjust_timeout(timer_margin);

	mxc_wdt_users = 0;

	mxc_wdt_miscdev.dev = dev;

	ret = misc_register(&mxc_wdt_miscdev);
	if (ret)
		goto fail;

	pr_info("MXC Watchdog # %d Timer: initial timeout %d sec\n", dev_num,
		timer_margin);

	return 0;

      fail:
	release_resource(mem);
	pr_info("MXC Watchdog Probe failed\n");
	return ret;
}

static void mxc_wdt_shutdown(struct device *dev)
{
	struct resource *res = dev_get_drvdata(dev);
	mxc_wdt_disable(res->start);
	pr_info("MXC Watchdog # %d shutdown\n", dev_num);
}

static int __exit mxc_wdt_remove(struct device *dev)
{
	struct resource *mem = dev_get_drvdata(dev);
	misc_deregister(&mxc_wdt_miscdev);
	release_resource(mem);
	pr_info("MXC Watchdog # %d removed\n", dev_num);
	return 0;
}

#ifdef	CONFIG_PM

/* REVISIT ... not clear this is the best way to handle system suspend; and
 * it's very inappropriate for selective device suspend (e.g. suspending this
 * through sysfs rather than by stopping the watchdog daemon).  Also, this
 * may not play well enough with NOWAYOUT...
 */

static int mxc_wdt_suspend(struct device *dev, u32 state, u32 level)
{
	struct resource *res = dev_get_drvdata(dev);
	if (level == SUSPEND_POWER_DOWN && mxc_wdt_users)
		mxc_wdt_disable(res->start);
	return 0;
}

static int mxc_wdt_resume(struct device *dev, u32 level)
{
	struct resource *res = dev_get_drvdata(dev);
	if (level == RESUME_POWER_ON && mxc_wdt_users) {
		mxc_wdt_enable(res->start);
		mxc_wdt_ping(res->start);
	}
	return 0;
}

#else
#define	mxc_wdt_suspend	NULL
#define	mxc_wdt_resume		NULL
#endif

static struct device_driver mxc_wdt_driver = {
	.name = "mxc_wdt",
	.bus = &platform_bus_type,
	.probe = mxc_wdt_probe,
	.shutdown = mxc_wdt_shutdown,
	.remove = __exit_p(mxc_wdt_remove),
	.suspend = mxc_wdt_suspend,
	.resume = mxc_wdt_resume,
};

static int __init mxc_wdt_init(void)
{
	pr_info("MXC WatchDog Driver %s\n", DVR_VER);

	if ((timer_margin < TIMER_MARGIN_MIN) ||
	    (timer_margin > TIMER_MARGIN_MAX)) {
		pr_info("MXC watchdog error. wrong timer_margin %d\n",
			timer_margin);
		pr_info("    Range: %d to %d seconds\n", TIMER_MARGIN_MIN,
			TIMER_MARGIN_MAX);
		return -EINVAL;
	}

	return driver_register(&mxc_wdt_driver);
}

static void __exit mxc_wdt_exit(void)
{
	driver_unregister(&mxc_wdt_driver);
	pr_info("MXC WatchDog Driver removed\n");
}

module_init(mxc_wdt_init);
module_exit(mxc_wdt_exit);

MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
示例#14
0
static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a,
			 int bind, int ref)
{
	unsigned char *b = skb_tail_pointer(skb);
	struct tcf_defact *d = to_defact(a);
	struct tc_defact opt = {
		.index   = d->tcf_index,
		.refcnt  = d->tcf_refcnt - ref,
		.bindcnt = d->tcf_bindcnt - bind,
		.action  = d->tcf_action,
	};
	struct tcf_t t;

	if (nla_put(skb, TCA_DEF_PARMS, sizeof(opt), &opt) ||
	    nla_put_string(skb, TCA_DEF_DATA, d->tcfd_defdata))
		goto nla_put_failure;

	tcf_tm_dump(&t, &d->tcf_tm);
	if (nla_put_64bit(skb, TCA_DEF_TM, sizeof(t), &t, TCA_DEF_PAD))
		goto nla_put_failure;
	return skb->len;

nla_put_failure:
	nlmsg_trim(skb, b);
	return -1;
}

static int tcf_simp_walker(struct net *net, struct sk_buff *skb,
			   struct netlink_callback *cb, int type,
			   const struct tc_action_ops *ops)
{
	struct tc_action_net *tn = net_generic(net, simp_net_id);

	return tcf_generic_walker(tn, skb, cb, type, ops);
}

static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index)
{
	struct tc_action_net *tn = net_generic(net, simp_net_id);

	return tcf_hash_search(tn, a, index);
}

static struct tc_action_ops act_simp_ops = {
	.kind		=	"simple",
	.type		=	TCA_ACT_SIMP,
	.owner		=	THIS_MODULE,
	.act		=	tcf_simp,
	.dump		=	tcf_simp_dump,
	.cleanup	=	tcf_simp_release,
	.init		=	tcf_simp_init,
	.walk		=	tcf_simp_walker,
	.lookup		=	tcf_simp_search,
	.size		=	sizeof(struct tcf_defact),
};

static __net_init int simp_init_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, simp_net_id);

	return tc_action_net_init(tn, &act_simp_ops, SIMP_TAB_MASK);
}

static void __net_exit simp_exit_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, simp_net_id);

	tc_action_net_exit(tn);
}

static struct pernet_operations simp_net_ops = {
	.init = simp_init_net,
	.exit = simp_exit_net,
	.id   = &simp_net_id,
	.size = sizeof(struct tc_action_net),
};

MODULE_AUTHOR("Jamal Hadi Salim(2005)");
MODULE_DESCRIPTION("Simple example action");
MODULE_LICENSE("GPL");

static int __init simp_init_module(void)
{
	int ret = tcf_register_action(&act_simp_ops, &simp_net_ops);
	if (!ret)
		pr_info("Simple TC action Loaded\n");
	return ret;
}

static void __exit simp_cleanup_module(void)
{
	tcf_unregister_action(&act_simp_ops, &simp_net_ops);
}

module_init(simp_init_module);
module_exit(simp_cleanup_module);
示例#15
0
static long wb_smsc_wdt_ioctl(struct file *file,
					unsigned int cmd, unsigned long arg)
{
	int new_timeout;

	union {
		struct watchdog_info __user *ident;
		int __user *i;
	} uarg;

	static const struct watchdog_info ident = {
		.options =		WDIOF_KEEPALIVEPING |
					WDIOF_SETTIMEOUT |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		"SMsC 37B787 Watchdog",
	};

	uarg.i = (int __user *)arg;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(uarg.ident, &ident, sizeof(ident))
								? -EFAULT : 0;
	case WDIOC_GETSTATUS:
		return put_user(wb_smsc_wdt_status(), uarg.i);
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, uarg.i);
	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;

		if (get_user(options, uarg.i))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			wb_smsc_wdt_disable();
			retval = 0;
		}
		if (options & WDIOS_ENABLECARD) {
			wb_smsc_wdt_enable();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		wb_smsc_wdt_reset_timer();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, uarg.i))
			return -EFAULT;
		/* the API states this is given in secs */
		if (unit == UNIT_MINUTE)
			new_timeout /= 60;
		if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
			return -EINVAL;
		timeout = new_timeout;
		wb_smsc_wdt_set_timeout(timeout);
		/* fall through - and return the new timeout... */
	case WDIOC_GETTIMEOUT:
		new_timeout = timeout;
		if (unit == UNIT_MINUTE)
			new_timeout *= 60;
		return put_user(new_timeout, uarg.i);
	default:
		return -ENOTTY;
	}
}

/* -- Notifier funtions -----------------------------------------*/

static int wb_smsc_wdt_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT) {
		/* set timeout to 0, to avoid possible race-condition */
		timeout = 0;
		wb_smsc_wdt_disable();
	}
	return NOTIFY_DONE;
}

/* -- Module's structures ---------------------------------------*/

static const struct file_operations wb_smsc_wdt_fops = {
	.owner	  = THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wb_smsc_wdt_write,
	.unlocked_ioctl	= wb_smsc_wdt_ioctl,
	.open		= wb_smsc_wdt_open,
	.release	= wb_smsc_wdt_release,
};

static struct notifier_block wb_smsc_wdt_notifier = {
	.notifier_call  = wb_smsc_wdt_notify_sys,
};

static struct miscdevice wb_smsc_wdt_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &wb_smsc_wdt_fops,
};

/* -- Module init functions -------------------------------------*/

/* module's "constructor" */

static int __init wb_smsc_wdt_init(void)
{
	int ret;

	pr_info("SMsC 37B787 watchdog component driver "
		VERSION " initialising...\n");

	if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
		pr_err("Unable to register IO port %#x\n", IOPORT);
		ret = -EBUSY;
		goto out_pnp;
	}

	/* set new maximum, if it's too big */
	if (timeout > MAX_TIMEOUT)
		timeout = MAX_TIMEOUT;

	/* init the watchdog timer */
	wb_smsc_wdt_initialize();

	ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
	if (ret) {
		pr_err("Unable to register reboot notifier err = %d\n", ret);
		goto out_io;
	}

	ret = misc_register(&wb_smsc_wdt_miscdev);
	if (ret) {
		pr_err("Unable to register miscdev on minor %d\n",
		       WATCHDOG_MINOR);
		goto out_rbt;
	}

	/* output info */
	pr_info("Timeout set to %d %s\n",
		timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
	pr_info("Watchdog initialized and sleeping (nowayout=%d)...\n",
		nowayout);
out_clean:
	return ret;

out_rbt:
	unregister_reboot_notifier(&wb_smsc_wdt_notifier);

out_io:
	release_region(IOPORT, IOPORT_SIZE);

out_pnp:
	goto out_clean;
}

/* module's "destructor" */

static void __exit wb_smsc_wdt_exit(void)
{
	/* Stop the timer before we leave */
	if (!nowayout) {
		wb_smsc_wdt_shutdown();
		pr_info("Watchdog disabled\n");
	}

	misc_deregister(&wb_smsc_wdt_miscdev);
	unregister_reboot_notifier(&wb_smsc_wdt_notifier);
	release_region(IOPORT, IOPORT_SIZE);

	pr_info("SMsC 37B787 watchdog component driver removed\n");
}

module_init(wb_smsc_wdt_init);
module_exit(wb_smsc_wdt_exit);

MODULE_AUTHOR("Sven Anders <*****@*****.**>");
MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version "
								VERSION ")");
MODULE_LICENSE("GPL");

#ifdef SMSC_SUPPORT_MINUTES
module_param(unit, int, 0);
MODULE_PARM_DESC(unit,
		"set unit to use, 0=seconds or 1=minutes, default is 0");
#endif

module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");

module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout,
		"Watchdog cannot be stopped once started (default="
				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
示例#16
0
static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
{
	static const struct ata_port_info info = {
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.udma_mask = 0x07,
		.port_ops = &cs5530_port_ops
	};
	/* The docking connector doesn't do UDMA, and it seems not MWDMA */
	static const struct ata_port_info info_palmax_secondary = {
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.port_ops = &cs5530_port_ops
	};
	const struct ata_port_info *ppi[] = { &info, NULL };
	int rc;

	rc = pcim_enable_device(pdev);
	if (rc)
		return rc;

	/* Chip initialisation */
	if (cs5530_init_chip())
		return -ENODEV;

	if (cs5530_is_palmax())
		ppi[1] = &info_palmax_secondary;

	/* Now kick off ATA set up */
	return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL);
}

#ifdef CONFIG_PM
static int cs5530_reinit_one(struct pci_dev *pdev)
{
	struct ata_host *host = dev_get_drvdata(&pdev->dev);
	int rc;

	rc = ata_pci_device_do_resume(pdev);
	if (rc)
		return rc;

	/* If we fail on resume we are doomed */
	if (cs5530_init_chip())
		return -EIO;

	ata_host_resume(host);
	return 0;
}
#endif /* CONFIG_PM */

static const struct pci_device_id cs5530[] = {
	{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), },

	{ },
};

static struct pci_driver cs5530_pci_driver = {
	.name 		= DRV_NAME,
	.id_table	= cs5530,
	.probe 		= cs5530_init_one,
	.remove		= ata_pci_remove_one,
#ifdef CONFIG_PM
	.suspend	= ata_pci_device_suspend,
	.resume		= cs5530_reinit_one,
#endif
};

static int __init cs5530_init(void)
{
	return pci_register_driver(&cs5530_pci_driver);
}

static void __exit cs5530_exit(void)
{
	pci_unregister_driver(&cs5530_pci_driver);
}

MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("low-level driver for the Cyrix/NS/AMD 5530");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, cs5530);
MODULE_VERSION(DRV_VERSION);

module_init(cs5530_init);
module_exit(cs5530_exit);
示例#17
0
/*
 * sysfs hook function
 */
static ssize_t madc_read(struct device *dev,
			 struct device_attribute *devattr, char *buf)
{
	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
	struct twl4030_madc_request req = {
		.channels = 1 << attr->index,
		.method = TWL4030_MADC_SW2,
		.type = TWL4030_MADC_WAIT,
	};
	long val;

	val = twl4030_madc_conversion(&req);
	if (val < 0)
		return val;

	return sprintf(buf, "%d\n", req.rbuf[attr->index]);
}

/* sysfs nodes to read individual channels from user side */
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2);
static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3);
static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4);
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5);
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6);
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7);
static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8);
static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9);
static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10);
static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11);
static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12);
static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15);

static struct attribute *twl4030_madc_attrs[] = {
	&sensor_dev_attr_in0_input.dev_attr.attr,
	&sensor_dev_attr_temp1_input.dev_attr.attr,
	&sensor_dev_attr_in2_input.dev_attr.attr,
	&sensor_dev_attr_in3_input.dev_attr.attr,
	&sensor_dev_attr_in4_input.dev_attr.attr,
	&sensor_dev_attr_in5_input.dev_attr.attr,
	&sensor_dev_attr_in6_input.dev_attr.attr,
	&sensor_dev_attr_in7_input.dev_attr.attr,
	&sensor_dev_attr_in8_input.dev_attr.attr,
	&sensor_dev_attr_in9_input.dev_attr.attr,
	&sensor_dev_attr_curr10_input.dev_attr.attr,
	&sensor_dev_attr_in11_input.dev_attr.attr,
	&sensor_dev_attr_in12_input.dev_attr.attr,
	&sensor_dev_attr_in15_input.dev_attr.attr,
	NULL
};
ATTRIBUTE_GROUPS(twl4030_madc);

static int twl4030_madc_hwmon_probe(struct platform_device *pdev)
{
	struct device *hwmon;

	hwmon = devm_hwmon_device_register_with_groups(&pdev->dev,
						       "twl4030_madc", NULL,
						       twl4030_madc_groups);
	return PTR_ERR_OR_ZERO(hwmon);
}

static struct platform_driver twl4030_madc_hwmon_driver = {
	.probe = twl4030_madc_hwmon_probe,
	.driver = {
		   .name = "twl4030_madc_hwmon",
		   .owner = THIS_MODULE,
		   },
};

module_platform_driver(twl4030_madc_hwmon_driver);

MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("J Keerthy");
MODULE_ALIAS("platform:twl4030_madc_hwmon");
示例#18
0
文件: mdc800.c 项目: davidbau/davej
int __init usb_mdc800_init (void)
{
	/* Allocate Memory */
	try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));

	memset(mdc800, 0, sizeof(struct mdc800_data));
	mdc800->dev=0;
	mdc800->open=0;
	mdc800->state=NOT_CONNECTED;
	spin_lock_init (&mdc800->io_lock);

	init_waitqueue_head (&mdc800->irq_wait);
	init_waitqueue_head (&mdc800->write_wait);
	init_waitqueue_head (&mdc800->download_wait);

	try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
	try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
	try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));

	try (mdc800->irq_urb=usb_alloc_urb (0));
	try (mdc800->download_urb=usb_alloc_urb (0));
	try (mdc800->write_urb=usb_alloc_urb (0));

	/* Register the driver */
	if (usb_register (&mdc800_usb_driver) < 0)
		goto cleanup_on_fail;

	info ("Mustek Digital Camera Driver " VERSION " (MDC800)");
	info (RELEASE_DATE " Henning Zabel <*****@*****.**>");

	return 0;

	/* Clean driver up, when something fails */

cleanup_on_fail:

	if (mdc800 != 0)
	{
		err ("can't alloc memory!");

		try_free_mem (mdc800->download_urb_buffer);
		try_free_mem (mdc800->write_urb_buffer);
		try_free_mem (mdc800->irq_urb_buffer);

		try_free_urb (mdc800->write_urb);
		try_free_urb (mdc800->download_urb);
		try_free_urb (mdc800->irq_urb);

		kfree (mdc800);
	}
	mdc800=0;
	return -1;
}


void __exit usb_mdc800_cleanup (void)
{
	usb_deregister (&mdc800_usb_driver);

	usb_free_urb (mdc800->irq_urb);
	usb_free_urb (mdc800->download_urb);
	usb_free_urb (mdc800->write_urb);

	kfree (mdc800->irq_urb_buffer);
	kfree (mdc800->write_urb_buffer);
	kfree (mdc800->download_urb_buffer);

	kfree (mdc800);
	mdc800=0;
}


MODULE_AUTHOR ("Henning Zabel <*****@*****.**>");
MODULE_DESCRIPTION ("USB Driver for Mustek MDC800 Digital Camera");

module_init (usb_mdc800_init);
module_exit (usb_mdc800_cleanup);
示例#19
0
static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	u32 value;
	static const struct watchdog_info ident = {
		.options = WDIOF_CARDRESET,
		.identity = "RDC321x WDT",
	};
	unsigned long flags;

	switch (cmd) {
	case WDIOC_KEEPALIVE:
		rdc321x_wdt_reset();
		break;
	case WDIOC_GETSTATUS:
		/* Read the value from the DATA register */
		spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
		pci_read_config_dword(rdc321x_wdt_device.sb_pdev,
					rdc321x_wdt_device.base_reg, &value);
		spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
		if (copy_to_user(argp, &value, sizeof(u32)))
			return -EFAULT;
		break;
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;
	case WDIOC_SETOPTIONS:
		if (copy_from_user(&value, argp, sizeof(int)))
			return -EFAULT;
		switch (value) {
		case WDIOS_ENABLECARD:
			rdc321x_wdt_start();
			break;
		case WDIOS_DISABLECARD:
			return rdc321x_wdt_stop();
		default:
			return -EINVAL;
		}
		break;
	default:
		return -ENOTTY;
	}
	return 0;
}

static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf,
				size_t count, loff_t *ppos)
{
	if (!count)
		return -EIO;

	rdc321x_wdt_reset();

	return count;
}

static const struct file_operations rdc321x_wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.unlocked_ioctl	= rdc321x_wdt_ioctl,
	.open		= rdc321x_wdt_open,
	.write		= rdc321x_wdt_write,
	.release	= rdc321x_wdt_release,
};

static struct miscdevice rdc321x_wdt_misc = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &rdc321x_wdt_fops,
};

static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
{
	int err;
	struct resource *r;
	struct rdc321x_wdt_pdata *pdata;

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data supplied\n");
		return -ENODEV;
	}

	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "wdt-reg");
	if (!r) {
		dev_err(&pdev->dev, "failed to get wdt-reg resource\n");
		return -ENODEV;
	}

	rdc321x_wdt_device.sb_pdev = pdata->sb_pdev;
	rdc321x_wdt_device.base_reg = r->start;

	err = misc_register(&rdc321x_wdt_misc);
	if (err < 0) {
		dev_err(&pdev->dev, "misc_register failed\n");
		return err;
	}

	spin_lock_init(&rdc321x_wdt_device.lock);

	/* Reset the watchdog */
	pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
				rdc321x_wdt_device.base_reg, RDC_WDT_RST);

	init_completion(&rdc321x_wdt_device.stop);
	rdc321x_wdt_device.queue = 0;

	clear_bit(0, &rdc321x_wdt_device.inuse);

	setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0);

	rdc321x_wdt_device.default_ticks = ticks;

	dev_info(&pdev->dev, "watchdog init success\n");

	return 0;
}

static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
{
	if (rdc321x_wdt_device.queue) {
		rdc321x_wdt_device.queue = 0;
		wait_for_completion(&rdc321x_wdt_device.stop);
	}

	misc_deregister(&rdc321x_wdt_misc);

	return 0;
}

static struct platform_driver rdc321x_wdt_driver = {
	.probe = rdc321x_wdt_probe,
	.remove = __devexit_p(rdc321x_wdt_remove),
	.driver = {
		.owner = THIS_MODULE,
		.name = "rdc321x-wdt",
	},
};

module_platform_driver(rdc321x_wdt_driver);

MODULE_AUTHOR("Florian Fainelli <*****@*****.**>");
MODULE_DESCRIPTION("RDC321x watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
static int asr_ioctl(struct inode *inode, struct file *file,
		     unsigned int cmd, unsigned long arg)
{
	static const struct watchdog_info ident = {
		.options =	WDIOF_KEEPALIVEPING | 
				WDIOF_MAGICCLOSE,
		.identity =	"IBM ASR"
	};
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int heartbeat;

	switch (cmd) {
		case WDIOC_GETSUPPORT:
			return copy_to_user(argp, &ident, sizeof(ident)) ?
				-EFAULT : 0;

		case WDIOC_GETSTATUS:
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, p);

		case WDIOC_KEEPALIVE:
			asr_toggle();
			return 0;

		/*
		 * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
		 * and WDIOC_GETTIMEOUT always returns 256.
		 */
		case WDIOC_GETTIMEOUT:
			heartbeat = 256;
			return put_user(heartbeat, p);

		case WDIOC_SETOPTIONS: {
			int new_options, retval = -EINVAL;

			if (get_user(new_options, p))
				return -EFAULT;

			if (new_options & WDIOS_DISABLECARD) {
				asr_disable();
				retval = 0;
			}

			if (new_options & WDIOS_ENABLECARD) {
				asr_enable();
				asr_toggle();
				retval = 0;
			}

			return retval;
		}
	}

	return -ENOIOCTLCMD;
}

static int asr_open(struct inode *inode, struct file *file)
{
	if(test_and_set_bit(0, &asr_is_open))
		return -EBUSY;

	asr_toggle();
	asr_enable();

	return nonseekable_open(inode, file);
}

static int asr_release(struct inode *inode, struct file *file)
{
	if (asr_expect_close == 42)
		asr_disable();
	else {
		printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
		asr_toggle();
	}
	clear_bit(0, &asr_is_open);
	asr_expect_close = 0;
	return 0;
}

static struct file_operations asr_fops = {
	.owner =	THIS_MODULE,
	.llseek	=	no_llseek,
	.write =	asr_write,
	.ioctl =	asr_ioctl,
	.open =		asr_open,
	.release =	asr_release,
};

static struct miscdevice asr_miscdev = {
	.minor =	WATCHDOG_MINOR,
	.name =		"watchdog",
	.fops =		&asr_fops,
};


struct ibmasr_id {
	const char *desc;
	int type;
};

static struct ibmasr_id __initdata ibmasr_id_table[] = {
	{ "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
	{ "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
	{ "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
	{ "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
	{ "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
	{ NULL }
};

static int __init ibmasr_init(void)
{
	struct ibmasr_id *id;
	int rc;

	for (id = ibmasr_id_table; id->desc; id++) {
		if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
			asr_type = id->type;
			break;
		}
	}

	if (!asr_type)
		return -ENODEV;

	rc = misc_register(&asr_miscdev);
	if (rc < 0) {
		printk(KERN_ERR PFX "failed to register misc device\n");
		return rc;
	}

	rc = asr_get_base_address();
	if (rc) {
		misc_deregister(&asr_miscdev);
		return rc;
	}

	return 0;
}

static void __exit ibmasr_exit(void)
{
	if (!nowayout)
		asr_disable();

	misc_deregister(&asr_miscdev);

	release_region(asr_base, asr_length);
}

module_init(ibmasr_init);
module_exit(ibmasr_exit);

module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");

MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
MODULE_AUTHOR("Andrey Panin");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
示例#21
0
static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
			    unsigned int cmd, unsigned long arg)
{
	int timeout;
	static struct watchdog_info info = {
		.options = WDIOF_KEEPALIVEPING,
		.firmware_version = 0,
		.identity = "MPC8xx watchdog",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user((void *)arg, &info, sizeof(info)))
			return -EFAULT;
		break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		if (put_user(wdt_status, (int *)arg))
			return -EFAULT;
		wdt_status &= ~WDIOF_KEEPALIVEPING;
		break;

	case WDIOC_GETTEMP:
		return -EOPNOTSUPP;

	case WDIOC_SETOPTIONS:
		return -EOPNOTSUPP;

	case WDIOC_KEEPALIVE:
		m8xx_wdt_reset();
		wdt_status |= WDIOF_KEEPALIVEPING;
		break;

	case WDIOC_SETTIMEOUT:
		return -EOPNOTSUPP;

	case WDIOC_GETTIMEOUT:
		timeout = m8xx_wdt_get_timeout();
		if (put_user(timeout, (int *)arg))
			return -EFAULT;
		break;

	default:
		return -ENOIOCTLCMD;
	}

	return 0;
}

static const struct file_operations mpc8xx_wdt_fops = {
	.owner = THIS_MODULE,
	.llseek = no_llseek,
	.write = mpc8xx_wdt_write,
	.ioctl = mpc8xx_wdt_ioctl,
	.open = mpc8xx_wdt_open,
	.release = mpc8xx_wdt_release,
};

static struct miscdevice mpc8xx_wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &mpc8xx_wdt_fops,
};

static int __init mpc8xx_wdt_init(void)
{
	return misc_register(&mpc8xx_wdt_miscdev);
}

static void __exit mpc8xx_wdt_exit(void)
{
	misc_deregister(&mpc8xx_wdt_miscdev);

	m8xx_wdt_reset();
	mpc8xx_wdt_handler_enable();
}

module_init(mpc8xx_wdt_init);
module_exit(mpc8xx_wdt_exit);

MODULE_AUTHOR("Florian Schirmer <*****@*****.**>");
MODULE_DESCRIPTION("MPC8xx watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
示例#22
0
static int tcf_gact_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref)
{
    unsigned char *b = skb_tail_pointer(skb);
    struct tcf_gact *gact = a->priv;
    struct tcf_t t;
    struct tc_gact opt = {
        .index   = gact->tcf_index,
        .refcnt  = gact->tcf_refcnt - ref,
        .bindcnt = gact->tcf_bindcnt - bind,
        .action  = gact->tcf_action,
    };

    NLA_PUT(skb, TCA_GACT_PARMS, sizeof(opt), &opt);
#ifdef CONFIG_GACT_PROB
    if (gact->tcfg_ptype) {
        struct tc_gact_p p_opt = {
            .paction = gact->tcfg_paction,
            .pval    = gact->tcfg_pval,
            .ptype   = gact->tcfg_ptype,
        };

        NLA_PUT(skb, TCA_GACT_PROB, sizeof(p_opt), &p_opt);
    }
#endif
    t.install = jiffies_to_clock_t(jiffies - gact->tcf_tm.install);
    t.lastuse = jiffies_to_clock_t(jiffies - gact->tcf_tm.lastuse);
    t.expires = jiffies_to_clock_t(gact->tcf_tm.expires);
    NLA_PUT(skb, TCA_GACT_TM, sizeof(t), &t);
    return skb->len;

nla_put_failure:
    nlmsg_trim(skb, b);
    return -1;
}

static struct tc_action_ops act_gact_ops = {
    .kind		=	"gact",
    .hinfo		=	&gact_hash_info,
    .type		=	TCA_ACT_GACT,
    .capab		=	TCA_CAP_NONE,
    .owner		=	THIS_MODULE,
    .act		=	tcf_gact,
    .dump		=	tcf_gact_dump,
    .cleanup	=	tcf_gact_cleanup,
    .lookup		=	tcf_hash_search,
    .init		=	tcf_gact_init,
    .walk		=	tcf_generic_walker
};

MODULE_AUTHOR("Jamal Hadi Salim(2002-4)");
MODULE_DESCRIPTION("Generic Classifier actions");
MODULE_LICENSE("GPL");

static int __init gact_init_module(void)
{
#ifdef CONFIG_GACT_PROB
    printk("GACT probability on\n");
#else
    printk("GACT probability NOT on\n");
#endif
    return tcf_register_action(&act_gact_ops);
}

static void __exit gact_cleanup_module(void)
{
    tcf_unregister_action(&act_gact_ops);
}

module_init(gact_init_module);
module_exit(gact_cleanup_module);
示例#23
0
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "SC520",
	};

	switch(cmd)
	{
		default:
			return -ENOIOCTLCMD;
		case WDIOC_GETSUPPORT:
			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
		case WDIOC_GETSTATUS:
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, p);
		case WDIOC_KEEPALIVE:
			wdt_keepalive();
			return 0;
		case WDIOC_SETOPTIONS:
		{
			int new_options, retval = -EINVAL;

			if(get_user(new_options, p))
				return -EFAULT;

			if(new_options & WDIOS_DISABLECARD) {
				wdt_turnoff();
				retval = 0;
			}

			if(new_options & WDIOS_ENABLECARD) {
				wdt_startup();
				retval = 0;
			}

			return retval;
		}
		case WDIOC_SETTIMEOUT:
		{
			int new_timeout;

			if(get_user(new_timeout, p))
				return -EFAULT;

			if(wdt_set_heartbeat(new_timeout))
				return -EINVAL;

			wdt_keepalive();
			/* Fall through */
		}
		case WDIOC_GETTIMEOUT:
			return put_user(timeout, p);
	}
}

static const struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= fop_write,
	.open		= fop_open,
	.release	= fop_close,
	.ioctl		= fop_ioctl,
};

static struct miscdevice wdt_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &wdt_fops,
};

/*
 *	Notifier for system down
 */

static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT)
		wdt_turnoff();
	return NOTIFY_DONE;
}

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static void __exit sc520_wdt_unload(void)
{
	if (!nowayout)
		wdt_turnoff();

	/* Deregister */
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	iounmap(wdtmrctl);
}

static int __init sc520_wdt_init(void)
{
	int rc = -EBUSY;

	spin_lock_init(&wdt_spinlock);

	init_timer(&timer);
	timer.function = wdt_timer_ping;
	timer.data = 0;

	/* Check that the timeout value is within it's range ; if not reset to the default */
	if (wdt_set_heartbeat(timeout)) {
		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
		printk(KERN_INFO PFX "timeout value must be 1<=timeout<=3600, using %d\n",
			WATCHDOG_TIMEOUT);
	}

	wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2);
	if (!wdtmrctl) {
		printk(KERN_ERR PFX "Unable to remap memory\n");
		rc = -ENOMEM;
		goto err_out_region2;
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc) {
		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			rc);
		goto err_out_ioremap;
	}

	rc = misc_register(&wdt_miscdev);
	if (rc) {
		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, rc);
		goto err_out_notifier;
	}

	printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
		timeout,nowayout);

	return 0;

err_out_notifier:
	unregister_reboot_notifier(&wdt_notifier);
err_out_ioremap:
	iounmap(wdtmrctl);
err_out_region2:
	return rc;
}

module_init(sc520_wdt_init);
module_exit(sc520_wdt_unload);

MODULE_AUTHOR("Scott and Bill Jennings");
MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
示例#24
0
static int tcf_sample_dump(struct sk_buff *skb, struct tc_action *a,
			   int bind, int ref)
{
	unsigned char *b = skb_tail_pointer(skb);
	struct tcf_sample *s = to_sample(a);
	struct tc_sample opt = {
		.index      = s->tcf_index,
		.action     = s->tcf_action,
		.refcnt     = s->tcf_refcnt - ref,
		.bindcnt    = s->tcf_bindcnt - bind,
	};
	struct tcf_t t;

	if (nla_put(skb, TCA_SAMPLE_PARMS, sizeof(opt), &opt))
		goto nla_put_failure;

	tcf_tm_dump(&t, &s->tcf_tm);
	if (nla_put_64bit(skb, TCA_SAMPLE_TM, sizeof(t), &t, TCA_SAMPLE_PAD))
		goto nla_put_failure;

	if (nla_put_u32(skb, TCA_SAMPLE_RATE, s->rate))
		goto nla_put_failure;

	if (s->truncate)
		if (nla_put_u32(skb, TCA_SAMPLE_TRUNC_SIZE, s->trunc_size))
			goto nla_put_failure;

	if (nla_put_u32(skb, TCA_SAMPLE_PSAMPLE_GROUP, s->psample_group_num))
		goto nla_put_failure;
	return skb->len;

nla_put_failure:
	nlmsg_trim(skb, b);
	return -1;
}

static int tcf_sample_walker(struct net *net, struct sk_buff *skb,
			     struct netlink_callback *cb, int type,
			     const struct tc_action_ops *ops)
{
	struct tc_action_net *tn = net_generic(net, sample_net_id);

	return tcf_generic_walker(tn, skb, cb, type, ops);
}

static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index)
{
	struct tc_action_net *tn = net_generic(net, sample_net_id);

	return tcf_hash_search(tn, a, index);
}

static struct tc_action_ops act_sample_ops = {
	.kind	  = "sample",
	.type	  = TCA_ACT_SAMPLE,
	.owner	  = THIS_MODULE,
	.act	  = tcf_sample_act,
	.dump	  = tcf_sample_dump,
	.init	  = tcf_sample_init,
	.cleanup  = tcf_sample_cleanup,
	.walk	  = tcf_sample_walker,
	.lookup	  = tcf_sample_search,
	.size	  = sizeof(struct tcf_sample),
};

static __net_init int sample_init_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, sample_net_id);

	return tc_action_net_init(tn, &act_sample_ops, SAMPLE_TAB_MASK);
}

static void __net_exit sample_exit_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, sample_net_id);

	tc_action_net_exit(tn);
}

static struct pernet_operations sample_net_ops = {
	.init = sample_init_net,
	.exit = sample_exit_net,
	.id   = &sample_net_id,
	.size = sizeof(struct tc_action_net),
};

static int __init sample_init_module(void)
{
	return tcf_register_action(&act_sample_ops, &sample_net_ops);
}

static void __exit sample_cleanup_module(void)
{
	tcf_unregister_action(&act_sample_ops, &sample_net_ops);
}

module_init(sample_init_module);
module_exit(sample_cleanup_module);

MODULE_AUTHOR("Yotam Gigi <*****@*****.**>");
MODULE_DESCRIPTION("Packet sampling action");
MODULE_LICENSE("GPL v2");
示例#25
0
static int codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
{
	const struct codel_sched_data *q = qdisc_priv(sch);
	struct tc_codel_xstats st = {
		.maxpacket	= q->stats.maxpacket,
		.count		= q->vars.count,
		.lastcount	= q->vars.lastcount,
		.drop_overlimit = q->drop_overlimit,
		.ldelay		= codel_time_to_us(q->vars.ldelay),
		.dropping	= q->vars.dropping,
		.ecn_mark	= q->stats.ecn_mark,
	};

	if (q->vars.dropping) {
		codel_tdiff_t delta = q->vars.drop_next - codel_get_time();

		if (delta >= 0)
			st.drop_next = codel_time_to_us(delta);
		else
			st.drop_next = -codel_time_to_us(-delta);
	}

	return gnet_stats_copy_app(d, &st, sizeof(st));
}

static void codel_reset(struct Qdisc *sch)
{
	struct codel_sched_data *q = qdisc_priv(sch);

	qdisc_reset_queue(sch);
	codel_vars_init(&q->vars);
}

static struct Qdisc_ops codel_qdisc_ops __read_mostly = {
	.id		=	"codel",
	.priv_size	=	sizeof(struct codel_sched_data),

	.enqueue	=	codel_qdisc_enqueue,
	.dequeue	=	codel_qdisc_dequeue,
	.peek		=	qdisc_peek_dequeued,
	.init		=	codel_init,
	.reset		=	codel_reset,
	.change 	=	codel_change,
	.dump		=	codel_dump,
	.dump_stats	=	codel_dump_stats,
	.owner		=	THIS_MODULE,
};

static int __init codel_module_init(void)
{
	return register_qdisc(&codel_qdisc_ops);
}

static void __exit codel_module_exit(void)
{
	unregister_qdisc(&codel_qdisc_ops);
}

module_init(codel_module_init)
module_exit(codel_module_exit)

MODULE_DESCRIPTION("Controlled Delay queue discipline");
MODULE_AUTHOR("Dave Taht");
MODULE_AUTHOR("Eric Dumazet");
MODULE_LICENSE("Dual BSD/GPL");
示例#26
0
static void imx_fpga_ack_irq(struct irq_data *data)
{
	struct irq_mng *mng = irq_data_get_irq_chip_data(data);
	unsigned int irq = data->irq;
#else
static void imx_fpga_ack_irq(unsigned int irq)
{
	struct irq_mng *mng = &global_mng;
#endif
	int shadow;

	shadow = 1 << ((irq - IRQ_FPGA_START) % NB_IT);
	pr_debug("%s: irq %d ack:0x%x\n", __FUNCTION__, irq, shadow);
	writew(shadow, mng->membase + FPGA_ISR);
}

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
static void imx_fpga_mask_irq(struct irq_data *data)
{
	struct irq_mng *mng = irq_data_get_irq_chip_data(data);
	unsigned int irq = data->irq;
#else
static void imx_fpga_mask_irq(unsigned int irq)
{
	struct irq_mng *mng = &global_mng;
#endif
	int shadow;

	shadow = readw(mng->membase + FPGA_IMR);
	shadow &= ~( 1 << ((irq - IRQ_FPGA_START) % NB_IT));
	pr_debug("%s: irq %d mask:0x%x\n", __FUNCTION__, irq, shadow);
	writew(shadow, mng->membase + FPGA_IMR);
}

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
static void imx_fpga_unmask_irq(struct irq_data *data)
{
	struct irq_mng *mng = irq_data_get_irq_chip_data(data);
	unsigned int irq = data->irq;
#else
static void imx_fpga_unmask_irq(unsigned int irq)
{
	struct irq_mng *mng = &global_mng;
#endif
	int shadow;

	shadow = readw(mng->membase + FPGA_IMR);
	shadow |= 1 << ((irq - IRQ_FPGA_START) % NB_IT);
	pr_debug("%s: irq %d mask:0x%x\n", __FUNCTION__, irq, shadow);
	writew(shadow, mng->membase + FPGA_IMR);
}

static irqreturn_t ocore_irq_mng_interrupt(int irq, void *data)
{
	struct irq_mng *mng = data;
	struct irq_desc *desc;
	unsigned int mask;

	mask = readw(mng->membase + FPGA_ISR);
	pr_debug("%s: mask:0x%04x\n", __FUNCTION__, mask);
	do {
		irq = IRQ_FPGA_START;

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
		desc = irq_to_desc(irq);
#else
		desc = irq_desc + irq;
#endif

		/* handle irqs */
		while (mask) {
			if (mask & 1) {
				pr_debug("handling irq %d 0x%08x\n", irq,
						(unsigned int)desc);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
				desc->handle_irq(irq, desc);
#else
				desc_handle_irq(irq, desc);
#endif
			}
			irq++;
			desc++;
			mask >>= 1;
		}
		mask = readw(mng->membase + FPGA_ISR);
	} while (mask != 0);

	return IRQ_HANDLED;
}

static struct irq_chip imx_fpga_chip = {
	.name		= "FPGA",
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
	.irq_ack	= imx_fpga_ack_irq,
	.irq_mask	= imx_fpga_mask_irq,
	.irq_unmask	= imx_fpga_unmask_irq,
#else
	.ack		= imx_fpga_ack_irq,
	.mask		= imx_fpga_mask_irq,
	.unmask		= imx_fpga_unmask_irq,
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
	.irq_set_type	= imx_fpga_irq_type,
#else
	.set_type	= imx_fpga_irq_type,
#endif
};

#ifdef CONFIG_PM
static int ocore_irq_mng_suspend(struct platform_device *pdev, pm_message_t state)
{
	dev_dbg(&pdev->dev, "suspended\n");

	return 0;
}

static int ocore_irq_mng_resume(struct platform_device *pdev)
{
	dev_dbg(&pdev->dev, "resumed\n");

	return 0;
}
#else
# define ocore_irq_mng_suspend NULL
# define ocore_irq_mng_resume NULL
#endif /* CONFIG_PM */

#if LINUX_VERSION_CODE > KERNEL_VERSION(3,8,0)
/* __dev* stuff is removed from Linux since 30/11/2012 */
#define __devinit
#define __devexit
#endif

static int __devinit ocore_irq_mng_probe(struct platform_device *pdev)
{
	struct ocore_irq_mng_pdata *pdata = pdev->dev.platform_data;
	unsigned int irq;
	u16 id;
	int ret = 0;
	struct resource *mem_res;
	struct resource *irq_res;
	struct irq_mng *mng;

	if (!pdata) {
		dev_err(&pdev->dev, "Platform data required !\n");
		return -ENODEV;
	}

	/* get resources */
	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem_res) {
		dev_err(&pdev->dev, "can't find mem resource\n");
		return -EINVAL;
	}
	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!irq_res) {
		dev_err(&pdev->dev, "can't find irq resource\n");
		return -EINVAL;
	}

	mem_res = request_mem_region(mem_res->start, resource_size(mem_res), pdev->name);
	if (!mem_res) {
		dev_err(&pdev->dev, "iomem already in use\n");
		return -EBUSY;
	}

	/* allocate memory for private structure */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
	mng = kmalloc(sizeof(struct irq_mng), GFP_KERNEL);
#else
	mng = &global_mng;
#endif
	if (!mng) {
		ret = -ENOMEM;
		goto out_release_mem;
	}
	pdata->mng = mng;

	mng->membase = ioremap(mem_res->start, resource_size(mem_res));
	if (!mng->membase) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto out_dev_free;
	}
	mng->mem_res = mem_res;
	mng->irq_res = irq_res;

	/* check if ID is correct */
	id = readw(mng->membase + ID_OFFSET);
	if (id != pdata->idnum) {
		printk(KERN_WARNING "For irq_mngr id:%d doesn't match with id"
			"read %d,\n is device present ?\n", pdata->idnum, id);
		ret = -ENODEV;
		goto out_iounmap;
	}

	/* Mask all interrupts initially */
	writew(0, mng->membase + FPGA_IMR);

	for (irq = IRQ_FPGA(0); irq < IRQ_FPGA(NB_IT); irq++) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
		irq_set_chip_data(irq, mng);
		irq_set_chip_and_handler_name(irq, &imx_fpga_chip,
						handle_edge_irq, NULL);
#else
		set_irq_chip_data(irq, mng);
		set_irq_chip_and_handler(irq, &imx_fpga_chip, handle_edge_irq);
#endif
		set_irq_flags(irq, IRQF_VALID);
	}
	/* clear pending interrupts */
	writew(0xffff, mng->membase + FPGA_ISR);

	ret = request_irq(mng->irq_res->start, ocore_irq_mng_interrupt,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
				IRQF_SAMPLE_RANDOM,
#else
				0,
#endif
				"ocore_irq_mng", mng);

	if (ret < 0) {
		printk(KERN_ERR "Can't register irq %d\n",
			   mng->irq_res->start);
		goto request_irq_error;
	}

	pr_debug("FPGA IRQs initialized (Parent=%d)\n", mng->irq_res->start);

	return 0;

request_irq_error:
out_iounmap:
	iounmap(mng->membase);
out_dev_free:
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
	kfree(mng);
#endif
out_release_mem:
	release_mem_region(mem_res->start, resource_size(mem_res));

	return ret;
}

static int __devexit ocore_irq_mng_remove(struct platform_device *pdev)
{
	struct ocore_irq_mng_pdata *pdata = pdev->dev.platform_data;
	struct irq_mng *mng = pdata->mng;
	unsigned int irq;

	for (irq = IRQ_FPGA(0); irq < IRQ_FPGA(NB_IT); irq++) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
		irq_set_chip(irq, NULL);
		irq_set_handler(irq, NULL);
#else
		set_irq_chip(irq, NULL);
		set_irq_handler(irq, NULL);
#endif
		set_irq_flags(irq, 0);
	}
	free_irq(mng->irq_res->start, mng);
	release_mem_region(mng->mem_res->start, resource_size(mng->mem_res));
	iounmap(mng->membase);
	kfree(mng);

	return 0;
}

static struct platform_driver ocore_irq_mng_driver = {
	.probe      = ocore_irq_mng_probe,
	.remove     = ocore_irq_mng_remove,
	.suspend    = ocore_irq_mng_suspend,
	.resume     = ocore_irq_mng_resume,
	.driver     = {
		.name   = DRIVER_NAME,
	},
};

static int __init ocore_irq_mng_init(void)
{
	return platform_driver_register(&ocore_irq_mng_driver);
}

static void __exit ocore_irq_mng_exit(void)
{
	platform_driver_unregister(&ocore_irq_mng_driver);
}

module_init(ocore_irq_mng_init);
module_exit(ocore_irq_mng_exit);

MODULE_AUTHOR("Julien Boibessot, <*****@*****.**>");
MODULE_DESCRIPTION("Armadeus OpenCore IRQ manager");
MODULE_LICENSE("GPL");
示例#27
0
static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a,
			   int bind, int ref)
{
	struct tcf_skbmod *d = to_skbmod(a);
	unsigned char *b = skb_tail_pointer(skb);
	struct tcf_skbmod_params  *p = rtnl_dereference(d->skbmod_p);
	struct tc_skbmod opt = {
		.index   = d->tcf_index,
		.refcnt  = d->tcf_refcnt - ref,
		.bindcnt = d->tcf_bindcnt - bind,
		.action  = d->tcf_action,
	};
	struct tcf_t t;

	opt.flags  = p->flags;
	if (nla_put(skb, TCA_SKBMOD_PARMS, sizeof(opt), &opt))
		goto nla_put_failure;
	if ((p->flags & SKBMOD_F_DMAC) &&
	    nla_put(skb, TCA_SKBMOD_DMAC, ETH_ALEN, p->eth_dst))
		goto nla_put_failure;
	if ((p->flags & SKBMOD_F_SMAC) &&
	    nla_put(skb, TCA_SKBMOD_SMAC, ETH_ALEN, p->eth_src))
		goto nla_put_failure;
	if ((p->flags & SKBMOD_F_ETYPE) &&
	    nla_put_u16(skb, TCA_SKBMOD_ETYPE, ntohs(p->eth_type)))
		goto nla_put_failure;

	tcf_tm_dump(&t, &d->tcf_tm);
	if (nla_put_64bit(skb, TCA_SKBMOD_TM, sizeof(t), &t, TCA_SKBMOD_PAD))
		goto nla_put_failure;

	return skb->len;
nla_put_failure:
	rcu_read_unlock();
	nlmsg_trim(skb, b);
	return -1;
}

static int tcf_skbmod_walker(struct net *net, struct sk_buff *skb,
			     struct netlink_callback *cb, int type,
			     const struct tc_action_ops *ops)
{
	struct tc_action_net *tn = net_generic(net, skbmod_net_id);

	return tcf_generic_walker(tn, skb, cb, type, ops);
}

static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index)
{
	struct tc_action_net *tn = net_generic(net, skbmod_net_id);

	return tcf_hash_search(tn, a, index);
}

static struct tc_action_ops act_skbmod_ops = {
	.kind		=	"skbmod",
	.type		=	TCA_ACT_SKBMOD,
	.owner		=	THIS_MODULE,
	.act		=	tcf_skbmod_run,
	.dump		=	tcf_skbmod_dump,
	.init		=	tcf_skbmod_init,
	.cleanup	=	tcf_skbmod_cleanup,
	.walk		=	tcf_skbmod_walker,
	.lookup		=	tcf_skbmod_search,
	.size		=	sizeof(struct tcf_skbmod),
};

static __net_init int skbmod_init_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, skbmod_net_id);

	return tc_action_net_init(tn, &act_skbmod_ops, SKBMOD_TAB_MASK);
}

static void __net_exit skbmod_exit_net(struct net *net)
{
	struct tc_action_net *tn = net_generic(net, skbmod_net_id);

	tc_action_net_exit(tn);
}

static struct pernet_operations skbmod_net_ops = {
	.init = skbmod_init_net,
	.exit = skbmod_exit_net,
	.id   = &skbmod_net_id,
	.size = sizeof(struct tc_action_net),
};

MODULE_AUTHOR("Jamal Hadi Salim, <*****@*****.**>");
MODULE_DESCRIPTION("SKB data mod-ing");
MODULE_LICENSE("GPL");

static int __init skbmod_init_module(void)
{
	return tcf_register_action(&act_skbmod_ops, &skbmod_net_ops);
}

static void __exit skbmod_cleanup_module(void)
{
	tcf_unregister_action(&act_skbmod_ops, &skbmod_net_ops);
}

module_init(skbmod_init_module);
module_exit(skbmod_cleanup_module);
示例#28
0
static long mtx1_wdt_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = (int __user *)argp;
	unsigned int value;
	static const struct watchdog_info ident = {
		.options = WDIOF_CARDRESET,
		.identity = "MTX-1 WDT",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		put_user(0, p);
		break;
	case WDIOC_SETOPTIONS:
		if (get_user(value, p))
			return -EFAULT;
		if (value & WDIOS_ENABLECARD)
			mtx1_wdt_start();
		else if (value & WDIOS_DISABLECARD)
			mtx1_wdt_stop();
		else
			return -EINVAL;
		return 0;
	case WDIOC_KEEPALIVE:
		mtx1_wdt_reset();
		break;
	default:
		return -ENOTTY;
	}
	return 0;
}


static ssize_t mtx1_wdt_write(struct file *file, const char *buf,
						size_t count, loff_t *ppos)
{
	if (!count)
		return -EIO;
	mtx1_wdt_reset();
	return count;
}

static const struct file_operations mtx1_wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.unlocked_ioctl	= mtx1_wdt_ioctl,
	.open		= mtx1_wdt_open,
	.write		= mtx1_wdt_write,
	.release	= mtx1_wdt_release,
};


static struct miscdevice mtx1_wdt_misc = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &mtx1_wdt_fops,
};


static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
{
	int ret;

	mtx1_wdt_device.gpio = pdev->resource[0].start;
	ret = gpio_request_one(mtx1_wdt_device.gpio,
				GPIOF_OUT_INIT_HIGH, "mtx1-wdt");
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to request gpio");
		return ret;
	}

	spin_lock_init(&mtx1_wdt_device.lock);
	init_completion(&mtx1_wdt_device.stop);
	mtx1_wdt_device.queue = 0;
	clear_bit(0, &mtx1_wdt_device.inuse);
	setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L);
	mtx1_wdt_device.default_ticks = ticks;

	ret = misc_register(&mtx1_wdt_misc);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to register\n");
		return ret;
	}
	mtx1_wdt_start();
	dev_info(&pdev->dev, "MTX-1 Watchdog driver\n");
	return 0;
}

static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
{
	/*                                       */
	if (mtx1_wdt_device.queue) {
		mtx1_wdt_device.queue = 0;
		wait_for_completion(&mtx1_wdt_device.stop);
	}

	gpio_free(mtx1_wdt_device.gpio);
	misc_deregister(&mtx1_wdt_misc);
	return 0;
}

static struct platform_driver mtx1_wdt_driver = {
	.probe = mtx1_wdt_probe,
	.remove = __devexit_p(mtx1_wdt_remove),
	.driver.name = "mtx1-wdt",
	.driver.owner = THIS_MODULE,
};

module_platform_driver(mtx1_wdt_driver);

MODULE_AUTHOR("Michael Stickel, Florian Fainelli");
MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_ALIAS("platform:mtx1-wdt");
static int __init multipdp_init(void)
{
	int ret;
	pdp_arg_t pdp_arg = { .id = 1, .ifname = "ttyCSD", };
	pdp_arg_t efs_arg = { .id = 8, .ifname = "ttyEFS", };
	pdp_arg_t gps_arg = { .id = 5, .ifname = "ttyGPS", };
	pdp_arg_t xtra_arg = { .id = 6, .ifname = "ttyXTRA", };
	pdp_arg_t smd_arg = { .id = 25, .ifname = "ttySMD", };
	pdp_arg_t pcm_arg = { .id = 30, .ifname = "ttyPCM", } ;
#ifdef LOOP_BACK_TEST	
	pdp_arg_t loopback_arg = { .id = 31, .ifname = "ttyLOBK", };
#endif

	wake_lock_init(&pdp_wake_lock, WAKE_LOCK_SUSPEND, "MULTI_PDP");
	

	/* run DPRAM I/O thread */
	ret = kernel_thread(dpram_thread, NULL, CLONE_FS | CLONE_FILES);
	if (ret < 0) {
		EPRINTK("kernel_thread() failed\n");
		return ret;
	}
	wait_for_completion(&dpram_complete);
	if (!dpram_task) {
		EPRINTK("DPRAM I/O thread error\n");
		return -EIO;
	}

	/* create serial device for Circuit Switched Data */
	ret = pdp_activate(&pdp_arg, DEV_TYPE_SERIAL, DEV_FLAG_STICKY);
	if (ret < 0) {
		EPRINTK("failed to create a serial device for CSD\n");
		goto err0;
	}

	ret = pdp_activate(&efs_arg, DEV_TYPE_SERIAL, DEV_FLAG_STICKY);
	if (ret < 0) {
		EPRINTK("failed to create a serial device for EFS\n");
		goto err1;
	}

	ret = pdp_activate(&gps_arg, DEV_TYPE_SERIAL, DEV_FLAG_STICKY);
	if (ret < 0) {
		EPRINTK("failed to create a serial device for GPS\n");
		goto err2;
	}

	ret = pdp_activate(&xtra_arg, DEV_TYPE_SERIAL, DEV_FLAG_STICKY);
	if (ret < 0) {
		EPRINTK("failed to create a serial device for XTRA\n");
		goto err3;
	}
	
	ret = pdp_activate(&smd_arg, DEV_TYPE_SERIAL, DEV_FLAG_STICKY);
	if (ret < 0) {
		EPRINTK("failed to create a serial device for SMD\n");
		goto err4;
	}

	ret = pdp_activate(&pcm_arg, DEV_TYPE_SERIAL, DEV_FLAG_STICKY);
	if (ret < 0) {
		EPRINTK("failed to create a serial device for SMD\n");
		goto err5;
	}

#ifdef LOOP_BACK_TEST	
	ret = pdp_activate(&loopback_arg, DEV_TYPE_SERIAL, DEV_FLAG_STICKY);
	if (ret < 0) {
		EPRINTK("failed to create a serial device for LoopBack\n");
		goto err6;
	}
#endif
	/* create app. interface device */
	ret = misc_register(&multipdp_dev);
	if (ret < 0) {
		EPRINTK("misc_register() failed\n");
		goto err1;
	}


#ifdef LOOP_BACK_TEST
	ret = device_create_file(multipdp_dev.this_device, &dev_attr_loopback);
#endif	

#ifdef CONFIG_PROC_FS
	create_proc_read_entry(APP_DEVNAME, 0, 0, 
			       multipdp_proc_read, NULL);
#endif

#ifdef	NO_TTY_DPRAM
	//
	printk("multipdp_init:multipdp_rx_noti_regi calling");
	multipdp_rx_noti_regi(multipdp_rx_cback );	
#endif
//	printk(KERN_INFO 
//	       "$Id: multipdp.c,v 1.10 2008/01/11 05:40:56 melonzz Exp $\n");
	return 0;

#ifdef LOOP_BACK_TEST	
err6:
	pdp_deactivate(&loopback_arg, 1);
#endif	
err5:
	/* undo serial device for Circuit Switched Data */
	pdp_deactivate(&pcm_arg, 1);

err4:
	/* undo serial device for Circuit Switched Data */
	pdp_deactivate(&smd_arg, 1);

err3:
	/* undo serial device for Circuit Switched Data */
	pdp_deactivate(&xtra_arg, 1);
err2:
	/* undo serial device for Circuit Switched Data */
	pdp_deactivate(&gps_arg, 1);
err1:
	/* undo serial device for Circuit Switched Data */
	pdp_deactivate(&pdp_arg, 1);
err0:
	/* kill DPRAM I/O thread */
	if (dpram_task) {
		send_sig(SIGUSR1, dpram_task, 1);
		wait_for_completion(&dpram_complete);
	}
	return ret;
}

static void __exit multipdp_exit(void)
{
	wake_lock_destroy(&pdp_wake_lock);
#ifdef CONFIG_PROC_FS
	remove_proc_entry(APP_DEVNAME, 0);
#endif

	/* remove app. interface device */
	misc_deregister(&multipdp_dev);

	/* clean up PDP context table */
	pdp_cleanup();

	/* kill DPRAM I/O thread */
	if (dpram_task) {
		send_sig(SIGUSR1, dpram_task, 1);
		wait_for_completion(&dpram_complete);
	}
}

//module_init(multipdp_init);
late_initcall(multipdp_init);
module_exit(multipdp_exit);

MODULE_AUTHOR("SAMSUNG ELECTRONICS CO., LTD");
MODULE_DESCRIPTION("Multiple PDP Muxer / Demuxer");
MODULE_LICENSE("GPL");
static int __devinit sil680_init_one(struct pci_dev *pdev,
				     const struct pci_device_id *id)
{
	static const struct ata_port_info info = {
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.udma_mask = ATA_UDMA6,
		.port_ops = &sil680_port_ops
	};
	static const struct ata_port_info info_slow = {
		.flags = ATA_FLAG_SLAVE_POSS,
		.pio_mask = 0x1f,
		.mwdma_mask = 0x07,
		.udma_mask = ATA_UDMA5,
		.port_ops = &sil680_port_ops
	};
	const struct ata_port_info *ppi[] = { &info, NULL };
	static int printed_version;
	struct ata_host *host;
	void __iomem *mmio_base;
	int rc, try_mmio;

	if (!printed_version++)
		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");

	rc = pcim_enable_device(pdev);
	if (rc)
		return rc;

	switch (sil680_init_chip(pdev, &try_mmio)) {
		case 0:
			ppi[0] = &info_slow;
			break;
		case 0x30:
			return -ENODEV;
	}

	if (!try_mmio)
		goto use_ioports;

	/* Try to acquire MMIO resources and fallback to PIO if
	 * that fails
	 */
	rc = pcim_iomap_regions(pdev, 1 << SIL680_MMIO_BAR, DRV_NAME);
	if (rc)
		goto use_ioports;

	/* Allocate host and set it up */
	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
	if (!host)
		return -ENOMEM;
	host->iomap = pcim_iomap_table(pdev);

	/* Setup DMA masks */
	rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
	if (rc)
		return rc;
	rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
	if (rc)
		return rc;
	pci_set_master(pdev);

	/* Get MMIO base and initialize port addresses */
	mmio_base = host->iomap[SIL680_MMIO_BAR];
	host->ports[0]->ioaddr.bmdma_addr = mmio_base + 0x00;
	host->ports[0]->ioaddr.cmd_addr = mmio_base + 0x80;
	host->ports[0]->ioaddr.ctl_addr = mmio_base + 0x8a;
	host->ports[0]->ioaddr.altstatus_addr = mmio_base + 0x8a;
	ata_sff_std_ports(&host->ports[0]->ioaddr);
	host->ports[1]->ioaddr.bmdma_addr = mmio_base + 0x08;
	host->ports[1]->ioaddr.cmd_addr = mmio_base + 0xc0;
	host->ports[1]->ioaddr.ctl_addr = mmio_base + 0xca;
	host->ports[1]->ioaddr.altstatus_addr = mmio_base + 0xca;
	ata_sff_std_ports(&host->ports[1]->ioaddr);

	/* Register & activate */
	return ata_host_activate(host, pdev->irq, ata_sff_interrupt,
				 IRQF_SHARED, &sil680_sht);

use_ioports:
	return ata_pci_sff_init_one(pdev, ppi, &sil680_sht, NULL);
}

#ifdef CONFIG_PM
static int sil680_reinit_one(struct pci_dev *pdev)
{
	struct ata_host *host = dev_get_drvdata(&pdev->dev);
	int try_mmio, rc;

	rc = ata_pci_device_do_resume(pdev);
	if (rc)
		return rc;
	sil680_init_chip(pdev, &try_mmio);
	ata_host_resume(host);
	return 0;
}
#endif

static const struct pci_device_id sil680[] = {
	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_SII_680), },

	{ },
};

static struct pci_driver sil680_pci_driver = {
	.name 		= DRV_NAME,
	.id_table	= sil680,
	.probe 		= sil680_init_one,
	.remove		= ata_pci_remove_one,
#ifdef CONFIG_PM
	.suspend	= ata_pci_device_suspend,
	.resume		= sil680_reinit_one,
#endif
};

static int __init sil680_init(void)
{
	return pci_register_driver(&sil680_pci_driver);
}

static void __exit sil680_exit(void)
{
	pci_unregister_driver(&sil680_pci_driver);
}

MODULE_AUTHOR("Alan Cox");
MODULE_DESCRIPTION("low-level driver for SI680 PATA");
MODULE_LICENSE("GPL");
MODULE_DEVICE_TABLE(pci, sil680);
MODULE_VERSION(DRV_VERSION);

module_init(sil680_init);
module_exit(sil680_exit);