* [PATCH 2/7] tpm: reorganize sysfs files - Updated patch
From: Kylene Jo Hall @ 2006-04-10 14:37 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, TPM Device Driver List
Many of the sysfs files were calling the TPM_GetCapability command with
different options and each command layed out in its own static const
array. Since for 1.2 more sysfs files of this type are coming I am
generalizing the array so there can be one array and the unique parts
can be filled in just before the command is called.
This updated version of the patch addresses the code redundancy and
ugliness in the tpm_show_* functions pointed out by Dave. It replaces
the 2/7 patch from the original set.
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm.c | 147 +++++++++++++++++++++++----------------
1 files changed, 87 insertions(+), 60 deletions(-)
--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-04-03 17:15:58.815947500 -0500
+++ linux-2.6.16-43/drivers/char/tpm/tpm.c 2006-04-03 17:14:02.620685750 -0500
@@ -119,17 +119,57 @@ out:
}
#define TPM_DIGEST_SIZE 20
-#define CAP_PCR_RESULT_SIZE 18
-static const u8 cap_pcr[] = {
+#define TPM_ERROR_SIZE 10
+#define TPM_RET_CODE_IDX 6
+#define TPM_GET_CAP_RET_SIZE_IDX 10
+#define TPM_GET_CAP_RET_UINT32_1_IDX 14
+#define TPM_GET_CAP_RET_UINT32_2_IDX 18
+#define TPM_GET_CAP_RET_UINT32_3_IDX 22
+#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+
+#define TPM_CAP_IDX 13
+#define TPM_CAP_SUBCAP_IDX 21
+
+enum tpm_capabilities {
+ TPM_CAP_PROP = 5,
+};
+
+enum tpm_sub_capabilities {
+ TPM_CAP_PROP_PCR = 0x1,
+ TPM_CAP_PROP_MANUFACTURER = 0x3,
+};
+
+/*
+ * This is a semi generic GetCapability command for use
+ * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG
+ * and their associated sub_capabilities.
+ */
+
+static const u8 tpm_cap[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 22, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 1
+ 0, 0, 0, 0, /* TPM_CAP_<TYPE> */
+ 0, 0, 0, 4, /* TPM_CAP_SUB_<TYPE> size */
+ 0, 0, 1, 0 /* TPM_CAP_SUB_<TYPE> */
};
-#define READ_PCR_RESULT_SIZE 30
+static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len,
+ char *desc)
+{
+ int err;
+
+ len = tpm_transmit(chip, data, len);
+ if (len < 0)
+ return len;
+ if (len == TPM_ERROR_SIZE) {
+ err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)));
+ dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+ return err;
+ }
+ return 0;
+}
+
static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
@@ -140,8 +180,8 @@ static const u8 pcrread[] = {
ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[READ_PCR_RESULT_SIZE];
- ssize_t len;
+ u8 data[30];
+ ssize_t rc;
int i, j, num_pcrs;
__be32 index;
char *str = buf;
@@ -150,29 +190,24 @@ ssize_t tpm_show_pcrs(struct device *dev
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_pcr, sizeof(cap_pcr));
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < CAP_PCR_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to determine the number of PCRS\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the number of PCRS");
+ if (rc)
return 0;
- }
num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
-
for (i = 0; i < num_pcrs; i++) {
memcpy(data, pcrread, sizeof(pcrread));
index = cpu_to_be32(i);
memcpy(data + 10, &index, 4);
- if ((len = tpm_transmit(chip, data, sizeof(data)))
- < READ_PCR_RESULT_SIZE){
- dev_dbg(chip->dev, "A TPM error (%d) occurred"
- " attempting to read PCR %d of %d\n",
- be32_to_cpu(*((__be32 *) (data + 6))),
- i, num_pcrs);
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to read a PCR");
+ if (rc)
goto out;
- }
str += sprintf(str, "PCR-%02d: ", i);
for (j = 0; j < TPM_DIGEST_SIZE; j++)
str += sprintf(str, "%02X ", *(data + 10 + j));
@@ -194,7 +229,7 @@ ssize_t tpm_show_pubek(struct device *de
char *buf)
{
u8 *data;
- ssize_t len;
+ ssize_t err;
int i, rc;
char *str = buf;
@@ -208,14 +243,10 @@ ssize_t tpm_show_pubek(struct device *de
memcpy(data, readpubek, sizeof(readpubek));
- if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
- READ_PUBEK_RESULT_SIZE) {
- dev_dbg(chip->dev, "A TPM error (%d) occurred "
- "attempting to read the PUBEK\n",
- be32_to_cpu(*((__be32 *) (data + 6))));
- rc = 0;
+ err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE,
+ "attempting to read the PUBEK");
+ if (err)
goto out;
- }
/*
ignore header 10 bytes
@@ -245,63 +276,59 @@ ssize_t tpm_show_pubek(struct device *de
if ((i + 1) % 16 == 0)
str += sprintf(str, "\n");
}
- rc = str - buf;
out:
+ rc = str - buf;
kfree(data);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_show_pubek);
-#define CAP_VER_RESULT_SIZE 18
+#define CAP_VERSION_1_1 6
+#define CAP_VERSION_IDX 13
static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 18, /* length */
0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 6,
+ 0, 0, 0, 0,
0, 0, 0, 0
};
-#define CAP_MANUFACTURER_RESULT_SIZE 18
-static const u8 cap_manufacturer[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 22, /* length */
- 0, 0, 0, 101, /* TPM_ORD_GetCapability */
- 0, 0, 0, 5,
- 0, 0, 0, 4,
- 0, 0, 1, 3
-};
-
ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
char *buf)
{
- u8 data[sizeof(cap_manufacturer)];
- ssize_t len;
+ u8 data[30];
+ ssize_t rc;
char *str = buf;
struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip == NULL)
return -ENODEV;
- memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
-
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_MANUFACTURER_RESULT_SIZE)
- return len;
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the manufacturer");
+ if (rc)
+ return 0;
str += sprintf(str, "Manufacturer: 0x%x\n",
- be32_to_cpu(*((__be32 *) (data + 14))));
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_1;
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the 1.1 version");
+ if (rc)
+ goto out;
- if ((len = tpm_transmit(chip, data, sizeof(data))) <
- CAP_VER_RESULT_SIZE)
- return len;
-
- str +=
- sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
- (int) data[14], (int) data[15], (int) data[16],
- (int) data[17]);
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[14], (int) data[15], (int) data[16],
+ (int) data[17]);
+out:
return str - buf;
}
EXPORT_SYMBOL_GPL(tpm_show_caps);
^ permalink raw reply
* [PATCH 4/7] tpm: return chip from tpm_register_hardware
From: Kylene Jo Hall @ 2006-04-10 14:37 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, TPM Device Driver List
Changes in the 1.2 TPM Specification make it necessary to update some
fields of the chip structure in the initialization function after it is
registered with tpm.c thus tpm_register_hardware was modified to return
a pointer to the structure. This patch makes that change and the
associated changes in tpm_atmel and tpm_nsc. The changes to
tpm_infineon will be coming in a patch from Marcel Selhorst.
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm.c | 11 ++++++-----
drivers/char/tpm/tpm.h | 10 +++++-----
drivers/char/tpm/tpm_atmel.c | 32 ++++++++++++++++++++++----------
drivers/char/tpm/tpm_atmel.h | 25 +++++++++++--------------
drivers/char/tpm/tpm_nsc.c | 17 +++++++++++------
5 files changed, 55 insertions(+), 40 deletions(-)
--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-03-30 15:39:35.320462000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.c 2006-03-30 16:28:14.690911250 -0600
@@ -558,7 +1095,8 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
* upon errant exit from this function specific probe function should call
* pci_disable_device
*/
-int tpm_register_hardware(struct device *dev, struct tpm_vendor_specific *entry)
+struct tpm_chip *tpm_register_hardware(struct device *dev, const struct tpm_vendor_specific
+ *entry)
{
#define DEVNAME_SIZE 7
@@ -569,7 +1107,7 @@ int tpm_register_hardware(struct device
/* Driver specific per-device data */
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
- return -ENOMEM;
+ return NULL;
init_MUTEX(&chip->buffer_mutex);
init_MUTEX(&chip->tpm_mutex);
@@ -598,7 +1136,7 @@ dev_num_search_complete:
if (chip->dev_num < 0) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
- return -ENODEV;
+ return NULL;
} else if (chip->dev_num == 0)
chip->vendor.miscdev.minor = TPM_MINOR;
else
@@ -619,7 +1157,7 @@ dev_num_search_complete:
put_device(dev);
kfree(chip);
dev_mask[i] &= !(1 << j);
- return -ENODEV;
+ return NULL;
}
spin_lock(&driver_lock);
@@ -634,7 +1172,7 @@ dev_num_search_complete:
chip->bios_dir = tpm_bios_log_setup(devname);
- return 0;
+ return chip;
}
EXPORT_SYMBOL_GPL(tpm_register_hardware);
--- linux-2.6.16/drivers/char/tpm/tpm.h 2006-03-30 15:39:35.320462000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.h 2006-03-29 14:16:30.119053500 -0600
@@ -41,9 +41,9 @@ extern ssize_t tpm_show_pcrs(struct devi
struct tpm_chip;
struct tpm_vendor_specific {
- u8 req_complete_mask;
- u8 req_complete_val;
- u8 req_canceled;
+ const u8 req_complete_mask;
+ const u8 req_complete_val;
+ const u8 req_canceled;
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
@@ -99,8 +114,8 @@ static inline void tpm_write_index(int b
outb(value & 0xFF, base+1);
}
-extern int tpm_register_hardware(struct device *,
- struct tpm_vendor_specific *);
+extern struct tpm_chip* tpm_register_hardware(struct device *,
+ const struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
extern int tpm_release(struct inode *, struct file *);
extern ssize_t tpm_write(struct file *, const char __user *, size_t,
--- linux-2.6.16/drivers/char/tpm/tpm_atmel.c 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm_atmel.c 2006-03-02 15:04:40.663271500 -0600
@@ -140,7 +140,7 @@ static struct attribute* atmel_attrs[] =
static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
-static struct tpm_vendor_specific tpm_atmel = {
+static const struct tpm_vendor_specific tpm_atmel = {
.recv = tpm_atml_recv,
.send = tpm_atml_send,
.cancel = tpm_atml_cancel,
@@ -179,18 +179,22 @@ static struct device_driver atml_drv = {
static int __init init_atmel(void)
{
int rc = 0;
+ void __iomem *iobase = NULL;
+ int have_region, region_size;
+ unsigned long base;
+ struct tpm_chip *chip;
driver_register(&atml_drv);
- if ((tpm_atmel.iobase = atmel_get_base_addr(&tpm_atmel)) == NULL) {
+ if ((iobase = atmel_get_base_addr(&base, ®ion_size)) == NULL) {
rc = -ENODEV;
goto err_unreg_drv;
}
- tpm_atmel.have_region =
+ have_region =
(atmel_request_region
- (tpm_atmel.base, tpm_atmel.region_size,
- "tpm_atmel0") == NULL) ? 0 : 1;
+ (tpm_atmel.base, region_size, "tpm_atmel0") == NULL) ? 0 : 1;
+
if (IS_ERR
(pdev =
@@ -199,17 +203,25 @@ static int __init init_atmel(void)
goto err_rel_reg;
}
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_atmel)) < 0)
+ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_atmel))) {
+ rc = -ENODEV;
goto err_unreg_dev;
+ }
+
+ chip->vendor.iobase = iobase;
+ chip->vendor.base = base;
+ chip->vendor.have_region = have_region;
+ chip->vendor.region_size = region_size;
+
return 0;
err_unreg_dev:
platform_device_unregister(pdev);
err_rel_reg:
- atmel_put_base_addr(&tpm_atmel);
- if (tpm_atmel.have_region)
- atmel_release_region(tpm_atmel.base,
- tpm_atmel.region_size);
+ atmel_put_base_addr(iobase);
+ if (have_region)
+ atmel_release_region(base,
+ region_size);
err_unreg_drv:
driver_unregister(&atml_drv);
return rc;
--- linux-2.6.16/drivers/char/tpm/tpm_atmel.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm_atmel.h 2006-03-02 14:50:27.725966250 -0600
@@ -28,13 +28,12 @@
#define atmel_request_region request_mem_region
#define atmel_release_region release_mem_region
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
- *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
{
- iounmap(vendor->iobase);
+ iounmap(iobase);
}
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
struct device_node *dn;
unsigned long address, size;
@@ -71,9 +70,9 @@ static void __iomem * atmel_get_base_add
else
size = reg[naddrc];
- vendor->base = address;
- vendor->region_size = size;
- return ioremap(vendor->base, vendor->region_size);
+ *base = address;
+ *region_size = size;
+ return ioremap(*base, *region_size);
}
#else
#define atmel_getb(chip, offset) inb(chip->vendor->base + offset)
@@ -106,14 +105,12 @@ static int atmel_verify_tpm11(void)
return 0;
}
-static inline void atmel_put_base_addr(struct tpm_vendor_specific
- *vendor)
+static inline void atmel_put_base_addr(void __iomem *iobase)
{
}
/* Determine where to talk to device */
-static void __iomem * atmel_get_base_addr(struct tpm_vendor_specific
- *vendor)
+static void __iomem * atmel_get_base_addr(unsigned long *base, int *region_size)
{
int lo, hi;
@@ -123,9 +120,9 @@ static void __iomem * atmel_get_base_add
lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
- vendor->base = (hi << 8) | lo;
- vendor->region_size = 2;
+ *base = (hi << 8) | lo;
+ *region_size = 2;
- return ioport_map(vendor->base, vendor->region_size);
+ return ioport_map(*base, *region_size);
}
#endif
--- linux-2.6.16/drivers/char/tpm/tpm_nsc.c 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm_nsc.c 2006-03-02 15:06:07.188679000 -0600
@@ -250,7 +250,7 @@ static struct attribute * nsc_attrs[] =
static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
-static struct tpm_vendor_specific tpm_nsc = {
+static const struct tpm_vendor_specific tpm_nsc = {
.recv = tpm_nsc_recv,
.send = tpm_nsc_send,
.cancel = tpm_nsc_cancel,
@@ -286,7 +286,8 @@ static int __init init_nsc(void)
int rc = 0;
int lo, hi;
int nscAddrBase = TPM_ADDR;
-
+ struct tpm_chip *chip;
+ unsigned long base;
/* verify that it is a National part (SID) */
if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
@@ -300,7 +301,7 @@ static int __init init_nsc(void)
hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
- tpm_nsc.base = (hi<<8) | lo;
+ base = (hi<<8) | lo;
/* enable the DPM module */
tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
@@ -320,13 +321,15 @@ static int __init init_nsc(void)
if ((rc = platform_device_register(pdev)) < 0)
goto err_free_dev;
- if (request_region(tpm_nsc.base, 2, "tpm_nsc0") == NULL ) {
+ if (request_region(base, 2, "tpm_nsc0") == NULL ) {
rc = -EBUSY;
goto err_unreg_dev;
}
- if ((rc = tpm_register_hardware(&pdev->dev, &tpm_nsc)) < 0)
+ if (!(chip = tpm_register_hardware(&pdev->dev, &tpm_nsc))) {
+ rc = -ENODEV;
goto err_rel_reg;
+ }
dev_dbg(&pdev->dev, "NSC TPM detected\n");
dev_dbg(&pdev->dev,
@@ -361,10 +364,12 @@ static int __init init_nsc(void)
"NSC TPM revision %d\n",
tpm_read_index(nscAddrBase, 0x27) & 0x1F);
+ chip->vendor.base = base;
+
return 0;
err_rel_reg:
- release_region(tpm_nsc.base, 2);
+ release_region(base, 2);
err_unreg_dev:
platform_device_unregister(pdev);
err_free_dev:
^ permalink raw reply
* [PATCH 3/7] tpm: chip struct update
From: Kylene Jo Hall @ 2006-04-10 14:37 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, TPM Device Driver List
To assist with chip management and better support the possibility of
having multiple TPMs in the system of the same kind, the struct
tpm_vendor_specific member of the tpm_chip was changed from a pointer to
an instance. This patch changes that declaration and fixes up all
accesses to the structure member except in tpm_infineon which is coming
in a patch from Marcel Selhorst.
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm.c | 48 +++++++++++++++------------------
drivers/char/tpm/tpm.h | 2 -
drivers/char/tpm/tpm_atmel.c | 26 ++++++++---------
drivers/char/tpm/tpm_nsc.c | 32 +++++++++++-----------
4 files changed, 53 insertions(+), 55 deletions(-)
--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-03-30 15:08:43.400724250 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.c 2006-03-29 14:17:14.421822250 -0600
@@ -78,21 +385,20 @@ static ssize_t tpm_transmit(struct tpm_c
down(&chip->tpm_mutex);
- if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+ if ((rc = chip->vendor.send(chip, (u8 *) buf, count)) < 0) {
dev_err(chip->dev,
"tpm_transmit: tpm_send: error %zd\n", rc);
goto out;
}
stop = jiffies + 2 * 60 * HZ;
do {
- u8 status = chip->vendor->status(chip);
- if ((status & chip->vendor->req_complete_mask) ==
- chip->vendor->req_complete_val) {
+ u8 status = chip->vendor.status(chip);
+ if ((status & chip->vendor.req_complete_mask) ==
+ chip->vendor.req_complete_val)
goto out_recv;
- }
- if ((status == chip->vendor->req_canceled)) {
+ if ((status == chip->vendor.req_canceled)) {
dev_err(chip->dev, "Operation Canceled\n");
rc = -ECANCELED;
goto out;
@@ -102,14 +411,13 @@ static ssize_t tpm_transmit(struct tpm_c
rmb();
} while (time_before(jiffies, stop));
-
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
dev_err(chip->dev, "Operation Timed out\n");
rc = -ETIME;
goto out;
out_recv:
- rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+ rc = chip->vendor.recv(chip, (u8 *) buf, bufsiz);
if (rc < 0)
dev_err(chip->dev,
"tpm_transmit: tpm_recv: error %zd\n", rc);
@@ -344,7 +832,7 @@ ssize_t tpm_store_cancel(struct device *dev
if (chip == NULL)
return 0;
- chip->vendor->cancel(chip);
+ chip->vendor.cancel(chip);
return count;
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
@@ -369,7 +913,7 @@ int tpm_open(struct inode *inode, struct
spin_lock(&driver_lock);
list_for_each_entry(pos, &tpm_chip_list, list) {
- if (pos->vendor->miscdev.minor == minor) {
+ if (pos->vendor.miscdev.minor == minor) {
chip = pos;
break;
}
@@ -502,14 +1049,14 @@ void tpm_remove_hardware(struct device *
spin_unlock(&driver_lock);
dev_set_drvdata(dev, NULL);
- misc_deregister(&chip->vendor->miscdev);
- kfree(chip->vendor->miscdev.name);
+ misc_deregister(&chip->vendor.miscdev);
+ kfree(chip->vendor.miscdev.name);
- sysfs_remove_group(&dev->kobj, chip->vendor->attr_group);
+ sysfs_remove_group(&dev->kobj, chip->vendor.attr_group);
tpm_bios_log_teardown(chip->bios_dir);
- dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &=
- ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
+ dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES] &=
+ ~(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
kfree(chip);
@@ -583,7 +1134,7 @@ int tpm_register_hardware(struct device
chip->user_read_timer.function = user_reader_timeout;
chip->user_read_timer.data = (unsigned long) chip;
- chip->vendor = entry;
+ memcpy(&chip->vendor, entry, sizeof(struct tpm_vendor_specific));
chip->dev_num = -1;
@@ -602,22 +1153,22 @@ dev_num_search_complete:
kfree(chip);
return -ENODEV;
} else if (chip->dev_num == 0)
- chip->vendor->miscdev.minor = TPM_MINOR;
+ chip->vendor.miscdev.minor = TPM_MINOR;
else
- chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+ chip->vendor.miscdev.minor = MISC_DYNAMIC_MINOR;
devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
- chip->vendor->miscdev.name = devname;
+ chip->vendor.miscdev.name = devname;
- chip->vendor->miscdev.dev = dev;
+ chip->vendor.miscdev.dev = dev;
chip->dev = get_device(dev);
- if (misc_register(&chip->vendor->miscdev)) {
+ if (misc_register(&chip->vendor.miscdev)) {
dev_err(chip->dev,
"unable to misc_register %s, minor %d\n",
- chip->vendor->miscdev.name,
- chip->vendor->miscdev.minor);
+ chip->vendor.miscdev.name,
+ chip->vendor.miscdev.minor);
put_device(dev);
kfree(chip);
dev_mask[i] &= !(1 << j);
@@ -632,7 +1183,7 @@ dev_num_search_complete:
spin_unlock(&driver_lock);
- sysfs_create_group(&dev->kobj, chip->vendor->attr_group);
+ sysfs_create_group(&dev->kobj, chip->vendor.attr_group);
chip->bios_dir = tpm_bios_log_setup(devname);
--- linux-2.6.16/drivers/char/tpm/tpm_atmel.c 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm_atmel.c 2006-03-02 15:04:40.663271500 -0600
@@ -47,12 +47,12 @@ static int tpm_atml_recv(struct tpm_chip
return -EIO;
for (i = 0; i < 6; i++) {
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading header\n");
return -EIO;
}
- *buf++ = ioread8(chip->vendor->iobase);
+ *buf++ = ioread8(chip->vendor.iobase);
}
/* size of the data received */
@@ -63,7 +63,7 @@ static int tpm_atml_recv(struct tpm_chip
dev_err(chip->dev,
"Recv size(%d) less than available space\n", size);
for (; i < size; i++) { /* clear the waiting data anyway */
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n");
return -EIO;
@@ -74,16 +74,16 @@ static int tpm_atml_recv(struct tpm_chip
/* read all the data available */
for (; i < size; i++) {
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
dev_err(chip->dev, "error reading data\n");
return -EIO;
}
- *buf++ = ioread8(chip->vendor->iobase);
+ *buf++ = ioread8(chip->vendor.iobase);
}
/* make sure data available is gone */
- status = ioread8(chip->vendor->iobase + 1);
+ status = ioread8(chip->vendor.iobase + 1);
if (status & ATML_STATUS_DATA_AVAIL) {
dev_err(chip->dev, "data available is stuck\n");
@@ -100,7 +100,7 @@ static int tpm_atml_send(struct tpm_chip
dev_dbg(chip->dev, "tpm_atml_send:\n");
for (i = 0; i < count; i++) {
dev_dbg(chip->dev, "%d 0x%x(%d)\n", i, buf[i], buf[i]);
- iowrite8(buf[i], chip->vendor->iobase);
+ iowrite8(buf[i], chip->vendor.iobase);
}
return count;
@@ -108,12 +108,12 @@ static int tpm_atml_send(struct tpm_chip
static void tpm_atml_cancel(struct tpm_chip *chip)
{
- iowrite8(ATML_STATUS_ABORT, chip->vendor->iobase + 1);
+ iowrite8(ATML_STATUS_ABORT, chip->vendor.iobase + 1);
}
static u8 tpm_atml_status(struct tpm_chip *chip)
{
- return ioread8(chip->vendor->iobase + 1);
+ return ioread8(chip->vendor.iobase + 1);
}
static struct file_operations atmel_ops = {
@@ -159,10 +159,10 @@ static void atml_plat_remove(void)
struct tpm_chip *chip = dev_get_drvdata(&pdev->dev);
if (chip) {
- if (chip->vendor->have_region)
- atmel_release_region(chip->vendor->base,
- chip->vendor->region_size);
- atmel_put_base_addr(chip->vendor);
+ if (chip->vendor.have_region)
+ atmel_release_region(chip->vendor.base,
+ chip->vendor.region_size);
+ atmel_put_base_addr(chip->vendor.iobase);
tpm_remove_hardware(chip->dev);
platform_device_unregister(pdev);
}
--- linux-2.6.16/drivers/char/tpm/tpm_nsc.c 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm_nsc.c 2006-03-02 15:06:07.188679000 -0600
@@ -71,7 +71,7 @@ static int wait_for_stat(struct tpm_chip
unsigned long stop;
/* status immediately available check */
- *data = inb(chip->vendor->base + NSC_STATUS);
+ *data = inb(chip->vendor.base + NSC_STATUS);
if ((*data & mask) == val)
return 0;
@@ -79,7 +79,7 @@ static int wait_for_stat(struct tpm_chip
stop = jiffies + 10 * HZ;
do {
msleep(TPM_TIMEOUT);
- *data = inb(chip->vendor->base + 1);
+ *data = inb(chip->vendor.base + 1);
if ((*data & mask) == val)
return 0;
}
@@ -94,9 +94,9 @@ static int nsc_wait_for_ready(struct tpm
unsigned long stop;
/* status immediately available check */
- status = inb(chip->vendor->base + NSC_STATUS);
+ status = inb(chip->vendor.base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor->base + NSC_DATA);
+ status = inb(chip->vendor.base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
@@ -104,9 +104,9 @@ static int nsc_wait_for_ready(struct tpm
stop = jiffies + 100;
do {
msleep(TPM_TIMEOUT);
- status = inb(chip->vendor->base + NSC_STATUS);
+ status = inb(chip->vendor.base + NSC_STATUS);
if (status & NSC_STATUS_OBF)
- status = inb(chip->vendor->base + NSC_DATA);
+ status = inb(chip->vendor.base + NSC_DATA);
if (status & NSC_STATUS_RDY)
return 0;
}
@@ -132,7 +132,7 @@ static int tpm_nsc_recv(struct tpm_chip
return -EIO;
}
if ((data =
- inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+ inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
dev_err(chip->dev, "not in normal mode (0x%x)\n",
data);
return -EIO;
@@ -148,7 +148,7 @@ static int tpm_nsc_recv(struct tpm_chip
}
if (data & NSC_STATUS_F0)
break;
- *p = inb(chip->vendor->base + NSC_DATA);
+ *p = inb(chip->vendor.base + NSC_DATA);
}
if ((data & NSC_STATUS_F0) == 0 &&
@@ -156,7 +156,7 @@ static int tpm_nsc_recv(struct tpm_chip
dev_err(chip->dev, "F0 not set\n");
return -EIO;
}
- if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+ if ((data = inb(chip->vendor.base + NSC_DATA)) != NSC_COMMAND_EOC) {
dev_err(chip->dev,
"expected end of command(0x%x)\n", data);
return -EIO;
@@ -182,7 +182,7 @@ static int tpm_nsc_send(struct tpm_chip
* fix it. Not sure why this is needed, we followed the flow
* chart in the manual to the letter.
*/
- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
if (nsc_wait_for_ready(chip) != 0)
return -EIO;
@@ -192,7 +192,7 @@ static int tpm_nsc_send(struct tpm_chip
return -EIO;
}
- outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_NORMAL, chip->vendor.base + NSC_COMMAND);
if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
dev_err(chip->dev, "IBR timeout\n");
return -EIO;
@@ -204,26 +204,26 @@ static int tpm_nsc_send(struct tpm_chip
"IBF timeout (while writing data)\n");
return -EIO;
}
- outb(buf[i], chip->vendor->base + NSC_DATA);
+ outb(buf[i], chip->vendor.base + NSC_DATA);
}
if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
dev_err(chip->dev, "IBF timeout\n");
return -EIO;
}
- outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_EOC, chip->vendor.base + NSC_COMMAND);
return count;
}
static void tpm_nsc_cancel(struct tpm_chip *chip)
{
- outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+ outb(NSC_COMMAND_CANCEL, chip->vendor.base + NSC_COMMAND);
}
static u8 tpm_nsc_status(struct tpm_chip *chip)
{
- return inb(chip->vendor->base + NSC_STATUS);
+ return inb(chip->vendor.base + NSC_STATUS);
}
static struct file_operations nsc_ops = {
@@ -268,7 +268,7 @@ static void __devexit tpm_nsc_remove(str
{
struct tpm_chip *chip = dev_get_drvdata(dev);
if ( chip ) {
- release_region(chip->vendor->base, 2);
+ release_region(chip->vendor.base, 2);
tpm_remove_hardware(chip->dev);
}
}
--- linux-2.6.16/drivers/char/tpm/tpm.h 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.h 2006-03-29 14:16:30.119053500 -0600
@@ -80,7 +93,7 @@ struct tpm_chip {
struct work_struct work;
struct semaphore tpm_mutex; /* tpm is processing */
- struct tpm_vendor_specific *vendor;
+ struct tpm_vendor_specific vendor;
struct dentry **bios_dir;
^ permalink raw reply
* [PATCH 5/7] tpm: command duration update
From: Kylene Jo Hall @ 2006-04-10 14:37 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, TPM Device Driver List
With the TPM 1.2 Specification, each command is classified as short,
medium or long and the chip tells you the maximum amount of time for a
response to each class of command. This patch provides and array of the
classifications and a function to determine how long the response should
be waited for. Also, it uses that information in the command processing
to determine how long to poll for. The function is exported so the 1.2
driver can use the functionality to determine how long to wait for a
DataAvailable interrupt if interrupts are being used.
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm.c | 313 ++++++++++++++++++++++++++++++++++++++-
drivers/char/tpm/tpm.h | 2
2 files changed, 312 insertions(+), 3 deletions(-)
--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-03-30 12:27:02.858478250 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.c 2006-03-29 14:17:14.421822250 -0600
@@ -35,10 +35,290 @@ enum tpm_const {
TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
};
+enum tpm_duration {
+ TPM_SHORT = 0,
+ TPM_MEDIUM = 1,
+ TPM_LONG = 2,
+ TPM_UNDEFINED,
+};
+
+#define TPM_MAX_ORDINAL 243
+#define TPM_MAX_PROTECTED_ORDINAL 12
+#define TPM_PROTECTED_ORDINAL_MASK 0xFF
+
static LIST_HEAD(tpm_chip_list);
static DEFINE_SPINLOCK(driver_lock);
static int dev_mask[TPM_NUM_MASK_ENTRIES];
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result. The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm_protected_ordinal_duration[TPM_MAX_PROTECTED_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+};
+
+static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_LONG,
+ TPM_MEDIUM, /* 15 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT, /* 20 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT, /* 25 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 30 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 35 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 40 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 45 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_MEDIUM, /* 50 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 55 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 60 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 65 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 70 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 75 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 80 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 85 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 90 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 95 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 100 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 105 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 110 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 115 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 120 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 125 */
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 130 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 135 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 140 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 145 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 150 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 155 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 160 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 165 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 170 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 175 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 180 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM, /* 185 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 190 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 195 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 200 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 205 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 210 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 215 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 220 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 225 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 230 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 235 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 240 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+};
+
static void user_reader_timeout(unsigned long ptr)
{
struct tpm_chip *chip = (struct tpm_chip *) ptr;
@@ -57,17 +337,44 @@ static void timeout_work(void *ptr)
}
/*
+ * Returns max number of jiffies to wait
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
+ u32 ordinal)
+{
+
+ int duration_idx = TPM_UNDEFINED;
+ int duration = 0;
+
+ if (ordinal < TPM_MAX_ORDINAL)
+ duration_idx = tpm_ordinal_duration[ordinal];
+ else if ((ordinal & TPM_PROTECTED_ORDINAL_MASK) <
+ TPM_MAX_PROTECTED_ORDINAL)
+ duration_idx =
+ tpm_protected_ordinal_duration[ordinal &
+ TPM_PROTECTED_ORDINAL_MASK];
+
+ if (duration_idx != TPM_UNDEFINED)
+ duration = chip->vendor.duration[duration_idx] * HZ / 1000;
+ if (duration <= 0)
+ return 2 * 60 * HZ;
+ else
+ return duration;
+}
+EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
+
+/*
* Internal kernel interface to transmit TPM commands
*/
static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
size_t bufsiz)
{
ssize_t rc;
- u32 count;
+ u32 count, ordinal;
unsigned long stop;
count = be32_to_cpu(*((__be32 *) (buf + 2)));
-
+ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
if (count == 0)
return -ENODATA;
if (count > bufsiz) {
@@ -78,7 +385,7 @@ static ssize_t tpm_transmit(struct tpm_c
goto out;
}
- stop = jiffies + 2 * 60 * HZ;
+ stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
do {
u8 status = chip->vendor.status(chip);
if ((status & chip->vendor.req_complete_mask) ==
--- linux-2.6.16/drivers/char/tpm/tpm.h 2006-03-30 16:43:45.933110250 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.h 2006-03-29 14:16:30.119053500 -0600
@@ -62,6 +68,7 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
+ u32 duration[3];
};
struct tpm_chip {
@@ -99,6 +114,7 @@ static inline void tpm_write_index(int b
outb(value & 0xFF, base+1);
}
+extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);
extern int tpm_open(struct inode *, struct file *);
^ permalink raw reply
* [PATCH 1/7] tpm: spacing cleanups
From: Kylene Jo Hall @ 2006-04-10 14:36 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, TPM Device Driver List
This patch fixes minor spacing issues.
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm.c | 9 ++++-----
1 files changed, 4 insertions(+), 5 deletions(-)
--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.c 2006-03-22 12:05:26.830788000 -0600
@@ -46,7 +326,7 @@ static void user_reader_timeout(unsigned
schedule_work(&chip->work);
}
-static void timeout_work(void * ptr)
+static void timeout_work(void *ptr)
{
struct tpm_chip *chip = ptr;
@@ -425,7 +963,7 @@ int tpm_release(struct inode *inode, str
EXPORT_SYMBOL_GPL(tpm_release);
ssize_t tpm_write(struct file *file, const char __user *buf,
- size_t size, loff_t * off)
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int in_size = size, out_size;
@@ -457,11 +995,10 @@ ssize_t tpm_write(struct file *file, con
return in_size;
}
-
EXPORT_SYMBOL_GPL(tpm_write);
-ssize_t tpm_read(struct file * file, char __user *buf,
- size_t size, loff_t * off)
+ssize_t tpm_read(struct file *file, char __user *buf,
+ size_t size, loff_t *off)
{
struct tpm_chip *chip = file->private_data;
int ret_size;
^ permalink raw reply
* [PATCH 6/7] tpm: new 1.2 sysfs files - Updated patch
From: Kylene Jo Hall @ 2006-04-10 14:37 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, TPM Device Driver List
Many of the sysfs files were calling the TPM_GetCapability command with
different options and each command layed out in its own static const
array. Since for 1.2 more sysfs files of this type are coming I am
generalizing the array so there can be one array and the unique parts
can be filled in just before the command is called.
This updated version of the patch breaks the multi-value sysfs file into
separate files pointed out by Greg. It also addresses the code
redundancy and ugliness in the tpm_show_* functions pointed out on
another patch by Dave Hansen. It replaces the 6/7 patch from the
original set.
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm.c | 232 +++++++++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm.h | 14 ++
2 files changed, 246 insertions(+)
--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-04-07 11:54:14.080726750 -0500
+++ linux-2.6.16-44/drivers/char/tpm/tpm.c 2006-04-05 16:44:56.293071750 -0500
@@ -431,17 +434,27 @@ out:
#define TPM_GET_CAP_RET_UINT32_2_IDX 18
#define TPM_GET_CAP_RET_UINT32_3_IDX 22
#define TPM_GET_CAP_RET_UINT32_4_IDX 26
+#define TPM_GET_CAP_PERM_DISABLE_IDX 16
+#define TPM_GET_CAP_PERM_INACTIVE_IDX 18
+#define TPM_GET_CAP_RET_BOOL_1_IDX 14
+#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16
#define TPM_CAP_IDX 13
#define TPM_CAP_SUBCAP_IDX 21
enum tpm_capabilities {
+ TPM_CAP_FLAG = 4,
TPM_CAP_PROP = 5,
};
enum tpm_sub_capabilities {
TPM_CAP_PROP_PCR = 0x1,
TPM_CAP_PROP_MANUFACTURER = 0x3,
+ TPM_CAP_FLAG_PERM = 0x8,
+ TPM_CAP_FLAG_VOL = 0x9,
+ TPM_CAP_PROP_OWNER = 0x11,
+ TPM_CAP_PROP_TIS_TIMEOUT = 0x15,
+ TPM_CAP_PROP_TIS_DURATION = 0x20,
};
/*
@@ -475,6 +488,181 @@ static ssize_t transmit_cmd(struct tpm_c
return 0;
}
+void tpm_gen_interrupt(struct tpm_chip *chip)
+{
+ u8 data[30];
+ ssize_t rc;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+}
+EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
+
+void tpm_get_timeouts(struct tpm_chip *chip)
+{
+ u8 data[30];
+ ssize_t rc;
+ u32 timeout;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the timeouts");
+ if (rc)
+ goto duration;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 4 * sizeof(u32))
+ goto duration;
+
+ /* Don't overwrite default if value is 0 */
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+ if (timeout)
+ chip->vendor.timeout_a = timeout;
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+ if (timeout)
+ chip->vendor.timeout_b = timeout;
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+ if (timeout)
+ chip->vendor.timeout_c = timeout;
+ timeout =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX)));
+ if (timeout)
+ chip->vendor.timeout_d = timeout;
+
+duration:
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the durations");
+ if (rc)
+ return;
+
+ if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX)))
+ != 3 * sizeof(u32))
+ return;
+
+ chip->vendor.duration[TPM_SHORT] =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)));
+ chip->vendor.duration[TPM_MEDIUM] =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX)));
+ chip->vendor.duration[TPM_LONG] =
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX)));
+}
+EXPORT_SYMBOL_GPL(tpm_get_timeouts);
+
+void tpm_continue_selftest(struct tpm_chip *chip)
+{
+
+ u8 data[] = {
+ 0, 193, /* TPM_TAG_RQU_COMMAND */
+ 0, 0, 0, 10, /* length */
+ 0, 0, 0, 83, /* TPM_ORD_GetCapability */
+ };
+
+ tpm_transmit(chip, data, sizeof(data));
+}
+EXPORT_SYMBOL_GPL(tpm_continue_selftest);
+
+ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[35];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_enabled);
+
+ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[35];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attemtping to determine the permanent state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_active);
+
+ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr,
+ char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the owner state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_owned);
+
+ssize_t tpm_show_temp_deactivated(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[sizeof(tpm_cap)];
+ ssize_t rc;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_FLAG;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL;
+
+ rc = transmit_cmd(chip, data, sizeof(data),
+ "attempting to determine the temporary state");
+ if (rc)
+ return 0;
+ return sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]);
+}
+EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated);
+
static const u8 pcrread[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
0, 0, 0, 14, /* length */
@@ -589,6 +777,7 @@ out:
EXPORT_SYMBOL_GPL(tpm_show_pubek);
#define CAP_VERSION_1_1 6
+#define CAP_VERSION_1_2 0x1A
#define CAP_VERSION_IDX 13
static const u8 cap_version[] = {
0, 193, /* TPM_TAG_RQU_COMMAND */
@@ -638,6 +827,52 @@ out:
}
EXPORT_SYMBOL_GPL(tpm_show_caps);
+ssize_t tpm_show_caps_1_2(struct device * dev,
+ struct device_attribute * attr, char *buf)
+{
+ u8 data[30];
+ ssize_t len;
+ char *str = buf;
+
+ struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (chip == NULL)
+ return -ENODEV;
+
+ memcpy(data, tpm_cap, sizeof(tpm_cap));
+ data[TPM_CAP_IDX] = TPM_CAP_PROP;
+ data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_dbg(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the manufacturer\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ return 0;
+ }
+
+ str += sprintf(str, "Manufacturer: 0x%x\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))));
+
+ memcpy(data, cap_version, sizeof(cap_version));
+ data[CAP_VERSION_IDX] = CAP_VERSION_1_2;
+
+ if ((len = tpm_transmit(chip, data, sizeof(data))) <=
+ TPM_ERROR_SIZE) {
+ dev_err(chip->dev, "A TPM error (%d) occurred "
+ "attempting to determine the 1.2 version\n",
+ be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))));
+ goto out;
+ }
+ str += sprintf(str,
+ "TCG version: %d.%d\nFirmware version: %d.%d\n",
+ (int) data[16], (int) data[17], (int) data[18],
+ (int) data[19]);
+
+out:
+ return str - buf;
+}
+EXPORT_SYMBOL_GPL(tpm_show_caps_1_2);
+
ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
--- linux-2.6.16/drivers/char/tpm/tpm.h 2006-04-07 11:54:14.080726750 -0500
+++ linux-2.6.16-44/drivers/char/tpm/tpm.h 2006-04-05 16:45:33.399390750 -0500
@@ -41,8 +41,18 @@ extern ssize_t tpm_show_pcrs(struct devi
char *);
extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
char *);
+extern ssize_t tpm_show_caps_1_2(struct device *, struct device_attribute *attr,
+ char *);
extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
const char *, size_t);
+extern ssize_t tpm_show_enabled(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_active(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_owned(struct device *, struct device_attribute *attr,
+ char *);
+extern ssize_t tpm_show_temp_deactivated(struct device *,
+ struct device_attribute *attr, char *);
struct tpm_chip;
@@ -62,6 +74,7 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
+ u32 timeout_a, timeout_b, timeout_c, timeout_d;
u32 duration[3];
};
@@ -100,6 +120,9 @@ static inline void tpm_write_index(int b
outb(value & 0xFF, base+1);
}
+extern void tpm_get_timeouts(struct tpm_chip *);
+extern void tpm_gen_interrupt(struct tpm_chip *);
+extern void tpm_continue_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);
^ permalink raw reply
* [PATCH 7/7] tpm: Driver for next generation TPM chips
From: Kylene Jo Hall @ 2006-04-10 14:37 UTC (permalink / raw)
To: linux-kernel; +Cc: akpm, TPM Device Driver List, Leendert Van Doorn
This patch contains the driver for the next generation of TPM chips
version 1.2 including support for interrupts. The Trusted Computing
Group has written the TPM Interface Specification (TIS) which defines a
common interface for all manufacturer's 1.2 TPM's thus the name
tpm_tis.
This updated version of the patch uses the new sysfs files that came
about from the comments and changes in patch 6/7. It replaces the 7/7
patch from the original set.
Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
---
drivers/char/tpm/tpm_tis.c | 638 +++++++++++++++++++++++++++++++++++
drivers/char/tpm/Kconfig | 11
drivers/char/tpm/Makefile | 1
drivers/char/tpm/tpm.c | 3
drivers/char/tpm/tpm.h | 9
5 files changed, 661 insertions(+), 1 deletion(-)
--- linux-2.6.16/drivers/char/tpm/tpm.h 2006-03-30 17:08:49.315065750 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.h 2006-03-29 14:16:30.119053500 -0600
@@ -57,6 +57,8 @@ struct tpm_vendor_specific {
void __iomem *iobase; /* ioremapped address */
unsigned long base; /* TPM base address */
+ int irq;
+
int region_size;
int have_region;
@@ -66,8 +68,13 @@ struct tpm_vendor_specific {
u8 (*status) (struct tpm_chip *);
struct miscdevice miscdev;
struct attribute_group *attr_group;
+ struct list_head list;
+ int locality;
u32 timeout_a, timeout_b, timeout_c, timeout_d;
u32 duration[3];
+
+ wait_queue_head_t read_queue;
+ wait_queue_head_t int_queue;
};
struct tpm_chip {
@@ -93,6 +100,8 @@ struct tpm_chip {
struct list_head list;
};
+#define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
+
static inline int tpm_read_index(int base, int index)
{
outb(index, base);
--- linux-2.6.16/drivers/char/tpm/tpm.c 2006-03-30 17:08:49.315065750 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/tpm.c 2006-03-30 16:51:48.567273000 -0600
@@ -391,6 +391,9 @@ static ssize_t tpm_transmit(struct tpm_c
goto out;
}
+ if (chip->vendor.irq)
+ goto out_recv;
+
stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
do {
u8 status = chip->vendor.status(chip);
--- linux-2.6.16/drivers/char/tpm/Makefile 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/Makefile 2006-03-02 16:20:06.002087500 -0600
@@ -5,6 +5,7 @@ obj-$(CONFIG_TCG_TPM) += tpm.o
ifdef CONFIG_ACPI
obj-$(CONFIG_TCG_TPM) += tpm_bios.o
endif
+obj-$(CONFIG_TCG_TIS) += tpm_tis.o
obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
--- linux-2.6.16/drivers/char/tpm/Kconfig 2006-03-19 23:53:29.000000000 -0600
+++ linux-2.6.16-rc1-tpm/drivers/char/tpm/Kconfig 2006-03-02 16:19:05.730320750 -0600
@@ -20,9 +20,18 @@ config TCG_TPM
Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI
and CONFIG_PNPACPI.
+config TCG_TIS
+ tristate "TPM Interface Specification 1.2 Interface"
+ depends on TCG_TPM
+ ---help---
+ If you have a TPM security chip that is compliant with the
+ TCG TIS 1.2 TPM specification say Yes and it will be accessible
+ from within Linux. To compile this driver as a module, choose
+ M here; the module will be called tpm_tis.
+
config TCG_NSC
tristate "National Semiconductor TPM Interface"
- depends on TCG_TPM
+ depends on TCG_TPM && PNPACPI
---help---
If you have a TPM security chip from National Semicondutor
say Yes and it will be accessible from within Linux. To
--- linux-2.6.16/drivers/char/tpm/tpm_tis.c 1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.16-44/drivers/char/tpm/tpm_tis.c 2006-04-07 11:46:03.338057250 -0500
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2005, 2006 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org
+ *
+ * This device driver implements the TPM interface as defined in
+ * the TCG TPM Interface Spec version 1.2, revision 1.0.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ */
+#include <linux/pnp.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include "tpm.h"
+
+#define TPM_HEADER_SIZE 10
+
+enum tis_access {
+ TPM_ACCESS_VALID = 0x80,
+ TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
+ TPM_ACCESS_REQUEST_PENDING = 0x04,
+ TPM_ACCESS_REQUEST_USE = 0x02,
+};
+
+enum tis_status {
+ TPM_STS_VALID = 0x80,
+ TPM_STS_COMMAND_READY = 0x40,
+ TPM_STS_GO = 0x20,
+ TPM_STS_DATA_AVAIL = 0x10,
+ TPM_STS_DATA_EXPECT = 0x08,
+};
+
+enum tis_int_flags {
+ TPM_GLOBAL_INT_ENABLE = 0x80000000,
+ TPM_INTF_BURST_COUNT_STATIC = 0x100,
+ TPM_INTF_CMD_READY_INT = 0x080,
+ TPM_INTF_INT_EDGE_FALLING = 0x040,
+ TPM_INTF_INT_EDGE_RISING = 0x020,
+ TPM_INTF_INT_LEVEL_LOW = 0x010,
+ TPM_INTF_INT_LEVEL_HIGH = 0x008,
+ TPM_INTF_LOCALITY_CHANGE_INT = 0x004,
+ TPM_INTF_STS_VALID_INT = 0x002,
+ TPM_INTF_DATA_AVAIL_INT = 0x001,
+};
+
+#define TPM_ACCESS(l) (0x0000 | ((l) << 12))
+#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12))
+#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12))
+#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12))
+#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12))
+#define TPM_STS(l) (0x0018 | ((l) << 12))
+#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12))
+
+#define TPM_DID_VID(l) (0x0F00 | ((l) << 12))
+#define TPM_RID(l) (0x0F04 | ((l) << 12))
+
+static LIST_HEAD(tis_chips);
+static DEFINE_SPINLOCK(tis_lock);
+
+static int check_locality(struct tpm_chip *chip, int l)
+{
+ if ((ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID))
+ return chip->vendor.locality = l;
+
+ return -1;
+}
+
+static void release_locality(struct tpm_chip *chip, int l, int force)
+{
+ if (force || (ioread8(chip->vendor.iobase + TPM_ACCESS(l)) &
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) ==
+ (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID))
+ iowrite8(TPM_ACCESS_ACTIVE_LOCALITY,
+ chip->vendor.iobase + TPM_ACCESS(l));
+}
+
+static int request_locality(struct tpm_chip *chip, int l)
+{
+ unsigned long stop;
+
+ if (check_locality(chip, l) >= 0)
+ return l;
+
+ iowrite8(TPM_ACCESS_REQUEST_USE,
+ chip->vendor.iobase + TPM_ACCESS(l));
+
+ if (chip->vendor.irq) {
+ interruptible_sleep_on_timeout(&chip->vendor.int_queue,
+ HZ *
+ chip->vendor.timeout_a /
+ 1000);
+ if (check_locality(chip, l) >= 0)
+ return l;
+
+ } else {
+ /* wait for burstcount */
+ stop = jiffies + (HZ * chip->vendor.timeout_a / 1000);
+ do {
+ if (check_locality(chip, l) >= 0)
+ return l;
+ msleep(TPM_TIMEOUT);
+ }
+ while (time_before(jiffies, stop));
+ }
+ return -1;
+}
+
+static u8 tpm_tis_status(struct tpm_chip *chip)
+{
+ return ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality));
+}
+
+static void tpm_tis_ready(struct tpm_chip *chip)
+{
+ /* this causes the current command to be aborted */
+ iowrite8(TPM_STS_COMMAND_READY,
+ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+}
+
+static int get_burstcount(struct tpm_chip *chip)
+{
+ unsigned long stop;
+ int burstcnt;
+
+ /* wait for burstcount */
+ /* which timeout value, spec has 2 answers (c & d) */
+ stop = jiffies + (HZ * chip->vendor.timeout_d / 1000);
+ do {
+ burstcnt = ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality) + 1);
+ burstcnt += ioread8(chip->vendor.iobase +
+ TPM_STS(chip->vendor.locality) +
+ 2) << 8;
+ if (burstcnt)
+ return burstcnt;
+ msleep(TPM_TIMEOUT);
+ } while (time_before(jiffies, stop));
+ return -EBUSY;
+}
+
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, u32 timeout,
+ wait_queue_head_t * queue)
+{
+ unsigned long stop;
+ u8 status;
+
+ /* check current status */
+ status = tpm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+
+ if (chip->vendor.irq) {
+ interruptible_sleep_on_timeout(queue, HZ * timeout / 1000);
+ status = tpm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } else {
+ stop = jiffies + (HZ * timeout / 1000);
+ do {
+ msleep(TPM_TIMEOUT);
+ status = tpm_tis_status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } while (time_before(jiffies, stop));
+ }
+ return -ETIME;
+}
+
+static int recv_data(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ int size = 0, burstcnt;
+ while (size < count &&
+ wait_for_stat(chip,
+ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ chip->vendor.timeout_c,
+ &chip->vendor.read_queue)
+ == 0) {
+ burstcnt = get_burstcount(chip);
+ for (; burstcnt > 0 && size < count; burstcnt--)
+ buf[size++] = ioread8(chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.
+ locality));
+ }
+ return size;
+}
+
+static int tpm_tis_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+ int size = 0;
+ int expected, status;
+
+ if (count < TPM_HEADER_SIZE) {
+ size = -EIO;
+ goto out;
+ }
+
+ /* read first 10 bytes, including tag, paramsize, and result */
+ if ((size =
+ recv_data(chip, buf, TPM_HEADER_SIZE)) < TPM_HEADER_SIZE) {
+ dev_err(chip->dev, "Unable to read header\n");
+ goto out;
+ }
+
+ expected = be32_to_cpu(*(__be32 *) (buf + 2));
+ if (expected > count) {
+ size = -EIO;
+ goto out;
+ }
+
+ if ((size +=
+ recv_data(chip, &buf[TPM_HEADER_SIZE],
+ expected - TPM_HEADER_SIZE)) < expected) {
+ dev_err(chip->dev, "Unable to read remainder of result\n");
+ size = -ETIME;
+ goto out;
+ }
+
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if (status & TPM_STS_DATA_AVAIL) { /* retry? */
+ dev_err(chip->dev, "Error left over data\n");
+ size = -EIO;
+ goto out;
+ }
+
+out:
+ tpm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ return size;
+}
+
+/*
+ * If interrupts are used (signaled by an irq set in the vendor structure)
+ * tpm.c can skip polling for the data to be available as the interrupt is
+ * waited for here
+ */
+static int tpm_tis_send(struct tpm_chip *chip, u8 * buf, size_t len)
+{
+ int rc, status, burstcnt;
+ size_t count = 0;
+ u32 ordinal;
+
+ if (request_locality(chip, 0) < 0)
+ return -EBUSY;
+
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_COMMAND_READY) == 0) {
+ tpm_tis_ready(chip);
+ if (wait_for_stat
+ (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
+ &chip->vendor.int_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+
+ while (count < len - 1) {
+ burstcnt = get_burstcount(chip);
+ for (; burstcnt > 0 && count < len - 1; burstcnt--) {
+ iowrite8(buf[count], chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.locality));
+ count++;
+ }
+
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_DATA_EXPECT) == 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+ }
+
+ /* write last byte */
+ iowrite8(buf[count],
+ chip->vendor.iobase +
+ TPM_DATA_FIFO(chip->vendor.locality));
+ wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
+ status = tpm_tis_status(chip);
+ if ((status & TPM_STS_DATA_EXPECT) != 0) {
+ rc = -EIO;
+ goto out_err;
+ }
+
+ /* go and do it */
+ iowrite8(TPM_STS_GO,
+ chip->vendor.iobase + TPM_STS(chip->vendor.locality));
+
+ if (chip->vendor.irq) {
+ ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
+ if (wait_for_stat
+ (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ tpm_calc_ordinal_duration(chip, ordinal),
+ &chip->vendor.read_queue) < 0) {
+ rc = -ETIME;
+ goto out_err;
+ }
+ }
+ return len;
+out_err:
+ tpm_tis_ready(chip);
+ release_locality(chip, chip->vendor.locality, 0);
+ return rc;
+}
+
+static struct file_operations tis_ops = {
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .open = tpm_open,
+ .read = tpm_read,
+ .write = tpm_write,
+ .release = tpm_release,
+};
+
+static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
+static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
+static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL);
+static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL);
+static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL);
+static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated,
+ NULL);
+static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL);
+static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
+
+static struct attribute *tis_attrs[] = {
+ &dev_attr_pubek.attr,
+ &dev_attr_pcrs.attr,
+ &dev_attr_enabled.attr,
+ &dev_attr_active.attr,
+ &dev_attr_owned.attr,
+ &dev_attr_temp_deactivated.attr,
+ &dev_attr_caps.attr,
+ &dev_attr_cancel.attr, NULL,
+};
+
+static struct attribute_group tis_attr_grp = {
+ .attrs = tis_attrs
+};
+
+static struct tpm_vendor_specific tpm_tis = {
+ .status = tpm_tis_status,
+ .recv = tpm_tis_recv,
+ .send = tpm_tis_send,
+ .cancel = tpm_tis_ready,
+ .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ .req_canceled = TPM_STS_COMMAND_READY,
+ .attr_group = &tis_attr_grp,
+ .miscdev = {
+ .fops = &tis_ops,},
+};
+
+static irqreturn_t tis_int_probe(int irq, void *dev_id, struct pt_regs
+ *regs)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ u32 interrupt;
+
+ interrupt = ioread32(chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ if (interrupt == 0)
+ return IRQ_NONE;
+
+ chip->vendor.irq = irq;
+
+ /* Clear interrupts handled with TPM_EOI */
+ iowrite32(interrupt,
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t tis_int_handler(int irq, void *dev_id, struct pt_regs
+ *regs)
+{
+ struct tpm_chip *chip = (struct tpm_chip *) dev_id;
+ u32 interrupt;
+ int i;
+
+ interrupt = ioread32(chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ if (interrupt == 0)
+ return IRQ_NONE;
+
+ if (interrupt & TPM_INTF_DATA_AVAIL_INT)
+ wake_up_interruptible(&chip->vendor.read_queue);
+ if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
+ for (i = 0; i < 5; i++)
+ if (check_locality(chip, i) >= 0)
+ break;
+ if (interrupt &
+ (TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_STS_VALID_INT |
+ TPM_INTF_CMD_READY_INT))
+ wake_up_interruptible(&chip->vendor.int_queue);
+
+ /* Clear interrupts handled with TPM_EOI */
+ iowrite32(interrupt,
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+ return IRQ_HANDLED;
+}
+
+static int __devinit tpm_tis_pnp_init(struct pnp_dev
+ *pnp_dev, const struct
+ pnp_device_id
+ *pnp_id)
+{
+ u32 vendor, intfcaps, intmask;
+ int rc, i;
+ unsigned long start, len;
+ struct tpm_chip *chip;
+
+ start = pnp_mem_start(pnp_dev, 0);
+ len = pnp_mem_len(pnp_dev, 0);
+
+ if (!(chip = tpm_register_hardware(&pnp_dev->dev, &tpm_tis)))
+ return -ENODEV;
+
+ chip->vendor.iobase = ioremap(start, len);
+ if (!chip->vendor.iobase) {
+ rc = -EIO;
+ goto out_err;
+ }
+
+ vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0));
+ if ((vendor & 0xFFFF) == 0xFFFF) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* Default timeouts */
+ chip->vendor.timeout_a = 750; /* ms */
+ chip->vendor.timeout_b = 2000; /* 2 sec */
+ chip->vendor.timeout_c = 750; /* ms */
+ chip->vendor.timeout_d = 750; /* ms */
+
+ dev_info(&pnp_dev->dev,
+ "1.2 TPM (device-id 0x%X, rev-id %d)\n",
+ vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0)));
+
+ /* Figure out the capabilities */
+ intfcaps =
+ ioread32(chip->vendor.iobase +
+ TPM_INTF_CAPS(chip->vendor.locality));
+ dev_dbg(&pnp_dev->dev, "TPM interface capabilities (0x%x):\n",
+ intfcaps);
+ if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+ dev_dbg(&pnp_dev->dev, "\tBurst Count Static\n");
+ if (intfcaps & TPM_INTF_CMD_READY_INT)
+ dev_dbg(&pnp_dev->dev, "\tCommand Ready Int Support\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Falling\n");
+ if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Edge Rising\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Level Low\n");
+ if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+ dev_dbg(&pnp_dev->dev, "\tInterrupt Level High\n");
+ if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+ dev_dbg(&pnp_dev->dev, "\tLocality Change Int Support\n");
+ if (intfcaps & TPM_INTF_STS_VALID_INT)
+ dev_dbg(&pnp_dev->dev, "\tSts Valid Int Support\n");
+ if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+ dev_dbg(&pnp_dev->dev, "\tData Avail Int Support\n");
+
+ if (request_locality(chip, 0) != 0) {
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ /* INTERRUPT Setup */
+ init_waitqueue_head(&chip->vendor.read_queue);
+ init_waitqueue_head(&chip->vendor.int_queue);
+
+ intmask =
+ ioread32(chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+
+ intmask |= TPM_INTF_CMD_READY_INT
+ | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+ | TPM_INTF_STS_VALID_INT;
+
+ iowrite32(intmask,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+
+ chip->vendor.irq =
+ ioread8(chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+
+ for (i = 3; i < 16 && chip->vendor.irq == 0; i++) {
+ iowrite8(i,
+ chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+ if (request_irq
+ (i, tis_int_probe, SA_SHIRQ,
+ chip->vendor.miscdev.name, chip) != 0) {
+ dev_info(chip->dev,
+ "Unable to request irq: %d for probe\n",
+ i);
+ continue;
+ }
+
+ /* Clear all existing */
+ iowrite32(ioread32
+ (chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality)),
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ /* Turn on */
+ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+
+ /* Generate Interrupts */
+ tpm_gen_interrupt(chip);
+
+ /* Turn off */
+ iowrite32(intmask,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ free_irq(i, chip);
+ }
+ if (chip->vendor.irq) {
+ iowrite8(chip->vendor.irq,
+ chip->vendor.iobase +
+ TPM_INT_VECTOR(chip->vendor.locality));
+ if (request_irq
+ (chip->vendor.irq, tis_int_handler, SA_SHIRQ,
+ chip->vendor.miscdev.name, chip) != 0) {
+ dev_info(chip->dev,
+ "Unable to request irq: %d for use\n", i);
+ chip->vendor.irq = 0;
+ } else {
+ /* Clear all existing */
+ iowrite32(ioread32
+ (chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality)),
+ chip->vendor.iobase +
+ TPM_INT_STATUS(chip->vendor.locality));
+
+ /* Turn on */
+ iowrite32(intmask | TPM_GLOBAL_INT_ENABLE,
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ }
+ }
+
+ INIT_LIST_HEAD(&chip->vendor.list);
+ spin_lock(&tis_lock);
+ list_add(&chip->vendor.list, &tis_chips);
+ spin_unlock(&tis_lock);
+
+ tpm_get_timeouts(chip);
+ tpm_continue_selftest(chip);
+
+ return 0;
+out_err:
+ if (chip->vendor.iobase)
+ iounmap(chip->vendor.iobase);
+ tpm_remove_hardware(chip->dev);
+ return rc;
+}
+
+static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
+{
+ return tpm_pm_suspend(&dev->dev, msg);
+}
+
+static int tpm_tis_pnp_resume(struct pnp_dev *dev)
+{
+ return tpm_pm_resume(&dev->dev);
+}
+
+static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = {
+ {"PNP0C31", 0}, /* TPM */
+ {"", 0}
+};
+
+static struct pnp_driver tis_pnp_driver = {
+ .name = "tpm_tis",
+ .id_table = tpm_pnp_tbl,
+ .probe = tpm_tis_pnp_init,
+ .suspend = tpm_tis_pnp_suspend,
+ .resume = tpm_tis_pnp_resume,
+};
+
+static int __init init_tis(void)
+{
+ return pnp_register_driver(&tis_pnp_driver);
+}
+
+static void __exit cleanup_tis(void)
+{
+ struct tpm_vendor_specific *i, *j;
+ struct tpm_chip *chip;
+ spin_lock(&tis_lock);
+ list_for_each_entry_safe(i, j, &tis_chips, list) {
+ chip = to_tpm_chip(i);
+ iowrite32(~TPM_GLOBAL_INT_ENABLE &
+ ioread32(chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.
+ locality)),
+ chip->vendor.iobase +
+ TPM_INT_ENABLE(chip->vendor.locality));
+ release_locality(chip, chip->vendor.locality, 1);
+ if (chip->vendor.irq)
+ free_irq(chip->vendor.irq, chip);
+ iounmap(i->iobase);
+ list_del(&i->list);
+ tpm_remove_hardware(chip->dev);
+ }
+ spin_unlock(&tis_lock);
+ pnp_unregister_driver(&tis_pnp_driver);
+}
+
+module_init(init_tis);
+module_exit(cleanup_tis);
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
^ permalink raw reply
* Re: [PATCH] deinline a few large functions in vlan code v2
From: Auke Kok @ 2006-04-10 14:31 UTC (permalink / raw)
To: Denis Vlasenko, David S. Miller; +Cc: linux-kernel, linux-net, jgarzik
In-Reply-To: <200604101716.58463.vda@ilport.com.ua>
Denis Vlasenko wrote:
> On Monday 10 April 2006 08:45, David S. Miller wrote:
>> From: Denis Vlasenko <vda@ilport.com.ua>
>> Date: Mon, 10 Apr 2006 08:28:20 +0300
>>
>>> IOW: shouldn't calls to these functions sit in
>>> #if defined(CONFIG_VLAN_8021Q) || defined (CONFIG_VLAN_8021Q_MODULE)
>>> block? For example, typhoon.c:
>>>
this should have gone to netdev instead of linux-net.
Cheers,
Auke
^ permalink raw reply
* [ALSA - driver 0002014]: no sound on my asus u5a
From: bugtrack @ 2006-04-10 14:38 UTC (permalink / raw)
To: alsa-devel
The following issue has been RESOLVED.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2014>
======================================================================
Reported By: diegor
Assigned To: tiwai
======================================================================
Project: ALSA - driver
Issue ID: 2014
Category: PCI - hda-intel
Reproducibility: always
Severity: minor
Priority: normal
Status: resolved
Distribution: debian
Kernel Version: 2.6.16.2
Resolution: fixed
Fixed in Version:
======================================================================
Date Submitted: 04-10-2006 16:29 CEST
Last Modified: 04-10-2006 16:38 CEST
======================================================================
Summary: no sound on my asus u5a
Description:
After i loaded the sound driver (snd-hda-intel) with chipset ad1986a, i set
the volume about 80%. The main channel (Vol) il blocked at 100% with
aumix. if i try to launch esd (or play an mp3) the speakers are mute.
After that i've loaded the driver (snd-hda-intel) the pcskeaker (beep) is
mute.
======================================================================
----------------------------------------------------------------------
tiwai - 04-10-06 16:38
----------------------------------------------------------------------
The problem should have been fixed on ALSA-1.0.11rc4 or later.
Issue History
Date Modified Username Field Change
======================================================================
04-10-06 16:29 diegor New Issue
04-10-06 16:29 diegor Distribution => debian
04-10-06 16:29 diegor Kernel Version => 2.6.16.2
04-10-06 16:30 diegor Issue Monitored: diegor
04-10-06 16:38 tiwai Status assigned => resolved
04-10-06 16:38 tiwai Resolution open => fixed
04-10-06 16:38 tiwai Note Added: 0009191
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* [ALSA - driver 0001047]: module hangs at seemingly random times
From: bugtrack @ 2006-04-10 14:40 UTC (permalink / raw)
To: alsa-devel
A NOTE has been added to this issue.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1047>
======================================================================
Reported By: alien999999999
Assigned To: mjander
======================================================================
Project: ALSA - driver
Issue ID: 1047
Category: PCI - au88x0
Reproducibility: sometimes
Severity: block
Priority: normal
Status: assigned
Distribution: Mandrake
Kernel Version: 2.6.7
======================================================================
Date Submitted: 04-12-2005 20:43 CEST
Last Modified: 04-10-2006 16:39 CEST
======================================================================
Summary: module hangs at seemingly random times
Description:
sometimes i start playing a song, and it starts playing a few second or so
and hangs, then i kill the application and modprobe -r all sound modules
and modprobe them again to make it work again.
BUT: sometimes not only that happens, but also when i try to kill the apps
it will not kill. when that happens, all kill, killall, top, ps aux
commands hang at the command line and cannot be killed by CTRL-C or
otherwise, i have been able to see that when i stopped my display
managener I did an lsmod and it gave something like this:
snd-pcm-oss 59752 11
snd-mixer-oss 20480 1 snd-pcm-oss
snd-au8810 43760 220
snd-ac97-codec 83408 1 snd-au8810
snd-pcm 108172 112 snd-pcm-oss,snd-au8810,snd-ac97-codec
snd-page-alloc 10384 1 snd-pcm
gameport 3840 1 snd-au8810
snd-mpu401-uart 11904 1 snd-au8810
as you can see the snd-au8810 module seem to have an impossible number of
"dependencies" (i think has to do with the number of unclosed sound-apps
trying to be played; this could be since gaim is programmed to execute an
'aplay %s')
i've had this major crash below only 3 times; and the logs didn't detect
anything specific at the time. the only thing the logs mentioned at that
time was an ntpd sync going on; so the only thing i can think of is that
at a certain moment when a sync is going on, some kind of lock is holding
cause this to happen... the only thing that i can do to fix this is
reset...
it is interesting to note that i also have an snd-emu10k1 as second card,
which never gave problems like this, and i am always able to "modprobe -r
snd-emu10k1" ...
======================================================================
----------------------------------------------------------------------
Raymond - 04-10-06 16:07
----------------------------------------------------------------------
http://sourceforge.net/mailarchive/forum.php?thread_id=10142869&forum_id=33141
-static int vortex_eq_init(vortex_t * vortex)
+static int __devinit vortex_eq_init(vortex_t * vortex)
{
Is there any reason to add _devinit to vortex_eq_init() ?
The current way of using the equalizer through the kcontrol of the mixer
inferface.
----------------------------------------------------------------------
tiwai - 04-10-06 16:39
----------------------------------------------------------------------
Because these functions are called even in the initialization (in the error
path). See the changelog for details.
Issue History
Date Modified Username Field Change
======================================================================
04-12-05 20:43 alien999999999 New Issue
04-12-05 20:43 alien999999999 Distribution => Mandrake
04-12-05 20:43 alien999999999 Kernel Version => 2.6.7
04-12-05 20:48 alien999999999 Note Added: 0004461
04-12-05 20:49 alien999999999 File Added: au88x0.c
04-12-05 20:49 alien999999999 File Added: au88x0.h
04-12-05 20:50 alien999999999 File Added: au88x0_core.c
04-12-05 20:50 alien999999999 File Added: au88x0_mixer.c
04-12-05 20:51 alien999999999 Note Added: 0004462
08-24-05 11:13 Raymond Note Added: 0005928
10-27-05 02:27 Raymond Note Added: 0006564
01-03-06 04:04 Raymond Note Added: 0007397
01-04-06 22:08 alien999999999 Note Added: 0007455
01-05-06 07:21 Raymond Note Added: 0007462
01-05-06 20:32 shurick Issue Monitored: shurick
01-06-06 17:17 alien999999999 Note Added: 0007488
01-06-06 17:33 alien999999999 File Added: alsa-cvs-2006-01-04.patch
01-13-06 13:51 Raymond Note Added: 0007639
01-13-06 18:18 tiwai Note Added: 0007648
01-14-06 04:53 Raymond Note Added: 0007653
01-14-06 05:00 Raymond Note Edited: 0007653
01-17-06 12:27 Raymond Note Added: 0007697
01-18-06 15:51 Raymond Note Added: 0007710
01-18-06 15:52 Raymond File Added: au88x0_codec.patch
01-19-06 13:51 Raymond Note Added: 0007719
02-05-06 05:20 Raymond Note Edited: 0007710
02-05-06 05:28 Raymond Note Added: 0007930
02-13-06 16:38 Raymond Note Deleted: 0006564
02-13-06 16:41 Raymond Note Added: 0008054
03-01-06 07:39 Raymond Note Added: 0008273
03-18-06 12:28 Raymond Note Deleted: 0008273
03-20-06 17:54 Raymond File Added: au88x0_conf.patch
03-21-06 02:02 Raymond Note Added: 0008734
03-21-06 18:01 tiwai Note Added: 0008754
03-22-06 02:05 Raymond File Added: au88x0_mpu401.patch
03-22-06 02:28 Raymond Note Added: 0008779
03-22-06 02:31 Raymond Note Edited: 0008779
03-22-06 02:38 rlrevell Note Added: 0008782
03-22-06 04:00 Raymond Note Added: 0008836
03-22-06 04:09 rlrevell Note Added: 0008839
03-26-06 09:55 Raymond Note Added: 0008967
03-29-06 17:48 Raymond Note Added: 0008995
03-31-06 06:52 Raymond Note Edited: 0008995
04-02-06 07:01 Raymond Note Edited: 0008995
04-10-06 16:07 Raymond Note Added: 0009190
04-10-06 16:39 tiwai Note Added: 0009192
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* [ALSA - driver 0001732]: Support for Intel D945Pvs Board
From: bugtrack @ 2006-04-10 14:40 UTC (permalink / raw)
To: alsa-devel
The following issue has been RESOLVED.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1732>
======================================================================
Reported By: timtt
Assigned To: tiwai
======================================================================
Project: ALSA - driver
Issue ID: 1732
Category: PCI - hda-intel
Reproducibility: always
Severity: feature
Priority: normal
Status: resolved
Distribution: FC4
Kernel Version: 2.6.14-1656
Resolution: fixed
Fixed in Version:
======================================================================
Date Submitted: 01-11-2006 04:53 CET
Last Modified: 04-10-2006 16:40 CEST
======================================================================
Summary: Support for Intel D945Pvs Board
Description:
Alsa is only able to output regular 2-channel audio via the headphone jack
at the back of this motherboard. This motherboard has an SPDIF connection
available that is currently not supported, but should be.
======================================================================
----------------------------------------------------------------------
rlrevell - 04-09-06 23:30
----------------------------------------------------------------------
Can you please send the patch to alsa-devel at lists.sourceforge.net
mailing list (you do not have to subscribe), and include a Signed-Off-By
line?
----------------------------------------------------------------------
tiwai - 04-10-06 16:40
----------------------------------------------------------------------
Fixed on CVS now.
Issue History
Date Modified Username Field Change
======================================================================
01-11-06 04:53 timtt New Issue
01-11-06 04:53 timtt Distribution => FC4
01-11-06 04:53 timtt Kernel Version => 2.6.14-1656
01-11-06 05:04 rlrevell Note Added: 0007558
01-11-06 18:30 timtt Note Added: 0007563
01-11-06 18:36 rlrevell Note Added: 0007564
01-20-06 22:47 timtt Note Added: 0007728
04-09-06 23:19 aclark Note Added: 0009187
04-09-06 23:19 aclark File Added: sigmatel.diff
04-09-06 23:19 aclark Issue Monitored: aclark
04-09-06 23:30 rlrevell Note Added: 0009188
04-10-06 16:40 tiwai Status assigned => resolved
04-10-06 16:40 tiwai Resolution open => fixed
04-10-06 16:40 tiwai Note Added: 0009193
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* Re: 2G memory split
From: Mark Lord @ 2006-04-10 14:39 UTC (permalink / raw)
To: Kirill Korotaev
Cc: Sergey Vlasov, Jens Axboe, Byron Stanoszek, Ingo Molnar,
linux-kernel, Andrew Morton, Linus Torvalds
In-Reply-To: <443A6789.9090809@sw.ru>
Kirill Korotaev wrote:
>>> +#if defined(CONFIG_DEFAULT_3G)
>>> +#define __PAGE_OFFSET_RAW (0xC0000000)
>>> +#elif defined(CONFIG_DEFAULT_3G_OPT)
>>> +#define __PAGE_OFFSET_RAW (0xB0000000)
>>> +#elif defined(CONFIG_DEFAULT_2G)
>>> +#define __PAGE_OFFSET_RAW (0x78000000)
>>> +#elif defined(CONFIG_DEFAULT_1G)
>>> +#define __PAGE_OFFSET_RAW (0x40000000)
>>> +#else
>>> +#error "Bad user/kernel offset"
>>> +#endif
>>> +
>>> #ifdef __ASSEMBLY__
>>> -#define __PAGE_OFFSET (0xC0000000)
>>> +#define __PAGE_OFFSET __PAGE_OFFSET_RAW
>>> #define __PHYSICAL_START CONFIG_PHYSICAL_START
>>> #else
>>> -#define __PAGE_OFFSET (0xC0000000UL)
>>> +#define __PAGE_OFFSET ((unsigned long)__PAGE_OFFSET_RAW)
>>> #define __PHYSICAL_START ((unsigned long)CONFIG_PHYSICAL_START)
>>> #endif
>>> #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START)
>>
>> Changing PAGE_OFFSET this way would break at least Valgrind (the latest
>> release 3.1.0 by default is statically linked at address 0xb0000000, and
>> PIE support does not seem to be present in that release). I remember
>> that similar changes were also breaking Lisp implementations (cmucl,
>> sbcl), however, I am not really sure about this.
> it also breaks some java versions, so we use 3:4 Gb split in OpenVZ, but
> redhat still uses 4:4 in enterprise version, so number of such
> applications should decrease :)
Mmm.. that's an old thread. The reply above was to
a posting from Sergey Vlasov (the same) on Tue Jan 10 2006,
12:06:50 EST.
^ permalink raw reply
* [LARTC] Where is the documentation for IFB ?
From: openswan @ 2006-04-10 14:41 UTC (permalink / raw)
To: lartc
Hi all,
Can you tell me where is the documentation for the new IFB (implemented
in kernels > 2.6.16).
Thanks in advance!
Nikolay
_______________________________________________
LARTC mailing list
LARTC@mailman.ds9a.nl
http://mailman.ds9a.nl/cgi-bin/mailman/listinfo/lartc
^ permalink raw reply
* Subject: [PATCH] Allow menuconfig to hotkey cycle through choices
From: John Rigby @ 2006-04-10 14:42 UTC (permalink / raw)
To: Roman Zippel; +Cc: lkml, Sam Ravnborg
[-- Attachment #1: Type: text/plain, Size: 79 bytes --]
Same patch as before now with better description added as requested by Roman.
[-- Attachment #2: 0001-Allow-menuconfig-to-cycle-through-choices.txt --]
[-- Type: text/plain, Size: 1508 bytes --]
Subject: [PATCH] Allow menuconfig to hotkey cycle through choices
If you have multiple configs inside a choice with prompts that start with the
same character typing the first character takes you to the first one under
the old behavior. You have to use arrow or +/- keys to go to the other choices.
With the patch typing the first character will cycle between all the
prompts starting with that character.
This behavior has always been available in normal "menus" which are handled by
dialog_menu. This patch adds the same functionality to dialog_checklist.
Signed-off-by: John Rigby <jrigby@freescale.com>
---
scripts/kconfig/lxdialog/checklist.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
8c5500ea727987ea35a7ccaa463dcaf50eb731b2
diff --git a/scripts/kconfig/lxdialog/checklist.c b/scripts/kconfig/lxdialog/checklist.c
index db07ae7..af41cb1 100644
--- a/scripts/kconfig/lxdialog/checklist.c
+++ b/scripts/kconfig/lxdialog/checklist.c
@@ -203,10 +203,15 @@ int dialog_checklist(const char *title,
while (key != ESC) {
key = wgetch(dialog);
- for (i = 0; i < max_choice; i++)
+ for (i = choice + 1; i < max_choice; i++)
if (toupper(key) ==
toupper(items[(scroll + i) * 3 + 1][0]))
break;
+ if (i == max_choice)
+ for (i = 0; i < max_choice; i++)
+ if (toupper(key) ==
+ toupper(items[(scroll + i) * 3 + 1][0]))
+ break;
if (i < max_choice || key == KEY_UP || key == KEY_DOWN ||
key == '+' || key == '-') {
--
1.2.4
^ permalink raw reply related
* [ALSA - driver 0001047]: module hangs at seemingly random times
From: bugtrack @ 2006-04-10 14:43 UTC (permalink / raw)
To: alsa-devel
A NOTE has been added to this issue.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1047>
======================================================================
Reported By: alien999999999
Assigned To: mjander
======================================================================
Project: ALSA - driver
Issue ID: 1047
Category: PCI - au88x0
Reproducibility: sometimes
Severity: block
Priority: normal
Status: assigned
Distribution: Mandrake
Kernel Version: 2.6.7
======================================================================
Date Submitted: 04-12-2005 20:43 CEST
Last Modified: 04-10-2006 16:43 CEST
======================================================================
Summary: module hangs at seemingly random times
Description:
sometimes i start playing a song, and it starts playing a few second or so
and hangs, then i kill the application and modprobe -r all sound modules
and modprobe them again to make it work again.
BUT: sometimes not only that happens, but also when i try to kill the apps
it will not kill. when that happens, all kill, killall, top, ps aux
commands hang at the command line and cannot be killed by CTRL-C or
otherwise, i have been able to see that when i stopped my display
managener I did an lsmod and it gave something like this:
snd-pcm-oss 59752 11
snd-mixer-oss 20480 1 snd-pcm-oss
snd-au8810 43760 220
snd-ac97-codec 83408 1 snd-au8810
snd-pcm 108172 112 snd-pcm-oss,snd-au8810,snd-ac97-codec
snd-page-alloc 10384 1 snd-pcm
gameport 3840 1 snd-au8810
snd-mpu401-uart 11904 1 snd-au8810
as you can see the snd-au8810 module seem to have an impossible number of
"dependencies" (i think has to do with the number of unclosed sound-apps
trying to be played; this could be since gaim is programmed to execute an
'aplay %s')
i've had this major crash below only 3 times; and the logs didn't detect
anything specific at the time. the only thing the logs mentioned at that
time was an ntpd sync going on; so the only thing i can think of is that
at a certain moment when a sync is going on, some kind of lock is holding
cause this to happen... the only thing that i can do to fix this is
reset...
it is interesting to note that i also have an snd-emu10k1 as second card,
which never gave problems like this, and i am always able to "modprobe -r
snd-emu10k1" ...
======================================================================
----------------------------------------------------------------------
tiwai - 04-10-06 16:39
----------------------------------------------------------------------
Because these functions are called even in the initialization (in the error
path). See the changelog for details.
----------------------------------------------------------------------
Raymond - 04-10-06 16:43
----------------------------------------------------------------------
http://www.lkml.org/lkml/2006/4/10/76
I2S (device 4) has not been implemented in au88x0
// ADB pcm.
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
snd_card_free(card);
return err;
}
#ifndef CHIP_AU8820
// ADB SPDIF
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) {
snd_card_free(card);
return err;
}
// A3D
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) {
snd_card_free(card);
return err;
}
#endif
/*
// ADB I2S
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
snd_card_free(card);
return err;
}
*/
#ifndef CHIP_AU8810
// WT pcm.
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) {
snd_card_free(card);
return err;
}
#endif
Do we really need the check ?
- if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
+ if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
return -ENODEV;
Issue History
Date Modified Username Field Change
======================================================================
04-12-05 20:43 alien999999999 New Issue
04-12-05 20:43 alien999999999 Distribution => Mandrake
04-12-05 20:43 alien999999999 Kernel Version => 2.6.7
04-12-05 20:48 alien999999999 Note Added: 0004461
04-12-05 20:49 alien999999999 File Added: au88x0.c
04-12-05 20:49 alien999999999 File Added: au88x0.h
04-12-05 20:50 alien999999999 File Added: au88x0_core.c
04-12-05 20:50 alien999999999 File Added: au88x0_mixer.c
04-12-05 20:51 alien999999999 Note Added: 0004462
08-24-05 11:13 Raymond Note Added: 0005928
10-27-05 02:27 Raymond Note Added: 0006564
01-03-06 04:04 Raymond Note Added: 0007397
01-04-06 22:08 alien999999999 Note Added: 0007455
01-05-06 07:21 Raymond Note Added: 0007462
01-05-06 20:32 shurick Issue Monitored: shurick
01-06-06 17:17 alien999999999 Note Added: 0007488
01-06-06 17:33 alien999999999 File Added: alsa-cvs-2006-01-04.patch
01-13-06 13:51 Raymond Note Added: 0007639
01-13-06 18:18 tiwai Note Added: 0007648
01-14-06 04:53 Raymond Note Added: 0007653
01-14-06 05:00 Raymond Note Edited: 0007653
01-17-06 12:27 Raymond Note Added: 0007697
01-18-06 15:51 Raymond Note Added: 0007710
01-18-06 15:52 Raymond File Added: au88x0_codec.patch
01-19-06 13:51 Raymond Note Added: 0007719
02-05-06 05:20 Raymond Note Edited: 0007710
02-05-06 05:28 Raymond Note Added: 0007930
02-13-06 16:38 Raymond Note Deleted: 0006564
02-13-06 16:41 Raymond Note Added: 0008054
03-01-06 07:39 Raymond Note Added: 0008273
03-18-06 12:28 Raymond Note Deleted: 0008273
03-20-06 17:54 Raymond File Added: au88x0_conf.patch
03-21-06 02:02 Raymond Note Added: 0008734
03-21-06 18:01 tiwai Note Added: 0008754
03-22-06 02:05 Raymond File Added: au88x0_mpu401.patch
03-22-06 02:28 Raymond Note Added: 0008779
03-22-06 02:31 Raymond Note Edited: 0008779
03-22-06 02:38 rlrevell Note Added: 0008782
03-22-06 04:00 Raymond Note Added: 0008836
03-22-06 04:09 rlrevell Note Added: 0008839
03-26-06 09:55 Raymond Note Added: 0008967
03-29-06 17:48 Raymond Note Added: 0008995
03-31-06 06:52 Raymond Note Edited: 0008995
04-02-06 07:01 Raymond Note Edited: 0008995
04-10-06 16:07 Raymond Note Added: 0009190
04-10-06 16:39 tiwai Note Added: 0009192
04-10-06 16:43 Raymond Note Added: 0009194
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* [2.6.16 PATCH] Filessytem Events Reporter V3
From: Yi Yang @ 2006-04-10 14:44 UTC (permalink / raw)
To: LKML; +Cc: Andrew Morton, Evgeniy Polyakov, Matt Helsley
Compared with Filesystem Events Reporter v2, the following changes are done:
- Can be built as module.
- Fix some bugs pointed out by Evgeniy
- Substitute spinlock with mutex
- Complete exit cleanup
This patch implements a filsystem events report facitily, Filesystem Events
Reporter, the user can monitor filesystem activities via it, currently, it
can monitor access, attribute change, open, create, modify, delete,
move and close of any file or directory as well as mount/umount.
Every filesystem event will include tgid, uid and gid of the process
which triggered this event, process name, file or directory name
operated by it.
Filesystem Events Reporter is never a duplicate of inotify, inotify
just concerns change on file or directory, Beagle uses it to watch
file changes in order to regenerate index for it, inotify can't tell
us who did that change and what is its process name, but filesystem
events reporter can do these, moreover inotify's overhead is greater
than filesystem events reporter, inotify needs compare inode with
watched file or directories list to decide whether it should generate an
inotify_event, some locks also increase overhead, filesystem event
connector hasn't these overhead, it just generates a fsevent and send.
To be important, filesystem event reporter doesn't add any new system
call, the user space application can make use of it by netlink socket,
but inotify added several system calls, many events mechanism in kernel
have used netlink as communication way with user space, for example,
KOBJECT_UEVENT, PROC_EVENTS, to use netlink will make it more possible
to unify events interface to netlink, the user space application can use
it very easy.
Every application using fsevent can set its own fsevent filter list
without effect in other applications using fsevent, there are three
filter lists, they are pid filter list, uid filetr list and gid
filter list, respectively, moreover, there is a fsevent mask used to
control those fsevents which fail to match three filter lists, an
application using fsevent can listen those fsevents it want to
monitor and ignore those fsevents it doesn't interest in by set
series of filters, there is a fsevent mask used to take effects on
all the applications using fsevent, it can be set by sysctl and proc
interface.
fs/Kconfig | 10
fs/Makefile | 3
fs/fsevent.c | 613 +++++++++++++++++++++++++++++++++++++++++++++++
fs/fsevent_hook.c | 5
fs/namespace.c | 12
include/linux/fsevent.h | 167 ++++++++++++
include/linux/fsnotify.h | 37 ++
include/linux/netlink.h | 1
8 files changed, 848 insertions(+)
Signed-off-by: Yi Yang <yang.y.yi@gmail.com>
--- a/include/linux/netlink.h.orig 2006-03-31 22:58:50.000000000 +0800
+++ b/include/linux/netlink.h 2006-04-05 21:06:15.000000000 +0800
@@ -21,6 +21,7 @@
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC 16
+#define NETLINK_FSEVENT 17 /* File system events to userspace */
#define MAX_LINKS 32
--- a/include/linux/fsnotify.h.orig 2006-01-03 11:21:10.000000000 +0800
+++ b/include/linux/fsnotify.h 2006-04-05 21:06:15.000000000 +0800
@@ -15,6 +15,7 @@
#include <linux/dnotify.h>
#include <linux/inotify.h>
+#include <linux/fsevent.h>
/*
* fsnotify_move - file old_name at old_dir was moved to new_name at new_dir
@@ -45,6 +46,8 @@ static inline void fsnotify_move(struct
if (source) {
inotify_inode_queue_event(source, IN_MOVE_SELF, 0, NULL);
}
+ raise_fsevent_move(old_dir, old_name, new_dir, new_name,
+ FSEVENT_MOVE | (isdir?FSEVENT_ISDIR:0));
}
/*
@@ -56,6 +59,8 @@ static inline void fsnotify_nameremove(s
isdir = IN_ISDIR;
dnotify_parent(dentry, DN_DELETE);
inotify_dentry_parent_queue_event(dentry, IN_DELETE|isdir, 0, dentry->d_name.name);
+ raise_fsevent(dentry,
+ FSEVENT_DELETE | (isdir?FSEVENT_ISDIR:0));
}
/*
@@ -74,6 +79,7 @@ static inline void fsnotify_create(struc
{
inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE, 0, name);
+ raise_fsevent_create(inode, name, FSEVENT_CREATE);
}
/*
@@ -83,6 +89,8 @@ static inline void fsnotify_mkdir(struct
{
inode_dir_notify(inode, DN_CREATE);
inotify_inode_queue_event(inode, IN_CREATE | IN_ISDIR, 0, name);
+ raise_fsevent_create(inode, name,
+ FSEVENT_CREATE | FSEVENT_ISDIR);
}
/*
@@ -99,6 +107,8 @@ static inline void fsnotify_access(struc
dnotify_parent(dentry, DN_ACCESS);
inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
inotify_inode_queue_event(inode, mask, 0, NULL);
+ raise_fsevent(dentry, FSEVENT_ACCESS |
+ ((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
}
/*
@@ -115,6 +125,8 @@ static inline void fsnotify_modify(struc
dnotify_parent(dentry, DN_MODIFY);
inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
inotify_inode_queue_event(inode, mask, 0, NULL);
+ raise_fsevent(dentry, FSEVENT_MODIFY |
+ ((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
}
/*
@@ -130,6 +142,9 @@ static inline void fsnotify_open(struct
inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
inotify_inode_queue_event(inode, mask, 0, NULL);
+ raise_fsevent(dentry, FSEVENT_OPEN |
+ ((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
+
}
/*
@@ -148,6 +163,8 @@ static inline void fsnotify_close(struct
inotify_dentry_parent_queue_event(dentry, mask, 0, name);
inotify_inode_queue_event(inode, mask, 0, NULL);
+ raise_fsevent(dentry, FSEVENT_CLOSE |
+ ((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
}
/*
@@ -163,6 +180,8 @@ static inline void fsnotify_xattr(struct
inotify_dentry_parent_queue_event(dentry, mask, 0, dentry->d_name.name);
inotify_inode_queue_event(inode, mask, 0, NULL);
+ raise_fsevent(dentry, FSEVENT_MODIFY_ATTRIB |
+ ((S_ISDIR(inode->i_mode))?FSEVENT_ISDIR:0));
}
/*
@@ -213,6 +232,24 @@ static inline void fsnotify_change(struc
inotify_dentry_parent_queue_event(dentry, in_mask, 0,
dentry->d_name.name);
}
+
+#ifdef CONFIG_FS_EVENTS
+ {
+ u32 fsevent_mask = 0;
+ if (ia_valid & (ATTR_UID | ATTR_GID | ATTR_MODE))
+ fsevent_mask |= FSEVENT_MODIFY_ATTRIB;
+ if ((ia_valid & ATTR_ATIME) && (ia_valid & ATTR_MTIME))
+ fsevent_mask |= FSEVENT_MODIFY_ATTRIB;
+ else if (ia_valid & ATTR_ATIME)
+ fsevent_mask |= FSEVENT_ACCESS;
+ else if (ia_valid & ATTR_MTIME)
+ fsevent_mask |= FSEVENT_MODIFY;
+ if (ia_valid & ATTR_SIZE)
+ fsevent_mask |= FSEVENT_MODIFY;
+ if (fsevent_mask)
+ raise_fsevent(dentry, fsevent_mask);
+ }
+#endif /* CONFIG_FS_EVENTS */
}
#ifdef CONFIG_INOTIFY /* inotify helpers */
--- a/fs/namespace.c.orig 2006-03-25 23:13:42.000000000 +0800
+++ b/fs/namespace.c 2006-04-05 21:06:15.000000000 +0800
@@ -25,6 +25,7 @@
#include <linux/mount.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
+#include <linux/fsevent.h>
#include "pnode.h"
extern int __init init_rootfs(void);
@@ -612,6 +613,13 @@ asmlinkage long sys_umount(char __user *
goto dput_and_out;
retval = do_umount(nd.mnt, flags);
+
+ if (retval == 0) {
+ char * tmp = getname(name);
+ raise_fsevent_umount(tmp);
+ putname(tmp);
+ }
+
dput_and_out:
path_release_on_umount(&nd);
out:
@@ -1459,6 +1467,10 @@ asmlinkage long sys_mount(char __user *
retval = do_mount((char *)dev_page, dir_page, (char *)type_page,
flags, (void *)data_page);
unlock_kernel();
+
+ if (retval == 0)
+ raise_fsevent_mount((char *)dev_page, dir_page);
+
free_page(data_page);
out3:
--- a/fs/Kconfig.orig 2006-03-31 21:23:20.000000000 +0800
+++ b/fs/Kconfig 2006-04-05 21:06:15.000000000 +0800
@@ -405,6 +405,16 @@ config INOTIFY
If unsure, say Y.
+config FS_EVENTS
+ tristate "Report filesystem events to userspace"
+ ---help---
+ Provide a facility that reports filesystem events to userspace. The
+ reported event include access, write, utime, chmod, chown, chgrp,
+ close, open, create, rename, unlink, mkdir, rmdir, mount, umount.
+
+ The user can set filesystem events filter to filter its events, so
+ that he just get those events he concerns.
+
config QUOTA
bool "Quota support"
help
--- a/fs/Makefile.orig 2006-03-31 21:23:33.000000000 +0800
+++ b/fs/Makefile 2006-04-10 22:23:37.000000000 +0800
@@ -13,6 +13,9 @@ obj-y := open.o read_write.o file_table.
ioprio.o pnode.o drop_caches.o
obj-$(CONFIG_INOTIFY) += inotify.o
+obj-$(CONFIG_FS_EVENTS) += fsevent.o
+fseventbase-$(CONFIG_FS_EVENTS) := fsevent_hook.o
+obj-y += $(fseventbase-y) $(fseventbase-m)
obj-$(CONFIG_EPOLL) += eventpoll.o
obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o
--- /dev/null 2003-01-30 18:24:37.000000000 +0800
+++ b/include/linux/fsevent.h 2006-04-08 22:09:30.000000000 +0800
@@ -0,0 +1,167 @@
+/*
+ * fsevent.h - filesystem events connector
+ *
+ * Copyright (C) 2006 Yi Yang <yang.y.yi@gmail.com>
+ * Based on cn_proc.h by Matt Helsley, IBM Corp
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LINUX_FSEVENT_H
+#define LINUX_FSEVENT_H
+
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/netlink.h>
+
+enum fsevent_type {
+ FSEVENT_ACCESS = 0x00000001, /* File was accessed */
+ FSEVENT_MODIFY = 0x00000002, /* File was modified */
+ FSEVENT_MODIFY_ATTRIB = 0x00000004, /* Metadata changed */
+ FSEVENT_CLOSE = 0x00000008, /* File was closed */
+ FSEVENT_OPEN = 0x00000010, /* File was opened */
+ FSEVENT_MOVE = 0x00000020, /* File was moved */
+ FSEVENT_CREATE = 0x00000040, /* File was created */
+ FSEVENT_DELETE = 0x00000080, /* File was deleted */
+ FSEVENT_MOUNT = 0x00000100, /* File system is mounted */
+ FSEVENT_UMOUNT = 0x00000200, /* File system is umounted */
+
+ /* The following definitions are command types for fsevent filter
+ * or acknowlege types of the corresponding commands
+ */
+ FSEVENT_FILTER_ALL = 0x08000000, /* For all events */
+ FSEVENT_FILTER_PID = 0x10000000, /* For some process ID */
+ FSEVENT_FILTER_UID = 0x20000000, /* For some user ID */
+ FSEVENT_FILTER_GID = 0x40000000, /* For some group ID */
+
+ FSEVENT_ISDIR = 0x80000000 /* It is set for a dir */
+};
+
+#define FSEVENT_MASK 0x800003ff
+
+typedef unsigned long fsevent_mask_t;
+
+enum filter_control {
+ FSEVENT_FILTER_LISTEN = 1, /* Listen fsevents mask defines*/
+ FSEVENT_FILTER_IGNORE , /* Ignore fsevents mask defines*/
+ FSEVENT_FILTER_REMOVE, /* Remove a given filter */
+};
+
+struct fsevent_filter {
+ /* filter type, it just is one of them
+ * FSEVENT_FILTER_ALL
+ * FSEVENT_FILTER_PID
+ * FSEVENT_FILTER_UID
+ * FSEVENT_FILTER_GID
+ */
+ enum fsevent_type type; /* filter type */
+
+ /* mask of file system events the user listen or ignore
+ * if the user need to ignore all the events of some pid
+ * , gid or uid, he(she) must set mask to FSEVENT_MASK.
+ */
+ fsevent_mask_t mask;
+ union {
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ } id;
+
+ enum filter_control control;
+};
+
+struct fsevent {
+ __u32 type;
+ __u32 cpu;
+ struct timespec timestamp;
+ pid_t pid;
+ uid_t uid;
+ gid_t gid;
+ int err;
+ __u32 len;
+ __u32 pname_len;
+ __u32 fname_len;
+ __u32 new_fname_len;
+ char name[0];
+};
+
+#define FSEVENT_FILTER_MSGSIZE \
+ (sizeof(struct fsevent_filter) + sizeof(struct nlmsghdr))
+
+#ifdef __KERNEL__
+#if defined(CONFIG_FS_EVENTS) || defined(CONFIG_FS_EVENTS_MODULE)
+extern int (* _raise_fsevent)
+ (const char * oldname, const char * newname, u32 mask);
+
+static inline void raise_fsevent(struct dentry * dentryp, u32 mask)
+{
+ if (!_raise_fsevent)
+ return;
+ if (dentryp->d_inode && (MAJOR(dentryp->d_inode->i_rdev) == 4))
+ return;
+ _raise_fsevent(dentryp->d_name.name, NULL, mask);
+}
+
+static inline void raise_fsevent_move(struct inode * olddir,
+ const char * oldname, struct inode * newdir,
+ const char * newname, u32 mask)
+{
+ if (!_raise_fsevent)
+ return;
+ _raise_fsevent(oldname, newname, mask);
+}
+
+static inline void raise_fsevent_create(struct inode * inode,
+ const char * name, u32 mask)
+{
+ if (!_raise_fsevent)
+ return;
+ _raise_fsevent(name, NULL, mask);
+}
+
+static inline void raise_fsevent_mount(const char * devname,
+ const char * mountpoint)
+{
+ if (!_raise_fsevent)
+ return;
+ _raise_fsevent(devname, mountpoint, FSEVENT_MOUNT);
+}
+
+static inline void raise_fsevent_umount(const char * mountpoint)
+{
+ if (!_raise_fsevent)
+ return;
+ _raise_fsevent(mountpoint, NULL, FSEVENT_UMOUNT);
+}
+#else
+static void raise_fsevent(struct dentry * dentryp, u32 mask)
+{}
+
+static void raise_fsevent_move(struct inode * olddir, const char * oldname,
+ struct inode * newdir, const char * newname, u32 mask)
+{}
+
+static void raise_fsevent_create(struct inode * inode,
+ const char * name, u32 mask)
+{}
+
+static void raise_fsevent_mount(const char * devname, const char * mountpoint)
+{}
+
+static void raise_fsevent_umount(const char * mountpoint)
+{}
+#endif /* CONFIG_FS_EVENTS || CONFIG_FS_EVENTS_MODULE */
+#endif /* __KERNEL__ */
+#endif /* LINUX_FSEVENT_H */
--- /dev/null 2003-01-30 18:24:37.000000000 +0800
+++ b/fs/fsevent.c 2006-04-10 22:06:45.000000000 +0800
@@ -0,0 +1,613 @@
+/*
+ * fsevent.c
+ *
+ * 2006 Copyright (c) Yi Yang <yang.y.yi@gmail.com>
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/moduleparam.h>
+#include <linux/fsevent.h>
+#include <linux/skbuff.h>
+#include <net/sock.h>
+#include <linux/list.h>
+#include <linux/percpu.h>
+#include <linux/cpu.h>
+#include <linux/kthread.h>
+#include <linux/notifier.h>
+#include <linux/compiler.h>
+#include <linux/workqueue.h>
+#include <linux/sysctl.h>
+#include <linux/mutex.h>
+
+#define FSEVENT_MASK_CTL_NAME -2
+
+static DEFINE_PER_CPU(struct sk_buff_head, fsevent_send_queue);
+static DEFINE_PER_CPU(struct work_struct, fsevent_work);
+
+typedef struct pid_filter {
+ pid_t pid;
+ u32 mask;
+ struct list_head list;
+} pid_filter;
+
+typedef struct uid_filter {
+ uid_t uid;
+ u32 mask;
+ struct list_head list;
+} uid_filter;
+
+typedef struct gid_filter {
+ gid_t gid;
+ u32 mask;
+ struct list_head list;
+} gid_filter;
+
+typedef struct fsevent_listener {
+ pid_t pid;
+ struct list_head pid_filter_list_head;
+ struct list_head uid_filter_list_head;
+ struct list_head gid_filter_list_head;
+ u32 mask;
+ struct list_head list;
+} listener;
+
+
+/* The netlink socket. */
+static struct sock * fsevent_sock = NULL;
+static LIST_HEAD(listener_list_head);
+static DEFINE_MUTEX(listener_list_mutex);
+
+static atomic_t fsevent_count = ATOMIC_INIT(0);
+static int fsevent_burst_limit = 100;
+static int fsevent_ratelimit = 5 * HZ;
+static unsigned long last = 0;
+static int fsevent_sum = 0;
+static u32 fsevents_mask = FSEVENT_MASK;
+static atomic_t fsevent_listener_num = ATOMIC_INIT(0);
+static int exit_flag = 0;
+
+static inline void get_seq(__u32 *ts, int *cpu)
+{
+ *ts = atomic_inc_return(&fsevent_count);
+ *cpu = smp_processor_id();
+}
+
+static void append_string(char **dest, const char *src, size_t len)
+{
+ strncpy(*dest, src, len);
+ (*dest)[len] = '\0';
+ *dest += len + 1;
+}
+
+static inline int filter_fsevent(u32 filter_mask, u32 event_mask)
+{
+ event_mask &= FSEVENT_MASK;
+ event_mask &= filter_mask;
+ if (event_mask == 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static int filter_fsevent_all(u32 * mask)
+{
+ int ret = 0;
+
+ (*mask) &= FSEVENT_MASK;
+
+ if ((((*mask) & FSEVENT_ISDIR) == FSEVENT_ISDIR)
+ && ((fsevents_mask & FSEVENT_ISDIR) == 0)) {
+ ret = -1;
+ goto out;
+ }
+
+ (*mask) &= fsevents_mask;
+ if ((*mask) == 0) {
+ ret = -1;
+ }
+
+out:
+ return ret;
+}
+
+static void fsevent_send(struct sk_buff * skb)
+{
+ struct sk_buff_head * head = &get_cpu_var(fsevent_send_queue);
+ skb_queue_tail(head, skb);
+ schedule_work(&per_cpu(fsevent_work, smp_processor_id()));
+ put_cpu_var(fsevent_send_queue);
+}
+
+int __raise_fsevent(const char * oldname, const char * newname, u32 mask)
+{
+ struct fsevent *event;
+ int namelen = 0;
+ char * nameptr = NULL;
+ unsigned int size;
+ struct nlmsghdr * nlhdr;
+ struct sk_buff * skb = NULL;
+
+ if (filter_fsevent_all(&mask) != 0)
+ return -1;
+
+ if (atomic_read(&fsevent_listener_num) <= 0)
+ return -1;
+
+ if (jiffies - last <= fsevent_ratelimit) {
+ if (fsevent_sum > fsevent_burst_limit)
+ return -1;
+ fsevent_sum++;
+ } else {
+ last = jiffies;
+ fsevent_sum = 0;
+ }
+
+ namelen = strlen(current->comm) + strlen(oldname) + 2;
+ if (newname)
+ namelen += strlen(newname) + 1;
+
+ size = NLMSG_SPACE(sizeof(struct fsevent) + namelen);
+
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb)
+ return -1;
+
+ nlhdr = NLMSG_PUT(skb, 0, 0, NLMSG_DONE, size - sizeof(*nlhdr));
+ event = NLMSG_DATA(nlhdr);
+
+ get_seq(&(nlhdr->nlmsg_seq), &event->cpu);
+ ktime_get_ts(&event->timestamp);
+ event->type = mask;
+ event->pid = current->tgid;
+ event->uid = current->uid;
+ event->gid = current->gid;
+ nameptr = event->name;
+ event->pname_len = strlen(current->comm);
+ append_string(&nameptr, current->comm, event->pname_len);
+ event->fname_len = strlen(oldname);
+ append_string(&nameptr, oldname, event->fname_len);
+ event->len = event->pname_len + event->fname_len + 2;
+ event->new_fname_len = 0;
+ if (newname) {
+ event->new_fname_len = strlen(newname);
+ append_string(&nameptr, newname, event->new_fname_len);
+ event->len += event->new_fname_len + 1;
+ }
+ fsevent_send(skb);
+ return 0;
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -1;
+}
+
+static int fsevent_ack(enum fsevent_type type, pid_t pid, u32 seq)
+{
+ struct fsevent *event;
+ unsigned int size;
+ struct sk_buff * skb = NULL;
+ struct nlmsghdr * nlhdr = NULL;
+
+ size = NLMSG_SPACE(sizeof(struct fsevent));
+
+ skb = alloc_skb(size, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ nlhdr = NLMSG_PUT(skb, 0, seq, NLMSG_DONE, size - sizeof(*nlhdr));
+ event = NLMSG_DATA(nlhdr);
+
+ ktime_get_ts(&event->timestamp);
+ event->cpu = -1;
+ event->type = type;
+ event->pid = 0;
+ event->uid = 0;
+ event->gid = 0;
+ event->len = 0;
+ event->pname_len = 0;
+ event->fname_len = 0;
+ event->new_fname_len = 0;
+ event->err = 0;
+
+ NETLINK_CB(skb).dst_group = 0;
+ NETLINK_CB(skb).dst_pid = pid;
+ NETLINK_CB(skb).pid = 0;
+
+ return (netlink_unicast(fsevent_sock, skb, pid, MSG_DONTWAIT));
+
+nlmsg_failure:
+ kfree_skb(skb);
+ return -1;
+}
+
+static void set_fsevent_mask(u32 * to_mask, u32 from_mask, int mode)
+{
+ if (mode == FSEVENT_FILTER_IGNORE)
+ (*to_mask) &= ~(from_mask);
+ else if (mode == FSEVENT_FILTER_LISTEN)
+ (*to_mask) |= from_mask;
+}
+
+#define DEFINE_FILTER_FIND_FUNC(type, key) \
+ type * find_##type(struct list_head * head, key##_t id) \
+ { \
+ int alloc_flag = 1; \
+ type * entry = NULL; \
+ \
+ list_for_each_entry(entry, head, list) { \
+ if (entry->key == id) { \
+ alloc_flag = 0; \
+ break; \
+ } \
+ } \
+ \
+ if (alloc_flag == 1) { \
+ entry = (type *)kmalloc(sizeof(type), GFP_KERNEL); \
+ if (entry == NULL) \
+ return NULL; \
+ memset(entry, 0, sizeof(type)); \
+ entry->key = id; \
+ list_add_tail(&(entry->list), head); \
+ } \
+ return entry; \
+ } \
+
+DEFINE_FILTER_FIND_FUNC(pid_filter, pid)
+
+DEFINE_FILTER_FIND_FUNC(uid_filter, uid)
+
+DEFINE_FILTER_FIND_FUNC(gid_filter, gid)
+
+DEFINE_FILTER_FIND_FUNC(listener, pid)
+
+static int set_fsevent_filter(struct fsevent_filter * filter, pid_t pid)
+{
+ enum fsevent_type type;
+ u32 mask = 0;
+ int control = 0;
+ listener * listenerp = NULL;
+ pid_filter * pfilter = NULL;
+ uid_filter * ufilter = NULL;
+ gid_filter * gfilter = NULL;
+ int ret = 0;
+
+ mask = filter->mask;
+ control = filter->control;
+ type = filter->type;
+ mask &= FSEVENT_MASK;
+ if (mask == 0) {
+ ret = -1;
+ goto out;
+ }
+
+ mutex_lock(&listener_list_mutex);
+ listenerp = find_listener(&listener_list_head, pid);
+ if (unlikely(listenerp == NULL)) {
+ mutex_unlock(&listener_list_mutex);
+ return -1;
+ }
+
+ if (!(listenerp->pid_filter_list_head.next)) {
+ INIT_LIST_HEAD(&(listenerp->pid_filter_list_head));
+ INIT_LIST_HEAD(&(listenerp->uid_filter_list_head));
+ INIT_LIST_HEAD(&(listenerp->gid_filter_list_head));
+ }
+
+ if ((type & FSEVENT_FILTER_ALL) == FSEVENT_FILTER_ALL) {
+ if (control == FSEVENT_FILTER_REMOVE) {
+ atomic_dec(&fsevent_listener_num);
+ list_del(&(listenerp->list));
+ kfree(listenerp);
+ } else
+ set_fsevent_mask(&(listenerp->mask), mask, control);
+ } else if ((type & FSEVENT_FILTER_PID) == FSEVENT_FILTER_PID) {
+ pfilter = find_pid_filter(&(listenerp->pid_filter_list_head),
+ filter->id.pid);
+ if (unlikely(pfilter == NULL))
+ return -1;
+
+ if (control == FSEVENT_FILTER_REMOVE) {
+ list_del(&(pfilter->list));
+ kfree(pfilter);
+ } else
+ set_fsevent_mask(&(pfilter->mask), mask, control);
+ } else if ((type & FSEVENT_FILTER_UID) == FSEVENT_FILTER_UID) {
+ ufilter = find_uid_filter(&(listenerp->uid_filter_list_head),
+ filter->id.uid);
+ if (unlikely(ufilter == NULL))
+ return -1;
+
+ if (control == FSEVENT_FILTER_REMOVE) {
+ list_del(&(ufilter->list));
+ kfree(ufilter);
+ } else
+ set_fsevent_mask(&(ufilter->mask), mask, control);
+ } else if ((type & FSEVENT_FILTER_GID) == FSEVENT_FILTER_GID) {
+ gfilter = find_gid_filter(&(listenerp->gid_filter_list_head),
+ filter->id.gid);
+ if (unlikely(gfilter == NULL))
+ return -1;
+
+ if (control == FSEVENT_FILTER_REMOVE) {
+ list_del(&(gfilter->list));
+ kfree(gfilter);
+ } else
+ set_fsevent_mask(&(gfilter->mask), mask, control);
+ }
+ mutex_unlock(&listener_list_mutex);
+ ret = 0;
+
+out:
+ fsevent_ack(type, pid, 0);
+ return(ret);
+}
+
+static listener * find_fsevent_listener(pid_t pid)
+{
+ listener * listenerp = NULL;
+ mutex_lock(&listener_list_mutex);
+ list_for_each_entry(listenerp, &listener_list_head, list) {
+ if (listenerp->pid == pid) {
+ mutex_unlock(&listener_list_mutex);
+ return listenerp;
+ }
+ }
+ mutex_unlock(&listener_list_mutex);
+ return NULL;
+}
+
+static void cleanup_dead_listener(listener * x)
+{
+ pid_filter * p = NULL, * pq = NULL;
+ uid_filter * u = NULL, * uq = NULL;
+ gid_filter * g = NULL, * gq = NULL;
+
+ if (x == NULL)
+ return;
+
+ list_del(&(x->list));
+
+ list_for_each_entry_safe(p, pq, &(x->pid_filter_list_head), list) {
+ list_del(&(p->list));
+ kfree(p);
+ }
+
+ list_for_each_entry_safe(u, uq, &(x->uid_filter_list_head), list) {
+ list_del(&(u->list));
+ kfree(u);
+ }
+
+ list_for_each_entry_safe(g, gq, &(x->gid_filter_list_head), list) {
+ list_del(&(g->list));
+ kfree(g);
+ }
+
+ kfree(x);
+}
+
+static void fsevent_recv(struct sock *sk, int len)
+{
+ struct sk_buff *skb = NULL;
+ struct nlmsghdr *nlhdr = NULL;
+ struct fsevent_filter * filter = NULL;
+ pid_t pid;
+ int inc_flag = 0;
+
+ if (exit_flag == 1)
+ return;
+
+ while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
+ skb_get(skb);
+ if (skb->len >= FSEVENT_FILTER_MSGSIZE) {
+ nlhdr = (struct nlmsghdr *)skb->data;
+ filter = NLMSG_DATA(nlhdr);
+ pid = NETLINK_CREDS(skb)->pid;
+ if (find_fsevent_listener(pid) == NULL)
+ inc_flag = 1;
+ if (set_fsevent_filter(filter, pid) == 0) {
+ if (inc_flag == 1)
+ atomic_inc(&fsevent_listener_num);
+ }
+
+ }
+ kfree_skb(skb);
+ }
+}
+
+#define DEFINE_FILTER_MATCH_FUNC(filtertype, key) \
+ static int match_##filtertype(listener * p, \
+ struct fsevent * event, \
+ struct sk_buff * skb) \
+ { \
+ int ret = 0; \
+ filtertype * xfilter = NULL; \
+ struct sk_buff * skb2 = NULL; \
+ struct list_head * head = &(p->key##_filter_list_head); \
+ list_for_each_entry(xfilter, head, list) { \
+ if (xfilter->key != event->key) \
+ continue; \
+ ret = filter_fsevent(xfilter->mask, event->type); \
+ if ( ret != 0) \
+ return -1; \
+ skb2 = skb_clone(skb, GFP_KERNEL); \
+ if (skb2 == NULL) \
+ return -1; \
+ NETLINK_CB(skb2).dst_group = 0; \
+ NETLINK_CB(skb2).dst_pid = p->pid; \
+ NETLINK_CB(skb2).pid = 0; \
+ return (netlink_unicast(fsevent_sock, skb2, \
+ p->pid, MSG_DONTWAIT)); \
+ } \
+ return -1; \
+ } \
+
+DEFINE_FILTER_MATCH_FUNC(pid_filter, pid)
+
+DEFINE_FILTER_MATCH_FUNC(uid_filter, uid)
+
+DEFINE_FILTER_MATCH_FUNC(gid_filter, gid)
+
+#define MATCH_XID(key, listenerp, event, skb) \
+ ret = match_##key##_filter(listenerp, event, skb); \
+ if (ret == 0) { \
+ kfree_skb(skb); \
+ continue; \
+ } \
+ do {} while (0) \
+
+static int fsevent_send_to_process(struct sk_buff * skb)
+{
+ listener * p = NULL, * q = NULL;
+ struct fsevent * event = NULL;
+ struct sk_buff * skb2 = NULL;
+ int ret = 0;
+
+ event = (struct fsevent *)(skb->data + sizeof(struct nlmsghdr));
+ mutex_lock(&listener_list_mutex);
+ list_for_each_entry_safe(p, q, &listener_list_head, list) {
+ MATCH_XID(pid, p, event, skb);
+ MATCH_XID(uid, p, event, skb);
+ MATCH_XID(gid, p, event, skb);
+
+ if (filter_fsevent(p->mask, event->type) == 0) {
+ skb2 = skb_clone(skb, GFP_KERNEL);
+ if (skb2 == NULL)
+ return -1;
+ NETLINK_CB(skb2).dst_group = 0;
+ NETLINK_CB(skb2).dst_pid = p->pid;
+ NETLINK_CB(skb2).pid = 0;
+ ret = netlink_unicast(fsevent_sock, skb2,
+ p->pid, 0);
+ if (ret == -ECONNREFUSED) {
+ atomic_dec(&fsevent_listener_num);
+ cleanup_dead_listener(p);
+ }
+ }
+ }
+ mutex_unlock(&listener_list_mutex);
+ return ret;
+}
+
+static void fsevent_commit(void * unused)
+{
+ struct sk_buff * skb = NULL;
+
+ while((skb = skb_dequeue(&get_cpu_var(fsevent_send_queue)))
+ != NULL) {
+ fsevent_send_to_process(skb);
+ kfree_skb(skb);
+ put_cpu_var(fsevent_send_queue);
+ }
+}
+
+static struct ctl_table fsevent_mask_sysctl[] = {
+ {
+ .ctl_name = FSEVENT_MASK_CTL_NAME,
+ .procname = "fsevent_mask",
+ .data = &fsevents_mask,
+ .maxlen = sizeof(u32),
+ .mode = 0644,
+ .proc_handler = &proc_dointvec,
+ },
+ { .ctl_name = 0 }
+};
+
+static struct ctl_table fs_root_sysctl[] = {
+ {
+ .ctl_name = CTL_FS,
+ .procname = "fs",
+ .mode = 0555,
+ .child = fsevent_mask_sysctl,
+ },
+ { .ctl_name = 0 }
+};
+
+static int __init fsevent_init(void)
+{
+ int cpu;
+ struct sk_buff_head * listptr;
+ struct work_struct * workptr;
+
+ fsevent_sock = netlink_kernel_create(NETLINK_FSEVENT, 0,
+ fsevent_recv, THIS_MODULE);
+ if (!fsevent_sock)
+ return -EIO;
+ for_each_cpu(cpu) {
+ listptr = &per_cpu(fsevent_send_queue, cpu);
+ skb_queue_head_init(listptr);
+ workptr = &per_cpu(fsevent_work, cpu);
+ INIT_WORK(workptr, fsevent_commit, NULL);
+ }
+
+ if (register_sysctl_table(fs_root_sysctl, 0) == NULL)
+ return -ENOMEM;
+
+ _raise_fsevent = __raise_fsevent;
+
+ return 0;
+}
+
+static void __exit fsevent_exit(void)
+{
+ listener * p = NULL, * q = NULL;
+ int cpu;
+ int wait_flag = 0;
+ struct sk_buff_head * skb_head = NULL;
+
+ fsevents_mask = 0;
+ _raise_fsevent = 0;
+ exit_flag = 1;
+
+ for_each_cpu(cpu)
+ schedule_work(&per_cpu(fsevent_work, cpu));
+
+ while (1) {
+ wait_flag = 0;
+ for_each_cpu(cpu) {
+ skb_head = &per_cpu(fsevent_send_queue, cpu);
+ if (skb_head->qlen != 0) {
+ wait_flag = 1;
+ break;
+ }
+ }
+ if (wait_flag == 1) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/10);
+ } else
+ break;
+ }
+
+ atomic_set(&fsevent_sock->sk_rmem_alloc, 0);
+ atomic_set(&fsevent_sock->sk_wmem_alloc, 0);
+ sock_release(fsevent_sock->sk_socket);
+ mutex_lock(&listener_list_mutex);
+ list_for_each_entry_safe(p, q, &listener_list_head, list) {
+ cleanup_dead_listener(p);
+ }
+ mutex_unlock(&listener_list_mutex);
+}
+
+module_init(fsevent_init);
+module_exit(fsevent_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yi Yang <yang.y.yi@gmail.com>");
+MODULE_DESCRIPTION("File System Events Reporter");
--- /dev/null 2003-01-30 18:24:37.000000000 +0800
+++ b/fs/fsevent_hook.c 2006-04-08 22:01:30.000000000 +0800
@@ -0,0 +1,5 @@
+#include <linux/fsevent.h>
+
+int (* _raise_fsevent)
+ (const char * oldname, const char * newname, u32 mask) = 0;
+EXPORT_SYMBOL(_raise_fsevent);
^ permalink raw reply
* [ALSA - driver 0001047]: module hangs at seemingly random times
From: bugtrack @ 2006-04-10 14:45 UTC (permalink / raw)
To: alsa-devel
A NOTE has been added to this issue.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1047>
======================================================================
Reported By: alien999999999
Assigned To: mjander
======================================================================
Project: ALSA - driver
Issue ID: 1047
Category: PCI - au88x0
Reproducibility: sometimes
Severity: block
Priority: normal
Status: assigned
Distribution: Mandrake
Kernel Version: 2.6.7
======================================================================
Date Submitted: 04-12-2005 20:43 CEST
Last Modified: 04-10-2006 16:45 CEST
======================================================================
Summary: module hangs at seemingly random times
Description:
sometimes i start playing a song, and it starts playing a few second or so
and hangs, then i kill the application and modprobe -r all sound modules
and modprobe them again to make it work again.
BUT: sometimes not only that happens, but also when i try to kill the apps
it will not kill. when that happens, all kill, killall, top, ps aux
commands hang at the command line and cannot be killed by CTRL-C or
otherwise, i have been able to see that when i stopped my display
managener I did an lsmod and it gave something like this:
snd-pcm-oss 59752 11
snd-mixer-oss 20480 1 snd-pcm-oss
snd-au8810 43760 220
snd-ac97-codec 83408 1 snd-au8810
snd-pcm 108172 112 snd-pcm-oss,snd-au8810,snd-ac97-codec
snd-page-alloc 10384 1 snd-pcm
gameport 3840 1 snd-au8810
snd-mpu401-uart 11904 1 snd-au8810
as you can see the snd-au8810 module seem to have an impossible number of
"dependencies" (i think has to do with the number of unclosed sound-apps
trying to be played; this could be since gaim is programmed to execute an
'aplay %s')
i've had this major crash below only 3 times; and the logs didn't detect
anything specific at the time. the only thing the logs mentioned at that
time was an ntpd sync going on; so the only thing i can think of is that
at a certain moment when a sync is going on, some kind of lock is holding
cause this to happen... the only thing that i can do to fix this is
reset...
it is interesting to note that i also have an snd-emu10k1 as second card,
which never gave problems like this, and i am always able to "modprobe -r
snd-emu10k1" ...
======================================================================
----------------------------------------------------------------------
Raymond - 04-10-06 16:43
----------------------------------------------------------------------
http://www.lkml.org/lkml/2006/4/10/76
I2S (device 4) has not been implemented in au88x0
// ADB pcm.
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
snd_card_free(card);
return err;
}
#ifndef CHIP_AU8820
// ADB SPDIF
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_SPDIF, 1)) < 0) {
snd_card_free(card);
return err;
}
// A3D
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_A3D, NR_A3D)) < 0) {
snd_card_free(card);
return err;
}
#endif
/*
// ADB I2S
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_I2S, 1)) < 0) {
snd_card_free(card);
return err;
}
*/
#ifndef CHIP_AU8810
// WT pcm.
if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_WT, NR_WT)) < 0) {
snd_card_free(card);
return err;
}
#endif
Do we really need the check ?
- if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
+ if ((chip == 0) || (idx < 0) || (idx >= VORTEX_PCM_LAST))
return -ENODEV;
----------------------------------------------------------------------
tiwai - 04-10-06 16:45
----------------------------------------------------------------------
Better than a wrong one.
Issue History
Date Modified Username Field Change
======================================================================
04-12-05 20:43 alien999999999 New Issue
04-12-05 20:43 alien999999999 Distribution => Mandrake
04-12-05 20:43 alien999999999 Kernel Version => 2.6.7
04-12-05 20:48 alien999999999 Note Added: 0004461
04-12-05 20:49 alien999999999 File Added: au88x0.c
04-12-05 20:49 alien999999999 File Added: au88x0.h
04-12-05 20:50 alien999999999 File Added: au88x0_core.c
04-12-05 20:50 alien999999999 File Added: au88x0_mixer.c
04-12-05 20:51 alien999999999 Note Added: 0004462
08-24-05 11:13 Raymond Note Added: 0005928
10-27-05 02:27 Raymond Note Added: 0006564
01-03-06 04:04 Raymond Note Added: 0007397
01-04-06 22:08 alien999999999 Note Added: 0007455
01-05-06 07:21 Raymond Note Added: 0007462
01-05-06 20:32 shurick Issue Monitored: shurick
01-06-06 17:17 alien999999999 Note Added: 0007488
01-06-06 17:33 alien999999999 File Added: alsa-cvs-2006-01-04.patch
01-13-06 13:51 Raymond Note Added: 0007639
01-13-06 18:18 tiwai Note Added: 0007648
01-14-06 04:53 Raymond Note Added: 0007653
01-14-06 05:00 Raymond Note Edited: 0007653
01-17-06 12:27 Raymond Note Added: 0007697
01-18-06 15:51 Raymond Note Added: 0007710
01-18-06 15:52 Raymond File Added: au88x0_codec.patch
01-19-06 13:51 Raymond Note Added: 0007719
02-05-06 05:20 Raymond Note Edited: 0007710
02-05-06 05:28 Raymond Note Added: 0007930
02-13-06 16:38 Raymond Note Deleted: 0006564
02-13-06 16:41 Raymond Note Added: 0008054
03-01-06 07:39 Raymond Note Added: 0008273
03-18-06 12:28 Raymond Note Deleted: 0008273
03-20-06 17:54 Raymond File Added: au88x0_conf.patch
03-21-06 02:02 Raymond Note Added: 0008734
03-21-06 18:01 tiwai Note Added: 0008754
03-22-06 02:05 Raymond File Added: au88x0_mpu401.patch
03-22-06 02:28 Raymond Note Added: 0008779
03-22-06 02:31 Raymond Note Edited: 0008779
03-22-06 02:38 rlrevell Note Added: 0008782
03-22-06 04:00 Raymond Note Added: 0008836
03-22-06 04:09 rlrevell Note Added: 0008839
03-26-06 09:55 Raymond Note Added: 0008967
03-29-06 17:48 Raymond Note Added: 0008995
03-31-06 06:52 Raymond Note Edited: 0008995
04-02-06 07:01 Raymond Note Edited: 0008995
04-10-06 16:07 Raymond Note Added: 0009190
04-10-06 16:39 tiwai Note Added: 0009192
04-10-06 16:43 Raymond Note Added: 0009194
04-10-06 16:45 tiwai Note Added: 0009195
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* Re: + git-klibc-mktemp-fix.patch added to -mm tree
From: H. Peter Anvin @ 2006-04-10 14:45 UTC (permalink / raw)
To: Keith Owens; +Cc: Sam Ravnborg, Herbert Xu, linux-kernel, akpm, mm-commits
In-Reply-To: <14836.1144654413@kao2.melbourne.sgi.com>
Keith Owens wrote:
> "H. Peter Anvin" (on Sat, 08 Apr 2006 13:27:06 -0700) wrote:
>> Either which way; I have a better fix for the bison issue (this all has
>> to do with the fact that make's handling of tools that output more than
>> one file at a time is at the very best insane)
>
> Hit the same problem back in the 2.5 kbuild days, and worked around it
> with some dummy dependency rules. Like this one for bison/yacc.
>
> side_effect(aicasm_gram.tab.h aicasm_gram.tab.c)
>
> which expands to
>
> $(objtree)/aicasm_gram.tab.h: $objtree/aicasm_gram.tab.c
> @/bin/true
>
> That forces make to wait until aicasm_gram.tab.c is built before using
> aicasm_gram.tab.h, and allows the following code to depend on either
> aicasm_gram.tab.h or aicasm_gram.tab.c without any races. The command
> should not get executed, but you still need a command to keep make
> happy.
A better way to do it for something like yacc/bison is to use a pattern
rule. Having two things on the LHS means different things for explicit
and for pattern rules!
-hpa
^ permalink raw reply
* Re: [patch][rfc] quell interactive feeding frenzy
From: Al Boldi @ 2006-04-10 14:43 UTC (permalink / raw)
To: linux-kernel; +Cc: Mike Galbraith, bert hubert
In-Reply-To: <1144607596.7408.34.camel@homer>
bert hubert wrote:
> In general, Linux systems are not maxed out as they will disappoint that
> way (like any system running with id=0).
top - 16:59:23 up 29 min, 0 users, load average: 993.49, 796.33, 496.21
Tasks: 1039 total, 1000 running, 39 sleeping, 0 stopped, 0 zombie
Cpu(s): 47.6% user, 52.4% system, 0.0% nice, 0.0% idle, 0.0% IO-wait
Mem: 125796k total, 123344k used, 2452k free, 64k buffers
Swap: 1020088k total, 9176k used, 1010912k free, 1752k cached
PID PR NI VIRT RES SHR SWAP S %CPU TIME+ Command
3946 28 0 2404 1460 720 944 R 5.8 0:14.78 top
4219 37 0 1580 488 416 1092 R 3.0 0:00.45 ping
4214 37 0 1584 480 408 1104 R 2.8 0:00.46 ping
4196 37 0 1580 480 408 1100 R 2.5 0:00.45 ping
4175 37 0 1584 488 416 1096 R 2.3 0:00.30 ping
3950 37 1 1580 492 416 1088 R 2.0 0:08.77 ping
4136 37 0 1580 488 416 1092 R 2.0 0:00.36 ping
4158 37 0 1584 484 408 1100 R 2.0 0:00.35 ping
4177 37 0 1580 480 408 1100 R 2.0 0:00.27 ping
4180 37 0 1580 484 408 1096 R 2.0 0:00.33 ping
4194 37 0 1580 480 408 1100 R 2.0 0:00.40 ping
4199 37 0 1584 484 408 1100 R 2.0 0:00.47 ping
4189 37 0 1580 488 416 1092 R 1.8 0:00.43 ping
4153 37 0 1584 480 408 1104 R 1.5 0:00.31 ping
4170 37 0 1584 484 408 1100 R 1.5 0:00.30 ping
4191 37 0 1584 492 416 1092 R 1.5 0:00.41 ping
4209 37 0 1584 484 408 1100 R 1.5 0:00.39 ping
4215 37 0 1584 484 408 1100 R 1.5 0:00.39 ping
4221 37 0 1580 492 416 1088 R 1.5 0:00.37 ping
4146 37 0 1580 488 416 1092 R 1.3 0:00.29 ping
4156 37 0 1584 484 408 1100 R 1.3 0:00.32 ping
4166 37 0 1584 488 416 1096 R 1.3 0:00.33 ping
4183 37 0 1580 480 408 1100 R 1.3 0:00.37 ping
4216 37 0 1584 480 408 1104 R 1.3 0:00.39 ping
4229 37 0 1584 484 408 1100 R 1.3 0:00.41 ping
4233 37 0 1584 488 416 1096 R 1.3 0:00.41 ping
4137 37 0 1580 484 408 1096 R 1.0 0:00.33 ping
4141 37 0 1584 484 408 1100 R 1.0 0:00.31 ping
4150 37 0 1580 484 408 1096 R 1.0 0:00.30 ping
4161 37 0 1580 480 408 1100 R 1.0 0:00.29 ping
4172 37 0 1584 484 408 1100 R 1.0 0:00.28 ping
4178 37 0 1580 480 408 1100 R 1.0 0:00.25 ping
4182 37 0 1584 484 408 1100 R 1.0 0:00.23 ping
After that the loadavg starts to wrap.
And even then it is possible to login.
And that's not with the default 2.6 scheduler, but rather w/ spa.
Thanks!
--
Al
^ permalink raw reply
* Re: [ANNOUNCE][RFC] PlugSched-6.3.1 for 2.6.16-rc5
From: Al Boldi @ 2006-04-10 14:43 UTC (permalink / raw)
To: Peter Williams; +Cc: linux-kernel
In-Reply-To: <44399E81.9050908@bigpond.net.au>
Peter Williams wrote:
> Al Boldi wrote:
> > But how does this explain spa_no_frills setting promotion to max not
> > having this problem?
>
> I'm still puzzled by this. The only thing I can think of is that the
> promotion mechanism is to simple in that it just moves all promotable
> tasks up one slot without regard for how long they've been on the queue.
> Doing this was a deliberate decision based on the desire to minimize
> overhead and the belief that it wouldn't matter in the grand scheme of
> things. I may do some experimenting with slightly more sophisticated
> version.
>
> Properly done, promotion should hardly ever occur but the cost would be
> slightly more complex enqueue/dequeue operations. The current version
> will do unnecessary promotions but it was felt this was more than
> compensated for by the lower enqueue/dequeue costs. We'll see how a
> more sophisticated version goes in terms of trade offs.
Would this affect the current, nearly perfect, spa_no_frills rr-behaviour w/
its ability to circumvent the timeslice problem when setting promo to max?
> >> This is one good reason not to use spa_no_frills on
> >> production systems.
> >
> > spa_ebs is great, but rather bursty. Even setting max_ia_bonus=0
> > doesn't fix that. Is there a way to smooth it like spa_no_frills?
>
> The principal determinant would be the smoothness of the yardstick.
> This is supposed to represent the task with the highest (recent) CPU
> usage rate per share and is used to determine how fairly CPU is being
> distributed among the currently active tasks. Tasks are given a
> priority based on how their CPU usage rate per share compares to this
> yardstick. This means that as the system load and/or type of task
> running changes the priorities of the tasks can change dramatically.
>
> Is the burstiness that you're seeing just in the observed priorities or
> is it associated with behavioural burstiness as well?
It's behavioural, exhibited in a choking style, like a jumpy mouse move
during ia boosts.
> >> Perhaps you should consider creating a child
> >> scheduler on top of it that meets your needs?
> >
> > Perhaps.
>
> Good. I've been hoping that other interested parties might be
> encouraged by the small interface to SPA children to try different ideas
> for scheduling.
Is there a no-op child skeleton available?
> One thing that could be played with here is to vary the time slice based
> on the priority. This would be in the opposite direction to the normal
> scheduler with higher priority tasks (i.e. those with lower prio values)
> getting smaller time slices. The rationale being:
>
> 1. stop tasks that have been given large bonuses from shutting out other
> tasks for too long, and
> 2. reduce the context switch rate for tasks that haven't received bonuses.
>
> Because tasks that get large bonuses will have short CPU bursts they
> should not be adversely effected (if this is done properly) as they will
> (except in exceptional circumstances such as a change in behaviour)
> surrender the CPU voluntarily before their reduced time slice has
> expired. Imaginative use of the available statistics could make this
> largely automatic but there would be a need to be aware that the
> statistics can be distorted by the shorter time slices.
>
> On the other hand, giving tasks without bonuses longer time slices
> shouldn't adversely effect interactive performance as the interactive
> tasks will (courtesy of their bonuses) preempt them.
I couldn't agree more. Tackling the problem on both fronts (prio/tslice) may
give us more control, which could result in a more appropriate / fairer /
smoother scheduler.
Thanks!
--
Al
^ permalink raw reply
* [ALSA - driver 0001934]: make problem
From: bugtrack @ 2006-04-10 14:46 UTC (permalink / raw)
To: alsa-devel
A NOTE has been added to this issue.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1934>
======================================================================
Reported By: kvo
Assigned To: perex
======================================================================
Project: ALSA - driver
Issue ID: 1934
Category: 0_compilation problem_!!!
Reproducibility: always
Severity: block
Priority: normal
Status: assigned
Distribution: RHEL4 Update 3
Kernel Version: 2.6.9-34.EL
======================================================================
Date Submitted: 03-17-2006 12:19 CET
Last Modified: 04-10-2006 16:46 CEST
======================================================================
Summary: make problem
Description:
./configure works OK. running make give error during compilation: module
'include/asound.h' (line 210) has some 'typedef' that doesn't match with
(probably) OS include. As a result, compilation stops and driver can not
be produced.
======================================================================
----------------------------------------------------------------------
kvo - 04-09-06 19:05
----------------------------------------------------------------------
Please look at new info and possible reason.
----------------------------------------------------------------------
tiwai - 04-10-06 16:46
----------------------------------------------------------------------
Sigh, it's a modified kernel by RedHat that not supported officially by
alsa package.
I don't know how to detect it.
Issue History
Date Modified Username Field Change
======================================================================
03-17-06 12:19 kvo New Issue
03-17-06 12:19 kvo Distribution => RHEL4 Update 3
03-17-06 12:19 kvo Kernel Version => 2.6.9-34.EL
03-17-06 12:25 tiwai Note Added: 0008643
03-19-06 22:26 kvo Note Added: 0008697
03-21-06 17:33 tiwai Note Added: 0008749
03-25-06 20:47 kvo File Added: config.log
03-25-06 22:19 kvo Note Added: 0008952
04-09-06 18:47 kvo File Added: info.zip
04-09-06 18:56 kvo Note Added: 0009181
04-09-06 19:05 kvo Issue Monitored: tiwai
04-09-06 19:05 kvo Note Added: 0009182
04-10-06 16:46 tiwai Note Added: 0009196
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* [ALSA - driver 0001857]: regression in snd-cs4281 in recent 2.6.16-rcX kernels
From: bugtrack @ 2006-04-10 14:47 UTC (permalink / raw)
To: alsa-devel
The following issue has been RESOLVED.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1857>
======================================================================
Reported By: hoffmajs
Assigned To: tiwai
======================================================================
Project: ALSA - driver
Issue ID: 1857
Category: PCI - cs4281
Reproducibility: always
Severity: major
Priority: normal
Status: resolved
Distribution: Ubuntu (Dapper)
Kernel Version: 2.6.16-rc4
Resolution: fixed
Fixed in Version:
======================================================================
Date Submitted: 02-19-2006 06:11 CET
Last Modified: 04-10-2006 16:47 CEST
======================================================================
Summary: regression in snd-cs4281 in recent 2.6.16-rcX
kernels
Description:
In the recent 2.6.16-rc kernels snd-cs4281 broke for me.
(I think since 2.6.16-rc2, but Im not sure atm. In 2.6.15 the card works
fine.)
# > modprobe snd-cs4281
ACPI: PCI Interrupt 0000:00:08.0[A] -> Link [LNKC] -> GSI 5 (level, low)
-> IRQ 5
never read ISV3 and ISV4 from AC'97
ACPI: PCI interrupt for device 0000:00:08.0 disabled
CS4281: probe of 0000:00:08.0 failed with error -5
and no soundcard is found.
If you need more info or want me to test something, please say so.
kind regards,
Jens
======================================================================
----------------------------------------------------------------------
Mo6eB - 04-09-06 12:29
----------------------------------------------------------------------
2.6.17-rc1 fixed it for me.
----------------------------------------------------------------------
tiwai - 04-10-06 16:47
----------------------------------------------------------------------
OK then let's close.
Issue History
Date Modified Username Field Change
======================================================================
02-19-06 06:11 hoffmajs New Issue
02-19-06 06:11 hoffmajs Distribution => Ubuntu (Dapper)
02-19-06 06:11 hoffmajs Kernel Version => 2.6.16-rc4
03-02-06 16:05 tiwai Note Added: 0008319
04-05-06 10:33 julienbras Note Added: 0009119
04-07-06 13:11 Mo6eB Note Added: 0009138
04-07-06 19:16 tiwai Note Added: 0009142
04-09-06 12:29 Mo6eB Note Added: 0009178
04-10-06 16:47 tiwai Status new => resolved
04-10-06 16:47 tiwai Resolution open => fixed
04-10-06 16:47 tiwai Assigned To => tiwai
04-10-06 16:47 tiwai Note Added: 0009197
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* [ALSA - driver 0002013]: no digital output
From: bugtrack @ 2006-04-10 14:50 UTC (permalink / raw)
To: alsa-devel
A NOTE has been added to this issue.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=2013>
======================================================================
Reported By: SamiH
Assigned To:
======================================================================
Project: ALSA - driver
Issue ID: 2013
Category: PCI - via82xx
Reproducibility: always
Severity: major
Priority: normal
Status: new
Distribution: BLFS
Kernel Version: 2.6.15.4
======================================================================
Date Submitted: 04-09-2006 11:43 CEST
Last Modified: 04-10-2006 16:50 CEST
======================================================================
Summary: no digital output
Description:
Shortly: Digital output doesn't work at all, or I don't know how to use
it.
This has been my problem quite long time now. I have upgraded my kernel
from 2.6.8 to 2.6.15.4 with some steps bitween those versions, and the
problem is still here. I have tried some live-cds with same results as my
stable system.
Analog stereo output works with no problems. If someone did tell me what I
should test on my system so that I could give the results to you.
These aren't broken:
* my external amplifier
* the digital coaxial cable
* speakers etc.
Please tell me at least what to do, what to search for, or something...
======================================================================
----------------------------------------------------------------------
tiwai - 04-10-06 16:50
----------------------------------------------------------------------
You didn't write what did you test...
Issue History
Date Modified Username Field Change
======================================================================
04-09-06 11:43 SamiH New Issue
04-09-06 11:43 SamiH Distribution => BLFS
04-09-06 11:43 SamiH Kernel Version => 2.6.15.4
04-10-06 16:50 tiwai Note Added: 0009198
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
* RE: event priority
From: Tian, Kevin @ 2006-04-10 14:51 UTC (permalink / raw)
To: Tian, Kevin, Keir Fraser; +Cc: xen-devel
>From: Tian,Kevin
>Sent: 2006年4月10日 22:31
>
>Hi, Keir,
> Seems current event priority is simple by
>earlier-alloc-higher-priority style, because event ports are allocated
>incrementally from 1 and event dispatcher uses bit search instruction
>to walk pending events sequentially. Is there any plan (or benefit) to
>add more flexible priority policy, since by current way the priority is
>decided completely by compilation sequence of different drivers?
Sorry, I should say driver init sequence here. :-)
Thanks,
Kevin
^ permalink raw reply
* [ALSA - utils 0001990]: aplay/arecord cannot play/capture A_LAW
From: bugtrack @ 2006-04-10 14:52 UTC (permalink / raw)
To: alsa-devel
A NOTE has been added to this issue.
======================================================================
<https://bugtrack.alsa-project.org/alsa-bug/view.php?id=1990>
======================================================================
Reported By: Raymond
Assigned To:
======================================================================
Project: ALSA - utils
Issue ID: 1990
Category: aplay/arecord
Reproducibility: always
Severity: major
Priority: normal
Status: new
======================================================================
Date Submitted: 04-01-2006 04:26 CEST
Last Modified: 04-10-2006 16:52 CEST
======================================================================
Summary: aplay/arecord cannot play/capture A_LAW
Description:
aplay/arecord can play MU_LAW and the sound card support MU_LAW and A_LAW
arecord -D hw:0,0 -f MU_LAW -t au -c 1 -r 8000 test.au
aplay -D hw:0,0 test.au
Try to use -t raw but the quality of A_LAW is very bad when compare with
MU_LAW
arecord -D hw:0,0 -f A_LAW -t raw -c 1 -r 8000 test.raw
aplay -D hw:0,0 test.raw
======================================================================
----------------------------------------------------------------------
Raymond - 04-08-06 07:47
----------------------------------------------------------------------
cat test.raw > /dev/dsp
or
cat test.raw > /dev/audio
Which of the above will play the sound correctly if test.raw is recorded
by arecord -D hw:0,0 -f A_LAW -t raw -c 1 -r 8000 test.raw ?
----------------------------------------------------------------------
tiwai - 04-10-06 16:52
----------------------------------------------------------------------
The OSS emulation doesn't support alaw format conversion, too. It's the
same behavior as OSS/Free.
Issue History
Date Modified Username Field Change
======================================================================
04-01-06 04:26 Raymond New Issue
04-03-06 07:16 Raymond Note Added: 0009085
04-03-06 07:36 Raymond Note Added: 0009086
04-07-06 19:32 tiwai Note Added: 0009152
04-08-06 07:47 Raymond Note Added: 0009171
04-10-06 16:52 tiwai Note Added: 0009199
======================================================================
-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.