3906 lines
132 KiB
Plaintext
3906 lines
132 KiB
Plaintext
From: Greg Kroah-Hartman <gregkh@suse.de>
|
|
Subject: Linux 2.6.38.3
|
|
Patch-mainline: Linux 2.6.38.3
|
|
|
|
|
|
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
|
|
|
|
diff --git a/Makefile b/Makefile
|
|
index 6c15525..e47e39e 100644
|
|
--- a/Makefile
|
|
+++ b/Makefile
|
|
@@ -1,7 +1,7 @@
|
|
VERSION = 2
|
|
PATCHLEVEL = 6
|
|
SUBLEVEL = 38
|
|
-EXTRAVERSION = .2
|
|
+EXTRAVERSION = .3
|
|
NAME = Flesh-Eating Bats with Fangs
|
|
|
|
# *DOCUMENTATION*
|
|
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
|
|
index 09d31db..aa92696 100644
|
|
--- a/arch/powerpc/kernel/time.c
|
|
+++ b/arch/powerpc/kernel/time.c
|
|
@@ -356,7 +356,7 @@ void account_system_vtime(struct task_struct *tsk)
|
|
}
|
|
get_paca()->user_time_scaled += user_scaled;
|
|
|
|
- if (in_irq() || idle_task(smp_processor_id()) != tsk) {
|
|
+ if (in_interrupt() || idle_task(smp_processor_id()) != tsk) {
|
|
account_system_time(tsk, 0, delta, sys_scaled);
|
|
if (stolen)
|
|
account_steal_time(stolen);
|
|
diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S
|
|
index 8fe2a49..4292df7 100644
|
|
--- a/arch/x86/crypto/aesni-intel_asm.S
|
|
+++ b/arch/x86/crypto/aesni-intel_asm.S
|
|
@@ -1612,6 +1612,7 @@ _zero_cipher_left_encrypt:
|
|
movdqa SHUF_MASK(%rip), %xmm10
|
|
PSHUFB_XMM %xmm10, %xmm0
|
|
|
|
+
|
|
ENCRYPT_SINGLE_BLOCK %xmm0, %xmm1 # Encrypt(K, Yn)
|
|
sub $16, %r11
|
|
add %r13, %r11
|
|
@@ -1634,7 +1635,9 @@ _zero_cipher_left_encrypt:
|
|
# GHASH computation for the last <16 byte block
|
|
sub %r13, %r11
|
|
add $16, %r11
|
|
- PSHUFB_XMM %xmm10, %xmm1
|
|
+
|
|
+ movdqa SHUF_MASK(%rip), %xmm10
|
|
+ PSHUFB_XMM %xmm10, %xmm0
|
|
|
|
# shuffle xmm0 back to output as ciphertext
|
|
|
|
diff --git a/arch/x86/crypto/aesni-intel_glue.c b/arch/x86/crypto/aesni-intel_glue.c
|
|
index e1e60c7..b375b2a 100644
|
|
--- a/arch/x86/crypto/aesni-intel_glue.c
|
|
+++ b/arch/x86/crypto/aesni-intel_glue.c
|
|
@@ -828,9 +828,15 @@ static int rfc4106_init(struct crypto_tfm *tfm)
|
|
struct cryptd_aead *cryptd_tfm;
|
|
struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *)
|
|
PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN);
|
|
+ struct crypto_aead *cryptd_child;
|
|
+ struct aesni_rfc4106_gcm_ctx *child_ctx;
|
|
cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0);
|
|
if (IS_ERR(cryptd_tfm))
|
|
return PTR_ERR(cryptd_tfm);
|
|
+
|
|
+ cryptd_child = cryptd_aead_child(cryptd_tfm);
|
|
+ child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child);
|
|
+ memcpy(child_ctx, ctx, sizeof(*ctx));
|
|
ctx->cryptd_tfm = cryptd_tfm;
|
|
tfm->crt_aead.reqsize = sizeof(struct aead_request)
|
|
+ crypto_aead_reqsize(&cryptd_tfm->base);
|
|
@@ -925,6 +931,9 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
|
|
int ret = 0;
|
|
struct crypto_tfm *tfm = crypto_aead_tfm(parent);
|
|
struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
|
|
+ struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
|
|
+ struct aesni_rfc4106_gcm_ctx *child_ctx =
|
|
+ aesni_rfc4106_gcm_ctx_get(cryptd_child);
|
|
u8 *new_key_mem = NULL;
|
|
|
|
if (key_len < 4) {
|
|
@@ -968,6 +977,7 @@ static int rfc4106_set_key(struct crypto_aead *parent, const u8 *key,
|
|
goto exit;
|
|
}
|
|
ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len);
|
|
+ memcpy(child_ctx, ctx, sizeof(*ctx));
|
|
exit:
|
|
kfree(new_key_mem);
|
|
return ret;
|
|
@@ -999,7 +1009,6 @@ static int rfc4106_encrypt(struct aead_request *req)
|
|
int ret;
|
|
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
|
|
struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
|
|
- struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
|
|
|
|
if (!irq_fpu_usable()) {
|
|
struct aead_request *cryptd_req =
|
|
@@ -1008,6 +1017,7 @@ static int rfc4106_encrypt(struct aead_request *req)
|
|
aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
|
|
return crypto_aead_encrypt(cryptd_req);
|
|
} else {
|
|
+ struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
|
|
kernel_fpu_begin();
|
|
ret = cryptd_child->base.crt_aead.encrypt(req);
|
|
kernel_fpu_end();
|
|
@@ -1020,7 +1030,6 @@ static int rfc4106_decrypt(struct aead_request *req)
|
|
int ret;
|
|
struct crypto_aead *tfm = crypto_aead_reqtfm(req);
|
|
struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
|
|
- struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
|
|
|
|
if (!irq_fpu_usable()) {
|
|
struct aead_request *cryptd_req =
|
|
@@ -1029,6 +1038,7 @@ static int rfc4106_decrypt(struct aead_request *req)
|
|
aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
|
|
return crypto_aead_decrypt(cryptd_req);
|
|
} else {
|
|
+ struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
|
|
kernel_fpu_begin();
|
|
ret = cryptd_child->base.crt_aead.decrypt(req);
|
|
kernel_fpu_end();
|
|
diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c
|
|
index bebabec..151787e 100644
|
|
--- a/arch/x86/kernel/cpu/mtrr/main.c
|
|
+++ b/arch/x86/kernel/cpu/mtrr/main.c
|
|
@@ -292,14 +292,24 @@ set_mtrr(unsigned int reg, unsigned long base, unsigned long size, mtrr_type typ
|
|
|
|
/*
|
|
* HACK!
|
|
- * We use this same function to initialize the mtrrs on boot.
|
|
- * The state of the boot cpu's mtrrs has been saved, and we want
|
|
- * to replicate across all the APs.
|
|
- * If we're doing that @reg is set to something special...
|
|
+ *
|
|
+ * We use this same function to initialize the mtrrs during boot,
|
|
+ * resume, runtime cpu online and on an explicit request to set a
|
|
+ * specific MTRR.
|
|
+ *
|
|
+ * During boot or suspend, the state of the boot cpu's mtrrs has been
|
|
+ * saved, and we want to replicate that across all the cpus that come
|
|
+ * online (either at the end of boot or resume or during a runtime cpu
|
|
+ * online). If we're doing that, @reg is set to something special and on
|
|
+ * this cpu we still do mtrr_if->set_all(). During boot/resume, this
|
|
+ * is unnecessary if at this point we are still on the cpu that started
|
|
+ * the boot/resume sequence. But there is no guarantee that we are still
|
|
+ * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be
|
|
+ * sure that we are in sync with everyone else.
|
|
*/
|
|
if (reg != ~0U)
|
|
mtrr_if->set(reg, base, size, type);
|
|
- else if (!mtrr_aps_delayed_init)
|
|
+ else
|
|
mtrr_if->set_all();
|
|
|
|
/* Wait for the others */
|
|
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
|
|
index 5655c22..2d2673c 100644
|
|
--- a/arch/x86/kernel/head64.c
|
|
+++ b/arch/x86/kernel/head64.c
|
|
@@ -77,6 +77,9 @@ void __init x86_64_start_kernel(char * real_mode_data)
|
|
/* Make NULL pointers segfault */
|
|
zap_identity_mappings();
|
|
|
|
+ /* Cleanup the over mapped high alias */
|
|
+ cleanup_highmap();
|
|
+
|
|
max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
|
|
|
|
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
|
|
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
|
|
index e543fe9..d3cfe26 100644
|
|
--- a/arch/x86/kernel/setup.c
|
|
+++ b/arch/x86/kernel/setup.c
|
|
@@ -297,9 +297,6 @@ static void __init init_gbpages(void)
|
|
static inline void init_gbpages(void)
|
|
{
|
|
}
|
|
-static void __init cleanup_highmap(void)
|
|
-{
|
|
-}
|
|
#endif
|
|
|
|
static void __init reserve_brk(void)
|
|
@@ -925,8 +922,6 @@ void __init setup_arch(char **cmdline_p)
|
|
*/
|
|
reserve_brk();
|
|
|
|
- cleanup_highmap();
|
|
-
|
|
memblock.current_limit = get_max_mapped();
|
|
memblock_x86_fill();
|
|
|
|
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
|
|
index f13ff3a..947f42a 100644
|
|
--- a/arch/x86/mm/init.c
|
|
+++ b/arch/x86/mm/init.c
|
|
@@ -279,6 +279,25 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
|
|
load_cr3(swapper_pg_dir);
|
|
#endif
|
|
|
|
+#ifdef CONFIG_X86_64
|
|
+ if (!after_bootmem && !start) {
|
|
+ pud_t *pud;
|
|
+ pmd_t *pmd;
|
|
+
|
|
+ mmu_cr4_features = read_cr4();
|
|
+
|
|
+ /*
|
|
+ * _brk_end cannot change anymore, but it and _end may be
|
|
+ * located on different 2M pages. cleanup_highmap(), however,
|
|
+ * can only consider _end when it runs, so destroy any
|
|
+ * mappings beyond _brk_end here.
|
|
+ */
|
|
+ pud = pud_offset(pgd_offset_k(_brk_end), _brk_end);
|
|
+ pmd = pmd_offset(pud, _brk_end - 1);
|
|
+ while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1))
|
|
+ pmd_clear(pmd);
|
|
+ }
|
|
+#endif
|
|
__flush_tlb_all();
|
|
|
|
if (!after_bootmem && e820_table_end > e820_table_start)
|
|
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
|
|
index 68f9921..c14a542 100644
|
|
--- a/arch/x86/mm/init_64.c
|
|
+++ b/arch/x86/mm/init_64.c
|
|
@@ -51,7 +51,6 @@
|
|
#include <asm/numa.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/init.h>
|
|
-#include <asm/setup.h>
|
|
|
|
static int __init parse_direct_gbpages_off(char *arg)
|
|
{
|
|
@@ -294,18 +293,18 @@ void __init init_extra_mapping_uc(unsigned long phys, unsigned long size)
|
|
* to the compile time generated pmds. This results in invalid pmds up
|
|
* to the point where we hit the physaddr 0 mapping.
|
|
*
|
|
- * We limit the mappings to the region from _text to _brk_end. _brk_end
|
|
- * is rounded up to the 2MB boundary. This catches the invalid pmds as
|
|
+ * We limit the mappings to the region from _text to _end. _end is
|
|
+ * rounded up to the 2MB boundary. This catches the invalid pmds as
|
|
* well, as they are located before _text:
|
|
*/
|
|
void __init cleanup_highmap(void)
|
|
{
|
|
unsigned long vaddr = __START_KERNEL_map;
|
|
- unsigned long vaddr_end = __START_KERNEL_map + (max_pfn_mapped << PAGE_SHIFT);
|
|
- unsigned long end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1;
|
|
+ unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1;
|
|
pmd_t *pmd = level2_kernel_pgt;
|
|
+ pmd_t *last_pmd = pmd + PTRS_PER_PMD;
|
|
|
|
- for (; vaddr + PMD_SIZE - 1 < vaddr_end; pmd++, vaddr += PMD_SIZE) {
|
|
+ for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
|
|
if (pmd_none(*pmd))
|
|
continue;
|
|
if (vaddr < (unsigned long) _text || vaddr > end)
|
|
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
|
|
index 8524939..c7358dd 100644
|
|
--- a/drivers/acpi/pci_root.c
|
|
+++ b/drivers/acpi/pci_root.c
|
|
@@ -564,7 +564,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
|
/* Indicate support for various _OSC capabilities. */
|
|
if (pci_ext_cfg_avail(root->bus->self))
|
|
flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
|
|
- if (pcie_aspm_enabled())
|
|
+ if (pcie_aspm_support_enabled())
|
|
flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
|
|
OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
|
|
if (pci_msi_enabled())
|
|
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
|
|
index 25ef1a4..b836e11 100644
|
|
--- a/drivers/atm/solos-pci.c
|
|
+++ b/drivers/atm/solos-pci.c
|
|
@@ -165,7 +165,6 @@ static uint32_t fpga_tx(struct solos_card *);
|
|
static irqreturn_t solos_irq(int irq, void *dev_id);
|
|
static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
|
|
static int list_vccs(int vci);
|
|
-static void release_vccs(struct atm_dev *dev);
|
|
static int atm_init(struct solos_card *, struct device *);
|
|
static void atm_remove(struct solos_card *);
|
|
static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
|
|
@@ -384,7 +383,6 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb
|
|
/* Anything but 'Showtime' is down */
|
|
if (strcmp(state_str, "Showtime")) {
|
|
atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
|
|
- release_vccs(card->atmdev[port]);
|
|
dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
|
|
return 0;
|
|
}
|
|
@@ -697,7 +695,7 @@ void solos_bh(unsigned long card_arg)
|
|
size);
|
|
}
|
|
if (atmdebug) {
|
|
- dev_info(&card->dev->dev, "Received: device %d\n", port);
|
|
+ dev_info(&card->dev->dev, "Received: port %d\n", port);
|
|
dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
|
|
size, le16_to_cpu(header->vpi),
|
|
le16_to_cpu(header->vci));
|
|
@@ -830,28 +828,6 @@ static int list_vccs(int vci)
|
|
return num_found;
|
|
}
|
|
|
|
-static void release_vccs(struct atm_dev *dev)
|
|
-{
|
|
- int i;
|
|
-
|
|
- write_lock_irq(&vcc_sklist_lock);
|
|
- for (i = 0; i < VCC_HTABLE_SIZE; i++) {
|
|
- struct hlist_head *head = &vcc_hash[i];
|
|
- struct hlist_node *node, *tmp;
|
|
- struct sock *s;
|
|
- struct atm_vcc *vcc;
|
|
-
|
|
- sk_for_each_safe(s, node, tmp, head) {
|
|
- vcc = atm_sk(s);
|
|
- if (vcc->dev == dev) {
|
|
- vcc_release_async(vcc, -EPIPE);
|
|
- sk_del_node_init(s);
|
|
- }
|
|
- }
|
|
- }
|
|
- write_unlock_irq(&vcc_sklist_lock);
|
|
-}
|
|
-
|
|
|
|
static int popen(struct atm_vcc *vcc)
|
|
{
|
|
@@ -1018,8 +994,15 @@ static uint32_t fpga_tx(struct solos_card *card)
|
|
|
|
/* Clean up and free oldskb now it's gone */
|
|
if (atmdebug) {
|
|
+ struct pkt_hdr *header = (void *)oldskb->data;
|
|
+ int size = le16_to_cpu(header->size);
|
|
+
|
|
+ skb_pull(oldskb, sizeof(*header));
|
|
dev_info(&card->dev->dev, "Transmitted: port %d\n",
|
|
port);
|
|
+ dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
|
|
+ size, le16_to_cpu(header->vpi),
|
|
+ le16_to_cpu(header->vci));
|
|
print_buffer(oldskb);
|
|
}
|
|
|
|
@@ -1262,7 +1245,7 @@ static int atm_init(struct solos_card *card, struct device *parent)
|
|
card->atmdev[i]->ci_range.vci_bits = 16;
|
|
card->atmdev[i]->dev_data = card;
|
|
card->atmdev[i]->phy_data = (void *)(unsigned long)i;
|
|
- atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN);
|
|
+ atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
|
|
|
|
skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
|
|
if (!skb) {
|
|
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
|
|
index 579f749..554bbd9 100644
|
|
--- a/drivers/block/cciss.h
|
|
+++ b/drivers/block/cciss.h
|
|
@@ -222,6 +222,7 @@ static void SA5_submit_command( ctlr_info_t *h, CommandList_struct *c)
|
|
h->ctlr, c->busaddr);
|
|
#endif /* CCISS_DEBUG */
|
|
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
|
|
+ readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
|
|
h->commands_outstanding++;
|
|
if ( h->commands_outstanding > h->max_outstanding)
|
|
h->max_outstanding = h->commands_outstanding;
|
|
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
|
|
index 700a384..f44ca40 100644
|
|
--- a/drivers/bluetooth/btusb.c
|
|
+++ b/drivers/bluetooth/btusb.c
|
|
@@ -71,6 +71,9 @@ static struct usb_device_id btusb_table[] = {
|
|
/* Apple MacBookAir3,1, MacBookAir3,2 */
|
|
{ USB_DEVICE(0x05ac, 0x821b) },
|
|
|
|
+ /* Apple MacBookPro8,2 */
|
|
+ { USB_DEVICE(0x05ac, 0x821a) },
|
|
+
|
|
/* AVM BlueFRITZ! USB v2.0 */
|
|
{ USB_DEVICE(0x057c, 0x3800) },
|
|
|
|
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
|
|
index 1f46f1c..7beb0e2 100644
|
|
--- a/drivers/char/tpm/tpm.c
|
|
+++ b/drivers/char/tpm/tpm.c
|
|
@@ -980,7 +980,7 @@ int tpm_open(struct inode *inode, struct file *file)
|
|
return -EBUSY;
|
|
}
|
|
|
|
- chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
|
|
+ chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
|
|
if (chip->data_buffer == NULL) {
|
|
clear_bit(0, &chip->is_open);
|
|
put_device(chip->dev);
|
|
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
|
|
index 23e0355..7e0e660 100644
|
|
--- a/drivers/edac/amd64_edac.c
|
|
+++ b/drivers/edac/amd64_edac.c
|
|
@@ -2765,7 +2765,7 @@ static int __init amd64_edac_init(void)
|
|
mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
|
|
ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
|
|
if (!(mcis && ecc_stngs))
|
|
- goto err_ret;
|
|
+ goto err_free;
|
|
|
|
msrs = msrs_alloc();
|
|
if (!msrs)
|
|
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
index 02d5c41..99768d9 100644
|
|
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
|
|
@@ -675,7 +675,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|
ATOM_ENCODER_CAP_RECORD *cap_record;
|
|
u16 caps = 0;
|
|
|
|
- while (record->ucRecordType > 0 &&
|
|
+ while (record->ucRecordSize > 0 &&
|
|
+ record->ucRecordType > 0 &&
|
|
record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
|
|
switch (record->ucRecordType) {
|
|
case ATOM_ENCODER_CAP_RECORD_TYPE:
|
|
@@ -720,7 +721,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|
break;
|
|
}
|
|
|
|
- while (record->ucRecordType > 0 &&
|
|
+ while (record->ucRecordSize > 0 &&
|
|
+ record->ucRecordType > 0 &&
|
|
record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
|
|
switch (record->ucRecordType) {
|
|
case ATOM_I2C_RECORD_TYPE:
|
|
@@ -782,10 +784,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev)
|
|
ATOM_HPD_INT_RECORD *hpd_record;
|
|
ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
|
|
|
|
- while (record->ucRecordType > 0
|
|
- && record->
|
|
- ucRecordType <=
|
|
- ATOM_MAX_OBJECT_RECORD_NUMBER) {
|
|
+ while (record->ucRecordSize > 0 &&
|
|
+ record->ucRecordType > 0 &&
|
|
+ record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
|
|
switch (record->ucRecordType) {
|
|
case ATOM_I2C_RECORD_TYPE:
|
|
i2c_record =
|
|
diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
|
|
index 318cc40..418c399 100644
|
|
--- a/drivers/hid/hid-magicmouse.c
|
|
+++ b/drivers/hid/hid-magicmouse.c
|
|
@@ -418,6 +418,8 @@ static void magicmouse_setup_input(struct input_dev *input, struct hid_device *h
|
|
input_set_abs_params(input, ABS_MT_POSITION_Y, -2456,
|
|
2565, 4, 0);
|
|
}
|
|
+
|
|
+ input_set_events_per_packet(input, 60);
|
|
}
|
|
|
|
if (report_undeciphered) {
|
|
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
|
|
index aa186cf..e06e045 100644
|
|
--- a/drivers/input/mouse/synaptics.c
|
|
+++ b/drivers/input/mouse/synaptics.c
|
|
@@ -836,8 +836,8 @@ static const struct dmi_system_id __initconst toshiba_dmi_table[] = {
|
|
},
|
|
|
|
},
|
|
- { }
|
|
#endif
|
|
+ { }
|
|
};
|
|
|
|
static bool broken_olpc_ec;
|
|
@@ -851,8 +851,8 @@ static const struct dmi_system_id __initconst olpc_dmi_table[] = {
|
|
DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
|
|
},
|
|
},
|
|
- { }
|
|
#endif
|
|
+ { }
|
|
};
|
|
|
|
void __init synaptics_module_init(void)
|
|
diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c
|
|
index 80a3ae3..c0cff64 100644
|
|
--- a/drivers/leds/leds-lp5521.c
|
|
+++ b/drivers/leds/leds-lp5521.c
|
|
@@ -534,7 +534,7 @@ static ssize_t lp5521_selftest(struct device *dev,
|
|
}
|
|
|
|
/* led class device attributes */
|
|
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
|
|
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
|
|
static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
|
|
|
|
static struct attribute *lp5521_led_attributes[] = {
|
|
@@ -548,15 +548,15 @@ static struct attribute_group lp5521_led_attribute_group = {
|
|
};
|
|
|
|
/* device attributes */
|
|
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
|
|
show_engine1_mode, store_engine1_mode);
|
|
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
|
|
show_engine2_mode, store_engine2_mode);
|
|
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
|
|
show_engine3_mode, store_engine3_mode);
|
|
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
|
|
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
|
|
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
|
|
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
|
|
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
|
|
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
|
|
static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
|
|
|
|
static struct attribute *lp5521_attributes[] = {
|
|
diff --git a/drivers/leds/leds-lp5523.c b/drivers/leds/leds-lp5523.c
|
|
index d0c4068..e19fed2 100644
|
|
--- a/drivers/leds/leds-lp5523.c
|
|
+++ b/drivers/leds/leds-lp5523.c
|
|
@@ -713,7 +713,7 @@ static ssize_t store_current(struct device *dev,
|
|
}
|
|
|
|
/* led class device attributes */
|
|
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
|
|
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
|
|
static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
|
|
|
|
static struct attribute *lp5523_led_attributes[] = {
|
|
@@ -727,21 +727,21 @@ static struct attribute_group lp5523_led_attribute_group = {
|
|
};
|
|
|
|
/* device attributes */
|
|
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
|
|
show_engine1_mode, store_engine1_mode);
|
|
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
|
|
show_engine2_mode, store_engine2_mode);
|
|
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
|
|
show_engine3_mode, store_engine3_mode);
|
|
-static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUSR,
|
|
show_engine1_leds, store_engine1_leds);
|
|
-static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUSR,
|
|
show_engine2_leds, store_engine2_leds);
|
|
-static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO,
|
|
+static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUSR,
|
|
show_engine3_leds, store_engine3_leds);
|
|
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
|
|
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
|
|
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
|
|
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
|
|
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
|
|
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
|
|
static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL);
|
|
|
|
static struct attribute *lp5523_attributes[] = {
|
|
diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
|
|
index ecdffa6..c090246 100644
|
|
--- a/drivers/media/radio/Kconfig
|
|
+++ b/drivers/media/radio/Kconfig
|
|
@@ -441,6 +441,7 @@ config RADIO_TIMBERDALE
|
|
config RADIO_WL1273
|
|
tristate "Texas Instruments WL1273 I2C FM Radio"
|
|
depends on I2C && VIDEO_V4L2
|
|
+ select MFD_CORE
|
|
select MFD_WL1273_CORE
|
|
select FW_LOADER
|
|
---help---
|
|
diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c
|
|
index df33a1d..a794ae6 100644
|
|
--- a/drivers/media/video/tlg2300/pd-video.c
|
|
+++ b/drivers/media/video/tlg2300/pd-video.c
|
|
@@ -764,10 +764,8 @@ static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix)
|
|
}
|
|
ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
|
|
vid_resol, &cmd_status);
|
|
- if (ret || cmd_status) {
|
|
- mutex_unlock(&pd->lock);
|
|
+ if (ret || cmd_status)
|
|
return -EBUSY;
|
|
- }
|
|
|
|
pix_def->pixelformat = pix->pixelformat; /* save it */
|
|
pix->height = (context->tvnormid & V4L2_STD_525_60) ? 480 : 576;
|
|
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c
|
|
index 4193af5..1707d22 100644
|
|
--- a/drivers/mfd/ab3100-core.c
|
|
+++ b/drivers/mfd/ab3100-core.c
|
|
@@ -613,7 +613,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100)
|
|
ab3100_get_priv.ab3100 = ab3100;
|
|
ab3100_get_priv.mode = false;
|
|
ab3100_get_reg_file = debugfs_create_file("get_reg",
|
|
- S_IWUGO, ab3100_dir, &ab3100_get_priv,
|
|
+ S_IWUSR, ab3100_dir, &ab3100_get_priv,
|
|
&ab3100_get_set_reg_fops);
|
|
if (!ab3100_get_reg_file) {
|
|
err = -ENOMEM;
|
|
@@ -623,7 +623,7 @@ static void ab3100_setup_debugfs(struct ab3100 *ab3100)
|
|
ab3100_set_priv.ab3100 = ab3100;
|
|
ab3100_set_priv.mode = true;
|
|
ab3100_set_reg_file = debugfs_create_file("set_reg",
|
|
- S_IWUGO, ab3100_dir, &ab3100_set_priv,
|
|
+ S_IWUSR, ab3100_dir, &ab3100_set_priv,
|
|
&ab3100_get_set_reg_fops);
|
|
if (!ab3100_set_reg_file) {
|
|
err = -ENOMEM;
|
|
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c
|
|
index 5fbca34..681984d 100644
|
|
--- a/drivers/mfd/ab3550-core.c
|
|
+++ b/drivers/mfd/ab3550-core.c
|
|
@@ -1053,17 +1053,17 @@ static inline void ab3550_setup_debugfs(struct ab3550 *ab)
|
|
goto exit_destroy_dir;
|
|
|
|
ab3550_bank_file = debugfs_create_file("register-bank",
|
|
- (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_bank_fops);
|
|
+ (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_bank_fops);
|
|
if (!ab3550_bank_file)
|
|
goto exit_destroy_reg;
|
|
|
|
ab3550_address_file = debugfs_create_file("register-address",
|
|
- (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_address_fops);
|
|
+ (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_address_fops);
|
|
if (!ab3550_address_file)
|
|
goto exit_destroy_bank;
|
|
|
|
ab3550_val_file = debugfs_create_file("register-value",
|
|
- (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_val_fops);
|
|
+ (S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_val_fops);
|
|
if (!ab3550_val_file)
|
|
goto exit_destroy_address;
|
|
|
|
diff --git a/drivers/mfd/ab8500-debugfs.c b/drivers/mfd/ab8500-debugfs.c
|
|
index 3c1541a..64748e4 100644
|
|
--- a/drivers/mfd/ab8500-debugfs.c
|
|
+++ b/drivers/mfd/ab8500-debugfs.c
|
|
@@ -585,18 +585,18 @@ static int __devinit ab8500_debug_probe(struct platform_device *plf)
|
|
goto exit_destroy_dir;
|
|
|
|
ab8500_bank_file = debugfs_create_file("register-bank",
|
|
- (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops);
|
|
+ (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops);
|
|
if (!ab8500_bank_file)
|
|
goto exit_destroy_reg;
|
|
|
|
ab8500_address_file = debugfs_create_file("register-address",
|
|
- (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev,
|
|
+ (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev,
|
|
&ab8500_address_fops);
|
|
if (!ab8500_address_file)
|
|
goto exit_destroy_bank;
|
|
|
|
ab8500_val_file = debugfs_create_file("register-value",
|
|
- (S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops);
|
|
+ (S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops);
|
|
if (!ab8500_val_file)
|
|
goto exit_destroy_address;
|
|
|
|
diff --git a/drivers/misc/ep93xx_pwm.c b/drivers/misc/ep93xx_pwm.c
|
|
index 46b3439..16d7179 100644
|
|
--- a/drivers/misc/ep93xx_pwm.c
|
|
+++ b/drivers/misc/ep93xx_pwm.c
|
|
@@ -249,11 +249,11 @@ static ssize_t ep93xx_pwm_set_invert(struct device *dev,
|
|
|
|
static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL);
|
|
static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL);
|
|
-static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO,
|
|
+static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO,
|
|
ep93xx_pwm_get_freq, ep93xx_pwm_set_freq);
|
|
-static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO,
|
|
+static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO,
|
|
ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent);
|
|
-static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO,
|
|
+static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO,
|
|
ep93xx_pwm_get_invert, ep93xx_pwm_set_invert);
|
|
|
|
static struct attribute *ep93xx_pwm_attrs[] = {
|
|
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
|
|
index ea5cfe2..24386a8 100644
|
|
--- a/drivers/net/myri10ge/myri10ge.c
|
|
+++ b/drivers/net/myri10ge/myri10ge.c
|
|
@@ -3645,6 +3645,7 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp)
|
|
dma_free_coherent(&pdev->dev, bytes,
|
|
ss->fw_stats, ss->fw_stats_bus);
|
|
ss->fw_stats = NULL;
|
|
+ netif_napi_del(&ss->napi);
|
|
}
|
|
}
|
|
kfree(mgp->ss);
|
|
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
|
|
index 587498e..3de98cb 100644
|
|
--- a/drivers/net/netxen/netxen_nic_ethtool.c
|
|
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
|
|
@@ -901,7 +901,7 @@ static int netxen_nic_set_flags(struct net_device *netdev, u32 data)
|
|
struct netxen_adapter *adapter = netdev_priv(netdev);
|
|
int hw_lro;
|
|
|
|
- if (data & ~ETH_FLAG_LRO)
|
|
+ if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
|
|
return -EINVAL;
|
|
|
|
if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
|
|
diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c
|
|
index 4c14510..45b2755 100644
|
|
--- a/drivers/net/qlcnic/qlcnic_ethtool.c
|
|
+++ b/drivers/net/qlcnic/qlcnic_ethtool.c
|
|
@@ -1003,7 +1003,7 @@ static int qlcnic_set_flags(struct net_device *netdev, u32 data)
|
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
|
int hw_lro;
|
|
|
|
- if (data & ~ETH_FLAG_LRO)
|
|
+ if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
|
|
return -EINVAL;
|
|
|
|
if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
|
|
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
|
|
index 39c17ce..0cdff2b 100644
|
|
--- a/drivers/net/s2io.c
|
|
+++ b/drivers/net/s2io.c
|
|
@@ -6726,7 +6726,7 @@ static int s2io_ethtool_set_flags(struct net_device *dev, u32 data)
|
|
int rc = 0;
|
|
int changed = 0;
|
|
|
|
- if (data & ~ETH_FLAG_LRO)
|
|
+ if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO))
|
|
return -EINVAL;
|
|
|
|
if (data & ETH_FLAG_LRO) {
|
|
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c
|
|
index 81254be..51f2ef1 100644
|
|
--- a/drivers/net/vmxnet3/vmxnet3_ethtool.c
|
|
+++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c
|
|
@@ -304,8 +304,8 @@ vmxnet3_set_flags(struct net_device *netdev, u32 data)
|
|
u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
|
|
unsigned long flags;
|
|
|
|
- if (data & ~ETH_FLAG_LRO)
|
|
- return -EOPNOTSUPP;
|
|
+ if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
|
|
+ return -EINVAL;
|
|
|
|
if (lro_requested ^ lro_present) {
|
|
/* toggle the LRO feature*/
|
|
diff --git a/drivers/net/vxge/vxge-ethtool.c b/drivers/net/vxge/vxge-ethtool.c
|
|
index 1dd3a21..c5eb034 100644
|
|
--- a/drivers/net/vxge/vxge-ethtool.c
|
|
+++ b/drivers/net/vxge/vxge-ethtool.c
|
|
@@ -1117,8 +1117,8 @@ static int vxge_set_flags(struct net_device *dev, u32 data)
|
|
struct vxgedev *vdev = netdev_priv(dev);
|
|
enum vxge_hw_status status;
|
|
|
|
- if (data & ~ETH_FLAG_RXHASH)
|
|
- return -EOPNOTSUPP;
|
|
+ if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH))
|
|
+ return -EINVAL;
|
|
|
|
if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
|
|
return 0;
|
|
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
|
|
index a09d15f..0848e09 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/main.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
|
@@ -1063,6 +1063,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
|
"Starting driver with initial channel: %d MHz\n",
|
|
curchan->center_freq);
|
|
|
|
+ ath9k_ps_wakeup(sc);
|
|
+
|
|
mutex_lock(&sc->mutex);
|
|
|
|
if (ath9k_wiphy_started(sc)) {
|
|
@@ -1179,6 +1181,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
|
|
mutex_unlock:
|
|
mutex_unlock(&sc->mutex);
|
|
|
|
+ ath9k_ps_restore(sc);
|
|
+
|
|
return r;
|
|
}
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
|
|
index 07b7804..5c9d83b 100644
|
|
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
|
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
|
@@ -1699,8 +1699,8 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
|
|
u8 tidno;
|
|
|
|
spin_lock_bh(&txctl->txq->axq_lock);
|
|
-
|
|
- if (ieee80211_is_data_qos(hdr->frame_control) && txctl->an) {
|
|
+ if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
|
|
+ ieee80211_is_data_qos(hdr->frame_control)) {
|
|
tidno = ieee80211_get_qos_ctl(hdr)[0] &
|
|
IEEE80211_QOS_CTL_TID_MASK;
|
|
tid = ATH_AN_2_TID(txctl->an, tidno);
|
|
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
|
|
index 3d5566e..ff0f5ba 100644
|
|
--- a/drivers/net/wireless/b43/dma.c
|
|
+++ b/drivers/net/wireless/b43/dma.c
|
|
@@ -1536,7 +1536,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
|
|
dmaaddr = meta->dmaaddr;
|
|
goto drop_recycle_buffer;
|
|
}
|
|
- if (unlikely(len > ring->rx_buffersize)) {
|
|
+ if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) {
|
|
/* The data did not fit into one descriptor buffer
|
|
* and is split over multiple buffers.
|
|
* This should never happen, as we try to allocate buffers
|
|
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
|
|
index a01c210..e8a80a1 100644
|
|
--- a/drivers/net/wireless/b43/dma.h
|
|
+++ b/drivers/net/wireless/b43/dma.h
|
|
@@ -163,7 +163,7 @@ struct b43_dmadesc_generic {
|
|
/* DMA engine tuning knobs */
|
|
#define B43_TXRING_SLOTS 256
|
|
#define B43_RXRING_SLOTS 64
|
|
-#define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN
|
|
+#define B43_DMA0_RX_BUFFERSIZE (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
|
|
|
|
/* Pointer poison */
|
|
#define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM))
|
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
|
|
index 9e6f313..c0cd307 100644
|
|
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
|
|
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
|
|
@@ -241,7 +241,7 @@ struct iwl_eeprom_enhanced_txpwr {
|
|
|
|
/* 6x00 Specific */
|
|
#define EEPROM_6000_TX_POWER_VERSION (4)
|
|
-#define EEPROM_6000_EEPROM_VERSION (0x434)
|
|
+#define EEPROM_6000_EEPROM_VERSION (0x423)
|
|
|
|
/* 6x50 Specific */
|
|
#define EEPROM_6050_TX_POWER_VERSION (4)
|
|
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
|
|
index 9b344a9..e183587 100644
|
|
--- a/drivers/net/wireless/p54/p54usb.c
|
|
+++ b/drivers/net/wireless/p54/p54usb.c
|
|
@@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
|
|
{USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */
|
|
{USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */
|
|
{USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */
|
|
+ {USB_DEVICE(0x0bf8, 0x1007)}, /* Fujitsu E-5400 USB */
|
|
{USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */
|
|
{USB_DEVICE(0x0db0, 0x6826)}, /* MSI UB54G (MS-6826) */
|
|
{USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */
|
|
@@ -68,6 +69,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
|
|
{USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */
|
|
{USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */
|
|
{USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */
|
|
+ {USB_DEVICE(0x2001, 0x3762)}, /* Conceptronic C54U */
|
|
{USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */
|
|
{USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */
|
|
|
|
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
|
|
index 54917a2..e2a528d 100644
|
|
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
|
|
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
|
|
@@ -2810,10 +2810,7 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
|
|
|
|
rt2800_register_read(rt2x00dev, WPDMA_GLO_CFG, ®);
|
|
rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0);
|
|
- rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0);
|
|
rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0);
|
|
- rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0);
|
|
- rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1);
|
|
rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
|
|
|
|
/* Wait for DMA, ignore error */
|
|
@@ -2823,9 +2820,6 @@ void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev)
|
|
rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 0);
|
|
rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 0);
|
|
rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
|
|
-
|
|
- rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
|
|
- rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
|
|
}
|
|
EXPORT_SYMBOL_GPL(rt2800_disable_radio);
|
|
|
|
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
|
|
index 3b3f1e4..37a38b5 100644
|
|
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
|
|
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
|
|
@@ -475,39 +475,23 @@ static int rt2800pci_enable_radio(struct rt2x00_dev *rt2x00dev)
|
|
|
|
static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
|
|
{
|
|
- u32 reg;
|
|
-
|
|
- rt2800_disable_radio(rt2x00dev);
|
|
-
|
|
- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
|
|
-
|
|
- rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, ®);
|
|
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX0, 1);
|
|
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX1, 1);
|
|
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX2, 1);
|
|
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX3, 1);
|
|
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX4, 1);
|
|
- rt2x00_set_field32(®, WPDMA_RST_IDX_DTX_IDX5, 1);
|
|
- rt2x00_set_field32(®, WPDMA_RST_IDX_DRX_IDX0, 1);
|
|
- rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
|
|
-
|
|
- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
|
|
- rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
|
|
+ if (rt2x00_is_soc(rt2x00dev)) {
|
|
+ rt2800_disable_radio(rt2x00dev);
|
|
+ rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
|
|
+ rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
|
|
+ }
|
|
}
|
|
|
|
static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
|
|
enum dev_state state)
|
|
{
|
|
- /*
|
|
- * Always put the device to sleep (even when we intend to wakeup!)
|
|
- * if the device is booting and wasn't asleep it will return
|
|
- * failure when attempting to wakeup.
|
|
- */
|
|
- rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
|
|
-
|
|
if (state == STATE_AWAKE) {
|
|
- rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
|
|
+ rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
|
|
rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
|
|
+ } else if (state == STATE_SLEEP) {
|
|
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
|
|
+ rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
|
|
+ rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
|
|
}
|
|
|
|
return 0;
|
|
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
|
|
index 9597a03..2b77a29 100644
|
|
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
|
|
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
|
|
@@ -1031,8 +1031,10 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
|
|
* Stop all work.
|
|
*/
|
|
cancel_work_sync(&rt2x00dev->intf_work);
|
|
- cancel_work_sync(&rt2x00dev->rxdone_work);
|
|
- cancel_work_sync(&rt2x00dev->txdone_work);
|
|
+ if (rt2x00_is_usb(rt2x00dev)) {
|
|
+ cancel_work_sync(&rt2x00dev->rxdone_work);
|
|
+ cancel_work_sync(&rt2x00dev->txdone_work);
|
|
+ }
|
|
|
|
/*
|
|
* Free the tx status fifo.
|
|
diff --git a/drivers/net/wireless/wl12xx/testmode.c b/drivers/net/wireless/wl12xx/testmode.c
|
|
index e64403b..6ec06a4 100644
|
|
--- a/drivers/net/wireless/wl12xx/testmode.c
|
|
+++ b/drivers/net/wireless/wl12xx/testmode.c
|
|
@@ -204,7 +204,10 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
|
|
|
|
kfree(wl->nvs);
|
|
|
|
- wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
|
|
+ if (len != sizeof(struct wl1271_nvs_file))
|
|
+ return -EINVAL;
|
|
+
|
|
+ wl->nvs = kzalloc(len, GFP_KERNEL);
|
|
if (!wl->nvs) {
|
|
wl1271_error("could not allocate memory for the nvs file");
|
|
ret = -ENOMEM;
|
|
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
|
|
index 3188cd9..bbdb4fd 100644
|
|
--- a/drivers/pci/pcie/aspm.c
|
|
+++ b/drivers/pci/pcie/aspm.c
|
|
@@ -69,6 +69,7 @@ struct pcie_link_state {
|
|
};
|
|
|
|
static int aspm_disabled, aspm_force, aspm_clear_state;
|
|
+static bool aspm_support_enabled = true;
|
|
static DEFINE_MUTEX(aspm_lock);
|
|
static LIST_HEAD(link_list);
|
|
|
|
@@ -896,6 +897,7 @@ static int __init pcie_aspm_disable(char *str)
|
|
{
|
|
if (!strcmp(str, "off")) {
|
|
aspm_disabled = 1;
|
|
+ aspm_support_enabled = false;
|
|
printk(KERN_INFO "PCIe ASPM is disabled\n");
|
|
} else if (!strcmp(str, "force")) {
|
|
aspm_force = 1;
|
|
@@ -930,3 +932,8 @@ int pcie_aspm_enabled(void)
|
|
}
|
|
EXPORT_SYMBOL(pcie_aspm_enabled);
|
|
|
|
+bool pcie_aspm_support_enabled(void)
|
|
+{
|
|
+ return aspm_support_enabled;
|
|
+}
|
|
+EXPORT_SYMBOL(pcie_aspm_support_enabled);
|
|
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
|
|
index 38b34a7..fa54ba7 100644
|
|
--- a/drivers/platform/x86/acer-wmi.c
|
|
+++ b/drivers/platform/x86/acer-wmi.c
|
|
@@ -222,6 +222,7 @@ struct acer_debug {
|
|
static struct rfkill *wireless_rfkill;
|
|
static struct rfkill *bluetooth_rfkill;
|
|
static struct rfkill *threeg_rfkill;
|
|
+static bool rfkill_inited;
|
|
|
|
/* Each low-level interface must define at least some of the following */
|
|
struct wmi_interface {
|
|
@@ -1161,9 +1162,13 @@ static int acer_rfkill_set(void *data, bool blocked)
|
|
{
|
|
acpi_status status;
|
|
u32 cap = (unsigned long)data;
|
|
- status = set_u32(!blocked, cap);
|
|
- if (ACPI_FAILURE(status))
|
|
- return -ENODEV;
|
|
+
|
|
+ if (rfkill_inited) {
|
|
+ status = set_u32(!blocked, cap);
|
|
+ if (ACPI_FAILURE(status))
|
|
+ return -ENODEV;
|
|
+ }
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -1187,14 +1192,16 @@ static struct rfkill *acer_rfkill_register(struct device *dev,
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
status = get_device_status(&state, cap);
|
|
- if (ACPI_SUCCESS(status))
|
|
- rfkill_init_sw_state(rfkill_dev, !state);
|
|
|
|
err = rfkill_register(rfkill_dev);
|
|
if (err) {
|
|
rfkill_destroy(rfkill_dev);
|
|
return ERR_PTR(err);
|
|
}
|
|
+
|
|
+ if (ACPI_SUCCESS(status))
|
|
+ rfkill_set_sw_state(rfkill_dev, !state);
|
|
+
|
|
return rfkill_dev;
|
|
}
|
|
|
|
@@ -1229,6 +1236,8 @@ static int acer_rfkill_init(struct device *dev)
|
|
}
|
|
}
|
|
|
|
+ rfkill_inited = true;
|
|
+
|
|
schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
|
|
|
|
return 0;
|
|
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
|
|
index 37268e9..afeb546 100644
|
|
--- a/drivers/rtc/rtc-ds1511.c
|
|
+++ b/drivers/rtc/rtc-ds1511.c
|
|
@@ -485,7 +485,7 @@ ds1511_nvram_write(struct file *filp, struct kobject *kobj,
|
|
static struct bin_attribute ds1511_nvram_attr = {
|
|
.attr = {
|
|
.name = "nvram",
|
|
- .mode = S_IRUGO | S_IWUGO,
|
|
+ .mode = S_IRUGO | S_IWUSR,
|
|
},
|
|
.size = DS1511_RAM_MAX,
|
|
.read = ds1511_nvram_read,
|
|
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
|
|
index f905ecb..01543d2 100644
|
|
--- a/drivers/scsi/scsi_transport_iscsi.c
|
|
+++ b/drivers/scsi/scsi_transport_iscsi.c
|
|
@@ -1847,7 +1847,7 @@ store_priv_session_##field(struct device *dev, \
|
|
#define iscsi_priv_session_rw_attr(field, format) \
|
|
iscsi_priv_session_attr_show(field, format) \
|
|
iscsi_priv_session_attr_store(field) \
|
|
-static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUGO, \
|
|
+static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \
|
|
show_priv_session_##field, \
|
|
store_priv_session_##field)
|
|
iscsi_priv_session_rw_attr(recovery_tmo, "%d");
|
|
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
|
|
index 7f5a6a8..3b00e90 100644
|
|
--- a/drivers/scsi/ses.c
|
|
+++ b/drivers/scsi/ses.c
|
|
@@ -390,9 +390,9 @@ static void ses_enclosure_data_process(struct enclosure_device *edev,
|
|
len = (desc_ptr[2] << 8) + desc_ptr[3];
|
|
/* skip past overall descriptor */
|
|
desc_ptr += len + 4;
|
|
- if (ses_dev->page10)
|
|
- addl_desc_ptr = ses_dev->page10 + 8;
|
|
}
|
|
+ if (ses_dev->page10)
|
|
+ addl_desc_ptr = ses_dev->page10 + 8;
|
|
type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
|
|
components = 0;
|
|
for (i = 0; i < types; i++, type_ptr += 4) {
|
|
diff --git a/drivers/staging/hv/channel.c b/drivers/staging/hv/channel.c
|
|
index 45a627d..09e596a 100644
|
|
--- a/drivers/staging/hv/channel.c
|
|
+++ b/drivers/staging/hv/channel.c
|
|
@@ -76,14 +76,14 @@ static void vmbus_setevent(struct vmbus_channel *channel)
|
|
|
|
if (channel->offermsg.monitor_allocated) {
|
|
/* Each u32 represents 32 channels */
|
|
- set_bit(channel->offermsg.child_relid & 31,
|
|
+ sync_set_bit(channel->offermsg.child_relid & 31,
|
|
(unsigned long *) gVmbusConnection.SendInterruptPage +
|
|
(channel->offermsg.child_relid >> 5));
|
|
|
|
monitorpage = gVmbusConnection.MonitorPages;
|
|
monitorpage++; /* Get the child to parent monitor page */
|
|
|
|
- set_bit(channel->monitor_bit,
|
|
+ sync_set_bit(channel->monitor_bit,
|
|
(unsigned long *)&monitorpage->trigger_group
|
|
[channel->monitor_grp].pending);
|
|
|
|
@@ -99,7 +99,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)
|
|
|
|
if (Channel->offermsg.monitor_allocated) {
|
|
/* Each u32 represents 32 channels */
|
|
- clear_bit(Channel->offermsg.child_relid & 31,
|
|
+ sync_clear_bit(Channel->offermsg.child_relid & 31,
|
|
(unsigned long *)gVmbusConnection.SendInterruptPage +
|
|
(Channel->offermsg.child_relid >> 5));
|
|
|
|
@@ -107,7 +107,7 @@ static void VmbusChannelClearEvent(struct vmbus_channel *channel)
|
|
(struct hv_monitor_page *)gVmbusConnection.MonitorPages;
|
|
monitorPage++; /* Get the child to parent monitor page */
|
|
|
|
- clear_bit(Channel->monitor_bit,
|
|
+ sync_clear_bit(Channel->monitor_bit,
|
|
(unsigned long *)&monitorPage->trigger_group
|
|
[Channel->monitor_grp].Pending);
|
|
}
|
|
diff --git a/drivers/staging/hv/connection.c b/drivers/staging/hv/connection.c
|
|
index c2e298f..0739eb7 100644
|
|
--- a/drivers/staging/hv/connection.c
|
|
+++ b/drivers/staging/hv/connection.c
|
|
@@ -281,7 +281,7 @@ void VmbusOnEvents(void)
|
|
for (dword = 0; dword < maxdword; dword++) {
|
|
if (recvInterruptPage[dword]) {
|
|
for (bit = 0; bit < 32; bit++) {
|
|
- if (test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) {
|
|
+ if (sync_test_and_clear_bit(bit, (unsigned long *)&recvInterruptPage[dword])) {
|
|
relid = (dword << 5) + bit;
|
|
DPRINT_DBG(VMBUS, "event detected for relid - %d", relid);
|
|
|
|
@@ -320,7 +320,7 @@ int VmbusPostMessage(void *buffer, size_t bufferLen)
|
|
int VmbusSetEvent(u32 childRelId)
|
|
{
|
|
/* Each u32 represents 32 channels */
|
|
- set_bit(childRelId & 31,
|
|
+ sync_set_bit(childRelId & 31,
|
|
(unsigned long *)gVmbusConnection.SendInterruptPage +
|
|
(childRelId >> 5));
|
|
|
|
diff --git a/drivers/staging/hv/netvsc_drv.c b/drivers/staging/hv/netvsc_drv.c
|
|
index b41c964..f433add 100644
|
|
--- a/drivers/staging/hv/netvsc_drv.c
|
|
+++ b/drivers/staging/hv/netvsc_drv.c
|
|
@@ -46,6 +46,7 @@ struct net_device_context {
|
|
/* point back to our device context */
|
|
struct vm_device *device_ctx;
|
|
unsigned long avail;
|
|
+ struct work_struct work;
|
|
};
|
|
|
|
struct netvsc_driver_context {
|
|
@@ -225,6 +226,7 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
|
unsigned int status)
|
|
{
|
|
struct vm_device *device_ctx = to_vm_device(device_obj);
|
|
+ struct net_device_context *ndev_ctx;
|
|
struct net_device *net = dev_get_drvdata(&device_ctx->device);
|
|
|
|
if (!net) {
|
|
@@ -237,6 +239,8 @@ static void netvsc_linkstatus_callback(struct hv_device *device_obj,
|
|
netif_carrier_on(net);
|
|
netif_wake_queue(net);
|
|
netif_notify_peers(net);
|
|
+ ndev_ctx = netdev_priv(net);
|
|
+ schedule_work(&ndev_ctx->work);
|
|
} else {
|
|
netif_carrier_off(net);
|
|
netif_stop_queue(net);
|
|
@@ -336,6 +340,25 @@ static const struct net_device_ops device_ops = {
|
|
.ndo_set_mac_address = eth_mac_addr,
|
|
};
|
|
|
|
+/*
|
|
+ * Send GARP packet to network peers after migrations.
|
|
+ * After Quick Migration, the network is not immediately operational in the
|
|
+ * current context when receiving RNDIS_STATUS_MEDIA_CONNECT event. So, add
|
|
+ * another netif_notify_peers() into a scheduled work, otherwise GARP packet
|
|
+ * will not be sent after quick migration, and cause network disconnection.
|
|
+ */
|
|
+static void netvsc_send_garp(struct work_struct *w)
|
|
+{
|
|
+ struct net_device_context *ndev_ctx;
|
|
+ struct net_device *net;
|
|
+
|
|
+ msleep(20);
|
|
+ ndev_ctx = container_of(w, struct net_device_context, work);
|
|
+ net = dev_get_drvdata(&ndev_ctx->device_ctx->device);
|
|
+ netif_notify_peers(net);
|
|
+}
|
|
+
|
|
+
|
|
static int netvsc_probe(struct device *device)
|
|
{
|
|
struct driver_context *driver_ctx =
|
|
@@ -364,6 +387,7 @@ static int netvsc_probe(struct device *device)
|
|
net_device_ctx->device_ctx = device_ctx;
|
|
net_device_ctx->avail = ring_size;
|
|
dev_set_drvdata(device, net);
|
|
+ INIT_WORK(&net_device_ctx->work, netvsc_send_garp);
|
|
|
|
/* Notify the netvsc driver of the new device */
|
|
ret = net_drv_obj->base.OnDeviceAdd(device_obj, &device_info);
|
|
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
|
|
index 84fdb64..87e6cf2 100644
|
|
--- a/drivers/staging/hv/vmbus_drv.c
|
|
+++ b/drivers/staging/hv/vmbus_drv.c
|
|
@@ -291,7 +291,7 @@ static int vmbus_on_isr(struct hv_driver *drv)
|
|
event = (union hv_synic_event_flags *)page_addr + VMBUS_MESSAGE_SINT;
|
|
|
|
/* Since we are a child, we only need to check bit 0 */
|
|
- if (test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
|
|
+ if (sync_test_and_clear_bit(0, (unsigned long *) &event->flags32[0])) {
|
|
DPRINT_DBG(VMBUS, "received event %d", event->flags32[0]);
|
|
ret |= 0x2;
|
|
}
|
|
diff --git a/drivers/staging/hv/vmbus_private.h b/drivers/staging/hv/vmbus_private.h
|
|
index 07f6d22..c75b2d7 100644
|
|
--- a/drivers/staging/hv/vmbus_private.h
|
|
+++ b/drivers/staging/hv/vmbus_private.h
|
|
@@ -31,6 +31,7 @@
|
|
#include "channel_mgmt.h"
|
|
#include "ring_buffer.h"
|
|
#include <linux/list.h>
|
|
+#include <asm/sync_bitops.h>
|
|
|
|
|
|
/*
|
|
diff --git a/drivers/staging/iio/imu/adis16400.h b/drivers/staging/iio/imu/adis16400.h
|
|
index 6ff33e1..90e90f0 100644
|
|
--- a/drivers/staging/iio/imu/adis16400.h
|
|
+++ b/drivers/staging/iio/imu/adis16400.h
|
|
@@ -17,7 +17,8 @@
|
|
#ifndef SPI_ADIS16400_H_
|
|
#define SPI_ADIS16400_H_
|
|
|
|
-#define ADIS16400_STARTUP_DELAY 220 /* ms */
|
|
+#define ADIS16400_STARTUP_DELAY 290 /* ms */
|
|
+#define ADIS16400_MTEST_DELAY 90 /* ms */
|
|
|
|
#define ADIS16400_READ_REG(a) a
|
|
#define ADIS16400_WRITE_REG(a) ((a) | 0x80)
|
|
diff --git a/drivers/staging/iio/imu/adis16400_core.c b/drivers/staging/iio/imu/adis16400_core.c
|
|
index cfb108a..2107edb 100644
|
|
--- a/drivers/staging/iio/imu/adis16400_core.c
|
|
+++ b/drivers/staging/iio/imu/adis16400_core.c
|
|
@@ -93,7 +93,6 @@ static int adis16400_spi_write_reg_16(struct device *dev,
|
|
.tx_buf = st->tx + 2,
|
|
.bits_per_word = 8,
|
|
.len = 2,
|
|
- .cs_change = 1,
|
|
},
|
|
};
|
|
|
|
@@ -137,7 +136,6 @@ static int adis16400_spi_read_reg_16(struct device *dev,
|
|
.rx_buf = st->rx,
|
|
.bits_per_word = 8,
|
|
.len = 2,
|
|
- .cs_change = 1,
|
|
},
|
|
};
|
|
|
|
@@ -375,7 +373,7 @@ static int adis16400_self_test(struct device *dev)
|
|
dev_err(dev, "problem starting self test");
|
|
goto err_ret;
|
|
}
|
|
-
|
|
+ msleep(ADIS16400_MTEST_DELAY);
|
|
adis16400_check_status(dev);
|
|
|
|
err_ret:
|
|
@@ -497,12 +495,12 @@ err_ret:
|
|
_reg)
|
|
|
|
static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_X, ADIS16400_XGYRO_OFF);
|
|
-static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Y, ADIS16400_XGYRO_OFF);
|
|
-static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Z, ADIS16400_XGYRO_OFF);
|
|
+static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Y, ADIS16400_YGYRO_OFF);
|
|
+static ADIS16400_DEV_ATTR_CALIBBIAS(GYRO_Z, ADIS16400_ZGYRO_OFF);
|
|
|
|
static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_X, ADIS16400_XACCL_OFF);
|
|
-static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Y, ADIS16400_XACCL_OFF);
|
|
-static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Z, ADIS16400_XACCL_OFF);
|
|
+static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Y, ADIS16400_YACCL_OFF);
|
|
+static ADIS16400_DEV_ATTR_CALIBBIAS(ACCEL_Z, ADIS16400_ZACCL_OFF);
|
|
|
|
|
|
static IIO_DEV_ATTR_IN_NAMED_RAW(0, supply, adis16400_read_14bit_signed,
|
|
diff --git a/drivers/staging/iio/imu/adis16400_ring.c b/drivers/staging/iio/imu/adis16400_ring.c
|
|
index 33293fb..da28cb4 100644
|
|
--- a/drivers/staging/iio/imu/adis16400_ring.c
|
|
+++ b/drivers/staging/iio/imu/adis16400_ring.c
|
|
@@ -122,12 +122,10 @@ static int adis16400_spi_read_burst(struct device *dev, u8 *rx)
|
|
.tx_buf = st->tx,
|
|
.bits_per_word = 8,
|
|
.len = 2,
|
|
- .cs_change = 0,
|
|
}, {
|
|
.rx_buf = rx,
|
|
.bits_per_word = 8,
|
|
.len = 24,
|
|
- .cs_change = 1,
|
|
},
|
|
};
|
|
|
|
@@ -162,9 +160,10 @@ static void adis16400_trigger_bh_to_ring(struct work_struct *work_s)
|
|
work_trigger_to_ring);
|
|
struct iio_ring_buffer *ring = st->indio_dev->ring;
|
|
|
|
- int i = 0;
|
|
+ int i = 0, j;
|
|
s16 *data;
|
|
size_t datasize = ring->access.get_bytes_per_datum(ring);
|
|
+ unsigned long mask = ring->scan_mask;
|
|
|
|
data = kmalloc(datasize , GFP_KERNEL);
|
|
if (data == NULL) {
|
|
@@ -174,9 +173,12 @@ static void adis16400_trigger_bh_to_ring(struct work_struct *work_s)
|
|
|
|
if (ring->scan_count)
|
|
if (adis16400_spi_read_burst(&st->indio_dev->dev, st->rx) >= 0)
|
|
- for (; i < ring->scan_count; i++)
|
|
+ for (; i < ring->scan_count; i++) {
|
|
+ j = __ffs(mask);
|
|
+ mask &= ~(1 << j);
|
|
data[i] = be16_to_cpup(
|
|
- (__be16 *)&(st->rx[i*2]));
|
|
+ (__be16 *)&(st->rx[j*2]));
|
|
+ }
|
|
|
|
/* Guaranteed to be aligned with 8 byte boundary */
|
|
if (ring->scan_timestamp)
|
|
diff --git a/drivers/staging/usbip/stub_rx.c b/drivers/staging/usbip/stub_rx.c
|
|
index ae6ac82..8e60332 100644
|
|
--- a/drivers/staging/usbip/stub_rx.c
|
|
+++ b/drivers/staging/usbip/stub_rx.c
|
|
@@ -170,33 +170,23 @@ static int tweak_set_configuration_cmd(struct urb *urb)
|
|
|
|
static int tweak_reset_device_cmd(struct urb *urb)
|
|
{
|
|
- struct usb_ctrlrequest *req;
|
|
- __u16 value;
|
|
- __u16 index;
|
|
- int ret;
|
|
-
|
|
- req = (struct usb_ctrlrequest *) urb->setup_packet;
|
|
- value = le16_to_cpu(req->wValue);
|
|
- index = le16_to_cpu(req->wIndex);
|
|
-
|
|
- usbip_uinfo("reset_device (port %d) to %s\n", index,
|
|
- dev_name(&urb->dev->dev));
|
|
+ struct stub_priv *priv = (struct stub_priv *) urb->context;
|
|
+ struct stub_device *sdev = priv->sdev;
|
|
|
|
- /* all interfaces should be owned by usbip driver, so just reset it. */
|
|
- ret = usb_lock_device_for_reset(urb->dev, NULL);
|
|
- if (ret < 0) {
|
|
- dev_err(&urb->dev->dev, "lock for reset\n");
|
|
- return ret;
|
|
- }
|
|
-
|
|
- /* try to reset the device */
|
|
- ret = usb_reset_device(urb->dev);
|
|
- if (ret < 0)
|
|
- dev_err(&urb->dev->dev, "device reset\n");
|
|
+ usbip_uinfo("reset_device %s\n", dev_name(&urb->dev->dev));
|
|
|
|
- usb_unlock_device(urb->dev);
|
|
-
|
|
- return ret;
|
|
+ /*
|
|
+ * usb_lock_device_for_reset caused a deadlock: it causes the driver
|
|
+ * to unbind. In the shutdown the rx thread is signalled to shut down
|
|
+ * but this thread is pending in the usb_lock_device_for_reset.
|
|
+ *
|
|
+ * Instead queue the reset.
|
|
+ *
|
|
+ * Unfortunatly an existing usbip connection will be dropped due to
|
|
+ * driver unbinding.
|
|
+ */
|
|
+ usb_queue_reset_device(sdev->interface);
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
diff --git a/drivers/staging/usbip/stub_tx.c b/drivers/staging/usbip/stub_tx.c
|
|
index d7136e2..b7a493c 100644
|
|
--- a/drivers/staging/usbip/stub_tx.c
|
|
+++ b/drivers/staging/usbip/stub_tx.c
|
|
@@ -169,7 +169,6 @@ static int stub_send_ret_submit(struct stub_device *sdev)
|
|
struct stub_priv *priv, *tmp;
|
|
|
|
struct msghdr msg;
|
|
- struct kvec iov[3];
|
|
size_t txsize;
|
|
|
|
size_t total_size = 0;
|
|
@@ -179,28 +178,73 @@ static int stub_send_ret_submit(struct stub_device *sdev)
|
|
struct urb *urb = priv->urb;
|
|
struct usbip_header pdu_header;
|
|
void *iso_buffer = NULL;
|
|
+ struct kvec *iov = NULL;
|
|
+ int iovnum = 0;
|
|
|
|
txsize = 0;
|
|
memset(&pdu_header, 0, sizeof(pdu_header));
|
|
memset(&msg, 0, sizeof(msg));
|
|
- memset(&iov, 0, sizeof(iov));
|
|
|
|
- usbip_dbg_stub_tx("setup txdata urb %p\n", urb);
|
|
+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
|
|
+ iovnum = 2 + urb->number_of_packets;
|
|
+ else
|
|
+ iovnum = 2;
|
|
+
|
|
+ iov = kzalloc(iovnum * sizeof(struct kvec), GFP_KERNEL);
|
|
|
|
+ if (!iov) {
|
|
+ usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_MALLOC);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ iovnum = 0;
|
|
|
|
/* 1. setup usbip_header */
|
|
setup_ret_submit_pdu(&pdu_header, urb);
|
|
+ usbip_dbg_stub_tx("setup txdata seqnum: %d urb: %p\n",
|
|
+ pdu_header.base.seqnum, urb);
|
|
+ /*usbip_dump_header(pdu_header);*/
|
|
usbip_header_correct_endian(&pdu_header, 1);
|
|
|
|
- iov[0].iov_base = &pdu_header;
|
|
- iov[0].iov_len = sizeof(pdu_header);
|
|
+ iov[iovnum].iov_base = &pdu_header;
|
|
+ iov[iovnum].iov_len = sizeof(pdu_header);
|
|
+ iovnum++;
|
|
txsize += sizeof(pdu_header);
|
|
|
|
/* 2. setup transfer buffer */
|
|
- if (usb_pipein(urb->pipe) && urb->actual_length > 0) {
|
|
- iov[1].iov_base = urb->transfer_buffer;
|
|
- iov[1].iov_len = urb->actual_length;
|
|
+ if (usb_pipein(urb->pipe) &&
|
|
+ usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS &&
|
|
+ urb->actual_length > 0) {
|
|
+ iov[iovnum].iov_base = urb->transfer_buffer;
|
|
+ iov[iovnum].iov_len = urb->actual_length;
|
|
+ iovnum++;
|
|
txsize += urb->actual_length;
|
|
+ } else if (usb_pipein(urb->pipe) &&
|
|
+ usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
|
|
+ /*
|
|
+ * For isochronous packets: actual length is the sum of
|
|
+ * the actual length of the individual, packets, but as
|
|
+ * the packet offsets are not changed there will be
|
|
+ * padding between the packets. To optimally use the
|
|
+ * bandwidth the padding is not transmitted.
|
|
+ */
|
|
+
|
|
+ int i;
|
|
+ for (i = 0; i < urb->number_of_packets; i++) {
|
|
+ iov[iovnum].iov_base = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
|
|
+ iov[iovnum].iov_len = urb->iso_frame_desc[i].actual_length;
|
|
+ iovnum++;
|
|
+ txsize += urb->iso_frame_desc[i].actual_length;
|
|
+ }
|
|
+
|
|
+ if (txsize != sizeof(pdu_header) + urb->actual_length) {
|
|
+ dev_err(&sdev->interface->dev,
|
|
+ "actual length of urb (%d) does not match iso packet sizes (%d)\n",
|
|
+ urb->actual_length, txsize-sizeof(pdu_header));
|
|
+ kfree(iov);
|
|
+ usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
|
|
+ return -1;
|
|
+ }
|
|
}
|
|
|
|
/* 3. setup iso_packet_descriptor */
|
|
@@ -211,32 +255,34 @@ static int stub_send_ret_submit(struct stub_device *sdev)
|
|
if (!iso_buffer) {
|
|
usbip_event_add(&sdev->ud,
|
|
SDEV_EVENT_ERROR_MALLOC);
|
|
+ kfree(iov);
|
|
return -1;
|
|
}
|
|
|
|
- iov[2].iov_base = iso_buffer;
|
|
- iov[2].iov_len = len;
|
|
+ iov[iovnum].iov_base = iso_buffer;
|
|
+ iov[iovnum].iov_len = len;
|
|
txsize += len;
|
|
+ iovnum++;
|
|
}
|
|
|
|
- ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg, iov,
|
|
- 3, txsize);
|
|
+ ret = kernel_sendmsg(sdev->ud.tcp_socket, &msg,
|
|
+ iov, iovnum, txsize);
|
|
if (ret != txsize) {
|
|
dev_err(&sdev->interface->dev,
|
|
"sendmsg failed!, retval %d for %zd\n",
|
|
ret, txsize);
|
|
+ kfree(iov);
|
|
kfree(iso_buffer);
|
|
usbip_event_add(&sdev->ud, SDEV_EVENT_ERROR_TCP);
|
|
return -1;
|
|
}
|
|
|
|
+ kfree(iov);
|
|
kfree(iso_buffer);
|
|
- usbip_dbg_stub_tx("send txdata\n");
|
|
|
|
total_size += txsize;
|
|
}
|
|
|
|
-
|
|
spin_lock_irqsave(&sdev->priv_lock, flags);
|
|
|
|
list_for_each_entry_safe(priv, tmp, &sdev->priv_free, list) {
|
|
diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
|
|
index 210ef16..2108ca1 100644
|
|
--- a/drivers/staging/usbip/usbip_common.c
|
|
+++ b/drivers/staging/usbip/usbip_common.c
|
|
@@ -334,10 +334,11 @@ void usbip_dump_header(struct usbip_header *pdu)
|
|
usbip_udbg("CMD_UNLINK: seq %u\n", pdu->u.cmd_unlink.seqnum);
|
|
break;
|
|
case USBIP_RET_SUBMIT:
|
|
- usbip_udbg("RET_SUBMIT: st %d al %u sf %d ec %d\n",
|
|
+ usbip_udbg("RET_SUBMIT: st %d al %u sf %d #p %d ec %d\n",
|
|
pdu->u.ret_submit.status,
|
|
pdu->u.ret_submit.actual_length,
|
|
pdu->u.ret_submit.start_frame,
|
|
+ pdu->u.ret_submit.number_of_packets,
|
|
pdu->u.ret_submit.error_count);
|
|
case USBIP_RET_UNLINK:
|
|
usbip_udbg("RET_UNLINK: status %d\n", pdu->u.ret_unlink.status);
|
|
@@ -625,6 +626,7 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
|
|
rpdu->status = urb->status;
|
|
rpdu->actual_length = urb->actual_length;
|
|
rpdu->start_frame = urb->start_frame;
|
|
+ rpdu->number_of_packets = urb->number_of_packets;
|
|
rpdu->error_count = urb->error_count;
|
|
} else {
|
|
/* vhci_rx.c */
|
|
@@ -632,6 +634,7 @@ static void usbip_pack_ret_submit(struct usbip_header *pdu, struct urb *urb,
|
|
urb->status = rpdu->status;
|
|
urb->actual_length = rpdu->actual_length;
|
|
urb->start_frame = rpdu->start_frame;
|
|
+ urb->number_of_packets = rpdu->number_of_packets;
|
|
urb->error_count = rpdu->error_count;
|
|
}
|
|
}
|
|
@@ -700,11 +703,13 @@ static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu,
|
|
cpu_to_be32s(&pdu->status);
|
|
cpu_to_be32s(&pdu->actual_length);
|
|
cpu_to_be32s(&pdu->start_frame);
|
|
+ cpu_to_be32s(&pdu->number_of_packets);
|
|
cpu_to_be32s(&pdu->error_count);
|
|
} else {
|
|
be32_to_cpus(&pdu->status);
|
|
be32_to_cpus(&pdu->actual_length);
|
|
be32_to_cpus(&pdu->start_frame);
|
|
+ cpu_to_be32s(&pdu->number_of_packets);
|
|
be32_to_cpus(&pdu->error_count);
|
|
}
|
|
}
|
|
@@ -830,6 +835,7 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
|
|
int size = np * sizeof(*iso);
|
|
int i;
|
|
int ret;
|
|
+ int total_length = 0;
|
|
|
|
if (!usb_pipeisoc(urb->pipe))
|
|
return 0;
|
|
@@ -859,19 +865,75 @@ int usbip_recv_iso(struct usbip_device *ud, struct urb *urb)
|
|
return -EPIPE;
|
|
}
|
|
|
|
+
|
|
for (i = 0; i < np; i++) {
|
|
iso = buff + (i * sizeof(*iso));
|
|
|
|
usbip_iso_pakcet_correct_endian(iso, 0);
|
|
usbip_pack_iso(iso, &urb->iso_frame_desc[i], 0);
|
|
+ total_length += urb->iso_frame_desc[i].actual_length;
|
|
}
|
|
|
|
kfree(buff);
|
|
|
|
+ if (total_length != urb->actual_length) {
|
|
+ dev_err(&urb->dev->dev,
|
|
+ "total length of iso packets (%d) not equal to actual length of buffer (%d)\n",
|
|
+ total_length, urb->actual_length);
|
|
+
|
|
+ if (ud->side == USBIP_STUB)
|
|
+ usbip_event_add(ud, SDEV_EVENT_ERROR_TCP);
|
|
+ else
|
|
+ usbip_event_add(ud, VDEV_EVENT_ERROR_TCP);
|
|
+
|
|
+ return -EPIPE;
|
|
+ }
|
|
+
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL_GPL(usbip_recv_iso);
|
|
|
|
+/*
|
|
+ * This functions restores the padding which was removed for optimizing
|
|
+ * the bandwidth during transfer over tcp/ip
|
|
+ *
|
|
+ * buffer and iso packets need to be stored and be in propeper endian in urb
|
|
+ * before calling this function
|
|
+ */
|
|
+int usbip_pad_iso(struct usbip_device *ud, struct urb *urb)
|
|
+{
|
|
+ int np = urb->number_of_packets;
|
|
+ int i;
|
|
+ int ret;
|
|
+ int actualoffset = urb->actual_length;
|
|
+
|
|
+ if (!usb_pipeisoc(urb->pipe))
|
|
+ return 0;
|
|
+
|
|
+ /* if no packets or length of data is 0, then nothing to unpack */
|
|
+ if (np == 0 || urb->actual_length == 0)
|
|
+ return 0;
|
|
+
|
|
+ /*
|
|
+ * if actual_length is transfer_buffer_length then no padding is
|
|
+ * present.
|
|
+ */
|
|
+ if (urb->actual_length == urb->transfer_buffer_length)
|
|
+ return 0;
|
|
+
|
|
+ /*
|
|
+ * loop over all packets from last to first (to prevent overwritting
|
|
+ * memory when padding) and move them into the proper place
|
|
+ */
|
|
+ for (i = np-1; i > 0; i--) {
|
|
+ actualoffset -= urb->iso_frame_desc[i].actual_length;
|
|
+ memmove(urb->transfer_buffer + urb->iso_frame_desc[i].offset,
|
|
+ urb->transfer_buffer + actualoffset,
|
|
+ urb->iso_frame_desc[i].actual_length);
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(usbip_pad_iso);
|
|
|
|
/* some members of urb must be substituted before. */
|
|
int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
|
|
diff --git a/drivers/staging/usbip/usbip_common.h b/drivers/staging/usbip/usbip_common.h
|
|
index d280e23..baa4c09 100644
|
|
--- a/drivers/staging/usbip/usbip_common.h
|
|
+++ b/drivers/staging/usbip/usbip_common.h
|
|
@@ -393,6 +393,8 @@ void usbip_header_correct_endian(struct usbip_header *pdu, int send);
|
|
int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb);
|
|
/* some members of urb must be substituted before. */
|
|
int usbip_recv_iso(struct usbip_device *ud, struct urb *urb);
|
|
+/* some members of urb must be substituted before. */
|
|
+int usbip_pad_iso(struct usbip_device *ud, struct urb *urb);
|
|
void *usbip_alloc_iso_desc_pdu(struct urb *urb, ssize_t *bufflen);
|
|
|
|
|
|
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c
|
|
index bf69914..109002a 100644
|
|
--- a/drivers/staging/usbip/vhci_rx.c
|
|
+++ b/drivers/staging/usbip/vhci_rx.c
|
|
@@ -99,6 +99,9 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
|
|
if (usbip_recv_iso(ud, urb) < 0)
|
|
return;
|
|
|
|
+ /* restore the padding in iso packets */
|
|
+ if (usbip_pad_iso(ud, urb) < 0)
|
|
+ return;
|
|
|
|
if (usbip_dbg_flag_vhci_rx)
|
|
usbip_dump_urb(urb);
|
|
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c
|
|
index 596ba60..51b5551 100644
|
|
--- a/drivers/watchdog/davinci_wdt.c
|
|
+++ b/drivers/watchdog/davinci_wdt.c
|
|
@@ -202,7 +202,6 @@ static struct miscdevice davinci_wdt_miscdev = {
|
|
static int __devinit davinci_wdt_probe(struct platform_device *pdev)
|
|
{
|
|
int ret = 0, size;
|
|
- struct resource *res;
|
|
struct device *dev = &pdev->dev;
|
|
|
|
wdt_clk = clk_get(dev, NULL);
|
|
@@ -216,31 +215,31 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev)
|
|
|
|
dev_info(dev, "heartbeat %d sec\n", heartbeat);
|
|
|
|
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
- if (res == NULL) {
|
|
+ wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ if (wdt_mem == NULL) {
|
|
dev_err(dev, "failed to get memory region resource\n");
|
|
return -ENOENT;
|
|
}
|
|
|
|
- size = resource_size(res);
|
|
- wdt_mem = request_mem_region(res->start, size, pdev->name);
|
|
-
|
|
- if (wdt_mem == NULL) {
|
|
+ size = resource_size(wdt_mem);
|
|
+ if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
|
|
dev_err(dev, "failed to get memory region\n");
|
|
return -ENOENT;
|
|
}
|
|
|
|
- wdt_base = ioremap(res->start, size);
|
|
+ wdt_base = ioremap(wdt_mem->start, size);
|
|
if (!wdt_base) {
|
|
dev_err(dev, "failed to map memory region\n");
|
|
+ release_mem_region(wdt_mem->start, size);
|
|
+ wdt_mem = NULL;
|
|
return -ENOMEM;
|
|
}
|
|
|
|
ret = misc_register(&davinci_wdt_miscdev);
|
|
if (ret < 0) {
|
|
dev_err(dev, "cannot register misc device\n");
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, size);
|
|
+ wdt_mem = NULL;
|
|
} else {
|
|
set_bit(WDT_DEVICE_INITED, &wdt_status);
|
|
}
|
|
@@ -253,8 +252,7 @@ static int __devexit davinci_wdt_remove(struct platform_device *pdev)
|
|
{
|
|
misc_deregister(&davinci_wdt_miscdev);
|
|
if (wdt_mem) {
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, resource_size(wdt_mem));
|
|
wdt_mem = NULL;
|
|
}
|
|
|
|
diff --git a/drivers/watchdog/max63xx_wdt.c b/drivers/watchdog/max63xx_wdt.c
|
|
index 3053ff0..1fe9bc5 100644
|
|
--- a/drivers/watchdog/max63xx_wdt.c
|
|
+++ b/drivers/watchdog/max63xx_wdt.c
|
|
@@ -270,7 +270,6 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
|
|
{
|
|
int ret = 0;
|
|
int size;
|
|
- struct resource *res;
|
|
struct device *dev = &pdev->dev;
|
|
struct max63xx_timeout *table;
|
|
|
|
@@ -294,21 +293,19 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
|
|
|
|
max63xx_pdev = pdev;
|
|
|
|
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
- if (res == NULL) {
|
|
+ wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ if (wdt_mem == NULL) {
|
|
dev_err(dev, "failed to get memory region resource\n");
|
|
return -ENOENT;
|
|
}
|
|
|
|
- size = resource_size(res);
|
|
- wdt_mem = request_mem_region(res->start, size, pdev->name);
|
|
-
|
|
- if (wdt_mem == NULL) {
|
|
+ size = resource_size(wdt_mem);
|
|
+ if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
|
|
dev_err(dev, "failed to get memory region\n");
|
|
return -ENOENT;
|
|
}
|
|
|
|
- wdt_base = ioremap(res->start, size);
|
|
+ wdt_base = ioremap(wdt_mem->start, size);
|
|
if (!wdt_base) {
|
|
dev_err(dev, "failed to map memory region\n");
|
|
ret = -ENOMEM;
|
|
@@ -326,8 +323,8 @@ static int __devinit max63xx_wdt_probe(struct platform_device *pdev)
|
|
out_unmap:
|
|
iounmap(wdt_base);
|
|
out_request:
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, size);
|
|
+ wdt_mem = NULL;
|
|
|
|
return ret;
|
|
}
|
|
@@ -336,8 +333,7 @@ static int __devexit max63xx_wdt_remove(struct platform_device *pdev)
|
|
{
|
|
misc_deregister(&max63xx_wdt_miscdev);
|
|
if (wdt_mem) {
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, resource_size(wdt_mem));
|
|
wdt_mem = NULL;
|
|
}
|
|
|
|
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c
|
|
index bf5b97c..8c8c7d5 100644
|
|
--- a/drivers/watchdog/pnx4008_wdt.c
|
|
+++ b/drivers/watchdog/pnx4008_wdt.c
|
|
@@ -254,7 +254,6 @@ static struct miscdevice pnx4008_wdt_miscdev = {
|
|
static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
|
|
{
|
|
int ret = 0, size;
|
|
- struct resource *res;
|
|
|
|
if (heartbeat < 1 || heartbeat > MAX_HEARTBEAT)
|
|
heartbeat = DEFAULT_HEARTBEAT;
|
|
@@ -262,42 +261,42 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev)
|
|
printk(KERN_INFO MODULE_NAME
|
|
"PNX4008 Watchdog Timer: heartbeat %d sec\n", heartbeat);
|
|
|
|
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
- if (res == NULL) {
|
|
+ wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ if (wdt_mem == NULL) {
|
|
printk(KERN_INFO MODULE_NAME
|
|
"failed to get memory region resouce\n");
|
|
return -ENOENT;
|
|
}
|
|
|
|
- size = resource_size(res);
|
|
- wdt_mem = request_mem_region(res->start, size, pdev->name);
|
|
+ size = resource_size(wdt_mem);
|
|
|
|
- if (wdt_mem == NULL) {
|
|
+ if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
|
|
printk(KERN_INFO MODULE_NAME "failed to get memory region\n");
|
|
return -ENOENT;
|
|
}
|
|
- wdt_base = (void __iomem *)IO_ADDRESS(res->start);
|
|
+ wdt_base = (void __iomem *)IO_ADDRESS(wdt_mem->start);
|
|
|
|
wdt_clk = clk_get(&pdev->dev, NULL);
|
|
if (IS_ERR(wdt_clk)) {
|
|
ret = PTR_ERR(wdt_clk);
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, size);
|
|
+ wdt_mem = NULL;
|
|
goto out;
|
|
}
|
|
|
|
ret = clk_enable(wdt_clk);
|
|
if (ret) {
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, size);
|
|
+ wdt_mem = NULL;
|
|
+ clk_put(wdt_clk);
|
|
goto out;
|
|
}
|
|
|
|
ret = misc_register(&pnx4008_wdt_miscdev);
|
|
if (ret < 0) {
|
|
printk(KERN_ERR MODULE_NAME "cannot register misc device\n");
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, size);
|
|
+ wdt_mem = NULL;
|
|
clk_disable(wdt_clk);
|
|
clk_put(wdt_clk);
|
|
} else {
|
|
@@ -320,8 +319,7 @@ static int __devexit pnx4008_wdt_remove(struct platform_device *pdev)
|
|
clk_put(wdt_clk);
|
|
|
|
if (wdt_mem) {
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, resource_size(wdt_mem));
|
|
wdt_mem = NULL;
|
|
}
|
|
return 0;
|
|
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
|
|
index ae53662..8303c57 100644
|
|
--- a/drivers/watchdog/s3c2410_wdt.c
|
|
+++ b/drivers/watchdog/s3c2410_wdt.c
|
|
@@ -402,7 +402,6 @@ static inline void s3c2410wdt_cpufreq_deregister(void)
|
|
|
|
static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
|
|
{
|
|
- struct resource *res;
|
|
struct device *dev;
|
|
unsigned int wtcon;
|
|
int started = 0;
|
|
@@ -416,20 +415,19 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
|
|
|
|
/* get the memory region for the watchdog timer */
|
|
|
|
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
- if (res == NULL) {
|
|
+ wdt_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
+ if (wdt_mem == NULL) {
|
|
dev_err(dev, "no memory resource specified\n");
|
|
return -ENOENT;
|
|
}
|
|
|
|
- size = resource_size(res);
|
|
- wdt_mem = request_mem_region(res->start, size, pdev->name);
|
|
- if (wdt_mem == NULL) {
|
|
+ size = resource_size(wdt_mem);
|
|
+ if (!request_mem_region(wdt_mem->start, size, pdev->name)) {
|
|
dev_err(dev, "failed to get memory region\n");
|
|
return -EBUSY;
|
|
}
|
|
|
|
- wdt_base = ioremap(res->start, size);
|
|
+ wdt_base = ioremap(wdt_mem->start, size);
|
|
if (wdt_base == NULL) {
|
|
dev_err(dev, "failed to ioremap() region\n");
|
|
ret = -EINVAL;
|
|
@@ -524,8 +522,8 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev)
|
|
iounmap(wdt_base);
|
|
|
|
err_req:
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, size);
|
|
+ wdt_mem = NULL;
|
|
|
|
return ret;
|
|
}
|
|
@@ -545,8 +543,7 @@ static int __devexit s3c2410wdt_remove(struct platform_device *dev)
|
|
|
|
iounmap(wdt_base);
|
|
|
|
- release_resource(wdt_mem);
|
|
- kfree(wdt_mem);
|
|
+ release_mem_region(wdt_mem->start, resource_size(wdt_mem));
|
|
wdt_mem = NULL;
|
|
return 0;
|
|
}
|
|
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c
|
|
index 8083728..c7ea4be 100644
|
|
--- a/drivers/watchdog/sp5100_tco.c
|
|
+++ b/drivers/watchdog/sp5100_tco.c
|
|
@@ -42,6 +42,7 @@
|
|
#define PFX TCO_MODULE_NAME ": "
|
|
|
|
/* internal variables */
|
|
+static u32 tcobase_phys;
|
|
static void __iomem *tcobase;
|
|
static unsigned int pm_iobase;
|
|
static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */
|
|
@@ -305,10 +306,18 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
|
|
/* Low three bits of BASE0 are reserved. */
|
|
val = val << 8 | (inb(SP5100_IO_PM_DATA_REG) & 0xf8);
|
|
|
|
+ if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
|
|
+ "SP5100 TCO")) {
|
|
+ printk(KERN_ERR PFX "mmio address 0x%04x already in use\n",
|
|
+ val);
|
|
+ goto unreg_region;
|
|
+ }
|
|
+ tcobase_phys = val;
|
|
+
|
|
tcobase = ioremap(val, SP5100_WDT_MEM_MAP_SIZE);
|
|
if (tcobase == 0) {
|
|
printk(KERN_ERR PFX "failed to get tcobase address\n");
|
|
- goto unreg_region;
|
|
+ goto unreg_mem_region;
|
|
}
|
|
|
|
/* Enable watchdog decode bit */
|
|
@@ -346,7 +355,8 @@ static unsigned char __devinit sp5100_tco_setupdevice(void)
|
|
/* Done */
|
|
return 1;
|
|
|
|
- iounmap(tcobase);
|
|
+unreg_mem_region:
|
|
+ release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
|
|
unreg_region:
|
|
release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
|
|
exit:
|
|
@@ -401,6 +411,7 @@ static int __devinit sp5100_tco_init(struct platform_device *dev)
|
|
|
|
exit:
|
|
iounmap(tcobase);
|
|
+ release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
|
|
release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
|
|
return ret;
|
|
}
|
|
@@ -414,6 +425,7 @@ static void __devexit sp5100_tco_cleanup(void)
|
|
/* Deregister */
|
|
misc_deregister(&sp5100_tco_miscdev);
|
|
iounmap(tcobase);
|
|
+ release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
|
|
release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
|
|
}
|
|
|
|
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
|
|
index 7f78cc7..bd64b41 100644
|
|
--- a/fs/btrfs/ctree.h
|
|
+++ b/fs/btrfs/ctree.h
|
|
@@ -1284,6 +1284,8 @@ struct btrfs_root {
|
|
#define BTRFS_INODE_NOATIME (1 << 9)
|
|
#define BTRFS_INODE_DIRSYNC (1 << 10)
|
|
|
|
+#define BTRFS_INODE_ROOT_ITEM_INIT (1 << 31)
|
|
+
|
|
/* some macros to generate set/get funcs for the struct fields. This
|
|
* assumes there is a lefoo_to_cpu for every type, so lets make a simple
|
|
* one for u8:
|
|
@@ -2355,6 +2357,8 @@ int btrfs_find_dead_roots(struct btrfs_root *root, u64 objectid);
|
|
int btrfs_find_orphan_roots(struct btrfs_root *tree_root);
|
|
int btrfs_set_root_node(struct btrfs_root_item *item,
|
|
struct extent_buffer *node);
|
|
+void btrfs_check_and_init_root_item(struct btrfs_root_item *item);
|
|
+
|
|
/* dir-item.c */
|
|
int btrfs_insert_dir_item(struct btrfs_trans_handle *trans,
|
|
struct btrfs_root *root, const char *name,
|
|
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
|
|
index e1aa8d6..edd9efa 100644
|
|
--- a/fs/btrfs/disk-io.c
|
|
+++ b/fs/btrfs/disk-io.c
|
|
@@ -1184,8 +1184,10 @@ struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
|
|
root->commit_root = btrfs_root_node(root);
|
|
BUG_ON(!root->node);
|
|
out:
|
|
- if (location->objectid != BTRFS_TREE_LOG_OBJECTID)
|
|
+ if (location->objectid != BTRFS_TREE_LOG_OBJECTID) {
|
|
root->ref_cows = 1;
|
|
+ btrfs_check_and_init_root_item(&root->root_item);
|
|
+ }
|
|
|
|
return root;
|
|
}
|
|
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
|
|
index 5fdb2ab..2ff51e6 100644
|
|
--- a/fs/btrfs/ioctl.c
|
|
+++ b/fs/btrfs/ioctl.c
|
|
@@ -294,6 +294,10 @@ static noinline int create_subvol(struct btrfs_root *root,
|
|
inode_item->nbytes = cpu_to_le64(root->leafsize);
|
|
inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
|
|
|
|
+ root_item.flags = 0;
|
|
+ root_item.byte_limit = 0;
|
|
+ inode_item->flags = cpu_to_le64(BTRFS_INODE_ROOT_ITEM_INIT);
|
|
+
|
|
btrfs_set_root_bytenr(&root_item, leaf->start);
|
|
btrfs_set_root_generation(&root_item, trans->transid);
|
|
btrfs_set_root_level(&root_item, 0);
|
|
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
|
|
index 6a1086e..3e45c32 100644
|
|
--- a/fs/btrfs/root-tree.c
|
|
+++ b/fs/btrfs/root-tree.c
|
|
@@ -471,3 +471,21 @@ again:
|
|
btrfs_free_path(path);
|
|
return 0;
|
|
}
|
|
+
|
|
+/*
|
|
+ * Old btrfs forgets to init root_item->flags and root_item->byte_limit
|
|
+ * for subvolumes. To work around this problem, we steal a bit from
|
|
+ * root_item->inode_item->flags, and use it to indicate if those fields
|
|
+ * have been properly initialized.
|
|
+ */
|
|
+void btrfs_check_and_init_root_item(struct btrfs_root_item *root_item)
|
|
+{
|
|
+ u64 inode_flags = le64_to_cpu(root_item->inode.flags);
|
|
+
|
|
+ if (!(inode_flags & BTRFS_INODE_ROOT_ITEM_INIT)) {
|
|
+ inode_flags |= BTRFS_INODE_ROOT_ITEM_INIT;
|
|
+ root_item->inode.flags = cpu_to_le64(inode_flags);
|
|
+ root_item->flags = 0;
|
|
+ root_item->byte_limit = 0;
|
|
+ }
|
|
+}
|
|
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
|
|
index 3d73c8d..f3d6681 100644
|
|
--- a/fs/btrfs/transaction.c
|
|
+++ b/fs/btrfs/transaction.c
|
|
@@ -970,6 +970,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
|
record_root_in_trans(trans, root);
|
|
btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
|
|
memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
|
|
+ btrfs_check_and_init_root_item(new_root_item);
|
|
|
|
root_flags = btrfs_root_flags(new_root_item);
|
|
if (pending->readonly)
|
|
diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
|
|
index c1436cf..4feb78c 100644
|
|
--- a/fs/ecryptfs/keystore.c
|
|
+++ b/fs/ecryptfs/keystore.c
|
|
@@ -1563,6 +1563,7 @@ int ecryptfs_keyring_auth_tok_for_sig(struct key **auth_tok_key,
|
|
printk(KERN_ERR "Could not find key with description: [%s]\n",
|
|
sig);
|
|
rc = process_request_key_err(PTR_ERR(*auth_tok_key));
|
|
+ (*auth_tok_key) = NULL;
|
|
goto out;
|
|
}
|
|
(*auth_tok) = ecryptfs_get_key_payload_data(*auth_tok_key);
|
|
diff --git a/fs/ecryptfs/mmap.c b/fs/ecryptfs/mmap.c
|
|
index cc64fca..eb9d967 100644
|
|
--- a/fs/ecryptfs/mmap.c
|
|
+++ b/fs/ecryptfs/mmap.c
|
|
@@ -374,6 +374,11 @@ static int ecryptfs_write_begin(struct file *file,
|
|
&& (pos != 0))
|
|
zero_user(page, 0, PAGE_CACHE_SIZE);
|
|
out:
|
|
+ if (unlikely(rc)) {
|
|
+ unlock_page(page);
|
|
+ page_cache_release(page);
|
|
+ *pagep = NULL;
|
|
+ }
|
|
return rc;
|
|
}
|
|
|
|
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
|
|
index 9f7f9e4..fee51db 100644
|
|
--- a/fs/ext4/inode.c
|
|
+++ b/fs/ext4/inode.c
|
|
@@ -5460,13 +5460,12 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
|
|
/* if nrblocks are contiguous */
|
|
if (chunk) {
|
|
/*
|
|
- * With N contiguous data blocks, it need at most
|
|
- * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks
|
|
- * 2 dindirect blocks
|
|
- * 1 tindirect block
|
|
+ * With N contiguous data blocks, we need at most
|
|
+ * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks,
|
|
+ * 2 dindirect blocks, and 1 tindirect block
|
|
*/
|
|
- indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb);
|
|
- return indirects + 3;
|
|
+ return DIV_ROUND_UP(nrblocks,
|
|
+ EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4;
|
|
}
|
|
/*
|
|
* if nrblocks are not contiguous, worse case, each block touch
|
|
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
|
index 4381efe..243deb0 100644
|
|
--- a/fs/ext4/super.c
|
|
+++ b/fs/ext4/super.c
|
|
@@ -2978,6 +2978,12 @@ static int ext4_register_li_request(struct super_block *sb,
|
|
mutex_unlock(&ext4_li_info->li_list_mtx);
|
|
|
|
sbi->s_li_request = elr;
|
|
+ /*
|
|
+ * set elr to NULL here since it has been inserted to
|
|
+ * the request_list and the removal and free of it is
|
|
+ * handled by ext4_clear_request_list from now on.
|
|
+ */
|
|
+ elr = NULL;
|
|
|
|
if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) {
|
|
ret = ext4_run_lazyinit_thread();
|
|
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
|
|
index 0c6d816..7c831a2 100644
|
|
--- a/fs/nfsd/lockd.c
|
|
+++ b/fs/nfsd/lockd.c
|
|
@@ -38,7 +38,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
|
|
exp_readlock();
|
|
nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
|
|
fh_put(&fh);
|
|
- rqstp->rq_client = NULL;
|
|
exp_readunlock();
|
|
/* We return nlm error codes as nlm doesn't know
|
|
* about nfsd, but nfsd does know about nlm..
|
|
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
|
|
index f0e448a..96aaaa4 100644
|
|
--- a/fs/nfsd/nfs4state.c
|
|
+++ b/fs/nfsd/nfs4state.c
|
|
@@ -397,10 +397,13 @@ static void unhash_generic_stateid(struct nfs4_stateid *stp)
|
|
|
|
static void free_generic_stateid(struct nfs4_stateid *stp)
|
|
{
|
|
- int oflag = nfs4_access_bmap_to_omode(stp);
|
|
+ int oflag;
|
|
|
|
- nfs4_file_put_access(stp->st_file, oflag);
|
|
- put_nfs4_file(stp->st_file);
|
|
+ if (stp->st_access_bmap) {
|
|
+ oflag = nfs4_access_bmap_to_omode(stp);
|
|
+ nfs4_file_put_access(stp->st_file, oflag);
|
|
+ put_nfs4_file(stp->st_file);
|
|
+ }
|
|
kmem_cache_free(stateid_slab, stp);
|
|
}
|
|
|
|
diff --git a/fs/nilfs2/file.c b/fs/nilfs2/file.c
|
|
index 2f560c9..f49e628 100644
|
|
--- a/fs/nilfs2/file.c
|
|
+++ b/fs/nilfs2/file.c
|
|
@@ -72,10 +72,9 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|
/*
|
|
* check to see if the page is mapped already (no holes)
|
|
*/
|
|
- if (PageMappedToDisk(page)) {
|
|
- unlock_page(page);
|
|
+ if (PageMappedToDisk(page))
|
|
goto mapped;
|
|
- }
|
|
+
|
|
if (page_has_buffers(page)) {
|
|
struct buffer_head *bh, *head;
|
|
int fully_mapped = 1;
|
|
@@ -90,7 +89,6 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|
|
|
if (fully_mapped) {
|
|
SetPageMappedToDisk(page);
|
|
- unlock_page(page);
|
|
goto mapped;
|
|
}
|
|
}
|
|
@@ -105,16 +103,17 @@ static int nilfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
|
|
return VM_FAULT_SIGBUS;
|
|
|
|
ret = block_page_mkwrite(vma, vmf, nilfs_get_block);
|
|
- if (unlikely(ret)) {
|
|
+ if (ret != VM_FAULT_LOCKED) {
|
|
nilfs_transaction_abort(inode->i_sb);
|
|
return ret;
|
|
}
|
|
+ nilfs_set_file_dirty(inode, 1 << (PAGE_SHIFT - inode->i_blkbits));
|
|
nilfs_transaction_commit(inode->i_sb);
|
|
|
|
mapped:
|
|
SetPageChecked(page);
|
|
wait_on_page_writeback(page);
|
|
- return 0;
|
|
+ return VM_FAULT_LOCKED;
|
|
}
|
|
|
|
static const struct vm_operations_struct nilfs_file_vm_ops = {
|
|
diff --git a/fs/notify/inotify/inotify_fsnotify.c b/fs/notify/inotify/inotify_fsnotify.c
|
|
index a91b69a..0348d0c 100644
|
|
--- a/fs/notify/inotify/inotify_fsnotify.c
|
|
+++ b/fs/notify/inotify/inotify_fsnotify.c
|
|
@@ -198,6 +198,7 @@ static void inotify_free_group_priv(struct fsnotify_group *group)
|
|
idr_for_each(&group->inotify_data.idr, idr_callback, group);
|
|
idr_remove_all(&group->inotify_data.idr);
|
|
idr_destroy(&group->inotify_data.idr);
|
|
+ atomic_dec(&group->inotify_data.user->inotify_devs);
|
|
free_uid(group->inotify_data.user);
|
|
}
|
|
|
|
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
|
|
index 4cd5d5d..aec9b4a 100644
|
|
--- a/fs/notify/inotify/inotify_user.c
|
|
+++ b/fs/notify/inotify/inotify_user.c
|
|
@@ -290,7 +290,6 @@ static int inotify_fasync(int fd, struct file *file, int on)
|
|
static int inotify_release(struct inode *ignored, struct file *file)
|
|
{
|
|
struct fsnotify_group *group = file->private_data;
|
|
- struct user_struct *user = group->inotify_data.user;
|
|
|
|
pr_debug("%s: group=%p\n", __func__, group);
|
|
|
|
@@ -299,8 +298,6 @@ static int inotify_release(struct inode *ignored, struct file *file)
|
|
/* free this group, matching get was inotify_init->fsnotify_obtain_group */
|
|
fsnotify_put_group(group);
|
|
|
|
- atomic_dec(&user->inotify_devs);
|
|
-
|
|
return 0;
|
|
}
|
|
|
|
@@ -697,7 +694,7 @@ retry:
|
|
return ret;
|
|
}
|
|
|
|
-static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsigned int max_events)
|
|
+static struct fsnotify_group *inotify_new_group(unsigned int max_events)
|
|
{
|
|
struct fsnotify_group *group;
|
|
|
|
@@ -710,8 +707,14 @@ static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsign
|
|
spin_lock_init(&group->inotify_data.idr_lock);
|
|
idr_init(&group->inotify_data.idr);
|
|
group->inotify_data.last_wd = 0;
|
|
- group->inotify_data.user = user;
|
|
group->inotify_data.fa = NULL;
|
|
+ group->inotify_data.user = get_current_user();
|
|
+
|
|
+ if (atomic_inc_return(&group->inotify_data.user->inotify_devs) >
|
|
+ inotify_max_user_instances) {
|
|
+ fsnotify_put_group(group);
|
|
+ return ERR_PTR(-EMFILE);
|
|
+ }
|
|
|
|
return group;
|
|
}
|
|
@@ -721,7 +724,6 @@ static struct fsnotify_group *inotify_new_group(struct user_struct *user, unsign
|
|
SYSCALL_DEFINE1(inotify_init1, int, flags)
|
|
{
|
|
struct fsnotify_group *group;
|
|
- struct user_struct *user;
|
|
int ret;
|
|
|
|
/* Check the IN_* constants for consistency. */
|
|
@@ -731,31 +733,16 @@ SYSCALL_DEFINE1(inotify_init1, int, flags)
|
|
if (flags & ~(IN_CLOEXEC | IN_NONBLOCK))
|
|
return -EINVAL;
|
|
|
|
- user = get_current_user();
|
|
- if (unlikely(atomic_read(&user->inotify_devs) >=
|
|
- inotify_max_user_instances)) {
|
|
- ret = -EMFILE;
|
|
- goto out_free_uid;
|
|
- }
|
|
-
|
|
/* fsnotify_obtain_group took a reference to group, we put this when we kill the file in the end */
|
|
- group = inotify_new_group(user, inotify_max_queued_events);
|
|
- if (IS_ERR(group)) {
|
|
- ret = PTR_ERR(group);
|
|
- goto out_free_uid;
|
|
- }
|
|
-
|
|
- atomic_inc(&user->inotify_devs);
|
|
+ group = inotify_new_group(inotify_max_queued_events);
|
|
+ if (IS_ERR(group))
|
|
+ return PTR_ERR(group);
|
|
|
|
ret = anon_inode_getfd("inotify", &inotify_fops, group,
|
|
O_RDONLY | flags);
|
|
- if (ret >= 0)
|
|
- return ret;
|
|
+ if (ret < 0)
|
|
+ fsnotify_put_group(group);
|
|
|
|
- fsnotify_put_group(group);
|
|
- atomic_dec(&user->inotify_devs);
|
|
-out_free_uid:
|
|
- free_uid(user);
|
|
return ret;
|
|
}
|
|
|
|
diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c
|
|
index 1fbb0e2..bbba782 100644
|
|
--- a/fs/ocfs2/aops.c
|
|
+++ b/fs/ocfs2/aops.c
|
|
@@ -1026,6 +1026,12 @@ static int ocfs2_prepare_page_for_write(struct inode *inode, u64 *p_blkno,
|
|
ocfs2_figure_cluster_boundaries(OCFS2_SB(inode->i_sb), cpos,
|
|
&cluster_start, &cluster_end);
|
|
|
|
+ /* treat the write as new if the a hole/lseek spanned across
|
|
+ * the page boundary.
|
|
+ */
|
|
+ new = new | ((i_size_read(inode) <= page_offset(page)) &&
|
|
+ (page_offset(page) <= user_pos));
|
|
+
|
|
if (page == wc->w_target_page) {
|
|
map_from = user_pos & (PAGE_CACHE_SIZE - 1);
|
|
map_to = map_from + user_len;
|
|
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
|
|
index a2a622e..b59ee61 100644
|
|
--- a/fs/quota/dquot.c
|
|
+++ b/fs/quota/dquot.c
|
|
@@ -442,7 +442,7 @@ EXPORT_SYMBOL(dquot_acquire);
|
|
*/
|
|
int dquot_commit(struct dquot *dquot)
|
|
{
|
|
- int ret = 0, ret2 = 0;
|
|
+ int ret = 0;
|
|
struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
|
|
|
|
mutex_lock(&dqopt->dqio_mutex);
|
|
@@ -454,15 +454,10 @@ int dquot_commit(struct dquot *dquot)
|
|
spin_unlock(&dq_list_lock);
|
|
/* Inactive dquot can be only if there was error during read/init
|
|
* => we have better not writing it */
|
|
- if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags)) {
|
|
+ if (test_bit(DQ_ACTIVE_B, &dquot->dq_flags))
|
|
ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
|
|
- if (info_dirty(&dqopt->info[dquot->dq_type])) {
|
|
- ret2 = dqopt->ops[dquot->dq_type]->write_file_info(
|
|
- dquot->dq_sb, dquot->dq_type);
|
|
- }
|
|
- if (ret >= 0)
|
|
- ret = ret2;
|
|
- }
|
|
+ else
|
|
+ ret = -EIO;
|
|
out_sem:
|
|
mutex_unlock(&dqopt->dqio_mutex);
|
|
return ret;
|
|
diff --git a/fs/squashfs/dir.c b/fs/squashfs/dir.c
|
|
index 0dc340a..3f79cd1 100644
|
|
--- a/fs/squashfs/dir.c
|
|
+++ b/fs/squashfs/dir.c
|
|
@@ -172,6 +172,11 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
|
|
length += sizeof(dirh);
|
|
|
|
dir_count = le32_to_cpu(dirh.count) + 1;
|
|
+
|
|
+ /* dir_count should never be larger than 256 */
|
|
+ if (dir_count > 256)
|
|
+ goto failed_read;
|
|
+
|
|
while (dir_count--) {
|
|
/*
|
|
* Read directory entry.
|
|
@@ -183,6 +188,10 @@ static int squashfs_readdir(struct file *file, void *dirent, filldir_t filldir)
|
|
|
|
size = le16_to_cpu(dire->size) + 1;
|
|
|
|
+ /* size should never be larger than SQUASHFS_NAME_LEN */
|
|
+ if (size > SQUASHFS_NAME_LEN)
|
|
+ goto failed_read;
|
|
+
|
|
err = squashfs_read_metadata(inode->i_sb, dire->name,
|
|
&block, &offset, size);
|
|
if (err < 0)
|
|
diff --git a/fs/squashfs/namei.c b/fs/squashfs/namei.c
|
|
index 7a9464d..5d922a6 100644
|
|
--- a/fs/squashfs/namei.c
|
|
+++ b/fs/squashfs/namei.c
|
|
@@ -176,6 +176,11 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
|
|
length += sizeof(dirh);
|
|
|
|
dir_count = le32_to_cpu(dirh.count) + 1;
|
|
+
|
|
+ /* dir_count should never be larger than 256 */
|
|
+ if (dir_count > 256)
|
|
+ goto data_error;
|
|
+
|
|
while (dir_count--) {
|
|
/*
|
|
* Read directory entry.
|
|
@@ -187,6 +192,10 @@ static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
|
|
|
|
size = le16_to_cpu(dire->size) + 1;
|
|
|
|
+ /* size should never be larger than SQUASHFS_NAME_LEN */
|
|
+ if (size > SQUASHFS_NAME_LEN)
|
|
+ goto data_error;
|
|
+
|
|
err = squashfs_read_metadata(dir->i_sb, dire->name,
|
|
&block, &offset, size);
|
|
if (err < 0)
|
|
@@ -228,6 +237,9 @@ exit_lookup:
|
|
d_add(dentry, inode);
|
|
return ERR_PTR(0);
|
|
|
|
+data_error:
|
|
+ err = -EIO;
|
|
+
|
|
read_failure:
|
|
ERROR("Unable to read directory block [%llx:%x]\n",
|
|
squashfs_i(dir)->start + msblk->directory_table,
|
|
diff --git a/fs/squashfs/zlib_wrapper.c b/fs/squashfs/zlib_wrapper.c
|
|
index 4661ae2..04ae9a5 100644
|
|
--- a/fs/squashfs/zlib_wrapper.c
|
|
+++ b/fs/squashfs/zlib_wrapper.c
|
|
@@ -26,6 +26,7 @@
|
|
#include <linux/buffer_head.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/zlib.h>
|
|
+#include <linux/vmalloc.h>
|
|
|
|
#include "squashfs_fs.h"
|
|
#include "squashfs_fs_sb.h"
|
|
@@ -37,8 +38,7 @@ static void *zlib_init(struct squashfs_sb_info *dummy)
|
|
z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
|
|
if (stream == NULL)
|
|
goto failed;
|
|
- stream->workspace = kmalloc(zlib_inflate_workspacesize(),
|
|
- GFP_KERNEL);
|
|
+ stream->workspace = vmalloc(zlib_inflate_workspacesize());
|
|
if (stream->workspace == NULL)
|
|
goto failed;
|
|
|
|
@@ -56,7 +56,7 @@ static void zlib_free(void *strm)
|
|
z_stream *stream = strm;
|
|
|
|
if (stream)
|
|
- kfree(stream->workspace);
|
|
+ vfree(stream->workspace);
|
|
kfree(stream);
|
|
}
|
|
|
|
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
|
|
index 02429d8..32bcb2c 100644
|
|
--- a/fs/ubifs/commit.c
|
|
+++ b/fs/ubifs/commit.c
|
|
@@ -521,7 +521,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
|
|
size_t sz;
|
|
|
|
if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
|
|
- goto out;
|
|
+ return 0;
|
|
|
|
INIT_LIST_HEAD(&list);
|
|
|
|
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
|
|
index 0bee4db..5b9e985 100644
|
|
--- a/fs/ubifs/debug.c
|
|
+++ b/fs/ubifs/debug.c
|
|
@@ -961,11 +961,39 @@ void dbg_dump_index(struct ubifs_info *c)
|
|
void dbg_save_space_info(struct ubifs_info *c)
|
|
{
|
|
struct ubifs_debug_info *d = c->dbg;
|
|
-
|
|
- ubifs_get_lp_stats(c, &d->saved_lst);
|
|
+ int freeable_cnt;
|
|
|
|
spin_lock(&c->space_lock);
|
|
+ memcpy(&d->saved_lst, &c->lst, sizeof(struct ubifs_lp_stats));
|
|
+
|
|
+ /*
|
|
+ * We use a dirty hack here and zero out @c->freeable_cnt, because it
|
|
+ * affects the free space calculations, and UBIFS might not know about
|
|
+ * all freeable eraseblocks. Indeed, we know about freeable eraseblocks
|
|
+ * only when we read their lprops, and we do this only lazily, upon the
|
|
+ * need. So at any given point of time @c->freeable_cnt might be not
|
|
+ * exactly accurate.
|
|
+ *
|
|
+ * Just one example about the issue we hit when we did not zero
|
|
+ * @c->freeable_cnt.
|
|
+ * 1. The file-system is mounted R/O, c->freeable_cnt is %0. We save the
|
|
+ * amount of free space in @d->saved_free
|
|
+ * 2. We re-mount R/W, which makes UBIFS to read the "lsave"
|
|
+ * information from flash, where we cache LEBs from various
|
|
+ * categories ('ubifs_remount_fs()' -> 'ubifs_lpt_init()'
|
|
+ * -> 'lpt_init_wr()' -> 'read_lsave()' -> 'ubifs_lpt_lookup()'
|
|
+ * -> 'ubifs_get_pnode()' -> 'update_cats()'
|
|
+ * -> 'ubifs_add_to_cat()').
|
|
+ * 3. Lsave contains a freeable eraseblock, and @c->freeable_cnt
|
|
+ * becomes %1.
|
|
+ * 4. We calculate the amount of free space when the re-mount is
|
|
+ * finished in 'dbg_check_space_info()' and it does not match
|
|
+ * @d->saved_free.
|
|
+ */
|
|
+ freeable_cnt = c->freeable_cnt;
|
|
+ c->freeable_cnt = 0;
|
|
d->saved_free = ubifs_get_free_space_nolock(c);
|
|
+ c->freeable_cnt = freeable_cnt;
|
|
spin_unlock(&c->space_lock);
|
|
}
|
|
|
|
@@ -982,12 +1010,15 @@ int dbg_check_space_info(struct ubifs_info *c)
|
|
{
|
|
struct ubifs_debug_info *d = c->dbg;
|
|
struct ubifs_lp_stats lst;
|
|
- long long avail, free;
|
|
+ long long free;
|
|
+ int freeable_cnt;
|
|
|
|
spin_lock(&c->space_lock);
|
|
- avail = ubifs_calc_available(c, c->min_idx_lebs);
|
|
+ freeable_cnt = c->freeable_cnt;
|
|
+ c->freeable_cnt = 0;
|
|
+ free = ubifs_get_free_space_nolock(c);
|
|
+ c->freeable_cnt = freeable_cnt;
|
|
spin_unlock(&c->space_lock);
|
|
- free = ubifs_get_free_space(c);
|
|
|
|
if (free != d->saved_free) {
|
|
ubifs_err("free space changed from %lld to %lld",
|
|
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
|
|
index 72775d3..ef5155e 100644
|
|
--- a/fs/ubifs/lpt.c
|
|
+++ b/fs/ubifs/lpt.c
|
|
@@ -1270,10 +1270,9 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
|
|
lnum = branch->lnum;
|
|
offs = branch->offs;
|
|
pnode = kzalloc(sizeof(struct ubifs_pnode), GFP_NOFS);
|
|
- if (!pnode) {
|
|
- err = -ENOMEM;
|
|
- goto out;
|
|
- }
|
|
+ if (!pnode)
|
|
+ return -ENOMEM;
|
|
+
|
|
if (lnum == 0) {
|
|
/*
|
|
* This pnode was not written which just means that the LEB
|
|
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c
|
|
index 9731898..ad485b6 100644
|
|
--- a/fs/xfs/linux-2.6/xfs_super.c
|
|
+++ b/fs/xfs/linux-2.6/xfs_super.c
|
|
@@ -1551,10 +1551,14 @@ xfs_fs_fill_super(
|
|
if (error)
|
|
goto out_free_sb;
|
|
|
|
- error = xfs_mountfs(mp);
|
|
- if (error)
|
|
- goto out_filestream_unmount;
|
|
-
|
|
+ /*
|
|
+ * we must configure the block size in the superblock before we run the
|
|
+ * full mount process as the mount process can lookup and cache inodes.
|
|
+ * For the same reason we must also initialise the syncd and register
|
|
+ * the inode cache shrinker so that inodes can be reclaimed during
|
|
+ * operations like a quotacheck that iterate all inodes in the
|
|
+ * filesystem.
|
|
+ */
|
|
sb->s_magic = XFS_SB_MAGIC;
|
|
sb->s_blocksize = mp->m_sb.sb_blocksize;
|
|
sb->s_blocksize_bits = ffs(sb->s_blocksize) - 1;
|
|
@@ -1562,6 +1566,16 @@ xfs_fs_fill_super(
|
|
sb->s_time_gran = 1;
|
|
set_posix_acl_flag(sb);
|
|
|
|
+ error = xfs_syncd_init(mp);
|
|
+ if (error)
|
|
+ goto out_filestream_unmount;
|
|
+
|
|
+ xfs_inode_shrinker_register(mp);
|
|
+
|
|
+ error = xfs_mountfs(mp);
|
|
+ if (error)
|
|
+ goto out_syncd_stop;
|
|
+
|
|
root = igrab(VFS_I(mp->m_rootip));
|
|
if (!root) {
|
|
error = ENOENT;
|
|
@@ -1577,14 +1591,11 @@ xfs_fs_fill_super(
|
|
goto fail_vnrele;
|
|
}
|
|
|
|
- error = xfs_syncd_init(mp);
|
|
- if (error)
|
|
- goto fail_vnrele;
|
|
-
|
|
- xfs_inode_shrinker_register(mp);
|
|
-
|
|
return 0;
|
|
|
|
+ out_syncd_stop:
|
|
+ xfs_inode_shrinker_unregister(mp);
|
|
+ xfs_syncd_stop(mp);
|
|
out_filestream_unmount:
|
|
xfs_filestream_unmount(mp);
|
|
out_free_sb:
|
|
@@ -1608,6 +1619,9 @@ xfs_fs_fill_super(
|
|
}
|
|
|
|
fail_unmount:
|
|
+ xfs_inode_shrinker_unregister(mp);
|
|
+ xfs_syncd_stop(mp);
|
|
+
|
|
/*
|
|
* Blow away any referenced inode in the filestreams cache.
|
|
* This can and will cause log traffic as inodes go inactive
|
|
diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
|
|
index 5ff1194..6724bf3 100644
|
|
--- a/include/drm/drm_pciids.h
|
|
+++ b/include/drm/drm_pciids.h
|
|
@@ -458,6 +458,8 @@
|
|
{0x1002, 0x9803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
|
|
{0x1002, 0x9804, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
|
|
{0x1002, 0x9805, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
|
|
+ {0x1002, 0x9806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
|
|
+ {0x1002, 0x9807, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
|
|
{0, 0, 0}
|
|
|
|
#define r128_PCI_IDS \
|
|
diff --git a/include/linux/atmdev.h b/include/linux/atmdev.h
|
|
index 475f8c4..381f4ce 100644
|
|
--- a/include/linux/atmdev.h
|
|
+++ b/include/linux/atmdev.h
|
|
@@ -443,6 +443,7 @@ void atm_dev_signal_change(struct atm_dev *dev, char signal);
|
|
|
|
void vcc_insert_socket(struct sock *sk);
|
|
|
|
+void atm_dev_release_vccs(struct atm_dev *dev);
|
|
|
|
/*
|
|
* This is approximately the algorithm used by alloc_skb.
|
|
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
|
|
index a3c1874..a04b6ce 100644
|
|
--- a/include/linux/ethtool.h
|
|
+++ b/include/linux/ethtool.h
|
|
@@ -591,6 +591,7 @@ int ethtool_op_set_ufo(struct net_device *dev, u32 data);
|
|
u32 ethtool_op_get_flags(struct net_device *dev);
|
|
int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported);
|
|
void ethtool_ntuple_flush(struct net_device *dev);
|
|
+bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported);
|
|
|
|
/**
|
|
* ðtool_ops - Alter and report network device settings
|
|
diff --git a/include/linux/pci.h b/include/linux/pci.h
|
|
index 559d028..6002bca 100644
|
|
--- a/include/linux/pci.h
|
|
+++ b/include/linux/pci.h
|
|
@@ -1002,12 +1002,11 @@ extern bool pcie_ports_auto;
|
|
#endif
|
|
|
|
#ifndef CONFIG_PCIEASPM
|
|
-static inline int pcie_aspm_enabled(void)
|
|
-{
|
|
- return 0;
|
|
-}
|
|
+static inline int pcie_aspm_enabled(void) { return 0; }
|
|
+static inline bool pcie_aspm_support_enabled(void) { return false; }
|
|
#else
|
|
extern int pcie_aspm_enabled(void);
|
|
+extern bool pcie_aspm_support_enabled(void);
|
|
#endif
|
|
|
|
#ifdef CONFIG_PCIEAER
|
|
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
|
|
index 85867dc..bfd36ff 100644
|
|
--- a/include/scsi/scsi_device.h
|
|
+++ b/include/scsi/scsi_device.h
|
|
@@ -461,7 +461,7 @@ static inline int scsi_device_qas(struct scsi_device *sdev)
|
|
}
|
|
static inline int scsi_device_enclosure(struct scsi_device *sdev)
|
|
{
|
|
- return sdev->inquiry[6] & (1<<6);
|
|
+ return sdev->inquiry ? (sdev->inquiry[6] & (1<<6)) : 1;
|
|
}
|
|
|
|
static inline int scsi_device_protection(struct scsi_device *sdev)
|
|
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
|
|
index e731f8d..ec26781 100644
|
|
--- a/include/sound/pcm.h
|
|
+++ b/include/sound/pcm.h
|
|
@@ -1030,9 +1030,7 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s
|
|
#define snd_pcm_lib_mmap_iomem NULL
|
|
#endif
|
|
|
|
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
|
|
- struct vm_area_struct *area);
|
|
-#define snd_pcm_lib_mmap_vmalloc snd_pcm_lib_mmap_noncached
|
|
+#define snd_pcm_lib_mmap_vmalloc NULL
|
|
|
|
static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
|
|
{
|
|
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
|
|
index 8031769..60f94fb 100644
|
|
--- a/include/sound/soc-dapm.h
|
|
+++ b/include/sound/soc-dapm.h
|
|
@@ -45,25 +45,25 @@
|
|
/* platform domain */
|
|
#define SND_SOC_DAPM_INPUT(wname) \
|
|
{ .id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0}
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM }
|
|
#define SND_SOC_DAPM_OUTPUT(wname) \
|
|
{ .id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0}
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM }
|
|
#define SND_SOC_DAPM_MIC(wname, wevent) \
|
|
{ .id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0, .event = wevent, \
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
|
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
|
|
#define SND_SOC_DAPM_HP(wname, wevent) \
|
|
{ .id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0, .event = wevent, \
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
|
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
|
#define SND_SOC_DAPM_SPK(wname, wevent) \
|
|
{ .id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0, .event = wevent, \
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
|
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
|
#define SND_SOC_DAPM_LINE(wname, wevent) \
|
|
{ .id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0, .event = wevent, \
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
|
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
|
|
|
|
/* path domain */
|
|
@@ -177,11 +177,11 @@
|
|
/* events that are pre and post DAPM */
|
|
#define SND_SOC_DAPM_PRE(wname, wevent) \
|
|
{ .id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0, .event = wevent, \
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
|
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD}
|
|
#define SND_SOC_DAPM_POST(wname, wevent) \
|
|
{ .id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \
|
|
- .num_kcontrols = 0, .event = wevent, \
|
|
+ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
|
|
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
|
|
|
|
/* stream domain */
|
|
diff --git a/kernel/perf_event.c b/kernel/perf_event.c
|
|
index ad02fea..b2536bd 100644
|
|
--- a/kernel/perf_event.c
|
|
+++ b/kernel/perf_event.c
|
|
@@ -62,7 +62,8 @@ static struct srcu_struct pmus_srcu;
|
|
*/
|
|
int sysctl_perf_event_paranoid __read_mostly = 1;
|
|
|
|
-int sysctl_perf_event_mlock __read_mostly = 512; /* 'free' kb per user */
|
|
+/* Minimum for 512 kiB + 1 user control page */
|
|
+int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' kiB per user */
|
|
|
|
/*
|
|
* max perf event sample rate
|
|
@@ -5916,6 +5917,11 @@ SYSCALL_DEFINE5(perf_event_open,
|
|
goto err_alloc;
|
|
}
|
|
|
|
+ if (task) {
|
|
+ put_task_struct(task);
|
|
+ task = NULL;
|
|
+ }
|
|
+
|
|
/*
|
|
* Look up the group leader (we will attach this event to it):
|
|
*/
|
|
diff --git a/kernel/signal.c b/kernel/signal.c
|
|
index 3175186..bf11d269 100644
|
|
--- a/kernel/signal.c
|
|
+++ b/kernel/signal.c
|
|
@@ -2423,7 +2423,7 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
|
|
/* Not even root can pretend to send signals from the kernel.
|
|
* Nor can they impersonate a kill()/tgkill(), which adds source info.
|
|
*/
|
|
- if (info.si_code != SI_QUEUE) {
|
|
+ if (info.si_code >= 0 || info.si_code == SI_TKILL) {
|
|
/* We used to allow any < 0 si_code */
|
|
WARN_ON_ONCE(info.si_code < 0);
|
|
return -EPERM;
|
|
@@ -2443,7 +2443,7 @@ long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
|
|
/* Not even root can pretend to send signals from the kernel.
|
|
* Nor can they impersonate a kill()/tgkill(), which adds source info.
|
|
*/
|
|
- if (info->si_code != SI_QUEUE) {
|
|
+ if (info->si_code >= 0 || info->si_code == SI_TKILL) {
|
|
/* We used to allow any < 0 si_code */
|
|
WARN_ON_ONCE(info->si_code < 0);
|
|
return -EPERM;
|
|
diff --git a/mm/mremap.c b/mm/mremap.c
|
|
index 1de98d4..a7c1f9f 100644
|
|
--- a/mm/mremap.c
|
|
+++ b/mm/mremap.c
|
|
@@ -277,9 +277,16 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,
|
|
if (old_len > vma->vm_end - addr)
|
|
goto Efault;
|
|
|
|
- if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) {
|
|
- if (new_len > old_len)
|
|
+ /* Need to be careful about a growing mapping */
|
|
+ if (new_len > old_len) {
|
|
+ unsigned long pgoff;
|
|
+
|
|
+ if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
|
|
goto Efault;
|
|
+ pgoff = (addr - vma->vm_start) >> PAGE_SHIFT;
|
|
+ pgoff += vma->vm_pgoff;
|
|
+ if (pgoff + (new_len >> PAGE_SHIFT) < pgoff)
|
|
+ goto Einval;
|
|
}
|
|
|
|
if (vma->vm_flags & VM_LOCKED) {
|
|
diff --git a/net/atm/common.c b/net/atm/common.c
|
|
index 1b9c52a..22b963d 100644
|
|
--- a/net/atm/common.c
|
|
+++ b/net/atm/common.c
|
|
@@ -252,6 +252,7 @@ void atm_dev_release_vccs(struct atm_dev *dev)
|
|
}
|
|
write_unlock_irq(&vcc_sklist_lock);
|
|
}
|
|
+EXPORT_SYMBOL(atm_dev_release_vccs);
|
|
|
|
static int adjust_tp(struct atm_trafprm *tp, unsigned char aal)
|
|
{
|
|
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c
|
|
index 2862f53..d935da7 100644
|
|
--- a/net/bluetooth/bnep/sock.c
|
|
+++ b/net/bluetooth/bnep/sock.c
|
|
@@ -88,6 +88,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
|
|
sockfd_put(nsock);
|
|
return -EBADFD;
|
|
}
|
|
+ ca.device[sizeof(ca.device)-1] = 0;
|
|
|
|
err = bnep_add_connection(&ca, nsock);
|
|
if (!err) {
|
|
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
|
|
index 960c6d1..926ed39 100644
|
|
--- a/net/bluetooth/sco.c
|
|
+++ b/net/bluetooth/sco.c
|
|
@@ -703,6 +703,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname, char __user
|
|
break;
|
|
}
|
|
|
|
+ memset(&cinfo, 0, sizeof(cinfo));
|
|
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
|
|
memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
|
|
|
|
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
|
|
index 16df053..47acf4a 100644
|
|
--- a/net/bridge/netfilter/ebtables.c
|
|
+++ b/net/bridge/netfilter/ebtables.c
|
|
@@ -1107,6 +1107,8 @@ static int do_replace(struct net *net, const void __user *user,
|
|
if (tmp.num_counters >= INT_MAX / sizeof(struct ebt_counter))
|
|
return -ENOMEM;
|
|
|
|
+ tmp.name[sizeof(tmp.name) - 1] = 0;
|
|
+
|
|
countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
|
|
newinfo = vmalloc(sizeof(*newinfo) + countersize);
|
|
if (!newinfo)
|
|
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
|
|
index ff23029..6c7c610 100644
|
|
--- a/net/core/ethtool.c
|
|
+++ b/net/core/ethtool.c
|
|
@@ -146,9 +146,24 @@ u32 ethtool_op_get_flags(struct net_device *dev)
|
|
}
|
|
EXPORT_SYMBOL(ethtool_op_get_flags);
|
|
|
|
+/* Check if device can enable (or disable) particular feature coded in "data"
|
|
+ * argument. Flags "supported" describe features that can be toggled by device.
|
|
+ * If feature can not be toggled, it state (enabled or disabled) must match
|
|
+ * hardcoded device features state, otherwise flags are marked as invalid.
|
|
+ */
|
|
+bool ethtool_invalid_flags(struct net_device *dev, u32 data, u32 supported)
|
|
+{
|
|
+ u32 features = dev->features & flags_dup_features;
|
|
+ /* "data" can contain only flags_dup_features bits,
|
|
+ * see __ethtool_set_flags */
|
|
+
|
|
+ return (features & ~supported) != (data & ~supported);
|
|
+}
|
|
+EXPORT_SYMBOL(ethtool_invalid_flags);
|
|
+
|
|
int ethtool_op_set_flags(struct net_device *dev, u32 data, u32 supported)
|
|
{
|
|
- if (data & ~supported)
|
|
+ if (ethtool_invalid_flags(dev, data, supported))
|
|
return -EINVAL;
|
|
|
|
dev->features = ((dev->features & ~flags_dup_features) |
|
|
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c
|
|
index 0c28263..116d3fd 100644
|
|
--- a/net/econet/af_econet.c
|
|
+++ b/net/econet/af_econet.c
|
|
@@ -435,10 +435,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
|
udpdest.sin_addr.s_addr = htonl(network | addr.station);
|
|
}
|
|
|
|
+ memset(&ah, 0, sizeof(ah));
|
|
ah.port = port;
|
|
ah.cb = cb & 0x7f;
|
|
ah.code = 2; /* magic */
|
|
- ah.pad = 0;
|
|
|
|
/* tack our header on the front of the iovec */
|
|
size = sizeof(struct aunhdr);
|
|
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
|
|
index e855fff..6d79aa1 100644
|
|
--- a/net/ipv4/netfilter/arp_tables.c
|
|
+++ b/net/ipv4/netfilter/arp_tables.c
|
|
@@ -1065,6 +1065,7 @@ static int do_replace(struct net *net, const void __user *user,
|
|
/* overflow check */
|
|
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
|
|
return -ENOMEM;
|
|
+ tmp.name[sizeof(tmp.name)-1] = 0;
|
|
|
|
newinfo = xt_alloc_table_info(tmp.size);
|
|
if (!newinfo)
|
|
@@ -1486,6 +1487,7 @@ static int compat_do_replace(struct net *net, void __user *user,
|
|
return -ENOMEM;
|
|
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
|
|
return -ENOMEM;
|
|
+ tmp.name[sizeof(tmp.name)-1] = 0;
|
|
|
|
newinfo = xt_alloc_table_info(tmp.size);
|
|
if (!newinfo)
|
|
@@ -1738,6 +1740,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
|
|
ret = -EFAULT;
|
|
break;
|
|
}
|
|
+ rev.name[sizeof(rev.name)-1] = 0;
|
|
|
|
try_then_request_module(xt_find_revision(NFPROTO_ARP, rev.name,
|
|
rev.revision, 1, &ret),
|
|
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
|
|
index 652efea..92fb4c5 100644
|
|
--- a/net/ipv4/netfilter/ip_tables.c
|
|
+++ b/net/ipv4/netfilter/ip_tables.c
|
|
@@ -387,7 +387,7 @@ ipt_do_table(struct sk_buff *skb,
|
|
verdict = (unsigned)(-v) - 1;
|
|
break;
|
|
}
|
|
- if (*stackptr == 0) {
|
|
+ if (*stackptr <= origptr) {
|
|
e = get_entry(table_base,
|
|
private->underflow[hook]);
|
|
pr_debug("Underflow (this is normal) "
|
|
@@ -427,10 +427,10 @@ ipt_do_table(struct sk_buff *skb,
|
|
/* Verdict */
|
|
break;
|
|
} while (!acpar.hotdrop);
|
|
- xt_info_rdunlock_bh();
|
|
pr_debug("Exiting %s; resetting sp from %u to %u\n",
|
|
__func__, *stackptr, origptr);
|
|
*stackptr = origptr;
|
|
+ xt_info_rdunlock_bh();
|
|
#ifdef DEBUG_ALLOW_ALL
|
|
return NF_ACCEPT;
|
|
#else
|
|
@@ -1261,6 +1261,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
|
|
/* overflow check */
|
|
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
|
|
return -ENOMEM;
|
|
+ tmp.name[sizeof(tmp.name)-1] = 0;
|
|
|
|
newinfo = xt_alloc_table_info(tmp.size);
|
|
if (!newinfo)
|
|
@@ -1805,6 +1806,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
|
|
return -ENOMEM;
|
|
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
|
|
return -ENOMEM;
|
|
+ tmp.name[sizeof(tmp.name)-1] = 0;
|
|
|
|
newinfo = xt_alloc_table_info(tmp.size);
|
|
if (!newinfo)
|
|
@@ -2034,6 +2036,7 @@ do_ipt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
|
|
ret = -EFAULT;
|
|
break;
|
|
}
|
|
+ rev.name[sizeof(rev.name)-1] = 0;
|
|
|
|
if (cmd == IPT_SO_GET_REVISION_TARGET)
|
|
target = 1;
|
|
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
|
|
index 1e26a48..af7dec6 100644
|
|
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
|
|
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
|
|
@@ -669,8 +669,11 @@ static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
|
|
char buffer[PROC_WRITELEN+1];
|
|
unsigned long nodenum;
|
|
|
|
- if (copy_from_user(buffer, input, PROC_WRITELEN))
|
|
+ if (size > PROC_WRITELEN)
|
|
+ return -EIO;
|
|
+ if (copy_from_user(buffer, input, size))
|
|
return -EFAULT;
|
|
+ buffer[size] = 0;
|
|
|
|
if (*buffer == '+') {
|
|
nodenum = simple_strtoul(buffer+1, NULL, 10);
|
|
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
|
|
index 7d227c6..eadafbf 100644
|
|
--- a/net/ipv6/netfilter/ip6_tables.c
|
|
+++ b/net/ipv6/netfilter/ip6_tables.c
|
|
@@ -410,7 +410,7 @@ ip6t_do_table(struct sk_buff *skb,
|
|
verdict = (unsigned)(-v) - 1;
|
|
break;
|
|
}
|
|
- if (*stackptr == 0)
|
|
+ if (*stackptr <= origptr)
|
|
e = get_entry(table_base,
|
|
private->underflow[hook]);
|
|
else
|
|
@@ -441,8 +441,8 @@ ip6t_do_table(struct sk_buff *skb,
|
|
break;
|
|
} while (!acpar.hotdrop);
|
|
|
|
- xt_info_rdunlock_bh();
|
|
*stackptr = origptr;
|
|
+ xt_info_rdunlock_bh();
|
|
|
|
#ifdef DEBUG_ALLOW_ALL
|
|
return NF_ACCEPT;
|
|
@@ -1274,6 +1274,7 @@ do_replace(struct net *net, const void __user *user, unsigned int len)
|
|
/* overflow check */
|
|
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
|
|
return -ENOMEM;
|
|
+ tmp.name[sizeof(tmp.name)-1] = 0;
|
|
|
|
newinfo = xt_alloc_table_info(tmp.size);
|
|
if (!newinfo)
|
|
@@ -1820,6 +1821,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
|
|
return -ENOMEM;
|
|
if (tmp.num_counters >= INT_MAX / sizeof(struct xt_counters))
|
|
return -ENOMEM;
|
|
+ tmp.name[sizeof(tmp.name)-1] = 0;
|
|
|
|
newinfo = xt_alloc_table_info(tmp.size);
|
|
if (!newinfo)
|
|
@@ -2049,6 +2051,7 @@ do_ip6t_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
|
|
ret = -EFAULT;
|
|
break;
|
|
}
|
|
+ rev.name[sizeof(rev.name)-1] = 0;
|
|
|
|
if (cmd == IP6T_SO_GET_REVISION_TARGET)
|
|
target = 1;
|
|
diff --git a/net/irda/iriap.c b/net/irda/iriap.c
|
|
index 5b743bd..3647753 100644
|
|
--- a/net/irda/iriap.c
|
|
+++ b/net/irda/iriap.c
|
|
@@ -656,10 +656,16 @@ static void iriap_getvaluebyclass_indication(struct iriap_cb *self,
|
|
n = 1;
|
|
|
|
name_len = fp[n++];
|
|
+
|
|
+ IRDA_ASSERT(name_len < IAS_MAX_CLASSNAME + 1, return;);
|
|
+
|
|
memcpy(name, fp+n, name_len); n+=name_len;
|
|
name[name_len] = '\0';
|
|
|
|
attr_len = fp[n++];
|
|
+
|
|
+ IRDA_ASSERT(attr_len < IAS_MAX_ATTRIBNAME + 1, return;);
|
|
+
|
|
memcpy(attr, fp+n, attr_len); n+=attr_len;
|
|
attr[attr_len] = '\0';
|
|
|
|
diff --git a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
|
|
index 7c567b8..2bb2beb 100644
|
|
--- a/net/irda/irnet/irnet_ppp.c
|
|
+++ b/net/irda/irnet/irnet_ppp.c
|
|
@@ -105,6 +105,9 @@ irnet_ctrl_write(irnet_socket * ap,
|
|
while(isspace(start[length - 1]))
|
|
length--;
|
|
|
|
+ DABORT(length < 5 || length > NICKNAME_MAX_LEN + 5,
|
|
+ -EINVAL, CTRL_ERROR, "Invalid nickname.\n");
|
|
+
|
|
/* Copy the name for later reuse */
|
|
memcpy(ap->rname, start + 5, length - 5);
|
|
ap->rname[length - 5] = '\0';
|
|
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
|
|
index 165a451..cac35ff 100644
|
|
--- a/net/mac80211/rc80211_minstrel_ht.c
|
|
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
|
@@ -639,18 +639,14 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
|
|
struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
|
|
struct ieee80211_local *local = hw_to_local(mp->hw);
|
|
u16 sta_cap = sta->ht_cap.cap;
|
|
+ int n_supported = 0;
|
|
int ack_dur;
|
|
int stbc;
|
|
int i;
|
|
|
|
/* fall back to the old minstrel for legacy stations */
|
|
- if (!sta->ht_cap.ht_supported) {
|
|
- msp->is_ht = false;
|
|
- memset(&msp->legacy, 0, sizeof(msp->legacy));
|
|
- msp->legacy.r = msp->ratelist;
|
|
- msp->legacy.sample_table = msp->sample_table;
|
|
- return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
|
|
- }
|
|
+ if (!sta->ht_cap.ht_supported)
|
|
+ goto use_legacy;
|
|
|
|
BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) !=
|
|
MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS);
|
|
@@ -705,7 +701,22 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband,
|
|
|
|
mi->groups[i].supported =
|
|
mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
|
|
+
|
|
+ if (mi->groups[i].supported)
|
|
+ n_supported++;
|
|
}
|
|
+
|
|
+ if (!n_supported)
|
|
+ goto use_legacy;
|
|
+
|
|
+ return;
|
|
+
|
|
+use_legacy:
|
|
+ msp->is_ht = false;
|
|
+ memset(&msp->legacy, 0, sizeof(msp->legacy));
|
|
+ msp->legacy.r = msp->ratelist;
|
|
+ msp->legacy.sample_table = msp->sample_table;
|
|
+ return mac80211_minstrel.rate_init(priv, sband, sta, &msp->legacy);
|
|
}
|
|
|
|
static void
|
|
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
|
|
index c426504..604216e 100644
|
|
--- a/net/mac80211/sta_info.c
|
|
+++ b/net/mac80211/sta_info.c
|
|
@@ -243,6 +243,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|
memcpy(sta->sta.addr, addr, ETH_ALEN);
|
|
sta->local = local;
|
|
sta->sdata = sdata;
|
|
+ sta->last_rx = jiffies;
|
|
|
|
ewma_init(&sta->avg_signal, 1024, 8);
|
|
|
|
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c
|
|
index 8678823..bcd5ed6 100644
|
|
--- a/net/netfilter/nf_conntrack_h323_asn1.c
|
|
+++ b/net/netfilter/nf_conntrack_h323_asn1.c
|
|
@@ -631,7 +631,7 @@ static int decode_seqof(bitstr_t *bs, const struct field_t *f,
|
|
CHECK_BOUND(bs, 2);
|
|
count = *bs->cur++;
|
|
count <<= 8;
|
|
- count = *bs->cur++;
|
|
+ count += *bs->cur++;
|
|
break;
|
|
case SEMI:
|
|
BYTE_ALIGN(bs);
|
|
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c
|
|
index 1734abb..174d51c 100644
|
|
--- a/net/rose/rose_subr.c
|
|
+++ b/net/rose/rose_subr.c
|
|
@@ -290,10 +290,15 @@ static int rose_parse_national(unsigned char *p, struct rose_facilities_struct *
|
|
facilities->source_ndigis = 0;
|
|
facilities->dest_ndigis = 0;
|
|
for (pt = p + 2, lg = 0 ; lg < l ; pt += AX25_ADDR_LEN, lg += AX25_ADDR_LEN) {
|
|
- if (pt[6] & AX25_HBIT)
|
|
+ if (pt[6] & AX25_HBIT) {
|
|
+ if (facilities->dest_ndigis >= ROSE_MAX_DIGIS)
|
|
+ return -1;
|
|
memcpy(&facilities->dest_digis[facilities->dest_ndigis++], pt, AX25_ADDR_LEN);
|
|
- else
|
|
+ } else {
|
|
+ if (facilities->source_ndigis >= ROSE_MAX_DIGIS)
|
|
+ return -1;
|
|
memcpy(&facilities->source_digis[facilities->source_ndigis++], pt, AX25_ADDR_LEN);
|
|
+ }
|
|
}
|
|
}
|
|
p += l + 2;
|
|
@@ -333,6 +338,11 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac
|
|
|
|
case 0xC0:
|
|
l = p[1];
|
|
+
|
|
+ /* Prevent overflows*/
|
|
+ if (l < 10 || l > 20)
|
|
+ return -1;
|
|
+
|
|
if (*p == FAC_CCITT_DEST_NSAP) {
|
|
memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN);
|
|
memcpy(callsign, p + 12, l - 10);
|
|
@@ -373,12 +383,16 @@ int rose_parse_facilities(unsigned char *p,
|
|
switch (*p) {
|
|
case FAC_NATIONAL: /* National */
|
|
len = rose_parse_national(p + 1, facilities, facilities_len - 1);
|
|
+ if (len < 0)
|
|
+ return 0;
|
|
facilities_len -= len + 1;
|
|
p += len + 1;
|
|
break;
|
|
|
|
case FAC_CCITT: /* CCITT */
|
|
len = rose_parse_ccitt(p + 1, facilities, facilities_len - 1);
|
|
+ if (len < 0)
|
|
+ return 0;
|
|
facilities_len -= len + 1;
|
|
p += len + 1;
|
|
break;
|
|
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
|
|
index f375dec..778e5df 100644
|
|
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
|
|
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
|
|
@@ -427,7 +427,7 @@ static int
|
|
context_derive_keys_rc4(struct krb5_ctx *ctx)
|
|
{
|
|
struct crypto_hash *hmac;
|
|
- static const char sigkeyconstant[] = "signaturekey";
|
|
+ char sigkeyconstant[] = "signaturekey";
|
|
int slen = strlen(sigkeyconstant) + 1; /* include null terminator */
|
|
struct hash_desc desc;
|
|
struct scatterlist sg[1];
|
|
diff --git a/sound/core/init.c b/sound/core/init.c
|
|
index 3e65da2..a0080aa 100644
|
|
--- a/sound/core/init.c
|
|
+++ b/sound/core/init.c
|
|
@@ -848,6 +848,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
|
|
return -ENOMEM;
|
|
mfile->file = file;
|
|
mfile->disconnected_f_op = NULL;
|
|
+ INIT_LIST_HEAD(&mfile->shutdown_list);
|
|
spin_lock(&card->files_lock);
|
|
if (card->shutdown) {
|
|
spin_unlock(&card->files_lock);
|
|
@@ -883,6 +884,9 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
|
|
list_for_each_entry(mfile, &card->files_list, list) {
|
|
if (mfile->file == file) {
|
|
list_del(&mfile->list);
|
|
+ spin_lock(&shutdown_lock);
|
|
+ list_del(&mfile->shutdown_list);
|
|
+ spin_unlock(&shutdown_lock);
|
|
if (mfile->disconnected_f_op)
|
|
fops_put(mfile->disconnected_f_op);
|
|
found = mfile;
|
|
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
|
|
index a82e3756..64449cb 100644
|
|
--- a/sound/core/pcm_lib.c
|
|
+++ b/sound/core/pcm_lib.c
|
|
@@ -375,6 +375,7 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
|
}
|
|
|
|
if (runtime->no_period_wakeup) {
|
|
+ snd_pcm_sframes_t xrun_threshold;
|
|
/*
|
|
* Without regular period interrupts, we have to check
|
|
* the elapsed time to detect xruns.
|
|
@@ -383,7 +384,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
|
|
if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)
|
|
goto no_delta_check;
|
|
hdelta = jdelta - delta * HZ / runtime->rate;
|
|
- while (hdelta > runtime->hw_ptr_buffer_jiffies / 2 + 1) {
|
|
+ xrun_threshold = runtime->hw_ptr_buffer_jiffies / 2 + 1;
|
|
+ while (hdelta > xrun_threshold) {
|
|
delta += runtime->buffer_size;
|
|
hw_base += runtime->buffer_size;
|
|
if (hw_base >= runtime->boundary)
|
|
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
|
|
index 4be45e7..6848dd9 100644
|
|
--- a/sound/core/pcm_native.c
|
|
+++ b/sound/core/pcm_native.c
|
|
@@ -3201,15 +3201,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
|
|
EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
|
|
#endif /* SNDRV_PCM_INFO_MMAP */
|
|
|
|
-/* mmap callback with pgprot_noncached */
|
|
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
|
|
- struct vm_area_struct *area)
|
|
-{
|
|
- area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
|
|
- return snd_pcm_default_mmap(substream, area);
|
|
-}
|
|
-EXPORT_SYMBOL(snd_pcm_lib_mmap_noncached);
|
|
-
|
|
/*
|
|
* mmap DMA buffer
|
|
*/
|
|
diff --git a/sound/oss/dev_table.h b/sound/oss/dev_table.h
|
|
index b7617be..0199a31 100644
|
|
--- a/sound/oss/dev_table.h
|
|
+++ b/sound/oss/dev_table.h
|
|
@@ -271,7 +271,7 @@ struct synth_operations
|
|
void (*reset) (int dev);
|
|
void (*hw_control) (int dev, unsigned char *event);
|
|
int (*load_patch) (int dev, int format, const char __user *addr,
|
|
- int offs, int count, int pmgr_flag);
|
|
+ int count, int pmgr_flag);
|
|
void (*aftertouch) (int dev, int voice, int pressure);
|
|
void (*controller) (int dev, int voice, int ctrl_num, int value);
|
|
void (*panning) (int dev, int voice, int value);
|
|
diff --git a/sound/oss/midi_synth.c b/sound/oss/midi_synth.c
|
|
index 3c09374..2292c23 100644
|
|
--- a/sound/oss/midi_synth.c
|
|
+++ b/sound/oss/midi_synth.c
|
|
@@ -476,7 +476,7 @@ EXPORT_SYMBOL(midi_synth_hw_control);
|
|
|
|
int
|
|
midi_synth_load_patch(int dev, int format, const char __user *addr,
|
|
- int offs, int count, int pmgr_flag)
|
|
+ int count, int pmgr_flag)
|
|
{
|
|
int orig_dev = synth_devs[dev]->midi_dev;
|
|
|
|
@@ -491,33 +491,29 @@ midi_synth_load_patch(int dev, int format, const char __user *addr,
|
|
if (!prefix_cmd(orig_dev, 0xf0))
|
|
return 0;
|
|
|
|
+ /* Invalid patch format */
|
|
if (format != SYSEX_PATCH)
|
|
- {
|
|
-/* printk("MIDI Error: Invalid patch format (key) 0x%x\n", format);*/
|
|
return -EINVAL;
|
|
- }
|
|
+
|
|
+ /* Patch header too short */
|
|
if (count < hdr_size)
|
|
- {
|
|
-/* printk("MIDI Error: Patch header too short\n");*/
|
|
return -EINVAL;
|
|
- }
|
|
+
|
|
count -= hdr_size;
|
|
|
|
/*
|
|
- * Copy the header from user space but ignore the first bytes which have
|
|
- * been transferred already.
|
|
+ * Copy the header from user space
|
|
*/
|
|
|
|
- if(copy_from_user(&((char *) &sysex)[offs], &(addr)[offs], hdr_size - offs))
|
|
+ if (copy_from_user(&sysex, addr, hdr_size))
|
|
return -EFAULT;
|
|
-
|
|
- if (count < sysex.len)
|
|
- {
|
|
-/* printk(KERN_WARNING "MIDI Warning: Sysex record too short (%d<%d)\n", count, (int) sysex.len);*/
|
|
+
|
|
+ /* Sysex record too short */
|
|
+ if ((unsigned)count < (unsigned)sysex.len)
|
|
sysex.len = count;
|
|
- }
|
|
- left = sysex.len;
|
|
- src_offs = 0;
|
|
+
|
|
+ left = sysex.len;
|
|
+ src_offs = 0;
|
|
|
|
for (i = 0; i < left && !signal_pending(current); i++)
|
|
{
|
|
diff --git a/sound/oss/midi_synth.h b/sound/oss/midi_synth.h
|
|
index 6bc9d00..b64ddd6 100644
|
|
--- a/sound/oss/midi_synth.h
|
|
+++ b/sound/oss/midi_synth.h
|
|
@@ -8,7 +8,7 @@ int midi_synth_open (int dev, int mode);
|
|
void midi_synth_close (int dev);
|
|
void midi_synth_hw_control (int dev, unsigned char *event);
|
|
int midi_synth_load_patch (int dev, int format, const char __user * addr,
|
|
- int offs, int count, int pmgr_flag);
|
|
+ int count, int pmgr_flag);
|
|
void midi_synth_panning (int dev, int channel, int pressure);
|
|
void midi_synth_aftertouch (int dev, int channel, int pressure);
|
|
void midi_synth_controller (int dev, int channel, int ctrl_num, int value);
|
|
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c
|
|
index 938c48c..407cd67 100644
|
|
--- a/sound/oss/opl3.c
|
|
+++ b/sound/oss/opl3.c
|
|
@@ -820,7 +820,7 @@ static void opl3_hw_control(int dev, unsigned char *event)
|
|
}
|
|
|
|
static int opl3_load_patch(int dev, int format, const char __user *addr,
|
|
- int offs, int count, int pmgr_flag)
|
|
+ int count, int pmgr_flag)
|
|
{
|
|
struct sbi_instrument ins;
|
|
|
|
@@ -830,11 +830,7 @@ static int opl3_load_patch(int dev, int format, const char __user *addr,
|
|
return -EINVAL;
|
|
}
|
|
|
|
- /*
|
|
- * What the fuck is going on here? We leave junk in the beginning
|
|
- * of ins and then check the field pretty close to that beginning?
|
|
- */
|
|
- if(copy_from_user(&((char *) &ins)[offs], addr + offs, sizeof(ins) - offs))
|
|
+ if (copy_from_user(&ins, addr, sizeof(ins)))
|
|
return -EFAULT;
|
|
|
|
if (ins.channel < 0 || ins.channel >= SBFM_MAXINSTR)
|
|
@@ -849,6 +845,10 @@ static int opl3_load_patch(int dev, int format, const char __user *addr,
|
|
|
|
static void opl3_panning(int dev, int voice, int value)
|
|
{
|
|
+
|
|
+ if (voice < 0 || voice >= devc->nr_voice)
|
|
+ return;
|
|
+
|
|
devc->voc[voice].panning = value;
|
|
}
|
|
|
|
@@ -1066,8 +1066,15 @@ static int opl3_alloc_voice(int dev, int chn, int note, struct voice_alloc_info
|
|
|
|
static void opl3_setup_voice(int dev, int voice, int chn)
|
|
{
|
|
- struct channel_info *info =
|
|
- &synth_devs[dev]->chn_info[chn];
|
|
+ struct channel_info *info;
|
|
+
|
|
+ if (voice < 0 || voice >= devc->nr_voice)
|
|
+ return;
|
|
+
|
|
+ if (chn < 0 || chn > 15)
|
|
+ return;
|
|
+
|
|
+ info = &synth_devs[dev]->chn_info[chn];
|
|
|
|
opl3_set_instr(dev, voice, info->pgm_num);
|
|
|
|
diff --git a/sound/oss/sequencer.c b/sound/oss/sequencer.c
|
|
index 5ea1098..30bcfe4 100644
|
|
--- a/sound/oss/sequencer.c
|
|
+++ b/sound/oss/sequencer.c
|
|
@@ -241,7 +241,7 @@ int sequencer_write(int dev, struct file *file, const char __user *buf, int coun
|
|
return -ENXIO;
|
|
|
|
fmt = (*(short *) &event_rec[0]) & 0xffff;
|
|
- err = synth_devs[dev]->load_patch(dev, fmt, buf, p + 4, c, 0);
|
|
+ err = synth_devs[dev]->load_patch(dev, fmt, buf + p, c, 0);
|
|
if (err < 0)
|
|
return err;
|
|
|
|
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
|
|
index 537cfba..863eafe 100644
|
|
--- a/sound/pci/ens1370.c
|
|
+++ b/sound/pci/ens1370.c
|
|
@@ -229,6 +229,7 @@ MODULE_PARM_DESC(lineio, "Line In to Rear Out (0 = auto, 1 = force).");
|
|
#define ES_REG_1371_CODEC 0x14 /* W/R: Codec Read/Write register address */
|
|
#define ES_1371_CODEC_RDY (1<<31) /* codec ready */
|
|
#define ES_1371_CODEC_WIP (1<<30) /* codec register access in progress */
|
|
+#define EV_1938_CODEC_MAGIC (1<<26)
|
|
#define ES_1371_CODEC_PIRD (1<<23) /* codec read/write select register */
|
|
#define ES_1371_CODEC_WRITE(a,d) ((((a)&0x7f)<<16)|(((d)&0xffff)<<0))
|
|
#define ES_1371_CODEC_READS(a) ((((a)&0x7f)<<16)|ES_1371_CODEC_PIRD)
|
|
@@ -603,12 +604,18 @@ static void snd_es1370_codec_write(struct snd_ak4531 *ak4531,
|
|
|
|
#ifdef CHIP1371
|
|
|
|
+static inline bool is_ev1938(struct ensoniq *ensoniq)
|
|
+{
|
|
+ return ensoniq->pci->device == 0x8938;
|
|
+}
|
|
+
|
|
static void snd_es1371_codec_write(struct snd_ac97 *ac97,
|
|
unsigned short reg, unsigned short val)
|
|
{
|
|
struct ensoniq *ensoniq = ac97->private_data;
|
|
- unsigned int t, x;
|
|
+ unsigned int t, x, flag;
|
|
|
|
+ flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
|
|
mutex_lock(&ensoniq->src_mutex);
|
|
for (t = 0; t < POLL_COUNT; t++) {
|
|
if (!(inl(ES_REG(ensoniq, 1371_CODEC)) & ES_1371_CODEC_WIP)) {
|
|
@@ -630,7 +637,8 @@ static void snd_es1371_codec_write(struct snd_ac97 *ac97,
|
|
0x00010000)
|
|
break;
|
|
}
|
|
- outl(ES_1371_CODEC_WRITE(reg, val), ES_REG(ensoniq, 1371_CODEC));
|
|
+ outl(ES_1371_CODEC_WRITE(reg, val) | flag,
|
|
+ ES_REG(ensoniq, 1371_CODEC));
|
|
/* restore SRC reg */
|
|
snd_es1371_wait_src_ready(ensoniq);
|
|
outl(x, ES_REG(ensoniq, 1371_SMPRATE));
|
|
@@ -647,8 +655,9 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
|
|
unsigned short reg)
|
|
{
|
|
struct ensoniq *ensoniq = ac97->private_data;
|
|
- unsigned int t, x, fail = 0;
|
|
+ unsigned int t, x, flag, fail = 0;
|
|
|
|
+ flag = is_ev1938(ensoniq) ? EV_1938_CODEC_MAGIC : 0;
|
|
__again:
|
|
mutex_lock(&ensoniq->src_mutex);
|
|
for (t = 0; t < POLL_COUNT; t++) {
|
|
@@ -671,7 +680,8 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
|
|
0x00010000)
|
|
break;
|
|
}
|
|
- outl(ES_1371_CODEC_READS(reg), ES_REG(ensoniq, 1371_CODEC));
|
|
+ outl(ES_1371_CODEC_READS(reg) | flag,
|
|
+ ES_REG(ensoniq, 1371_CODEC));
|
|
/* restore SRC reg */
|
|
snd_es1371_wait_src_ready(ensoniq);
|
|
outl(x, ES_REG(ensoniq, 1371_SMPRATE));
|
|
@@ -683,6 +693,11 @@ static unsigned short snd_es1371_codec_read(struct snd_ac97 *ac97,
|
|
/* now wait for the stinkin' data (RDY) */
|
|
for (t = 0; t < POLL_COUNT; t++) {
|
|
if ((x = inl(ES_REG(ensoniq, 1371_CODEC))) & ES_1371_CODEC_RDY) {
|
|
+ if (is_ev1938(ensoniq)) {
|
|
+ for (t = 0; t < 100; t++)
|
|
+ inl(ES_REG(ensoniq, CONTROL));
|
|
+ x = inl(ES_REG(ensoniq, 1371_CODEC));
|
|
+ }
|
|
mutex_unlock(&ensoniq->src_mutex);
|
|
return ES_1371_CODEC_READ(x);
|
|
}
|
|
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
|
|
index 8dabab7..7aee900 100644
|
|
--- a/sound/pci/hda/patch_analog.c
|
|
+++ b/sound/pci/hda/patch_analog.c
|
|
@@ -4353,6 +4353,84 @@ static int ad1984a_thinkpad_init(struct hda_codec *codec)
|
|
}
|
|
|
|
/*
|
|
+ * Precision R5500
|
|
+ * 0x12 - HP/line-out
|
|
+ * 0x13 - speaker (mono)
|
|
+ * 0x15 - mic-in
|
|
+ */
|
|
+
|
|
+static struct hda_verb ad1984a_precision_verbs[] = {
|
|
+ /* Unmute main output path */
|
|
+ {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */
|
|
+ {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x1f}, /* 0dB */
|
|
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) + 0x17}, /* 0dB */
|
|
+ /* Analog mixer; mute as default */
|
|
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
|
|
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
|
|
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
|
|
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
|
|
+ {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
|
|
+ /* Select mic as input */
|
|
+ {0x0c, AC_VERB_SET_CONNECT_SEL, 0x1},
|
|
+ {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE + 0x27}, /* 0dB */
|
|
+ /* Configure as mic */
|
|
+ {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
|
|
+ {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x7002}, /* raise mic as default */
|
|
+ /* HP unmute */
|
|
+ {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
|
|
+ /* turn on EAPD */
|
|
+ {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
|
|
+ /* unsolicited event for pin-sense */
|
|
+ {0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT},
|
|
+ { } /* end */
|
|
+};
|
|
+
|
|
+static struct snd_kcontrol_new ad1984a_precision_mixers[] = {
|
|
+ HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT),
|
|
+ HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT),
|
|
+ HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT),
|
|
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT),
|
|
+ HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT),
|
|
+ HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT),
|
|
+ HDA_CODEC_VOLUME("Mic Boost Volume", 0x15, 0x0, HDA_INPUT),
|
|
+ HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT),
|
|
+ HDA_CODEC_VOLUME("Speaker Playback Volume", 0x13, 0x0, HDA_OUTPUT),
|
|
+ HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT),
|
|
+ HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT),
|
|
+ { } /* end */
|
|
+};
|
|
+
|
|
+
|
|
+/* mute internal speaker if HP is plugged */
|
|
+static void ad1984a_precision_automute(struct hda_codec *codec)
|
|
+{
|
|
+ unsigned int present;
|
|
+
|
|
+ present = snd_hda_jack_detect(codec, 0x12);
|
|
+ snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
|
|
+ HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
|
|
+}
|
|
+
|
|
+
|
|
+/* unsolicited event for HP jack sensing */
|
|
+static void ad1984a_precision_unsol_event(struct hda_codec *codec,
|
|
+ unsigned int res)
|
|
+{
|
|
+ if ((res >> 26) != AD1884A_HP_EVENT)
|
|
+ return;
|
|
+ ad1984a_precision_automute(codec);
|
|
+}
|
|
+
|
|
+/* initialize jack-sensing, too */
|
|
+static int ad1984a_precision_init(struct hda_codec *codec)
|
|
+{
|
|
+ ad198x_init(codec);
|
|
+ ad1984a_precision_automute(codec);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
* HP Touchsmart
|
|
* port-A (0x11) - front hp-out
|
|
* port-B (0x14) - unused
|
|
@@ -4481,6 +4559,7 @@ enum {
|
|
AD1884A_MOBILE,
|
|
AD1884A_THINKPAD,
|
|
AD1984A_TOUCHSMART,
|
|
+ AD1984A_PRECISION,
|
|
AD1884A_MODELS
|
|
};
|
|
|
|
@@ -4490,9 +4569,11 @@ static const char * const ad1884a_models[AD1884A_MODELS] = {
|
|
[AD1884A_MOBILE] = "mobile",
|
|
[AD1884A_THINKPAD] = "thinkpad",
|
|
[AD1984A_TOUCHSMART] = "touchsmart",
|
|
+ [AD1984A_PRECISION] = "precision",
|
|
};
|
|
|
|
static struct snd_pci_quirk ad1884a_cfg_tbl[] = {
|
|
+ SND_PCI_QUIRK(0x1028, 0x04ac, "Precision R5500", AD1984A_PRECISION),
|
|
SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE),
|
|
SND_PCI_QUIRK(0x103c, 0x3037, "HP 2230s", AD1884A_LAPTOP),
|
|
SND_PCI_QUIRK(0x103c, 0x3056, "HP", AD1884A_MOBILE),
|
|
@@ -4586,6 +4667,14 @@ static int patch_ad1884a(struct hda_codec *codec)
|
|
codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event;
|
|
codec->patch_ops.init = ad1984a_thinkpad_init;
|
|
break;
|
|
+ case AD1984A_PRECISION:
|
|
+ spec->mixers[0] = ad1984a_precision_mixers;
|
|
+ spec->init_verbs[spec->num_init_verbs++] =
|
|
+ ad1984a_precision_verbs;
|
|
+ spec->multiout.dig_out_nid = 0;
|
|
+ codec->patch_ops.unsol_event = ad1984a_precision_unsol_event;
|
|
+ codec->patch_ops.init = ad1984a_precision_init;
|
|
+ break;
|
|
case AD1984A_TOUCHSMART:
|
|
spec->mixers[0] = ad1984a_touchsmart_mixers;
|
|
spec->init_verbs[0] = ad1984a_touchsmart_verbs;
|
|
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
|
|
index 4d5004e..e33d69e 100644
|
|
--- a/sound/pci/hda/patch_conexant.c
|
|
+++ b/sound/pci/hda/patch_conexant.c
|
|
@@ -3130,6 +3130,8 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
|
|
SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
|
|
SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
|
|
SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
|
|
+ SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
|
|
+ SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
|
|
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
|
|
SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
|
|
{}
|
|
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
|
|
index ec0fa2d..520f94a 100644
|
|
--- a/sound/pci/hda/patch_hdmi.c
|
|
+++ b/sound/pci/hda/patch_hdmi.c
|
|
@@ -1276,6 +1276,39 @@ static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|
stream_tag, format, substream);
|
|
}
|
|
|
|
+static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec,
|
|
+ int channels)
|
|
+{
|
|
+ unsigned int chanmask;
|
|
+ int chan = channels ? (channels - 1) : 1;
|
|
+
|
|
+ switch (channels) {
|
|
+ default:
|
|
+ case 0:
|
|
+ case 2:
|
|
+ chanmask = 0x00;
|
|
+ break;
|
|
+ case 4:
|
|
+ chanmask = 0x08;
|
|
+ break;
|
|
+ case 6:
|
|
+ chanmask = 0x0b;
|
|
+ break;
|
|
+ case 8:
|
|
+ chanmask = 0x13;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Set the audio infoframe channel allocation and checksum fields. The
|
|
+ * channel count is computed implicitly by the hardware. */
|
|
+ snd_hda_codec_write(codec, 0x1, 0,
|
|
+ Nv_VERB_SET_Channel_Allocation, chanmask);
|
|
+
|
|
+ snd_hda_codec_write(codec, 0x1, 0,
|
|
+ Nv_VERB_SET_Info_Frame_Checksum,
|
|
+ (0x71 - chan - chanmask));
|
|
+}
|
|
+
|
|
static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
|
|
struct hda_codec *codec,
|
|
struct snd_pcm_substream *substream)
|
|
@@ -1294,6 +1327,10 @@ static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
|
|
AC_VERB_SET_STREAM_FORMAT, 0);
|
|
}
|
|
|
|
+ /* The audio hardware sends a channel count of 0x7 (8ch) when all the
|
|
+ * streams are disabled. */
|
|
+ nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
|
|
+
|
|
return snd_hda_multi_out_dig_close(codec, &spec->multiout);
|
|
}
|
|
|
|
@@ -1304,37 +1341,16 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|
struct snd_pcm_substream *substream)
|
|
{
|
|
int chs;
|
|
- unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
|
|
+ unsigned int dataDCC1, dataDCC2, channel_id;
|
|
int i;
|
|
|
|
mutex_lock(&codec->spdif_mutex);
|
|
|
|
chs = substream->runtime->channels;
|
|
- chan = chs ? (chs - 1) : 1;
|
|
|
|
- switch (chs) {
|
|
- default:
|
|
- case 0:
|
|
- case 2:
|
|
- chanmask = 0x00;
|
|
- break;
|
|
- case 4:
|
|
- chanmask = 0x08;
|
|
- break;
|
|
- case 6:
|
|
- chanmask = 0x0b;
|
|
- break;
|
|
- case 8:
|
|
- chanmask = 0x13;
|
|
- break;
|
|
- }
|
|
dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
|
|
dataDCC2 = 0x2;
|
|
|
|
- /* set the Audio InforFrame Channel Allocation */
|
|
- snd_hda_codec_write(codec, 0x1, 0,
|
|
- Nv_VERB_SET_Channel_Allocation, chanmask);
|
|
-
|
|
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
|
|
if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
|
|
snd_hda_codec_write(codec,
|
|
@@ -1409,10 +1425,7 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
|
|
}
|
|
}
|
|
|
|
- /* set the Audio Info Frame Checksum */
|
|
- snd_hda_codec_write(codec, 0x1, 0,
|
|
- Nv_VERB_SET_Info_Frame_Checksum,
|
|
- (0x71 - chan - chanmask));
|
|
+ nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs);
|
|
|
|
mutex_unlock(&codec->spdif_mutex);
|
|
return 0;
|
|
@@ -1508,6 +1521,11 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
|
|
spec->multiout.max_channels = 8;
|
|
spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x;
|
|
codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
|
|
+
|
|
+ /* Initialize the audio infoframe channel mask and checksum to something
|
|
+ * valid */
|
|
+ nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
|
|
index c2eb6a7..e164a4b 100644
|
|
--- a/sound/pci/hda/patch_realtek.c
|
|
+++ b/sound/pci/hda/patch_realtek.c
|
|
@@ -1360,7 +1360,7 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
|
|
case 0x10ec0883:
|
|
case 0x10ec0885:
|
|
case 0x10ec0887:
|
|
- case 0x10ec0889:
|
|
+ /*case 0x10ec0889:*/ /* this causes an SPDIF problem */
|
|
alc889_coef_init(codec);
|
|
break;
|
|
case 0x10ec0888:
|
|
@@ -14191,7 +14191,7 @@ static hda_nid_t alc269vb_capsrc_nids[1] = {
|
|
};
|
|
|
|
static hda_nid_t alc269_adc_candidates[] = {
|
|
- 0x08, 0x09, 0x07,
|
|
+ 0x08, 0x09, 0x07, 0x11,
|
|
};
|
|
|
|
#define alc269_modes alc260_modes
|
|
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
|
|
index 671ef8d..aab7765 100644
|
|
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
|
|
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
|
|
@@ -110,12 +110,12 @@ static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
|
|
slave_config.direction = DMA_TO_DEVICE;
|
|
slave_config.dst_addr = dma_params->dma_addr;
|
|
slave_config.dst_addr_width = buswidth;
|
|
- slave_config.dst_maxburst = dma_params->burstsize;
|
|
+ slave_config.dst_maxburst = dma_params->burstsize * buswidth;
|
|
} else {
|
|
slave_config.direction = DMA_FROM_DEVICE;
|
|
slave_config.src_addr = dma_params->dma_addr;
|
|
slave_config.src_addr_width = buswidth;
|
|
- slave_config.src_maxburst = dma_params->burstsize;
|
|
+ slave_config.src_maxburst = dma_params->burstsize * buswidth;
|
|
}
|
|
|
|
ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
|
|
@@ -303,6 +303,11 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
|
|
|
|
static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
|
|
{
|
|
+ struct imx_ssi *ssi = platform_get_drvdata(pdev);
|
|
+
|
|
+ ssi->dma_params_tx.burstsize = 6;
|
|
+ ssi->dma_params_rx.burstsize = 4;
|
|
+
|
|
return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
|
|
}
|
|
|
|
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
|
|
index a4406a1..dc8a875 100644
|
|
--- a/sound/soc/imx/imx-ssi.h
|
|
+++ b/sound/soc/imx/imx-ssi.h
|
|
@@ -234,7 +234,4 @@ void imx_pcm_free(struct snd_pcm *pcm);
|
|
*/
|
|
#define IMX_SSI_DMABUF_SIZE (64 * 1024)
|
|
|
|
-#define DMA_RXFIFO_BURST 0x4
|
|
-#define DMA_TXFIFO_BURST 0x6
|
|
-
|
|
#endif /* _IMX_SSI_H */
|
|
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
|
|
index 784cff5..9027da4 100644
|
|
--- a/sound/soc/pxa/corgi.c
|
|
+++ b/sound/soc/pxa/corgi.c
|
|
@@ -310,7 +310,7 @@ static struct snd_soc_dai_link corgi_dai = {
|
|
.cpu_dai_name = "pxa2xx-i2s",
|
|
.codec_dai_name = "wm8731-hifi",
|
|
.platform_name = "pxa-pcm-audio",
|
|
- .codec_name = "wm8731-codec-0.001b",
|
|
+ .codec_name = "wm8731-codec.0-001b",
|
|
.init = corgi_wm8731_init,
|
|
.ops = &corgi_ops,
|
|
};
|