mirror of
https://github.com/a52xq-dev/kernel.git
synced 2026-10-18 21:58:11 +07:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging-2.6: (342 commits) Staging: comedi: fix build errors Staging: udlfb: update to version 0.2.3 Staging: udlfb: fix some sparse warnings. Staging: udlfb: clean up checkpatch warnings in udlfb.c Staging: udlfb: clean up checkpatch warnings in udlfb.h Staging: udlfb: add udlfb driver to build Staging: add udlfb driver Staging: pata_rdc: remove pointless comments Staging: pata_rdc: remove DRIVER macros Staging: pata_rdc: remove dbgprintf macro Staging: pata_rdc: remove broken flag Staging: pata_rdc: fix build warnings Staging: pata_rdc: use PCI_DEVICE Staging: pata_rdc: remove function prototypes Staging: pata_rdc: coding style fixes Staging: pata_rdc: convert code to work in 2.6.29 Staging: pata_rdc: add driver to the build system Staging: add pata_rdc driver Staging: remove obsolete serqt_usb driver Staging: serqt_usb2 add the driver to the build ...
This commit is contained in:
commit
fb20871a54
658 changed files with 165609 additions and 240517 deletions
|
|
@ -5479,6 +5479,7 @@ STAGING SUBSYSTEM
|
|||
P: Greg Kroah-Hartman
|
||||
M: gregkh@suse.de
|
||||
T: quilt kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/
|
||||
L: devel@driverdev.osuosl.org
|
||||
S: Maintained
|
||||
F: drivers/staging/
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,8 @@ source "drivers/staging/altpciechdma/Kconfig"
|
|||
|
||||
source "drivers/staging/rtl8187se/Kconfig"
|
||||
|
||||
source "drivers/staging/rtl8192su/Kconfig"
|
||||
|
||||
source "drivers/staging/rspiusb/Kconfig"
|
||||
|
||||
source "drivers/staging/mimio/Kconfig"
|
||||
|
|
@ -113,11 +115,19 @@ source "drivers/staging/heci/Kconfig"
|
|||
|
||||
source "drivers/staging/line6/Kconfig"
|
||||
|
||||
source "drivers/staging/serqt_usb/Kconfig"
|
||||
|
||||
source "drivers/gpu/drm/radeon/Kconfig"
|
||||
|
||||
source "drivers/staging/octeon/Kconfig"
|
||||
|
||||
source "drivers/staging/serqt_usb2/Kconfig"
|
||||
|
||||
source "drivers/staging/vt6655/Kconfig"
|
||||
|
||||
source "drivers/staging/cpc-usb/Kconfig"
|
||||
|
||||
source "drivers/staging/pata_rdc/Kconfig"
|
||||
|
||||
source "drivers/staging/udlfb/Kconfig"
|
||||
|
||||
endif # !STAGING_EXCLUDE_BUILD
|
||||
endif # STAGING
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ obj-$(CONFIG_ASUS_OLED) += asus_oled/
|
|||
obj-$(CONFIG_PANEL) += panel/
|
||||
obj-$(CONFIG_ALTERA_PCIE_CHDMA) += altpciechdma/
|
||||
obj-$(CONFIG_RTL8187SE) += rtl8187se/
|
||||
obj-$(CONFIG_RTL8192SU) += rtl8192su/
|
||||
obj-$(CONFIG_USB_RSPI) += rspiusb/
|
||||
obj-$(CONFIG_INPUT_MIMIO) += mimio/
|
||||
obj-$(CONFIG_TRANZPORT) += frontier/
|
||||
|
|
@ -39,5 +40,9 @@ obj-$(CONFIG_IDE_PHISON) += phison/
|
|||
obj-$(CONFIG_PLAN9AUTH) += p9auth/
|
||||
obj-$(CONFIG_HECI) += heci/
|
||||
obj-$(CONFIG_LINE6_USB) += line6/
|
||||
obj-$(CONFIG_USB_SERIAL_QUATECH_ESU100) += serqt_usb/
|
||||
obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/
|
||||
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
|
||||
obj-$(CONFIG_VT6655) += vt6655/
|
||||
obj-$(CONFIG_USB_CPC) += cpc-usb/
|
||||
obj-$(CONFIG_RDC_17F3101X) += pata_rdc/
|
||||
obj-$(CONFIG_FB_UDL) += udlfb/
|
||||
|
|
|
|||
|
|
@ -312,7 +312,6 @@ static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
|
|||
{
|
||||
u16 fctl;
|
||||
int hdrlen;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
fctl = le16_to_cpu(hdr->frame_control);
|
||||
switch (fctl & IEEE80211_FCTL_FTYPE) {
|
||||
|
|
@ -375,13 +374,13 @@ static inline void dump_ieee80211_hdr(struct ieee80211_hdr *hdr, char *tag)
|
|||
printk("FC=0x%04x DUR=0x%04x",
|
||||
fctl, le16_to_cpu(hdr->duration_id));
|
||||
if (hdrlen >= 10)
|
||||
printk(" A1=%s", print_mac(mac, hdr->addr1));
|
||||
printk(" A1=%pM", hdr->addr1);
|
||||
if (hdrlen >= 16)
|
||||
printk(" A2=%s", print_mac(mac, hdr->addr2));
|
||||
printk(" A2=%pM", hdr->addr2);
|
||||
if (hdrlen >= 24)
|
||||
printk(" A3=%s", print_mac(mac, hdr->addr3));
|
||||
printk(" A3=%pM", hdr->addr3);
|
||||
if (hdrlen >= 30)
|
||||
printk(" A4=%s", print_mac(mac, hdr->addr4));
|
||||
printk(" A4=%pM", hdr->addr4);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -58,15 +58,17 @@ static inline void agnx_interrupt_ack(struct agnx_priv *priv, u32 *reason)
|
|||
*reason |= AGNX_STAT_TXM;
|
||||
}
|
||||
}
|
||||
/* if (*reason & AGNX_STAT_X) {
|
||||
#if 0
|
||||
if (*reason & AGNX_STAT_X) {
|
||||
reg = ioread32(ctl + AGNX_INT_STAT);
|
||||
iowrite32(reg, ctl + AGNX_INT_STAT);
|
||||
/* FIXME reinit interrupt mask *\/
|
||||
/* FIXME reinit interrupt mask */
|
||||
reg = 0xc390bf9 & ~IRQ_TX_BEACON;
|
||||
reg &= ~IRQ_TX_DISABLE;
|
||||
iowrite32(reg, ctl + AGNX_INT_MASK);
|
||||
iowrite32(0x800, ctl + AGNX_CIR_BLKCTL);
|
||||
} */
|
||||
}
|
||||
#endif
|
||||
} /* agnx_interrupt_ack */
|
||||
|
||||
static irqreturn_t agnx_interrupt_handler(int irq, void *dev_id)
|
||||
|
|
@ -150,8 +152,7 @@ static int agnx_get_mac_address(struct agnx_priv *priv)
|
|||
*((u32 *)(priv->mac_addr + 2)) = cpu_to_le32(reg);
|
||||
|
||||
if (!is_valid_ether_addr(priv->mac_addr)) {
|
||||
DECLARE_MAC_BUF(mbuf);
|
||||
printk(KERN_WARNING PFX "read mac %s\n", print_mac(mbuf, priv->mac_addr));
|
||||
printk(KERN_WARNING PFX "read mac %pM\n", priv->mac_addr);
|
||||
printk(KERN_WARNING PFX "Invalid hwaddr! Using random hwaddr\n");
|
||||
random_ether_addr(priv->mac_addr);
|
||||
}
|
||||
|
|
@ -220,7 +221,7 @@ static void agnx_periodic_work_handler(struct work_struct *work)
|
|||
/* TODO Recalibrate*/
|
||||
/* calibrate_oscillator(priv); */
|
||||
/* antenna_calibrate(priv); */
|
||||
/* agnx_send_packet(priv, 997); /
|
||||
/* agnx_send_packet(priv, 997); */
|
||||
/* FIXME */
|
||||
/* if (debug == 3) */
|
||||
/* delay = msecs_to_jiffies(AGNX_PERIODIC_DELAY); */
|
||||
|
|
@ -455,47 +456,35 @@ static int __devinit agnx_pci_probe(struct pci_dev *pdev,
|
|||
{
|
||||
struct ieee80211_hw *dev;
|
||||
struct agnx_priv *priv;
|
||||
u32 mem_addr0, mem_len0;
|
||||
u32 mem_addr1, mem_len1;
|
||||
int err;
|
||||
DECLARE_MAC_BUF(mac);
|
||||
|
||||
err = pci_enable_device(pdev);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Can't enable new PCI device\n");
|
||||
dev_err(&pdev->dev, "can't enable pci device\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
/* get pci resource */
|
||||
mem_addr0 = pci_resource_start(pdev, 0);
|
||||
mem_len0 = pci_resource_len(pdev, 0);
|
||||
mem_addr1 = pci_resource_start(pdev, 1);
|
||||
mem_len1 = pci_resource_len(pdev, 1);
|
||||
printk(KERN_DEBUG PFX "Memaddr0 is %x, length is %x\n", mem_addr0, mem_len0);
|
||||
printk(KERN_DEBUG PFX "Memaddr1 is %x, length is %x\n", mem_addr1, mem_len1);
|
||||
|
||||
err = pci_request_regions(pdev, "agnx-pci");
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Can't obtain PCI resource\n");
|
||||
dev_err(&pdev->dev, "can't reserve PCI resources\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
|
||||
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
||||
printk(KERN_ERR PFX "No suitable DMA available\n");
|
||||
dev_err(&pdev->dev, "no suitable DMA available\n");
|
||||
err = -EIO;
|
||||
goto err_free_reg;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
printk(KERN_DEBUG PFX "pdev->irq is %d\n", pdev->irq);
|
||||
|
||||
dev = ieee80211_alloc_hw(sizeof(*priv), &agnx_ops);
|
||||
if (!dev) {
|
||||
printk(KERN_ERR PFX "ieee80211 alloc failed\n");
|
||||
dev_err(&pdev->dev, "ieee80211 alloc failed\n");
|
||||
err = -ENOMEM;
|
||||
goto err_free_reg;
|
||||
}
|
||||
/* init priv */
|
||||
priv = dev->priv;
|
||||
memset(priv, 0, sizeof(*priv));
|
||||
priv->mode = NL80211_IFTYPE_MONITOR;
|
||||
|
|
@ -504,17 +493,17 @@ static int __devinit agnx_pci_probe(struct pci_dev *pdev,
|
|||
spin_lock_init(&priv->lock);
|
||||
priv->init_status = AGNX_UNINIT;
|
||||
|
||||
/* Map mem #1 and #2 */
|
||||
priv->ctl = pci_iomap(pdev, 0, mem_len0);
|
||||
/* printk(KERN_DEBUG PFX"MEM1 mapped address is 0x%p\n", priv->ctl); */
|
||||
priv->ctl = pci_iomap(pdev, 0, 0);
|
||||
/* dev_dbg(&pdev->dev, "MEM1 mapped address is 0x%p\n", priv->ctl); */
|
||||
if (!priv->ctl) {
|
||||
printk(KERN_ERR PFX "Can't map device memory\n");
|
||||
dev_err(&pdev->dev, "can't map device memory\n");
|
||||
err = -ENOMEM;
|
||||
goto err_free_dev;
|
||||
}
|
||||
priv->data = pci_iomap(pdev, 1, mem_len1);
|
||||
printk(KERN_DEBUG PFX "MEM2 mapped address is 0x%p\n", priv->data);
|
||||
priv->data = pci_iomap(pdev, 1, 0);
|
||||
if (!priv->data) {
|
||||
printk(KERN_ERR PFX "Can't map device memory\n");
|
||||
dev_err(&pdev->dev, "can't map device memory\n");
|
||||
err = -ENOMEM;
|
||||
goto err_iounmap2;
|
||||
}
|
||||
|
||||
|
|
@ -555,15 +544,15 @@ static int __devinit agnx_pci_probe(struct pci_dev *pdev,
|
|||
|
||||
err = ieee80211_register_hw(dev);
|
||||
if (err) {
|
||||
printk(KERN_ERR PFX "Can't register hardware\n");
|
||||
dev_err(&pdev->dev, "can't register hardware\n");
|
||||
goto err_iounmap;
|
||||
}
|
||||
|
||||
agnx_hw_reset(priv);
|
||||
|
||||
|
||||
printk(PFX "%s: hwaddr %s, Rev 0x%02x\n", wiphy_name(dev->wiphy),
|
||||
print_mac(mac, dev->wiphy->perm_addr), priv->revid);
|
||||
dev_info(&pdev->dev, "%s: hwaddr %pM, Rev 0x%02x\n",
|
||||
wiphy_name(dev->wiphy),
|
||||
dev->wiphy->perm_addr, priv->revid);
|
||||
return 0;
|
||||
|
||||
err_iounmap:
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ static void mac_address_set(struct agnx_priv *priv)
|
|||
iowrite32(reg, ctl + AGNX_RXM_MACLO);
|
||||
}
|
||||
|
||||
static void receiver_bssid_set(struct agnx_priv *priv, u8 *bssid)
|
||||
static void receiver_bssid_set(struct agnx_priv *priv, const u8 *bssid)
|
||||
{
|
||||
void __iomem *ctl = priv->ctl;
|
||||
u32 reg;
|
||||
|
|
@ -954,7 +954,7 @@ int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void agnx_set_bssid(struct agnx_priv *priv, u8 *bssid)
|
||||
void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid)
|
||||
{
|
||||
receiver_bssid_set(priv, bssid);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ u8 read_from_eeprom(struct agnx_priv *priv, u16 address);
|
|||
void agnx_hw_init(struct agnx_priv *priv);
|
||||
int agnx_hw_reset(struct agnx_priv *priv);
|
||||
int agnx_set_ssid(struct agnx_priv *priv, u8 *ssid, size_t ssid_len);
|
||||
void agnx_set_bssid(struct agnx_priv *priv, u8 *bssid);
|
||||
void agnx_set_bssid(struct agnx_priv *priv, const u8 *bssid);
|
||||
void enable_power_saving(struct agnx_priv *priv);
|
||||
void disable_power_saving(struct agnx_priv *priv);
|
||||
void calibrate_antenna_period(unsigned long data);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id)
|
|||
printk(PFX "RX hash cmd are : %.8x%.8x\n", reghi, reglo);
|
||||
}
|
||||
|
||||
void hash_write(struct agnx_priv *priv, u8 *mac_addr, u8 sta_id)
|
||||
void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id)
|
||||
{
|
||||
void __iomem *ctl = priv->ctl;
|
||||
u32 reghi, reglo;
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ struct agnx_beacon_hdr {
|
|||
/* 802.11(abg) beacon */
|
||||
} __attribute__((__packed__));
|
||||
|
||||
void hash_write(struct agnx_priv *priv, u8 *mac_addr, u8 sta_id);
|
||||
void hash_write(struct agnx_priv *priv, const u8 *mac_addr, u8 sta_id);
|
||||
void hash_dump(struct agnx_priv *priv, u8 sta_id);
|
||||
void hash_read(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
|
||||
void hash_delete(struct agnx_priv *priv, u32 reghi, u32 reglo, u8 sta_id);
|
||||
|
|
|
|||
|
|
@ -399,6 +399,7 @@ static inline void ape_chdma_desc_set(struct ape_chdma_desc *desc, dma_addr_t ad
|
|||
desc->rc_addr_l = cpu_to_le32(pci_dma_l(addr));
|
||||
}
|
||||
|
||||
#if ALTPCIECHDMA_CDEV
|
||||
/*
|
||||
* ape_sg_to_chdma_table() - Create a device descriptor table from a scatterlist.
|
||||
*
|
||||
|
|
@ -456,6 +457,7 @@ static int ape_sg_to_chdma_table(struct scatterlist *sgl, int nents, int first,
|
|||
j++;
|
||||
return j;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* compare buffers */
|
||||
static inline int compare(u32 *p, u32 *q, int len)
|
||||
|
|
@ -540,8 +542,8 @@ static int __devinit dma_test(struct ape_dev *ape, struct pci_dev *dev)
|
|||
printk(KERN_DEBUG "Could not allocate coherent DMA buffer.\n");
|
||||
goto fail;
|
||||
}
|
||||
printk(KERN_DEBUG "Allocated cache-coherent DMA buffer (virtual address = 0x%016llx, bus address = 0x%016llx).\n",
|
||||
(u64)buffer_virt, (u64)buffer_bus);
|
||||
printk(KERN_DEBUG "Allocated cache-coherent DMA buffer (virtual address = %p, bus address = 0x%016llx).\n",
|
||||
buffer_virt, (u64)buffer_bus);
|
||||
|
||||
/* fill first half of buffer with its virtual address as data */
|
||||
for (i = 0; i < 4 * PAGE_SIZE; i += 4)
|
||||
|
|
@ -783,7 +785,7 @@ static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
goto err_ape;
|
||||
}
|
||||
ape->pci_dev = dev;
|
||||
dev->dev.driver_data = (void *)ape;
|
||||
dev_set_drvdata(&dev->dev, ape);
|
||||
printk(KERN_DEBUG "probe() ape = 0x%p\n", ape);
|
||||
|
||||
printk(KERN_DEBUG "sizeof(struct ape_chdma_table) = %d.\n",
|
||||
|
|
@ -801,8 +803,8 @@ static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
goto err_table;
|
||||
}
|
||||
|
||||
printk(KERN_DEBUG "table_virt = 0x%16llx, table_bus = 0x%16llx.\n",
|
||||
(u64)ape->table_virt, (u64)ape->table_bus);
|
||||
printk(KERN_DEBUG "table_virt = %p, table_bus = 0x%16llx.\n",
|
||||
ape->table_virt, (u64)ape->table_bus);
|
||||
|
||||
/* enable device */
|
||||
rc = pci_enable_device(dev);
|
||||
|
|
@ -913,9 +915,11 @@ static int __devinit probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||
rc = 0;
|
||||
printk(KERN_DEBUG "probe() successful.\n");
|
||||
goto end;
|
||||
#if ALTPCIECHDMA_CDEV
|
||||
err_cdev:
|
||||
/* unmap the BARs */
|
||||
unmap_bars(ape, dev);
|
||||
#endif
|
||||
err_map:
|
||||
/* free allocated irq */
|
||||
if (ape->irq_line >= 0)
|
||||
|
|
@ -930,7 +934,7 @@ err_irq:
|
|||
pci_release_regions(dev);
|
||||
err_mask:
|
||||
err_regions:
|
||||
err_rev:
|
||||
/*err_rev:*/
|
||||
/* clean up everything before device enable() */
|
||||
err_enable:
|
||||
if (ape->table_virt)
|
||||
|
|
@ -946,19 +950,11 @@ end:
|
|||
|
||||
static void __devexit remove(struct pci_dev *dev)
|
||||
{
|
||||
struct ape_dev *ape;
|
||||
struct ape_dev *ape = dev_get_drvdata(&dev->dev);
|
||||
|
||||
printk(KERN_DEBUG "remove(0x%p)\n", dev);
|
||||
if ((dev == 0) || (dev->dev.driver_data == 0)) {
|
||||
printk(KERN_DEBUG "remove(dev = 0x%p) dev->dev.driver_data = 0x%p\n",
|
||||
dev, (dev? dev->dev.driver_data: NULL));
|
||||
return;
|
||||
}
|
||||
ape = (struct ape_dev *)dev->dev.driver_data;
|
||||
printk(KERN_DEBUG "remove(dev = 0x%p) where dev->dev.driver_data = 0x%p\n", dev, ape);
|
||||
if (ape->pci_dev != dev) {
|
||||
printk(KERN_DEBUG "dev->dev.driver_data->pci_dev (0x%08lx) != dev (0x%08lx)\n",
|
||||
(unsigned long)ape->pci_dev, (unsigned long)dev);
|
||||
}
|
||||
printk(KERN_DEBUG "remove(dev = 0x%p) where ape = 0x%p\n", dev, ape);
|
||||
|
||||
/* remove character device */
|
||||
#if ALTPCIECHDMA_CDEV
|
||||
sg_exit(ape);
|
||||
|
|
@ -1151,7 +1147,7 @@ static struct pci_driver pci_driver = {
|
|||
.name = DRV_NAME,
|
||||
.id_table = ids,
|
||||
.probe = probe,
|
||||
.remove = remove,
|
||||
.remove = __devexit_p(remove),
|
||||
/* resume, suspend are optional */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ config ANDROID
|
|||
---help---
|
||||
Enable support for various drivers needed on the Android platform
|
||||
|
||||
if ANDROID
|
||||
|
||||
config ANDROID_BINDER_IPC
|
||||
bool "Android Binder IPC Driver"
|
||||
default n
|
||||
|
|
@ -73,9 +75,13 @@ config ANDROID_RAM_CONSOLE_EARLY_SIZE
|
|||
default 0
|
||||
depends on ANDROID_RAM_CONSOLE_EARLY_INIT
|
||||
|
||||
config ANDROID_TIMED_OUTPUT
|
||||
bool "Timed output class driver"
|
||||
default y
|
||||
|
||||
config ANDROID_TIMED_GPIO
|
||||
tristate "Android timed gpio driver"
|
||||
depends on GENERIC_GPIO
|
||||
depends on GENERIC_GPIO && ANDROID_TIMED_OUTPUT
|
||||
default n
|
||||
|
||||
config ANDROID_LOW_MEMORY_KILLER
|
||||
|
|
@ -84,4 +90,6 @@ config ANDROID_LOW_MEMORY_KILLER
|
|||
---help---
|
||||
Register processes to be killed when memory is low
|
||||
|
||||
endif # if ANDROID
|
||||
|
||||
endmenu
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o
|
||||
obj-$(CONFIG_ANDROID_LOGGER) += logger.o
|
||||
obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
|
||||
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
|
||||
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
|
||||
obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ static struct hlist_head binder_dead_nodes;
|
|||
static HLIST_HEAD(binder_deferred_list);
|
||||
static DEFINE_MUTEX(binder_deferred_lock);
|
||||
|
||||
static int binder_read_proc_proc(
|
||||
char *page, char **start, off_t off, int count, int *eof, void *data);
|
||||
static int binder_read_proc_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data);
|
||||
|
||||
/* This is only defined in include/asm-arm/sizes.h */
|
||||
#ifndef SZ_1K
|
||||
|
|
@ -81,12 +81,15 @@ enum {
|
|||
static uint32_t binder_debug_mask = BINDER_DEBUG_USER_ERROR |
|
||||
BINDER_DEBUG_FAILED_TRANSACTION | BINDER_DEBUG_DEAD_TRANSACTION;
|
||||
module_param_named(debug_mask, binder_debug_mask, uint, S_IWUSR | S_IRUGO);
|
||||
|
||||
static int binder_debug_no_lock;
|
||||
module_param_named(proc_no_lock, binder_debug_no_lock, bool, S_IWUSR | S_IRUGO);
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(binder_user_error_wait);
|
||||
static int binder_stop_on_user_error;
|
||||
static int binder_set_stop_on_user_error(
|
||||
const char *val, struct kernel_param *kp)
|
||||
|
||||
static int binder_set_stop_on_user_error(const char *val,
|
||||
struct kernel_param *kp)
|
||||
{
|
||||
int ret;
|
||||
ret = param_set_int(val, kp);
|
||||
|
|
@ -185,13 +188,13 @@ struct binder_node {
|
|||
int local_strong_refs;
|
||||
void __user *ptr;
|
||||
void __user *cookie;
|
||||
unsigned has_strong_ref : 1;
|
||||
unsigned pending_strong_ref : 1;
|
||||
unsigned has_weak_ref : 1;
|
||||
unsigned pending_weak_ref : 1;
|
||||
unsigned has_async_transaction : 1;
|
||||
unsigned accept_fds : 1;
|
||||
int min_priority : 8;
|
||||
unsigned has_strong_ref:1;
|
||||
unsigned pending_strong_ref:1;
|
||||
unsigned has_weak_ref:1;
|
||||
unsigned pending_weak_ref:1;
|
||||
unsigned has_async_transaction:1;
|
||||
unsigned accept_fds:1;
|
||||
unsigned min_priority:8;
|
||||
struct list_head async_todo;
|
||||
};
|
||||
|
||||
|
|
@ -221,10 +224,10 @@ struct binder_buffer {
|
|||
struct list_head entry; /* free and allocated entries by addesss */
|
||||
struct rb_node rb_node; /* free entry by size or allocated entry */
|
||||
/* by address */
|
||||
unsigned free : 1;
|
||||
unsigned allow_user_free : 1;
|
||||
unsigned async_transaction : 1;
|
||||
unsigned debug_id : 29;
|
||||
unsigned free:1;
|
||||
unsigned allow_user_free:1;
|
||||
unsigned async_transaction:1;
|
||||
unsigned debug_id:29;
|
||||
|
||||
struct binder_transaction *transaction;
|
||||
|
||||
|
|
@ -306,8 +309,8 @@ struct binder_transaction {
|
|||
struct binder_proc *to_proc;
|
||||
struct binder_thread *to_thread;
|
||||
struct binder_transaction *to_parent;
|
||||
unsigned need_reply : 1;
|
||||
/*unsigned is_dead : 1;*/ /* not used at the moment */
|
||||
unsigned need_reply:1;
|
||||
/* unsigned is_dead:1; */ /* not used at the moment */
|
||||
|
||||
struct binder_buffer *buffer;
|
||||
unsigned int code;
|
||||
|
|
@ -474,8 +477,8 @@ static void binder_set_nice(long nice)
|
|||
binder_user_error("binder: %d RLIMIT_NICE not set\n", current->pid);
|
||||
}
|
||||
|
||||
static size_t binder_buffer_size(
|
||||
struct binder_proc *proc, struct binder_buffer *buffer)
|
||||
static size_t binder_buffer_size(struct binder_proc *proc,
|
||||
struct binder_buffer *buffer)
|
||||
{
|
||||
if (list_is_last(&buffer->entry, &proc->buffers))
|
||||
return proc->buffer + proc->buffer_size - (void *)buffer->data;
|
||||
|
|
@ -484,8 +487,8 @@ static size_t binder_buffer_size(
|
|||
struct binder_buffer, entry) - (size_t)buffer->data;
|
||||
}
|
||||
|
||||
static void binder_insert_free_buffer(
|
||||
struct binder_proc *proc, struct binder_buffer *new_buffer)
|
||||
static void binder_insert_free_buffer(struct binder_proc *proc,
|
||||
struct binder_buffer *new_buffer)
|
||||
{
|
||||
struct rb_node **p = &proc->free_buffers.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
|
|
@ -517,8 +520,8 @@ static void binder_insert_free_buffer(
|
|||
rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
|
||||
}
|
||||
|
||||
static void binder_insert_allocated_buffer(
|
||||
struct binder_proc *proc, struct binder_buffer *new_buffer)
|
||||
static void binder_insert_allocated_buffer(struct binder_proc *proc,
|
||||
struct binder_buffer *new_buffer)
|
||||
{
|
||||
struct rb_node **p = &proc->allocated_buffers.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
|
|
@ -542,8 +545,8 @@ static void binder_insert_allocated_buffer(
|
|||
rb_insert_color(&new_buffer->rb_node, &proc->allocated_buffers);
|
||||
}
|
||||
|
||||
static struct binder_buffer *binder_buffer_lookup(
|
||||
struct binder_proc *proc, void __user *user_ptr)
|
||||
static struct binder_buffer *binder_buffer_lookup(struct binder_proc *proc,
|
||||
void __user *user_ptr)
|
||||
{
|
||||
struct rb_node *n = proc->allocated_buffers.rb_node;
|
||||
struct binder_buffer *buffer;
|
||||
|
|
@ -567,7 +570,8 @@ static struct binder_buffer *binder_buffer_lookup(
|
|||
}
|
||||
|
||||
static int binder_update_page_range(struct binder_proc *proc, int allocate,
|
||||
void *start, void *end, struct vm_area_struct *vma)
|
||||
void *start, void *end,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
void *page_addr;
|
||||
unsigned long user_page_addr;
|
||||
|
|
@ -664,7 +668,8 @@ err_no_vma:
|
|||
}
|
||||
|
||||
static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
|
||||
size_t data_size, size_t offsets_size, int is_async)
|
||||
size_t data_size,
|
||||
size_t offsets_size, int is_async)
|
||||
{
|
||||
struct rb_node *n = proc->free_buffers.rb_node;
|
||||
struct binder_buffer *buffer;
|
||||
|
|
@ -692,8 +697,9 @@ static struct binder_buffer *binder_alloc_buf(struct binder_proc *proc,
|
|||
if (is_async &&
|
||||
proc->free_async_space < size + sizeof(struct binder_buffer)) {
|
||||
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
|
||||
printk(KERN_ERR "binder: %d: binder_alloc_buf size %zd f"
|
||||
"ailed, no async space left\n", proc->pid, size);
|
||||
printk(KERN_ERR
|
||||
"binder: %d: binder_alloc_buf size %zd failed, "
|
||||
"no async space left\n", proc->pid, size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -777,8 +783,8 @@ static void *buffer_end_page(struct binder_buffer *buffer)
|
|||
return (void *)(((uintptr_t)(buffer + 1) - 1) & PAGE_MASK);
|
||||
}
|
||||
|
||||
static void binder_delete_free_buffer(
|
||||
struct binder_proc *proc, struct binder_buffer *buffer)
|
||||
static void binder_delete_free_buffer(struct binder_proc *proc,
|
||||
struct binder_buffer *buffer)
|
||||
{
|
||||
struct binder_buffer *prev, *next = NULL;
|
||||
int free_page_end = 1;
|
||||
|
|
@ -824,8 +830,8 @@ static void binder_delete_free_buffer(
|
|||
}
|
||||
}
|
||||
|
||||
static void binder_free_buf(
|
||||
struct binder_proc *proc, struct binder_buffer *buffer)
|
||||
static void binder_free_buf(struct binder_proc *proc,
|
||||
struct binder_buffer *buffer)
|
||||
{
|
||||
size_t size, buffer_size;
|
||||
|
||||
|
|
@ -877,8 +883,8 @@ static void binder_free_buf(
|
|||
binder_insert_free_buffer(proc, buffer);
|
||||
}
|
||||
|
||||
static struct binder_node *
|
||||
binder_get_node(struct binder_proc *proc, void __user *ptr)
|
||||
static struct binder_node *binder_get_node(struct binder_proc *proc,
|
||||
void __user *ptr)
|
||||
{
|
||||
struct rb_node *n = proc->nodes.rb_node;
|
||||
struct binder_node *node;
|
||||
|
|
@ -896,8 +902,9 @@ binder_get_node(struct binder_proc *proc, void __user *ptr)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct binder_node *
|
||||
binder_new_node(struct binder_proc *proc, void __user *ptr, void __user *cookie)
|
||||
static struct binder_node *binder_new_node(struct binder_proc *proc,
|
||||
void __user *ptr,
|
||||
void __user *cookie)
|
||||
{
|
||||
struct rb_node **p = &proc->nodes.rb_node;
|
||||
struct rb_node *parent = NULL;
|
||||
|
|
@ -935,9 +942,8 @@ binder_new_node(struct binder_proc *proc, void __user *ptr, void __user *cookie)
|
|||
return node;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_inc_node(struct binder_node *node, int strong, int internal,
|
||||
struct list_head *target_list)
|
||||
static int binder_inc_node(struct binder_node *node, int strong, int internal,
|
||||
struct list_head *target_list)
|
||||
{
|
||||
if (strong) {
|
||||
if (internal) {
|
||||
|
|
@ -971,8 +977,7 @@ binder_inc_node(struct binder_node *node, int strong, int internal,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_dec_node(struct binder_node *node, int strong, int internal)
|
||||
static int binder_dec_node(struct binder_node *node, int strong, int internal)
|
||||
{
|
||||
if (strong) {
|
||||
if (internal)
|
||||
|
|
@ -1014,8 +1019,8 @@ binder_dec_node(struct binder_node *node, int strong, int internal)
|
|||
}
|
||||
|
||||
|
||||
static struct binder_ref *
|
||||
binder_get_ref(struct binder_proc *proc, uint32_t desc)
|
||||
static struct binder_ref *binder_get_ref(struct binder_proc *proc,
|
||||
uint32_t desc)
|
||||
{
|
||||
struct rb_node *n = proc->refs_by_desc.rb_node;
|
||||
struct binder_ref *ref;
|
||||
|
|
@ -1033,8 +1038,8 @@ binder_get_ref(struct binder_proc *proc, uint32_t desc)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static struct binder_ref *
|
||||
binder_get_ref_for_node(struct binder_proc *proc, struct binder_node *node)
|
||||
static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc,
|
||||
struct binder_node *node)
|
||||
{
|
||||
struct rb_node *n;
|
||||
struct rb_node **p = &proc->refs_by_node.rb_node;
|
||||
|
|
@ -1099,8 +1104,7 @@ binder_get_ref_for_node(struct binder_proc *proc, struct binder_node *node)
|
|||
return new_ref;
|
||||
}
|
||||
|
||||
static void
|
||||
binder_delete_ref(struct binder_ref *ref)
|
||||
static void binder_delete_ref(struct binder_ref *ref)
|
||||
{
|
||||
if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS)
|
||||
printk(KERN_INFO "binder: %d delete ref %d desc %d for "
|
||||
|
|
@ -1125,9 +1129,8 @@ binder_delete_ref(struct binder_ref *ref)
|
|||
binder_stats.obj_deleted[BINDER_STAT_REF]++;
|
||||
}
|
||||
|
||||
static int
|
||||
binder_inc_ref(
|
||||
struct binder_ref *ref, int strong, struct list_head *target_list)
|
||||
static int binder_inc_ref(struct binder_ref *ref, int strong,
|
||||
struct list_head *target_list)
|
||||
{
|
||||
int ret;
|
||||
if (strong) {
|
||||
|
|
@ -1149,8 +1152,7 @@ binder_inc_ref(
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
binder_dec_ref(struct binder_ref *ref, int strong)
|
||||
static int binder_dec_ref(struct binder_ref *ref, int strong)
|
||||
{
|
||||
if (strong) {
|
||||
if (ref->strong == 0) {
|
||||
|
|
@ -1182,9 +1184,8 @@ binder_dec_ref(struct binder_ref *ref, int strong)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
binder_pop_transaction(
|
||||
struct binder_thread *target_thread, struct binder_transaction *t)
|
||||
static void binder_pop_transaction(struct binder_thread *target_thread,
|
||||
struct binder_transaction *t)
|
||||
{
|
||||
if (target_thread) {
|
||||
BUG_ON(target_thread->transaction_stack != t);
|
||||
|
|
@ -1200,8 +1201,8 @@ binder_pop_transaction(
|
|||
binder_stats.obj_deleted[BINDER_STAT_TRANSACTION]++;
|
||||
}
|
||||
|
||||
static void
|
||||
binder_send_failed_reply(struct binder_transaction *t, uint32_t error_code)
|
||||
static void binder_send_failed_reply(struct binder_transaction *t,
|
||||
uint32_t error_code)
|
||||
{
|
||||
struct binder_thread *target_thread;
|
||||
BUG_ON(t->flags & TF_ONE_WAY);
|
||||
|
|
@ -1253,13 +1254,13 @@ binder_send_failed_reply(struct binder_transaction *t, uint32_t error_code)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
binder_transaction_buffer_release(struct binder_proc *proc,
|
||||
struct binder_buffer *buffer, size_t *failed_at);
|
||||
static void binder_transaction_buffer_release(struct binder_proc *proc,
|
||||
struct binder_buffer *buffer,
|
||||
size_t *failed_at);
|
||||
|
||||
static void
|
||||
binder_transaction(struct binder_proc *proc, struct binder_thread *thread,
|
||||
struct binder_transaction_data *tr, int reply)
|
||||
static void binder_transaction(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
struct binder_transaction_data *tr, int reply)
|
||||
{
|
||||
struct binder_transaction *t;
|
||||
struct binder_work *tcomplete;
|
||||
|
|
@ -1661,8 +1662,9 @@ err_no_context_mgr_node:
|
|||
thread->return_error = return_error;
|
||||
}
|
||||
|
||||
static void
|
||||
binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer *buffer, size_t *failed_at)
|
||||
static void binder_transaction_buffer_release(struct binder_proc *proc,
|
||||
struct binder_buffer *buffer,
|
||||
size_t *failed_at)
|
||||
{
|
||||
size_t *offp, *off_end;
|
||||
int debug_id = buffer->debug_id;
|
||||
|
|
@ -1730,9 +1732,8 @@ binder_transaction_buffer_release(struct binder_proc *proc, struct binder_buffer
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
void __user *buffer, int size, signed long *consumed)
|
||||
int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
||||
void __user *buffer, int size, signed long *consumed)
|
||||
{
|
||||
uint32_t cmd;
|
||||
void __user *ptr = buffer + *consumed;
|
||||
|
|
@ -2104,7 +2105,8 @@ binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
|||
} break;
|
||||
|
||||
default:
|
||||
printk(KERN_ERR "binder: %d:%d unknown command %d\n", proc->pid, thread->pid, cmd);
|
||||
printk(KERN_ERR "binder: %d:%d unknown command %d\n",
|
||||
proc->pid, thread->pid, cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
*consumed = ptr - buffer;
|
||||
|
|
@ -2112,8 +2114,8 @@ binder_thread_write(struct binder_proc *proc, struct binder_thread *thread,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
binder_stat_br(struct binder_proc *proc, struct binder_thread *thread, uint32_t cmd)
|
||||
void binder_stat_br(struct binder_proc *proc, struct binder_thread *thread,
|
||||
uint32_t cmd)
|
||||
{
|
||||
if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.br)) {
|
||||
binder_stats.br[_IOC_NR(cmd)]++;
|
||||
|
|
@ -2122,22 +2124,23 @@ binder_stat_br(struct binder_proc *proc, struct binder_thread *thread, uint32_t
|
|||
}
|
||||
}
|
||||
|
||||
static int
|
||||
binder_has_proc_work(struct binder_proc *proc, struct binder_thread *thread)
|
||||
static int binder_has_proc_work(struct binder_proc *proc,
|
||||
struct binder_thread *thread)
|
||||
{
|
||||
return !list_empty(&proc->todo) || (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
|
||||
return !list_empty(&proc->todo) ||
|
||||
(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
|
||||
}
|
||||
|
||||
static int
|
||||
binder_has_thread_work(struct binder_thread *thread)
|
||||
static int binder_has_thread_work(struct binder_thread *thread)
|
||||
{
|
||||
return !list_empty(&thread->todo) || thread->return_error != BR_OK ||
|
||||
(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN);
|
||||
}
|
||||
|
||||
static int
|
||||
binder_thread_read(struct binder_proc *proc, struct binder_thread *thread,
|
||||
void __user *buffer, int size, signed long *consumed, int non_block)
|
||||
static int binder_thread_read(struct binder_proc *proc,
|
||||
struct binder_thread *thread,
|
||||
void __user *buffer, int size,
|
||||
signed long *consumed, int non_block)
|
||||
{
|
||||
void __user *ptr = buffer + *consumed;
|
||||
void __user *end = buffer + size;
|
||||
|
|
@ -2152,7 +2155,8 @@ binder_thread_read(struct binder_proc *proc, struct binder_thread *thread,
|
|||
}
|
||||
|
||||
retry:
|
||||
wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);
|
||||
wait_for_proc_work = thread->transaction_stack == NULL &&
|
||||
list_empty(&thread->todo);
|
||||
|
||||
if (thread->return_error != BR_OK && ptr < end) {
|
||||
if (thread->return_error2 != BR_OK) {
|
||||
|
|
@ -2182,7 +2186,8 @@ retry:
|
|||
"for process work before calling BC_REGISTER_"
|
||||
"LOOPER or BC_ENTER_LOOPER (state %x)\n",
|
||||
proc->pid, thread->pid, thread->looper);
|
||||
wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
|
||||
wait_event_interruptible(binder_user_error_wait,
|
||||
binder_stop_on_user_error < 2);
|
||||
}
|
||||
binder_set_nice(proc->default_priority);
|
||||
if (non_block) {
|
||||
|
|
@ -2304,8 +2309,10 @@ retry:
|
|||
case BINDER_WORK_DEAD_BINDER:
|
||||
case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
|
||||
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
|
||||
struct binder_ref_death *death = container_of(w, struct binder_ref_death, work);
|
||||
struct binder_ref_death *death;
|
||||
uint32_t cmd;
|
||||
|
||||
death = container_of(w, struct binder_ref_death, work);
|
||||
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
|
||||
cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
|
||||
else
|
||||
|
|
@ -2362,15 +2369,19 @@ retry:
|
|||
|
||||
if (t->from) {
|
||||
struct task_struct *sender = t->from->proc->tsk;
|
||||
tr.sender_pid = task_tgid_nr_ns(sender, current->nsproxy->pid_ns);
|
||||
tr.sender_pid = task_tgid_nr_ns(sender,
|
||||
current->nsproxy->pid_ns);
|
||||
} else {
|
||||
tr.sender_pid = 0;
|
||||
}
|
||||
|
||||
tr.data_size = t->buffer->data_size;
|
||||
tr.offsets_size = t->buffer->offsets_size;
|
||||
tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset;
|
||||
tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));
|
||||
tr.data.ptr.buffer = (void *)t->buffer->data +
|
||||
proc->user_buffer_offset;
|
||||
tr.data.ptr.offsets = tr.data.ptr.buffer +
|
||||
ALIGN(t->buffer->data_size,
|
||||
sizeof(void *));
|
||||
|
||||
if (put_user(cmd, (uint32_t __user *)ptr))
|
||||
return -EFAULT;
|
||||
|
|
@ -2384,7 +2395,8 @@ retry:
|
|||
printk(KERN_INFO "binder: %d:%d %s %d %d:%d, cmd %d"
|
||||
"size %zd-%zd ptr %p-%p\n",
|
||||
proc->pid, thread->pid,
|
||||
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" : "BR_REPLY",
|
||||
(cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
|
||||
"BR_REPLY",
|
||||
t->debug_id, t->from ? t->from->proc->pid : 0,
|
||||
t->from ? t->from->pid : 0, cmd,
|
||||
t->buffer->data_size, t->buffer->offsets_size,
|
||||
|
|
@ -2430,7 +2442,9 @@ static void binder_release_work(struct list_head *list)
|
|||
list_del_init(&w->entry);
|
||||
switch (w->type) {
|
||||
case BINDER_WORK_TRANSACTION: {
|
||||
struct binder_transaction *t = container_of(w, struct binder_transaction, work);
|
||||
struct binder_transaction *t;
|
||||
|
||||
t = container_of(w, struct binder_transaction, work);
|
||||
if (t->buffer->target_node && !(t->flags & TF_ONE_WAY))
|
||||
binder_send_failed_reply(t, BR_DEAD_REPLY);
|
||||
} break;
|
||||
|
|
@ -2480,7 +2494,8 @@ static struct binder_thread *binder_get_thread(struct binder_proc *proc)
|
|||
return thread;
|
||||
}
|
||||
|
||||
static int binder_free_thread(struct binder_proc *proc, struct binder_thread *thread)
|
||||
static int binder_free_thread(struct binder_proc *proc,
|
||||
struct binder_thread *thread)
|
||||
{
|
||||
struct binder_transaction *t;
|
||||
struct binder_transaction *send_reply = NULL;
|
||||
|
|
@ -2493,8 +2508,10 @@ static int binder_free_thread(struct binder_proc *proc, struct binder_thread *th
|
|||
while (t) {
|
||||
active_transactions++;
|
||||
if (binder_debug_mask & BINDER_DEBUG_DEAD_TRANSACTION)
|
||||
printk(KERN_INFO "binder: release %d:%d transaction %d %s, still active\n",
|
||||
proc->pid, thread->pid, t->debug_id, (t->to_thread == thread) ? "in" : "out");
|
||||
printk(KERN_INFO "binder: release %d:%d transaction %d "
|
||||
"%s, still active\n", proc->pid, thread->pid,
|
||||
t->debug_id,
|
||||
(t->to_thread == thread) ? "in" : "out");
|
||||
if (t->to_thread == thread) {
|
||||
t->to_proc = NULL;
|
||||
t->to_thread = NULL;
|
||||
|
|
@ -2517,7 +2534,8 @@ static int binder_free_thread(struct binder_proc *proc, struct binder_thread *th
|
|||
return active_transactions;
|
||||
}
|
||||
|
||||
static unsigned int binder_poll(struct file *filp, struct poll_table_struct *wait)
|
||||
static unsigned int binder_poll(struct file *filp,
|
||||
struct poll_table_struct *wait)
|
||||
{
|
||||
struct binder_proc *proc = filp->private_data;
|
||||
struct binder_thread *thread = NULL;
|
||||
|
|
@ -2778,7 +2796,8 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||
proc->files = get_files_struct(current);
|
||||
proc->vma = vma;
|
||||
|
||||
/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n", proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
|
||||
/*printk(KERN_INFO "binder_mmap: %d %lx-%lx maps %p\n",
|
||||
proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
|
||||
return 0;
|
||||
|
||||
err_alloc_small_buf_failed:
|
||||
|
|
@ -2790,7 +2809,8 @@ err_alloc_pages_failed:
|
|||
err_get_vm_area_failed:
|
||||
err_already_mapped:
|
||||
err_bad_arg:
|
||||
printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n", proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
|
||||
printk(KERN_ERR "binder_mmap: %d %lx-%lx %s failed %d\n",
|
||||
proc->pid, vma->vm_start, vma->vm_end, failure_string, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -2799,7 +2819,8 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|||
struct binder_proc *proc;
|
||||
|
||||
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
|
||||
printk(KERN_INFO "binder_open: %d:%d\n", current->group_leader->pid, current->pid);
|
||||
printk(KERN_INFO "binder_open: %d:%d\n",
|
||||
current->group_leader->pid, current->pid);
|
||||
|
||||
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
|
||||
if (proc == NULL)
|
||||
|
|
@ -2821,7 +2842,9 @@ static int binder_open(struct inode *nodp, struct file *filp)
|
|||
char strbuf[11];
|
||||
snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);
|
||||
remove_proc_entry(strbuf, binder_proc_dir_entry_proc);
|
||||
create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc);
|
||||
create_proc_read_entry(strbuf, S_IRUGO,
|
||||
binder_proc_dir_entry_proc,
|
||||
binder_read_proc_proc, proc);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -2925,12 +2948,15 @@ static void binder_deferred_release(struct binder_proc *proc)
|
|||
}
|
||||
}
|
||||
if (binder_debug_mask & BINDER_DEBUG_DEAD_BINDER)
|
||||
printk(KERN_INFO "binder: node %d now dead, refs %d, death %d\n", node->debug_id, incoming_refs, death);
|
||||
printk(KERN_INFO "binder: node %d now dead, "
|
||||
"refs %d, death %d\n", node->debug_id,
|
||||
incoming_refs, death);
|
||||
}
|
||||
}
|
||||
outgoing_refs = 0;
|
||||
while ((n = rb_first(&proc->refs_by_desc))) {
|
||||
struct binder_ref *ref = rb_entry(n, struct binder_ref, rb_node_desc);
|
||||
struct binder_ref *ref = rb_entry(n, struct binder_ref,
|
||||
rb_node_desc);
|
||||
outgoing_refs++;
|
||||
binder_delete_ref(ref);
|
||||
}
|
||||
|
|
@ -2938,12 +2964,15 @@ static void binder_deferred_release(struct binder_proc *proc)
|
|||
buffers = 0;
|
||||
|
||||
while ((n = rb_first(&proc->allocated_buffers))) {
|
||||
struct binder_buffer *buffer = rb_entry(n, struct binder_buffer, rb_node);
|
||||
struct binder_buffer *buffer = rb_entry(n, struct binder_buffer,
|
||||
rb_node);
|
||||
t = buffer->transaction;
|
||||
if (t) {
|
||||
t->buffer = NULL;
|
||||
buffer->transaction = NULL;
|
||||
printk(KERN_ERR "binder: release proc %d, transaction %d, not freed\n", proc->pid, t->debug_id);
|
||||
printk(KERN_ERR "binder: release proc %d, "
|
||||
"transaction %d, not freed\n",
|
||||
proc->pid, t->debug_id);
|
||||
/*BUG();*/
|
||||
}
|
||||
binder_free_buf(proc, buffer);
|
||||
|
|
@ -2957,8 +2986,13 @@ static void binder_deferred_release(struct binder_proc *proc)
|
|||
int i;
|
||||
for (i = 0; i < proc->buffer_size / PAGE_SIZE; i++) {
|
||||
if (proc->pages[i]) {
|
||||
if (binder_debug_mask & BINDER_DEBUG_BUFFER_ALLOC)
|
||||
printk(KERN_INFO "binder_release: %d: page %d at %p not freed\n", proc->pid, i, proc->buffer + i * PAGE_SIZE);
|
||||
if (binder_debug_mask &
|
||||
BINDER_DEBUG_BUFFER_ALLOC)
|
||||
printk(KERN_INFO
|
||||
"binder_release: %d: "
|
||||
"page %d at %p not freed\n",
|
||||
proc->pid, i,
|
||||
proc->buffer + i * PAGE_SIZE);
|
||||
__free_page(proc->pages[i]);
|
||||
page_count++;
|
||||
}
|
||||
|
|
@ -2970,8 +3004,12 @@ static void binder_deferred_release(struct binder_proc *proc)
|
|||
put_task_struct(proc->tsk);
|
||||
|
||||
if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
|
||||
printk(KERN_INFO "binder_release: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d, buffers %d, pages %d\n",
|
||||
proc->pid, threads, nodes, incoming_refs, outgoing_refs, active_transactions, buffers, page_count);
|
||||
printk(KERN_INFO
|
||||
"binder_release: %d threads %d, nodes %d (ref %d), "
|
||||
"refs %d, active transactions %d, buffers %d, "
|
||||
"pages %d\n",
|
||||
proc->pid, threads, nodes, incoming_refs, outgoing_refs,
|
||||
active_transactions, buffers, page_count);
|
||||
|
||||
kfree(proc);
|
||||
}
|
||||
|
|
@ -2998,9 +3036,11 @@ static void binder_deferred_func(struct work_struct *work)
|
|||
mutex_unlock(&binder_deferred_lock);
|
||||
|
||||
files = NULL;
|
||||
if (defer & BINDER_DEFERRED_PUT_FILES)
|
||||
if ((files = proc->files))
|
||||
if (defer & BINDER_DEFERRED_PUT_FILES) {
|
||||
files = proc->files;
|
||||
if (files)
|
||||
proc->files = NULL;
|
||||
}
|
||||
|
||||
if (defer & BINDER_DEFERRED_FLUSH)
|
||||
binder_deferred_flush(proc);
|
||||
|
|
@ -3027,10 +3067,14 @@ static void binder_defer_work(struct binder_proc *proc, int defer)
|
|||
mutex_unlock(&binder_deferred_lock);
|
||||
}
|
||||
|
||||
static char *print_binder_transaction(char *buf, char *end, const char *prefix, struct binder_transaction *t)
|
||||
static char *print_binder_transaction(char *buf, char *end, const char *prefix,
|
||||
struct binder_transaction *t)
|
||||
{
|
||||
buf += snprintf(buf, end - buf, "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d",
|
||||
prefix, t->debug_id, t, t->from ? t->from->proc->pid : 0,
|
||||
buf += snprintf(buf, end - buf,
|
||||
"%s %d: %p from %d:%d to %d:%d code %x "
|
||||
"flags %x pri %ld r%d",
|
||||
prefix, t->debug_id, t,
|
||||
t->from ? t->from->proc->pid : 0,
|
||||
t->from ? t->from->pid : 0,
|
||||
t->to_proc ? t->to_proc->pid : 0,
|
||||
t->to_thread ? t->to_thread->pid : 0,
|
||||
|
|
@ -3053,7 +3097,8 @@ static char *print_binder_transaction(char *buf, char *end, const char *prefix,
|
|||
return buf;
|
||||
}
|
||||
|
||||
static char *print_binder_buffer(char *buf, char *end, const char *prefix, struct binder_buffer *buffer)
|
||||
static char *print_binder_buffer(char *buf, char *end, const char *prefix,
|
||||
struct binder_buffer *buffer)
|
||||
{
|
||||
buf += snprintf(buf, end - buf, "%s %d: %p size %zd:%zd %s\n",
|
||||
prefix, buffer->debug_id, buffer->data,
|
||||
|
|
@ -3063,7 +3108,8 @@ static char *print_binder_buffer(char *buf, char *end, const char *prefix, struc
|
|||
}
|
||||
|
||||
static char *print_binder_work(char *buf, char *end, const char *prefix,
|
||||
const char *transaction_prefix, struct binder_work *w)
|
||||
const char *transaction_prefix,
|
||||
struct binder_work *w)
|
||||
{
|
||||
struct binder_node *node;
|
||||
struct binder_transaction *t;
|
||||
|
|
@ -3080,7 +3126,8 @@ static char *print_binder_work(char *buf, char *end, const char *prefix,
|
|||
case BINDER_WORK_NODE:
|
||||
node = container_of(w, struct binder_node, work);
|
||||
buf += snprintf(buf, end - buf, "%snode work %d: u%p c%p\n",
|
||||
prefix, node->debug_id, node->ptr, node->cookie);
|
||||
prefix, node->debug_id, node->ptr,
|
||||
node->cookie);
|
||||
break;
|
||||
case BINDER_WORK_DEAD_BINDER:
|
||||
buf += snprintf(buf, end - buf, "%shas dead binder\n", prefix);
|
||||
|
|
@ -3101,27 +3148,33 @@ static char *print_binder_work(char *buf, char *end, const char *prefix,
|
|||
return buf;
|
||||
}
|
||||
|
||||
static char *print_binder_thread(char *buf, char *end, struct binder_thread *thread, int print_always)
|
||||
static char *print_binder_thread(char *buf, char *end,
|
||||
struct binder_thread *thread,
|
||||
int print_always)
|
||||
{
|
||||
struct binder_transaction *t;
|
||||
struct binder_work *w;
|
||||
char *start_buf = buf;
|
||||
char *header_buf;
|
||||
|
||||
buf += snprintf(buf, end - buf, " thread %d: l %02x\n", thread->pid, thread->looper);
|
||||
buf += snprintf(buf, end - buf, " thread %d: l %02x\n",
|
||||
thread->pid, thread->looper);
|
||||
header_buf = buf;
|
||||
t = thread->transaction_stack;
|
||||
while (t) {
|
||||
if (buf >= end)
|
||||
break;
|
||||
if (t->from == thread) {
|
||||
buf = print_binder_transaction(buf, end, " outgoing transaction", t);
|
||||
buf = print_binder_transaction(buf, end,
|
||||
" outgoing transaction", t);
|
||||
t = t->from_parent;
|
||||
} else if (t->to_thread == thread) {
|
||||
buf = print_binder_transaction(buf, end, " incoming transaction", t);
|
||||
buf = print_binder_transaction(buf, end,
|
||||
" incoming transaction", t);
|
||||
t = t->to_parent;
|
||||
} else {
|
||||
buf = print_binder_transaction(buf, end, " bad transaction", t);
|
||||
buf = print_binder_transaction(buf, end,
|
||||
" bad transaction", t);
|
||||
t = NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -3142,11 +3195,14 @@ static char *print_binder_node(char *buf, char *end, struct binder_node *node)
|
|||
struct hlist_node *pos;
|
||||
struct binder_work *w;
|
||||
int count;
|
||||
|
||||
count = 0;
|
||||
hlist_for_each_entry(ref, pos, &node->refs, node_entry)
|
||||
count++;
|
||||
|
||||
buf += snprintf(buf, end - buf, " node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d",
|
||||
buf += snprintf(buf, end - buf,
|
||||
" node %d: u%p c%p hs %d hw %d ls %d lw %d "
|
||||
"is %d iw %d",
|
||||
node->debug_id, node->ptr, node->cookie,
|
||||
node->has_strong_ref, node->has_weak_ref,
|
||||
node->local_strong_refs, node->local_weak_refs,
|
||||
|
|
@ -3175,13 +3231,16 @@ static char *print_binder_node(char *buf, char *end, struct binder_node *node)
|
|||
|
||||
static char *print_binder_ref(char *buf, char *end, struct binder_ref *ref)
|
||||
{
|
||||
buf += snprintf(buf, end - buf, " ref %d: desc %d %snode %d s %d w %d d %p\n",
|
||||
ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ",
|
||||
ref->node->debug_id, ref->strong, ref->weak, ref->death);
|
||||
buf += snprintf(buf, end - buf,
|
||||
" ref %d: desc %d %snode %d s %d w %d d %p\n",
|
||||
ref->debug_id, ref->desc,
|
||||
ref->node->proc ? "" : "dead ", ref->node->debug_id,
|
||||
ref->strong, ref->weak, ref->death);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static char *print_binder_proc(char *buf, char *end, struct binder_proc *proc, int print_all)
|
||||
static char *print_binder_proc(char *buf, char *end,
|
||||
struct binder_proc *proc, int print_all)
|
||||
{
|
||||
struct binder_work *w;
|
||||
struct rb_node *n;
|
||||
|
|
@ -3191,19 +3250,34 @@ static char *print_binder_proc(char *buf, char *end, struct binder_proc *proc, i
|
|||
buf += snprintf(buf, end - buf, "proc %d\n", proc->pid);
|
||||
header_buf = buf;
|
||||
|
||||
for (n = rb_first(&proc->threads); n != NULL && buf < end; n = rb_next(n))
|
||||
buf = print_binder_thread(buf, end, rb_entry(n, struct binder_thread, rb_node), print_all);
|
||||
for (n = rb_first(&proc->nodes); n != NULL && buf < end; n = rb_next(n)) {
|
||||
struct binder_node *node = rb_entry(n, struct binder_node, rb_node);
|
||||
for (n = rb_first(&proc->threads);
|
||||
n != NULL && buf < end;
|
||||
n = rb_next(n))
|
||||
buf = print_binder_thread(buf, end,
|
||||
rb_entry(n, struct binder_thread,
|
||||
rb_node), print_all);
|
||||
for (n = rb_first(&proc->nodes);
|
||||
n != NULL && buf < end;
|
||||
n = rb_next(n)) {
|
||||
struct binder_node *node = rb_entry(n, struct binder_node,
|
||||
rb_node);
|
||||
if (print_all || node->has_async_transaction)
|
||||
buf = print_binder_node(buf, end, node);
|
||||
}
|
||||
if (print_all) {
|
||||
for (n = rb_first(&proc->refs_by_desc); n != NULL && buf < end; n = rb_next(n))
|
||||
buf = print_binder_ref(buf, end, rb_entry(n, struct binder_ref, rb_node_desc));
|
||||
for (n = rb_first(&proc->refs_by_desc);
|
||||
n != NULL && buf < end;
|
||||
n = rb_next(n))
|
||||
buf = print_binder_ref(buf, end,
|
||||
rb_entry(n, struct binder_ref,
|
||||
rb_node_desc));
|
||||
}
|
||||
for (n = rb_first(&proc->allocated_buffers); n != NULL && buf < end; n = rb_next(n))
|
||||
buf = print_binder_buffer(buf, end, " buffer", rb_entry(n, struct binder_buffer, rb_node));
|
||||
for (n = rb_first(&proc->allocated_buffers);
|
||||
n != NULL && buf < end;
|
||||
n = rb_next(n))
|
||||
buf = print_binder_buffer(buf, end, " buffer",
|
||||
rb_entry(n, struct binder_buffer,
|
||||
rb_node));
|
||||
list_for_each_entry(w, &proc->todo, entry) {
|
||||
if (buf >= end)
|
||||
break;
|
||||
|
|
@ -3213,7 +3287,8 @@ static char *print_binder_proc(char *buf, char *end, struct binder_proc *proc, i
|
|||
list_for_each_entry(w, &proc->delivered_death, entry) {
|
||||
if (buf >= end)
|
||||
break;
|
||||
buf += snprintf(buf, end - buf, " has delivered dead binder\n");
|
||||
buf += snprintf(buf, end - buf,
|
||||
" has delivered dead binder\n");
|
||||
break;
|
||||
}
|
||||
if (!print_all && buf == header_buf)
|
||||
|
|
@ -3272,20 +3347,24 @@ static const char *binder_objstat_strings[] = {
|
|||
"transaction_complete"
|
||||
};
|
||||
|
||||
static char *print_binder_stats(char *buf, char *end, const char *prefix, struct binder_stats *stats)
|
||||
static char *print_binder_stats(char *buf, char *end, const char *prefix,
|
||||
struct binder_stats *stats)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->bc) != ARRAY_SIZE(binder_command_strings));
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->bc) !=
|
||||
ARRAY_SIZE(binder_command_strings));
|
||||
for (i = 0; i < ARRAY_SIZE(stats->bc); i++) {
|
||||
if (stats->bc[i])
|
||||
buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix,
|
||||
binder_command_strings[i], stats->bc[i]);
|
||||
binder_command_strings[i],
|
||||
stats->bc[i]);
|
||||
if (buf >= end)
|
||||
return buf;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->br) != ARRAY_SIZE(binder_return_strings));
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->br) !=
|
||||
ARRAY_SIZE(binder_return_strings));
|
||||
for (i = 0; i < ARRAY_SIZE(stats->br); i++) {
|
||||
if (stats->br[i])
|
||||
buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix,
|
||||
|
|
@ -3294,13 +3373,17 @@ static char *print_binder_stats(char *buf, char *end, const char *prefix, struct
|
|||
return buf;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != ARRAY_SIZE(binder_objstat_strings));
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != ARRAY_SIZE(stats->obj_deleted));
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
|
||||
ARRAY_SIZE(binder_objstat_strings));
|
||||
BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) !=
|
||||
ARRAY_SIZE(stats->obj_deleted));
|
||||
for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) {
|
||||
if (stats->obj_created[i] || stats->obj_deleted[i])
|
||||
buf += snprintf(buf, end - buf, "%s%s: active %d total %d\n", prefix,
|
||||
buf += snprintf(buf, end - buf,
|
||||
"%s%s: active %d total %d\n", prefix,
|
||||
binder_objstat_strings[i],
|
||||
stats->obj_created[i] - stats->obj_deleted[i],
|
||||
stats->obj_created[i] -
|
||||
stats->obj_deleted[i],
|
||||
stats->obj_created[i]);
|
||||
if (buf >= end)
|
||||
return buf;
|
||||
|
|
@ -3308,7 +3391,8 @@ static char *print_binder_stats(char *buf, char *end, const char *prefix, struct
|
|||
return buf;
|
||||
}
|
||||
|
||||
static char *print_binder_proc_stats(char *buf, char *end, struct binder_proc *proc)
|
||||
static char *print_binder_proc_stats(char *buf, char *end,
|
||||
struct binder_proc *proc)
|
||||
{
|
||||
struct binder_work *w;
|
||||
struct rb_node *n;
|
||||
|
|
@ -3340,12 +3424,14 @@ static char *print_binder_proc_stats(char *buf, char *end, struct binder_proc *p
|
|||
strong = 0;
|
||||
weak = 0;
|
||||
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
|
||||
struct binder_ref *ref = rb_entry(n, struct binder_ref, rb_node_desc);
|
||||
struct binder_ref *ref = rb_entry(n, struct binder_ref,
|
||||
rb_node_desc);
|
||||
count++;
|
||||
strong += ref->strong;
|
||||
weak += ref->weak;
|
||||
}
|
||||
buf += snprintf(buf, end - buf, " refs: %d s %d w %d\n", count, strong, weak);
|
||||
buf += snprintf(buf, end - buf, " refs: %d s %d w %d\n",
|
||||
count, strong, weak);
|
||||
if (buf >= end)
|
||||
return buf;
|
||||
|
||||
|
|
@ -3376,8 +3462,8 @@ static char *print_binder_proc_stats(char *buf, char *end, struct binder_proc *p
|
|||
}
|
||||
|
||||
|
||||
static int binder_read_proc_state(
|
||||
char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
static int binder_read_proc_state(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
struct hlist_node *pos;
|
||||
|
|
@ -3424,8 +3510,8 @@ static int binder_read_proc_state(
|
|||
return len < count ? len : count;
|
||||
}
|
||||
|
||||
static int binder_read_proc_stats(
|
||||
char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
static int binder_read_proc_stats(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
struct hlist_node *pos;
|
||||
|
|
@ -3464,8 +3550,8 @@ static int binder_read_proc_stats(
|
|||
return len < count ? len : count;
|
||||
}
|
||||
|
||||
static int binder_read_proc_transactions(
|
||||
char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
static int binder_read_proc_transactions(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
struct hlist_node *pos;
|
||||
|
|
@ -3502,8 +3588,8 @@ static int binder_read_proc_transactions(
|
|||
return len < count ? len : count;
|
||||
}
|
||||
|
||||
static int binder_read_proc_proc(
|
||||
char *page, char **start, off_t off, int count, int *eof, void *data)
|
||||
static int binder_read_proc_proc(char *page, char **start, off_t off,
|
||||
int count, int *eof, void *data)
|
||||
{
|
||||
struct binder_proc *proc = data;
|
||||
int len = 0;
|
||||
|
|
@ -3533,9 +3619,12 @@ static int binder_read_proc_proc(
|
|||
return len < count ? len : count;
|
||||
}
|
||||
|
||||
static char *print_binder_transaction_log_entry(char *buf, char *end, struct binder_transaction_log_entry *e)
|
||||
static char *print_binder_transaction_log_entry(char *buf, char *end,
|
||||
struct binder_transaction_log_entry *e)
|
||||
{
|
||||
buf += snprintf(buf, end - buf, "%d: %s from %d:%d to %d:%d node %d handle %d size %d:%d\n",
|
||||
buf += snprintf(buf, end - buf,
|
||||
"%d: %s from %d:%d to %d:%d node %d handle %d "
|
||||
"size %d:%d\n",
|
||||
e->debug_id, (e->call_type == 2) ? "reply" :
|
||||
((e->call_type == 1) ? "async" : "call "), e->from_proc,
|
||||
e->from_thread, e->to_proc, e->to_thread, e->to_node,
|
||||
|
|
@ -3559,13 +3648,15 @@ static int binder_read_proc_transaction_log(
|
|||
for (i = log->next; i < ARRAY_SIZE(log->entry); i++) {
|
||||
if (buf >= end)
|
||||
break;
|
||||
buf = print_binder_transaction_log_entry(buf, end, &log->entry[i]);
|
||||
buf = print_binder_transaction_log_entry(buf, end,
|
||||
&log->entry[i]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < log->next; i++) {
|
||||
if (buf >= end)
|
||||
break;
|
||||
buf = print_binder_transaction_log_entry(buf, end, &log->entry[i]);
|
||||
buf = print_binder_transaction_log_entry(buf, end,
|
||||
&log->entry[i]);
|
||||
}
|
||||
|
||||
*start = page + off;
|
||||
|
|
@ -3579,7 +3670,7 @@ static int binder_read_proc_transaction_log(
|
|||
return len < count ? len : count;
|
||||
}
|
||||
|
||||
static struct file_operations binder_fops = {
|
||||
static const struct file_operations binder_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.poll = binder_poll,
|
||||
.unlocked_ioctl = binder_ioctl,
|
||||
|
|
@ -3601,14 +3692,35 @@ static int __init binder_init(void)
|
|||
|
||||
binder_proc_dir_entry_root = proc_mkdir("binder", NULL);
|
||||
if (binder_proc_dir_entry_root)
|
||||
binder_proc_dir_entry_proc = proc_mkdir("proc", binder_proc_dir_entry_root);
|
||||
binder_proc_dir_entry_proc = proc_mkdir("proc",
|
||||
binder_proc_dir_entry_root);
|
||||
ret = misc_register(&binder_miscdev);
|
||||
if (binder_proc_dir_entry_root) {
|
||||
create_proc_read_entry("state", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_state, NULL);
|
||||
create_proc_read_entry("stats", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_stats, NULL);
|
||||
create_proc_read_entry("transactions", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transactions, NULL);
|
||||
create_proc_read_entry("transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log);
|
||||
create_proc_read_entry("failed_transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log_failed);
|
||||
create_proc_read_entry("state",
|
||||
S_IRUGO,
|
||||
binder_proc_dir_entry_root,
|
||||
binder_read_proc_state,
|
||||
NULL);
|
||||
create_proc_read_entry("stats",
|
||||
S_IRUGO,
|
||||
binder_proc_dir_entry_root,
|
||||
binder_read_proc_stats,
|
||||
NULL);
|
||||
create_proc_read_entry("transactions",
|
||||
S_IRUGO,
|
||||
binder_proc_dir_entry_root,
|
||||
binder_read_proc_transactions,
|
||||
NULL);
|
||||
create_proc_read_entry("transaction_log",
|
||||
S_IRUGO,
|
||||
binder_proc_dir_entry_root,
|
||||
binder_read_proc_transaction_log,
|
||||
&binder_transaction_log);
|
||||
create_proc_read_entry("failed_transaction_log",
|
||||
S_IRUGO,
|
||||
binder_proc_dir_entry_root,
|
||||
binder_read_proc_transaction_log,
|
||||
&binder_transaction_log_failed);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
* mutex 'mutex'.
|
||||
*/
|
||||
struct logger_log {
|
||||
unsigned char * buffer; /* the ring buffer itself */
|
||||
unsigned char *buffer;/* the ring buffer itself */
|
||||
struct miscdevice misc; /* misc device representing the log */
|
||||
wait_queue_head_t wq; /* wait queue for readers */
|
||||
struct list_head readers; /* this log's readers */
|
||||
|
|
@ -52,7 +52,7 @@ struct logger_log {
|
|||
* reference counting. The structure is protected by log->mutex.
|
||||
*/
|
||||
struct logger_reader {
|
||||
struct logger_log * log; /* associated log */
|
||||
struct logger_log *log; /* associated log */
|
||||
struct list_head list; /* entry in logger_log's list */
|
||||
size_t r_off; /* current read head offset */
|
||||
};
|
||||
|
|
@ -74,7 +74,7 @@ struct logger_reader {
|
|||
* file->logger_log. Thus what file->private_data points at depends on whether
|
||||
* or not the file was opened for reading. This function hides that dirtiness.
|
||||
*/
|
||||
static inline struct logger_log * file_get_log(struct file *file)
|
||||
static inline struct logger_log *file_get_log(struct file *file)
|
||||
{
|
||||
if (file->f_mode & FMODE_READ) {
|
||||
struct logger_reader *reader = file->private_data;
|
||||
|
|
@ -379,7 +379,7 @@ ssize_t logger_aio_write(struct kiocb *iocb, const struct iovec *iov,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct logger_log * get_log_from_minor(int);
|
||||
static struct logger_log *get_log_from_minor(int);
|
||||
|
||||
/*
|
||||
* logger_open - the log's open() file operation
|
||||
|
|
@ -519,7 +519,7 @@ static long logger_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static struct file_operations logger_fops = {
|
||||
static const struct file_operations logger_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = logger_read,
|
||||
.aio_write = logger_aio_write,
|
||||
|
|
@ -557,7 +557,7 @@ DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024)
|
|||
DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024)
|
||||
|
||||
static struct logger_log * get_log_from_minor(int minor)
|
||||
static struct logger_log *get_log_from_minor(int minor)
|
||||
{
|
||||
if (log_main.misc.minor == minor)
|
||||
return &log_main;
|
||||
|
|
|
|||
|
|
@ -34,18 +34,24 @@ static int lowmem_adj[6] = {
|
|||
};
|
||||
static int lowmem_adj_size = 4;
|
||||
static size_t lowmem_minfree[6] = {
|
||||
3*512, // 6MB
|
||||
2*1024, // 8MB
|
||||
4*1024, // 16MB
|
||||
16*1024, // 64MB
|
||||
3 * 512, /* 6MB */
|
||||
2 * 1024, /* 8MB */
|
||||
4 * 1024, /* 16MB */
|
||||
16 * 1024, /* 64MB */
|
||||
};
|
||||
static int lowmem_minfree_size = 4;
|
||||
|
||||
#define lowmem_print(level, x...) do { if(lowmem_debug_level >= (level)) printk(x); } while(0)
|
||||
#define lowmem_print(level, x...) \
|
||||
do { \
|
||||
if (lowmem_debug_level >= (level)) \
|
||||
printk(x); \
|
||||
} while (0)
|
||||
|
||||
module_param_named(cost, lowmem_shrinker.seeks, int, S_IRUGO | S_IWUSR);
|
||||
module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size, S_IRUGO | S_IWUSR);
|
||||
module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size, S_IRUGO | S_IWUSR);
|
||||
module_param_array_named(adj, lowmem_adj, int, &lowmem_adj_size,
|
||||
S_IRUGO | S_IWUSR);
|
||||
module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
|
||||
S_IRUGO | S_IWUSR);
|
||||
module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
|
||||
|
||||
static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
|
||||
|
|
@ -57,46 +63,77 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
|
|||
int i;
|
||||
int min_adj = OOM_ADJUST_MAX + 1;
|
||||
int selected_tasksize = 0;
|
||||
int selected_oom_adj;
|
||||
int array_size = ARRAY_SIZE(lowmem_adj);
|
||||
int other_free = global_page_state(NR_FREE_PAGES) + global_page_state(NR_FILE_PAGES);
|
||||
if(lowmem_adj_size < array_size)
|
||||
int other_free = global_page_state(NR_FREE_PAGES);
|
||||
int other_file = global_page_state(NR_FILE_PAGES);
|
||||
|
||||
if (lowmem_adj_size < array_size)
|
||||
array_size = lowmem_adj_size;
|
||||
if(lowmem_minfree_size < array_size)
|
||||
if (lowmem_minfree_size < array_size)
|
||||
array_size = lowmem_minfree_size;
|
||||
for(i = 0; i < array_size; i++) {
|
||||
if(other_free < lowmem_minfree[i]) {
|
||||
for (i = 0; i < array_size; i++) {
|
||||
if (other_free < lowmem_minfree[i] &&
|
||||
other_file < lowmem_minfree[i]) {
|
||||
min_adj = lowmem_adj[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(nr_to_scan > 0)
|
||||
lowmem_print(3, "lowmem_shrink %d, %x, ofree %d, ma %d\n", nr_to_scan, gfp_mask, other_free, min_adj);
|
||||
if (nr_to_scan > 0)
|
||||
lowmem_print(3, "lowmem_shrink %d, %x, ofree %d %d, ma %d\n",
|
||||
nr_to_scan, gfp_mask, other_free, other_file,
|
||||
min_adj);
|
||||
rem = global_page_state(NR_ACTIVE_ANON) +
|
||||
global_page_state(NR_ACTIVE_FILE) +
|
||||
global_page_state(NR_INACTIVE_ANON) +
|
||||
global_page_state(NR_INACTIVE_FILE);
|
||||
if (nr_to_scan <= 0 || min_adj == OOM_ADJUST_MAX + 1) {
|
||||
lowmem_print(5, "lowmem_shrink %d, %x, return %d\n",
|
||||
nr_to_scan, gfp_mask, rem);
|
||||
return rem;
|
||||
}
|
||||
selected_oom_adj = min_adj;
|
||||
|
||||
read_lock(&tasklist_lock);
|
||||
for_each_process(p) {
|
||||
if(p->oomkilladj >= 0 && p->mm) {
|
||||
tasksize = get_mm_rss(p->mm);
|
||||
if(nr_to_scan > 0 && tasksize > 0 && p->oomkilladj >= min_adj) {
|
||||
if(selected == NULL ||
|
||||
p->oomkilladj > selected->oomkilladj ||
|
||||
(p->oomkilladj == selected->oomkilladj &&
|
||||
tasksize > selected_tasksize)) {
|
||||
selected = p;
|
||||
selected_tasksize = tasksize;
|
||||
lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
|
||||
p->pid, p->comm, p->oomkilladj, tasksize);
|
||||
}
|
||||
}
|
||||
rem += tasksize;
|
||||
int oom_adj;
|
||||
|
||||
task_lock(p);
|
||||
if (!p->mm) {
|
||||
task_unlock(p);
|
||||
continue;
|
||||
}
|
||||
oom_adj = p->oomkilladj;
|
||||
if (oom_adj < min_adj) {
|
||||
task_unlock(p);
|
||||
continue;
|
||||
}
|
||||
tasksize = get_mm_rss(p->mm);
|
||||
task_unlock(p);
|
||||
if (tasksize <= 0)
|
||||
continue;
|
||||
if (selected) {
|
||||
if (oom_adj < selected_oom_adj)
|
||||
continue;
|
||||
if (oom_adj == selected_oom_adj &&
|
||||
tasksize <= selected_tasksize)
|
||||
continue;
|
||||
}
|
||||
selected = p;
|
||||
selected_tasksize = tasksize;
|
||||
selected_oom_adj = oom_adj;
|
||||
lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",
|
||||
p->pid, p->comm, oom_adj, tasksize);
|
||||
}
|
||||
if(selected != NULL) {
|
||||
if (selected) {
|
||||
lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
|
||||
selected->pid, selected->comm,
|
||||
selected->oomkilladj, selected_tasksize);
|
||||
selected->pid, selected->comm,
|
||||
selected_oom_adj, selected_tasksize);
|
||||
force_sig(SIGKILL, selected);
|
||||
rem -= selected_tasksize;
|
||||
}
|
||||
lowmem_print(4, "lowmem_shrink %d, %x, return %d\n", nr_to_scan, gfp_mask, rem);
|
||||
lowmem_print(4, "lowmem_shrink %d, %x, return %d\n",
|
||||
nr_to_scan, gfp_mask, rem);
|
||||
read_unlock(&tasklist_lock);
|
||||
return rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include <linux/proc_fs.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#ifdef CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION
|
||||
#include <linux/rslib.h>
|
||||
|
|
@ -225,8 +225,9 @@ static int __init ram_console_init(struct ram_console_buffer *buffer,
|
|||
buffer_size - sizeof(struct ram_console_buffer);
|
||||
|
||||
if (ram_console_buffer_size > buffer_size) {
|
||||
pr_err("ram_console: buffer %p, invalid size %zu, datasize %zu\n",
|
||||
buffer, buffer_size, ram_console_buffer_size);
|
||||
pr_err("ram_console: buffer %p, invalid size %zu, "
|
||||
"datasize %zu\n", buffer, buffer_size,
|
||||
ram_console_buffer_size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -365,7 +366,7 @@ static ssize_t ram_console_read_old(struct file *file, char __user *buf,
|
|||
return count;
|
||||
}
|
||||
|
||||
static struct file_operations ram_console_file_ops = {
|
||||
static const struct file_operations ram_console_file_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = ram_console_read_old,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,13 +20,12 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include "timed_output.h"
|
||||
#include "timed_gpio.h"
|
||||
|
||||
|
||||
static struct class *timed_gpio_class;
|
||||
|
||||
struct timed_gpio_data {
|
||||
struct device *dev;
|
||||
struct timed_output_dev dev;
|
||||
struct hrtimer timer;
|
||||
spinlock_t lock;
|
||||
unsigned gpio;
|
||||
|
|
@ -36,70 +35,62 @@ struct timed_gpio_data {
|
|||
|
||||
static enum hrtimer_restart gpio_timer_func(struct hrtimer *timer)
|
||||
{
|
||||
struct timed_gpio_data *gpio_data = container_of(timer, struct timed_gpio_data, timer);
|
||||
struct timed_gpio_data *data =
|
||||
container_of(timer, struct timed_gpio_data, timer);
|
||||
|
||||
gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? 1 : 0);
|
||||
gpio_direction_output(data->gpio, data->active_low ? 1 : 0);
|
||||
return HRTIMER_NORESTART;
|
||||
}
|
||||
|
||||
static ssize_t gpio_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
static int gpio_get_time(struct timed_output_dev *dev)
|
||||
{
|
||||
struct timed_gpio_data *gpio_data = dev_get_drvdata(dev);
|
||||
int remaining;
|
||||
struct timed_gpio_data *data =
|
||||
container_of(dev, struct timed_gpio_data, dev);
|
||||
|
||||
if (hrtimer_active(&gpio_data->timer)) {
|
||||
ktime_t r = hrtimer_get_remaining(&gpio_data->timer);
|
||||
if (hrtimer_active(&data->timer)) {
|
||||
ktime_t r = hrtimer_get_remaining(&data->timer);
|
||||
struct timeval t = ktime_to_timeval(r);
|
||||
remaining = t.tv_sec * 1000 + t.tv_usec / 1000;
|
||||
return t.tv_sec * 1000 + t.tv_usec / 1000;
|
||||
} else
|
||||
remaining = 0;
|
||||
|
||||
return sprintf(buf, "%d\n", remaining);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t gpio_enable_store(
|
||||
struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
static void gpio_enable(struct timed_output_dev *dev, int value)
|
||||
{
|
||||
struct timed_gpio_data *gpio_data = dev_get_drvdata(dev);
|
||||
int value;
|
||||
struct timed_gpio_data *data =
|
||||
container_of(dev, struct timed_gpio_data, dev);
|
||||
unsigned long flags;
|
||||
|
||||
sscanf(buf, "%d", &value);
|
||||
|
||||
spin_lock_irqsave(&gpio_data->lock, flags);
|
||||
spin_lock_irqsave(&data->lock, flags);
|
||||
|
||||
/* cancel previous timer and set GPIO according to value */
|
||||
hrtimer_cancel(&gpio_data->timer);
|
||||
gpio_direction_output(gpio_data->gpio, gpio_data->active_low ? !value : !!value);
|
||||
hrtimer_cancel(&data->timer);
|
||||
gpio_direction_output(data->gpio, data->active_low ? !value : !!value);
|
||||
|
||||
if (value > 0) {
|
||||
if (value > gpio_data->max_timeout)
|
||||
value = gpio_data->max_timeout;
|
||||
if (value > data->max_timeout)
|
||||
value = data->max_timeout;
|
||||
|
||||
hrtimer_start(&gpio_data->timer,
|
||||
ktime_set(value / 1000, (value % 1000) * 1000000),
|
||||
HRTIMER_MODE_REL);
|
||||
hrtimer_start(&data->timer,
|
||||
ktime_set(value / 1000, (value % 1000) * 1000000),
|
||||
HRTIMER_MODE_REL);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&gpio_data->lock, flags);
|
||||
|
||||
return size;
|
||||
spin_unlock_irqrestore(&data->lock, flags);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, gpio_enable_show, gpio_enable_store);
|
||||
|
||||
static int timed_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct timed_gpio_platform_data *pdata = pdev->dev.platform_data;
|
||||
struct timed_gpio *cur_gpio;
|
||||
struct timed_gpio_data *gpio_data, *gpio_dat;
|
||||
int i, ret = 0;
|
||||
int i, j, ret = 0;
|
||||
|
||||
if (!pdata)
|
||||
return -EBUSY;
|
||||
|
||||
gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios, GFP_KERNEL);
|
||||
gpio_data = kzalloc(sizeof(struct timed_gpio_data) * pdata->num_gpios,
|
||||
GFP_KERNEL);
|
||||
if (!gpio_data)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
@ -107,23 +98,26 @@ static int timed_gpio_probe(struct platform_device *pdev)
|
|||
cur_gpio = &pdata->gpios[i];
|
||||
gpio_dat = &gpio_data[i];
|
||||
|
||||
hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
hrtimer_init(&gpio_dat->timer, CLOCK_MONOTONIC,
|
||||
HRTIMER_MODE_REL);
|
||||
gpio_dat->timer.function = gpio_timer_func;
|
||||
spin_lock_init(&gpio_dat->lock);
|
||||
|
||||
gpio_dat->dev.name = cur_gpio->name;
|
||||
gpio_dat->dev.get_time = gpio_get_time;
|
||||
gpio_dat->dev.enable = gpio_enable;
|
||||
ret = timed_output_dev_register(&gpio_dat->dev);
|
||||
if (ret < 0) {
|
||||
for (j = 0; j < i; j++)
|
||||
timed_output_dev_unregister(&gpio_data[i].dev);
|
||||
kfree(gpio_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio_dat->gpio = cur_gpio->gpio;
|
||||
gpio_dat->max_timeout = cur_gpio->max_timeout;
|
||||
gpio_dat->active_low = cur_gpio->active_low;
|
||||
gpio_direction_output(gpio_dat->gpio, gpio_dat->active_low);
|
||||
|
||||
gpio_dat->dev = device_create(timed_gpio_class, &pdev->dev, 0, "%s", cur_gpio->name);
|
||||
if (unlikely(IS_ERR(gpio_dat->dev)))
|
||||
return PTR_ERR(gpio_dat->dev);
|
||||
|
||||
dev_set_drvdata(gpio_dat->dev, gpio_dat);
|
||||
ret = device_create_file(gpio_dat->dev, &dev_attr_enable);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, gpio_data);
|
||||
|
|
@ -137,10 +131,8 @@ static int timed_gpio_remove(struct platform_device *pdev)
|
|||
struct timed_gpio_data *gpio_data = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pdata->num_gpios; i++) {
|
||||
device_remove_file(gpio_data[i].dev, &dev_attr_enable);
|
||||
device_unregister(gpio_data[i].dev);
|
||||
}
|
||||
for (i = 0; i < pdata->num_gpios; i++)
|
||||
timed_output_dev_unregister(&gpio_data[i].dev);
|
||||
|
||||
kfree(gpio_data);
|
||||
|
||||
|
|
@ -151,22 +143,18 @@ static struct platform_driver timed_gpio_driver = {
|
|||
.probe = timed_gpio_probe,
|
||||
.remove = timed_gpio_remove,
|
||||
.driver = {
|
||||
.name = "timed-gpio",
|
||||
.name = TIMED_GPIO_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init timed_gpio_init(void)
|
||||
{
|
||||
timed_gpio_class = class_create(THIS_MODULE, "timed_output");
|
||||
if (IS_ERR(timed_gpio_class))
|
||||
return PTR_ERR(timed_gpio_class);
|
||||
return platform_driver_register(&timed_gpio_driver);
|
||||
}
|
||||
|
||||
static void __exit timed_gpio_exit(void)
|
||||
{
|
||||
class_destroy(timed_gpio_class);
|
||||
platform_driver_unregister(&timed_gpio_driver);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,10 +16,12 @@
|
|||
#ifndef _LINUX_TIMED_GPIO_H
|
||||
#define _LINUX_TIMED_GPIO_H
|
||||
|
||||
#define TIMED_GPIO_NAME "timed-gpio"
|
||||
|
||||
struct timed_gpio {
|
||||
const char *name;
|
||||
unsigned gpio;
|
||||
int max_timeout;
|
||||
int max_timeout;
|
||||
u8 active_low;
|
||||
};
|
||||
|
||||
|
|
|
|||
121
drivers/staging/android/timed_output.c
Normal file
121
drivers/staging/android/timed_output.c
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/* drivers/misc/timed_output.c
|
||||
*
|
||||
* Copyright (C) 2009 Google, Inc.
|
||||
* Author: Mike Lockwood <lockwood@android.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include "timed_output.h"
|
||||
|
||||
static struct class *timed_output_class;
|
||||
static atomic_t device_count;
|
||||
|
||||
static ssize_t enable_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct timed_output_dev *tdev = dev_get_drvdata(dev);
|
||||
int remaining = tdev->get_time(tdev);
|
||||
|
||||
return sprintf(buf, "%d\n", remaining);
|
||||
}
|
||||
|
||||
static ssize_t enable_store(
|
||||
struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t size)
|
||||
{
|
||||
struct timed_output_dev *tdev = dev_get_drvdata(dev);
|
||||
int value;
|
||||
|
||||
sscanf(buf, "%d", &value);
|
||||
tdev->enable(tdev, value);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, enable_show, enable_store);
|
||||
|
||||
static int create_timed_output_class(void)
|
||||
{
|
||||
if (!timed_output_class) {
|
||||
timed_output_class = class_create(THIS_MODULE, "timed_output");
|
||||
if (IS_ERR(timed_output_class))
|
||||
return PTR_ERR(timed_output_class);
|
||||
atomic_set(&device_count, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int timed_output_dev_register(struct timed_output_dev *tdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!tdev || !tdev->name || !tdev->enable || !tdev->get_time)
|
||||
return -EINVAL;
|
||||
|
||||
ret = create_timed_output_class();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tdev->index = atomic_inc_return(&device_count);
|
||||
tdev->dev = device_create(timed_output_class, NULL,
|
||||
MKDEV(0, tdev->index), NULL, tdev->name);
|
||||
if (IS_ERR(tdev->dev))
|
||||
return PTR_ERR(tdev->dev);
|
||||
|
||||
ret = device_create_file(tdev->dev, &dev_attr_enable);
|
||||
if (ret < 0)
|
||||
goto err_create_file;
|
||||
|
||||
dev_set_drvdata(tdev->dev, tdev);
|
||||
tdev->state = 0;
|
||||
return 0;
|
||||
|
||||
err_create_file:
|
||||
device_destroy(timed_output_class, MKDEV(0, tdev->index));
|
||||
printk(KERN_ERR "timed_output: Failed to register driver %s\n",
|
||||
tdev->name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timed_output_dev_register);
|
||||
|
||||
void timed_output_dev_unregister(struct timed_output_dev *tdev)
|
||||
{
|
||||
device_remove_file(tdev->dev, &dev_attr_enable);
|
||||
device_destroy(timed_output_class, MKDEV(0, tdev->index));
|
||||
dev_set_drvdata(tdev->dev, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(timed_output_dev_unregister);
|
||||
|
||||
static int __init timed_output_init(void)
|
||||
{
|
||||
return create_timed_output_class();
|
||||
}
|
||||
|
||||
static void __exit timed_output_exit(void)
|
||||
{
|
||||
class_destroy(timed_output_class);
|
||||
}
|
||||
|
||||
module_init(timed_output_init);
|
||||
module_exit(timed_output_exit);
|
||||
|
||||
MODULE_AUTHOR("Mike Lockwood <lockwood@android.com>");
|
||||
MODULE_DESCRIPTION("timed output class driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
37
drivers/staging/android/timed_output.h
Normal file
37
drivers/staging/android/timed_output.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* include/linux/timed_output.h
|
||||
*
|
||||
* Copyright (C) 2008 Google, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_TIMED_OUTPUT_H
|
||||
#define _LINUX_TIMED_OUTPUT_H
|
||||
|
||||
struct timed_output_dev {
|
||||
const char *name;
|
||||
|
||||
/* enable the output and set the timer */
|
||||
void (*enable)(struct timed_output_dev *sdev, int timeout);
|
||||
|
||||
/* returns the current number of milliseconds remaining on the timer */
|
||||
int (*get_time)(struct timed_output_dev *sdev);
|
||||
|
||||
/* private data */
|
||||
struct device *dev;
|
||||
int index;
|
||||
int state;
|
||||
};
|
||||
|
||||
extern int timed_output_dev_register(struct timed_output_dev *dev);
|
||||
extern void timed_output_dev_unregister(struct timed_output_dev *dev);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue