From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757480AbcB1MwQ (ORCPT ); Sun, 28 Feb 2016 07:52:16 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:35027 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756975AbcB1MwI (ORCPT ); Sun, 28 Feb 2016 07:52:08 -0500 Message-ID: <1456663915.3098.56.camel@decadent.org.uk> Subject: Linux 3.2.78 From: Ben Hutchings To: linux-kernel@vger.kernel.org, Andrew Morton , torvalds@linux-foundation.org, Jiri Slaby , stable@vger.kernel.org Cc: lwn@lwn.net Date: Sun, 28 Feb 2016 12:51:55 +0000 Content-Type: multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature"; boundary="=-MG3KiWKiyB3BB5eI867o" X-Mailer: Evolution 3.18.3-1 Mime-Version: 1.0 X-SA-Exim-Connect-IP: 2a02:8011:400e:2:b06c:6b7a:5449:a1ad X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org --=-MG3KiWKiyB3BB5eI867o Content-Type: multipart/mixed; boundary="=-D5NFU6NFVyTDevrPhqlY" --=-D5NFU6NFVyTDevrPhqlY Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: base64 SSdtIGFubm91bmNpbmcgdGhlIHJlbGVhc2Ugb2YgdGhlIDMuMi43OCBrZXJuZWwuCgpBbGwgdXNl cnMgb2YgdGhlIDMuMiBrZXJuZWwgc2VyaWVzIHNob3VsZCB1cGdyYWRlLgoKVGhlIHVwZGF0ZWQg My4yLnkgZ2l0IHRyZWUgY2FuIGJlIGZvdW5kIGF0OgrCoMKgwqDCoMKgwqDCoMKgaHR0cHM6Ly9n aXQua2VybmVsLm9yZy9wdWIvc2NtL2xpbnV4L2tlcm5lbC9naXQvc3RhYmxlL2xpbnV4LXN0YWJs ZS5naXQgbGludXgtMy4yLnkKYW5kIGNhbiBiZSBicm93c2VkIGF0IHRoZSBub3JtYWwga2VybmVs Lm9yZyBnaXQgd2ViIGJyb3dzZXI6CsKgwqDCoMKgwqDCoMKgwqBodHRwczovL2dpdC5rZXJuZWwu b3JnLz9wPWxpbnV4L2tlcm5lbC9naXQvc3RhYmxlL2xpbnV4LXN0YWJsZS5naXQKClRoZSBkaWZm IGZyb20gMy4yLjc3IGlzIGF0dGFjaGVkIHRvIHRoaXMgbWVzc2FnZS4KCkJlbi4KCi0tLS0tLS0t LS0tLQoKwqBEb2N1bWVudGF0aW9uL3N5c2N0bC9mcy50eHTCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoHzCoMKgMjMgKysrCsKgTWFrZWZpbGXCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqDCoDIgKy0K wqBhcmNoL2FybS9jb21tb24vaWNzdC5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgfMKgwqDCoDkgKy0KwqBhcmNoL3g4Ni9rdm0veDg2LmPCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqAzICstCsKgYXJjaC94ODYv bW0vcGFnZWF0dHIuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzC oMKgwqA0ICstCsKgY3J5cHRvL2FsZ2lmX2hhc2guY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqA0ICstCsKgY3J5cHRvL2FsZ2lmX3NrY2lwaGVy LmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqDCoDUgKy0KwqBj cnlwdG8vY3J5cHRvX3VzZXIuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqB8wqDCoMKgNiArLQrCoGNyeXB0by9zaGFzaC5jwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqA3ICstCsKgZHJpdmVy cy9hdGEvYWhjaS5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqB8wqDCoDIwICsrKwrCoGRyaXZlcnMvYXRhL2xpYmFoY2kuY8KgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqDCoDQgKy0KwqBkcml2ZXJzL2F0YS9saWJh dGEtc2ZmLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgMzIgKyst LQrCoGRyaXZlcnMvZ3B1L2RybS92bXdnZngvdm13Z2Z4X2Rydi5jwqDCoMKgwqDCoMKgwqDCoHzC oMKgwqA3ICsKwqBkcml2ZXJzL2luZmluaWJhbmQvaHcvY3hnYjMvaXdjaF9jbS5jwqDCoMKgwqDC oMKgfMKgwqDCoDQgKy0KwqBkcml2ZXJzL21lZGlhL2R2Yi9mcm9udGVuZHMvdGRhMTAwNHguY8Kg wqDCoMKgwqB8wqDCoMKgOSArKwrCoGRyaXZlcnMvbWVkaWEvdmlkZW8vc2FhNzEzNC9zYWE3MTM0 LWFsc2EuYyB8wqDCoMKgNSArLQrCoGRyaXZlcnMvbmV0L3BwcC9wcHRwLmPCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoDM0ICsrKy0tCsKgZHJpdmVycy9wY2kv cGNpZS9hZXIvYWVyZHJ2LmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqDCoDQgKy0K wqBkcml2ZXJzL3BjaS9wY2llL2Flci9hZXJkcnYuaMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqB8wqDCoMKgMSAtCsKgZHJpdmVycy9wY2kvcGNpZS9hZXIvYWVyZHJ2X2NvcmUuY8KgwqDCoMKg wqDCoMKgwqDCoHzCoMKgwqAyIC0KwqBkcml2ZXJzL3BsYXRmb3JtL3g4Ni9pbnRlbF9zY3VfaXBj dXRpbC5jwqDCoMKgfMKgwqDCoDIgKy0KwqBkcml2ZXJzL3Njc2kvZGV2aWNlX2hhbmRsZXIvc2Nz aV9kaF9yZGFjLmMgfMKgwqDCoDQgKy0KwqBkcml2ZXJzL3Njc2kvc2QuY8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKgNyArLQrCoGRyaXZl cnMvdHR5L3R0eV9pby5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoHzCoMKgMjQgKystCsKgZHJpdmVycy91c2IvY2xhc3MvY2RjLWFjbS5jwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoDExICsrCsKgZHJpdmVycy91c2IvY2xhc3MvY2RjLWFj bS5owqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKgMSArCsKgZHJpdmVycy91 c2IvaG9zdC94aGNpLXBjaS5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKg NCArLQrCoGRyaXZlcnMvdXNiL2hvc3QveGhjaS1yaW5nLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqB8wqDCoDEwIC0tCsKgZHJpdmVycy91c2IvaG9zdC94aGNpLmPCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqDCoDQgKy0KwqBkcml2ZXJzL3VzYi9zZXJp YWwvY3AyMTB4LmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqAxICsKwqBk cml2ZXJzL3VzYi9zZXJpYWwvZnRkaV9zaW8uY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8 wqDCoMKgMSArCsKgZHJpdmVycy91c2Ivc2VyaWFsL2Z0ZGlfc2lvX2lkcy5owqDCoMKgwqDCoMKg wqDCoMKgwqB8wqDCoMKgMSArCsKgZHJpdmVycy91c2Ivc2VyaWFsL29wdGlvbi5jwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoDE2ICsrCsKgZHJpdmVycy91c2Ivc2VyaWFsL3Zp c29yLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqAxMSArLQrCoGRyaXZl cnMvdmlydGlvL3ZpcnRpb19wY2kuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKg wqDCoDIgKwrCoGZzL2J0cmZzL2RlbGF5ZWQtaW5vZGUuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgfMKgwqDCoDMgKy0KwqBmcy9idHJmcy9kZWxheWVkLWlub2RlLmjCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqAyICstCsKgZnMvYnRyZnMv aW5vZGUuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoHzCoMKgMTQgKy0KwqBmcy9vY2ZzMi9kbG0vZGxtcmVjb3ZlcnkuY8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKgMiArCsKgZnMvcGlwZS5jwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDC oDUyICsrKysrKy0KwqBmcy90aW1lcmZkLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqAyICstCsKgaW5jbHVkZS9saW51 eC9ocnRpbWVyLmjCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqAz NCArKysrLQrCoGluY2x1ZGUvbGludXgvcGlwZV9mc19pLmjCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqB8wqDCoMKgNCArCsKgaW5jbHVkZS9saW51eC9zY2hlZC5owqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKgMiArCsKgaW5jbHVkZS9u ZXQvYWZfdW5peC5owqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8 wqDCoMKgNCArLQrCoGluY2x1ZGUvbmV0L3NjbS5owqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqAxICsKwqBpbmNsdWRlL3NvdW5kL3Jhd21p ZGkuaMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKgNCArCsKg a2VybmVsL2hydGltZXIuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoHzCoMKgNTYgKysrKy0tLQrCoGtlcm5lbC9pdGltZXIuY8KgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKgwqDCoDIgKy0K wqBrZXJuZWwvcG9zaXgtdGltZXJzLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoHzCoMKgwqAyICstCsKga2VybmVsL3NjaGVkX2ZhaXIuY8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqA5ICsrCsKga2VybmVsL3N5 c2N0bC5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqB8wqDCoDE0ICsrCsKga2VybmVsL3RpbWUvdGltZXJfbGlzdC5jwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKgMiArLQrCoGxpYi9rbGlzdC5jwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzC oMKgwqA2ICstCsKgbW0vYmFja2luZy1kZXYuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgwqAyICstCsKgbmV0L2NvcmUvc2NtLmPCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgfMKg wqDCoDcgKwrCoG5ldC9yZmtpbGwvY29yZS5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgMTYgKy0KwqBuZXQvc2N0cC9zb2NrZXQuY8KgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoDEwICst CsKgbmV0L3VuaXgvYWZfdW5peC5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqB8wqDCoDI3ICsrKy0KwqBuZXQvdW5peC9nYXJiYWdlLmPCoMKgwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgMTggKystCsKgc291 bmQvY29yZS9vc3MvcGNtX29zcy5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqB8wqDCoDIxICsrLQrCoHNvdW5kL2NvcmUvcmF3bWlkaS5jwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHwgMTM0ICsrKysrKysrKysrKy0tLS0tCsKgc291bmQv Y29yZS9zZXEvb3NzL3NlcV9vc3NfaW5pdC5jwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoMKgMiAr LQrCoHNvdW5kL2NvcmUvc2VxL29zcy9zZXFfb3NzX3N5bnRoLmPCoMKgwqDCoMKgwqDCoMKgwqB8 wqDCoMKgMiArLQrCoHNvdW5kL2NvcmUvc2VxL3NlcV9jbGllbnRtZ3IuY8KgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgfMKgwqDCoDMgKwrCoHNvdW5kL2NvcmUvc2VxL3NlcV9wb3J0cy5jwqDCoMKg wqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHwgMjMzICsrKysrKysrKysrKysrKystLS0tLS0t LS0tLS0tCsKgc291bmQvY29yZS9zZXEvc2VxX3RpbWVyLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKg wqDCoMKgwqDCoMKgfMKgwqA4NyArKysrKysrKy0tLQrCoHNvdW5kL2NvcmUvc2VxL3NlcV92aXJt aWRpLmPCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqB8wqDCoDIzICsrLQrCoHNvdW5kL2Nv cmUvdGltZXIuY8KgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgfMKgwqA3MiArKysrKystLS0KwqBzb3VuZC9kcml2ZXJzL2R1bW15LmPCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoHzCoMKgMzUgKystLS0KwqBzb3VuZC91c2Iv bWlkaS5jwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oMKgfMKgwqDCoDEgLQrCoHRvb2xzL3BlcmYvdXRpbC91aS9icm93c2Vycy9hbm5vdGF0ZS5jwqDC oMKgwqDCoHzCoMKgwqA0ICstCsKgNzIgZmlsZXMgY2hhbmdlZCwgODQzIGluc2VydGlvbnMoKyks IDM1MyBkZWxldGlvbnMoLSkKCkFsYW4gU3Rlcm4gKDEpOgrCoMKgwqDCoMKgwqBTQ1NJOiBmaXgg Y3Jhc2hlcyBpbiBzZCBhbmQgc3IgcnVudGltZSBQTQoKQWxleGFuZHJhIFlhdGVzICgxKToKwqDC oMKgwqDCoMKgYWhjaTogSW50ZWwgRE5WIGRldmljZSBJRHMgU0FUQQoKQW5kcmV5IEtvbm92YWxv diAoMSk6CsKgwqDCoMKgwqDCoEFMU0E6IHVzYi1hdWRpbzogYXZvaWQgZnJlZWluZyB1bWlkaSBv YmplY3QgdHdpY2UKCkJlbiBIdXRjaGluZ3MgKDIpOgrCoMKgwqDCoMKgwqBwaXBlOiBGaXggYnVm ZmVyIG9mZnNldCBhZnRlciBwYXJ0aWFsbHkgZmFpbGVkIHJlYWQKwqDCoMKgwqDCoMKgTGludXgg My4yLjc4CgpEYW4gQ2FycGVudGVyICgxKToKwqDCoMKgwqDCoMKgaW50ZWxfc2N1X2lwY3V0aWw6 IHVuZGVyZmxvdyBpbiBzY3VfcmVnX2FjY2VzcygpCgpEYW5pZWxlIFBhbG1hcyAoMSk6CsKgwqDC oMKgwqDCoFVTQjogc2VyaWFsOiBvcHRpb246IEFkZGluZyBzdXBwb3J0IGZvciBUZWxpdCBMRTky MgoKRGF2aWQgU3RlcmJhICgxKToKwqDCoMKgwqDCoMKgYnRyZnM6IHByb3Blcmx5IHNldCB0aGUg dGVybWluYXRpb24gdmFsdWUgb2YgY3R4LT5wb3MgaW4gcmVhZGRpcgoKRXJpYyBEdW1hemV0ICgx KToKwqDCoMKgwqDCoMKgYWZfdW5peDogZml4IHN0cnVjdCBwaWQgbWVtb3J5IGxlYWsKCkdyZWcg S3JvYWgtSGFydG1hbiAoMSk6CsKgwqDCoMKgwqDCoFVTQjogc2VyaWFsOiBmdGRpX3NpbzogYWRk IHN1cHBvcnQgZm9yIFlhZXN1IFNDVS0xOCBjYWJsZQoKSGFubmVzIEZyZWRlcmljIFNvd2EgKDIp OgrCoMKgwqDCoMKgwqBwcHRwOiBmaXggaWxsZWdhbCBtZW1vcnkgYWNjZXNzIGNhdXNlZCBieSBt dWx0aXBsZSBiaW5kKClzCsKgwqDCoMKgwqDCoHVuaXg6IGNvcnJlY3RseSB0cmFjayBpbi1mbGln aHQgZmRzIGluIHNlbmRpbmcgcHJvY2VzcyB1c2VyX3N0cnVjdAoKSGFubmVzIFJlaW5lY2tlICgx KToKwqDCoMKgwqDCoMKgc2NzaV9kaF9yZGFjOiBhbHdheXMgcmV0cnkgTU9ERSBTRUxFQ1Qgb24g Y29tbWFuZCBsb2NrIHZpb2xhdGlvbgoKSGFyaXByYXNhZCBTICgxKToKwqDCoMKgwqDCoMKgaXdf Y3hnYjM6IEZpeCBpbmNvcnJlY3RseSByZXR1cm5pbmcgZXJyb3Igb24gc3VjY2VzcwoKSGVyYmVy dCBYdSAoMik6CsKgwqDCoMKgwqDCoGNyeXB0bzogc2hhc2ggLSBGaXggaGFzX2tleSBzZXR0aW5n CsKgwqDCoMKgwqDCoGNyeXB0bzogYWxnaWZfc2tjaXBoZXIgLSBEbyBub3QgZGVyZWZlcmVuY2Ug Y3R4IHdpdGhvdXQgc29ja2V0IGxvY2sKCkphbWVzIEJvdHRvbWxleSAoMSk6CsKgwqDCoMKgwqDC oGtsaXN0OiBmaXggc3RhcnRpbmcgcG9pbnQgcmVtb3ZlZCBidWcgaW4ga2xpc3QgaXRlcmF0b3Jz CgpKb2hhbiBIb3ZvbGQgKDEpOgrCoMKgwqDCoMKgwqBVU0I6IHZpc29yOiBmaXggbnVsbC1kZXJl ZiBhdCBwcm9iZQoKSm9oYW5uZXMgQmVyZyAoMSk6CsKgwqDCoMKgwqDCoHJma2lsbDogZml4IHJm a2lsbF9mb3BfcmVhZCB3YWl0X2V2ZW50IHVzYWdlCgpMaW51cyBXYWxsZWlqICgyKToKwqDCoMKg wqDCoMKgQVJNOiA4NTE3LzE6IElDU1Q6IGF2b2lkIGFyaXRobWV0aWMgb3ZlcmZsb3cgaW4gaWNz dF9oeigpCsKgwqDCoMKgwqDCoEFSTTogODUxOS8xOiBJQ1NUOiB0cnkgb3RoZXIgZGl2aWRlbmRz IHRoYW4gMQoKTHUgQmFvbHUgKDIpOgrCoMKgwqDCoMKgwqB1c2I6IGNkYy1hY206IHNlbmQgemVy byBwYWNrZXQgZm9yIGludGVsIDcyNjAgbW9kZW0KwqDCoMKgwqDCoMKgdXNiOiB4aGNpOiBhcHBs eSBYSENJX1BNRV9TVFVDS19RVUlSSyB0byBJbnRlbCBCcm94dG9uLU0gcGxhdGZvcm1zCgpNYXJj ZWxvIFJpY2FyZG8gTGVpdG5lciAoMSk6CsKgwqDCoMKgwqDCoHNjdHA6IGFsbG93IHNldHRpbmcg U0NUUF9TQUNLX0lNTUVESUFURUxZIGJ5IHRoZSBhcHBsaWNhdGlvbgoKTWFya3VzIFRyaXBwZWxz ZG9yZiAoMSk6CsKgwqDCoMKgwqDCoHBlcmYgYW5ub3RhdGUgYnJvd3NlcjogRml4IGJlaGF2aW91 ciBvZiBTaGlmdC1UYWIgd2l0aCBub3RoaW5nIGZvY3Vzc2VkCgpNYXRoaWFzIEtyYXVzZSAoMSk6 CsKgwqDCoMKgwqDCoGNyeXB0bzogdXNlciAtIGxvY2sgY3J5cHRvX2FsZ19saXN0IG9uIGFsZyBk dW1wCgpNYXRoaWFzIE55bWFuICgyKToKwqDCoMKgwqDCoMKgUmV2ZXJ0ICJ4aGNpOiBkb24ndCBm aW5pc2ggYSBURCBpZiB3ZSBnZXQgYSBzaG9ydC10cmFuc2ZlciBldmVudCBtaWQgVEQiCsKgwqDC oMKgwqDCoHhoY2k6IEZpeCBsaXN0IGNvcnJ1cHRpb24gaW4gdXJiIGRlcXVldWUgYXQgaG9zdCBy ZW1vdmFsCgpNYXR0IEZsZW1pbmcgKDEpOgrCoMKgwqDCoMKgwqB4ODYvbW0vcGF0OiBBdm9pZCB0 cnVuY2F0aW9uIHdoZW4gY29udmVydGluZyBjcGEtPm51bXBhZ2VzIHRvIGFkZHJlc3MKCk1hdXJv IENhcnZhbGhvIENoZWhhYiAoMik6CsKgwqDCoMKgwqDCoHRkYTEwMDR4OiBvbmx5IHVwZGF0ZSB0 aGUgZnJvbnRlbmQgcHJvcGVydGllcyBpZiBsb2NrZWQKwqDCoMKgwqDCoMKgc2FhNzEzNC1hbHNh OiBPbmx5IGZyZWVzIHJlZ2lzdGVyZWQgc291bmQgY2FyZHMKCk1pY2hhZWwgUy4gVHNpcmtpbiAo MSk6CsKgwqDCoMKgwqDCoHZpcnRpb19wY2k6IGZpeCB1c2UgYWZ0ZXIgZnJlZSBvbiByZWxlYXNl CgpNaWtlIEdhbGJyYWl0aCAoMSk6CsKgwqDCoMKgwqDCoHNjaGVkOiBmaXggX19zY2hlZF9zZXRz Y2hlZHVsZXIoKSB2cyBsb2FkIGJhbGFuY2luZyByYWNlCgpPbGl2ZXIgTmV1a3VtICgxKToKwqDC oMKgwqDCoMKgY2RjLWFjbTpleGNsdWRlIFNhbXN1bmcgcGhvbmUgMDRlODo2ODVkCgpQYW9sbyBC b256aW5pICgxKToKwqDCoMKgwqDCoMKgS1ZNOiB2bXg6IGZpeCBNUFggZGV0ZWN0aW9uCgpQZXRl ciBEZWRlY2tlciAoMSk6CsKgwqDCoMKgwqDCoFVTQjogY3AyMTB4OiBhZGQgSUQgZm9yIElBSSBV U0IgdG8gUlM0ODUgYWRhcHRvcgoKUGV0ZXIgSHVybGV5ICgxKToKwqDCoMKgwqDCoMKgdHR5OiBG aXggdW5zYWZlIGxkaXNjIHJlZmVyZW5jZSB2aWEgaW9jdGwoVElPQ0dFVEQpCgpSb2IgQ2xhcmsg KDEpOgrCoMKgwqDCoMKgwqBkcm0vdm13Z2Z4OiByZXNwZWN0ICdub21vZGVzZXQnCgpTZWJhc3Rp YW4gQW5kcnplaiBTaWV3aW9yICgxKToKwqDCoMKgwqDCoMKgUENJL0FFUjogRmx1c2ggd29ya3F1 ZXVlIG9uIGRldmljZSByZW1vdmUgdG8gYXZvaWQgdXNlLWFmdGVyLWZyZWUKClRha2FzaGkgSXdh aSAoMTYpOgrCoMKgwqDCoMKgwqBBTFNBOiBzZXE6IEZpeCBpbmNvcnJlY3Qgc2FuaXR5IGNoZWNr IGF0IHNuZF9zZXFfb3NzX3N5bnRoX2NsZWFudXAoKQrCoMKgwqDCoMKgwqBBTFNBOiBzZXE6IERl Z3JhZGUgdGhlIGVycm9yIG1lc3NhZ2UgZm9yIHRvbyBtYW55IG9wZW5zCsKgwqDCoMKgwqDCoEFM U0E6IGR1bW15OiBEaXNhYmxlIHN3aXRjaGluZyB0aW1lciBiYWNrZW5kIHZpYSBzeXNmcwrCoMKg wqDCoMKgwqBBTFNBOiBzZXE6IEZpeCByYWNlIGF0IGNsb3NpbmcgaW4gdmlybWlkaSBkcml2ZXIK wqDCoMKgwqDCoMKgQUxTQTogcmF3bWlkaTogUmVtb3ZlIGtlcm5lbCBXQVJOSU5HIGZvciBOVUxM IHVzZXItc3BhY2UgYnVmZmVyIGNoZWNrCsKgwqDCoMKgwqDCoEFMU0E6IHBjbTogRml4IHBvdGVu dGlhbCBkZWFkbG9jayBpbiBPU1MgZW11bGF0aW9uCsKgwqDCoMKgwqDCoEFMU0E6IHNlcTogRml4 IHlldCBhbm90aGVyIHJhY2VzIGFtb25nIEFMU0EgdGltZXIgYWNjZXNzZXMKwqDCoMKgwqDCoMKg QUxTQTogdGltZXI6IEZpeCBsaW5rIGNvcnJ1cHRpb24gZHVlIHRvIGRvdWJsZSBzdGFydCBvciBz dG9wCsKgwqDCoMKgwqDCoEFMU0E6IHJhd21pZGk6IE1ha2Ugc25kX3Jhd21pZGlfdHJhbnNtaXQo KSByYWNlLWZyZWUKwqDCoMKgwqDCoMKgQUxTQTogcmF3bWlkaTogRml4IHJhY2UgYXQgY29weWlu ZyAmIHVwZGF0aW5nIHRoZSBwb3NpdGlvbgrCoMKgwqDCoMKgwqBBTFNBOiBzZXE6IEZpeCBsb2Nr ZGVwIHdhcm5pbmdzIGR1ZSB0byBkb3VibGUgbXV0ZXggbG9ja3MKwqDCoMKgwqDCoMKgQUxTQTog dGltZXI6IEZpeCBsZWZ0b3ZlciBsaW5rIGF0IGNsb3NpbmcKwqDCoMKgwqDCoMKgQUxTQTogZHVt bXk6IEltcGxlbWVudCB0aW1lciBiYWNrZW5kIHN3aXRjaGluZyBtb3JlIHNhZmVseQrCoMKgwqDC oMKgwqBBTFNBOiB0aW1lcjogRml4IHdyb25nIGluc3RhbmNlIHBhc3NlZCB0byBzbGF2ZSBjYWxs YmFja3MKwqDCoMKgwqDCoMKgQUxTQTogdGltZXI6IEZpeCByYWNlIGJldHdlZW4gc3RvcCBhbmQg aW50ZXJydXB0CsKgwqDCoMKgwqDCoEFMU0E6IHRpbWVyOiBGaXggcmFjZSBhdCBjb25jdXJyZW50 IHJlYWRzCgpUZWp1biBIZW8gKDIpOgrCoMKgwqDCoMKgwqBsaWJhdGE6IGRpc2FibGUgZm9yY2Vk IFBPUlRTX0lNUEwgZm9yID49IEFIQ0kgMS4zCsKgwqDCoMKgwqDCoGxpYmF0YTogZml4IHNmZiBo b3N0IHN0YXRlIG1hY2hpbmUgbG9ja2luZyB3aGlsZSBwb2xsaW5nCgpUZXRzdW8gSGFuZGEgKDEp OgrCoMKgwqDCoMKgwqBtbSwgdm1zdGF0OiBmaXggd3JvbmcgV1Egc2xlZXAgd2hlbiBtZW1vcnkg cmVjbGFpbSBkb2Vzbid0IG1ha2UgYW55IHByb2dyZXNzCgpUaG9tYXMgR2xlaXhuZXIgKDQpOgrC oMKgwqDCoMKgwqBocnRpbWVyOiBIYW5kbGUgcmVtYWluaW5nIHRpbWUgcHJvcGVyIGZvciBUSU1F X0xPV19SRVMKwqDCoMKgwqDCoMKgdGltZXJmZDogSGFuZGxlIHJlbGF0aXZlIHRpbWVycyB3aXRo IENPTkZJR19USU1FX0xPV19SRVMgcHJvcGVyCsKgwqDCoMKgwqDCoHBvc2l4LXRpbWVyczogSGFu ZGxlIHJlbGF0aXZlIHRpbWVycyB3aXRoIENPTkZJR19USU1FX0xPV19SRVMgcHJvcGVyCsKgwqDC oMKgwqDCoGl0aW1lcnM6IEhhbmRsZSByZWxhdGl2ZSB0aW1lcnMgd2l0aCBDT05GSUdfVElNRV9M T1dfUkVTIHByb3BlcgoKVmxhZGlzIERyb25vdiAoMSk6CsKgwqDCoMKgwqDCoFVTQjogc2VyaWFs OiB2aXNvcjogZml4IGNyYXNoIG9uIGRldGVjdGluZyBkZXZpY2Ugd2l0aG91dCB3cml0ZV91cmJz CgpXYW5nLCBSdWkgWSAoMSk6CsKgwqDCoMKgwqDCoGNyeXB0bzogYWxnaWZfaGFzaCAtIHdhaXQg Zm9yIGNyeXB0b19haGFzaF9pbml0KCkgdG8gY29tcGxldGUKCldpbGx5IFRhcnJlYXUgKDEpOgrC oMKgwqDCoMKgwqBwaXBlOiBsaW1pdCB0aGUgcGVyLXVzZXIgYW1vdW50IG9mIHBhZ2VzIGFsbG9j YXRlZCBpbiBwaXBlcwoKWGluIExvbmcgKDEpOgrCoMKgwqDCoMKgwqBzY3RwOiB0cmFuc2xhdGUg bmV0d29yayBvcmRlciB0byBob3N0IG9yZGVyIHdoZW4gdXNlcnMgZ2V0IGEgaG1hY2lkCgp3aWxs eSB0YXJyZWF1ICgxKToKwqDCoMKgwqDCoMKgdW5peDogcHJvcGVybHkgYWNjb3VudCBmb3IgRkRz IHBhc3NlZCBvdmVyIHVuaXggc29ja2V0cwoKeHVlaml1ZmVpICgxKToKwqDCoMKgwqDCoMKgb2Nm czIvZGxtOiBjbGVhciByZWZtYXAgYml0IG9mIHJlY292ZXJ5IGxvY2sgd2hpbGUgZG9pbmcgbG9j YWwgcmVjb3ZlcnkgY2xlYW51cAoKLS0gCkJlbiBIdXRjaGluZ3MKS25vd2xlZGdlIGlzIHBvd2Vy LiAgRnJhbmNlIGlzIGJhY29uLn== --=-D5NFU6NFVyTDevrPhqlY Content-Type: text/x-diff; charset="UTF-8"; name="linux-3.2.78.patch" Content-Disposition: attachment; filename="linux-3.2.78.patch" Content-Transfer-Encoding: quoted-printable diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index b318a7848add..b9cea8fe47f0 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt @@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs: - nr_open - overflowuid - overflowgid +- pipe-user-pages-hard +- pipe-user-pages-soft - suid_dumpable - super-max - super-nr @@ -157,6 +159,27 @@ The default is 65534. =20 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 +pipe-user-pages-hard: + +Maximum total number of pages a non-privileged user may allocate for pipes= . +Once this limit is reached, no new pipes may be allocated until usage goes +below the limit again. When set to 0, no limit is applied, which is the de= fault +setting. + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + +pipe-user-pages-soft: + +Maximum total number of pages a non-privileged user may allocate for pipes +before the pipe size gets limited to a single page. Once this limit is rea= ched, +new pipes will be limited to a single page in size for this user in order = to +limit total memory usage, and trying to increase them using fcntl() will b= e +denied until usage goes below the limit again. The default value allows to +allocate up to 1024 pipes at their default size. When set to 0, no limit i= s +applied. + +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D + suid_dumpable: =20 This value can be used to query and set the core dump mode for setuid diff --git a/Makefile b/Makefile index 4e9b8eec1a1b..e43b86ec72bf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION =3D 3 PATCHLEVEL =3D 2 -SUBLEVEL =3D 77 +SUBLEVEL =3D 78 EXTRAVERSION =3D NAME =3D Saber-toothed Squirrel =20 diff --git a/arch/arm/common/icst.c b/arch/arm/common/icst.c index 2dc6da70ae59..d7ed252708c5 100644 --- a/arch/arm/common/icst.c +++ b/arch/arm/common/icst.c @@ -16,7 +16,7 @@ */ #include #include - +#include #include =20 /* @@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div); =20 unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco) { - return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]); + u64 dividend =3D p->ref * 2 * (u64)(vco.v + 8); + u32 divisor =3D (vco.r + 2) * p->s2div[vco.s]; + + do_div(dividend, divisor); + return (unsigned long)dividend; } =20 EXPORT_SYMBOL(icst_hz); @@ -58,6 +62,7 @@ icst_hz_to_vco(const struct icst_params *p, unsigned long= freq) =20 if (f > p->vco_min && f <=3D p->vco_max) break; + i++; } while (i < 8); =20 if (i >=3D 8) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d47d1537afc4..09dab5bc4995 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5257,9 +5257,10 @@ int kvm_arch_init(void *opaque) goto out; =20 kvm_set_mmio_spte_mask(); - kvm_init_msr_list(); =20 kvm_x86_ops =3D ops; + kvm_init_msr_list(); + kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK, PT_DIRTY_MASK, PT64_NX_MASK, 0); =20 diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index f9e526742fa1..11fbe4498f29 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c @@ -32,7 +32,7 @@ struct cpa_data { unsigned long *vaddr; pgprot_t mask_set; pgprot_t mask_clr; - int numpages; + unsigned long numpages; int flags; unsigned long pfn; unsigned force_split : 1; @@ -820,7 +820,7 @@ static int __change_page_attr_set_clr(struct cpa_data *= cpa, int checkalias) * CPA operation. Either a large page has been * preserved or a single page update happened. */ - BUG_ON(cpa->numpages > numpages); + BUG_ON(cpa->numpages > numpages || !cpa->numpages); numpages -=3D cpa->numpages; if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY)) cpa->curpage++; diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 2dfb0f10e0bb..d11d431251f7 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -56,7 +56,8 @@ static int hash_sendmsg(struct kiocb *unused, struct sock= et *sock, =20 lock_sock(sk); if (!ctx->more) { - err =3D crypto_ahash_init(&ctx->req); + err =3D af_alg_wait_for_completion(crypto_ahash_init(&ctx->req), + &ctx->completion); if (err) goto unlock; } @@ -136,6 +137,7 @@ static ssize_t hash_sendpage(struct socket *sock, struc= t page *page, } else { if (!ctx->more) { err =3D crypto_ahash_init(&ctx->req); + err =3D af_alg_wait_for_completion(err, &ctx->completion); if (err) goto unlock; } diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 45fa6bd9187b..da5d4ed238e2 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -249,8 +249,11 @@ static int skcipher_sendmsg(struct kiocb *unused, stru= ct socket *sock, { struct sock *sk =3D sock->sk; struct alg_sock *ask =3D alg_sk(sk); + struct sock *psk =3D ask->parent; + struct alg_sock *pask =3D alg_sk(psk); struct skcipher_ctx *ctx =3D ask->private; - struct crypto_ablkcipher *tfm =3D crypto_ablkcipher_reqtfm(&ctx->req); + struct ablkcipher_tfm *skc =3D pask->private; + struct crypto_ablkcipher *tfm =3D skc->base; unsigned ivsize =3D crypto_ablkcipher_ivsize(tfm); struct skcipher_sg_list *sgl; struct af_alg_control con =3D {}; diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 5b63b8dd1f9f..a1d586685f5e 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -390,8 +390,12 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, st= ruct nlmsghdr *nlh) if (link->dump =3D=3D NULL) return -EINVAL; =20 - return netlink_dump_start(crypto_nlsk, skb, nlh, + down_read(&crypto_alg_sem); + err =3D netlink_dump_start(crypto_nlsk, skb, nlh, link->dump, link->done, 0); + up_read(&crypto_alg_sem); + + return err; } =20 err =3D nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX, diff --git a/crypto/shash.c b/crypto/shash.c index d15f35019c4b..060e42bf2b37 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -353,11 +353,10 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tf= m) crt->final =3D shash_async_final; crt->finup =3D shash_async_finup; crt->digest =3D shash_async_digest; + crt->setkey =3D shash_async_setkey; + + crt->has_setkey =3D alg->setkey !=3D shash_no_setkey; =20 - if (alg->setkey) { - crt->setkey =3D shash_async_setkey; - crt->has_setkey =3D true; - } if (alg->export) crt->export =3D shash_async_export; if (alg->import) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 71174576eb3b..f2fd6a7392fc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -274,6 +274,26 @@ static const struct pci_device_id ahci_pci_tbl[] =3D { { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */ { PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */ + { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */ + { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */ { PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */ { PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */ { PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index fa3eca351fec..1adb71733d05 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -480,8 +480,8 @@ void ahci_save_initial_config(struct device *dev, } } =20 - /* fabricate port_map from cap.nr_ports */ - if (!port_map) { + /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */ + if (!port_map && vers < 0x10300) { port_map =3D (1 << ahci_nr_ports(cap)) - 1; dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map); =20 diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 22edc9271a3a..cb290af1525b 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struct ata_port *ap= , static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq) { struct ata_port *ap =3D qc->ap; - unsigned long flags; =20 if (ap->ops->error_handler) { if (in_wq) { - spin_lock_irqsave(ap->lock, flags); - /* EH might have kicked in while host lock is * released. */ @@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct ata_queued_cmd= *qc, int in_wq) } else ata_port_freeze(ap); } - - spin_unlock_irqrestore(ap->lock, flags); } else { if (likely(!(qc->err_mask & AC_ERR_HSM))) ata_qc_complete(qc); @@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct ata_queued_cm= d *qc, int in_wq) } } else { if (in_wq) { - spin_lock_irqsave(ap->lock, flags); ata_sff_irq_on(ap); ata_qc_complete(qc); - spin_unlock_irqrestore(ap->lock, flags); } else ata_qc_complete(qc); } @@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap, struct ata= _queued_cmd *qc, { struct ata_link *link =3D qc->dev->link; struct ata_eh_info *ehi =3D &link->eh_info; - unsigned long flags =3D 0; int poll_next; =20 + lockdep_assert_held(ap->lock); + WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) =3D=3D 0); =20 /* Make sure ata_sff_qc_issue() does not throw things @@ -1112,14 +1106,6 @@ fsm_start: } } =20 - /* Send the CDB (atapi) or the first data block (ata pio out). - * During the state transition, interrupt handler shouldn't - * be invoked before the data transfer is complete and - * hsm_task_state is changed. Hence, the following locking. - */ - if (in_wq) - spin_lock_irqsave(ap->lock, flags); - if (qc->tf.protocol =3D=3D ATA_PROT_PIO) { /* PIO data out protocol. * send first data block. @@ -1135,9 +1121,6 @@ fsm_start: /* send CDB */ atapi_send_cdb(ap, qc); =20 - if (in_wq) - spin_unlock_irqrestore(ap->lock, flags); - /* if polling, ata_sff_pio_task() handles the rest. * otherwise, interrupt handler takes over from here. */ @@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct work_struct *wo= rk) u8 status; int poll_next; =20 + spin_lock_irq(ap->lock); + BUG_ON(ap->sff_pio_task_link =3D=3D NULL); /* qc can be NULL if timeout occurred */ qc =3D ata_qc_from_tag(ap, link->active_tag); if (!qc) { ap->sff_pio_task_link =3D NULL; - return; + goto out_unlock; } =20 fsm_start: @@ -1381,11 +1366,14 @@ fsm_start: */ status =3D ata_sff_busy_wait(ap, ATA_BUSY, 5); if (status & ATA_BUSY) { + spin_unlock_irq(ap->lock); ata_msleep(ap, 2); + spin_lock_irq(ap->lock); + status =3D ata_sff_busy_wait(ap, ATA_BUSY, 10); if (status & ATA_BUSY) { ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE); - return; + goto out_unlock; } } =20 @@ -1402,6 +1390,8 @@ fsm_start: */ if (poll_next) goto fsm_start; +out_unlock: + spin_unlock_irq(ap->lock); } =20 /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/v= mwgfx_drv.c index f739fcf35d74..148fa9120c5f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -25,6 +25,7 @@ * *************************************************************************= */ #include +#include =20 #include "drmP.h" #include "vmwgfx_drv.h" @@ -1142,6 +1143,12 @@ static int vmw_probe(struct pci_dev *pdev, const str= uct pci_device_id *ent) static int __init vmwgfx_init(void) { int ret; + +#ifdef CONFIG_VGA_CONSOLE + if (vgacon_text_force()) + return -EINVAL; +#endif + ret =3D drm_pci_init(&driver, &vmw_pci_driver); if (ret) DRM_ERROR("Failed initializing DRM.\n"); diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/= cxgb3/iwch_cm.c index c88b12beef25..997c5a95b02a 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_cm.c +++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c @@ -150,7 +150,7 @@ static int iwch_l2t_send(struct t3cdev *tdev, struct sk= _buff *skb, struct l2t_en error =3D l2t_send(tdev, skb, l2e); if (error < 0) kfree_skb(skb); - return error; + return error < 0 ? error : 0; } =20 int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb) @@ -166,7 +166,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk= _buff *skb) error =3D cxgb3_ofld_send(tdev, skb); if (error < 0) kfree_skb(skb); - return error; + return error < 0 ? error : 0; } =20 static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *sk= b) diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/fro= ntends/tda1004x.c index ea485d923550..7a8b7dbc048b 100644 --- a/drivers/media/dvb/frontends/tda1004x.c +++ b/drivers/media/dvb/frontends/tda1004x.c @@ -898,9 +898,18 @@ static int tda1004x_set_fe(struct dvb_frontend* fe, static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_pa= rameters *fe_params) { struct tda1004x_state* state =3D fe->demodulator_priv; + int status; =20 dprintk("%s\n", __func__); =20 + status =3D tda1004x_read_byte(state, TDA1004X_STATUS_CD); + if (status =3D=3D -1) + return -EIO; + + /* Only update the properties cache if device is locked */ + if (!(status & 8)) + return 0; + // inversion status fe_params->inversion =3D INVERSION_OFF; if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20) diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/vid= eo/saa7134/saa7134-alsa.c index dbcdfbf8aed0..11b0ef3a2858 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -1145,6 +1145,8 @@ static int alsa_device_init(struct saa7134_dev *dev) =20 static int alsa_device_exit(struct saa7134_dev *dev) { + if (!snd_saa7134_cards[dev->nr]) + return 1; =20 snd_card_free(snd_saa7134_cards[dev->nr]); snd_saa7134_cards[dev->nr] =3D NULL; @@ -1194,7 +1196,8 @@ static void saa7134_alsa_exit(void) int idx; =20 for (idx =3D 0; idx < SNDRV_CARDS; idx++) { - snd_card_free(snd_saa7134_cards[idx]); + if (snd_saa7134_cards[idx]) + snd_card_free(snd_saa7134_cards[idx]); } =20 saa7134_dmasound_init =3D NULL; diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 165ee14825b8..cefb47334ac7 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -131,24 +131,27 @@ static int lookup_chan_dst(u16 call_id, __be32 d_addr= ) return i < MAX_CALLID; } =20 -static int add_chan(struct pppox_sock *sock) +static int add_chan(struct pppox_sock *sock, + struct pptp_addr *sa) { static int call_id; =20 spin_lock(&chan_lock); - if (!sock->proto.pptp.src_addr.call_id) { + if (!sa->call_id) { call_id =3D find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1); if (call_id =3D=3D MAX_CALLID) { call_id =3D find_next_zero_bit(callid_bitmap, MAX_CALLID, 1); if (call_id =3D=3D MAX_CALLID) goto out_err; } - sock->proto.pptp.src_addr.call_id =3D call_id; - } else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap)) + sa->call_id =3D call_id; + } else if (test_bit(sa->call_id, callid_bitmap)) { goto out_err; + } =20 - set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap); - rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock); + sock->proto.pptp.src_addr =3D *sa; + set_bit(sa->call_id, callid_bitmap); + rcu_assign_pointer(callid_sock[sa->call_id], sock); spin_unlock(&chan_lock); =20 return 0; @@ -417,7 +420,6 @@ static int pptp_bind(struct socket *sock, struct sockad= dr *uservaddr, struct sock *sk =3D sock->sk; struct sockaddr_pppox *sp =3D (struct sockaddr_pppox *) uservaddr; struct pppox_sock *po =3D pppox_sk(sk); - struct pptp_opt *opt =3D &po->proto.pptp; int error =3D 0; =20 if (sockaddr_len < sizeof(struct sockaddr_pppox)) @@ -425,10 +427,22 @@ static int pptp_bind(struct socket *sock, struct sock= addr *uservaddr, =20 lock_sock(sk); =20 - opt->src_addr =3D sp->sa_addr.pptp; - if (add_chan(po)) + if (sk->sk_state & PPPOX_DEAD) { + error =3D -EALREADY; + goto out; + } + + if (sk->sk_state & PPPOX_BOUND) { error =3D -EBUSY; + goto out; + } + + if (add_chan(po, &sp->sa_addr.pptp)) + error =3D -EBUSY; + else + sk->sk_state |=3D PPPOX_BOUND; =20 +out: release_sock(sk); return error; } @@ -499,7 +513,7 @@ static int pptp_connect(struct socket *sock, struct soc= kaddr *uservaddr, } =20 opt->dst_addr =3D sp->sa_addr.pptp; - sk->sk_state =3D PPPOX_CONNECTED; + sk->sk_state |=3D PPPOX_CONNECTED; =20 end: release_sock(sk); diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c index 58ad7917553c..8cc54f24d0aa 100644 --- a/drivers/pci/pcie/aer/aerdrv.c +++ b/drivers/pci/pcie/aer/aerdrv.c @@ -263,7 +263,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device= *dev) rpc->rpd =3D dev; INIT_WORK(&rpc->dpc_handler, aer_isr); mutex_init(&rpc->rpc_mutex); - init_waitqueue_head(&rpc->wait_release); =20 /* Use PCIe bus function to store rpc into PCIe device */ set_service_data(dev, rpc); @@ -286,8 +285,7 @@ static void aer_remove(struct pcie_device *dev) if (rpc->isr) free_irq(dev->irq, dev); =20 - wait_event(rpc->wait_release, rpc->prod_idx =3D=3D rpc->cons_idx); - + flush_work(&rpc->dpc_handler); aer_disable_rootport(rpc); kfree(rpc); set_service_data(dev, NULL); diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 94a7598eb262..9c611f1bc56a 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h @@ -76,7 +76,6 @@ struct aer_rpc { * recovery on the same * root port hierarchy */ - wait_queue_head_t wait_release; }; =20 struct aer_broadcast_data { diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerd= rv_core.c index ee82c559092a..21addfa2f89e 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -823,8 +823,6 @@ void aer_isr(struct work_struct *work) while (get_e_source(rpc, &e_src)) aer_isr_one_error(p_device, &e_src); mutex_unlock(&rpc->rpc_mutex); - - wake_up(&rpc->wait_release); } =20 /** diff --git a/drivers/platform/x86/intel_scu_ipcutil.c b/drivers/platform/x8= 6/intel_scu_ipcutil.c index 2d0f9136ea9a..6bfc4327eec6 100644 --- a/drivers/platform/x86/intel_scu_ipcutil.c +++ b/drivers/platform/x86/intel_scu_ipcutil.c @@ -52,7 +52,7 @@ struct scu_ipc_data { =20 static int scu_reg_access(u32 cmd, struct scu_ipc_data *data) { - int count =3D data->count; + unsigned int count =3D data->count; =20 if (count =3D=3D 0 || count =3D=3D 3 || count > 4) return -EINVAL; diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/devi= ce_handler/scsi_dh_rdac.c index 1d3127920063..0d289009fe3b 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -573,7 +573,7 @@ static int mode_select_handle_sense(struct scsi_device = *sdev, /* * Command Lock contention */ - err =3D SCSI_DH_RETRY; + err =3D SCSI_DH_IMM_RETRY; break; default: break; @@ -623,6 +623,8 @@ retry: err =3D mode_select_handle_sense(sdev, h->sense); if (err =3D=3D SCSI_DH_RETRY && retry_cnt--) goto retry; + if (err =3D=3D SCSI_DH_IMM_RETRY) + goto retry; } if (err =3D=3D SCSI_DH_OK) { h->state =3D RDAC_STATE_ACTIVE; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a50825ba4909..9a4f52d8e1db 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2767,8 +2767,8 @@ static int sd_suspend(struct device *dev, pm_message_= t mesg) struct scsi_disk *sdkp =3D scsi_disk_get_from_dev(dev); int ret =3D 0; =20 - if (!sdkp) - return 0; /* this can happen */ + if (!sdkp) /* E.g.: runtime suspend following sd_remove() */ + return 0; =20 if (sdkp->WCE) { sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); @@ -2792,6 +2792,9 @@ static int sd_resume(struct device *dev) struct scsi_disk *sdkp =3D scsi_disk_get_from_dev(dev); int ret =3D 0; =20 + if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ + return 0; + if (!sdkp->device->manage_start_stop) goto done; =20 diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6ab03229c837..1f9ee25b635e 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -2475,6 +2475,28 @@ static int tiocsetd(struct tty_struct *tty, int __us= er *p) } =20 /** + * tiocgetd - get line discipline + * @tty: tty device + * @p: pointer to user data + * + * Retrieves the line discipline id directly from the ldisc. + * + * Locking: waits for ldisc reference (in case the line discipline + * is changing or the tty is being hungup) + */ + +static int tiocgetd(struct tty_struct *tty, int __user *p) +{ + struct tty_ldisc *ld; + int ret; + + ld =3D tty_ldisc_ref_wait(tty); + ret =3D put_user(ld->ops->num, p); + tty_ldisc_deref(ld); + return ret; +} + +/** * send_break - performed time break * @tty: device to break on * @duration: timeout in mS @@ -2684,7 +2706,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, u= nsigned long arg) case TIOCGSID: return tiocgsid(tty, real_tty, p); case TIOCGETD: - return put_user(tty->ldisc->ops->num, (int __user *)p); + return tiocgetd(tty, p); case TIOCSETD: return tiocsetd(tty, p); case TIOCVHANGUP: diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 660c3349ea73..bbb217495917 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1237,6 +1237,8 @@ made_compressed_probe: usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd); snd->urb->transfer_flags |=3D URB_NO_TRANSFER_DMA_MAP; + if (quirks & SEND_ZERO_PACKET) + snd->urb->transfer_flags |=3D URB_ZERO_PACKET; snd->instance =3D acm; } =20 @@ -1666,6 +1668,11 @@ static const struct usb_device_id acm_ids[] =3D { .driver_info =3D NO_DATA_INTERFACE, }, =20 + /*Samsung phone in firmware update mode */ + { USB_DEVICE(0x04e8, 0x685d), + .driver_info =3D IGNORE_DEVICE, + }, + /* Exclude Infineon Flash Loader utility */ { USB_DEVICE(0x058b, 0x0041), .driver_info =3D IGNORE_DEVICE, @@ -1689,6 +1696,10 @@ static const struct usb_device_id acm_ids[] =3D { { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_ACM_PROTO_AT_CDMA) }, =20 + { USB_DEVICE(0x1519, 0x0452), /* Intel 7260 modem */ + .driver_info =3D SEND_ZERO_PACKET, + }, + { } }; =20 diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 9af5ad24c7b9..dfd66bb5977a 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -129,3 +129,4 @@ struct acm { #define NO_DATA_INTERFACE 16 #define IGNORE_DEVICE 32 #define CLEAR_HALT_CONDITIONS BIT(7) +#define SEND_ZERO_PACKET BIT(8) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 5223884e9e92..244e1b12259d 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -39,6 +39,7 @@ #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f +#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8 =20 static const char hcd_name[] =3D "xhci_hcd"; =20 @@ -132,7 +133,8 @@ static void xhci_pci_quirks(struct device *dev, struct = xhci_hcd *xhci) if (pdev->vendor =3D=3D PCI_VENDOR_ID_INTEL && (pdev->device =3D=3D PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI || pdev->device =3D=3D PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI || - pdev->device =3D=3D PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) { + pdev->device =3D=3D PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI || + pdev->device =3D=3D PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) { xhci->quirks |=3D XHCI_PME_STUCK_QUIRK; } if (pdev->vendor =3D=3D PCI_VENDOR_ID_ETRON && diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9f57111a3e43..5fdb85fba447 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2187,10 +2187,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhc= i, struct xhci_td *td, EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); /* Fast path - was this the last TRB in the TD for this URB? */ if (event_trb =3D=3D td->last_trb) { - if (td->urb_length_set && trb_comp_code =3D=3D COMP_SHORT_TX) - return finish_td(xhci, td, event_trb, event, ep, - status, false); - if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) !=3D 0) { td->urb->actual_length =3D td->urb->transfer_buffer_length - @@ -2242,12 +2238,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhc= i, struct xhci_td *td, td->urb->actual_length +=3D TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); - - if (trb_comp_code =3D=3D COMP_SHORT_TX) { - xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n"); - td->urb_length_set =3D true; - return 0; - } } =20 return finish_td(xhci, td, event_trb, event, ep, status, false); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a1f90c7fb564..cfd5d3a6d34d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1533,7 +1533,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb = *urb, int status) if (temp =3D=3D 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) { xhci_dbg(xhci, "HW died, freeing TD.\n"); urb_priv =3D urb->hcpriv; - for (i =3D urb_priv->td_cnt; i < urb_priv->length; i++) { + for (i =3D urb_priv->td_cnt; + i < urb_priv->length && xhci->devs[urb->dev->slot_id]; + i++) { td =3D urb_priv->td[i]; if (!list_empty(&td->td_list)) list_del_init(&td->td_list); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2d622d7ba534..a30b188f914a 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -104,6 +104,7 @@ static const struct usb_device_id id_table[] =3D { { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Ba= by-JTAG */ + { USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adap= tor */ { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Ba= by-LIN */ { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ { USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 4ffaa9d1087e..509275766f5e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -848,6 +848,7 @@ static struct usb_device_id id_table_combined [] =3D { { USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID), .driver_info =3D (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) }, + { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) }, { USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) }, =20 /* Papouch devices based on FTDI chip */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_si= o_ids.h index 7d11642430c6..f9d55c4f5091 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -615,6 +615,7 @@ */ #define RATOC_VENDOR_ID 0x0584 #define RATOC_PRODUCT_ID_USB60F 0xb020 +#define RATOC_PRODUCT_ID_SCU18 0xb03a =20 /* * Acton Research Corp. diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 5a311692f983..0aa025f1d5fd 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -269,6 +269,8 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 #define TELIT_PRODUCT_UE910_V2 0x1012 +#define TELIT_PRODUCT_LE922_USBCFG0 0x1042 +#define TELIT_PRODUCT_LE922_USBCFG3 0x1043 #define TELIT_PRODUCT_LE920 0x1200 #define TELIT_PRODUCT_LE910 0x1201 =20 @@ -621,6 +623,16 @@ static const struct option_blacklist_info telit_le920_= blacklist =3D { .reserved =3D BIT(1) | BIT(5), }; =20 +static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = =3D { + .sendsetup =3D BIT(2), + .reserved =3D BIT(0) | BIT(1) | BIT(3), +}; + +static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = =3D { + .sendsetup =3D BIT(0), + .reserved =3D BIT(1) | BIT(2) | BIT(3), +}; + static const struct usb_device_id option_ids[] =3D { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -1166,6 +1178,10 @@ static const struct usb_device_id option_ids[] =3D { { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0), + .driver_info =3D (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3), + .driver_info =3D (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910), .driver_info =3D (kernel_ulong_t)&telit_le910_blacklist }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 80a6ff69eb83..ea74788c6fd6 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -587,6 +587,11 @@ static int treo_attach(struct usb_serial *serial) =20 dbg("%s", __func__); =20 + if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) { + dev_err(&serial->interface->dev, "missing endpoints\n"); + return -ENODEV; + } + /* * It appears that Treos and Kyoceras want to use the * 1st bulk in endpoint to communicate with the 2nd bulk out endpoint, @@ -635,8 +640,10 @@ static int clie_5_attach(struct usb_serial *serial) */ =20 /* some sanity check */ - if (serial->num_ports < 2) - return -1; + if (serial->num_bulk_out < 2) { + dev_err(&serial->interface->dev, "missing bulk out endpoints\n"); + return -ENODEV; + } =20 /* port 0 now uses the modified endpoint Address */ port =3D serial->port[0]; diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 13f6cd8fffd2..49cc7ada4fc5 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -698,6 +698,7 @@ out: static void __devexit virtio_pci_remove(struct pci_dev *pci_dev) { struct virtio_pci_device *vp_dev =3D pci_get_drvdata(pci_dev); + struct device *dev =3D get_device(&vp_dev->vdev.dev); =20 unregister_virtio_device(&vp_dev->vdev); =20 @@ -706,6 +707,7 @@ static void __devexit virtio_pci_remove(struct pci_dev = *pci_dev) pci_iounmap(pci_dev, vp_dev->ioaddr); pci_release_regions(pci_dev); pci_disable_device(pci_dev); + put_device(dev); } =20 #ifdef CONFIG_PM diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 9c1eccc2c503..dd9b557ab6d5 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1593,7 +1593,7 @@ int btrfs_should_delete_dir_index(struct list_head *d= el_list, */ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, filldir_t filldir, - struct list_head *ins_list) + struct list_head *ins_list, bool *emitted) { struct btrfs_dir_item *di; struct btrfs_delayed_item *curr, *next; @@ -1637,6 +1637,7 @@ int btrfs_readdir_delayed_dir_index(struct file *filp= , void *dirent, =20 if (over) return 1; + *emitted =3D true; } return 0; } diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 7083d08b2a21..cacdc5644ebf 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -133,7 +133,7 @@ int btrfs_should_delete_dir_index(struct list_head *del= _list, u64 index); int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, filldir_t filldir, - struct list_head *ins_list); + struct list_head *ins_list, bool *emitted); =20 /* for init */ int __init btrfs_delayed_inode_init(void); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e4c38d49404c..007d487eeb6c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4111,6 +4111,7 @@ static int btrfs_real_readdir(struct file *filp, void= *dirent, char *name_ptr; int name_len; int is_curr =3D 0; /* filp->f_pos points to the current index? */ + bool emitted; =20 /* FIXME, use a real flag for deciding about the key type */ if (root->fs_info->tree_root =3D=3D root) @@ -4153,6 +4154,7 @@ static int btrfs_real_readdir(struct file *filp, void= *dirent, if (ret < 0) goto err; =20 + emitted =3D false; while (1) { leaf =3D path->nodes[0]; slot =3D path->slots[0]; @@ -4254,6 +4256,7 @@ skip: =20 if (over) goto nopos; + emitted =3D true; di_len =3D btrfs_dir_name_len(leaf, di) + btrfs_dir_data_len(leaf, di) + sizeof(*di); di_cur +=3D di_len; @@ -4267,11 +4270,20 @@ next: if (is_curr) filp->f_pos++; ret =3D btrfs_readdir_delayed_dir_index(filp, dirent, filldir, - &ins_list); + &ins_list, &emitted); if (ret) goto nopos; } =20 + /* + * If we haven't emitted any dir entry, we must not touch filp->f_pos as + * it was was set to the termination value in previous call. We assume + * that "." and ".." were emitted if we reach this point and set the + * termination value as well for an empty directory. + */ + if (filp->f_pos > 2 && !emitted) + goto nopos; + /* Reached end of directory/root. Bump pos past the last item. */ if (key_type =3D=3D BTRFS_DIR_INDEX_KEY) /* diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c index 0e5013ed7f13..bf3f00809ac2 100644 --- a/fs/ocfs2/dlm/dlmrecovery.c +++ b/fs/ocfs2/dlm/dlmrecovery.c @@ -2333,6 +2333,8 @@ static void dlm_do_local_recovery_cleanup(struct dlm_= ctxt *dlm, u8 dead_node) break; } } + dlm_lockres_clear_refmap_bit(dlm, res, + dead_node); spin_unlock(&res->spinlock); continue; } diff --git a/fs/pipe.c b/fs/pipe.c index d2cbeff6cb32..bf3a99302d2a 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -35,6 +35,12 @@ unsigned int pipe_max_size =3D 1048576; */ unsigned int pipe_min_size =3D PAGE_SIZE; =20 +/* Maximum allocatable pages per user. Hard limit is unset by default, sof= t + * matches default values. + */ +unsigned long pipe_user_pages_hard; +unsigned long pipe_user_pages_soft =3D PIPE_DEF_BUFFERS * INR_OPEN_CUR; + /* * We use a start+len construction, which provides full use of the=20 * allocated memory. @@ -389,6 +395,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov, void *addr; size_t chars =3D buf->len, remaining; int error, atomic; + int offset; =20 if (chars > total_len) chars =3D total_len; @@ -402,9 +409,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov= , =20 atomic =3D !iov_fault_in_pages_write(iov, chars); remaining =3D chars; + offset =3D buf->offset; redo: addr =3D ops->map(pipe, buf, atomic); - error =3D pipe_iov_copy_to_user(iov, addr, &buf->offset, + error =3D pipe_iov_copy_to_user(iov, addr, &offset, &remaining, atomic); ops->unmap(pipe, buf, addr); if (unlikely(error)) { @@ -420,6 +428,7 @@ redo: break; } ret +=3D chars; + buf->offset +=3D chars; buf->len -=3D chars; =20 /* Was it a packet buffer? Clean up and exit */ @@ -929,20 +938,49 @@ const struct file_operations rdwr_pipefifo_fops =3D { .fasync =3D pipe_rdwr_fasync, }; =20 +static void account_pipe_buffers(struct pipe_inode_info *pipe, + unsigned long old, unsigned long new) +{ + atomic_long_add(new - old, &pipe->user->pipe_bufs); +} + +static bool too_many_pipe_buffers_soft(struct user_struct *user) +{ + return pipe_user_pages_soft && + atomic_long_read(&user->pipe_bufs) >=3D pipe_user_pages_soft; +} + +static bool too_many_pipe_buffers_hard(struct user_struct *user) +{ + return pipe_user_pages_hard && + atomic_long_read(&user->pipe_bufs) >=3D pipe_user_pages_hard; +} + struct pipe_inode_info * alloc_pipe_info(struct inode *inode) { struct pipe_inode_info *pipe; =20 pipe =3D kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); if (pipe) { - pipe->bufs =3D kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GF= P_KERNEL); + unsigned long pipe_bufs =3D PIPE_DEF_BUFFERS; + struct user_struct *user =3D get_current_user(); + + if (!too_many_pipe_buffers_hard(user)) { + if (too_many_pipe_buffers_soft(user)) + pipe_bufs =3D 1; + pipe->bufs =3D kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERN= EL); + } + if (pipe->bufs) { init_waitqueue_head(&pipe->wait); pipe->r_counter =3D pipe->w_counter =3D 1; pipe->inode =3D inode; - pipe->buffers =3D PIPE_DEF_BUFFERS; + pipe->buffers =3D pipe_bufs; + pipe->user =3D user; + account_pipe_buffers(pipe, 0, pipe_bufs); return pipe; } + free_uid(user); kfree(pipe); } =20 @@ -953,6 +991,8 @@ void __free_pipe_info(struct pipe_inode_info *pipe) { int i; =20 + account_pipe_buffers(pipe, pipe->buffers, 0); + free_uid(pipe->user); for (i =3D 0; i < pipe->buffers; i++) { struct pipe_buffer *buf =3D pipe->bufs + i; if (buf->ops) @@ -1201,6 +1241,7 @@ static long pipe_set_size(struct pipe_inode_info *pip= e, unsigned long nr_pages) memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer)); } =20 + account_pipe_buffers(pipe, pipe->buffers, nr_pages); pipe->curbuf =3D 0; kfree(pipe->bufs); pipe->bufs =3D bufs; @@ -1274,6 +1315,11 @@ long pipe_fcntl(struct file *file, unsigned int cmd,= unsigned long arg) if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) { ret =3D -EPERM; goto out; + } else if ((too_many_pipe_buffers_hard(pipe->user) || + too_many_pipe_buffers_soft(pipe->user)) && + !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { + ret =3D -EPERM; + goto out; } ret =3D pipe_set_size(pipe, nr_pages); break; diff --git a/fs/timerfd.c b/fs/timerfd.c index dffeb3795af1..113208c3a874 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c @@ -123,7 +123,7 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx= *ctx) { ktime_t remaining; =20 - remaining =3D hrtimer_expires_remaining(&ctx->tmr); + remaining =3D hrtimer_expires_remaining_adjusted(&ctx->tmr); return remaining.tv64 < 0 ? ktime_set(0, 0): remaining; } =20 diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index cc07d2777bbe..9942977e5a06 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -96,6 +96,7 @@ enum hrtimer_restart { * @function: timer expiry callback function * @base: pointer to the timer base (per cpu and per clock) * @state: state information (See bit values above) + * @is_rel: Set if the timer was armed relative * @start_site: timer statistics field to store the site where the timer * was started * @start_comm: timer statistics field to store the name of the process wh= ich @@ -110,7 +111,8 @@ struct hrtimer { ktime_t _softexpires; enum hrtimer_restart (*function)(struct hrtimer *); struct hrtimer_clock_base *base; - unsigned long state; + u8 state; + u8 is_rel; #ifdef CONFIG_TIMER_STATS int start_pid; void *start_site; @@ -315,6 +317,29 @@ static inline void clock_was_set_delayed(void) { } =20 #endif =20 +static inline ktime_t +__hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t = now) +{ + ktime_t rem =3D ktime_sub(timer->node.expires, now); + + /* + * Adjust relative timers for the extra we added in + * hrtimer_start_range_ns() to prevent short timeouts. + */ +#ifdef CONFIG_TIME_LOW_RES + if (timer->is_rel) + rem =3D ktime_sub(rem, KTIME_LOW_RES); +#endif + return rem; +} + +static inline ktime_t +hrtimer_expires_remaining_adjusted(const struct hrtimer *timer) +{ + return __hrtimer_expires_remaining_adjusted(timer, + timer->base->get_time()); +} + extern void clock_was_set(void); #ifdef CONFIG_TIMERFD extern void timerfd_clock_was_set(void); @@ -383,7 +408,12 @@ static inline int hrtimer_restart(struct hrtimer *time= r) } =20 /* Query timers: */ -extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer); +extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool a= djust); + +static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer) +{ + return __hrtimer_get_remaining(timer, false); +} extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *t= p); =20 extern ktime_t hrtimer_get_next_event(void); diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 8778c26c942e..0e8ecbddb21e 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -43,6 +43,7 @@ struct pipe_buffer { * @fasync_writers: writer side fasync * @inode: inode this pipe is attached to * @bufs: the circular array of pipe buffers + * @user: the user who created this pipe **/ struct pipe_inode_info { wait_queue_head_t wait; @@ -57,6 +58,7 @@ struct pipe_inode_info { struct fasync_struct *fasync_writers; struct inode *inode; struct pipe_buffer *bufs; + struct user_struct *user; }; =20 /* @@ -142,6 +144,8 @@ void pipe_unlock(struct pipe_inode_info *); void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); =20 extern unsigned int pipe_max_size, pipe_min_size; +extern unsigned long pipe_user_pages_hard; +extern unsigned long pipe_user_pages_soft; int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t = *); =20 =20 diff --git a/include/linux/sched.h b/include/linux/sched.h index 9b9ac291f66e..fb76ee7dbd9d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -709,6 +709,8 @@ struct user_struct { unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */ #endif unsigned long locked_shm; /* How many pages of mlocked shm ? */ + unsigned long unix_inflight; /* How many files in flight in unix sockets = */ + atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers= */ =20 #ifdef CONFIG_KEYS struct key *uid_keyring; /* UID specific keyring */ diff --git a/include/net/af_unix.h b/include/net/af_unix.h index f4842f7afaa5..a69bfee1dd27 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -6,8 +6,8 @@ #include #include =20 -extern void unix_inflight(struct file *fp); -extern void unix_notinflight(struct file *fp); +extern void unix_inflight(struct user_struct *user, struct file *fp); +extern void unix_notinflight(struct user_struct *user, struct file *fp); extern void unix_gc(void); extern void wait_for_unix_gc(void); extern struct sock *unix_get_socket(struct file *filp); diff --git a/include/net/scm.h b/include/net/scm.h index 5da0a7b7eb41..9822a68ae148 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -16,6 +16,7 @@ struct scm_fp_list { struct list_head list; short count; short max; + struct user_struct *user; struct file *fp[SCM_MAX_FD]; }; =20 diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index 6b14359d9fed..680a47f3c639 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -167,6 +167,10 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_subst= ream *substream, int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int = count); int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, unsigned char *buffer, int count); +int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, + unsigned char *buffer, int count); +int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, + int count); =20 /* main midi functions */ =20 diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index d9ce3d484231..6918c031363e 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -910,7 +910,7 @@ static int enqueue_hrtimer(struct hrtimer *timer, */ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, - unsigned long newstate, int reprogram) + u8 newstate, int reprogram) { struct timerqueue_node *next_timer; if (!(timer->state & HRTIMER_STATE_ENQUEUED)) @@ -944,7 +944,7 @@ static inline int remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base) { if (hrtimer_is_queued(timer)) { - unsigned long state; + u8 state; int reprogram; =20 /* @@ -970,6 +970,22 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_c= lock_base *base) return 0; } =20 +static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t= tim, + const enum hrtimer_mode mode) +{ +#ifdef CONFIG_TIME_LOW_RES + /* + * CONFIG_TIME_LOW_RES indicates that the system has no way to return + * granular time values. For relative timers we add KTIME_LOW_RES + * (i.e. one jiffie) to prevent short timeouts. + */ + timer->is_rel =3D mode & HRTIMER_MODE_REL; + if (timer->is_rel) + tim =3D ktime_add_safe(tim, KTIME_LOW_RES); +#endif + return tim; +} + int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, unsigned long delta_ns, const enum hrtimer_mode mode, int wakeup) @@ -983,19 +999,10 @@ int __hrtimer_start_range_ns(struct hrtimer *timer, k= time_t tim, /* Remove an active timer from the queue: */ ret =3D remove_hrtimer(timer, base); =20 - if (mode & HRTIMER_MODE_REL) { + if (mode & HRTIMER_MODE_REL) tim =3D ktime_add_safe(tim, base->get_time()); - /* - * CONFIG_TIME_LOW_RES is a temporary way for architectures - * to signal that they simply return xtime in - * do_gettimeoffset(). In this case we want to round up by - * resolution when starting a relative timer, to avoid short - * timeouts. This will go away with the GTOD framework. - */ -#ifdef CONFIG_TIME_LOW_RES - tim =3D ktime_add_safe(tim, base->resolution); -#endif - } + + tim =3D hrtimer_update_lowres(timer, tim, mode); =20 hrtimer_set_expires_range_ns(timer, tim, delta_ns); =20 @@ -1120,19 +1127,25 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel); /** * hrtimer_get_remaining - get remaining time for the timer * @timer: the timer to read + * @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=3Dy */ -ktime_t hrtimer_get_remaining(const struct hrtimer *timer) +ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust) { unsigned long flags; ktime_t rem; =20 lock_hrtimer_base(timer, &flags); - rem =3D hrtimer_expires_remaining(timer); +#ifdef CONFIG_TIME_LOW_RES + if (adjust) + rem =3D hrtimer_expires_remaining_adjusted(timer); + else +#endif + rem =3D hrtimer_expires_remaining(timer); unlock_hrtimer_base(timer, &flags); =20 return rem; } -EXPORT_SYMBOL_GPL(hrtimer_get_remaining); +EXPORT_SYMBOL_GPL(__hrtimer_get_remaining); =20 #ifdef CONFIG_NO_HZ /** @@ -1249,6 +1262,15 @@ static void __run_hrtimer(struct hrtimer *timer, kti= me_t *now) fn =3D timer->function; =20 /* + * Clear the 'is relative' flag for the TIME_LOW_RES case. If the + * timer is restarted with a period then it becomes an absolute + * timer. If its not restarted it does not matter. + */ +#ifdef CONFIG_TIME_LOW_RES + timer->is_rel =3D false; +#endif + + /* * Because we run timers from hardirq context, there is no chance * they get migrated to another cpu, therefore its safe to unlock * the timer base. diff --git a/kernel/itimer.c b/kernel/itimer.c index d802883153da..c6f948960a51 100644 --- a/kernel/itimer.c +++ b/kernel/itimer.c @@ -26,7 +26,7 @@ */ static struct timeval itimer_get_remtime(struct hrtimer *timer) { - ktime_t rem =3D hrtimer_get_remaining(timer); + ktime_t rem =3D __hrtimer_get_remaining(timer, true); =20 /* * Racy but safe: if the itimer expires after the above diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 02824a5c2693..67661832ac2b 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -706,7 +706,7 @@ common_timer_get(struct k_itimer *timr, struct itimersp= ec *cur_setting) (timr->it_sigev_notify & ~SIGEV_THREAD_ID) =3D=3D SIGEV_NONE)) timr->it_overrun +=3D (unsigned int) hrtimer_forward(timer, now, iv); =20 - remaining =3D ktime_sub(hrtimer_get_expires(timer), now); + remaining =3D __hrtimer_expires_remaining_adjusted(timer, now); /* Return 0 only, when the timer is expired and not pending */ if (remaining.tv64 <=3D 0) { /* diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 4c6dae17cd1e..98e103988aad 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -2791,6 +2791,7 @@ int can_migrate_task(struct task_struct *p, struct rq= *rq, int this_cpu, * 1) running (obviously), or * 2) cannot be migrated to this CPU due to cpus_allowed, or * 3) are cache-hot on their current CPU. + * 4) p->pi_lock is held. */ if (!cpumask_test_cpu(this_cpu, tsk_cpus_allowed(p))) { schedstat_inc(p, se.statistics.nr_failed_migrations_affine); @@ -2804,6 +2805,14 @@ int can_migrate_task(struct task_struct *p, struct r= q *rq, int this_cpu, } =20 /* + * rt -> fair class change may be in progress. If we sneak in should + * double_lock_balance() release rq->lock, and move the task, we will + * cause switched_to_fair() to meet a passed but no longer valid rq. + */ + if (raw_spin_is_locked(&p->pi_lock)) + return 0; + + /* * Aggressive migration if: * 1) task is cache cold, or * 2) too many balance attempts have failed. diff --git a/kernel/sysctl.c b/kernel/sysctl.c index ea7ec7f197c4..8f3d1453082d 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -1518,6 +1518,20 @@ static struct ctl_table fs_table[] =3D { .proc_handler =3D &pipe_proc_fn, .extra1 =3D &pipe_min_size, }, + { + .procname =3D "pipe-user-pages-hard", + .data =3D &pipe_user_pages_hard, + .maxlen =3D sizeof(pipe_user_pages_hard), + .mode =3D 0644, + .proc_handler =3D proc_doulongvec_minmax, + }, + { + .procname =3D "pipe-user-pages-soft", + .data =3D &pipe_user_pages_soft, + .maxlen =3D sizeof(pipe_user_pages_soft), + .mode =3D 0644, + .proc_handler =3D proc_doulongvec_minmax, + }, { } }; =20 diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 3258455549f4..8e17101216cd 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -57,7 +57,7 @@ print_timer(struct seq_file *m, struct hrtimer *taddr, st= ruct hrtimer *timer, print_name_offset(m, taddr); SEQ_printf(m, ", "); print_name_offset(m, timer->function); - SEQ_printf(m, ", S:%02lx", timer->state); + SEQ_printf(m, ", S:%02x", timer->state); #ifdef CONFIG_TIMER_STATS SEQ_printf(m, ", "); print_name_offset(m, timer->start_site); diff --git a/lib/klist.c b/lib/klist.c index 573d6068a42e..9a30dcd4eae6 100644 --- a/lib/klist.c +++ b/lib/klist.c @@ -282,9 +282,9 @@ void klist_iter_init_node(struct klist *k, struct klist= _iter *i, struct klist_node *n) { i->i_klist =3D k; - i->i_cur =3D n; - if (n) - kref_get(&n->n_ref); + i->i_cur =3D NULL; + if (n && kref_get_unless_zero(&n->n_ref)) + i->i_cur =3D n; } EXPORT_SYMBOL_GPL(klist_iter_init_node); =20 diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 17f54030263d..845e58b35507 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -879,7 +879,7 @@ long wait_iff_congested(struct zone *zone, int sync, lo= ng timeout) * here rather than calling cond_resched(). */ if (current->flags & PF_WQ_WORKER) - schedule_timeout(1); + schedule_timeout_uninterruptible(1); else cond_resched(); =20 diff --git a/net/core/scm.c b/net/core/scm.c index 51b4d52a6f98..9adabedaf8ad 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -80,6 +80,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_f= p_list **fplp) *fplp =3D fpl; fpl->count =3D 0; fpl->max =3D SCM_MAX_FD; + fpl->user =3D NULL; } fpp =3D &fpl->fp[fpl->count]; =20 @@ -100,6 +101,10 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct sc= m_fp_list **fplp) *fpp++ =3D file; fpl->count++; } + + if (!fpl->user) + fpl->user =3D get_uid(current_user()); + return num; } =20 @@ -124,6 +129,7 @@ void __scm_destroy(struct scm_cookie *scm) list_del(&fpl->list); for (i=3Dfpl->count-1; i>=3D0; i--) fput(fpl->fp[i]); + free_uid(fpl->user); kfree(fpl); } =20 @@ -342,6 +348,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) for (i =3D 0; i < fpl->count; i++) get_file(fpl->fp[i]); new_fpl->max =3D new_fpl->count; + new_fpl->user =3D get_uid(fpl->user); } return new_fpl; } diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 13d0fb69609b..ae7b50afc215 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -1065,17 +1065,6 @@ static unsigned int rfkill_fop_poll(struct file *fil= e, poll_table *wait) return res; } =20 -static bool rfkill_readable(struct rfkill_data *data) -{ - bool r; - - mutex_lock(&data->mtx); - r =3D !list_empty(&data->events); - mutex_unlock(&data->mtx); - - return r; -} - static ssize_t rfkill_fop_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { @@ -1092,8 +1081,11 @@ static ssize_t rfkill_fop_read(struct file *file, ch= ar __user *buf, goto out; } mutex_unlock(&data->mtx); + /* since we re-check and it just compares pointers, + * using !list_empty() without locking isn't a problem + */ ret =3D wait_event_interruptible(data->read_wait, - rfkill_readable(data)); + !list_empty(&data->events)); mutex_lock(&data->mtx); =20 if (ret) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 396283b306ab..5b0e16cfaff5 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -5309,6 +5309,7 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk= , int len, struct sctp_hmac_algo_param *hmacs; __u16 data_len =3D 0; u32 num_idents; + int i; =20 if (!sctp_auth_enable) return -EACCES; @@ -5326,8 +5327,12 @@ static int sctp_getsockopt_hmac_ident(struct sock *s= k, int len, return -EFAULT; if (put_user(num_idents, &p->shmac_num_idents)) return -EFAULT; - if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len)) - return -EFAULT; + for (i =3D 0; i < num_idents; i++) { + __u16 hmacid =3D ntohs(hmacs->hmac_ids[i]); + + if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16))) + return -EFAULT; + } return 0; } =20 @@ -6241,6 +6246,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr= *msg, /* Minimally, validate the sinfo_flags. */ if (cmsgs->info->sinfo_flags & ~(SCTP_UNORDERED | SCTP_ADDR_OVER | + SCTP_SACK_IMMEDIATELY | SCTP_ABORT | SCTP_EOF)) return -EINVAL; break; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 30a8899388d2..390e079913f4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1454,7 +1454,7 @@ static void unix_detach_fds(struct scm_cookie *scm, s= truct sk_buff *skb) UNIXCB(skb).fp =3D NULL; =20 for (i =3D scm->fp->count-1; i >=3D 0; i--) - unix_notinflight(scm->fp->fp[i]); + unix_notinflight(scm->fp->user, scm->fp->fp[i]); } =20 static void unix_destruct_scm(struct sk_buff *skb) @@ -1472,6 +1472,21 @@ static void unix_destruct_scm(struct sk_buff *skb) sock_wfree(skb); } =20 +/* + * The "user->unix_inflight" variable is protected by the garbage + * collection lock, and we just read it locklessly here. If you go + * over the limit, there might be a tiny race in actually noticing + * it across threads. Tough. + */ +static inline bool too_many_unix_fds(struct task_struct *p) +{ + struct user_struct *user =3D current_user(); + + if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) + return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); + return false; +} + #define MAX_RECURSION_LEVEL 4 =20 static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) @@ -1480,6 +1495,9 @@ static int unix_attach_fds(struct scm_cookie *scm, st= ruct sk_buff *skb) unsigned char max_level =3D 0; int unix_sock_count =3D 0; =20 + if (too_many_unix_fds(current)) + return -ETOOMANYREFS; + for (i =3D scm->fp->count - 1; i >=3D 0; i--) { struct sock *sk =3D unix_get_socket(scm->fp->fp[i]); =20 @@ -1501,10 +1519,8 @@ static int unix_attach_fds(struct scm_cookie *scm, s= truct sk_buff *skb) if (!UNIXCB(skb).fp) return -ENOMEM; =20 - if (unix_sock_count) { - for (i =3D scm->fp->count - 1; i >=3D 0; i--) - unix_inflight(scm->fp->fp[i]); - } + for (i =3D scm->fp->count - 1; i >=3D 0; i--) + unix_inflight(scm->fp->user, scm->fp->fp[i]); return max_level; } =20 @@ -2100,6 +2116,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, st= ruct socket *sock, =20 if (signal_pending(current)) { err =3D sock_intr_errno(timeo); + scm_destroy(siocb->scm); goto out; } =20 diff --git a/net/unix/garbage.c b/net/unix/garbage.c index 00d3e5678599..33a21260b79b 100644 --- a/net/unix/garbage.c +++ b/net/unix/garbage.c @@ -122,12 +122,14 @@ struct sock *unix_get_socket(struct file *filp) * descriptor if it is for an AF_UNIX socket. */ =20 -void unix_inflight(struct file *fp) +void unix_inflight(struct user_struct *user, struct file *fp) { struct sock *s =3D unix_get_socket(fp); + + spin_lock(&unix_gc_lock); + if (s) { struct unix_sock *u =3D unix_sk(s); - spin_lock(&unix_gc_lock); if (atomic_long_inc_return(&u->inflight) =3D=3D 1) { BUG_ON(!list_empty(&u->link)); list_add_tail(&u->link, &gc_inflight_list); @@ -135,22 +137,26 @@ void unix_inflight(struct file *fp) BUG_ON(list_empty(&u->link)); } unix_tot_inflight++; - spin_unlock(&unix_gc_lock); } + user->unix_inflight++; + spin_unlock(&unix_gc_lock); } =20 -void unix_notinflight(struct file *fp) +void unix_notinflight(struct user_struct *user, struct file *fp) { struct sock *s =3D unix_get_socket(fp); + + spin_lock(&unix_gc_lock); + if (s) { struct unix_sock *u =3D unix_sk(s); - spin_lock(&unix_gc_lock); BUG_ON(list_empty(&u->link)); if (atomic_long_dec_and_test(&u->inflight)) list_del_init(&u->link); unix_tot_inflight--; - spin_unlock(&unix_gc_lock); } + user->unix_inflight--; + spin_unlock(&unix_gc_lock); } =20 static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *)= , diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 542f69e80366..fa49a27226f0 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_substream *substr= eam, return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, = best_rate, NULL); } =20 -static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream) +static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream, + bool trylock) { struct snd_pcm_runtime *runtime =3D substream->runtime; struct snd_pcm_hw_params *params, *sparams; @@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_su= bstream *substream) struct snd_mask sformat_mask; struct snd_mask mask; =20 - if (mutex_lock_interruptible(&runtime->oss.params_lock)) + if (trylock) { + if (!(mutex_trylock(&runtime->oss.params_lock))) + return -EAGAIN; + } else if (mutex_lock_interruptible(&runtime->oss.params_lock)) return -EINTR; sw_params =3D kmalloc(sizeof(*sw_params), GFP_KERNEL); params =3D kmalloc(sizeof(*params), GFP_KERNEL); @@ -1091,7 +1095,7 @@ static int snd_pcm_oss_get_active_substream(struct sn= d_pcm_oss_file *pcm_oss_fil if (asubstream =3D=3D NULL) asubstream =3D substream; if (substream->runtime->oss.params) { - err =3D snd_pcm_oss_change_params(substream); + err =3D snd_pcm_oss_change_params(substream, false); if (err < 0) return err; } @@ -1130,7 +1134,7 @@ static int snd_pcm_oss_make_ready(struct snd_pcm_subs= tream *substream) return 0; runtime =3D substream->runtime; if (runtime->oss.params) { - err =3D snd_pcm_oss_change_params(substream); + err =3D snd_pcm_oss_change_params(substream, false); if (err < 0) return err; } @@ -2168,7 +2172,7 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_f= ile *pcm_oss_file, int stre runtime =3D substream->runtime; =20 if (runtime->oss.params && - (err =3D snd_pcm_oss_change_params(substream)) < 0) + (err =3D snd_pcm_oss_change_params(substream, false)) < 0) return err; =20 info.fragsize =3D runtime->oss.period_bytes; @@ -2804,7 +2808,12 @@ static int snd_pcm_oss_mmap(struct file *file, struc= t vm_area_struct *area) return -EIO; =09 if (runtime->oss.params) { - if ((err =3D snd_pcm_oss_change_params(substream)) < 0) + /* use mutex_trylock() for params_lock for avoiding a deadlock + * between mmap_sem and params_lock taken by + * copy_from/to_user() in snd_pcm_oss_write/read() + */ + err =3D snd_pcm_oss_change_params(substream, true); + if (err < 0) return err; } #ifdef CONFIG_SND_PCM_OSS_PLUGINS diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index 1bb95aeea084..14e7453969af 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -934,31 +934,36 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmi= di_substream *substream, unsigned long flags; long result =3D 0, count1; struct snd_rawmidi_runtime *runtime =3D substream->runtime; + unsigned long appl_ptr; =20 + spin_lock_irqsave(&runtime->lock, flags); while (count > 0 && runtime->avail) { count1 =3D runtime->buffer_size - runtime->appl_ptr; if (count1 > count) count1 =3D count; - spin_lock_irqsave(&runtime->lock, flags); if (count1 > (int)runtime->avail) count1 =3D runtime->avail; + + /* update runtime->appl_ptr before unlocking for userbuf */ + appl_ptr =3D runtime->appl_ptr; + runtime->appl_ptr +=3D count1; + runtime->appl_ptr %=3D runtime->buffer_size; + runtime->avail -=3D count1; + if (kernelbuf) - memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1)= ; + memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1); if (userbuf) { spin_unlock_irqrestore(&runtime->lock, flags); if (copy_to_user(userbuf + result, - runtime->buffer + runtime->appl_ptr, count1)) { + runtime->buffer + appl_ptr, count1)) { return result > 0 ? result : -EFAULT; } spin_lock_irqsave(&runtime->lock, flags); } - runtime->appl_ptr +=3D count1; - runtime->appl_ptr %=3D runtime->buffer_size; - runtime->avail -=3D count1; - spin_unlock_irqrestore(&runtime->lock, flags); result +=3D count1; count -=3D count1; } + spin_unlock_irqrestore(&runtime->lock, flags); return result; } =20 @@ -1044,23 +1049,16 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_s= ubstream *substream) } =20 /** - * snd_rawmidi_transmit_peek - copy data from the internal buffer + * __snd_rawmidi_transmit_peek - copy data from the internal buffer * @substream: the rawmidi substream * @buffer: the buffer pointer * @count: data size to transfer * - * Copies data from the internal output buffer to the given buffer. - * - * Call this in the interrupt handler when the midi output is ready, - * and call snd_rawmidi_transmit_ack() after the transmission is - * finished. - * - * Returns the size of copied data, or a negative error code on failure. + * This is a variant of snd_rawmidi_transmit_peek() without spinlock. */ -int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, +int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, unsigned char *buffer, int count) { - unsigned long flags; int result, count1; struct snd_rawmidi_runtime *runtime =3D substream->runtime; =20 @@ -1069,7 +1067,6 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_subs= tream *substream, return -EINVAL; } result =3D 0; - spin_lock_irqsave(&runtime->lock, flags); if (runtime->avail >=3D runtime->buffer_size) { /* warning: lowlevel layer MUST trigger down the hardware */ goto __skip; @@ -1094,31 +1091,52 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_su= bstream *substream, } } __skip: - spin_unlock_irqrestore(&runtime->lock, flags); return result; } +EXPORT_SYMBOL(__snd_rawmidi_transmit_peek); =20 /** - * snd_rawmidi_transmit_ack - acknowledge the transmission + * snd_rawmidi_transmit_peek - copy data from the internal buffer * @substream: the rawmidi substream - * @count: the tranferred count + * @buffer: the buffer pointer + * @count: data size to transfer * - * Advances the hardware pointer for the internal output buffer with - * the given size and updates the condition. - * Call after the transmission is finished. + * Copies data from the internal output buffer to the given buffer. + * + * Call this in the interrupt handler when the midi output is ready, + * and call snd_rawmidi_transmit_ack() after the transmission is + * finished. * - * Returns the advanced size if successful, or a negative error code on fa= ilure. + * Return: The size of copied data, or a negative error code on failure. */ -int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int = count) +int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, + unsigned char *buffer, int count) { + struct snd_rawmidi_runtime *runtime =3D substream->runtime; + int result; unsigned long flags; + + spin_lock_irqsave(&runtime->lock, flags); + result =3D __snd_rawmidi_transmit_peek(substream, buffer, count); + spin_unlock_irqrestore(&runtime->lock, flags); + return result; +} + +/** + * __snd_rawmidi_transmit_ack - acknowledge the transmission + * @substream: the rawmidi substream + * @count: the tranferred count + * + * This is a variant of __snd_rawmidi_transmit_ack() without spinlock. + */ +int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, in= t count) +{ struct snd_rawmidi_runtime *runtime =3D substream->runtime; =20 if (runtime->buffer =3D=3D NULL) { snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n"); return -EINVAL; } - spin_lock_irqsave(&runtime->lock, flags); snd_BUG_ON(runtime->avail + count > runtime->buffer_size); runtime->hw_ptr +=3D count; runtime->hw_ptr %=3D runtime->buffer_size; @@ -1128,9 +1146,32 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_subs= tream *substream, int count) if (runtime->drain || snd_rawmidi_ready(substream)) wake_up(&runtime->sleep); } - spin_unlock_irqrestore(&runtime->lock, flags); return count; } +EXPORT_SYMBOL(__snd_rawmidi_transmit_ack); + +/** + * snd_rawmidi_transmit_ack - acknowledge the transmission + * @substream: the rawmidi substream + * @count: the transferred count + * + * Advances the hardware pointer for the internal output buffer with + * the given size and updates the condition. + * Call after the transmission is finished. + * + * Return: The advanced size if successful, or a negative error code on fa= ilure. + */ +int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int = count) +{ + struct snd_rawmidi_runtime *runtime =3D substream->runtime; + int result; + unsigned long flags; + + spin_lock_irqsave(&runtime->lock, flags); + result =3D __snd_rawmidi_transmit_ack(substream, count); + spin_unlock_irqrestore(&runtime->lock, flags); + return result; +} =20 /** * snd_rawmidi_transmit - copy from the buffer to the device @@ -1145,12 +1186,22 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_sub= stream *substream, int count) int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, unsigned char *buffer, int count) { + struct snd_rawmidi_runtime *runtime =3D substream->runtime; + int result; + unsigned long flags; + + spin_lock_irqsave(&runtime->lock, flags); if (!substream->opened) - return -EBADFD; - count =3D snd_rawmidi_transmit_peek(substream, buffer, count); - if (count < 0) - return count; - return snd_rawmidi_transmit_ack(substream, count); + result =3D -EBADFD; + else { + count =3D __snd_rawmidi_transmit_peek(substream, buffer, count); + if (count <=3D 0) + result =3D count; + else + result =3D __snd_rawmidi_transmit_ack(substream, count); + } + spin_unlock_irqrestore(&runtime->lock, flags); + return result; } =20 static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substr= eam, @@ -1161,8 +1212,9 @@ static long snd_rawmidi_kernel_write1(struct snd_rawm= idi_substream *substream, unsigned long flags; long count1, result; struct snd_rawmidi_runtime *runtime =3D substream->runtime; + unsigned long appl_ptr; =20 - if (snd_BUG_ON(!kernelbuf && !userbuf)) + if (!kernelbuf && !userbuf) return -EINVAL; if (snd_BUG_ON(!runtime->buffer)) return -EINVAL; @@ -1181,12 +1233,19 @@ static long snd_rawmidi_kernel_write1(struct snd_ra= wmidi_substream *substream, count1 =3D count; if (count1 > (long)runtime->avail) count1 =3D runtime->avail; + + /* update runtime->appl_ptr before unlocking for userbuf */ + appl_ptr =3D runtime->appl_ptr; + runtime->appl_ptr +=3D count1; + runtime->appl_ptr %=3D runtime->buffer_size; + runtime->avail -=3D count1; + if (kernelbuf) - memcpy(runtime->buffer + runtime->appl_ptr, + memcpy(runtime->buffer + appl_ptr, kernelbuf + result, count1); else if (userbuf) { spin_unlock_irqrestore(&runtime->lock, flags); - if (copy_from_user(runtime->buffer + runtime->appl_ptr, + if (copy_from_user(runtime->buffer + appl_ptr, userbuf + result, count1)) { spin_lock_irqsave(&runtime->lock, flags); result =3D result > 0 ? result : -EFAULT; @@ -1194,9 +1253,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawm= idi_substream *substream, } spin_lock_irqsave(&runtime->lock, flags); } - runtime->appl_ptr +=3D count1; - runtime->appl_ptr %=3D runtime->buffer_size; - runtime->avail -=3D count1; result +=3D count1; count -=3D count1; } diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss= _init.c index e3cb46fef2c7..966d0dc5385b 100644 --- a/sound/core/seq/oss/seq_oss_init.c +++ b/sound/core/seq/oss/seq_oss_init.c @@ -196,7 +196,7 @@ snd_seq_oss_open(struct file *file, int level) =20 dp->index =3D i; if (i >=3D SNDRV_SEQ_OSS_MAX_CLIENTS) { - snd_printk(KERN_ERR "too many applications\n"); + pr_debug("ALSA: seq_oss: too many applications\n"); rc =3D -ENOMEM; goto _error; } diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_os= s_synth.c index c5b773a1eea9..4a09c3085ca4 100644 --- a/sound/core/seq/oss/seq_oss_synth.c +++ b/sound/core/seq/oss/seq_oss_synth.c @@ -310,7 +310,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp) struct seq_oss_synth *rec; struct seq_oss_synthinfo *info; =20 - if (snd_BUG_ON(dp->max_synthdev >=3D SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) + if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS)) return; for (i =3D 0; i < dp->max_synthdev; i++) { info =3D &dp->synths[i]; diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.= c index ecfbf5f39d38..08865dcbf5f1 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct snd_seq_client= *client, else down_read(&grp->list_mutex); list_for_each_entry(subs, &grp->list_head, src_list) { + /* both ports ready? */ + if (atomic_read(&subs->ref_count) !=3D 2) + continue; event->dest =3D subs->info.dest; if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) /* convert time according to flag with subscription */ diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index 9516e5ce3aad..67c91d226552 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -175,10 +175,6 @@ struct snd_seq_client_port *snd_seq_create_port(struct= snd_seq_client *client, } =20 /* */ -enum group_type { - SRC_LIST, DEST_LIST -}; - static int subscribe_port(struct snd_seq_client *client, struct snd_seq_client_port *port, struct snd_seq_port_subs_info *grp, @@ -205,6 +201,20 @@ static struct snd_seq_client_port *get_client_port(str= uct snd_seq_addr *addr, return NULL; } =20 +static void delete_and_unsubscribe_port(struct snd_seq_client *client, + struct snd_seq_client_port *port, + struct snd_seq_subscribers *subs, + bool is_src, bool ack); + +static inline struct snd_seq_subscribers * +get_subscriber(struct list_head *p, bool is_src) +{ + if (is_src) + return list_entry(p, struct snd_seq_subscribers, src_list); + else + return list_entry(p, struct snd_seq_subscribers, dest_list); +} + /* * remove all subscribers on the list * this is called from port_delete, for each src and dest list. @@ -212,7 +222,7 @@ static struct snd_seq_client_port *get_client_port(stru= ct snd_seq_addr *addr, static void clear_subscriber_list(struct snd_seq_client *client, struct snd_seq_client_port *port, struct snd_seq_port_subs_info *grp, - int grptype) + int is_src) { struct list_head *p, *n; =20 @@ -221,15 +231,13 @@ static void clear_subscriber_list(struct snd_seq_clie= nt *client, struct snd_seq_client *c; struct snd_seq_client_port *aport; =20 - if (grptype =3D=3D SRC_LIST) { - subs =3D list_entry(p, struct snd_seq_subscribers, src_list); + subs =3D get_subscriber(p, is_src); + if (is_src) aport =3D get_client_port(&subs->info.dest, &c); - } else { - subs =3D list_entry(p, struct snd_seq_subscribers, dest_list); + else aport =3D get_client_port(&subs->info.sender, &c); - } - list_del(p); - unsubscribe_port(client, port, grp, &subs->info, 0); + delete_and_unsubscribe_port(client, port, subs, is_src, false); + if (!aport) { /* looks like the connected port is being deleted. * we decrease the counter, and when both ports are deleted @@ -237,21 +245,14 @@ static void clear_subscriber_list(struct snd_seq_clie= nt *client, */ if (atomic_dec_and_test(&subs->ref_count)) kfree(subs); - } else { - /* ok we got the connected port */ - struct snd_seq_port_subs_info *agrp; - agrp =3D (grptype =3D=3D SRC_LIST) ? &aport->c_dest : &aport->c_src; - down_write(&agrp->list_mutex); - if (grptype =3D=3D SRC_LIST) - list_del(&subs->dest_list); - else - list_del(&subs->src_list); - up_write(&agrp->list_mutex); - unsubscribe_port(c, aport, agrp, &subs->info, 1); - kfree(subs); - snd_seq_port_unlock(aport); - snd_seq_client_unlock(c); + continue; } + + /* ok we got the connected port */ + delete_and_unsubscribe_port(c, aport, subs, !is_src, true); + kfree(subs); + snd_seq_port_unlock(aport); + snd_seq_client_unlock(c); } } =20 @@ -264,8 +265,8 @@ static int port_delete(struct snd_seq_client *client, snd_use_lock_sync(&port->use_lock);=20 =20 /* clear subscribers info */ - clear_subscriber_list(client, port, &port->c_src, SRC_LIST); - clear_subscriber_list(client, port, &port->c_dest, DEST_LIST); + clear_subscriber_list(client, port, &port->c_src, true); + clear_subscriber_list(client, port, &port->c_dest, false); =20 if (port->private_free) port->private_free(port->private_data); @@ -484,85 +485,120 @@ static int match_subs_info(struct snd_seq_port_subsc= ribe *r, return 0; } =20 - -/* connect two ports */ -int snd_seq_port_connect(struct snd_seq_client *connector, - struct snd_seq_client *src_client, - struct snd_seq_client_port *src_port, - struct snd_seq_client *dest_client, - struct snd_seq_client_port *dest_port, - struct snd_seq_port_subscribe *info) +static int check_and_subscribe_port(struct snd_seq_client *client, + struct snd_seq_client_port *port, + struct snd_seq_subscribers *subs, + bool is_src, bool exclusive, bool ack) { - struct snd_seq_port_subs_info *src =3D &src_port->c_src; - struct snd_seq_port_subs_info *dest =3D &dest_port->c_dest; - struct snd_seq_subscribers *subs, *s; - int err, src_called =3D 0; - unsigned long flags; - int exclusive; + struct snd_seq_port_subs_info *grp; + struct list_head *p; + struct snd_seq_subscribers *s; + int err; =20 - subs =3D kzalloc(sizeof(*subs), GFP_KERNEL); - if (! subs) - return -ENOMEM; - - subs->info =3D *info; - atomic_set(&subs->ref_count, 2); - - down_write(&src->list_mutex); - down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING); - - exclusive =3D info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0; + grp =3D is_src ? &port->c_src : &port->c_dest; err =3D -EBUSY; + down_write(&grp->list_mutex); if (exclusive) { - if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head)) + if (!list_empty(&grp->list_head)) goto __error; } else { - if (src->exclusive || dest->exclusive) + if (grp->exclusive) goto __error; /* check whether already exists */ - list_for_each_entry(s, &src->list_head, src_list) { - if (match_subs_info(info, &s->info)) - goto __error; - } - list_for_each_entry(s, &dest->list_head, dest_list) { - if (match_subs_info(info, &s->info)) + list_for_each(p, &grp->list_head) { + s =3D get_subscriber(p, is_src); + if (match_subs_info(&subs->info, &s->info)) goto __error; } } =20 - if ((err =3D subscribe_port(src_client, src_port, src, info, - connector->number !=3D src_client->number)) < 0) - goto __error; - src_called =3D 1; - - if ((err =3D subscribe_port(dest_client, dest_port, dest, info, - connector->number !=3D dest_client->number)) < 0) + err =3D subscribe_port(client, port, grp, &subs->info, ack); + if (err < 0) { + grp->exclusive =3D 0; goto __error; + } =20 /* add to list */ - write_lock_irqsave(&src->list_lock, flags); - // write_lock(&dest->list_lock); // no other lock yet - list_add_tail(&subs->src_list, &src->list_head); - list_add_tail(&subs->dest_list, &dest->list_head); - // write_unlock(&dest->list_lock); // no other lock yet - write_unlock_irqrestore(&src->list_lock, flags); + write_lock_irq(&grp->list_lock); + if (is_src) + list_add_tail(&subs->src_list, &grp->list_head); + else + list_add_tail(&subs->dest_list, &grp->list_head); + grp->exclusive =3D exclusive; + atomic_inc(&subs->ref_count); + write_unlock_irq(&grp->list_lock); + err =3D 0; + + __error: + up_write(&grp->list_mutex); + return err; +} =20 - src->exclusive =3D dest->exclusive =3D exclusive; +static void delete_and_unsubscribe_port(struct snd_seq_client *client, + struct snd_seq_client_port *port, + struct snd_seq_subscribers *subs, + bool is_src, bool ack) +{ + struct snd_seq_port_subs_info *grp; + + grp =3D is_src ? &port->c_src : &port->c_dest; + down_write(&grp->list_mutex); + write_lock_irq(&grp->list_lock); + if (is_src) + list_del(&subs->src_list); + else + list_del(&subs->dest_list); + grp->exclusive =3D 0; + write_unlock_irq(&grp->list_lock); + up_write(&grp->list_mutex); + + unsubscribe_port(client, port, grp, &subs->info, ack); +} + +/* connect two ports */ +int snd_seq_port_connect(struct snd_seq_client *connector, + struct snd_seq_client *src_client, + struct snd_seq_client_port *src_port, + struct snd_seq_client *dest_client, + struct snd_seq_client_port *dest_port, + struct snd_seq_port_subscribe *info) +{ + struct snd_seq_subscribers *subs; + bool exclusive; + int err; + + subs =3D kzalloc(sizeof(*subs), GFP_KERNEL); + if (!subs) + return -ENOMEM; + + subs->info =3D *info; + atomic_set(&subs->ref_count, 0); + INIT_LIST_HEAD(&subs->src_list); + INIT_LIST_HEAD(&subs->dest_list); + + exclusive =3D !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE); + + err =3D check_and_subscribe_port(src_client, src_port, subs, true, + exclusive, + connector->number !=3D src_client->number); + if (err < 0) + goto error; + err =3D check_and_subscribe_port(dest_client, dest_port, subs, false, + exclusive, + connector->number !=3D dest_client->number); + if (err < 0) + goto error_dest; =20 - up_write(&dest->list_mutex); - up_write(&src->list_mutex); return 0; =20 - __error: - if (src_called) - unsubscribe_port(src_client, src_port, src, info, - connector->number !=3D src_client->number); + error_dest: + delete_and_unsubscribe_port(src_client, src_port, subs, true, + connector->number !=3D src_client->number); + error: kfree(subs); - up_write(&dest->list_mutex); - up_write(&src->list_mutex); return err; } =20 - /* remove the connection */ int snd_seq_port_disconnect(struct snd_seq_client *connector, struct snd_seq_client *src_client, @@ -572,37 +608,28 @@ int snd_seq_port_disconnect(struct snd_seq_client *co= nnector, struct snd_seq_port_subscribe *info) { struct snd_seq_port_subs_info *src =3D &src_port->c_src; - struct snd_seq_port_subs_info *dest =3D &dest_port->c_dest; struct snd_seq_subscribers *subs; int err =3D -ENOENT; - unsigned long flags; =20 down_write(&src->list_mutex); - down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING); - /* look for the connection */ list_for_each_entry(subs, &src->list_head, src_list) { if (match_subs_info(info, &subs->info)) { - write_lock_irqsave(&src->list_lock, flags); - // write_lock(&dest->list_lock); // no lock yet - list_del(&subs->src_list); - list_del(&subs->dest_list); - // write_unlock(&dest->list_lock); - write_unlock_irqrestore(&src->list_lock, flags); - src->exclusive =3D dest->exclusive =3D 0; - unsubscribe_port(src_client, src_port, src, info, - connector->number !=3D src_client->number); - unsubscribe_port(dest_client, dest_port, dest, info, - connector->number !=3D dest_client->number); - kfree(subs); + atomic_dec(&subs->ref_count); /* mark as not ready */ err =3D 0; break; } } - - up_write(&dest->list_mutex); up_write(&src->list_mutex); - return err; + if (err < 0) + return err; + + delete_and_unsubscribe_port(src_client, src_port, subs, true, + connector->number !=3D src_client->number); + delete_and_unsubscribe_port(dest_client, dest_port, subs, false, + connector->number !=3D dest_client->number); + kfree(subs); + return 0; } =20 =20 diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 24d44b2f61ac..6ec30a98a92a 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -92,6 +92,9 @@ void snd_seq_timer_delete(struct snd_seq_timer **tmr) =20 void snd_seq_timer_defaults(struct snd_seq_timer * tmr) { + unsigned long flags; + + spin_lock_irqsave(&tmr->lock, flags); /* setup defaults */ tmr->ppq =3D 96; /* 96 PPQ */ tmr->tempo =3D 500000; /* 120 BPM */ @@ -107,21 +110,25 @@ void snd_seq_timer_defaults(struct snd_seq_timer * tm= r) tmr->preferred_resolution =3D seq_default_timer_resolution; =20 tmr->skew =3D tmr->skew_base =3D SKEW_BASE; + spin_unlock_irqrestore(&tmr->lock, flags); } =20 -void snd_seq_timer_reset(struct snd_seq_timer * tmr) +static void seq_timer_reset(struct snd_seq_timer *tmr) { - unsigned long flags; - - spin_lock_irqsave(&tmr->lock, flags); - /* reset time & songposition */ tmr->cur_time.tv_sec =3D 0; tmr->cur_time.tv_nsec =3D 0; =20 tmr->tick.cur_tick =3D 0; tmr->tick.fraction =3D 0; +} + +void snd_seq_timer_reset(struct snd_seq_timer *tmr) +{ + unsigned long flags; =20 + spin_lock_irqsave(&tmr->lock, flags); + seq_timer_reset(tmr); spin_unlock_irqrestore(&tmr->lock, flags); } =20 @@ -140,8 +147,11 @@ static void snd_seq_timer_interrupt(struct snd_timer_i= nstance *timeri, tmr =3D q->timer; if (tmr =3D=3D NULL) return; - if (!tmr->running) + spin_lock_irqsave(&tmr->lock, flags); + if (!tmr->running) { + spin_unlock_irqrestore(&tmr->lock, flags); return; + } =20 resolution *=3D ticks; if (tmr->skew !=3D tmr->skew_base) { @@ -150,8 +160,6 @@ static void snd_seq_timer_interrupt(struct snd_timer_in= stance *timeri, (((resolution & 0xffff) * tmr->skew) >> 16); } =20 - spin_lock_irqsave(&tmr->lock, flags); - /* update timer */ snd_seq_inc_time_nsec(&tmr->cur_time, resolution); =20 @@ -298,26 +306,30 @@ int snd_seq_timer_open(struct snd_seq_queue *q) t->callback =3D snd_seq_timer_interrupt; t->callback_data =3D q; t->flags |=3D SNDRV_TIMER_IFLG_AUTO; + spin_lock_irq(&tmr->lock); tmr->timeri =3D t; + spin_unlock_irq(&tmr->lock); return 0; } =20 int snd_seq_timer_close(struct snd_seq_queue *q) { struct snd_seq_timer *tmr; + struct snd_timer_instance *t; =09 tmr =3D q->timer; if (snd_BUG_ON(!tmr)) return -EINVAL; - if (tmr->timeri) { - snd_timer_stop(tmr->timeri); - snd_timer_close(tmr->timeri); - tmr->timeri =3D NULL; - } + spin_lock_irq(&tmr->lock); + t =3D tmr->timeri; + tmr->timeri =3D NULL; + spin_unlock_irq(&tmr->lock); + if (t) + snd_timer_close(t); return 0; } =20 -int snd_seq_timer_stop(struct snd_seq_timer * tmr) +static int seq_timer_stop(struct snd_seq_timer *tmr) { if (! tmr->timeri) return -EINVAL; @@ -328,6 +340,17 @@ int snd_seq_timer_stop(struct snd_seq_timer * tmr) return 0; } =20 +int snd_seq_timer_stop(struct snd_seq_timer *tmr) +{ + unsigned long flags; + int err; + + spin_lock_irqsave(&tmr->lock, flags); + err =3D seq_timer_stop(tmr); + spin_unlock_irqrestore(&tmr->lock, flags); + return err; +} + static int initialize_timer(struct snd_seq_timer *tmr) { struct snd_timer *t; @@ -360,13 +383,13 @@ static int initialize_timer(struct snd_seq_timer *tmr= ) return 0; } =20 -int snd_seq_timer_start(struct snd_seq_timer * tmr) +static int seq_timer_start(struct snd_seq_timer *tmr) { if (! tmr->timeri) return -EINVAL; if (tmr->running) - snd_seq_timer_stop(tmr); - snd_seq_timer_reset(tmr); + seq_timer_stop(tmr); + seq_timer_reset(tmr); if (initialize_timer(tmr) < 0) return -EINVAL; snd_timer_start(tmr->timeri, tmr->ticks); @@ -375,14 +398,25 @@ int snd_seq_timer_start(struct snd_seq_timer * tmr) return 0; } =20 -int snd_seq_timer_continue(struct snd_seq_timer * tmr) +int snd_seq_timer_start(struct snd_seq_timer *tmr) +{ + unsigned long flags; + int err; + + spin_lock_irqsave(&tmr->lock, flags); + err =3D seq_timer_start(tmr); + spin_unlock_irqrestore(&tmr->lock, flags); + return err; +} + +static int seq_timer_continue(struct snd_seq_timer *tmr) { if (! tmr->timeri) return -EINVAL; if (tmr->running) return -EBUSY; if (! tmr->initialized) { - snd_seq_timer_reset(tmr); + seq_timer_reset(tmr); if (initialize_timer(tmr) < 0) return -EINVAL; } @@ -392,11 +426,24 @@ int snd_seq_timer_continue(struct snd_seq_timer * tmr= ) return 0; } =20 +int snd_seq_timer_continue(struct snd_seq_timer *tmr) +{ + unsigned long flags; + int err; + + spin_lock_irqsave(&tmr->lock, flags); + err =3D seq_timer_continue(tmr); + spin_unlock_irqrestore(&tmr->lock, flags); + return err; +} + /* return current 'real' time. use timeofday() to get better granularity. = */ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr) { snd_seq_real_time_t cur_time; + unsigned long flags; =20 + spin_lock_irqsave(&tmr->lock, flags); cur_time =3D tmr->cur_time; if (tmr->running) {=20 struct timeval tm; @@ -412,7 +459,7 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct s= nd_seq_timer *tmr) } snd_seq_sanity_real_time(&cur_time); } - =20 + spin_unlock_irqrestore(&tmr->lock, flags); return cur_time;=09 } =20 diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index 4b50e604276d..6b38e7c2641a 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -155,21 +155,26 @@ static void snd_virmidi_output_trigger(struct snd_raw= midi_substream *substream, struct snd_virmidi *vmidi =3D substream->runtime->private_data; int count, res; unsigned char buf[32], *pbuf; + unsigned long flags; =20 if (up) { vmidi->trigger =3D 1; if (vmidi->seq_mode =3D=3D SNDRV_VIRMIDI_SEQ_DISPATCH && !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) { - snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - s= ubstream->runtime->avail); - return; /* ignored */ + while (snd_rawmidi_transmit(substream, buf, + sizeof(buf)) > 0) { + /* ignored */ + } + return; } if (vmidi->event.type !=3D SNDRV_SEQ_EVENT_NONE) { if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_ato= mic(), 0) < 0) return; vmidi->event.type =3D SNDRV_SEQ_EVENT_NONE; } + spin_lock_irqsave(&substream->runtime->lock, flags); while (1) { - count =3D snd_rawmidi_transmit_peek(substream, buf, sizeof(buf)); + count =3D __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf)); if (count <=3D 0) break; pbuf =3D buf; @@ -179,16 +184,18 @@ static void snd_virmidi_output_trigger(struct snd_raw= midi_substream *substream, snd_midi_event_reset_encode(vmidi->parser); continue; } - snd_rawmidi_transmit_ack(substream, res); + __snd_rawmidi_transmit_ack(substream, res); pbuf +=3D res; count -=3D res; if (vmidi->event.type !=3D SNDRV_SEQ_EVENT_NONE) { if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_a= tomic(), 0) < 0) - return; + goto out; vmidi->event.type =3D SNDRV_SEQ_EVENT_NONE; } } } + out: + spin_unlock_irqrestore(&substream->runtime->lock, flags); } else { vmidi->trigger =3D 0; } @@ -254,9 +261,13 @@ static int snd_virmidi_output_open(struct snd_rawmidi_= substream *substream) */ static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream= ) { + struct snd_virmidi_dev *rdev =3D substream->rmidi->private_data; struct snd_virmidi *vmidi =3D substream->runtime->private_data; - snd_midi_event_free(vmidi->parser); + + write_lock_irq(&rdev->filelist_lock); list_del(&vmidi->list); + write_unlock_irq(&rdev->filelist_lock); + snd_midi_event_free(vmidi->parser); substream->runtime->private_data =3D NULL; kfree(vmidi); return 0; diff --git a/sound/core/timer.c b/sound/core/timer.c index 76bdfaccb8de..beb41ecb2730 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -414,7 +414,7 @@ static void snd_timer_notify1(struct snd_timer_instance= *ti, int event) spin_lock_irqsave(&timer->lock, flags); list_for_each_entry(ts, &ti->slave_active_head, active_list) if (ts->ccallback) - ts->ccallback(ti, event + 100, &tstamp, resolution); + ts->ccallback(ts, event + 100, &tstamp, resolution); spin_unlock_irqrestore(&timer->lock, flags); } =20 @@ -443,6 +443,10 @@ static int snd_timer_start_slave(struct snd_timer_inst= ance *timeri) unsigned long flags; =20 spin_lock_irqsave(&slave_active_lock, flags); + if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { + spin_unlock_irqrestore(&slave_active_lock, flags); + return -EBUSY; + } timeri->flags |=3D SNDRV_TIMER_IFLG_RUNNING; if (timeri->master && timeri->timer) { spin_lock(&timeri->timer->lock); @@ -467,18 +471,26 @@ int snd_timer_start(struct snd_timer_instance *timeri= , unsigned int ticks) return -EINVAL; if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { result =3D snd_timer_start_slave(timeri); - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); + if (result >=3D 0) + snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); return result; } timer =3D timeri->timer; if (timer =3D=3D NULL) return -EINVAL; spin_lock_irqsave(&timer->lock, flags); + if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | + SNDRV_TIMER_IFLG_START)) { + result =3D -EBUSY; + goto unlock; + } timeri->ticks =3D timeri->cticks =3D ticks; timeri->pticks =3D 0; result =3D snd_timer_start1(timer, timeri, ticks); + unlock: spin_unlock_irqrestore(&timer->lock, flags); - snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); + if (result >=3D 0) + snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START); return result; } =20 @@ -494,9 +506,17 @@ static int _snd_timer_stop(struct snd_timer_instance *= timeri, if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) { if (!keep_flag) { spin_lock_irqsave(&slave_active_lock, flags); + if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) { + spin_unlock_irqrestore(&slave_active_lock, flags); + return -EBUSY; + } + if (timeri->timer) + spin_lock(&timeri->timer->lock); timeri->flags &=3D ~SNDRV_TIMER_IFLG_RUNNING; list_del_init(&timeri->ack_list); list_del_init(&timeri->active_list); + if (timeri->timer) + spin_unlock(&timeri->timer->lock); spin_unlock_irqrestore(&slave_active_lock, flags); } goto __end; @@ -505,6 +525,11 @@ static int _snd_timer_stop(struct snd_timer_instance *= timeri, if (!timer) return -EINVAL; spin_lock_irqsave(&timer->lock, flags); + if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING | + SNDRV_TIMER_IFLG_START))) { + spin_unlock_irqrestore(&timer->lock, flags); + return -EBUSY; + } list_del_init(&timeri->ack_list); list_del_init(&timeri->active_list); if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) && @@ -570,10 +595,15 @@ int snd_timer_continue(struct snd_timer_instance *tim= eri) if (! timer) return -EINVAL; spin_lock_irqsave(&timer->lock, flags); + if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) { + result =3D -EBUSY; + goto unlock; + } if (!timeri->cticks) timeri->cticks =3D 1; timeri->pticks =3D 0; result =3D snd_timer_start1(timer, timeri, timer->sticks); + unlock: spin_unlock_irqrestore(&timer->lock, flags); snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE); return result; @@ -701,8 +731,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsi= gned long ticks_left) ti->cticks =3D ti->ticks; } else { ti->flags &=3D ~SNDRV_TIMER_IFLG_RUNNING; - if (--timer->running) - list_del_init(&ti->active_list); + --timer->running; + list_del_init(&ti->active_list); } if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || (ti->flags & SNDRV_TIMER_IFLG_FAST)) @@ -1860,6 +1890,7 @@ static ssize_t snd_timer_user_read(struct file *file,= char __user *buffer, { struct snd_timer_user *tu; long result =3D 0, unit; + int qhead; int err =3D 0; =20 tu =3D file->private_data; @@ -1871,7 +1902,7 @@ static ssize_t snd_timer_user_read(struct file *file,= char __user *buffer, =20 if ((file->f_flags & O_NONBLOCK) !=3D 0 || result > 0) { err =3D -EAGAIN; - break; + goto _error; } =20 set_current_state(TASK_INTERRUPTIBLE); @@ -1886,38 +1917,33 @@ static ssize_t snd_timer_user_read(struct file *fil= e, char __user *buffer, =20 if (signal_pending(current)) { err =3D -ERESTARTSYS; - break; + goto _error; } } =20 + qhead =3D tu->qhead++; + tu->qhead %=3D tu->queue_size; spin_unlock_irq(&tu->qlock); - if (err < 0) - goto _error; =20 if (tu->tread) { - if (copy_to_user(buffer, &tu->tqueue[tu->qhead++], - sizeof(struct snd_timer_tread))) { + if (copy_to_user(buffer, &tu->tqueue[qhead], + sizeof(struct snd_timer_tread))) err =3D -EFAULT; - goto _error; - } } else { - if (copy_to_user(buffer, &tu->queue[tu->qhead++], - sizeof(struct snd_timer_read))) { + if (copy_to_user(buffer, &tu->queue[qhead], + sizeof(struct snd_timer_read))) err =3D -EFAULT; - goto _error; - } } =20 - tu->qhead %=3D tu->queue_size; - - result +=3D unit; - buffer +=3D unit; - spin_lock_irq(&tu->qlock); tu->qused--; + if (err < 0) + goto _error; + result +=3D unit; + buffer +=3D unit; } - spin_unlock_irq(&tu->qlock); _error: + spin_unlock_irq(&tu->qlock); return result > 0 ? result : err; } =20 diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index 97f1f93ed275..3662c6267f55 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c @@ -109,6 +109,9 @@ struct dummy_timer_ops { snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *); }; =20 +#define get_dummy_ops(substream) \ + (*(const struct dummy_timer_ops **)(substream)->runtime->private_data) + struct dummy_model { const char *name; int (*playback_constraints)(struct snd_pcm_runtime *runtime); @@ -134,7 +137,6 @@ struct snd_dummy { spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; - const struct dummy_timer_ops *timer_ops; }; =20 /* @@ -228,6 +230,8 @@ struct dummy_model *dummy_models[] =3D { */ =20 struct dummy_systimer_pcm { + /* ops must be the first item */ + const struct dummy_timer_ops *timer_ops; spinlock_t lock; struct timer_list timer; unsigned long base_time; @@ -365,6 +369,8 @@ static struct dummy_timer_ops dummy_systimer_ops =3D { */ =20 struct dummy_hrtimer_pcm { + /* ops must be the first item */ + const struct dummy_timer_ops *timer_ops; ktime_t base_time; ktime_t period_time; atomic_t running; @@ -491,31 +497,25 @@ static struct dummy_timer_ops dummy_hrtimer_ops =3D { =20 static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_dummy *dummy =3D snd_pcm_substream_chip(substream); - switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: - return dummy->timer_ops->start(substream); + return get_dummy_ops(substream)->start(substream); case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - return dummy->timer_ops->stop(substream); + return get_dummy_ops(substream)->stop(substream); } return -EINVAL; } =20 static int dummy_pcm_prepare(struct snd_pcm_substream *substream) { - struct snd_dummy *dummy =3D snd_pcm_substream_chip(substream); - - return dummy->timer_ops->prepare(substream); + return get_dummy_ops(substream)->prepare(substream); } =20 static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *subst= ream) { - struct snd_dummy *dummy =3D snd_pcm_substream_chip(substream); - - return dummy->timer_ops->pointer(substream); + return get_dummy_ops(substream)->pointer(substream); } =20 static struct snd_pcm_hardware dummy_pcm_hardware =3D { @@ -561,17 +561,19 @@ static int dummy_pcm_open(struct snd_pcm_substream *s= ubstream) struct snd_dummy *dummy =3D snd_pcm_substream_chip(substream); struct dummy_model *model =3D dummy->model; struct snd_pcm_runtime *runtime =3D substream->runtime; + const struct dummy_timer_ops *ops; int err; =20 - dummy->timer_ops =3D &dummy_systimer_ops; + ops =3D &dummy_systimer_ops; #ifdef CONFIG_HIGH_RES_TIMERS if (hrtimer) - dummy->timer_ops =3D &dummy_hrtimer_ops; + ops =3D &dummy_hrtimer_ops; #endif =20 - err =3D dummy->timer_ops->create(substream); + err =3D ops->create(substream); if (err < 0) return err; + get_dummy_ops(substream) =3D ops; =20 runtime->hw =3D dummy->pcm_hw; if (substream->pcm->device & 1) { @@ -593,7 +595,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *sub= stream) err =3D model->capture_constraints(substream->runtime); } if (err < 0) { - dummy->timer_ops->free(substream); + get_dummy_ops(substream)->free(substream); return err; } return 0; @@ -601,8 +603,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *sub= stream) =20 static int dummy_pcm_close(struct snd_pcm_substream *substream) { - struct snd_dummy *dummy =3D snd_pcm_substream_chip(substream); - dummy->timer_ops->free(substream); + get_dummy_ops(substream)->free(substream); return 0; } =20 diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 075f32483769..7b8532453c4f 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -2289,7 +2289,6 @@ int snd_usbmidi_create(struct snd_card *card, else err =3D snd_usbmidi_create_endpoints(umidi, endpoints); if (err < 0) { - snd_usbmidi_free(umidi); return err; } =20 diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/br= owsers/annotate.c index 0575905d1205..6d7e7ca7c251 100644 --- a/tools/perf/util/ui/browsers/annotate.c +++ b/tools/perf/util/ui/browsers/annotate.c @@ -276,11 +276,11 @@ static int annotate_browser__run(struct annotate_brow= ser *self, int evidx, nd =3D self->curr_hot; break; case K_UNTAB: - if (nd !=3D NULL) + if (nd !=3D NULL) { nd =3D rb_next(nd); if (nd =3D=3D NULL) nd =3D rb_first(&self->entries); - else + } else nd =3D self->curr_hot; break; case 'H': =0D --=-D5NFU6NFVyTDevrPhqlY-- --=-MG3KiWKiyB3BB5eI867o Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIVAwUAVtLta+e/yOyVhhEJAQpbtxAAl0JEBjwB+mbRCw0JGzPtPWYABcSfNGUq tvfrcfT4c7cOEDz4ev5c78cTY0Croa0Y+BhL9VZ1Y+J8B+nV4Z+Uo0UOHnXfHuM5 vexOO2bw6avL2ABT5+ifODOArcMJm5ZPbSB8JUVuHMGKZP8y3A3z5jXRofn73RTF C1uXBXs/E26vReab+VvdEI5V98OB+6dJnVLFWKMCzDGqY4v9kokUpob3YPghJ0RX WRszrHN+cn/O9oK1j48Sm9OJDPyW9AB5A7SSI/KndrWyke8uzSvaqATj8vk+yZul BSs9desLKQIIxke0JmZyMXwyq+KwMccnexWGuqPncxL8o/jOiYwi65kqrwtrhv5A vmEQO3RBJAZ7clBJ2+0vZBDYH2Z8ZJmLQxpoELaFjBrv1W/1JdI6Hp2SkymIb7VF OLabkA59R/S7t+cYP9cu/Yo2HRTBn3k747IetWdLNQJk/x8dz4efn/YAvPGNnuKC IApkyuzu+a4J/YGJE8y69Dx0Ip62UFUHQEgoUk4ItGqgSNsyXyMOSaS0JgbLdFBx pM3zyFOw4HczP43xGzCqESE1yEDwfYj/kxW3QvtW7pmGNtLnNnmiEhfRBkcxPWMN 0gOTh08QeI17z78U/SGfV+C9unxGpAH+V+Ww8NY/3EzkxvDrAse/ZNTKGgTtjZmW jvAeazBkzk4= =RXEP -----END PGP SIGNATURE----- --=-MG3KiWKiyB3BB5eI867o--