diff options
167 files changed, 5809 insertions, 2543 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index d08759aa0903..d77fbd8b79ac 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
| @@ -1915,6 +1915,12 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 1915 | Format: { 0 | 1 } | 1915 | Format: { 0 | 1 } |
| 1916 | See arch/parisc/kernel/pdc_chassis.c | 1916 | See arch/parisc/kernel/pdc_chassis.c |
| 1917 | 1917 | ||
| 1918 | percpu_alloc= [X86] Select which percpu first chunk allocator to use. | ||
| 1919 | Allowed values are one of "lpage", "embed" and "4k". | ||
| 1920 | See comments in arch/x86/kernel/setup_percpu.c for | ||
| 1921 | details on each allocator. This parameter is primarily | ||
| 1922 | for debugging and performance comparison. | ||
| 1923 | |||
| 1918 | pf. [PARIDE] | 1924 | pf. [PARIDE] |
| 1919 | See Documentation/blockdev/paride.txt. | 1925 | See Documentation/blockdev/paride.txt. |
| 1920 | 1926 | ||
| @@ -2467,7 +2473,8 @@ and is between 256 and 4096 characters. It is defined in the file | |||
| 2467 | 2473 | ||
| 2468 | tp720= [HW,PS2] | 2474 | tp720= [HW,PS2] |
| 2469 | 2475 | ||
| 2470 | trace_buf_size=nn[KMG] [ftrace] will set tracing buffer size. | 2476 | trace_buf_size=nn[KMG] |
| 2477 | [FTRACE] will set tracing buffer size. | ||
| 2471 | 2478 | ||
| 2472 | trix= [HW,OSS] MediaTrix AudioTrix Pro | 2479 | trix= [HW,OSS] MediaTrix AudioTrix Pro |
| 2473 | Format: | 2480 | Format: |
diff --git a/Documentation/leds-lp3944.txt b/Documentation/leds-lp3944.txt new file mode 100644 index 000000000000..c6eda18b15ef --- /dev/null +++ b/Documentation/leds-lp3944.txt | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | Kernel driver lp3944 | ||
| 2 | ==================== | ||
| 3 | |||
| 4 | * National Semiconductor LP3944 Fun-light Chip | ||
| 5 | Prefix: 'lp3944' | ||
| 6 | Addresses scanned: None (see the Notes section below) | ||
| 7 | Datasheet: Publicly available at the National Semiconductor website | ||
| 8 | http://www.national.com/pf/LP/LP3944.html | ||
| 9 | |||
| 10 | Authors: | ||
| 11 | Antonio Ospite <ospite@studenti.unina.it> | ||
| 12 | |||
| 13 | |||
| 14 | Description | ||
| 15 | ----------- | ||
| 16 | The LP3944 is a helper chip that can drive up to 8 leds, with two programmable | ||
| 17 | DIM modes; it could even be used as a gpio expander but this driver assumes it | ||
| 18 | is used as a led controller. | ||
| 19 | |||
| 20 | The DIM modes are used to set _blink_ patterns for leds, the pattern is | ||
| 21 | specified supplying two parameters: | ||
| 22 | - period: from 0s to 1.6s | ||
| 23 | - duty cycle: percentage of the period the led is on, from 0 to 100 | ||
| 24 | |||
| 25 | Setting a led in DIM0 or DIM1 mode makes it blink according to the pattern. | ||
| 26 | See the datasheet for details. | ||
| 27 | |||
| 28 | LP3944 can be found on Motorola A910 smartphone, where it drives the rgb | ||
| 29 | leds, the camera flash light and the lcds power. | ||
| 30 | |||
| 31 | |||
| 32 | Notes | ||
| 33 | ----- | ||
| 34 | The chip is used mainly in embedded contexts, so this driver expects it is | ||
| 35 | registered using the i2c_board_info mechanism. | ||
| 36 | |||
| 37 | To register the chip at address 0x60 on adapter 0, set the platform data | ||
| 38 | according to include/linux/leds-lp3944.h, set the i2c board info: | ||
| 39 | |||
| 40 | static struct i2c_board_info __initdata a910_i2c_board_info[] = { | ||
| 41 | { | ||
| 42 | I2C_BOARD_INFO("lp3944", 0x60), | ||
| 43 | .platform_data = &a910_lp3944_leds, | ||
| 44 | }, | ||
| 45 | }; | ||
| 46 | |||
| 47 | and register it in the platform init function | ||
| 48 | |||
| 49 | i2c_register_board_info(0, a910_i2c_board_info, | ||
| 50 | ARRAY_SIZE(a910_i2c_board_info)); | ||
diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 8d999d862d0e..79f533f38c61 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt | |||
| @@ -1238,1122 +1238,7 @@ descriptions for the SOC devices for which new nodes have been | |||
| 1238 | defined; this list will expand as more and more SOC-containing | 1238 | defined; this list will expand as more and more SOC-containing |
| 1239 | platforms are moved over to use the flattened-device-tree model. | 1239 | platforms are moved over to use the flattened-device-tree model. |
| 1240 | 1240 | ||
| 1241 | a) PHY nodes | 1241 | VII - Specifying interrupt information for devices |
| 1242 | |||
| 1243 | Required properties: | ||
| 1244 | |||
| 1245 | - device_type : Should be "ethernet-phy" | ||
| 1246 | - interrupts : <a b> where a is the interrupt number and b is a | ||
| 1247 | field that represents an encoding of the sense and level | ||
| 1248 | information for the interrupt. This should be encoded based on | ||
| 1249 | the information in section 2) depending on the type of interrupt | ||
| 1250 | controller you have. | ||
| 1251 | - interrupt-parent : the phandle for the interrupt controller that | ||
| 1252 | services interrupts for this device. | ||
| 1253 | - reg : The ID number for the phy, usually a small integer | ||
| 1254 | - linux,phandle : phandle for this node; likely referenced by an | ||
| 1255 | ethernet controller node. | ||
| 1256 | |||
| 1257 | |||
| 1258 | Example: | ||
| 1259 | |||
| 1260 | ethernet-phy@0 { | ||
| 1261 | linux,phandle = <2452000> | ||
| 1262 | interrupt-parent = <40000>; | ||
| 1263 | interrupts = <35 1>; | ||
| 1264 | reg = <0>; | ||
| 1265 | device_type = "ethernet-phy"; | ||
| 1266 | }; | ||
| 1267 | |||
| 1268 | |||
| 1269 | b) Interrupt controllers | ||
| 1270 | |||
| 1271 | Some SOC devices contain interrupt controllers that are different | ||
| 1272 | from the standard Open PIC specification. The SOC device nodes for | ||
| 1273 | these types of controllers should be specified just like a standard | ||
| 1274 | OpenPIC controller. Sense and level information should be encoded | ||
| 1275 | as specified in section 2) of this chapter for each device that | ||
| 1276 | specifies an interrupt. | ||
| 1277 | |||
| 1278 | Example : | ||
| 1279 | |||
| 1280 | pic@40000 { | ||
| 1281 | linux,phandle = <40000>; | ||
| 1282 | interrupt-controller; | ||
| 1283 | #address-cells = <0>; | ||
| 1284 | reg = <40000 40000>; | ||
| 1285 | compatible = "chrp,open-pic"; | ||
| 1286 | device_type = "open-pic"; | ||
| 1287 | }; | ||
| 1288 | |||
| 1289 | c) 4xx/Axon EMAC ethernet nodes | ||
| 1290 | |||
| 1291 | The EMAC ethernet controller in IBM and AMCC 4xx chips, and also | ||
| 1292 | the Axon bridge. To operate this needs to interact with a ths | ||
| 1293 | special McMAL DMA controller, and sometimes an RGMII or ZMII | ||
| 1294 | interface. In addition to the nodes and properties described | ||
| 1295 | below, the node for the OPB bus on which the EMAC sits must have a | ||
| 1296 | correct clock-frequency property. | ||
| 1297 | |||
| 1298 | i) The EMAC node itself | ||
| 1299 | |||
| 1300 | Required properties: | ||
| 1301 | - device_type : "network" | ||
| 1302 | |||
| 1303 | - compatible : compatible list, contains 2 entries, first is | ||
| 1304 | "ibm,emac-CHIP" where CHIP is the host ASIC (440gx, | ||
| 1305 | 405gp, Axon) and second is either "ibm,emac" or | ||
| 1306 | "ibm,emac4". For Axon, thus, we have: "ibm,emac-axon", | ||
| 1307 | "ibm,emac4" | ||
| 1308 | - interrupts : <interrupt mapping for EMAC IRQ and WOL IRQ> | ||
| 1309 | - interrupt-parent : optional, if needed for interrupt mapping | ||
| 1310 | - reg : <registers mapping> | ||
| 1311 | - local-mac-address : 6 bytes, MAC address | ||
| 1312 | - mal-device : phandle of the associated McMAL node | ||
| 1313 | - mal-tx-channel : 1 cell, index of the tx channel on McMAL associated | ||
| 1314 | with this EMAC | ||
| 1315 | - mal-rx-channel : 1 cell, index of the rx channel on McMAL associated | ||
| 1316 | with this EMAC | ||
| 1317 | - cell-index : 1 cell, hardware index of the EMAC cell on a given | ||
| 1318 | ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on | ||
| 1319 | each Axon chip) | ||
| 1320 | - max-frame-size : 1 cell, maximum frame size supported in bytes | ||
| 1321 | - rx-fifo-size : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec | ||
| 1322 | operations. | ||
| 1323 | For Axon, 2048 | ||
| 1324 | - tx-fifo-size : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec | ||
| 1325 | operations. | ||
| 1326 | For Axon, 2048. | ||
| 1327 | - fifo-entry-size : 1 cell, size of a fifo entry (used to calculate | ||
| 1328 | thresholds). | ||
| 1329 | For Axon, 0x00000010 | ||
| 1330 | - mal-burst-size : 1 cell, MAL burst size (used to calculate thresholds) | ||
| 1331 | in bytes. | ||
| 1332 | For Axon, 0x00000100 (I think ...) | ||
| 1333 | - phy-mode : string, mode of operations of the PHY interface. | ||
| 1334 | Supported values are: "mii", "rmii", "smii", "rgmii", | ||
| 1335 | "tbi", "gmii", rtbi", "sgmii". | ||
| 1336 | For Axon on CAB, it is "rgmii" | ||
| 1337 | - mdio-device : 1 cell, required iff using shared MDIO registers | ||
| 1338 | (440EP). phandle of the EMAC to use to drive the | ||
| 1339 | MDIO lines for the PHY used by this EMAC. | ||
| 1340 | - zmii-device : 1 cell, required iff connected to a ZMII. phandle of | ||
| 1341 | the ZMII device node | ||
| 1342 | - zmii-channel : 1 cell, required iff connected to a ZMII. Which ZMII | ||
| 1343 | channel or 0xffffffff if ZMII is only used for MDIO. | ||
| 1344 | - rgmii-device : 1 cell, required iff connected to an RGMII. phandle | ||
| 1345 | of the RGMII device node. | ||
| 1346 | For Axon: phandle of plb5/plb4/opb/rgmii | ||
| 1347 | - rgmii-channel : 1 cell, required iff connected to an RGMII. Which | ||
| 1348 | RGMII channel is used by this EMAC. | ||
| 1349 | Fox Axon: present, whatever value is appropriate for each | ||
| 1350 | EMAC, that is the content of the current (bogus) "phy-port" | ||
| 1351 | property. | ||
| 1352 | |||
| 1353 | Optional properties: | ||
| 1354 | - phy-address : 1 cell, optional, MDIO address of the PHY. If absent, | ||
| 1355 | a search is performed. | ||
| 1356 | - phy-map : 1 cell, optional, bitmap of addresses to probe the PHY | ||
| 1357 | for, used if phy-address is absent. bit 0x00000001 is | ||
| 1358 | MDIO address 0. | ||
| 1359 | For Axon it can be absent, though my current driver | ||
| 1360 | doesn't handle phy-address yet so for now, keep | ||
| 1361 | 0x00ffffff in it. | ||
| 1362 | - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec | ||
| 1363 | operations (if absent the value is the same as | ||
| 1364 | rx-fifo-size). For Axon, either absent or 2048. | ||
| 1365 | - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec | ||
| 1366 | operations (if absent the value is the same as | ||
| 1367 | tx-fifo-size). For Axon, either absent or 2048. | ||
| 1368 | - tah-device : 1 cell, optional. If connected to a TAH engine for | ||
| 1369 | offload, phandle of the TAH device node. | ||
| 1370 | - tah-channel : 1 cell, optional. If appropriate, channel used on the | ||
| 1371 | TAH engine. | ||
| 1372 | |||
| 1373 | Example: | ||
| 1374 | |||
| 1375 | EMAC0: ethernet@40000800 { | ||
| 1376 | device_type = "network"; | ||
| 1377 | compatible = "ibm,emac-440gp", "ibm,emac"; | ||
| 1378 | interrupt-parent = <&UIC1>; | ||
| 1379 | interrupts = <1c 4 1d 4>; | ||
| 1380 | reg = <40000800 70>; | ||
| 1381 | local-mac-address = [00 04 AC E3 1B 1E]; | ||
| 1382 | mal-device = <&MAL0>; | ||
| 1383 | mal-tx-channel = <0 1>; | ||
| 1384 | mal-rx-channel = <0>; | ||
| 1385 | cell-index = <0>; | ||
| 1386 | max-frame-size = <5dc>; | ||
| 1387 | rx-fifo-size = <1000>; | ||
| 1388 | tx-fifo-size = <800>; | ||
| 1389 | phy-mode = "rmii"; | ||
| 1390 | phy-map = <00000001>; | ||
| 1391 | zmii-device = <&ZMII0>; | ||
| 1392 | zmii-channel = <0>; | ||
| 1393 | }; | ||
| 1394 | |||
| 1395 | ii) McMAL node | ||
| 1396 | |||
| 1397 | Required properties: | ||
| 1398 | - device_type : "dma-controller" | ||
| 1399 | - compatible : compatible list, containing 2 entries, first is | ||
| 1400 | "ibm,mcmal-CHIP" where CHIP is the host ASIC (like | ||
| 1401 | emac) and the second is either "ibm,mcmal" or | ||
| 1402 | "ibm,mcmal2". | ||
| 1403 | For Axon, "ibm,mcmal-axon","ibm,mcmal2" | ||
| 1404 | - interrupts : <interrupt mapping for the MAL interrupts sources: | ||
| 1405 | 5 sources: tx_eob, rx_eob, serr, txde, rxde>. | ||
| 1406 | For Axon: This is _different_ from the current | ||
| 1407 | firmware. We use the "delayed" interrupts for txeob | ||
| 1408 | and rxeob. Thus we end up with mapping those 5 MPIC | ||
| 1409 | interrupts, all level positive sensitive: 10, 11, 32, | ||
| 1410 | 33, 34 (in decimal) | ||
| 1411 | - dcr-reg : < DCR registers range > | ||
| 1412 | - dcr-parent : if needed for dcr-reg | ||
| 1413 | - num-tx-chans : 1 cell, number of Tx channels | ||
| 1414 | - num-rx-chans : 1 cell, number of Rx channels | ||
| 1415 | |||
| 1416 | iii) ZMII node | ||
| 1417 | |||
| 1418 | Required properties: | ||
| 1419 | - compatible : compatible list, containing 2 entries, first is | ||
| 1420 | "ibm,zmii-CHIP" where CHIP is the host ASIC (like | ||
| 1421 | EMAC) and the second is "ibm,zmii". | ||
| 1422 | For Axon, there is no ZMII node. | ||
| 1423 | - reg : <registers mapping> | ||
| 1424 | |||
| 1425 | iv) RGMII node | ||
| 1426 | |||
| 1427 | Required properties: | ||
| 1428 | - compatible : compatible list, containing 2 entries, first is | ||
| 1429 | "ibm,rgmii-CHIP" where CHIP is the host ASIC (like | ||
| 1430 | EMAC) and the second is "ibm,rgmii". | ||
| 1431 | For Axon, "ibm,rgmii-axon","ibm,rgmii" | ||
| 1432 | - reg : <registers mapping> | ||
| 1433 | - revision : as provided by the RGMII new version register if | ||
| 1434 | available. | ||
| 1435 | For Axon: 0x0000012a | ||
| 1436 | |||
| 1437 | d) Xilinx IP cores | ||
| 1438 | |||
| 1439 | The Xilinx EDK toolchain ships with a set of IP cores (devices) for use | ||
| 1440 | in Xilinx Spartan and Virtex FPGAs. The devices cover the whole range | ||
| 1441 | of standard device types (network, serial, etc.) and miscellaneous | ||
| 1442 | devices (gpio, LCD, spi, etc). Also, since these devices are | ||
| 1443 | implemented within the fpga fabric every instance of the device can be | ||
| 1444 | synthesised with different options that change the behaviour. | ||
| 1445 | |||
| 1446 | Each IP-core has a set of parameters which the FPGA designer can use to | ||
| 1447 | control how the core is synthesized. Historically, the EDK tool would | ||
| 1448 | extract the device parameters relevant to device drivers and copy them | ||
| 1449 | into an 'xparameters.h' in the form of #define symbols. This tells the | ||
| 1450 | device drivers how the IP cores are configured, but it requres the kernel | ||
| 1451 | to be recompiled every time the FPGA bitstream is resynthesized. | ||
| 1452 | |||
| 1453 | The new approach is to export the parameters into the device tree and | ||
| 1454 | generate a new device tree each time the FPGA bitstream changes. The | ||
| 1455 | parameters which used to be exported as #defines will now become | ||
| 1456 | properties of the device node. In general, device nodes for IP-cores | ||
| 1457 | will take the following form: | ||
| 1458 | |||
| 1459 | (name): (generic-name)@(base-address) { | ||
| 1460 | compatible = "xlnx,(ip-core-name)-(HW_VER)" | ||
| 1461 | [, (list of compatible devices), ...]; | ||
| 1462 | reg = <(baseaddr) (size)>; | ||
| 1463 | interrupt-parent = <&interrupt-controller-phandle>; | ||
| 1464 | interrupts = < ... >; | ||
| 1465 | xlnx,(parameter1) = "(string-value)"; | ||
| 1466 | xlnx,(parameter2) = <(int-value)>; | ||
| 1467 | }; | ||
| 1468 | |||
| 1469 | (generic-name): an open firmware-style name that describes the | ||
| 1470 | generic class of device. Preferably, this is one word, such | ||
| 1471 | as 'serial' or 'ethernet'. | ||
| 1472 | (ip-core-name): the name of the ip block (given after the BEGIN | ||
| 1473 | directive in system.mhs). Should be in lowercase | ||
| 1474 | and all underscores '_' converted to dashes '-'. | ||
| 1475 | (name): is derived from the "PARAMETER INSTANCE" value. | ||
| 1476 | (parameter#): C_* parameters from system.mhs. The C_ prefix is | ||
| 1477 | dropped from the parameter name, the name is converted | ||
| 1478 | to lowercase and all underscore '_' characters are | ||
| 1479 | converted to dashes '-'. | ||
| 1480 | (baseaddr): the baseaddr parameter value (often named C_BASEADDR). | ||
| 1481 | (HW_VER): from the HW_VER parameter. | ||
| 1482 | (size): the address range size (often C_HIGHADDR - C_BASEADDR + 1). | ||
| 1483 | |||
| 1484 | Typically, the compatible list will include the exact IP core version | ||
| 1485 | followed by an older IP core version which implements the same | ||
| 1486 | interface or any other device with the same interface. | ||
| 1487 | |||
| 1488 | 'reg', 'interrupt-parent' and 'interrupts' are all optional properties. | ||
| 1489 | |||
| 1490 | For example, the following block from system.mhs: | ||
| 1491 | |||
| 1492 | BEGIN opb_uartlite | ||
| 1493 | PARAMETER INSTANCE = opb_uartlite_0 | ||
| 1494 | PARAMETER HW_VER = 1.00.b | ||
| 1495 | PARAMETER C_BAUDRATE = 115200 | ||
| 1496 | PARAMETER C_DATA_BITS = 8 | ||
| 1497 | PARAMETER C_ODD_PARITY = 0 | ||
| 1498 | PARAMETER C_USE_PARITY = 0 | ||
| 1499 | PARAMETER C_CLK_FREQ = 50000000 | ||
| 1500 | PARAMETER C_BASEADDR = 0xEC100000 | ||
| 1501 | PARAMETER C_HIGHADDR = 0xEC10FFFF | ||
| 1502 | BUS_INTERFACE SOPB = opb_7 | ||
| 1503 | PORT OPB_Clk = CLK_50MHz | ||
| 1504 | PORT Interrupt = opb_uartlite_0_Interrupt | ||
| 1505 | PORT RX = opb_uartlite_0_RX | ||
| 1506 | PORT TX = opb_uartlite_0_TX | ||
| 1507 | PORT OPB_Rst = sys_bus_reset_0 | ||
| 1508 | END | ||
| 1509 | |||
| 1510 | becomes the following device tree node: | ||
| 1511 | |||
| 1512 | opb_uartlite_0: serial@ec100000 { | ||
| 1513 | device_type = "serial"; | ||
| 1514 | compatible = "xlnx,opb-uartlite-1.00.b"; | ||
| 1515 | reg = <ec100000 10000>; | ||
| 1516 | interrupt-parent = <&opb_intc_0>; | ||
| 1517 | interrupts = <1 0>; // got this from the opb_intc parameters | ||
| 1518 | current-speed = <d#115200>; // standard serial device prop | ||
| 1519 | clock-frequency = <d#50000000>; // standard serial device prop | ||
| 1520 | xlnx,data-bits = <8>; | ||
| 1521 | xlnx,odd-parity = <0>; | ||
| 1522 | xlnx,use-parity = <0>; | ||
| 1523 | }; | ||
| 1524 | |||
| 1525 | Some IP cores actually implement 2 or more logical devices. In | ||
| 1526 | this case, the device should still describe the whole IP core with | ||
| 1527 | a single node and add a child node for each logical device. The | ||
| 1528 | ranges property can be used to translate from parent IP-core to the | ||
| 1529 | registers of each device. In addition, the parent node should be | ||
| 1530 | compatible with the bus type 'xlnx,compound', and should contain | ||
| 1531 | #address-cells and #size-cells, as with any other bus. (Note: this | ||
| 1532 | makes the assumption that both logical devices have the same bus | ||
| 1533 | binding. If this is not true, then separate nodes should be used | ||
| 1534 | for each logical device). The 'cell-index' property can be used to | ||
| 1535 | enumerate logical devices within an IP core. For example, the | ||
| 1536 | following is the system.mhs entry for the dual ps2 controller found | ||
| 1537 | on the ml403 reference design. | ||
| 1538 | |||
| 1539 | BEGIN opb_ps2_dual_ref | ||
| 1540 | PARAMETER INSTANCE = opb_ps2_dual_ref_0 | ||
| 1541 | PARAMETER HW_VER = 1.00.a | ||
| 1542 | PARAMETER C_BASEADDR = 0xA9000000 | ||
| 1543 | PARAMETER C_HIGHADDR = 0xA9001FFF | ||
| 1544 | BUS_INTERFACE SOPB = opb_v20_0 | ||
| 1545 | PORT Sys_Intr1 = ps2_1_intr | ||
| 1546 | PORT Sys_Intr2 = ps2_2_intr | ||
| 1547 | PORT Clkin1 = ps2_clk_rx_1 | ||
| 1548 | PORT Clkin2 = ps2_clk_rx_2 | ||
| 1549 | PORT Clkpd1 = ps2_clk_tx_1 | ||
| 1550 | PORT Clkpd2 = ps2_clk_tx_2 | ||
| 1551 | PORT Rx1 = ps2_d_rx_1 | ||
| 1552 | PORT Rx2 = ps2_d_rx_2 | ||
| 1553 | PORT Txpd1 = ps2_d_tx_1 | ||
| 1554 | PORT Txpd2 = ps2_d_tx_2 | ||
| 1555 | END | ||
| 1556 | |||
| 1557 | It would result in the following device tree nodes: | ||
| 1558 | |||
| 1559 | opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 { | ||
| 1560 | #address-cells = <1>; | ||
| 1561 | #size-cells = <1>; | ||
| 1562 | compatible = "xlnx,compound"; | ||
| 1563 | ranges = <0 a9000000 2000>; | ||
| 1564 | // If this device had extra parameters, then they would | ||
| 1565 | // go here. | ||
| 1566 | ps2@0 { | ||
| 1567 | compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; | ||
| 1568 | reg = <0 40>; | ||
| 1569 | interrupt-parent = <&opb_intc_0>; | ||
| 1570 | interrupts = <3 0>; | ||
| 1571 | cell-index = <0>; | ||
| 1572 | }; | ||
| 1573 | ps2@1000 { | ||
| 1574 | compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; | ||
| 1575 | reg = <1000 40>; | ||
| 1576 | interrupt-parent = <&opb_intc_0>; | ||
| 1577 | interrupts = <3 0>; | ||
| 1578 | cell-index = <0>; | ||
| 1579 | }; | ||
| 1580 | }; | ||
| 1581 | |||
| 1582 | Also, the system.mhs file defines bus attachments from the processor | ||
| 1583 | to the devices. The device tree structure should reflect the bus | ||
| 1584 | attachments. Again an example; this system.mhs fragment: | ||
| 1585 | |||
| 1586 | BEGIN ppc405_virtex4 | ||
| 1587 | PARAMETER INSTANCE = ppc405_0 | ||
| 1588 | PARAMETER HW_VER = 1.01.a | ||
| 1589 | BUS_INTERFACE DPLB = plb_v34_0 | ||
| 1590 | BUS_INTERFACE IPLB = plb_v34_0 | ||
| 1591 | END | ||
| 1592 | |||
| 1593 | BEGIN opb_intc | ||
| 1594 | PARAMETER INSTANCE = opb_intc_0 | ||
| 1595 | PARAMETER HW_VER = 1.00.c | ||
| 1596 | PARAMETER C_BASEADDR = 0xD1000FC0 | ||
| 1597 | PARAMETER C_HIGHADDR = 0xD1000FDF | ||
| 1598 | BUS_INTERFACE SOPB = opb_v20_0 | ||
| 1599 | END | ||
| 1600 | |||
| 1601 | BEGIN opb_uart16550 | ||
| 1602 | PARAMETER INSTANCE = opb_uart16550_0 | ||
| 1603 | PARAMETER HW_VER = 1.00.d | ||
| 1604 | PARAMETER C_BASEADDR = 0xa0000000 | ||
| 1605 | PARAMETER C_HIGHADDR = 0xa0001FFF | ||
| 1606 | BUS_INTERFACE SOPB = opb_v20_0 | ||
| 1607 | END | ||
| 1608 | |||
| 1609 | BEGIN plb_v34 | ||
| 1610 | PARAMETER INSTANCE = plb_v34_0 | ||
| 1611 | PARAMETER HW_VER = 1.02.a | ||
| 1612 | END | ||
| 1613 | |||
| 1614 | BEGIN plb_bram_if_cntlr | ||
| 1615 | PARAMETER INSTANCE = plb_bram_if_cntlr_0 | ||
| 1616 | PARAMETER HW_VER = 1.00.b | ||
| 1617 | PARAMETER C_BASEADDR = 0xFFFF0000 | ||
| 1618 | PARAMETER C_HIGHADDR = 0xFFFFFFFF | ||
| 1619 | BUS_INTERFACE SPLB = plb_v34_0 | ||
| 1620 | END | ||
| 1621 | |||
| 1622 | BEGIN plb2opb_bridge | ||
| 1623 | PARAMETER INSTANCE = plb2opb_bridge_0 | ||
| 1624 | PARAMETER HW_VER = 1.01.a | ||
| 1625 | PARAMETER C_RNG0_BASEADDR = 0x20000000 | ||
| 1626 | PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF | ||
| 1627 | PARAMETER C_RNG1_BASEADDR = 0x60000000 | ||
| 1628 | PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF | ||
| 1629 | PARAMETER C_RNG2_BASEADDR = 0x80000000 | ||
| 1630 | PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF | ||
| 1631 | PARAMETER C_RNG3_BASEADDR = 0xC0000000 | ||
| 1632 | PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF | ||
| 1633 | BUS_INTERFACE SPLB = plb_v34_0 | ||
| 1634 | BUS_INTERFACE MOPB = opb_v20_0 | ||
| 1635 | END | ||
| 1636 | |||
| 1637 | Gives this device tree (some properties removed for clarity): | ||
| 1638 | |||
| 1639 | plb@0 { | ||
| 1640 | #address-cells = <1>; | ||
| 1641 | #size-cells = <1>; | ||
| 1642 | compatible = "xlnx,plb-v34-1.02.a"; | ||
| 1643 | device_type = "ibm,plb"; | ||
| 1644 | ranges; // 1:1 translation | ||
| 1645 | |||
| 1646 | plb_bram_if_cntrl_0: bram@ffff0000 { | ||
| 1647 | reg = <ffff0000 10000>; | ||
| 1648 | } | ||
| 1649 | |||
| 1650 | opb@20000000 { | ||
| 1651 | #address-cells = <1>; | ||
| 1652 | #size-cells = <1>; | ||
| 1653 | ranges = <20000000 20000000 20000000 | ||
| 1654 | 60000000 60000000 20000000 | ||
| 1655 | 80000000 80000000 40000000 | ||
| 1656 | c0000000 c0000000 20000000>; | ||
| 1657 | |||
| 1658 | opb_uart16550_0: serial@a0000000 { | ||
| 1659 | reg = <a00000000 2000>; | ||
| 1660 | }; | ||
| 1661 | |||
| 1662 | opb_intc_0: interrupt-controller@d1000fc0 { | ||
| 1663 | reg = <d1000fc0 20>; | ||
| 1664 | }; | ||
| 1665 | }; | ||
| 1666 | }; | ||
| 1667 | |||
| 1668 | That covers the general approach to binding xilinx IP cores into the | ||
| 1669 | device tree. The following are bindings for specific devices: | ||
| 1670 | |||
| 1671 | i) Xilinx ML300 Framebuffer | ||
| 1672 | |||
| 1673 | Simple framebuffer device from the ML300 reference design (also on the | ||
| 1674 | ML403 reference design as well as others). | ||
| 1675 | |||
| 1676 | Optional properties: | ||
| 1677 | - resolution = <xres yres> : pixel resolution of framebuffer. Some | ||
| 1678 | implementations use a different resolution. | ||
| 1679 | Default is <d#640 d#480> | ||
| 1680 | - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory. | ||
| 1681 | Default is <d#1024 d#480>. | ||
| 1682 | - rotate-display (empty) : rotate display 180 degrees. | ||
| 1683 | |||
| 1684 | ii) Xilinx SystemACE | ||
| 1685 | |||
| 1686 | The Xilinx SystemACE device is used to program FPGAs from an FPGA | ||
| 1687 | bitstream stored on a CF card. It can also be used as a generic CF | ||
| 1688 | interface device. | ||
| 1689 | |||
| 1690 | Optional properties: | ||
| 1691 | - 8-bit (empty) : Set this property for SystemACE in 8 bit mode | ||
| 1692 | |||
| 1693 | iii) Xilinx EMAC and Xilinx TEMAC | ||
| 1694 | |||
| 1695 | Xilinx Ethernet devices. In addition to general xilinx properties | ||
| 1696 | listed above, nodes for these devices should include a phy-handle | ||
| 1697 | property, and may include other common network device properties | ||
| 1698 | like local-mac-address. | ||
| 1699 | |||
| 1700 | iv) Xilinx Uartlite | ||
| 1701 | |||
| 1702 | Xilinx uartlite devices are simple fixed speed serial ports. | ||
| 1703 | |||
| 1704 | Required properties: | ||
| 1705 | - current-speed : Baud rate of uartlite | ||
| 1706 | |||
| 1707 | v) Xilinx hwicap | ||
| 1708 | |||
| 1709 | Xilinx hwicap devices provide access to the configuration logic | ||
| 1710 | of the FPGA through the Internal Configuration Access Port | ||
| 1711 | (ICAP). The ICAP enables partial reconfiguration of the FPGA, | ||
| 1712 | readback of the configuration information, and some control over | ||
| 1713 | 'warm boots' of the FPGA fabric. | ||
| 1714 | |||
| 1715 | Required properties: | ||
| 1716 | - xlnx,family : The family of the FPGA, necessary since the | ||
| 1717 | capabilities of the underlying ICAP hardware | ||
| 1718 | differ between different families. May be | ||
| 1719 | 'virtex2p', 'virtex4', or 'virtex5'. | ||
| 1720 | |||
| 1721 | vi) Xilinx Uart 16550 | ||
| 1722 | |||
| 1723 | Xilinx UART 16550 devices are very similar to the NS16550 but with | ||
| 1724 | different register spacing and an offset from the base address. | ||
| 1725 | |||
| 1726 | Required properties: | ||
| 1727 | - clock-frequency : Frequency of the clock input | ||
| 1728 | - reg-offset : A value of 3 is required | ||
| 1729 | - reg-shift : A value of 2 is required | ||
| 1730 | |||
| 1731 | e) USB EHCI controllers | ||
| 1732 | |||
| 1733 | Required properties: | ||
| 1734 | - compatible : should be "usb-ehci". | ||
| 1735 | - reg : should contain at least address and length of the standard EHCI | ||
| 1736 | register set for the device. Optional platform-dependent registers | ||
| 1737 | (debug-port or other) can be also specified here, but only after | ||
| 1738 | definition of standard EHCI registers. | ||
| 1739 | - interrupts : one EHCI interrupt should be described here. | ||
| 1740 | If device registers are implemented in big endian mode, the device | ||
| 1741 | node should have "big-endian-regs" property. | ||
| 1742 | If controller implementation operates with big endian descriptors, | ||
| 1743 | "big-endian-desc" property should be specified. | ||
| 1744 | If both big endian registers and descriptors are used by the controller | ||
| 1745 | implementation, "big-endian" property can be specified instead of having | ||
| 1746 | both "big-endian-regs" and "big-endian-desc". | ||
| 1747 | |||
| 1748 | Example (Sequoia 440EPx): | ||
| 1749 | ehci@e0000300 { | ||
| 1750 | compatible = "ibm,usb-ehci-440epx", "usb-ehci"; | ||
| 1751 | interrupt-parent = <&UIC0>; | ||
| 1752 | interrupts = <1a 4>; | ||
| 1753 | reg = <0 e0000300 90 0 e0000390 70>; | ||
| 1754 | big-endian; | ||
| 1755 | }; | ||
| 1756 | |||
| 1757 | f) MDIO on GPIOs | ||
| 1758 | |||
| 1759 | Currently defined compatibles: | ||
| 1760 | - virtual,gpio-mdio | ||
| 1761 | |||
| 1762 | MDC and MDIO lines connected to GPIO controllers are listed in the | ||
| 1763 | gpios property as described in section VIII.1 in the following order: | ||
| 1764 | |||
| 1765 | MDC, MDIO. | ||
| 1766 | |||
| 1767 | Example: | ||
| 1768 | |||
| 1769 | mdio { | ||
| 1770 | compatible = "virtual,mdio-gpio"; | ||
| 1771 | #address-cells = <1>; | ||
| 1772 | #size-cells = <0>; | ||
| 1773 | gpios = <&qe_pio_a 11 | ||
| 1774 | &qe_pio_c 6>; | ||
| 1775 | }; | ||
| 1776 | |||
| 1777 | g) SPI (Serial Peripheral Interface) busses | ||
| 1778 | |||
| 1779 | SPI busses can be described with a node for the SPI master device | ||
| 1780 | and a set of child nodes for each SPI slave on the bus. For this | ||
| 1781 | discussion, it is assumed that the system's SPI controller is in | ||
| 1782 | SPI master mode. This binding does not describe SPI controllers | ||
| 1783 | in slave mode. | ||
| 1784 | |||
| 1785 | The SPI master node requires the following properties: | ||
| 1786 | - #address-cells - number of cells required to define a chip select | ||
| 1787 | address on the SPI bus. | ||
| 1788 | - #size-cells - should be zero. | ||
| 1789 | - compatible - name of SPI bus controller following generic names | ||
| 1790 | recommended practice. | ||
| 1791 | No other properties are required in the SPI bus node. It is assumed | ||
| 1792 | that a driver for an SPI bus device will understand that it is an SPI bus. | ||
| 1793 | However, the binding does not attempt to define the specific method for | ||
| 1794 | assigning chip select numbers. Since SPI chip select configuration is | ||
| 1795 | flexible and non-standardized, it is left out of this binding with the | ||
| 1796 | assumption that board specific platform code will be used to manage | ||
| 1797 | chip selects. Individual drivers can define additional properties to | ||
| 1798 | support describing the chip select layout. | ||
| 1799 | |||
| 1800 | SPI slave nodes must be children of the SPI master node and can | ||
| 1801 | contain the following properties. | ||
| 1802 | - reg - (required) chip select address of device. | ||
| 1803 | - compatible - (required) name of SPI device following generic names | ||
| 1804 | recommended practice | ||
| 1805 | - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz | ||
| 1806 | - spi-cpol - (optional) Empty property indicating device requires | ||
| 1807 | inverse clock polarity (CPOL) mode | ||
| 1808 | - spi-cpha - (optional) Empty property indicating device requires | ||
| 1809 | shifted clock phase (CPHA) mode | ||
| 1810 | - spi-cs-high - (optional) Empty property indicating device requires | ||
| 1811 | chip select active high | ||
| 1812 | |||
| 1813 | SPI example for an MPC5200 SPI bus: | ||
| 1814 | spi@f00 { | ||
| 1815 | #address-cells = <1>; | ||
| 1816 | #size-cells = <0>; | ||
| 1817 | compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi"; | ||
| 1818 | reg = <0xf00 0x20>; | ||
| 1819 | interrupts = <2 13 0 2 14 0>; | ||
| 1820 | interrupt-parent = <&mpc5200_pic>; | ||
| 1821 | |||
| 1822 | ethernet-switch@0 { | ||
| 1823 | compatible = "micrel,ks8995m"; | ||
| 1824 | spi-max-frequency = <1000000>; | ||
| 1825 | reg = <0>; | ||
| 1826 | }; | ||
| 1827 | |||
| 1828 | codec@1 { | ||
| 1829 | compatible = "ti,tlv320aic26"; | ||
| 1830 | spi-max-frequency = <100000>; | ||
| 1831 | reg = <1>; | ||
| 1832 | }; | ||
| 1833 | }; | ||
| 1834 | |||
| 1835 | VII - Marvell Discovery mv64[345]6x System Controller chips | ||
| 1836 | =========================================================== | ||
| 1837 | |||
| 1838 | The Marvell mv64[345]60 series of system controller chips contain | ||
| 1839 | many of the peripherals needed to implement a complete computer | ||
| 1840 | system. In this section, we define device tree nodes to describe | ||
| 1841 | the system controller chip itself and each of the peripherals | ||
| 1842 | which it contains. Compatible string values for each node are | ||
| 1843 | prefixed with the string "marvell,", for Marvell Technology Group Ltd. | ||
| 1844 | |||
| 1845 | 1) The /system-controller node | ||
| 1846 | |||
| 1847 | This node is used to represent the system-controller and must be | ||
| 1848 | present when the system uses a system controller chip. The top-level | ||
| 1849 | system-controller node contains information that is global to all | ||
| 1850 | devices within the system controller chip. The node name begins | ||
| 1851 | with "system-controller" followed by the unit address, which is | ||
| 1852 | the base address of the memory-mapped register set for the system | ||
| 1853 | controller chip. | ||
| 1854 | |||
| 1855 | Required properties: | ||
| 1856 | |||
| 1857 | - ranges : Describes the translation of system controller addresses | ||
| 1858 | for memory mapped registers. | ||
| 1859 | - clock-frequency: Contains the main clock frequency for the system | ||
| 1860 | controller chip. | ||
| 1861 | - reg : This property defines the address and size of the | ||
| 1862 | memory-mapped registers contained within the system controller | ||
| 1863 | chip. The address specified in the "reg" property should match | ||
| 1864 | the unit address of the system-controller node. | ||
| 1865 | - #address-cells : Address representation for system controller | ||
| 1866 | devices. This field represents the number of cells needed to | ||
| 1867 | represent the address of the memory-mapped registers of devices | ||
| 1868 | within the system controller chip. | ||
| 1869 | - #size-cells : Size representation for for the memory-mapped | ||
| 1870 | registers within the system controller chip. | ||
| 1871 | - #interrupt-cells : Defines the width of cells used to represent | ||
| 1872 | interrupts. | ||
| 1873 | |||
| 1874 | Optional properties: | ||
| 1875 | |||
| 1876 | - model : The specific model of the system controller chip. Such | ||
| 1877 | as, "mv64360", "mv64460", or "mv64560". | ||
| 1878 | - compatible : A string identifying the compatibility identifiers | ||
| 1879 | of the system controller chip. | ||
| 1880 | |||
| 1881 | The system-controller node contains child nodes for each system | ||
| 1882 | controller device that the platform uses. Nodes should not be created | ||
| 1883 | for devices which exist on the system controller chip but are not used | ||
| 1884 | |||
| 1885 | Example Marvell Discovery mv64360 system-controller node: | ||
| 1886 | |||
| 1887 | system-controller@f1000000 { /* Marvell Discovery mv64360 */ | ||
| 1888 | #address-cells = <1>; | ||
| 1889 | #size-cells = <1>; | ||
| 1890 | model = "mv64360"; /* Default */ | ||
| 1891 | compatible = "marvell,mv64360"; | ||
| 1892 | clock-frequency = <133333333>; | ||
| 1893 | reg = <0xf1000000 0x10000>; | ||
| 1894 | virtual-reg = <0xf1000000>; | ||
| 1895 | ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */ | ||
| 1896 | 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */ | ||
| 1897 | 0xa0000000 0xa0000000 0x4000000 /* User FLASH */ | ||
| 1898 | 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */ | ||
| 1899 | 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */ | ||
| 1900 | |||
| 1901 | [ child node definitions... ] | ||
| 1902 | } | ||
| 1903 | |||
| 1904 | 2) Child nodes of /system-controller | ||
| 1905 | |||
| 1906 | a) Marvell Discovery MDIO bus | ||
| 1907 | |||
| 1908 | The MDIO is a bus to which the PHY devices are connected. For each | ||
| 1909 | device that exists on this bus, a child node should be created. See | ||
| 1910 | the definition of the PHY node below for an example of how to define | ||
| 1911 | a PHY. | ||
| 1912 | |||
| 1913 | Required properties: | ||
| 1914 | - #address-cells : Should be <1> | ||
| 1915 | - #size-cells : Should be <0> | ||
| 1916 | - device_type : Should be "mdio" | ||
| 1917 | - compatible : Should be "marvell,mv64360-mdio" | ||
| 1918 | |||
| 1919 | Example: | ||
| 1920 | |||
| 1921 | mdio { | ||
| 1922 | #address-cells = <1>; | ||
| 1923 | #size-cells = <0>; | ||
| 1924 | device_type = "mdio"; | ||
| 1925 | compatible = "marvell,mv64360-mdio"; | ||
| 1926 | |||
| 1927 | ethernet-phy@0 { | ||
| 1928 | ...... | ||
| 1929 | }; | ||
| 1930 | }; | ||
| 1931 | |||
| 1932 | |||
| 1933 | b) Marvell Discovery ethernet controller | ||
| 1934 | |||
| 1935 | The Discover ethernet controller is described with two levels | ||
| 1936 | of nodes. The first level describes an ethernet silicon block | ||
| 1937 | and the second level describes up to 3 ethernet nodes within | ||
| 1938 | that block. The reason for the multiple levels is that the | ||
| 1939 | registers for the node are interleaved within a single set | ||
| 1940 | of registers. The "ethernet-block" level describes the | ||
| 1941 | shared register set, and the "ethernet" nodes describe ethernet | ||
| 1942 | port-specific properties. | ||
| 1943 | |||
| 1944 | Ethernet block node | ||
| 1945 | |||
| 1946 | Required properties: | ||
| 1947 | - #address-cells : <1> | ||
| 1948 | - #size-cells : <0> | ||
| 1949 | - compatible : "marvell,mv64360-eth-block" | ||
| 1950 | - reg : Offset and length of the register set for this block | ||
| 1951 | |||
| 1952 | Example Discovery Ethernet block node: | ||
| 1953 | ethernet-block@2000 { | ||
| 1954 | #address-cells = <1>; | ||
| 1955 | #size-cells = <0>; | ||
| 1956 | compatible = "marvell,mv64360-eth-block"; | ||
| 1957 | reg = <0x2000 0x2000>; | ||
| 1958 | ethernet@0 { | ||
| 1959 | ....... | ||
| 1960 | }; | ||
| 1961 | }; | ||
| 1962 | |||
| 1963 | Ethernet port node | ||
| 1964 | |||
| 1965 | Required properties: | ||
| 1966 | - device_type : Should be "network". | ||
| 1967 | - compatible : Should be "marvell,mv64360-eth". | ||
| 1968 | - reg : Should be <0>, <1>, or <2>, according to which registers | ||
| 1969 | within the silicon block the device uses. | ||
| 1970 | - interrupts : <a> where a is the interrupt number for the port. | ||
| 1971 | - interrupt-parent : the phandle for the interrupt controller | ||
| 1972 | that services interrupts for this device. | ||
| 1973 | - phy : the phandle for the PHY connected to this ethernet | ||
| 1974 | controller. | ||
| 1975 | - local-mac-address : 6 bytes, MAC address | ||
| 1976 | |||
| 1977 | Example Discovery Ethernet port node: | ||
| 1978 | ethernet@0 { | ||
| 1979 | device_type = "network"; | ||
| 1980 | compatible = "marvell,mv64360-eth"; | ||
| 1981 | reg = <0>; | ||
| 1982 | interrupts = <32>; | ||
| 1983 | interrupt-parent = <&PIC>; | ||
| 1984 | phy = <&PHY0>; | ||
| 1985 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 1986 | }; | ||
| 1987 | |||
| 1988 | |||
| 1989 | |||
| 1990 | c) Marvell Discovery PHY nodes | ||
| 1991 | |||
| 1992 | Required properties: | ||
| 1993 | - device_type : Should be "ethernet-phy" | ||
| 1994 | - interrupts : <a> where a is the interrupt number for this phy. | ||
| 1995 | - interrupt-parent : the phandle for the interrupt controller that | ||
| 1996 | services interrupts for this device. | ||
| 1997 | - reg : The ID number for the phy, usually a small integer | ||
| 1998 | |||
| 1999 | Example Discovery PHY node: | ||
| 2000 | ethernet-phy@1 { | ||
| 2001 | device_type = "ethernet-phy"; | ||
| 2002 | compatible = "broadcom,bcm5421"; | ||
| 2003 | interrupts = <76>; /* GPP 12 */ | ||
| 2004 | interrupt-parent = <&PIC>; | ||
| 2005 | reg = <1>; | ||
| 2006 | }; | ||
| 2007 | |||
| 2008 | |||
| 2009 | d) Marvell Discovery SDMA nodes | ||
| 2010 | |||
| 2011 | Represent DMA hardware associated with the MPSC (multiprotocol | ||
| 2012 | serial controllers). | ||
| 2013 | |||
| 2014 | Required properties: | ||
| 2015 | - compatible : "marvell,mv64360-sdma" | ||
| 2016 | - reg : Offset and length of the register set for this device | ||
| 2017 | - interrupts : <a> where a is the interrupt number for the DMA | ||
| 2018 | device. | ||
| 2019 | - interrupt-parent : the phandle for the interrupt controller | ||
| 2020 | that services interrupts for this device. | ||
| 2021 | |||
| 2022 | Example Discovery SDMA node: | ||
| 2023 | sdma@4000 { | ||
| 2024 | compatible = "marvell,mv64360-sdma"; | ||
| 2025 | reg = <0x4000 0xc18>; | ||
| 2026 | virtual-reg = <0xf1004000>; | ||
| 2027 | interrupts = <36>; | ||
| 2028 | interrupt-parent = <&PIC>; | ||
| 2029 | }; | ||
| 2030 | |||
| 2031 | |||
| 2032 | e) Marvell Discovery BRG nodes | ||
| 2033 | |||
| 2034 | Represent baud rate generator hardware associated with the MPSC | ||
| 2035 | (multiprotocol serial controllers). | ||
| 2036 | |||
| 2037 | Required properties: | ||
| 2038 | - compatible : "marvell,mv64360-brg" | ||
| 2039 | - reg : Offset and length of the register set for this device | ||
| 2040 | - clock-src : A value from 0 to 15 which selects the clock | ||
| 2041 | source for the baud rate generator. This value corresponds | ||
| 2042 | to the CLKS value in the BRGx configuration register. See | ||
| 2043 | the mv64x60 User's Manual. | ||
| 2044 | - clock-frequence : The frequency (in Hz) of the baud rate | ||
| 2045 | generator's input clock. | ||
| 2046 | - current-speed : The current speed setting (presumably by | ||
| 2047 | firmware) of the baud rate generator. | ||
| 2048 | |||
| 2049 | Example Discovery BRG node: | ||
| 2050 | brg@b200 { | ||
| 2051 | compatible = "marvell,mv64360-brg"; | ||
| 2052 | reg = <0xb200 0x8>; | ||
| 2053 | clock-src = <8>; | ||
| 2054 | clock-frequency = <133333333>; | ||
| 2055 | current-speed = <9600>; | ||
| 2056 | }; | ||
| 2057 | |||
| 2058 | |||
| 2059 | f) Marvell Discovery CUNIT nodes | ||
| 2060 | |||
| 2061 | Represent the Serial Communications Unit device hardware. | ||
| 2062 | |||
| 2063 | Required properties: | ||
| 2064 | - reg : Offset and length of the register set for this device | ||
| 2065 | |||
| 2066 | Example Discovery CUNIT node: | ||
| 2067 | cunit@f200 { | ||
| 2068 | reg = <0xf200 0x200>; | ||
| 2069 | }; | ||
| 2070 | |||
| 2071 | |||
| 2072 | g) Marvell Discovery MPSCROUTING nodes | ||
| 2073 | |||
| 2074 | Represent the Discovery's MPSC routing hardware | ||
| 2075 | |||
| 2076 | Required properties: | ||
| 2077 | - reg : Offset and length of the register set for this device | ||
| 2078 | |||
| 2079 | Example Discovery CUNIT node: | ||
| 2080 | mpscrouting@b500 { | ||
| 2081 | reg = <0xb400 0xc>; | ||
| 2082 | }; | ||
| 2083 | |||
| 2084 | |||
| 2085 | h) Marvell Discovery MPSCINTR nodes | ||
| 2086 | |||
| 2087 | Represent the Discovery's MPSC DMA interrupt hardware registers | ||
| 2088 | (SDMA cause and mask registers). | ||
| 2089 | |||
| 2090 | Required properties: | ||
| 2091 | - reg : Offset and length of the register set for this device | ||
| 2092 | |||
| 2093 | Example Discovery MPSCINTR node: | ||
| 2094 | mpsintr@b800 { | ||
| 2095 | reg = <0xb800 0x100>; | ||
| 2096 | }; | ||
| 2097 | |||
| 2098 | |||
| 2099 | i) Marvell Discovery MPSC nodes | ||
| 2100 | |||
| 2101 | Represent the Discovery's MPSC (Multiprotocol Serial Controller) | ||
| 2102 | serial port. | ||
| 2103 | |||
| 2104 | Required properties: | ||
| 2105 | - device_type : "serial" | ||
| 2106 | - compatible : "marvell,mv64360-mpsc" | ||
| 2107 | - reg : Offset and length of the register set for this device | ||
| 2108 | - sdma : the phandle for the SDMA node used by this port | ||
| 2109 | - brg : the phandle for the BRG node used by this port | ||
| 2110 | - cunit : the phandle for the CUNIT node used by this port | ||
| 2111 | - mpscrouting : the phandle for the MPSCROUTING node used by this port | ||
| 2112 | - mpscintr : the phandle for the MPSCINTR node used by this port | ||
| 2113 | - cell-index : the hardware index of this cell in the MPSC core | ||
| 2114 | - max_idle : value needed for MPSC CHR3 (Maximum Frame Length) | ||
| 2115 | register | ||
| 2116 | - interrupts : <a> where a is the interrupt number for the MPSC. | ||
| 2117 | - interrupt-parent : the phandle for the interrupt controller | ||
| 2118 | that services interrupts for this device. | ||
| 2119 | |||
| 2120 | Example Discovery MPSCINTR node: | ||
| 2121 | mpsc@8000 { | ||
| 2122 | device_type = "serial"; | ||
| 2123 | compatible = "marvell,mv64360-mpsc"; | ||
| 2124 | reg = <0x8000 0x38>; | ||
| 2125 | virtual-reg = <0xf1008000>; | ||
| 2126 | sdma = <&SDMA0>; | ||
| 2127 | brg = <&BRG0>; | ||
| 2128 | cunit = <&CUNIT>; | ||
| 2129 | mpscrouting = <&MPSCROUTING>; | ||
| 2130 | mpscintr = <&MPSCINTR>; | ||
| 2131 | cell-index = <0>; | ||
| 2132 | max_idle = <40>; | ||
| 2133 | interrupts = <40>; | ||
| 2134 | interrupt-parent = <&PIC>; | ||
| 2135 | }; | ||
| 2136 | |||
| 2137 | |||
| 2138 | j) Marvell Discovery Watch Dog Timer nodes | ||
| 2139 | |||
| 2140 | Represent the Discovery's watchdog timer hardware | ||
| 2141 | |||
| 2142 | Required properties: | ||
| 2143 | - compatible : "marvell,mv64360-wdt" | ||
| 2144 | - reg : Offset and length of the register set for this device | ||
| 2145 | |||
| 2146 | Example Discovery Watch Dog Timer node: | ||
| 2147 | wdt@b410 { | ||
| 2148 | compatible = "marvell,mv64360-wdt"; | ||
| 2149 | reg = <0xb410 0x8>; | ||
| 2150 | }; | ||
| 2151 | |||
| 2152 | |||
| 2153 | k) Marvell Discovery I2C nodes | ||
| 2154 | |||
| 2155 | Represent the Discovery's I2C hardware | ||
| 2156 | |||
| 2157 | Required properties: | ||
| 2158 | - device_type : "i2c" | ||
| 2159 | - compatible : "marvell,mv64360-i2c" | ||
| 2160 | - reg : Offset and length of the register set for this device | ||
| 2161 | - interrupts : <a> where a is the interrupt number for the I2C. | ||
| 2162 | - interrupt-parent : the phandle for the interrupt controller | ||
| 2163 | that services interrupts for this device. | ||
| 2164 | |||
| 2165 | Example Discovery I2C node: | ||
| 2166 | compatible = "marvell,mv64360-i2c"; | ||
| 2167 | reg = <0xc000 0x20>; | ||
| 2168 | virtual-reg = <0xf100c000>; | ||
| 2169 | interrupts = <37>; | ||
| 2170 | interrupt-parent = <&PIC>; | ||
| 2171 | }; | ||
| 2172 | |||
| 2173 | |||
| 2174 | l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes | ||
| 2175 | |||
| 2176 | Represent the Discovery's PIC hardware | ||
| 2177 | |||
| 2178 | Required properties: | ||
| 2179 | - #interrupt-cells : <1> | ||
| 2180 | - #address-cells : <0> | ||
| 2181 | - compatible : "marvell,mv64360-pic" | ||
| 2182 | - reg : Offset and length of the register set for this device | ||
| 2183 | - interrupt-controller | ||
| 2184 | |||
| 2185 | Example Discovery PIC node: | ||
| 2186 | pic { | ||
| 2187 | #interrupt-cells = <1>; | ||
| 2188 | #address-cells = <0>; | ||
| 2189 | compatible = "marvell,mv64360-pic"; | ||
| 2190 | reg = <0x0 0x88>; | ||
| 2191 | interrupt-controller; | ||
| 2192 | }; | ||
| 2193 | |||
| 2194 | |||
| 2195 | m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes | ||
| 2196 | |||
| 2197 | Represent the Discovery's MPP hardware | ||
| 2198 | |||
| 2199 | Required properties: | ||
| 2200 | - compatible : "marvell,mv64360-mpp" | ||
| 2201 | - reg : Offset and length of the register set for this device | ||
| 2202 | |||
| 2203 | Example Discovery MPP node: | ||
| 2204 | mpp@f000 { | ||
| 2205 | compatible = "marvell,mv64360-mpp"; | ||
| 2206 | reg = <0xf000 0x10>; | ||
| 2207 | }; | ||
| 2208 | |||
| 2209 | |||
| 2210 | n) Marvell Discovery GPP (General Purpose Pins) nodes | ||
| 2211 | |||
| 2212 | Represent the Discovery's GPP hardware | ||
| 2213 | |||
| 2214 | Required properties: | ||
| 2215 | - compatible : "marvell,mv64360-gpp" | ||
| 2216 | - reg : Offset and length of the register set for this device | ||
| 2217 | |||
| 2218 | Example Discovery GPP node: | ||
| 2219 | gpp@f000 { | ||
| 2220 | compatible = "marvell,mv64360-gpp"; | ||
| 2221 | reg = <0xf100 0x20>; | ||
| 2222 | }; | ||
| 2223 | |||
| 2224 | |||
| 2225 | o) Marvell Discovery PCI host bridge node | ||
| 2226 | |||
| 2227 | Represents the Discovery's PCI host bridge device. The properties | ||
| 2228 | for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE | ||
| 2229 | 1275-1994. A typical value for the compatible property is | ||
| 2230 | "marvell,mv64360-pci". | ||
| 2231 | |||
| 2232 | Example Discovery PCI host bridge node | ||
| 2233 | pci@80000000 { | ||
| 2234 | #address-cells = <3>; | ||
| 2235 | #size-cells = <2>; | ||
| 2236 | #interrupt-cells = <1>; | ||
| 2237 | device_type = "pci"; | ||
| 2238 | compatible = "marvell,mv64360-pci"; | ||
| 2239 | reg = <0xcf8 0x8>; | ||
| 2240 | ranges = <0x01000000 0x0 0x0 | ||
| 2241 | 0x88000000 0x0 0x01000000 | ||
| 2242 | 0x02000000 0x0 0x80000000 | ||
| 2243 | 0x80000000 0x0 0x08000000>; | ||
| 2244 | bus-range = <0 255>; | ||
| 2245 | clock-frequency = <66000000>; | ||
| 2246 | interrupt-parent = <&PIC>; | ||
| 2247 | interrupt-map-mask = <0xf800 0x0 0x0 0x7>; | ||
| 2248 | interrupt-map = < | ||
| 2249 | /* IDSEL 0x0a */ | ||
| 2250 | 0x5000 0 0 1 &PIC 80 | ||
| 2251 | 0x5000 0 0 2 &PIC 81 | ||
| 2252 | 0x5000 0 0 3 &PIC 91 | ||
| 2253 | 0x5000 0 0 4 &PIC 93 | ||
| 2254 | |||
| 2255 | /* IDSEL 0x0b */ | ||
| 2256 | 0x5800 0 0 1 &PIC 91 | ||
| 2257 | 0x5800 0 0 2 &PIC 93 | ||
| 2258 | 0x5800 0 0 3 &PIC 80 | ||
| 2259 | 0x5800 0 0 4 &PIC 81 | ||
| 2260 | |||
| 2261 | /* IDSEL 0x0c */ | ||
| 2262 | 0x6000 0 0 1 &PIC 91 | ||
| 2263 | 0x6000 0 0 2 &PIC 93 | ||
| 2264 | 0x6000 0 0 3 &PIC 80 | ||
| 2265 | 0x6000 0 0 4 &PIC 81 | ||
| 2266 | |||
| 2267 | /* IDSEL 0x0d */ | ||
| 2268 | 0x6800 0 0 1 &PIC 93 | ||
| 2269 | 0x6800 0 0 2 &PIC 80 | ||
| 2270 | 0x6800 0 0 3 &PIC 81 | ||
| 2271 | 0x6800 0 0 4 &PIC 91 | ||
| 2272 | >; | ||
| 2273 | }; | ||
| 2274 | |||
| 2275 | |||
| 2276 | p) Marvell Discovery CPU Error nodes | ||
| 2277 | |||
| 2278 | Represent the Discovery's CPU error handler device. | ||
| 2279 | |||
| 2280 | Required properties: | ||
| 2281 | - compatible : "marvell,mv64360-cpu-error" | ||
| 2282 | - reg : Offset and length of the register set for this device | ||
| 2283 | - interrupts : the interrupt number for this device | ||
| 2284 | - interrupt-parent : the phandle for the interrupt controller | ||
| 2285 | that services interrupts for this device. | ||
| 2286 | |||
| 2287 | Example Discovery CPU Error node: | ||
| 2288 | cpu-error@0070 { | ||
| 2289 | compatible = "marvell,mv64360-cpu-error"; | ||
| 2290 | reg = <0x70 0x10 0x128 0x28>; | ||
| 2291 | interrupts = <3>; | ||
| 2292 | interrupt-parent = <&PIC>; | ||
| 2293 | }; | ||
| 2294 | |||
| 2295 | |||
| 2296 | q) Marvell Discovery SRAM Controller nodes | ||
| 2297 | |||
| 2298 | Represent the Discovery's SRAM controller device. | ||
| 2299 | |||
| 2300 | Required properties: | ||
| 2301 | - compatible : "marvell,mv64360-sram-ctrl" | ||
| 2302 | - reg : Offset and length of the register set for this device | ||
| 2303 | - interrupts : the interrupt number for this device | ||
| 2304 | - interrupt-parent : the phandle for the interrupt controller | ||
| 2305 | that services interrupts for this device. | ||
| 2306 | |||
| 2307 | Example Discovery SRAM Controller node: | ||
| 2308 | sram-ctrl@0380 { | ||
| 2309 | compatible = "marvell,mv64360-sram-ctrl"; | ||
| 2310 | reg = <0x380 0x80>; | ||
| 2311 | interrupts = <13>; | ||
| 2312 | interrupt-parent = <&PIC>; | ||
| 2313 | }; | ||
| 2314 | |||
| 2315 | |||
| 2316 | r) Marvell Discovery PCI Error Handler nodes | ||
| 2317 | |||
| 2318 | Represent the Discovery's PCI error handler device. | ||
| 2319 | |||
| 2320 | Required properties: | ||
| 2321 | - compatible : "marvell,mv64360-pci-error" | ||
| 2322 | - reg : Offset and length of the register set for this device | ||
| 2323 | - interrupts : the interrupt number for this device | ||
| 2324 | - interrupt-parent : the phandle for the interrupt controller | ||
| 2325 | that services interrupts for this device. | ||
| 2326 | |||
| 2327 | Example Discovery PCI Error Handler node: | ||
| 2328 | pci-error@1d40 { | ||
| 2329 | compatible = "marvell,mv64360-pci-error"; | ||
| 2330 | reg = <0x1d40 0x40 0xc28 0x4>; | ||
| 2331 | interrupts = <12>; | ||
| 2332 | interrupt-parent = <&PIC>; | ||
| 2333 | }; | ||
| 2334 | |||
| 2335 | |||
| 2336 | s) Marvell Discovery Memory Controller nodes | ||
| 2337 | |||
| 2338 | Represent the Discovery's memory controller device. | ||
| 2339 | |||
| 2340 | Required properties: | ||
| 2341 | - compatible : "marvell,mv64360-mem-ctrl" | ||
| 2342 | - reg : Offset and length of the register set for this device | ||
| 2343 | - interrupts : the interrupt number for this device | ||
| 2344 | - interrupt-parent : the phandle for the interrupt controller | ||
| 2345 | that services interrupts for this device. | ||
| 2346 | |||
| 2347 | Example Discovery Memory Controller node: | ||
| 2348 | mem-ctrl@1400 { | ||
| 2349 | compatible = "marvell,mv64360-mem-ctrl"; | ||
| 2350 | reg = <0x1400 0x60>; | ||
| 2351 | interrupts = <17>; | ||
| 2352 | interrupt-parent = <&PIC>; | ||
| 2353 | }; | ||
| 2354 | |||
| 2355 | |||
| 2356 | VIII - Specifying interrupt information for devices | ||
| 2357 | =================================================== | 1242 | =================================================== |
| 2358 | 1243 | ||
| 2359 | The device tree represents the busses and devices of a hardware | 1244 | The device tree represents the busses and devices of a hardware |
| @@ -2439,56 +1324,7 @@ encodings listed below: | |||
| 2439 | 2 = high to low edge sensitive type enabled | 1324 | 2 = high to low edge sensitive type enabled |
| 2440 | 3 = low to high edge sensitive type enabled | 1325 | 3 = low to high edge sensitive type enabled |
| 2441 | 1326 | ||
| 2442 | IX - Specifying GPIO information for devices | 1327 | VIII - Specifying Device Power Management Information (sleep property) |
| 2443 | ============================================ | ||
| 2444 | |||
| 2445 | 1) gpios property | ||
| 2446 | ----------------- | ||
| 2447 | |||
| 2448 | Nodes that makes use of GPIOs should define them using `gpios' property, | ||
| 2449 | format of which is: <&gpio-controller1-phandle gpio1-specifier | ||
| 2450 | &gpio-controller2-phandle gpio2-specifier | ||
| 2451 | 0 /* holes are permitted, means no GPIO 3 */ | ||
| 2452 | &gpio-controller4-phandle gpio4-specifier | ||
| 2453 | ...>; | ||
| 2454 | |||
| 2455 | Note that gpio-specifier length is controller dependent. | ||
| 2456 | |||
| 2457 | gpio-specifier may encode: bank, pin position inside the bank, | ||
| 2458 | whether pin is open-drain and whether pin is logically inverted. | ||
| 2459 | |||
| 2460 | Example of the node using GPIOs: | ||
| 2461 | |||
| 2462 | node { | ||
| 2463 | gpios = <&qe_pio_e 18 0>; | ||
| 2464 | }; | ||
| 2465 | |||
| 2466 | In this example gpio-specifier is "18 0" and encodes GPIO pin number, | ||
| 2467 | and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller. | ||
| 2468 | |||
| 2469 | 2) gpio-controller nodes | ||
| 2470 | ------------------------ | ||
| 2471 | |||
| 2472 | Every GPIO controller node must have #gpio-cells property defined, | ||
| 2473 | this information will be used to translate gpio-specifiers. | ||
| 2474 | |||
| 2475 | Example of two SOC GPIO banks defined as gpio-controller nodes: | ||
| 2476 | |||
| 2477 | qe_pio_a: gpio-controller@1400 { | ||
| 2478 | #gpio-cells = <2>; | ||
| 2479 | compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank"; | ||
| 2480 | reg = <0x1400 0x18>; | ||
| 2481 | gpio-controller; | ||
| 2482 | }; | ||
| 2483 | |||
| 2484 | qe_pio_e: gpio-controller@1460 { | ||
| 2485 | #gpio-cells = <2>; | ||
| 2486 | compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; | ||
| 2487 | reg = <0x1460 0x18>; | ||
| 2488 | gpio-controller; | ||
| 2489 | }; | ||
| 2490 | |||
| 2491 | X - Specifying Device Power Management Information (sleep property) | ||
| 2492 | =================================================================== | 1328 | =================================================================== |
| 2493 | 1329 | ||
| 2494 | Devices on SOCs often have mechanisms for placing devices into low-power | 1330 | Devices on SOCs often have mechanisms for placing devices into low-power |
diff --git a/Documentation/powerpc/dts-bindings/4xx/emac.txt b/Documentation/powerpc/dts-bindings/4xx/emac.txt new file mode 100644 index 000000000000..2161334a7ca5 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/4xx/emac.txt | |||
| @@ -0,0 +1,148 @@ | |||
| 1 | 4xx/Axon EMAC ethernet nodes | ||
| 2 | |||
| 3 | The EMAC ethernet controller in IBM and AMCC 4xx chips, and also | ||
| 4 | the Axon bridge. To operate this needs to interact with a ths | ||
| 5 | special McMAL DMA controller, and sometimes an RGMII or ZMII | ||
| 6 | interface. In addition to the nodes and properties described | ||
| 7 | below, the node for the OPB bus on which the EMAC sits must have a | ||
| 8 | correct clock-frequency property. | ||
| 9 | |||
| 10 | i) The EMAC node itself | ||
| 11 | |||
| 12 | Required properties: | ||
| 13 | - device_type : "network" | ||
| 14 | |||
| 15 | - compatible : compatible list, contains 2 entries, first is | ||
| 16 | "ibm,emac-CHIP" where CHIP is the host ASIC (440gx, | ||
| 17 | 405gp, Axon) and second is either "ibm,emac" or | ||
| 18 | "ibm,emac4". For Axon, thus, we have: "ibm,emac-axon", | ||
| 19 | "ibm,emac4" | ||
| 20 | - interrupts : <interrupt mapping for EMAC IRQ and WOL IRQ> | ||
| 21 | - interrupt-parent : optional, if needed for interrupt mapping | ||
| 22 | - reg : <registers mapping> | ||
| 23 | - local-mac-address : 6 bytes, MAC address | ||
| 24 | - mal-device : phandle of the associated McMAL node | ||
| 25 | - mal-tx-channel : 1 cell, index of the tx channel on McMAL associated | ||
| 26 | with this EMAC | ||
| 27 | - mal-rx-channel : 1 cell, index of the rx channel on McMAL associated | ||
| 28 | with this EMAC | ||
| 29 | - cell-index : 1 cell, hardware index of the EMAC cell on a given | ||
| 30 | ASIC (typically 0x0 and 0x1 for EMAC0 and EMAC1 on | ||
| 31 | each Axon chip) | ||
| 32 | - max-frame-size : 1 cell, maximum frame size supported in bytes | ||
| 33 | - rx-fifo-size : 1 cell, Rx fifo size in bytes for 10 and 100 Mb/sec | ||
| 34 | operations. | ||
| 35 | For Axon, 2048 | ||
| 36 | - tx-fifo-size : 1 cell, Tx fifo size in bytes for 10 and 100 Mb/sec | ||
| 37 | operations. | ||
| 38 | For Axon, 2048. | ||
| 39 | - fifo-entry-size : 1 cell, size of a fifo entry (used to calculate | ||
| 40 | thresholds). | ||
| 41 | For Axon, 0x00000010 | ||
| 42 | - mal-burst-size : 1 cell, MAL burst size (used to calculate thresholds) | ||
| 43 | in bytes. | ||
| 44 | For Axon, 0x00000100 (I think ...) | ||
| 45 | - phy-mode : string, mode of operations of the PHY interface. | ||
| 46 | Supported values are: "mii", "rmii", "smii", "rgmii", | ||
| 47 | "tbi", "gmii", rtbi", "sgmii". | ||
| 48 | For Axon on CAB, it is "rgmii" | ||
| 49 | - mdio-device : 1 cell, required iff using shared MDIO registers | ||
| 50 | (440EP). phandle of the EMAC to use to drive the | ||
| 51 | MDIO lines for the PHY used by this EMAC. | ||
| 52 | - zmii-device : 1 cell, required iff connected to a ZMII. phandle of | ||
| 53 | the ZMII device node | ||
| 54 | - zmii-channel : 1 cell, required iff connected to a ZMII. Which ZMII | ||
| 55 | channel or 0xffffffff if ZMII is only used for MDIO. | ||
| 56 | - rgmii-device : 1 cell, required iff connected to an RGMII. phandle | ||
| 57 | of the RGMII device node. | ||
| 58 | For Axon: phandle of plb5/plb4/opb/rgmii | ||
| 59 | - rgmii-channel : 1 cell, required iff connected to an RGMII. Which | ||
| 60 | RGMII channel is used by this EMAC. | ||
| 61 | Fox Axon: present, whatever value is appropriate for each | ||
| 62 | EMAC, that is the content of the current (bogus) "phy-port" | ||
| 63 | property. | ||
| 64 | |||
| 65 | Optional properties: | ||
| 66 | - phy-address : 1 cell, optional, MDIO address of the PHY. If absent, | ||
| 67 | a search is performed. | ||
| 68 | - phy-map : 1 cell, optional, bitmap of addresses to probe the PHY | ||
| 69 | for, used if phy-address is absent. bit 0x00000001 is | ||
| 70 | MDIO address 0. | ||
| 71 | For Axon it can be absent, though my current driver | ||
| 72 | doesn't handle phy-address yet so for now, keep | ||
| 73 | 0x00ffffff in it. | ||
| 74 | - rx-fifo-size-gige : 1 cell, Rx fifo size in bytes for 1000 Mb/sec | ||
| 75 | operations (if absent the value is the same as | ||
| 76 | rx-fifo-size). For Axon, either absent or 2048. | ||
| 77 | - tx-fifo-size-gige : 1 cell, Tx fifo size in bytes for 1000 Mb/sec | ||
| 78 | operations (if absent the value is the same as | ||
| 79 | tx-fifo-size). For Axon, either absent or 2048. | ||
| 80 | - tah-device : 1 cell, optional. If connected to a TAH engine for | ||
| 81 | offload, phandle of the TAH device node. | ||
| 82 | - tah-channel : 1 cell, optional. If appropriate, channel used on the | ||
| 83 | TAH engine. | ||
| 84 | |||
| 85 | Example: | ||
| 86 | |||
| 87 | EMAC0: ethernet@40000800 { | ||
| 88 | device_type = "network"; | ||
| 89 | compatible = "ibm,emac-440gp", "ibm,emac"; | ||
| 90 | interrupt-parent = <&UIC1>; | ||
| 91 | interrupts = <1c 4 1d 4>; | ||
| 92 | reg = <40000800 70>; | ||
| 93 | local-mac-address = [00 04 AC E3 1B 1E]; | ||
| 94 | mal-device = <&MAL0>; | ||
| 95 | mal-tx-channel = <0 1>; | ||
| 96 | mal-rx-channel = <0>; | ||
| 97 | cell-index = <0>; | ||
| 98 | max-frame-size = <5dc>; | ||
| 99 | rx-fifo-size = <1000>; | ||
| 100 | tx-fifo-size = <800>; | ||
| 101 | phy-mode = "rmii"; | ||
| 102 | phy-map = <00000001>; | ||
| 103 | zmii-device = <&ZMII0>; | ||
| 104 | zmii-channel = <0>; | ||
| 105 | }; | ||
| 106 | |||
| 107 | ii) McMAL node | ||
| 108 | |||
| 109 | Required properties: | ||
| 110 | - device_type : "dma-controller" | ||
| 111 | - compatible : compatible list, containing 2 entries, first is | ||
| 112 | "ibm,mcmal-CHIP" where CHIP is the host ASIC (like | ||
| 113 | emac) and the second is either "ibm,mcmal" or | ||
| 114 | "ibm,mcmal2". | ||
| 115 | For Axon, "ibm,mcmal-axon","ibm,mcmal2" | ||
| 116 | - interrupts : <interrupt mapping for the MAL interrupts sources: | ||
| 117 | 5 sources: tx_eob, rx_eob, serr, txde, rxde>. | ||
| 118 | For Axon: This is _different_ from the current | ||
| 119 | firmware. We use the "delayed" interrupts for txeob | ||
| 120 | and rxeob. Thus we end up with mapping those 5 MPIC | ||
| 121 | interrupts, all level positive sensitive: 10, 11, 32, | ||
| 122 | 33, 34 (in decimal) | ||
| 123 | - dcr-reg : < DCR registers range > | ||
| 124 | - dcr-parent : if needed for dcr-reg | ||
| 125 | - num-tx-chans : 1 cell, number of Tx channels | ||
| 126 | - num-rx-chans : 1 cell, number of Rx channels | ||
| 127 | |||
| 128 | iii) ZMII node | ||
| 129 | |||
| 130 | Required properties: | ||
| 131 | - compatible : compatible list, containing 2 entries, first is | ||
| 132 | "ibm,zmii-CHIP" where CHIP is the host ASIC (like | ||
| 133 | EMAC) and the second is "ibm,zmii". | ||
| 134 | For Axon, there is no ZMII node. | ||
| 135 | - reg : <registers mapping> | ||
| 136 | |||
| 137 | iv) RGMII node | ||
| 138 | |||
| 139 | Required properties: | ||
| 140 | - compatible : compatible list, containing 2 entries, first is | ||
| 141 | "ibm,rgmii-CHIP" where CHIP is the host ASIC (like | ||
| 142 | EMAC) and the second is "ibm,rgmii". | ||
| 143 | For Axon, "ibm,rgmii-axon","ibm,rgmii" | ||
| 144 | - reg : <registers mapping> | ||
| 145 | - revision : as provided by the RGMII new version register if | ||
| 146 | available. | ||
| 147 | For Axon: 0x0000012a | ||
| 148 | |||
diff --git a/Documentation/powerpc/dts-bindings/gpio/gpio.txt b/Documentation/powerpc/dts-bindings/gpio/gpio.txt new file mode 100644 index 000000000000..edaa84d288a1 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/gpio/gpio.txt | |||
| @@ -0,0 +1,50 @@ | |||
| 1 | Specifying GPIO information for devices | ||
| 2 | ============================================ | ||
| 3 | |||
| 4 | 1) gpios property | ||
| 5 | ----------------- | ||
| 6 | |||
| 7 | Nodes that makes use of GPIOs should define them using `gpios' property, | ||
| 8 | format of which is: <&gpio-controller1-phandle gpio1-specifier | ||
| 9 | &gpio-controller2-phandle gpio2-specifier | ||
| 10 | 0 /* holes are permitted, means no GPIO 3 */ | ||
| 11 | &gpio-controller4-phandle gpio4-specifier | ||
| 12 | ...>; | ||
| 13 | |||
| 14 | Note that gpio-specifier length is controller dependent. | ||
| 15 | |||
| 16 | gpio-specifier may encode: bank, pin position inside the bank, | ||
| 17 | whether pin is open-drain and whether pin is logically inverted. | ||
| 18 | |||
| 19 | Example of the node using GPIOs: | ||
| 20 | |||
| 21 | node { | ||
| 22 | gpios = <&qe_pio_e 18 0>; | ||
| 23 | }; | ||
| 24 | |||
| 25 | In this example gpio-specifier is "18 0" and encodes GPIO pin number, | ||
| 26 | and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller. | ||
| 27 | |||
| 28 | 2) gpio-controller nodes | ||
| 29 | ------------------------ | ||
| 30 | |||
| 31 | Every GPIO controller node must have #gpio-cells property defined, | ||
| 32 | this information will be used to translate gpio-specifiers. | ||
| 33 | |||
| 34 | Example of two SOC GPIO banks defined as gpio-controller nodes: | ||
| 35 | |||
| 36 | qe_pio_a: gpio-controller@1400 { | ||
| 37 | #gpio-cells = <2>; | ||
| 38 | compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank"; | ||
| 39 | reg = <0x1400 0x18>; | ||
| 40 | gpio-controller; | ||
| 41 | }; | ||
| 42 | |||
| 43 | qe_pio_e: gpio-controller@1460 { | ||
| 44 | #gpio-cells = <2>; | ||
| 45 | compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; | ||
| 46 | reg = <0x1460 0x18>; | ||
| 47 | gpio-controller; | ||
| 48 | }; | ||
| 49 | |||
| 50 | |||
diff --git a/Documentation/powerpc/dts-bindings/gpio/led.txt b/Documentation/powerpc/dts-bindings/gpio/led.txt index 4fe14deedc0a..064db928c3c1 100644 --- a/Documentation/powerpc/dts-bindings/gpio/led.txt +++ b/Documentation/powerpc/dts-bindings/gpio/led.txt | |||
| @@ -16,10 +16,17 @@ LED sub-node properties: | |||
| 16 | string defining the trigger assigned to the LED. Current triggers are: | 16 | string defining the trigger assigned to the LED. Current triggers are: |
| 17 | "backlight" - LED will act as a back-light, controlled by the framebuffer | 17 | "backlight" - LED will act as a back-light, controlled by the framebuffer |
| 18 | system | 18 | system |
| 19 | "default-on" - LED will turn on | 19 | "default-on" - LED will turn on, but see "default-state" below |
| 20 | "heartbeat" - LED "double" flashes at a load average based rate | 20 | "heartbeat" - LED "double" flashes at a load average based rate |
| 21 | "ide-disk" - LED indicates disk activity | 21 | "ide-disk" - LED indicates disk activity |
| 22 | "timer" - LED flashes at a fixed, configurable rate | 22 | "timer" - LED flashes at a fixed, configurable rate |
| 23 | - default-state: (optional) The initial state of the LED. Valid | ||
| 24 | values are "on", "off", and "keep". If the LED is already on or off | ||
| 25 | and the default-state property is set the to same value, then no | ||
| 26 | glitch should be produced where the LED momentarily turns off (or | ||
| 27 | on). The "keep" setting will keep the LED at whatever its current | ||
| 28 | state is, without producing a glitch. The default is off if this | ||
| 29 | property is not present. | ||
| 23 | 30 | ||
| 24 | Examples: | 31 | Examples: |
| 25 | 32 | ||
| @@ -30,14 +37,22 @@ leds { | |||
| 30 | gpios = <&mcu_pio 0 1>; /* Active low */ | 37 | gpios = <&mcu_pio 0 1>; /* Active low */ |
| 31 | linux,default-trigger = "ide-disk"; | 38 | linux,default-trigger = "ide-disk"; |
| 32 | }; | 39 | }; |
| 40 | |||
| 41 | fault { | ||
| 42 | gpios = <&mcu_pio 1 0>; | ||
| 43 | /* Keep LED on if BIOS detected hardware fault */ | ||
| 44 | default-state = "keep"; | ||
| 45 | }; | ||
| 33 | }; | 46 | }; |
| 34 | 47 | ||
| 35 | run-control { | 48 | run-control { |
| 36 | compatible = "gpio-leds"; | 49 | compatible = "gpio-leds"; |
| 37 | red { | 50 | red { |
| 38 | gpios = <&mpc8572 6 0>; | 51 | gpios = <&mpc8572 6 0>; |
| 52 | default-state = "off"; | ||
| 39 | }; | 53 | }; |
| 40 | green { | 54 | green { |
| 41 | gpios = <&mpc8572 7 0>; | 55 | gpios = <&mpc8572 7 0>; |
| 56 | default-state = "on"; | ||
| 42 | }; | 57 | }; |
| 43 | } | 58 | } |
diff --git a/Documentation/powerpc/dts-bindings/gpio/mdio.txt b/Documentation/powerpc/dts-bindings/gpio/mdio.txt new file mode 100644 index 000000000000..bc9549529014 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/gpio/mdio.txt | |||
| @@ -0,0 +1,19 @@ | |||
| 1 | MDIO on GPIOs | ||
| 2 | |||
| 3 | Currently defined compatibles: | ||
| 4 | - virtual,gpio-mdio | ||
| 5 | |||
| 6 | MDC and MDIO lines connected to GPIO controllers are listed in the | ||
| 7 | gpios property as described in section VIII.1 in the following order: | ||
| 8 | |||
| 9 | MDC, MDIO. | ||
| 10 | |||
| 11 | Example: | ||
| 12 | |||
| 13 | mdio { | ||
| 14 | compatible = "virtual,mdio-gpio"; | ||
| 15 | #address-cells = <1>; | ||
| 16 | #size-cells = <0>; | ||
| 17 | gpios = <&qe_pio_a 11 | ||
| 18 | &qe_pio_c 6>; | ||
| 19 | }; | ||
diff --git a/Documentation/powerpc/dts-bindings/marvell.txt b/Documentation/powerpc/dts-bindings/marvell.txt new file mode 100644 index 000000000000..3708a2fd4747 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/marvell.txt | |||
| @@ -0,0 +1,521 @@ | |||
| 1 | Marvell Discovery mv64[345]6x System Controller chips | ||
| 2 | =========================================================== | ||
| 3 | |||
| 4 | The Marvell mv64[345]60 series of system controller chips contain | ||
| 5 | many of the peripherals needed to implement a complete computer | ||
| 6 | system. In this section, we define device tree nodes to describe | ||
| 7 | the system controller chip itself and each of the peripherals | ||
| 8 | which it contains. Compatible string values for each node are | ||
| 9 | prefixed with the string "marvell,", for Marvell Technology Group Ltd. | ||
| 10 | |||
| 11 | 1) The /system-controller node | ||
| 12 | |||
| 13 | This node is used to represent the system-controller and must be | ||
| 14 | present when the system uses a system controller chip. The top-level | ||
| 15 | system-controller node contains information that is global to all | ||
| 16 | devices within the system controller chip. The node name begins | ||
| 17 | with "system-controller" followed by the unit address, which is | ||
| 18 | the base address of the memory-mapped register set for the system | ||
| 19 | controller chip. | ||
| 20 | |||
| 21 | Required properties: | ||
| 22 | |||
| 23 | - ranges : Describes the translation of system controller addresses | ||
| 24 | for memory mapped registers. | ||
| 25 | - clock-frequency: Contains the main clock frequency for the system | ||
| 26 | controller chip. | ||
| 27 | - reg : This property defines the address and size of the | ||
| 28 | memory-mapped registers contained within the system controller | ||
| 29 | chip. The address specified in the "reg" property should match | ||
| 30 | the unit address of the system-controller node. | ||
| 31 | - #address-cells : Address representation for system controller | ||
| 32 | devices. This field represents the number of cells needed to | ||
| 33 | represent the address of the memory-mapped registers of devices | ||
| 34 | within the system controller chip. | ||
| 35 | - #size-cells : Size representation for for the memory-mapped | ||
| 36 | registers within the system controller chip. | ||
| 37 | - #interrupt-cells : Defines the width of cells used to represent | ||
| 38 | interrupts. | ||
| 39 | |||
| 40 | Optional properties: | ||
| 41 | |||
| 42 | - model : The specific model of the system controller chip. Such | ||
| 43 | as, "mv64360", "mv64460", or "mv64560". | ||
| 44 | - compatible : A string identifying the compatibility identifiers | ||
| 45 | of the system controller chip. | ||
| 46 | |||
| 47 | The system-controller node contains child nodes for each system | ||
| 48 | controller device that the platform uses. Nodes should not be created | ||
| 49 | for devices which exist on the system controller chip but are not used | ||
| 50 | |||
| 51 | Example Marvell Discovery mv64360 system-controller node: | ||
| 52 | |||
| 53 | system-controller@f1000000 { /* Marvell Discovery mv64360 */ | ||
| 54 | #address-cells = <1>; | ||
| 55 | #size-cells = <1>; | ||
| 56 | model = "mv64360"; /* Default */ | ||
| 57 | compatible = "marvell,mv64360"; | ||
| 58 | clock-frequency = <133333333>; | ||
| 59 | reg = <0xf1000000 0x10000>; | ||
| 60 | virtual-reg = <0xf1000000>; | ||
| 61 | ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */ | ||
| 62 | 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */ | ||
| 63 | 0xa0000000 0xa0000000 0x4000000 /* User FLASH */ | ||
| 64 | 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */ | ||
| 65 | 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */ | ||
| 66 | |||
| 67 | [ child node definitions... ] | ||
| 68 | } | ||
| 69 | |||
| 70 | 2) Child nodes of /system-controller | ||
| 71 | |||
| 72 | a) Marvell Discovery MDIO bus | ||
| 73 | |||
| 74 | The MDIO is a bus to which the PHY devices are connected. For each | ||
| 75 | device that exists on this bus, a child node should be created. See | ||
| 76 | the definition of the PHY node below for an example of how to define | ||
| 77 | a PHY. | ||
| 78 | |||
| 79 | Required properties: | ||
| 80 | - #address-cells : Should be <1> | ||
| 81 | - #size-cells : Should be <0> | ||
| 82 | - device_type : Should be "mdio" | ||
| 83 | - compatible : Should be "marvell,mv64360-mdio" | ||
| 84 | |||
| 85 | Example: | ||
| 86 | |||
| 87 | mdio { | ||
| 88 | #address-cells = <1>; | ||
| 89 | #size-cells = <0>; | ||
| 90 | device_type = "mdio"; | ||
| 91 | compatible = "marvell,mv64360-mdio"; | ||
| 92 | |||
| 93 | ethernet-phy@0 { | ||
| 94 | ...... | ||
| 95 | }; | ||
| 96 | }; | ||
| 97 | |||
| 98 | |||
| 99 | b) Marvell Discovery ethernet controller | ||
| 100 | |||
| 101 | The Discover ethernet controller is described with two levels | ||
| 102 | of nodes. The first level describes an ethernet silicon block | ||
| 103 | and the second level describes up to 3 ethernet nodes within | ||
| 104 | that block. The reason for the multiple levels is that the | ||
| 105 | registers for the node are interleaved within a single set | ||
| 106 | of registers. The "ethernet-block" level describes the | ||
| 107 | shared register set, and the "ethernet" nodes describe ethernet | ||
| 108 | port-specific properties. | ||
| 109 | |||
| 110 | Ethernet block node | ||
| 111 | |||
| 112 | Required properties: | ||
| 113 | - #address-cells : <1> | ||
| 114 | - #size-cells : <0> | ||
| 115 | - compatible : "marvell,mv64360-eth-block" | ||
| 116 | - reg : Offset and length of the register set for this block | ||
| 117 | |||
| 118 | Example Discovery Ethernet block node: | ||
| 119 | ethernet-block@2000 { | ||
| 120 | #address-cells = <1>; | ||
| 121 | #size-cells = <0>; | ||
| 122 | compatible = "marvell,mv64360-eth-block"; | ||
| 123 | reg = <0x2000 0x2000>; | ||
| 124 | ethernet@0 { | ||
| 125 | ....... | ||
| 126 | }; | ||
| 127 | }; | ||
| 128 | |||
| 129 | Ethernet port node | ||
| 130 | |||
| 131 | Required properties: | ||
| 132 | - device_type : Should be "network". | ||
| 133 | - compatible : Should be "marvell,mv64360-eth". | ||
| 134 | - reg : Should be <0>, <1>, or <2>, according to which registers | ||
| 135 | within the silicon block the device uses. | ||
| 136 | - interrupts : <a> where a is the interrupt number for the port. | ||
| 137 | - interrupt-parent : the phandle for the interrupt controller | ||
| 138 | that services interrupts for this device. | ||
| 139 | - phy : the phandle for the PHY connected to this ethernet | ||
| 140 | controller. | ||
| 141 | - local-mac-address : 6 bytes, MAC address | ||
| 142 | |||
| 143 | Example Discovery Ethernet port node: | ||
| 144 | ethernet@0 { | ||
| 145 | device_type = "network"; | ||
| 146 | compatible = "marvell,mv64360-eth"; | ||
| 147 | reg = <0>; | ||
| 148 | interrupts = <32>; | ||
| 149 | interrupt-parent = <&PIC>; | ||
| 150 | phy = <&PHY0>; | ||
| 151 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
| 152 | }; | ||
| 153 | |||
| 154 | |||
| 155 | |||
| 156 | c) Marvell Discovery PHY nodes | ||
| 157 | |||
| 158 | Required properties: | ||
| 159 | - device_type : Should be "ethernet-phy" | ||
| 160 | - interrupts : <a> where a is the interrupt number for this phy. | ||
| 161 | - interrupt-parent : the phandle for the interrupt controller that | ||
| 162 | services interrupts for this device. | ||
| 163 | - reg : The ID number for the phy, usually a small integer | ||
| 164 | |||
| 165 | Example Discovery PHY node: | ||
| 166 | ethernet-phy@1 { | ||
| 167 | device_type = "ethernet-phy"; | ||
| 168 | compatible = "broadcom,bcm5421"; | ||
| 169 | interrupts = <76>; /* GPP 12 */ | ||
| 170 | interrupt-parent = <&PIC>; | ||
| 171 | reg = <1>; | ||
| 172 | }; | ||
| 173 | |||
| 174 | |||
| 175 | d) Marvell Discovery SDMA nodes | ||
| 176 | |||
| 177 | Represent DMA hardware associated with the MPSC (multiprotocol | ||
| 178 | serial controllers). | ||
| 179 | |||
| 180 | Required properties: | ||
| 181 | - compatible : "marvell,mv64360-sdma" | ||
| 182 | - reg : Offset and length of the register set for this device | ||
| 183 | - interrupts : <a> where a is the interrupt number for the DMA | ||
| 184 | device. | ||
| 185 | - interrupt-parent : the phandle for the interrupt controller | ||
| 186 | that services interrupts for this device. | ||
| 187 | |||
| 188 | Example Discovery SDMA node: | ||
| 189 | sdma@4000 { | ||
| 190 | compatible = "marvell,mv64360-sdma"; | ||
| 191 | reg = <0x4000 0xc18>; | ||
| 192 | virtual-reg = <0xf1004000>; | ||
| 193 | interrupts = <36>; | ||
| 194 | interrupt-parent = <&PIC>; | ||
| 195 | }; | ||
| 196 | |||
| 197 | |||
| 198 | e) Marvell Discovery BRG nodes | ||
| 199 | |||
| 200 | Represent baud rate generator hardware associated with the MPSC | ||
| 201 | (multiprotocol serial controllers). | ||
| 202 | |||
| 203 | Required properties: | ||
| 204 | - compatible : "marvell,mv64360-brg" | ||
| 205 | - reg : Offset and length of the register set for this device | ||
| 206 | - clock-src : A value from 0 to 15 which selects the clock | ||
| 207 | source for the baud rate generator. This value corresponds | ||
| 208 | to the CLKS value in the BRGx configuration register. See | ||
| 209 | the mv64x60 User's Manual. | ||
| 210 | - clock-frequence : The frequency (in Hz) of the baud rate | ||
| 211 | generator's input clock. | ||
| 212 | - current-speed : The current speed setting (presumably by | ||
| 213 | firmware) of the baud rate generator. | ||
| 214 | |||
| 215 | Example Discovery BRG node: | ||
| 216 | brg@b200 { | ||
| 217 | compatible = "marvell,mv64360-brg"; | ||
| 218 | reg = <0xb200 0x8>; | ||
| 219 | clock-src = <8>; | ||
| 220 | clock-frequency = <133333333>; | ||
| 221 | current-speed = <9600>; | ||
| 222 | }; | ||
| 223 | |||
| 224 | |||
| 225 | f) Marvell Discovery CUNIT nodes | ||
| 226 | |||
| 227 | Represent the Serial Communications Unit device hardware. | ||
| 228 | |||
| 229 | Required properties: | ||
| 230 | - reg : Offset and length of the register set for this device | ||
| 231 | |||
| 232 | Example Discovery CUNIT node: | ||
| 233 | cunit@f200 { | ||
| 234 | reg = <0xf200 0x200>; | ||
| 235 | }; | ||
| 236 | |||
| 237 | |||
| 238 | g) Marvell Discovery MPSCROUTING nodes | ||
| 239 | |||
| 240 | Represent the Discovery's MPSC routing hardware | ||
| 241 | |||
| 242 | Required properties: | ||
| 243 | - reg : Offset and length of the register set for this device | ||
| 244 | |||
| 245 | Example Discovery CUNIT node: | ||
| 246 | mpscrouting@b500 { | ||
| 247 | reg = <0xb400 0xc>; | ||
| 248 | }; | ||
| 249 | |||
| 250 | |||
| 251 | h) Marvell Discovery MPSCINTR nodes | ||
| 252 | |||
| 253 | Represent the Discovery's MPSC DMA interrupt hardware registers | ||
| 254 | (SDMA cause and mask registers). | ||
| 255 | |||
| 256 | Required properties: | ||
| 257 | - reg : Offset and length of the register set for this device | ||
| 258 | |||
| 259 | Example Discovery MPSCINTR node: | ||
| 260 | mpsintr@b800 { | ||
| 261 | reg = <0xb800 0x100>; | ||
| 262 | }; | ||
| 263 | |||
| 264 | |||
| 265 | i) Marvell Discovery MPSC nodes | ||
| 266 | |||
| 267 | Represent the Discovery's MPSC (Multiprotocol Serial Controller) | ||
| 268 | serial port. | ||
| 269 | |||
| 270 | Required properties: | ||
| 271 | - device_type : "serial" | ||
| 272 | - compatible : "marvell,mv64360-mpsc" | ||
| 273 | - reg : Offset and length of the register set for this device | ||
| 274 | - sdma : the phandle for the SDMA node used by this port | ||
| 275 | - brg : the phandle for the BRG node used by this port | ||
| 276 | - cunit : the phandle for the CUNIT node used by this port | ||
| 277 | - mpscrouting : the phandle for the MPSCROUTING node used by this port | ||
| 278 | - mpscintr : the phandle for the MPSCINTR node used by this port | ||
| 279 | - cell-index : the hardware index of this cell in the MPSC core | ||
| 280 | - max_idle : value needed for MPSC CHR3 (Maximum Frame Length) | ||
| 281 | register | ||
| 282 | - interrupts : <a> where a is the interrupt number for the MPSC. | ||
| 283 | - interrupt-parent : the phandle for the interrupt controller | ||
| 284 | that services interrupts for this device. | ||
| 285 | |||
| 286 | Example Discovery MPSCINTR node: | ||
| 287 | mpsc@8000 { | ||
| 288 | device_type = "serial"; | ||
| 289 | compatible = "marvell,mv64360-mpsc"; | ||
| 290 | reg = <0x8000 0x38>; | ||
| 291 | virtual-reg = <0xf1008000>; | ||
| 292 | sdma = <&SDMA0>; | ||
| 293 | brg = <&BRG0>; | ||
| 294 | cunit = <&CUNIT>; | ||
| 295 | mpscrouting = <&MPSCROUTING>; | ||
| 296 | mpscintr = <&MPSCINTR>; | ||
| 297 | cell-index = <0>; | ||
| 298 | max_idle = <40>; | ||
| 299 | interrupts = <40>; | ||
| 300 | interrupt-parent = <&PIC>; | ||
| 301 | }; | ||
| 302 | |||
| 303 | |||
| 304 | j) Marvell Discovery Watch Dog Timer nodes | ||
| 305 | |||
| 306 | Represent the Discovery's watchdog timer hardware | ||
| 307 | |||
| 308 | Required properties: | ||
| 309 | - compatible : "marvell,mv64360-wdt" | ||
| 310 | - reg : Offset and length of the register set for this device | ||
| 311 | |||
| 312 | Example Discovery Watch Dog Timer node: | ||
| 313 | wdt@b410 { | ||
| 314 | compatible = "marvell,mv64360-wdt"; | ||
| 315 | reg = <0xb410 0x8>; | ||
| 316 | }; | ||
| 317 | |||
| 318 | |||
| 319 | k) Marvell Discovery I2C nodes | ||
| 320 | |||
| 321 | Represent the Discovery's I2C hardware | ||
| 322 | |||
| 323 | Required properties: | ||
| 324 | - device_type : "i2c" | ||
| 325 | - compatible : "marvell,mv64360-i2c" | ||
| 326 | - reg : Offset and length of the register set for this device | ||
| 327 | - interrupts : <a> where a is the interrupt number for the I2C. | ||
| 328 | - interrupt-parent : the phandle for the interrupt controller | ||
| 329 | that services interrupts for this device. | ||
| 330 | |||
| 331 | Example Discovery I2C node: | ||
| 332 | compatible = "marvell,mv64360-i2c"; | ||
| 333 | reg = <0xc000 0x20>; | ||
| 334 | virtual-reg = <0xf100c000>; | ||
| 335 | interrupts = <37>; | ||
| 336 | interrupt-parent = <&PIC>; | ||
| 337 | }; | ||
| 338 | |||
| 339 | |||
| 340 | l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes | ||
| 341 | |||
| 342 | Represent the Discovery's PIC hardware | ||
| 343 | |||
| 344 | Required properties: | ||
| 345 | - #interrupt-cells : <1> | ||
| 346 | - #address-cells : <0> | ||
| 347 | - compatible : "marvell,mv64360-pic" | ||
| 348 | - reg : Offset and length of the register set for this device | ||
| 349 | - interrupt-controller | ||
| 350 | |||
| 351 | Example Discovery PIC node: | ||
| 352 | pic { | ||
| 353 | #interrupt-cells = <1>; | ||
| 354 | #address-cells = <0>; | ||
| 355 | compatible = "marvell,mv64360-pic"; | ||
| 356 | reg = <0x0 0x88>; | ||
| 357 | interrupt-controller; | ||
| 358 | }; | ||
| 359 | |||
| 360 | |||
| 361 | m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes | ||
| 362 | |||
| 363 | Represent the Discovery's MPP hardware | ||
| 364 | |||
| 365 | Required properties: | ||
| 366 | - compatible : "marvell,mv64360-mpp" | ||
| 367 | - reg : Offset and length of the register set for this device | ||
| 368 | |||
| 369 | Example Discovery MPP node: | ||
| 370 | mpp@f000 { | ||
| 371 | compatible = "marvell,mv64360-mpp"; | ||
| 372 | reg = <0xf000 0x10>; | ||
| 373 | }; | ||
| 374 | |||
| 375 | |||
| 376 | n) Marvell Discovery GPP (General Purpose Pins) nodes | ||
| 377 | |||
| 378 | Represent the Discovery's GPP hardware | ||
| 379 | |||
| 380 | Required properties: | ||
| 381 | - compatible : "marvell,mv64360-gpp" | ||
| 382 | - reg : Offset and length of the register set for this device | ||
| 383 | |||
| 384 | Example Discovery GPP node: | ||
| 385 | gpp@f000 { | ||
| 386 | compatible = "marvell,mv64360-gpp"; | ||
| 387 | reg = <0xf100 0x20>; | ||
| 388 | }; | ||
| 389 | |||
| 390 | |||
| 391 | o) Marvell Discovery PCI host bridge node | ||
| 392 | |||
| 393 | Represents the Discovery's PCI host bridge device. The properties | ||
| 394 | for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE | ||
| 395 | 1275-1994. A typical value for the compatible property is | ||
| 396 | "marvell,mv64360-pci". | ||
| 397 | |||
| 398 | Example Discovery PCI host bridge node | ||
| 399 | pci@80000000 { | ||
| 400 | #address-cells = <3>; | ||
| 401 | #size-cells = <2>; | ||
| 402 | #interrupt-cells = <1>; | ||
| 403 | device_type = "pci"; | ||
| 404 | compatible = "marvell,mv64360-pci"; | ||
| 405 | reg = <0xcf8 0x8>; | ||
| 406 | ranges = <0x01000000 0x0 0x0 | ||
| 407 | 0x88000000 0x0 0x01000000 | ||
| 408 | 0x02000000 0x0 0x80000000 | ||
| 409 | 0x80000000 0x0 0x08000000>; | ||
| 410 | bus-range = <0 255>; | ||
| 411 | clock-frequency = <66000000>; | ||
| 412 | interrupt-parent = <&PIC>; | ||
| 413 | interrupt-map-mask = <0xf800 0x0 0x0 0x7>; | ||
| 414 | interrupt-map = < | ||
| 415 | /* IDSEL 0x0a */ | ||
| 416 | 0x5000 0 0 1 &PIC 80 | ||
| 417 | 0x5000 0 0 2 &PIC 81 | ||
| 418 | 0x5000 0 0 3 &PIC 91 | ||
| 419 | 0x5000 0 0 4 &PIC 93 | ||
| 420 | |||
| 421 | /* IDSEL 0x0b */ | ||
| 422 | 0x5800 0 0 1 &PIC 91 | ||
| 423 | 0x5800 0 0 2 &PIC 93 | ||
| 424 | 0x5800 0 0 3 &PIC 80 | ||
| 425 | 0x5800 0 0 4 &PIC 81 | ||
| 426 | |||
| 427 | /* IDSEL 0x0c */ | ||
| 428 | 0x6000 0 0 1 &PIC 91 | ||
| 429 | 0x6000 0 0 2 &PIC 93 | ||
| 430 | 0x6000 0 0 3 &PIC 80 | ||
| 431 | 0x6000 0 0 4 &PIC 81 | ||
| 432 | |||
| 433 | /* IDSEL 0x0d */ | ||
| 434 | 0x6800 0 0 1 &PIC 93 | ||
| 435 | 0x6800 0 0 2 &PIC 80 | ||
| 436 | 0x6800 0 0 3 &PIC 81 | ||
| 437 | 0x6800 0 0 4 &PIC 91 | ||
| 438 | >; | ||
| 439 | }; | ||
| 440 | |||
| 441 | |||
| 442 | p) Marvell Discovery CPU Error nodes | ||
| 443 | |||
| 444 | Represent the Discovery's CPU error handler device. | ||
| 445 | |||
| 446 | Required properties: | ||
| 447 | - compatible : "marvell,mv64360-cpu-error" | ||
| 448 | - reg : Offset and length of the register set for this device | ||
| 449 | - interrupts : the interrupt number for this device | ||
| 450 | - interrupt-parent : the phandle for the interrupt controller | ||
| 451 | that services interrupts for this device. | ||
| 452 | |||
| 453 | Example Discovery CPU Error node: | ||
| 454 | cpu-error@0070 { | ||
| 455 | compatible = "marvell,mv64360-cpu-error"; | ||
| 456 | reg = <0x70 0x10 0x128 0x28>; | ||
| 457 | interrupts = <3>; | ||
| 458 | interrupt-parent = <&PIC>; | ||
| 459 | }; | ||
| 460 | |||
| 461 | |||
| 462 | q) Marvell Discovery SRAM Controller nodes | ||
| 463 | |||
| 464 | Represent the Discovery's SRAM controller device. | ||
| 465 | |||
| 466 | Required properties: | ||
| 467 | - compatible : "marvell,mv64360-sram-ctrl" | ||
| 468 | - reg : Offset and length of the register set for this device | ||
| 469 | - interrupts : the interrupt number for this device | ||
| 470 | - interrupt-parent : the phandle for the interrupt controller | ||
| 471 | that services interrupts for this device. | ||
| 472 | |||
| 473 | Example Discovery SRAM Controller node: | ||
| 474 | sram-ctrl@0380 { | ||
| 475 | compatible = "marvell,mv64360-sram-ctrl"; | ||
| 476 | reg = <0x380 0x80>; | ||
| 477 | interrupts = <13>; | ||
| 478 | interrupt-parent = <&PIC>; | ||
| 479 | }; | ||
| 480 | |||
| 481 | |||
| 482 | r) Marvell Discovery PCI Error Handler nodes | ||
| 483 | |||
| 484 | Represent the Discovery's PCI error handler device. | ||
| 485 | |||
| 486 | Required properties: | ||
| 487 | - compatible : "marvell,mv64360-pci-error" | ||
| 488 | - reg : Offset and length of the register set for this device | ||
| 489 | - interrupts : the interrupt number for this device | ||
| 490 | - interrupt-parent : the phandle for the interrupt controller | ||
| 491 | that services interrupts for this device. | ||
| 492 | |||
| 493 | Example Discovery PCI Error Handler node: | ||
| 494 | pci-error@1d40 { | ||
| 495 | compatible = "marvell,mv64360-pci-error"; | ||
| 496 | reg = <0x1d40 0x40 0xc28 0x4>; | ||
| 497 | interrupts = <12>; | ||
| 498 | interrupt-parent = <&PIC>; | ||
| 499 | }; | ||
| 500 | |||
| 501 | |||
| 502 | s) Marvell Discovery Memory Controller nodes | ||
| 503 | |||
| 504 | Represent the Discovery's memory controller device. | ||
| 505 | |||
| 506 | Required properties: | ||
| 507 | - compatible : "marvell,mv64360-mem-ctrl" | ||
| 508 | - reg : Offset and length of the register set for this device | ||
| 509 | - interrupts : the interrupt number for this device | ||
| 510 | - interrupt-parent : the phandle for the interrupt controller | ||
| 511 | that services interrupts for this device. | ||
| 512 | |||
| 513 | Example Discovery Memory Controller node: | ||
| 514 | mem-ctrl@1400 { | ||
| 515 | compatible = "marvell,mv64360-mem-ctrl"; | ||
| 516 | reg = <0x1400 0x60>; | ||
| 517 | interrupts = <17>; | ||
| 518 | interrupt-parent = <&PIC>; | ||
| 519 | }; | ||
| 520 | |||
| 521 | |||
diff --git a/Documentation/powerpc/dts-bindings/phy.txt b/Documentation/powerpc/dts-bindings/phy.txt new file mode 100644 index 000000000000..bb8c742eb8c5 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/phy.txt | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | PHY nodes | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - device_type : Should be "ethernet-phy" | ||
| 6 | - interrupts : <a b> where a is the interrupt number and b is a | ||
| 7 | field that represents an encoding of the sense and level | ||
| 8 | information for the interrupt. This should be encoded based on | ||
| 9 | the information in section 2) depending on the type of interrupt | ||
| 10 | controller you have. | ||
| 11 | - interrupt-parent : the phandle for the interrupt controller that | ||
| 12 | services interrupts for this device. | ||
| 13 | - reg : The ID number for the phy, usually a small integer | ||
| 14 | - linux,phandle : phandle for this node; likely referenced by an | ||
| 15 | ethernet controller node. | ||
| 16 | |||
| 17 | Example: | ||
| 18 | |||
| 19 | ethernet-phy@0 { | ||
| 20 | linux,phandle = <2452000> | ||
| 21 | interrupt-parent = <40000>; | ||
| 22 | interrupts = <35 1>; | ||
| 23 | reg = <0>; | ||
| 24 | device_type = "ethernet-phy"; | ||
| 25 | }; | ||
diff --git a/Documentation/powerpc/dts-bindings/spi-bus.txt b/Documentation/powerpc/dts-bindings/spi-bus.txt new file mode 100644 index 000000000000..e782add2e457 --- /dev/null +++ b/Documentation/powerpc/dts-bindings/spi-bus.txt | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | SPI (Serial Peripheral Interface) busses | ||
| 2 | |||
| 3 | SPI busses can be described with a node for the SPI master device | ||
| 4 | and a set of child nodes for each SPI slave on the bus. For this | ||
| 5 | discussion, it is assumed that the system's SPI controller is in | ||
| 6 | SPI master mode. This binding does not describe SPI controllers | ||
| 7 | in slave mode. | ||
| 8 | |||
| 9 | The SPI master node requires the following properties: | ||
| 10 | - #address-cells - number of cells required to define a chip select | ||
| 11 | address on the SPI bus. | ||
| 12 | - #size-cells - should be zero. | ||
| 13 | - compatible - name of SPI bus controller following generic names | ||
| 14 | recommended practice. | ||
| 15 | No other properties are required in the SPI bus node. It is assumed | ||
| 16 | that a driver for an SPI bus device will understand that it is an SPI bus. | ||
| 17 | However, the binding does not attempt to define the specific method for | ||
| 18 | assigning chip select numbers. Since SPI chip select configuration is | ||
| 19 | flexible and non-standardized, it is left out of this binding with the | ||
| 20 | assumption that board specific platform code will be used to manage | ||
| 21 | chip selects. Individual drivers can define additional properties to | ||
| 22 | support describing the chip select layout. | ||
| 23 | |||
| 24 | SPI slave nodes must be children of the SPI master node and can | ||
| 25 | contain the following properties. | ||
| 26 | - reg - (required) chip select address of device. | ||
| 27 | - compatible - (required) name of SPI device following generic names | ||
| 28 | recommended practice | ||
| 29 | - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz | ||
| 30 | - spi-cpol - (optional) Empty property indicating device requires | ||
| 31 | inverse clock polarity (CPOL) mode | ||
| 32 | - spi-cpha - (optional) Empty property indicating device requires | ||
| 33 | shifted clock phase (CPHA) mode | ||
| 34 | - spi-cs-high - (optional) Empty property indicating device requires | ||
| 35 | chip select active high | ||
| 36 | |||
| 37 | SPI example for an MPC5200 SPI bus: | ||
| 38 | spi@f00 { | ||
| 39 | #address-cells = <1>; | ||
| 40 | #size-cells = <0>; | ||
| 41 | compatible = "fsl,mpc5200b-spi","fsl,mpc5200-spi"; | ||
| 42 | reg = <0xf00 0x20>; | ||
| 43 | interrupts = <2 13 0 2 14 0>; | ||
| 44 | interrupt-parent = <&mpc5200_pic>; | ||
| 45 | |||
| 46 | ethernet-switch@0 { | ||
| 47 | compatible = "micrel,ks8995m"; | ||
| 48 | spi-max-frequency = <1000000>; | ||
| 49 | reg = <0>; | ||
| 50 | }; | ||
| 51 | |||
| 52 | codec@1 { | ||
| 53 | compatible = "ti,tlv320aic26"; | ||
| 54 | spi-max-frequency = <100000>; | ||
| 55 | reg = <1>; | ||
| 56 | }; | ||
| 57 | }; | ||
diff --git a/Documentation/powerpc/dts-bindings/usb-ehci.txt b/Documentation/powerpc/dts-bindings/usb-ehci.txt new file mode 100644 index 000000000000..fa18612f757b --- /dev/null +++ b/Documentation/powerpc/dts-bindings/usb-ehci.txt | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | USB EHCI controllers | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : should be "usb-ehci". | ||
| 5 | - reg : should contain at least address and length of the standard EHCI | ||
| 6 | register set for the device. Optional platform-dependent registers | ||
| 7 | (debug-port or other) can be also specified here, but only after | ||
| 8 | definition of standard EHCI registers. | ||
| 9 | - interrupts : one EHCI interrupt should be described here. | ||
| 10 | If device registers are implemented in big endian mode, the device | ||
| 11 | node should have "big-endian-regs" property. | ||
| 12 | If controller implementation operates with big endian descriptors, | ||
| 13 | "big-endian-desc" property should be specified. | ||
| 14 | If both big endian registers and descriptors are used by the controller | ||
| 15 | implementation, "big-endian" property can be specified instead of having | ||
| 16 | both "big-endian-regs" and "big-endian-desc". | ||
| 17 | |||
| 18 | Example (Sequoia 440EPx): | ||
| 19 | ehci@e0000300 { | ||
| 20 | compatible = "ibm,usb-ehci-440epx", "usb-ehci"; | ||
| 21 | interrupt-parent = <&UIC0>; | ||
| 22 | interrupts = <1a 4>; | ||
| 23 | reg = <0 e0000300 90 0 e0000390 70>; | ||
| 24 | big-endian; | ||
| 25 | }; | ||
diff --git a/Documentation/powerpc/dts-bindings/xilinx.txt b/Documentation/powerpc/dts-bindings/xilinx.txt new file mode 100644 index 000000000000..80339fe4300b --- /dev/null +++ b/Documentation/powerpc/dts-bindings/xilinx.txt | |||
| @@ -0,0 +1,295 @@ | |||
| 1 | d) Xilinx IP cores | ||
| 2 | |||
| 3 | The Xilinx EDK toolchain ships with a set of IP cores (devices) for use | ||
| 4 | in Xilinx Spartan and Virtex FPGAs. The devices cover the whole range | ||
| 5 | of standard device types (network, serial, etc.) and miscellaneous | ||
| 6 | devices (gpio, LCD, spi, etc). Also, since these devices are | ||
| 7 | implemented within the fpga fabric every instance of the device can be | ||
| 8 | synthesised with different options that change the behaviour. | ||
| 9 | |||
| 10 | Each IP-core has a set of parameters which the FPGA designer can use to | ||
| 11 | control how the core is synthesized. Historically, the EDK tool would | ||
| 12 | extract the device parameters relevant to device drivers and copy them | ||
| 13 | into an 'xparameters.h' in the form of #define symbols. This tells the | ||
| 14 | device drivers how the IP cores are configured, but it requres the kernel | ||
| 15 | to be recompiled every time the FPGA bitstream is resynthesized. | ||
| 16 | |||
| 17 | The new approach is to export the parameters into the device tree and | ||
| 18 | generate a new device tree each time the FPGA bitstream changes. The | ||
| 19 | parameters which used to be exported as #defines will now become | ||
| 20 | properties of the device node. In general, device nodes for IP-cores | ||
| 21 | will take the following form: | ||
| 22 | |||
| 23 | (name): (generic-name)@(base-address) { | ||
| 24 | compatible = "xlnx,(ip-core-name)-(HW_VER)" | ||
| 25 | [, (list of compatible devices), ...]; | ||
| 26 | reg = <(baseaddr) (size)>; | ||
| 27 | interrupt-parent = <&interrupt-controller-phandle>; | ||
| 28 | interrupts = < ... >; | ||
| 29 | xlnx,(parameter1) = "(string-value)"; | ||
| 30 | xlnx,(parameter2) = <(int-value)>; | ||
| 31 | }; | ||
| 32 | |||
| 33 | (generic-name): an open firmware-style name that describes the | ||
| 34 | generic class of device. Preferably, this is one word, such | ||
| 35 | as 'serial' or 'ethernet'. | ||
| 36 | (ip-core-name): the name of the ip block (given after the BEGIN | ||
| 37 | directive in system.mhs). Should be in lowercase | ||
| 38 | and all underscores '_' converted to dashes '-'. | ||
| 39 | (name): is derived from the "PARAMETER INSTANCE" value. | ||
| 40 | (parameter#): C_* parameters from system.mhs. The C_ prefix is | ||
| 41 | dropped from the parameter name, the name is converted | ||
| 42 | to lowercase and all underscore '_' characters are | ||
| 43 | converted to dashes '-'. | ||
| 44 | (baseaddr): the baseaddr parameter value (often named C_BASEADDR). | ||
| 45 | (HW_VER): from the HW_VER parameter. | ||
| 46 | (size): the address range size (often C_HIGHADDR - C_BASEADDR + 1). | ||
| 47 | |||
| 48 | Typically, the compatible list will include the exact IP core version | ||
| 49 | followed by an older IP core version which implements the same | ||
| 50 | interface or any other device with the same interface. | ||
| 51 | |||
| 52 | 'reg', 'interrupt-parent' and 'interrupts' are all optional properties. | ||
| 53 | |||
| 54 | For example, the following block from system.mhs: | ||
| 55 | |||
| 56 | BEGIN opb_uartlite | ||
| 57 | PARAMETER INSTANCE = opb_uartlite_0 | ||
| 58 | PARAMETER HW_VER = 1.00.b | ||
| 59 | PARAMETER C_BAUDRATE = 115200 | ||
| 60 | PARAMETER C_DATA_BITS = 8 | ||
| 61 | PARAMETER C_ODD_PARITY = 0 | ||
| 62 | PARAMETER C_USE_PARITY = 0 | ||
| 63 | PARAMETER C_CLK_FREQ = 50000000 | ||
| 64 | PARAMETER C_BASEADDR = 0xEC100000 | ||
| 65 | PARAMETER C_HIGHADDR = 0xEC10FFFF | ||
| 66 | BUS_INTERFACE SOPB = opb_7 | ||
| 67 | PORT OPB_Clk = CLK_50MHz | ||
| 68 | PORT Interrupt = opb_uartlite_0_Interrupt | ||
| 69 | PORT RX = opb_uartlite_0_RX | ||
| 70 | PORT TX = opb_uartlite_0_TX | ||
| 71 | PORT OPB_Rst = sys_bus_reset_0 | ||
| 72 | END | ||
| 73 | |||
| 74 | becomes the following device tree node: | ||
| 75 | |||
| 76 | opb_uartlite_0: serial@ec100000 { | ||
| 77 | device_type = "serial"; | ||
| 78 | compatible = "xlnx,opb-uartlite-1.00.b"; | ||
| 79 | reg = <ec100000 10000>; | ||
| 80 | interrupt-parent = <&opb_intc_0>; | ||
| 81 | interrupts = <1 0>; // got this from the opb_intc parameters | ||
| 82 | current-speed = <d#115200>; // standard serial device prop | ||
| 83 | clock-frequency = <d#50000000>; // standard serial device prop | ||
| 84 | xlnx,data-bits = <8>; | ||
| 85 | xlnx,odd-parity = <0>; | ||
| 86 | xlnx,use-parity = <0>; | ||
| 87 | }; | ||
| 88 | |||
| 89 | Some IP cores actually implement 2 or more logical devices. In | ||
| 90 | this case, the device should still describe the whole IP core with | ||
| 91 | a single node and add a child node for each logical device. The | ||
| 92 | ranges property can be used to translate from parent IP-core to the | ||
| 93 | registers of each device. In addition, the parent node should be | ||
| 94 | compatible with the bus type 'xlnx,compound', and should contain | ||
| 95 | #address-cells and #size-cells, as with any other bus. (Note: this | ||
| 96 | makes the assumption that both logical devices have the same bus | ||
| 97 | binding. If this is not true, then separate nodes should be used | ||
| 98 | for each logical device). The 'cell-index' property can be used to | ||
| 99 | enumerate logical devices within an IP core. For example, the | ||
| 100 | following is the system.mhs entry for the dual ps2 controller found | ||
| 101 | on the ml403 reference design. | ||
| 102 | |||
| 103 | BEGIN opb_ps2_dual_ref | ||
| 104 | PARAMETER INSTANCE = opb_ps2_dual_ref_0 | ||
| 105 | PARAMETER HW_VER = 1.00.a | ||
| 106 | PARAMETER C_BASEADDR = 0xA9000000 | ||
| 107 | PARAMETER C_HIGHADDR = 0xA9001FFF | ||
| 108 | BUS_INTERFACE SOPB = opb_v20_0 | ||
| 109 | PORT Sys_Intr1 = ps2_1_intr | ||
| 110 | PORT Sys_Intr2 = ps2_2_intr | ||
| 111 | PORT Clkin1 = ps2_clk_rx_1 | ||
| 112 | PORT Clkin2 = ps2_clk_rx_2 | ||
| 113 | PORT Clkpd1 = ps2_clk_tx_1 | ||
| 114 | PORT Clkpd2 = ps2_clk_tx_2 | ||
| 115 | PORT Rx1 = ps2_d_rx_1 | ||
| 116 | PORT Rx2 = ps2_d_rx_2 | ||
| 117 | PORT Txpd1 = ps2_d_tx_1 | ||
| 118 | PORT Txpd2 = ps2_d_tx_2 | ||
| 119 | END | ||
| 120 | |||
| 121 | It would result in the following device tree nodes: | ||
| 122 | |||
| 123 | opb_ps2_dual_ref_0: opb-ps2-dual-ref@a9000000 { | ||
| 124 | #address-cells = <1>; | ||
| 125 | #size-cells = <1>; | ||
| 126 | compatible = "xlnx,compound"; | ||
| 127 | ranges = <0 a9000000 2000>; | ||
| 128 | // If this device had extra parameters, then they would | ||
| 129 | // go here. | ||
| 130 | ps2@0 { | ||
| 131 | compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; | ||
| 132 | reg = <0 40>; | ||
| 133 | interrupt-parent = <&opb_intc_0>; | ||
| 134 | interrupts = <3 0>; | ||
| 135 | cell-index = <0>; | ||
| 136 | }; | ||
| 137 | ps2@1000 { | ||
| 138 | compatible = "xlnx,opb-ps2-dual-ref-1.00.a"; | ||
| 139 | reg = <1000 40>; | ||
| 140 | interrupt-parent = <&opb_intc_0>; | ||
| 141 | interrupts = <3 0>; | ||
| 142 | cell-index = <0>; | ||
| 143 | }; | ||
| 144 | }; | ||
| 145 | |||
| 146 | Also, the system.mhs file defines bus attachments from the processor | ||
| 147 | to the devices. The device tree structure should reflect the bus | ||
| 148 | attachments. Again an example; this system.mhs fragment: | ||
| 149 | |||
| 150 | BEGIN ppc405_virtex4 | ||
| 151 | PARAMETER INSTANCE = ppc405_0 | ||
| 152 | PARAMETER HW_VER = 1.01.a | ||
| 153 | BUS_INTERFACE DPLB = plb_v34_0 | ||
| 154 | BUS_INTERFACE IPLB = plb_v34_0 | ||
| 155 | END | ||
| 156 | |||
| 157 | BEGIN opb_intc | ||
| 158 | PARAMETER INSTANCE = opb_intc_0 | ||
| 159 | PARAMETER HW_VER = 1.00.c | ||
| 160 | PARAMETER C_BASEADDR = 0xD1000FC0 | ||
| 161 | PARAMETER C_HIGHADDR = 0xD1000FDF | ||
| 162 | BUS_INTERFACE SOPB = opb_v20_0 | ||
| 163 | END | ||
| 164 | |||
| 165 | BEGIN opb_uart16550 | ||
| 166 | PARAMETER INSTANCE = opb_uart16550_0 | ||
| 167 | PARAMETER HW_VER = 1.00.d | ||
| 168 | PARAMETER C_BASEADDR = 0xa0000000 | ||
| 169 | PARAMETER C_HIGHADDR = 0xa0001FFF | ||
| 170 | BUS_INTERFACE SOPB = opb_v20_0 | ||
| 171 | END | ||
| 172 | |||
| 173 | BEGIN plb_v34 | ||
| 174 | PARAMETER INSTANCE = plb_v34_0 | ||
| 175 | PARAMETER HW_VER = 1.02.a | ||
| 176 | END | ||
| 177 | |||
| 178 | BEGIN plb_bram_if_cntlr | ||
| 179 | PARAMETER INSTANCE = plb_bram_if_cntlr_0 | ||
| 180 | PARAMETER HW_VER = 1.00.b | ||
| 181 | PARAMETER C_BASEADDR = 0xFFFF0000 | ||
| 182 | PARAMETER C_HIGHADDR = 0xFFFFFFFF | ||
| 183 | BUS_INTERFACE SPLB = plb_v34_0 | ||
| 184 | END | ||
| 185 | |||
| 186 | BEGIN plb2opb_bridge | ||
| 187 | PARAMETER INSTANCE = plb2opb_bridge_0 | ||
| 188 | PARAMETER HW_VER = 1.01.a | ||
| 189 | PARAMETER C_RNG0_BASEADDR = 0x20000000 | ||
| 190 | PARAMETER C_RNG0_HIGHADDR = 0x3FFFFFFF | ||
| 191 | PARAMETER C_RNG1_BASEADDR = 0x60000000 | ||
| 192 | PARAMETER C_RNG1_HIGHADDR = 0x7FFFFFFF | ||
| 193 | PARAMETER C_RNG2_BASEADDR = 0x80000000 | ||
| 194 | PARAMETER C_RNG2_HIGHADDR = 0xBFFFFFFF | ||
| 195 | PARAMETER C_RNG3_BASEADDR = 0xC0000000 | ||
| 196 | PARAMETER C_RNG3_HIGHADDR = 0xDFFFFFFF | ||
| 197 | BUS_INTERFACE SPLB = plb_v34_0 | ||
| 198 | BUS_INTERFACE MOPB = opb_v20_0 | ||
| 199 | END | ||
| 200 | |||
| 201 | Gives this device tree (some properties removed for clarity): | ||
| 202 | |||
| 203 | plb@0 { | ||
| 204 | #address-cells = <1>; | ||
| 205 | #size-cells = <1>; | ||
| 206 | compatible = "xlnx,plb-v34-1.02.a"; | ||
| 207 | device_type = "ibm,plb"; | ||
| 208 | ranges; // 1:1 translation | ||
| 209 | |||
| 210 | plb_bram_if_cntrl_0: bram@ffff0000 { | ||
| 211 | reg = <ffff0000 10000>; | ||
| 212 | } | ||
| 213 | |||
| 214 | opb@20000000 { | ||
| 215 | #address-cells = <1>; | ||
| 216 | #size-cells = <1>; | ||
| 217 | ranges = <20000000 20000000 20000000 | ||
| 218 | 60000000 60000000 20000000 | ||
| 219 | 80000000 80000000 40000000 | ||
| 220 | c0000000 c0000000 20000000>; | ||
| 221 | |||
| 222 | opb_uart16550_0: serial@a0000000 { | ||
| 223 | reg = <a00000000 2000>; | ||
| 224 | }; | ||
| 225 | |||
| 226 | opb_intc_0: interrupt-controller@d1000fc0 { | ||
| 227 | reg = <d1000fc0 20>; | ||
| 228 | }; | ||
| 229 | }; | ||
| 230 | }; | ||
| 231 | |||
| 232 | That covers the general approach to binding xilinx IP cores into the | ||
| 233 | device tree. The following are bindings for specific devices: | ||
| 234 | |||
| 235 | i) Xilinx ML300 Framebuffer | ||
| 236 | |||
| 237 | Simple framebuffer device from the ML300 reference design (also on the | ||
| 238 | ML403 reference design as well as others). | ||
| 239 | |||
| 240 | Optional properties: | ||
| 241 | - resolution = <xres yres> : pixel resolution of framebuffer. Some | ||
| 242 | implementations use a different resolution. | ||
| 243 | Default is <d#640 d#480> | ||
| 244 | - virt-resolution = <xvirt yvirt> : Size of framebuffer in memory. | ||
| 245 | Default is <d#1024 d#480>. | ||
| 246 | - rotate-display (empty) : rotate display 180 degrees. | ||
| 247 | |||
| 248 | ii) Xilinx SystemACE | ||
| 249 | |||
| 250 | The Xilinx SystemACE device is used to program FPGAs from an FPGA | ||
| 251 | bitstream stored on a CF card. It can also be used as a generic CF | ||
| 252 | interface device. | ||
| 253 | |||
| 254 | Optional properties: | ||
| 255 | - 8-bit (empty) : Set this property for SystemACE in 8 bit mode | ||
| 256 | |||
| 257 | iii) Xilinx EMAC and Xilinx TEMAC | ||
| 258 | |||
| 259 | Xilinx Ethernet devices. In addition to general xilinx properties | ||
| 260 | listed above, nodes for these devices should include a phy-handle | ||
| 261 | property, and may include other common network device properties | ||
| 262 | like local-mac-address. | ||
| 263 | |||
| 264 | iv) Xilinx Uartlite | ||
| 265 | |||
| 266 | Xilinx uartlite devices are simple fixed speed serial ports. | ||
| 267 | |||
| 268 | Required properties: | ||
| 269 | - current-speed : Baud rate of uartlite | ||
| 270 | |||
| 271 | v) Xilinx hwicap | ||
| 272 | |||
| 273 | Xilinx hwicap devices provide access to the configuration logic | ||
| 274 | of the FPGA through the Internal Configuration Access Port | ||
| 275 | (ICAP). The ICAP enables partial reconfiguration of the FPGA, | ||
| 276 | readback of the configuration information, and some control over | ||
| 277 | 'warm boots' of the FPGA fabric. | ||
| 278 | |||
| 279 | Required properties: | ||
| 280 | - xlnx,family : The family of the FPGA, necessary since the | ||
| 281 | capabilities of the underlying ICAP hardware | ||
| 282 | differ between different families. May be | ||
| 283 | 'virtex2p', 'virtex4', or 'virtex5'. | ||
| 284 | |||
| 285 | vi) Xilinx Uart 16550 | ||
| 286 | |||
| 287 | Xilinx UART 16550 devices are very similar to the NS16550 but with | ||
| 288 | different register spacing and an offset from the base address. | ||
| 289 | |||
| 290 | Required properties: | ||
| 291 | - clock-frequency : Frequency of the clock input | ||
| 292 | - reg-offset : A value of 3 is required | ||
| 293 | - reg-shift : A value of 2 is required | ||
| 294 | |||
| 295 | |||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index bf6cedfa05db..d00131ca0835 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -62,7 +62,6 @@ config HAVE_LATENCYTOP_SUPPORT | |||
| 62 | 62 | ||
| 63 | config TRACE_IRQFLAGS_SUPPORT | 63 | config TRACE_IRQFLAGS_SUPPORT |
| 64 | bool | 64 | bool |
| 65 | depends on PPC64 | ||
| 66 | default y | 65 | default y |
| 67 | 66 | ||
| 68 | config LOCKDEP_SUPPORT | 67 | config LOCKDEP_SUPPORT |
diff --git a/arch/powerpc/boot/.gitignore b/arch/powerpc/boot/.gitignore index 2f50acd11a60..3d80c3e9cf60 100644 --- a/arch/powerpc/boot/.gitignore +++ b/arch/powerpc/boot/.gitignore | |||
| @@ -36,3 +36,13 @@ zImage.pseries | |||
| 36 | zconf.h | 36 | zconf.h |
| 37 | zlib.h | 37 | zlib.h |
| 38 | zutil.h | 38 | zutil.h |
| 39 | fdt.c | ||
| 40 | fdt.h | ||
| 41 | fdt_ro.c | ||
| 42 | fdt_rw.c | ||
| 43 | fdt_strerror.c | ||
| 44 | fdt_sw.c | ||
| 45 | fdt_wip.c | ||
| 46 | libfdt.h | ||
| 47 | libfdt_internal.h | ||
| 48 | |||
diff --git a/arch/powerpc/boot/dts/amigaone.dts b/arch/powerpc/boot/dts/amigaone.dts index 26549fca2ed4..49ac36b16dd7 100644 --- a/arch/powerpc/boot/dts/amigaone.dts +++ b/arch/powerpc/boot/dts/amigaone.dts | |||
| @@ -70,8 +70,8 @@ | |||
| 70 | devsel-speed = <0x00000001>; | 70 | devsel-speed = <0x00000001>; |
| 71 | min-grant = <0>; | 71 | min-grant = <0>; |
| 72 | max-latency = <0>; | 72 | max-latency = <0>; |
| 73 | /* First 64k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */ | 73 | /* First 4k for I/O at 0x0 on PCI mapped to 0x0 on ISA. */ |
| 74 | ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00010000>; | 74 | ranges = <0x00000001 0 0x01000000 0 0x00000000 0x00001000>; |
| 75 | interrupt-parent = <&i8259>; | 75 | interrupt-parent = <&i8259>; |
| 76 | #interrupt-cells = <2>; | 76 | #interrupt-cells = <2>; |
| 77 | #address-cells = <2>; | 77 | #address-cells = <2>; |
diff --git a/arch/powerpc/boot/dts/mpc8569mds.dts b/arch/powerpc/boot/dts/mpc8569mds.dts index a8dcb018c4a5..a680165292f2 100644 --- a/arch/powerpc/boot/dts/mpc8569mds.dts +++ b/arch/powerpc/boot/dts/mpc8569mds.dts | |||
| @@ -253,6 +253,7 @@ | |||
| 253 | /* Filled in by U-Boot */ | 253 | /* Filled in by U-Boot */ |
| 254 | clock-frequency = <0>; | 254 | clock-frequency = <0>; |
| 255 | status = "disabled"; | 255 | status = "disabled"; |
| 256 | sdhci,1-bit-only; | ||
| 256 | }; | 257 | }; |
| 257 | 258 | ||
| 258 | crypto@30000 { | 259 | crypto@30000 { |
diff --git a/arch/powerpc/include/asm/cpm1.h b/arch/powerpc/include/asm/cpm1.h index 2ff798744c1d..7685ffde8821 100644 --- a/arch/powerpc/include/asm/cpm1.h +++ b/arch/powerpc/include/asm/cpm1.h | |||
| @@ -598,8 +598,6 @@ typedef struct risc_timer_pram { | |||
| 598 | #define CICR_IEN ((uint)0x00000080) /* Int. enable */ | 598 | #define CICR_IEN ((uint)0x00000080) /* Int. enable */ |
| 599 | #define CICR_SPS ((uint)0x00000001) /* SCC Spread */ | 599 | #define CICR_SPS ((uint)0x00000001) /* SCC Spread */ |
| 600 | 600 | ||
| 601 | #define IMAP_ADDR (get_immrbase()) | ||
| 602 | |||
| 603 | #define CPM_PIN_INPUT 0 | 601 | #define CPM_PIN_INPUT 0 |
| 604 | #define CPM_PIN_OUTPUT 1 | 602 | #define CPM_PIN_OUTPUT 1 |
| 605 | #define CPM_PIN_PRIMARY 0 | 603 | #define CPM_PIN_PRIMARY 0 |
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index 3d9e887c3c0c..b44aaabdd1a6 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h | |||
| @@ -309,7 +309,9 @@ static inline void dma_sync_single_for_cpu(struct device *dev, | |||
| 309 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 309 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
| 310 | 310 | ||
| 311 | BUG_ON(!dma_ops); | 311 | BUG_ON(!dma_ops); |
| 312 | dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0, | 312 | |
| 313 | if (dma_ops->sync_single_range_for_cpu) | ||
| 314 | dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0, | ||
| 313 | size, direction); | 315 | size, direction); |
| 314 | } | 316 | } |
| 315 | 317 | ||
| @@ -320,7 +322,9 @@ static inline void dma_sync_single_for_device(struct device *dev, | |||
| 320 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 322 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
| 321 | 323 | ||
| 322 | BUG_ON(!dma_ops); | 324 | BUG_ON(!dma_ops); |
| 323 | dma_ops->sync_single_range_for_device(dev, dma_handle, | 325 | |
| 326 | if (dma_ops->sync_single_range_for_device) | ||
| 327 | dma_ops->sync_single_range_for_device(dev, dma_handle, | ||
| 324 | 0, size, direction); | 328 | 0, size, direction); |
| 325 | } | 329 | } |
| 326 | 330 | ||
| @@ -331,7 +335,9 @@ static inline void dma_sync_sg_for_cpu(struct device *dev, | |||
| 331 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 335 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
| 332 | 336 | ||
| 333 | BUG_ON(!dma_ops); | 337 | BUG_ON(!dma_ops); |
| 334 | dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction); | 338 | |
| 339 | if (dma_ops->sync_sg_for_cpu) | ||
| 340 | dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction); | ||
| 335 | } | 341 | } |
| 336 | 342 | ||
| 337 | static inline void dma_sync_sg_for_device(struct device *dev, | 343 | static inline void dma_sync_sg_for_device(struct device *dev, |
| @@ -341,7 +347,9 @@ static inline void dma_sync_sg_for_device(struct device *dev, | |||
| 341 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 347 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
| 342 | 348 | ||
| 343 | BUG_ON(!dma_ops); | 349 | BUG_ON(!dma_ops); |
| 344 | dma_ops->sync_sg_for_device(dev, sgl, nents, direction); | 350 | |
| 351 | if (dma_ops->sync_sg_for_device) | ||
| 352 | dma_ops->sync_sg_for_device(dev, sgl, nents, direction); | ||
| 345 | } | 353 | } |
| 346 | 354 | ||
| 347 | static inline void dma_sync_single_range_for_cpu(struct device *dev, | 355 | static inline void dma_sync_single_range_for_cpu(struct device *dev, |
| @@ -351,7 +359,9 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev, | |||
| 351 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 359 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
| 352 | 360 | ||
| 353 | BUG_ON(!dma_ops); | 361 | BUG_ON(!dma_ops); |
| 354 | dma_ops->sync_single_range_for_cpu(dev, dma_handle, | 362 | |
| 363 | if (dma_ops->sync_single_range_for_cpu) | ||
| 364 | dma_ops->sync_single_range_for_cpu(dev, dma_handle, | ||
| 355 | offset, size, direction); | 365 | offset, size, direction); |
| 356 | } | 366 | } |
| 357 | 367 | ||
| @@ -362,7 +372,9 @@ static inline void dma_sync_single_range_for_device(struct device *dev, | |||
| 362 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); | 372 | struct dma_mapping_ops *dma_ops = get_dma_ops(dev); |
| 363 | 373 | ||
| 364 | BUG_ON(!dma_ops); | 374 | BUG_ON(!dma_ops); |
| 365 | dma_ops->sync_single_range_for_device(dev, dma_handle, offset, | 375 | |
| 376 | if (dma_ops->sync_single_range_for_device) | ||
| 377 | dma_ops->sync_single_range_for_device(dev, dma_handle, offset, | ||
| 366 | size, direction); | 378 | size, direction); |
| 367 | } | 379 | } |
| 368 | #else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */ | 380 | #else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */ |
diff --git a/arch/powerpc/include/asm/highmem.h b/arch/powerpc/include/asm/highmem.h index 684a73f4324f..a74c4ee6c020 100644 --- a/arch/powerpc/include/asm/highmem.h +++ b/arch/powerpc/include/asm/highmem.h | |||
| @@ -22,9 +22,7 @@ | |||
| 22 | 22 | ||
| 23 | #ifdef __KERNEL__ | 23 | #ifdef __KERNEL__ |
| 24 | 24 | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 27 | #include <linux/highmem.h> | ||
| 28 | #include <asm/kmap_types.h> | 26 | #include <asm/kmap_types.h> |
| 29 | #include <asm/tlbflush.h> | 27 | #include <asm/tlbflush.h> |
| 30 | #include <asm/page.h> | 28 | #include <asm/page.h> |
| @@ -62,6 +60,9 @@ extern pte_t *pkmap_page_table; | |||
| 62 | 60 | ||
| 63 | extern void *kmap_high(struct page *page); | 61 | extern void *kmap_high(struct page *page); |
| 64 | extern void kunmap_high(struct page *page); | 62 | extern void kunmap_high(struct page *page); |
| 63 | extern void *kmap_atomic_prot(struct page *page, enum km_type type, | ||
| 64 | pgprot_t prot); | ||
| 65 | extern void kunmap_atomic(void *kvaddr, enum km_type type); | ||
| 65 | 66 | ||
| 66 | static inline void *kmap(struct page *page) | 67 | static inline void *kmap(struct page *page) |
| 67 | { | 68 | { |
| @@ -79,62 +80,11 @@ static inline void kunmap(struct page *page) | |||
| 79 | kunmap_high(page); | 80 | kunmap_high(page); |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | /* | ||
| 83 | * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap | ||
| 84 | * gives a more generic (and caching) interface. But kmap_atomic can | ||
| 85 | * be used in IRQ contexts, so in some (very limited) cases we need | ||
| 86 | * it. | ||
| 87 | */ | ||
| 88 | static inline void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | ||
| 89 | { | ||
| 90 | unsigned int idx; | ||
| 91 | unsigned long vaddr; | ||
| 92 | |||
| 93 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | ||
| 94 | pagefault_disable(); | ||
| 95 | if (!PageHighMem(page)) | ||
| 96 | return page_address(page); | ||
| 97 | |||
| 98 | debug_kmap_atomic(type); | ||
| 99 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
| 100 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
| 101 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
| 102 | BUG_ON(!pte_none(*(kmap_pte-idx))); | ||
| 103 | #endif | ||
| 104 | __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1); | ||
| 105 | local_flush_tlb_page(NULL, vaddr); | ||
| 106 | |||
| 107 | return (void*) vaddr; | ||
| 108 | } | ||
| 109 | |||
| 110 | static inline void *kmap_atomic(struct page *page, enum km_type type) | 83 | static inline void *kmap_atomic(struct page *page, enum km_type type) |
| 111 | { | 84 | { |
| 112 | return kmap_atomic_prot(page, type, kmap_prot); | 85 | return kmap_atomic_prot(page, type, kmap_prot); |
| 113 | } | 86 | } |
| 114 | 87 | ||
| 115 | static inline void kunmap_atomic(void *kvaddr, enum km_type type) | ||
| 116 | { | ||
| 117 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
| 118 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | ||
| 119 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | ||
| 120 | |||
| 121 | if (vaddr < __fix_to_virt(FIX_KMAP_END)) { | ||
| 122 | pagefault_enable(); | ||
| 123 | return; | ||
| 124 | } | ||
| 125 | |||
| 126 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | ||
| 127 | |||
| 128 | /* | ||
| 129 | * force other mappings to Oops if they'll try to access | ||
| 130 | * this pte without first remap it | ||
| 131 | */ | ||
| 132 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | ||
| 133 | local_flush_tlb_page(NULL, vaddr); | ||
| 134 | #endif | ||
| 135 | pagefault_enable(); | ||
| 136 | } | ||
| 137 | |||
| 138 | static inline struct page *kmap_atomic_to_page(void *ptr) | 88 | static inline struct page *kmap_atomic_to_page(void *ptr) |
| 139 | { | 89 | { |
| 140 | unsigned long idx, vaddr = (unsigned long) ptr; | 90 | unsigned long idx, vaddr = (unsigned long) ptr; |
| @@ -148,6 +98,7 @@ static inline struct page *kmap_atomic_to_page(void *ptr) | |||
| 148 | return pte_page(*pte); | 98 | return pte_page(*pte); |
| 149 | } | 99 | } |
| 150 | 100 | ||
| 101 | |||
| 151 | #define flush_cache_kmaps() flush_cache_all() | 102 | #define flush_cache_kmaps() flush_cache_all() |
| 152 | 103 | ||
| 153 | #endif /* __KERNEL__ */ | 104 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 867ab8ed69b3..8b505eaaa38a 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
| @@ -68,13 +68,13 @@ static inline int irqs_disabled_flags(unsigned long flags) | |||
| 68 | 68 | ||
| 69 | #if defined(CONFIG_BOOKE) | 69 | #if defined(CONFIG_BOOKE) |
| 70 | #define SET_MSR_EE(x) mtmsr(x) | 70 | #define SET_MSR_EE(x) mtmsr(x) |
| 71 | #define local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") | 71 | #define raw_local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") |
| 72 | #else | 72 | #else |
| 73 | #define SET_MSR_EE(x) mtmsr(x) | 73 | #define SET_MSR_EE(x) mtmsr(x) |
| 74 | #define local_irq_restore(flags) mtmsr(flags) | 74 | #define raw_local_irq_restore(flags) mtmsr(flags) |
| 75 | #endif | 75 | #endif |
| 76 | 76 | ||
| 77 | static inline void local_irq_disable(void) | 77 | static inline void raw_local_irq_disable(void) |
| 78 | { | 78 | { |
| 79 | #ifdef CONFIG_BOOKE | 79 | #ifdef CONFIG_BOOKE |
| 80 | __asm__ __volatile__("wrteei 0": : :"memory"); | 80 | __asm__ __volatile__("wrteei 0": : :"memory"); |
| @@ -86,7 +86,7 @@ static inline void local_irq_disable(void) | |||
| 86 | #endif | 86 | #endif |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | static inline void local_irq_enable(void) | 89 | static inline void raw_local_irq_enable(void) |
| 90 | { | 90 | { |
| 91 | #ifdef CONFIG_BOOKE | 91 | #ifdef CONFIG_BOOKE |
| 92 | __asm__ __volatile__("wrteei 1": : :"memory"); | 92 | __asm__ __volatile__("wrteei 1": : :"memory"); |
| @@ -98,7 +98,7 @@ static inline void local_irq_enable(void) | |||
| 98 | #endif | 98 | #endif |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | static inline void local_irq_save_ptr(unsigned long *flags) | 101 | static inline void raw_local_irq_save_ptr(unsigned long *flags) |
| 102 | { | 102 | { |
| 103 | unsigned long msr; | 103 | unsigned long msr; |
| 104 | msr = mfmsr(); | 104 | msr = mfmsr(); |
| @@ -110,12 +110,12 @@ static inline void local_irq_save_ptr(unsigned long *flags) | |||
| 110 | #endif | 110 | #endif |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | #define local_save_flags(flags) ((flags) = mfmsr()) | 113 | #define raw_local_save_flags(flags) ((flags) = mfmsr()) |
| 114 | #define local_irq_save(flags) local_irq_save_ptr(&flags) | 114 | #define raw_local_irq_save(flags) raw_local_irq_save_ptr(&flags) |
| 115 | #define irqs_disabled() ((mfmsr() & MSR_EE) == 0) | 115 | #define raw_irqs_disabled() ((mfmsr() & MSR_EE) == 0) |
| 116 | #define raw_irqs_disabled_flags(flags) (((flags) & MSR_EE) == 0) | ||
| 116 | 117 | ||
| 117 | #define hard_irq_enable() local_irq_enable() | 118 | #define hard_irq_disable() raw_local_irq_disable() |
| 118 | #define hard_irq_disable() local_irq_disable() | ||
| 119 | 119 | ||
| 120 | static inline int irqs_disabled_flags(unsigned long flags) | 120 | static inline int irqs_disabled_flags(unsigned long flags) |
| 121 | { | 121 | { |
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index e05d26fa372f..82b72207c51c 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h | |||
| @@ -47,7 +47,8 @@ | |||
| 47 | * generic accessors and iterators here | 47 | * generic accessors and iterators here |
| 48 | */ | 48 | */ |
| 49 | #define __real_pte(e,p) ((real_pte_t) { \ | 49 | #define __real_pte(e,p) ((real_pte_t) { \ |
| 50 | (e), pte_val(*((p) + PTRS_PER_PTE)) }) | 50 | (e), ((e) & _PAGE_COMBO) ? \ |
| 51 | (pte_val(*((p) + PTRS_PER_PTE))) : 0 }) | ||
| 51 | #define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \ | 52 | #define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \ |
| 52 | (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) | 53 | (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) |
| 53 | #define __rpte_to_pte(r) ((r).pte) | 54 | #define __rpte_to_pte(r) ((r).pte) |
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 01c12339b304..168fce726201 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h | |||
| @@ -58,7 +58,7 @@ struct rtas_t { | |||
| 58 | unsigned long entry; /* physical address pointer */ | 58 | unsigned long entry; /* physical address pointer */ |
| 59 | unsigned long base; /* physical address pointer */ | 59 | unsigned long base; /* physical address pointer */ |
| 60 | unsigned long size; | 60 | unsigned long size; |
| 61 | spinlock_t lock; | 61 | raw_spinlock_t lock; |
| 62 | struct rtas_args args; | 62 | struct rtas_args args; |
| 63 | struct device_node *dev; /* virtual address pointer */ | 63 | struct device_node *dev; /* virtual address pointer */ |
| 64 | }; | 64 | }; |
| @@ -245,5 +245,8 @@ static inline u32 rtas_config_addr(int busno, int devfn, int reg) | |||
| 245 | (devfn << 8) | (reg & 0xff); | 245 | (devfn << 8) | (reg & 0xff); |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | extern void __cpuinit rtas_give_timebase(void); | ||
| 249 | extern void __cpuinit rtas_take_timebase(void); | ||
| 250 | |||
| 248 | #endif /* __KERNEL__ */ | 251 | #endif /* __KERNEL__ */ |
| 249 | #endif /* _POWERPC_RTAS_H */ | 252 | #endif /* _POWERPC_RTAS_H */ |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 4dd38f129153..3cadba60a4b6 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
| @@ -191,11 +191,49 @@ transfer_to_handler_cont: | |||
| 191 | mflr r9 | 191 | mflr r9 |
| 192 | lwz r11,0(r9) /* virtual address of handler */ | 192 | lwz r11,0(r9) /* virtual address of handler */ |
| 193 | lwz r9,4(r9) /* where to go when done */ | 193 | lwz r9,4(r9) /* where to go when done */ |
| 194 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 195 | lis r12,reenable_mmu@h | ||
| 196 | ori r12,r12,reenable_mmu@l | ||
| 197 | mtspr SPRN_SRR0,r12 | ||
| 198 | mtspr SPRN_SRR1,r10 | ||
| 199 | SYNC | ||
| 200 | RFI | ||
| 201 | reenable_mmu: /* re-enable mmu so we can */ | ||
| 202 | mfmsr r10 | ||
| 203 | lwz r12,_MSR(r1) | ||
| 204 | xor r10,r10,r12 | ||
| 205 | andi. r10,r10,MSR_EE /* Did EE change? */ | ||
| 206 | beq 1f | ||
| 207 | |||
| 208 | /* Save handler and return address into the 2 unused words | ||
| 209 | * of the STACK_FRAME_OVERHEAD (sneak sneak sneak). Everything | ||
| 210 | * else can be recovered from the pt_regs except r3 which for | ||
| 211 | * normal interrupts has been set to pt_regs and for syscalls | ||
| 212 | * is an argument, so we temporarily use ORIG_GPR3 to save it | ||
| 213 | */ | ||
| 214 | stw r9,8(r1) | ||
| 215 | stw r11,12(r1) | ||
| 216 | stw r3,ORIG_GPR3(r1) | ||
| 217 | bl trace_hardirqs_off | ||
| 218 | lwz r0,GPR0(r1) | ||
| 219 | lwz r3,ORIG_GPR3(r1) | ||
| 220 | lwz r4,GPR4(r1) | ||
| 221 | lwz r5,GPR5(r1) | ||
| 222 | lwz r6,GPR6(r1) | ||
| 223 | lwz r7,GPR7(r1) | ||
| 224 | lwz r8,GPR8(r1) | ||
| 225 | lwz r9,8(r1) | ||
| 226 | lwz r11,12(r1) | ||
| 227 | 1: mtctr r11 | ||
| 228 | mtlr r9 | ||
| 229 | bctr /* jump to handler */ | ||
| 230 | #else /* CONFIG_TRACE_IRQFLAGS */ | ||
| 194 | mtspr SPRN_SRR0,r11 | 231 | mtspr SPRN_SRR0,r11 |
| 195 | mtspr SPRN_SRR1,r10 | 232 | mtspr SPRN_SRR1,r10 |
| 196 | mtlr r9 | 233 | mtlr r9 |
| 197 | SYNC | 234 | SYNC |
| 198 | RFI /* jump to handler, enable MMU */ | 235 | RFI /* jump to handler, enable MMU */ |
| 236 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
| 199 | 237 | ||
| 200 | #if defined (CONFIG_6xx) || defined(CONFIG_E500) | 238 | #if defined (CONFIG_6xx) || defined(CONFIG_E500) |
| 201 | 4: rlwinm r12,r12,0,~_TLF_NAPPING | 239 | 4: rlwinm r12,r12,0,~_TLF_NAPPING |
| @@ -251,6 +289,31 @@ _GLOBAL(DoSyscall) | |||
| 251 | #ifdef SHOW_SYSCALLS | 289 | #ifdef SHOW_SYSCALLS |
| 252 | bl do_show_syscall | 290 | bl do_show_syscall |
| 253 | #endif /* SHOW_SYSCALLS */ | 291 | #endif /* SHOW_SYSCALLS */ |
| 292 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 293 | /* Return from syscalls can (and generally will) hard enable | ||
| 294 | * interrupts. You aren't supposed to call a syscall with | ||
| 295 | * interrupts disabled in the first place. However, to ensure | ||
| 296 | * that we get it right vs. lockdep if it happens, we force | ||
| 297 | * that hard enable here with appropriate tracing if we see | ||
| 298 | * that we have been called with interrupts off | ||
| 299 | */ | ||
| 300 | mfmsr r11 | ||
| 301 | andi. r12,r11,MSR_EE | ||
| 302 | bne+ 1f | ||
| 303 | /* We came in with interrupts disabled, we enable them now */ | ||
| 304 | bl trace_hardirqs_on | ||
| 305 | mfmsr r11 | ||
| 306 | lwz r0,GPR0(r1) | ||
| 307 | lwz r3,GPR3(r1) | ||
| 308 | lwz r4,GPR4(r1) | ||
| 309 | ori r11,r11,MSR_EE | ||
| 310 | lwz r5,GPR5(r1) | ||
| 311 | lwz r6,GPR6(r1) | ||
| 312 | lwz r7,GPR7(r1) | ||
| 313 | lwz r8,GPR8(r1) | ||
| 314 | mtmsr r11 | ||
| 315 | 1: | ||
| 316 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
| 254 | rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | 317 | rlwinm r10,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ |
| 255 | lwz r11,TI_FLAGS(r10) | 318 | lwz r11,TI_FLAGS(r10) |
| 256 | andi. r11,r11,_TIF_SYSCALL_T_OR_A | 319 | andi. r11,r11,_TIF_SYSCALL_T_OR_A |
| @@ -275,6 +338,7 @@ ret_from_syscall: | |||
| 275 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ | 338 | rlwinm r12,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */ |
| 276 | /* disable interrupts so current_thread_info()->flags can't change */ | 339 | /* disable interrupts so current_thread_info()->flags can't change */ |
| 277 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ | 340 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ |
| 341 | /* Note: We don't bother telling lockdep about it */ | ||
| 278 | SYNC | 342 | SYNC |
| 279 | MTMSRD(r10) | 343 | MTMSRD(r10) |
| 280 | lwz r9,TI_FLAGS(r12) | 344 | lwz r9,TI_FLAGS(r12) |
| @@ -288,6 +352,19 @@ ret_from_syscall: | |||
| 288 | oris r11,r11,0x1000 /* Set SO bit in CR */ | 352 | oris r11,r11,0x1000 /* Set SO bit in CR */ |
| 289 | stw r11,_CCR(r1) | 353 | stw r11,_CCR(r1) |
| 290 | syscall_exit_cont: | 354 | syscall_exit_cont: |
| 355 | lwz r8,_MSR(r1) | ||
| 356 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 357 | /* If we are going to return from the syscall with interrupts | ||
| 358 | * off, we trace that here. It shouldn't happen though but we | ||
| 359 | * want to catch the bugger if it does right ? | ||
| 360 | */ | ||
| 361 | andi. r10,r8,MSR_EE | ||
| 362 | bne+ 1f | ||
| 363 | stw r3,GPR3(r1) | ||
| 364 | bl trace_hardirqs_off | ||
| 365 | lwz r3,GPR3(r1) | ||
| 366 | 1: | ||
| 367 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
| 291 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 368 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
| 292 | /* If the process has its own DBCR0 value, load it up. The internal | 369 | /* If the process has its own DBCR0 value, load it up. The internal |
| 293 | debug mode bit tells us that dbcr0 should be loaded. */ | 370 | debug mode bit tells us that dbcr0 should be loaded. */ |
| @@ -311,7 +388,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) | |||
| 311 | mtlr r4 | 388 | mtlr r4 |
| 312 | mtcr r5 | 389 | mtcr r5 |
| 313 | lwz r7,_NIP(r1) | 390 | lwz r7,_NIP(r1) |
| 314 | lwz r8,_MSR(r1) | ||
| 315 | FIX_SRR1(r8, r0) | 391 | FIX_SRR1(r8, r0) |
| 316 | lwz r2,GPR2(r1) | 392 | lwz r2,GPR2(r1) |
| 317 | lwz r1,GPR1(r1) | 393 | lwz r1,GPR1(r1) |
| @@ -394,7 +470,9 @@ syscall_exit_work: | |||
| 394 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) | 470 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) |
| 395 | beq ret_from_except | 471 | beq ret_from_except |
| 396 | 472 | ||
| 397 | /* Re-enable interrupts */ | 473 | /* Re-enable interrupts. There is no need to trace that with |
| 474 | * lockdep as we are supposed to have IRQs on at this point | ||
| 475 | */ | ||
| 398 | ori r10,r10,MSR_EE | 476 | ori r10,r10,MSR_EE |
| 399 | SYNC | 477 | SYNC |
| 400 | MTMSRD(r10) | 478 | MTMSRD(r10) |
| @@ -705,6 +783,7 @@ ret_from_except: | |||
| 705 | /* Hard-disable interrupts so that current_thread_info()->flags | 783 | /* Hard-disable interrupts so that current_thread_info()->flags |
| 706 | * can't change between when we test it and when we return | 784 | * can't change between when we test it and when we return |
| 707 | * from the interrupt. */ | 785 | * from the interrupt. */ |
| 786 | /* Note: We don't bother telling lockdep about it */ | ||
| 708 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) | 787 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) |
| 709 | SYNC /* Some chip revs have problems here... */ | 788 | SYNC /* Some chip revs have problems here... */ |
| 710 | MTMSRD(r10) /* disable interrupts */ | 789 | MTMSRD(r10) /* disable interrupts */ |
| @@ -744,11 +823,24 @@ resume_kernel: | |||
| 744 | beq+ restore | 823 | beq+ restore |
| 745 | andi. r0,r3,MSR_EE /* interrupts off? */ | 824 | andi. r0,r3,MSR_EE /* interrupts off? */ |
| 746 | beq restore /* don't schedule if so */ | 825 | beq restore /* don't schedule if so */ |
| 826 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 827 | /* Lockdep thinks irqs are enabled, we need to call | ||
| 828 | * preempt_schedule_irq with IRQs off, so we inform lockdep | ||
| 829 | * now that we -did- turn them off already | ||
| 830 | */ | ||
| 831 | bl trace_hardirqs_off | ||
| 832 | #endif | ||
| 747 | 1: bl preempt_schedule_irq | 833 | 1: bl preempt_schedule_irq |
| 748 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) | 834 | rlwinm r9,r1,0,0,(31-THREAD_SHIFT) |
| 749 | lwz r3,TI_FLAGS(r9) | 835 | lwz r3,TI_FLAGS(r9) |
| 750 | andi. r0,r3,_TIF_NEED_RESCHED | 836 | andi. r0,r3,_TIF_NEED_RESCHED |
| 751 | bne- 1b | 837 | bne- 1b |
| 838 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 839 | /* And now, to properly rebalance the above, we tell lockdep they | ||
| 840 | * are being turned back on, which will happen when we return | ||
| 841 | */ | ||
| 842 | bl trace_hardirqs_on | ||
| 843 | #endif | ||
| 752 | #else | 844 | #else |
| 753 | resume_kernel: | 845 | resume_kernel: |
| 754 | #endif /* CONFIG_PREEMPT */ | 846 | #endif /* CONFIG_PREEMPT */ |
| @@ -765,6 +857,28 @@ restore: | |||
| 765 | stw r6,icache_44x_need_flush@l(r4) | 857 | stw r6,icache_44x_need_flush@l(r4) |
| 766 | 1: | 858 | 1: |
| 767 | #endif /* CONFIG_44x */ | 859 | #endif /* CONFIG_44x */ |
| 860 | |||
| 861 | lwz r9,_MSR(r1) | ||
| 862 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 863 | /* Lockdep doesn't know about the fact that IRQs are temporarily turned | ||
| 864 | * off in this assembly code while peeking at TI_FLAGS() and such. However | ||
| 865 | * we need to inform it if the exception turned interrupts off, and we | ||
| 866 | * are about to trun them back on. | ||
| 867 | * | ||
| 868 | * The problem here sadly is that we don't know whether the exceptions was | ||
| 869 | * one that turned interrupts off or not. So we always tell lockdep about | ||
| 870 | * turning them on here when we go back to wherever we came from with EE | ||
| 871 | * on, even if that may meen some redudant calls being tracked. Maybe later | ||
| 872 | * we could encode what the exception did somewhere or test the exception | ||
| 873 | * type in the pt_regs but that sounds overkill | ||
| 874 | */ | ||
| 875 | andi. r10,r9,MSR_EE | ||
| 876 | beq 1f | ||
| 877 | bl trace_hardirqs_on | ||
| 878 | lwz r9,_MSR(r1) | ||
| 879 | 1: | ||
| 880 | #endif /* CONFIG_TRACE_IRQFLAGS */ | ||
| 881 | |||
| 768 | lwz r0,GPR0(r1) | 882 | lwz r0,GPR0(r1) |
| 769 | lwz r2,GPR2(r1) | 883 | lwz r2,GPR2(r1) |
| 770 | REST_4GPRS(3, r1) | 884 | REST_4GPRS(3, r1) |
| @@ -782,7 +896,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) | |||
| 782 | stwcx. r0,0,r1 /* to clear the reservation */ | 896 | stwcx. r0,0,r1 /* to clear the reservation */ |
| 783 | 897 | ||
| 784 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) | 898 | #if !(defined(CONFIG_4xx) || defined(CONFIG_BOOKE)) |
| 785 | lwz r9,_MSR(r1) | ||
| 786 | andi. r10,r9,MSR_RI /* check if this exception occurred */ | 899 | andi. r10,r9,MSR_RI /* check if this exception occurred */ |
| 787 | beql nonrecoverable /* at a bad place (MSR:RI = 0) */ | 900 | beql nonrecoverable /* at a bad place (MSR:RI = 0) */ |
| 788 | 901 | ||
| @@ -805,7 +918,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) | |||
| 805 | MTMSRD(r10) /* clear the RI bit */ | 918 | MTMSRD(r10) /* clear the RI bit */ |
| 806 | .globl exc_exit_restart | 919 | .globl exc_exit_restart |
| 807 | exc_exit_restart: | 920 | exc_exit_restart: |
| 808 | lwz r9,_MSR(r1) | ||
| 809 | lwz r12,_NIP(r1) | 921 | lwz r12,_NIP(r1) |
| 810 | FIX_SRR1(r9,r10) | 922 | FIX_SRR1(r9,r10) |
| 811 | mtspr SPRN_SRR0,r12 | 923 | mtspr SPRN_SRR0,r12 |
| @@ -1035,11 +1147,18 @@ do_work: /* r10 contains MSR_KERNEL here */ | |||
| 1035 | beq do_user_signal | 1147 | beq do_user_signal |
| 1036 | 1148 | ||
| 1037 | do_resched: /* r10 contains MSR_KERNEL here */ | 1149 | do_resched: /* r10 contains MSR_KERNEL here */ |
| 1150 | /* Note: We don't need to inform lockdep that we are enabling | ||
| 1151 | * interrupts here. As far as it knows, they are already enabled | ||
| 1152 | */ | ||
| 1038 | ori r10,r10,MSR_EE | 1153 | ori r10,r10,MSR_EE |
| 1039 | SYNC | 1154 | SYNC |
| 1040 | MTMSRD(r10) /* hard-enable interrupts */ | 1155 | MTMSRD(r10) /* hard-enable interrupts */ |
| 1041 | bl schedule | 1156 | bl schedule |
| 1042 | recheck: | 1157 | recheck: |
| 1158 | /* Note: And we don't tell it we are disabling them again | ||
| 1159 | * neither. Those disable/enable cycles used to peek at | ||
| 1160 | * TI_FLAGS aren't advertised. | ||
| 1161 | */ | ||
| 1043 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) | 1162 | LOAD_MSR_KERNEL(r10,MSR_KERNEL) |
| 1044 | SYNC | 1163 | SYNC |
| 1045 | MTMSRD(r10) /* disable interrupts */ | 1164 | MTMSRD(r10) /* disable interrupts */ |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 48469463f89e..fc2132942754 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
| @@ -1124,9 +1124,8 @@ mmu_off: | |||
| 1124 | RFI | 1124 | RFI |
| 1125 | 1125 | ||
| 1126 | /* | 1126 | /* |
| 1127 | * Use the first pair of BAT registers to map the 1st 16MB | 1127 | * On 601, we use 3 BATs to map up to 24M of RAM at _PAGE_OFFSET |
| 1128 | * of RAM to PAGE_OFFSET. From this point on we can't safely | 1128 | * (we keep one for debugging) and on others, we use one 256M BAT. |
| 1129 | * call OF any more. | ||
| 1130 | */ | 1129 | */ |
| 1131 | initial_bats: | 1130 | initial_bats: |
| 1132 | lis r11,PAGE_OFFSET@h | 1131 | lis r11,PAGE_OFFSET@h |
| @@ -1136,12 +1135,16 @@ initial_bats: | |||
| 1136 | bne 4f | 1135 | bne 4f |
| 1137 | ori r11,r11,4 /* set up BAT registers for 601 */ | 1136 | ori r11,r11,4 /* set up BAT registers for 601 */ |
| 1138 | li r8,0x7f /* valid, block length = 8MB */ | 1137 | li r8,0x7f /* valid, block length = 8MB */ |
| 1139 | oris r9,r11,0x800000@h /* set up BAT reg for 2nd 8M */ | ||
| 1140 | oris r10,r8,0x800000@h /* set up BAT reg for 2nd 8M */ | ||
| 1141 | mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */ | 1138 | mtspr SPRN_IBAT0U,r11 /* N.B. 601 has valid bit in */ |
| 1142 | mtspr SPRN_IBAT0L,r8 /* lower BAT register */ | 1139 | mtspr SPRN_IBAT0L,r8 /* lower BAT register */ |
| 1143 | mtspr SPRN_IBAT1U,r9 | 1140 | addis r11,r11,0x800000@h |
| 1144 | mtspr SPRN_IBAT1L,r10 | 1141 | addis r8,r8,0x800000@h |
| 1142 | mtspr SPRN_IBAT1U,r11 | ||
| 1143 | mtspr SPRN_IBAT1L,r8 | ||
| 1144 | addis r11,r11,0x800000@h | ||
| 1145 | addis r8,r8,0x800000@h | ||
| 1146 | mtspr SPRN_IBAT2U,r11 | ||
| 1147 | mtspr SPRN_IBAT2L,r8 | ||
| 1145 | isync | 1148 | isync |
| 1146 | blr | 1149 | blr |
| 1147 | 1150 | ||
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index fa983a59c4ce..a359cb08e900 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c | |||
| @@ -76,7 +76,7 @@ struct of_device *of_device_alloc(struct device_node *np, | |||
| 76 | dev->dev.archdata.of_node = np; | 76 | dev->dev.archdata.of_node = np; |
| 77 | 77 | ||
| 78 | if (bus_id) | 78 | if (bus_id) |
| 79 | dev_set_name(&dev->dev, bus_id); | 79 | dev_set_name(&dev->dev, "%s", bus_id); |
| 80 | else | 80 | else |
| 81 | of_device_make_bus_id(dev); | 81 | of_device_make_bus_id(dev); |
| 82 | 82 | ||
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 3e7135bbe40f..892a9f2e6d76 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -528,7 +528,7 @@ void show_regs(struct pt_regs * regs) | |||
| 528 | 528 | ||
| 529 | for (i = 0; i < 32; i++) { | 529 | for (i = 0; i < 32; i++) { |
| 530 | if ((i % REGS_PER_LINE) == 0) | 530 | if ((i % REGS_PER_LINE) == 0) |
| 531 | printk("\n" KERN_INFO "GPR%02d: ", i); | 531 | printk("\nGPR%02d: ", i); |
| 532 | printk(REG " ", regs->gpr[i]); | 532 | printk(REG " ", regs->gpr[i]); |
| 533 | if (i == LAST_VOLATILE && !FULL_REGS(regs)) | 533 | if (i == LAST_VOLATILE && !FULL_REGS(regs)) |
| 534 | break; | 534 | break; |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index ee4c7609b649..c434823b8c83 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
| @@ -38,9 +38,10 @@ | |||
| 38 | #include <asm/syscalls.h> | 38 | #include <asm/syscalls.h> |
| 39 | #include <asm/smp.h> | 39 | #include <asm/smp.h> |
| 40 | #include <asm/atomic.h> | 40 | #include <asm/atomic.h> |
| 41 | #include <asm/time.h> | ||
| 41 | 42 | ||
| 42 | struct rtas_t rtas = { | 43 | struct rtas_t rtas = { |
| 43 | .lock = SPIN_LOCK_UNLOCKED | 44 | .lock = __RAW_SPIN_LOCK_UNLOCKED |
| 44 | }; | 45 | }; |
| 45 | EXPORT_SYMBOL(rtas); | 46 | EXPORT_SYMBOL(rtas); |
| 46 | 47 | ||
| @@ -67,6 +68,28 @@ unsigned long rtas_rmo_buf; | |||
| 67 | void (*rtas_flash_term_hook)(int); | 68 | void (*rtas_flash_term_hook)(int); |
| 68 | EXPORT_SYMBOL(rtas_flash_term_hook); | 69 | EXPORT_SYMBOL(rtas_flash_term_hook); |
| 69 | 70 | ||
| 71 | /* RTAS use home made raw locking instead of spin_lock_irqsave | ||
| 72 | * because those can be called from within really nasty contexts | ||
| 73 | * such as having the timebase stopped which would lockup with | ||
| 74 | * normal locks and spinlock debugging enabled | ||
| 75 | */ | ||
| 76 | static unsigned long lock_rtas(void) | ||
| 77 | { | ||
| 78 | unsigned long flags; | ||
| 79 | |||
| 80 | local_irq_save(flags); | ||
| 81 | preempt_disable(); | ||
| 82 | __raw_spin_lock_flags(&rtas.lock, flags); | ||
| 83 | return flags; | ||
| 84 | } | ||
| 85 | |||
| 86 | static void unlock_rtas(unsigned long flags) | ||
| 87 | { | ||
| 88 | __raw_spin_unlock(&rtas.lock); | ||
| 89 | local_irq_restore(flags); | ||
| 90 | preempt_enable(); | ||
| 91 | } | ||
| 92 | |||
| 70 | /* | 93 | /* |
| 71 | * call_rtas_display_status and call_rtas_display_status_delay | 94 | * call_rtas_display_status and call_rtas_display_status_delay |
| 72 | * are designed only for very early low-level debugging, which | 95 | * are designed only for very early low-level debugging, which |
| @@ -79,7 +102,7 @@ static void call_rtas_display_status(char c) | |||
| 79 | 102 | ||
| 80 | if (!rtas.base) | 103 | if (!rtas.base) |
| 81 | return; | 104 | return; |
| 82 | spin_lock_irqsave(&rtas.lock, s); | 105 | s = lock_rtas(); |
| 83 | 106 | ||
| 84 | args->token = 10; | 107 | args->token = 10; |
| 85 | args->nargs = 1; | 108 | args->nargs = 1; |
| @@ -89,7 +112,7 @@ static void call_rtas_display_status(char c) | |||
| 89 | 112 | ||
| 90 | enter_rtas(__pa(args)); | 113 | enter_rtas(__pa(args)); |
| 91 | 114 | ||
| 92 | spin_unlock_irqrestore(&rtas.lock, s); | 115 | unlock_rtas(s); |
| 93 | } | 116 | } |
| 94 | 117 | ||
| 95 | static void call_rtas_display_status_delay(char c) | 118 | static void call_rtas_display_status_delay(char c) |
| @@ -411,8 +434,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) | |||
| 411 | if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) | 434 | if (!rtas.entry || token == RTAS_UNKNOWN_SERVICE) |
| 412 | return -1; | 435 | return -1; |
| 413 | 436 | ||
| 414 | /* Gotta do something different here, use global lock for now... */ | 437 | s = lock_rtas(); |
| 415 | spin_lock_irqsave(&rtas.lock, s); | ||
| 416 | rtas_args = &rtas.args; | 438 | rtas_args = &rtas.args; |
| 417 | 439 | ||
| 418 | rtas_args->token = token; | 440 | rtas_args->token = token; |
| @@ -439,8 +461,7 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) | |||
| 439 | outputs[i] = rtas_args->rets[i+1]; | 461 | outputs[i] = rtas_args->rets[i+1]; |
| 440 | ret = (nret > 0)? rtas_args->rets[0]: 0; | 462 | ret = (nret > 0)? rtas_args->rets[0]: 0; |
| 441 | 463 | ||
| 442 | /* Gotta do something different here, use global lock for now... */ | 464 | unlock_rtas(s); |
| 443 | spin_unlock_irqrestore(&rtas.lock, s); | ||
| 444 | 465 | ||
| 445 | if (buff_copy) { | 466 | if (buff_copy) { |
| 446 | log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); | 467 | log_error(buff_copy, ERR_TYPE_RTAS_LOG, 0); |
| @@ -837,7 +858,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
| 837 | 858 | ||
| 838 | buff_copy = get_errorlog_buffer(); | 859 | buff_copy = get_errorlog_buffer(); |
| 839 | 860 | ||
| 840 | spin_lock_irqsave(&rtas.lock, flags); | 861 | flags = lock_rtas(); |
| 841 | 862 | ||
| 842 | rtas.args = args; | 863 | rtas.args = args; |
| 843 | enter_rtas(__pa(&rtas.args)); | 864 | enter_rtas(__pa(&rtas.args)); |
| @@ -848,7 +869,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
| 848 | if (args.rets[0] == -1) | 869 | if (args.rets[0] == -1) |
| 849 | errbuf = __fetch_rtas_last_error(buff_copy); | 870 | errbuf = __fetch_rtas_last_error(buff_copy); |
| 850 | 871 | ||
| 851 | spin_unlock_irqrestore(&rtas.lock, flags); | 872 | unlock_rtas(flags); |
| 852 | 873 | ||
| 853 | if (buff_copy) { | 874 | if (buff_copy) { |
| 854 | if (errbuf) | 875 | if (errbuf) |
| @@ -951,3 +972,33 @@ int __init early_init_dt_scan_rtas(unsigned long node, | |||
| 951 | /* break now */ | 972 | /* break now */ |
| 952 | return 1; | 973 | return 1; |
| 953 | } | 974 | } |
| 975 | |||
| 976 | static raw_spinlock_t timebase_lock; | ||
| 977 | static u64 timebase = 0; | ||
| 978 | |||
| 979 | void __cpuinit rtas_give_timebase(void) | ||
| 980 | { | ||
| 981 | unsigned long flags; | ||
| 982 | |||
| 983 | local_irq_save(flags); | ||
| 984 | hard_irq_disable(); | ||
| 985 | __raw_spin_lock(&timebase_lock); | ||
| 986 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); | ||
| 987 | timebase = get_tb(); | ||
| 988 | __raw_spin_unlock(&timebase_lock); | ||
| 989 | |||
| 990 | while (timebase) | ||
| 991 | barrier(); | ||
| 992 | rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); | ||
| 993 | local_irq_restore(flags); | ||
| 994 | } | ||
| 995 | |||
| 996 | void __cpuinit rtas_take_timebase(void) | ||
| 997 | { | ||
| 998 | while (!timebase) | ||
| 999 | barrier(); | ||
| 1000 | __raw_spin_lock(&timebase_lock); | ||
| 1001 | set_tb(timebase >> 32, timebase & 0xffffffff); | ||
| 1002 | timebase = 0; | ||
| 1003 | __raw_spin_unlock(&timebase_lock); | ||
| 1004 | } | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 1d154248cf40..e1e3059cf34b 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
| @@ -119,6 +119,8 @@ notrace unsigned long __init early_init(unsigned long dt_ptr) | |||
| 119 | */ | 119 | */ |
| 120 | notrace void __init machine_init(unsigned long dt_ptr) | 120 | notrace void __init machine_init(unsigned long dt_ptr) |
| 121 | { | 121 | { |
| 122 | lockdep_init(); | ||
| 123 | |||
| 122 | /* Enable early debugging if any specified (see udbg.h) */ | 124 | /* Enable early debugging if any specified (see udbg.h) */ |
| 123 | udbg_early_init(); | 125 | udbg_early_init(); |
| 124 | 126 | ||
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 65484b2200b3..0b47de07302d 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -68,7 +68,8 @@ EXPORT_PER_CPU_SYMBOL(cpu_core_map); | |||
| 68 | /* SMP operations for this machine */ | 68 | /* SMP operations for this machine */ |
| 69 | struct smp_ops_t *smp_ops; | 69 | struct smp_ops_t *smp_ops; |
| 70 | 70 | ||
| 71 | static volatile unsigned int cpu_callin_map[NR_CPUS]; | 71 | /* Can't be static due to PowerMac hackery */ |
| 72 | volatile unsigned int cpu_callin_map[NR_CPUS]; | ||
| 72 | 73 | ||
| 73 | int smt_enabled_at_boot = 1; | 74 | int smt_enabled_at_boot = 1; |
| 74 | 75 | ||
diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 0362a891e54e..acb74a17bbbf 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c | |||
| @@ -219,7 +219,7 @@ void udbg_init_pas_realmode(void) | |||
| 219 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x | 219 | #ifdef CONFIG_PPC_EARLY_DEBUG_44x |
| 220 | #include <platforms/44x/44x.h> | 220 | #include <platforms/44x/44x.h> |
| 221 | 221 | ||
| 222 | static int udbg_44x_as1_flush(void) | 222 | static void udbg_44x_as1_flush(void) |
| 223 | { | 223 | { |
| 224 | if (udbg_comport) { | 224 | if (udbg_comport) { |
| 225 | while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) | 225 | while ((as1_readb(&udbg_comport->lsr) & LSR_THRE) == 0) |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 2d2192e48de7..3e68363405b7 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -30,3 +30,4 @@ obj-$(CONFIG_PPC_MM_SLICES) += slice.o | |||
| 30 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o | 30 | obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o |
| 31 | obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o | 31 | obj-$(CONFIG_PPC_SUBPAGE_PROT) += subpage-prot.o |
| 32 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o | 32 | obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o |
| 33 | obj-$(CONFIG_HIGHMEM) += highmem.o | ||
diff --git a/arch/powerpc/mm/highmem.c b/arch/powerpc/mm/highmem.c new file mode 100644 index 000000000000..c2186c74c85a --- /dev/null +++ b/arch/powerpc/mm/highmem.c | |||
| @@ -0,0 +1,77 @@ | |||
| 1 | /* | ||
| 2 | * highmem.c: virtual kernel memory mappings for high memory | ||
| 3 | * | ||
| 4 | * PowerPC version, stolen from the i386 version. | ||
| 5 | * | ||
| 6 | * Used in CONFIG_HIGHMEM systems for memory pages which | ||
| 7 | * are not addressable by direct kernel virtual addresses. | ||
| 8 | * | ||
| 9 | * Copyright (C) 1999 Gerhard Wichert, Siemens AG | ||
| 10 | * Gerhard.Wichert@pdb.siemens.de | ||
| 11 | * | ||
| 12 | * | ||
| 13 | * Redesigned the x86 32-bit VM architecture to deal with | ||
| 14 | * up to 16 Terrabyte physical memory. With current x86 CPUs | ||
| 15 | * we now support up to 64 Gigabytes physical RAM. | ||
| 16 | * | ||
| 17 | * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com> | ||
| 18 | * | ||
| 19 | * Reworked for PowerPC by various contributors. Moved from | ||
| 20 | * highmem.h by Benjamin Herrenschmidt (c) 2009 IBM Corp. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/highmem.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | |||
| 26 | /* | ||
| 27 | * The use of kmap_atomic/kunmap_atomic is discouraged - kmap/kunmap | ||
| 28 | * gives a more generic (and caching) interface. But kmap_atomic can | ||
| 29 | * be used in IRQ contexts, so in some (very limited) cases we need | ||
| 30 | * it. | ||
| 31 | */ | ||
| 32 | void *kmap_atomic_prot(struct page *page, enum km_type type, pgprot_t prot) | ||
| 33 | { | ||
| 34 | unsigned int idx; | ||
| 35 | unsigned long vaddr; | ||
| 36 | |||
| 37 | /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ | ||
| 38 | pagefault_disable(); | ||
| 39 | if (!PageHighMem(page)) | ||
| 40 | return page_address(page); | ||
| 41 | |||
| 42 | debug_kmap_atomic(type); | ||
| 43 | idx = type + KM_TYPE_NR*smp_processor_id(); | ||
| 44 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | ||
| 45 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
| 46 | BUG_ON(!pte_none(*(kmap_pte-idx))); | ||
| 47 | #endif | ||
| 48 | __set_pte_at(&init_mm, vaddr, kmap_pte-idx, mk_pte(page, prot), 1); | ||
| 49 | local_flush_tlb_page(NULL, vaddr); | ||
| 50 | |||
| 51 | return (void*) vaddr; | ||
| 52 | } | ||
| 53 | EXPORT_SYMBOL(kmap_atomic_prot); | ||
| 54 | |||
| 55 | void kunmap_atomic(void *kvaddr, enum km_type type) | ||
| 56 | { | ||
| 57 | #ifdef CONFIG_DEBUG_HIGHMEM | ||
| 58 | unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; | ||
| 59 | enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); | ||
| 60 | |||
| 61 | if (vaddr < __fix_to_virt(FIX_KMAP_END)) { | ||
| 62 | pagefault_enable(); | ||
| 63 | return; | ||
| 64 | } | ||
| 65 | |||
| 66 | BUG_ON(vaddr != __fix_to_virt(FIX_KMAP_BEGIN + idx)); | ||
| 67 | |||
| 68 | /* | ||
| 69 | * force other mappings to Oops if they'll try to access | ||
| 70 | * this pte without first remap it | ||
| 71 | */ | ||
| 72 | pte_clear(&init_mm, vaddr, kmap_pte-idx); | ||
| 73 | local_flush_tlb_page(NULL, vaddr); | ||
| 74 | #endif | ||
| 75 | pagefault_enable(); | ||
| 76 | } | ||
| 77 | EXPORT_SYMBOL(kunmap_atomic); | ||
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 42e09a9f77e2..0362c88f47d7 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/of_gpio.h> | 18 | #include <linux/of_gpio.h> |
| 19 | #include <linux/of_i2c.h> | ||
| 19 | 20 | ||
| 20 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
| 21 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
| @@ -65,7 +66,6 @@ define_machine(warp) { | |||
| 65 | 66 | ||
| 66 | static u32 post_info; | 67 | static u32 post_info; |
| 67 | 68 | ||
| 68 | /* I am not sure this is the best place for this... */ | ||
| 69 | static int __init warp_post_info(void) | 69 | static int __init warp_post_info(void) |
| 70 | { | 70 | { |
| 71 | struct device_node *np; | 71 | struct device_node *np; |
| @@ -194,9 +194,9 @@ static int pika_setup_leds(void) | |||
| 194 | return 0; | 194 | return 0; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | static void pika_setup_critical_temp(struct i2c_client *client) | 197 | static void pika_setup_critical_temp(struct device_node *np, |
| 198 | struct i2c_client *client) | ||
| 198 | { | 199 | { |
| 199 | struct device_node *np; | ||
| 200 | int irq, rc; | 200 | int irq, rc; |
| 201 | 201 | ||
| 202 | /* Do this before enabling critical temp interrupt since we | 202 | /* Do this before enabling critical temp interrupt since we |
| @@ -208,14 +208,7 @@ static void pika_setup_critical_temp(struct i2c_client *client) | |||
| 208 | i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */ | 208 | i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */ |
| 209 | i2c_smbus_write_byte_data(client, 3, 0); /* Tlow */ | 209 | i2c_smbus_write_byte_data(client, 3, 0); /* Tlow */ |
| 210 | 210 | ||
| 211 | np = of_find_compatible_node(NULL, NULL, "adi,ad7414"); | ||
| 212 | if (np == NULL) { | ||
| 213 | printk(KERN_ERR __FILE__ ": Unable to find ad7414\n"); | ||
| 214 | return; | ||
| 215 | } | ||
| 216 | |||
| 217 | irq = irq_of_parse_and_map(np, 0); | 211 | irq = irq_of_parse_and_map(np, 0); |
| 218 | of_node_put(np); | ||
| 219 | if (irq == NO_IRQ) { | 212 | if (irq == NO_IRQ) { |
| 220 | printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n"); | 213 | printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n"); |
| 221 | return; | 214 | return; |
| @@ -244,32 +237,24 @@ static inline void pika_dtm_check_fan(void __iomem *fpga) | |||
| 244 | 237 | ||
| 245 | static int pika_dtm_thread(void __iomem *fpga) | 238 | static int pika_dtm_thread(void __iomem *fpga) |
| 246 | { | 239 | { |
| 247 | struct i2c_adapter *adap; | 240 | struct device_node *np; |
| 248 | struct i2c_client *client; | 241 | struct i2c_client *client; |
| 249 | 242 | ||
| 250 | /* We loop in case either driver was compiled as a module and | 243 | np = of_find_compatible_node(NULL, NULL, "adi,ad7414"); |
| 251 | * has not been insmoded yet. | 244 | if (np == NULL) |
| 252 | */ | 245 | return -ENOENT; |
| 253 | while (!(adap = i2c_get_adapter(0))) { | ||
| 254 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 255 | schedule_timeout(HZ); | ||
| 256 | } | ||
| 257 | |||
| 258 | while (1) { | ||
| 259 | list_for_each_entry(client, &adap->clients, list) | ||
| 260 | if (client->addr == 0x4a) | ||
| 261 | goto found_it; | ||
| 262 | 246 | ||
| 263 | set_current_state(TASK_INTERRUPTIBLE); | 247 | client = of_find_i2c_device_by_node(np); |
| 264 | schedule_timeout(HZ); | 248 | if (client == NULL) { |
| 249 | of_node_put(np); | ||
| 250 | return -ENOENT; | ||
| 265 | } | 251 | } |
| 266 | 252 | ||
| 267 | found_it: | 253 | pika_setup_critical_temp(np, client); |
| 268 | pika_setup_critical_temp(client); | ||
| 269 | 254 | ||
| 270 | i2c_put_adapter(adap); | 255 | of_node_put(np); |
| 271 | 256 | ||
| 272 | printk(KERN_INFO "PIKA DTM thread running.\n"); | 257 | printk(KERN_INFO "Warp DTM thread running.\n"); |
| 273 | 258 | ||
| 274 | while (!kthread_should_stop()) { | 259 | while (!kthread_should_stop()) { |
| 275 | int val; | 260 | int val; |
| @@ -291,7 +276,6 @@ found_it: | |||
| 291 | return 0; | 276 | return 0; |
| 292 | } | 277 | } |
| 293 | 278 | ||
| 294 | |||
| 295 | static int __init pika_dtm_start(void) | 279 | static int __init pika_dtm_start(void) |
| 296 | { | 280 | { |
| 297 | struct task_struct *dtm_thread; | 281 | struct task_struct *dtm_thread; |
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 77f90b356356..60ed9c067b1d 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
| @@ -285,6 +285,7 @@ static struct of_device_id mpc85xx_ids[] = { | |||
| 285 | { .type = "qe", }, | 285 | { .type = "qe", }, |
| 286 | { .compatible = "fsl,qe", }, | 286 | { .compatible = "fsl,qe", }, |
| 287 | { .compatible = "gianfar", }, | 287 | { .compatible = "gianfar", }, |
| 288 | { .compatible = "fsl,rapidio-delta", }, | ||
| 288 | {}, | 289 | {}, |
| 289 | }; | 290 | }; |
| 290 | 291 | ||
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index cc0b0db8a6f3..62c592ede641 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
| @@ -52,20 +52,19 @@ smp_85xx_kick_cpu(int nr) | |||
| 52 | 52 | ||
| 53 | pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); | 53 | pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); |
| 54 | 54 | ||
| 55 | local_irq_save(flags); | ||
| 56 | |||
| 57 | np = of_get_cpu_node(nr, NULL); | 55 | np = of_get_cpu_node(nr, NULL); |
| 58 | cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); | 56 | cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); |
| 59 | 57 | ||
| 60 | if (cpu_rel_addr == NULL) { | 58 | if (cpu_rel_addr == NULL) { |
| 61 | printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); | 59 | printk(KERN_ERR "No cpu-release-addr for cpu %d\n", nr); |
| 62 | local_irq_restore(flags); | ||
| 63 | return; | 60 | return; |
| 64 | } | 61 | } |
| 65 | 62 | ||
| 66 | /* Map the spin table */ | 63 | /* Map the spin table */ |
| 67 | bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY); | 64 | bptr_vaddr = ioremap(*cpu_rel_addr, SIZE_BOOT_ENTRY); |
| 68 | 65 | ||
| 66 | local_irq_save(flags); | ||
| 67 | |||
| 69 | out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); | 68 | out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); |
| 70 | out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); | 69 | out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); |
| 71 | 70 | ||
| @@ -73,10 +72,10 @@ smp_85xx_kick_cpu(int nr) | |||
| 73 | while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) | 72 | while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) |
| 74 | mdelay(1); | 73 | mdelay(1); |
| 75 | 74 | ||
| 76 | iounmap(bptr_vaddr); | ||
| 77 | |||
| 78 | local_irq_restore(flags); | 75 | local_irq_restore(flags); |
| 79 | 76 | ||
| 77 | iounmap(bptr_vaddr); | ||
| 78 | |||
| 80 | pr_debug("waited %d msecs for CPU #%d.\n", n, nr); | 79 | pr_debug("waited %d msecs for CPU #%d.\n", n, nr); |
| 81 | } | 80 | } |
| 82 | 81 | ||
diff --git a/arch/powerpc/platforms/85xx/socrates.c b/arch/powerpc/platforms/85xx/socrates.c index d0e8443b12c6..747d8fb3ab82 100644 --- a/arch/powerpc/platforms/85xx/socrates.c +++ b/arch/powerpc/platforms/85xx/socrates.c | |||
| @@ -102,10 +102,11 @@ static struct of_device_id __initdata socrates_of_bus_ids[] = { | |||
| 102 | {}, | 102 | {}, |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | static void __init socrates_init(void) | 105 | static int __init socrates_publish_devices(void) |
| 106 | { | 106 | { |
| 107 | of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL); | 107 | return of_platform_bus_probe(NULL, socrates_of_bus_ids, NULL); |
| 108 | } | 108 | } |
| 109 | machine_device_initcall(socrates, socrates_publish_devices); | ||
| 109 | 110 | ||
| 110 | /* | 111 | /* |
| 111 | * Called very early, device-tree isn't unflattened | 112 | * Called very early, device-tree isn't unflattened |
| @@ -124,7 +125,6 @@ define_machine(socrates) { | |||
| 124 | .name = "Socrates", | 125 | .name = "Socrates", |
| 125 | .probe = socrates_probe, | 126 | .probe = socrates_probe, |
| 126 | .setup_arch = socrates_setup_arch, | 127 | .setup_arch = socrates_setup_arch, |
| 127 | .init = socrates_init, | ||
| 128 | .init_IRQ = socrates_pic_init, | 128 | .init_IRQ = socrates_pic_init, |
| 129 | .get_irq = mpic_get_irq, | 129 | .get_irq = mpic_get_irq, |
| 130 | .restart = fsl_rstcr_restart, | 130 | .restart = fsl_rstcr_restart, |
diff --git a/arch/powerpc/platforms/85xx/xes_mpc85xx.c b/arch/powerpc/platforms/85xx/xes_mpc85xx.c index ee01532786e4..1b426050a2f9 100644 --- a/arch/powerpc/platforms/85xx/xes_mpc85xx.c +++ b/arch/powerpc/platforms/85xx/xes_mpc85xx.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | #include <sysdev/fsl_soc.h> | 33 | #include <sysdev/fsl_soc.h> |
| 34 | #include <sysdev/fsl_pci.h> | 34 | #include <sysdev/fsl_pci.h> |
| 35 | #include <linux/of_platform.h> | ||
| 36 | 35 | ||
| 37 | /* A few bit definitions needed for fixups on some boards */ | 36 | /* A few bit definitions needed for fixups on some boards */ |
| 38 | #define MPC85xx_L2CTL_L2E 0x80000000 /* L2 enable */ | 37 | #define MPC85xx_L2CTL_L2E 0x80000000 /* L2 enable */ |
diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index 9046803c8276..bc97fada48c6 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <asm/prom.h> | 36 | #include <asm/prom.h> |
| 37 | #include <asm/smp.h> | 37 | #include <asm/smp.h> |
| 38 | #include <asm/paca.h> | 38 | #include <asm/paca.h> |
| 39 | #include <asm/time.h> | ||
| 40 | #include <asm/machdep.h> | 39 | #include <asm/machdep.h> |
| 41 | #include <asm/cputable.h> | 40 | #include <asm/cputable.h> |
| 42 | #include <asm/firmware.h> | 41 | #include <asm/firmware.h> |
| @@ -140,31 +139,6 @@ static void __devinit smp_cell_setup_cpu(int cpu) | |||
| 140 | mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER); | 139 | mtspr(SPRN_DABRX, DABRX_KERNEL | DABRX_USER); |
| 141 | } | 140 | } |
| 142 | 141 | ||
| 143 | static DEFINE_SPINLOCK(timebase_lock); | ||
| 144 | static unsigned long timebase = 0; | ||
| 145 | |||
| 146 | static void __devinit cell_give_timebase(void) | ||
| 147 | { | ||
| 148 | spin_lock(&timebase_lock); | ||
| 149 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); | ||
| 150 | timebase = get_tb(); | ||
| 151 | spin_unlock(&timebase_lock); | ||
| 152 | |||
| 153 | while (timebase) | ||
| 154 | barrier(); | ||
| 155 | rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); | ||
| 156 | } | ||
| 157 | |||
| 158 | static void __devinit cell_take_timebase(void) | ||
| 159 | { | ||
| 160 | while (!timebase) | ||
| 161 | barrier(); | ||
| 162 | spin_lock(&timebase_lock); | ||
| 163 | set_tb(timebase >> 32, timebase & 0xffffffff); | ||
| 164 | timebase = 0; | ||
| 165 | spin_unlock(&timebase_lock); | ||
| 166 | } | ||
| 167 | |||
| 168 | static void __devinit smp_cell_kick_cpu(int nr) | 142 | static void __devinit smp_cell_kick_cpu(int nr) |
| 169 | { | 143 | { |
| 170 | BUG_ON(nr < 0 || nr >= NR_CPUS); | 144 | BUG_ON(nr < 0 || nr >= NR_CPUS); |
| @@ -224,8 +198,8 @@ void __init smp_init_cell(void) | |||
| 224 | 198 | ||
| 225 | /* Non-lpar has additional take/give timebase */ | 199 | /* Non-lpar has additional take/give timebase */ |
| 226 | if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { | 200 | if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { |
| 227 | smp_ops->give_timebase = cell_give_timebase; | 201 | smp_ops->give_timebase = rtas_give_timebase; |
| 228 | smp_ops->take_timebase = cell_take_timebase; | 202 | smp_ops->take_timebase = rtas_take_timebase; |
| 229 | } | 203 | } |
| 230 | 204 | ||
| 231 | DBG(" <- smp_init_cell()\n"); | 205 | DBG(" <- smp_init_cell()\n"); |
diff --git a/arch/powerpc/platforms/chrp/smp.c b/arch/powerpc/platforms/chrp/smp.c index 10a4a4d063b6..02cafecc90e3 100644 --- a/arch/powerpc/platforms/chrp/smp.c +++ b/arch/powerpc/platforms/chrp/smp.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
| 27 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
| 28 | #include <asm/smp.h> | 28 | #include <asm/smp.h> |
| 29 | #include <asm/time.h> | ||
| 30 | #include <asm/machdep.h> | 29 | #include <asm/machdep.h> |
| 31 | #include <asm/mpic.h> | 30 | #include <asm/mpic.h> |
| 32 | #include <asm/rtas.h> | 31 | #include <asm/rtas.h> |
| @@ -42,40 +41,12 @@ static void __devinit smp_chrp_setup_cpu(int cpu_nr) | |||
| 42 | mpic_setup_this_cpu(); | 41 | mpic_setup_this_cpu(); |
| 43 | } | 42 | } |
| 44 | 43 | ||
| 45 | static DEFINE_SPINLOCK(timebase_lock); | ||
| 46 | static unsigned int timebase_upper = 0, timebase_lower = 0; | ||
| 47 | |||
| 48 | void __devinit smp_chrp_give_timebase(void) | ||
| 49 | { | ||
| 50 | spin_lock(&timebase_lock); | ||
| 51 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); | ||
| 52 | timebase_upper = get_tbu(); | ||
| 53 | timebase_lower = get_tbl(); | ||
| 54 | spin_unlock(&timebase_lock); | ||
| 55 | |||
| 56 | while (timebase_upper || timebase_lower) | ||
| 57 | barrier(); | ||
| 58 | rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); | ||
| 59 | } | ||
| 60 | |||
| 61 | void __devinit smp_chrp_take_timebase(void) | ||
| 62 | { | ||
| 63 | while (!(timebase_upper || timebase_lower)) | ||
| 64 | barrier(); | ||
| 65 | spin_lock(&timebase_lock); | ||
| 66 | set_tb(timebase_upper, timebase_lower); | ||
| 67 | timebase_upper = 0; | ||
| 68 | timebase_lower = 0; | ||
| 69 | spin_unlock(&timebase_lock); | ||
| 70 | printk("CPU %i taken timebase\n", smp_processor_id()); | ||
| 71 | } | ||
| 72 | |||
| 73 | /* CHRP with openpic */ | 44 | /* CHRP with openpic */ |
| 74 | struct smp_ops_t chrp_smp_ops = { | 45 | struct smp_ops_t chrp_smp_ops = { |
| 75 | .message_pass = smp_mpic_message_pass, | 46 | .message_pass = smp_mpic_message_pass, |
| 76 | .probe = smp_mpic_probe, | 47 | .probe = smp_mpic_probe, |
| 77 | .kick_cpu = smp_chrp_kick_cpu, | 48 | .kick_cpu = smp_chrp_kick_cpu, |
| 78 | .setup_cpu = smp_chrp_setup_cpu, | 49 | .setup_cpu = smp_chrp_setup_cpu, |
| 79 | .give_timebase = smp_chrp_give_timebase, | 50 | .give_timebase = rtas_give_timebase, |
| 80 | .take_timebase = smp_chrp_take_timebase, | 51 | .take_timebase = rtas_take_timebase, |
| 81 | }; | 52 | }; |
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c index 153051eb6d93..a4619347aa7e 100644 --- a/arch/powerpc/platforms/pasemi/setup.c +++ b/arch/powerpc/platforms/pasemi/setup.c | |||
| @@ -71,20 +71,25 @@ static void pas_restart(char *cmd) | |||
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | #ifdef CONFIG_SMP | 73 | #ifdef CONFIG_SMP |
| 74 | static DEFINE_SPINLOCK(timebase_lock); | 74 | static raw_spinlock_t timebase_lock; |
| 75 | static unsigned long timebase; | 75 | static unsigned long timebase; |
| 76 | 76 | ||
| 77 | static void __devinit pas_give_timebase(void) | 77 | static void __devinit pas_give_timebase(void) |
| 78 | { | 78 | { |
| 79 | spin_lock(&timebase_lock); | 79 | unsigned long flags; |
| 80 | |||
| 81 | local_irq_save(flags); | ||
| 82 | hard_irq_disable(); | ||
| 83 | __raw_spin_lock(&timebase_lock); | ||
| 80 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); | 84 | mtspr(SPRN_TBCTL, TBCTL_FREEZE); |
| 81 | isync(); | 85 | isync(); |
| 82 | timebase = get_tb(); | 86 | timebase = get_tb(); |
| 83 | spin_unlock(&timebase_lock); | 87 | __raw_spin_unlock(&timebase_lock); |
| 84 | 88 | ||
| 85 | while (timebase) | 89 | while (timebase) |
| 86 | barrier(); | 90 | barrier(); |
| 87 | mtspr(SPRN_TBCTL, TBCTL_RESTART); | 91 | mtspr(SPRN_TBCTL, TBCTL_RESTART); |
| 92 | local_irq_restore(flags); | ||
| 88 | } | 93 | } |
| 89 | 94 | ||
| 90 | static void __devinit pas_take_timebase(void) | 95 | static void __devinit pas_take_timebase(void) |
| @@ -92,10 +97,10 @@ static void __devinit pas_take_timebase(void) | |||
| 92 | while (!timebase) | 97 | while (!timebase) |
| 93 | smp_rmb(); | 98 | smp_rmb(); |
| 94 | 99 | ||
| 95 | spin_lock(&timebase_lock); | 100 | __raw_spin_lock(&timebase_lock); |
| 96 | set_tb(timebase >> 32, timebase & 0xffffffff); | 101 | set_tb(timebase >> 32, timebase & 0xffffffff); |
| 97 | timebase = 0; | 102 | timebase = 0; |
| 98 | spin_unlock(&timebase_lock); | 103 | __raw_spin_unlock(&timebase_lock); |
| 99 | } | 104 | } |
| 100 | 105 | ||
| 101 | struct smp_ops_t pas_smp_ops = { | 106 | struct smp_ops_t pas_smp_ops = { |
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 86f69a4eb49b..c20522656367 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
| @@ -103,11 +103,6 @@ unsigned long smu_cmdbuf_abs; | |||
| 103 | EXPORT_SYMBOL(smu_cmdbuf_abs); | 103 | EXPORT_SYMBOL(smu_cmdbuf_abs); |
| 104 | #endif | 104 | #endif |
| 105 | 105 | ||
| 106 | #ifdef CONFIG_SMP | ||
| 107 | extern struct smp_ops_t psurge_smp_ops; | ||
| 108 | extern struct smp_ops_t core99_smp_ops; | ||
| 109 | #endif /* CONFIG_SMP */ | ||
| 110 | |||
| 111 | static void pmac_show_cpuinfo(struct seq_file *m) | 106 | static void pmac_show_cpuinfo(struct seq_file *m) |
| 112 | { | 107 | { |
| 113 | struct device_node *np; | 108 | struct device_node *np; |
| @@ -341,34 +336,6 @@ static void __init pmac_setup_arch(void) | |||
| 341 | ROOT_DEV = DEFAULT_ROOT_DEVICE; | 336 | ROOT_DEV = DEFAULT_ROOT_DEVICE; |
| 342 | #endif | 337 | #endif |
| 343 | 338 | ||
| 344 | #ifdef CONFIG_SMP | ||
| 345 | /* Check for Core99 */ | ||
| 346 | ic = of_find_node_by_name(NULL, "uni-n"); | ||
| 347 | if (!ic) | ||
| 348 | ic = of_find_node_by_name(NULL, "u3"); | ||
| 349 | if (!ic) | ||
| 350 | ic = of_find_node_by_name(NULL, "u4"); | ||
| 351 | if (ic) { | ||
| 352 | of_node_put(ic); | ||
| 353 | smp_ops = &core99_smp_ops; | ||
| 354 | } | ||
| 355 | #ifdef CONFIG_PPC32 | ||
| 356 | else { | ||
| 357 | /* | ||
| 358 | * We have to set bits in cpu_possible_map here since the | ||
| 359 | * secondary CPU(s) aren't in the device tree, and | ||
| 360 | * setup_per_cpu_areas only allocates per-cpu data for | ||
| 361 | * CPUs in the cpu_possible_map. | ||
| 362 | */ | ||
| 363 | int cpu; | ||
| 364 | |||
| 365 | for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu) | ||
| 366 | cpu_set(cpu, cpu_possible_map); | ||
| 367 | smp_ops = &psurge_smp_ops; | ||
| 368 | } | ||
| 369 | #endif | ||
| 370 | #endif /* CONFIG_SMP */ | ||
| 371 | |||
| 372 | #ifdef CONFIG_ADB | 339 | #ifdef CONFIG_ADB |
| 373 | if (strstr(cmd_line, "adb_sync")) { | 340 | if (strstr(cmd_line, "adb_sync")) { |
| 374 | extern int __adb_probe_sync; | 341 | extern int __adb_probe_sync; |
| @@ -512,6 +479,14 @@ static void __init pmac_init_early(void) | |||
| 512 | #ifdef CONFIG_PPC64 | 479 | #ifdef CONFIG_PPC64 |
| 513 | iommu_init_early_dart(); | 480 | iommu_init_early_dart(); |
| 514 | #endif | 481 | #endif |
| 482 | |||
| 483 | /* SMP Init has to be done early as we need to patch up | ||
| 484 | * cpu_possible_map before interrupt stacks are allocated | ||
| 485 | * or kaboom... | ||
| 486 | */ | ||
| 487 | #ifdef CONFIG_SMP | ||
| 488 | pmac_setup_smp(); | ||
| 489 | #endif | ||
| 515 | } | 490 | } |
| 516 | 491 | ||
| 517 | static int __init pmac_declare_of_platform_devices(void) | 492 | static int __init pmac_declare_of_platform_devices(void) |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index cf1dbe758890..6d4da7b46b41 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
| @@ -64,10 +64,11 @@ | |||
| 64 | extern void __secondary_start_pmac_0(void); | 64 | extern void __secondary_start_pmac_0(void); |
| 65 | extern int pmac_pfunc_base_install(void); | 65 | extern int pmac_pfunc_base_install(void); |
| 66 | 66 | ||
| 67 | #ifdef CONFIG_PPC32 | 67 | static void (*pmac_tb_freeze)(int freeze); |
| 68 | static u64 timebase; | ||
| 69 | static int tb_req; | ||
| 68 | 70 | ||
| 69 | /* Sync flag for HW tb sync */ | 71 | #ifdef CONFIG_PPC32 |
| 70 | static volatile int sec_tb_reset = 0; | ||
| 71 | 72 | ||
| 72 | /* | 73 | /* |
| 73 | * Powersurge (old powermac SMP) support. | 74 | * Powersurge (old powermac SMP) support. |
| @@ -294,6 +295,9 @@ static int __init smp_psurge_probe(void) | |||
| 294 | psurge_quad_init(); | 295 | psurge_quad_init(); |
| 295 | /* All released cards using this HW design have 4 CPUs */ | 296 | /* All released cards using this HW design have 4 CPUs */ |
| 296 | ncpus = 4; | 297 | ncpus = 4; |
| 298 | /* No sure how timebase sync works on those, let's use SW */ | ||
| 299 | smp_ops->give_timebase = smp_generic_give_timebase; | ||
| 300 | smp_ops->take_timebase = smp_generic_take_timebase; | ||
| 297 | } else { | 301 | } else { |
| 298 | iounmap(quad_base); | 302 | iounmap(quad_base); |
| 299 | if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { | 303 | if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) { |
| @@ -308,18 +312,15 @@ static int __init smp_psurge_probe(void) | |||
| 308 | psurge_start = ioremap(PSURGE_START, 4); | 312 | psurge_start = ioremap(PSURGE_START, 4); |
| 309 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); | 313 | psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4); |
| 310 | 314 | ||
| 311 | /* | 315 | /* This is necessary because OF doesn't know about the |
| 312 | * This is necessary because OF doesn't know about the | ||
| 313 | * secondary cpu(s), and thus there aren't nodes in the | 316 | * secondary cpu(s), and thus there aren't nodes in the |
| 314 | * device tree for them, and smp_setup_cpu_maps hasn't | 317 | * device tree for them, and smp_setup_cpu_maps hasn't |
| 315 | * set their bits in cpu_possible_map and cpu_present_map. | 318 | * set their bits in cpu_present_map. |
| 316 | */ | 319 | */ |
| 317 | if (ncpus > NR_CPUS) | 320 | if (ncpus > NR_CPUS) |
| 318 | ncpus = NR_CPUS; | 321 | ncpus = NR_CPUS; |
| 319 | for (i = 1; i < ncpus ; ++i) { | 322 | for (i = 1; i < ncpus ; ++i) |
| 320 | cpu_set(i, cpu_present_map); | 323 | cpu_set(i, cpu_present_map); |
| 321 | set_hard_smp_processor_id(i, i); | ||
| 322 | } | ||
| 323 | 324 | ||
| 324 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); | 325 | if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352); |
| 325 | 326 | ||
| @@ -329,8 +330,14 @@ static int __init smp_psurge_probe(void) | |||
| 329 | static void __init smp_psurge_kick_cpu(int nr) | 330 | static void __init smp_psurge_kick_cpu(int nr) |
| 330 | { | 331 | { |
| 331 | unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8; | 332 | unsigned long start = __pa(__secondary_start_pmac_0) + nr * 8; |
| 332 | unsigned long a; | 333 | unsigned long a, flags; |
| 333 | int i; | 334 | int i, j; |
| 335 | |||
| 336 | /* Defining this here is evil ... but I prefer hiding that | ||
| 337 | * crap to avoid giving people ideas that they can do the | ||
| 338 | * same. | ||
| 339 | */ | ||
| 340 | extern volatile unsigned int cpu_callin_map[NR_CPUS]; | ||
| 334 | 341 | ||
| 335 | /* may need to flush here if secondary bats aren't setup */ | 342 | /* may need to flush here if secondary bats aren't setup */ |
| 336 | for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) | 343 | for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32) |
| @@ -339,47 +346,52 @@ static void __init smp_psurge_kick_cpu(int nr) | |||
| 339 | 346 | ||
| 340 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); | 347 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353); |
| 341 | 348 | ||
| 349 | /* This is going to freeze the timeebase, we disable interrupts */ | ||
| 350 | local_irq_save(flags); | ||
| 351 | |||
| 342 | out_be32(psurge_start, start); | 352 | out_be32(psurge_start, start); |
| 343 | mb(); | 353 | mb(); |
| 344 | 354 | ||
| 345 | psurge_set_ipi(nr); | 355 | psurge_set_ipi(nr); |
| 356 | |||
| 346 | /* | 357 | /* |
| 347 | * We can't use udelay here because the timebase is now frozen. | 358 | * We can't use udelay here because the timebase is now frozen. |
| 348 | */ | 359 | */ |
| 349 | for (i = 0; i < 2000; ++i) | 360 | for (i = 0; i < 2000; ++i) |
| 350 | barrier(); | 361 | asm volatile("nop" : : : "memory"); |
| 351 | psurge_clr_ipi(nr); | 362 | psurge_clr_ipi(nr); |
| 352 | 363 | ||
| 353 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); | 364 | /* |
| 354 | } | 365 | * Also, because the timebase is frozen, we must not return to the |
| 355 | 366 | * caller which will try to do udelay's etc... Instead, we wait -here- | |
| 356 | /* | 367 | * for the CPU to callin. |
| 357 | * With the dual-cpu powersurge board, the decrementers and timebases | 368 | */ |
| 358 | * of both cpus are frozen after the secondary cpu is started up, | 369 | for (i = 0; i < 100000 && !cpu_callin_map[nr]; ++i) { |
| 359 | * until we give the secondary cpu another interrupt. This routine | 370 | for (j = 1; j < 10000; j++) |
| 360 | * uses this to get the timebases synchronized. | 371 | asm volatile("nop" : : : "memory"); |
| 361 | * -- paulus. | 372 | asm volatile("sync" : : : "memory"); |
| 362 | */ | 373 | } |
| 363 | static void __init psurge_dual_sync_tb(int cpu_nr) | 374 | if (!cpu_callin_map[nr]) |
| 364 | { | 375 | goto stuck; |
| 365 | int t; | 376 | |
| 366 | 377 | /* And we do the TB sync here too for standard dual CPU cards */ | |
| 367 | set_dec(tb_ticks_per_jiffy); | 378 | if (psurge_type == PSURGE_DUAL) { |
| 368 | /* XXX fixme */ | 379 | while(!tb_req) |
| 369 | set_tb(0, 0); | 380 | barrier(); |
| 370 | 381 | tb_req = 0; | |
| 371 | if (cpu_nr > 0) { | 382 | mb(); |
| 383 | timebase = get_tb(); | ||
| 384 | mb(); | ||
| 385 | while (timebase) | ||
| 386 | barrier(); | ||
| 372 | mb(); | 387 | mb(); |
| 373 | sec_tb_reset = 1; | ||
| 374 | return; | ||
| 375 | } | 388 | } |
| 389 | stuck: | ||
| 390 | /* now interrupt the secondary, restarting both TBs */ | ||
| 391 | if (psurge_type == PSURGE_DUAL) | ||
| 392 | psurge_set_ipi(1); | ||
| 376 | 393 | ||
| 377 | /* wait for the secondary to have reset its TB before proceeding */ | 394 | if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354); |
| 378 | for (t = 10000000; t > 0 && !sec_tb_reset; --t) | ||
| 379 | ; | ||
| 380 | |||
| 381 | /* now interrupt the secondary, starting both TBs */ | ||
| 382 | psurge_set_ipi(1); | ||
| 383 | } | 395 | } |
| 384 | 396 | ||
| 385 | static struct irqaction psurge_irqaction = { | 397 | static struct irqaction psurge_irqaction = { |
| @@ -390,36 +402,35 @@ static struct irqaction psurge_irqaction = { | |||
| 390 | 402 | ||
| 391 | static void __init smp_psurge_setup_cpu(int cpu_nr) | 403 | static void __init smp_psurge_setup_cpu(int cpu_nr) |
| 392 | { | 404 | { |
| 405 | if (cpu_nr != 0) | ||
| 406 | return; | ||
| 393 | 407 | ||
| 394 | if (cpu_nr == 0) { | 408 | /* reset the entry point so if we get another intr we won't |
| 395 | /* If we failed to start the second CPU, we should still | 409 | * try to startup again */ |
| 396 | * send it an IPI to start the timebase & DEC or we might | 410 | out_be32(psurge_start, 0x100); |
| 397 | * have them stuck. | 411 | if (setup_irq(30, &psurge_irqaction)) |
| 398 | */ | 412 | printk(KERN_ERR "Couldn't get primary IPI interrupt"); |
| 399 | if (num_online_cpus() < 2) { | ||
| 400 | if (psurge_type == PSURGE_DUAL) | ||
| 401 | psurge_set_ipi(1); | ||
| 402 | return; | ||
| 403 | } | ||
| 404 | /* reset the entry point so if we get another intr we won't | ||
| 405 | * try to startup again */ | ||
| 406 | out_be32(psurge_start, 0x100); | ||
| 407 | if (setup_irq(30, &psurge_irqaction)) | ||
| 408 | printk(KERN_ERR "Couldn't get primary IPI interrupt"); | ||
| 409 | } | ||
| 410 | |||
| 411 | if (psurge_type == PSURGE_DUAL) | ||
| 412 | psurge_dual_sync_tb(cpu_nr); | ||
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | void __init smp_psurge_take_timebase(void) | 415 | void __init smp_psurge_take_timebase(void) |
| 416 | { | 416 | { |
| 417 | /* Dummy implementation */ | 417 | if (psurge_type != PSURGE_DUAL) |
| 418 | return; | ||
| 419 | |||
| 420 | tb_req = 1; | ||
| 421 | mb(); | ||
| 422 | while (!timebase) | ||
| 423 | barrier(); | ||
| 424 | mb(); | ||
| 425 | set_tb(timebase >> 32, timebase & 0xffffffff); | ||
| 426 | timebase = 0; | ||
| 427 | mb(); | ||
| 428 | set_dec(tb_ticks_per_jiffy/2); | ||
| 418 | } | 429 | } |
| 419 | 430 | ||
| 420 | void __init smp_psurge_give_timebase(void) | 431 | void __init smp_psurge_give_timebase(void) |
| 421 | { | 432 | { |
| 422 | /* Dummy implementation */ | 433 | /* Nothing to do here */ |
| 423 | } | 434 | } |
| 424 | 435 | ||
| 425 | /* PowerSurge-style Macs */ | 436 | /* PowerSurge-style Macs */ |
| @@ -437,9 +448,6 @@ struct smp_ops_t psurge_smp_ops = { | |||
| 437 | * Core 99 and later support | 448 | * Core 99 and later support |
| 438 | */ | 449 | */ |
| 439 | 450 | ||
| 440 | static void (*pmac_tb_freeze)(int freeze); | ||
| 441 | static u64 timebase; | ||
| 442 | static int tb_req; | ||
| 443 | 451 | ||
| 444 | static void smp_core99_give_timebase(void) | 452 | static void smp_core99_give_timebase(void) |
| 445 | { | 453 | { |
| @@ -478,7 +486,6 @@ static void __devinit smp_core99_take_timebase(void) | |||
| 478 | set_tb(timebase >> 32, timebase & 0xffffffff); | 486 | set_tb(timebase >> 32, timebase & 0xffffffff); |
| 479 | timebase = 0; | 487 | timebase = 0; |
| 480 | mb(); | 488 | mb(); |
| 481 | set_dec(tb_ticks_per_jiffy/2); | ||
| 482 | 489 | ||
| 483 | local_irq_restore(flags); | 490 | local_irq_restore(flags); |
| 484 | } | 491 | } |
| @@ -920,3 +927,34 @@ struct smp_ops_t core99_smp_ops = { | |||
| 920 | # endif | 927 | # endif |
| 921 | #endif | 928 | #endif |
| 922 | }; | 929 | }; |
| 930 | |||
| 931 | void __init pmac_setup_smp(void) | ||
| 932 | { | ||
| 933 | struct device_node *np; | ||
| 934 | |||
| 935 | /* Check for Core99 */ | ||
| 936 | np = of_find_node_by_name(NULL, "uni-n"); | ||
| 937 | if (!np) | ||
| 938 | np = of_find_node_by_name(NULL, "u3"); | ||
| 939 | if (!np) | ||
| 940 | np = of_find_node_by_name(NULL, "u4"); | ||
| 941 | if (np) { | ||
| 942 | of_node_put(np); | ||
| 943 | smp_ops = &core99_smp_ops; | ||
| 944 | } | ||
| 945 | #ifdef CONFIG_PPC32 | ||
| 946 | else { | ||
| 947 | /* We have to set bits in cpu_possible_map here since the | ||
| 948 | * secondary CPU(s) aren't in the device tree. Various | ||
| 949 | * things won't be initialized for CPUs not in the possible | ||
| 950 | * map, so we really need to fix it up here. | ||
| 951 | */ | ||
| 952 | int cpu; | ||
| 953 | |||
| 954 | for (cpu = 1; cpu < 4 && cpu < NR_CPUS; ++cpu) | ||
| 955 | cpu_set(cpu, cpu_possible_map); | ||
| 956 | smp_ops = &psurge_smp_ops; | ||
| 957 | } | ||
| 958 | #endif /* CONFIG_PPC32 */ | ||
| 959 | } | ||
| 960 | |||
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 1a231c389ba0..1f8f6cfb94f7 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
| @@ -35,7 +35,6 @@ | |||
| 35 | #include <asm/prom.h> | 35 | #include <asm/prom.h> |
| 36 | #include <asm/smp.h> | 36 | #include <asm/smp.h> |
| 37 | #include <asm/paca.h> | 37 | #include <asm/paca.h> |
| 38 | #include <asm/time.h> | ||
| 39 | #include <asm/machdep.h> | 38 | #include <asm/machdep.h> |
| 40 | #include <asm/cputable.h> | 39 | #include <asm/cputable.h> |
| 41 | #include <asm/firmware.h> | 40 | #include <asm/firmware.h> |
| @@ -118,31 +117,6 @@ static void __devinit smp_xics_setup_cpu(int cpu) | |||
| 118 | } | 117 | } |
| 119 | #endif /* CONFIG_XICS */ | 118 | #endif /* CONFIG_XICS */ |
| 120 | 119 | ||
| 121 | static DEFINE_SPINLOCK(timebase_lock); | ||
| 122 | static unsigned long timebase = 0; | ||
| 123 | |||
| 124 | static void __devinit pSeries_give_timebase(void) | ||
| 125 | { | ||
| 126 | spin_lock(&timebase_lock); | ||
| 127 | rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); | ||
| 128 | timebase = get_tb(); | ||
| 129 | spin_unlock(&timebase_lock); | ||
| 130 | |||
| 131 | while (timebase) | ||
| 132 | barrier(); | ||
| 133 | rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); | ||
| 134 | } | ||
| 135 | |||
| 136 | static void __devinit pSeries_take_timebase(void) | ||
| 137 | { | ||
| 138 | while (!timebase) | ||
| 139 | barrier(); | ||
| 140 | spin_lock(&timebase_lock); | ||
| 141 | set_tb(timebase >> 32, timebase & 0xffffffff); | ||
| 142 | timebase = 0; | ||
| 143 | spin_unlock(&timebase_lock); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void __devinit smp_pSeries_kick_cpu(int nr) | 120 | static void __devinit smp_pSeries_kick_cpu(int nr) |
| 147 | { | 121 | { |
| 148 | BUG_ON(nr < 0 || nr >= NR_CPUS); | 122 | BUG_ON(nr < 0 || nr >= NR_CPUS); |
| @@ -209,8 +183,8 @@ static void __init smp_init_pseries(void) | |||
| 209 | 183 | ||
| 210 | /* Non-lpar has additional take/give timebase */ | 184 | /* Non-lpar has additional take/give timebase */ |
| 211 | if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { | 185 | if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { |
| 212 | smp_ops->give_timebase = pSeries_give_timebase; | 186 | smp_ops->give_timebase = rtas_give_timebase; |
| 213 | smp_ops->take_timebase = pSeries_take_timebase; | 187 | smp_ops->take_timebase = rtas_take_timebase; |
| 214 | } | 188 | } |
| 215 | 189 | ||
| 216 | pr_debug(" <- smp_init_pSeries()\n"); | 190 | pr_debug(" <- smp_init_pSeries()\n"); |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 9c3af5045495..d46de1f0f3ee 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -279,28 +279,29 @@ static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr, | |||
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | #ifdef CONFIG_PPC_DCR | 281 | #ifdef CONFIG_PPC_DCR |
| 282 | static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, | 282 | static void _mpic_map_dcr(struct mpic *mpic, struct device_node *node, |
| 283 | struct mpic_reg_bank *rb, | ||
| 283 | unsigned int offset, unsigned int size) | 284 | unsigned int offset, unsigned int size) |
| 284 | { | 285 | { |
| 285 | const u32 *dbasep; | 286 | const u32 *dbasep; |
| 286 | 287 | ||
| 287 | dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL); | 288 | dbasep = of_get_property(node, "dcr-reg", NULL); |
| 288 | 289 | ||
| 289 | rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size); | 290 | rb->dhost = dcr_map(node, *dbasep + offset, size); |
| 290 | BUG_ON(!DCR_MAP_OK(rb->dhost)); | 291 | BUG_ON(!DCR_MAP_OK(rb->dhost)); |
| 291 | } | 292 | } |
| 292 | 293 | ||
| 293 | static inline void mpic_map(struct mpic *mpic, phys_addr_t phys_addr, | 294 | static inline void mpic_map(struct mpic *mpic, struct device_node *node, |
| 294 | struct mpic_reg_bank *rb, unsigned int offset, | 295 | phys_addr_t phys_addr, struct mpic_reg_bank *rb, |
| 295 | unsigned int size) | 296 | unsigned int offset, unsigned int size) |
| 296 | { | 297 | { |
| 297 | if (mpic->flags & MPIC_USES_DCR) | 298 | if (mpic->flags & MPIC_USES_DCR) |
| 298 | _mpic_map_dcr(mpic, rb, offset, size); | 299 | _mpic_map_dcr(mpic, node, rb, offset, size); |
| 299 | else | 300 | else |
| 300 | _mpic_map_mmio(mpic, phys_addr, rb, offset, size); | 301 | _mpic_map_mmio(mpic, phys_addr, rb, offset, size); |
| 301 | } | 302 | } |
| 302 | #else /* CONFIG_PPC_DCR */ | 303 | #else /* CONFIG_PPC_DCR */ |
| 303 | #define mpic_map(m,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) | 304 | #define mpic_map(m,n,p,b,o,s) _mpic_map_mmio(m,p,b,o,s) |
| 304 | #endif /* !CONFIG_PPC_DCR */ | 305 | #endif /* !CONFIG_PPC_DCR */ |
| 305 | 306 | ||
| 306 | 307 | ||
| @@ -1052,11 +1053,10 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1052 | int intvec_top; | 1053 | int intvec_top; |
| 1053 | u64 paddr = phys_addr; | 1054 | u64 paddr = phys_addr; |
| 1054 | 1055 | ||
| 1055 | mpic = alloc_bootmem(sizeof(struct mpic)); | 1056 | mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL); |
| 1056 | if (mpic == NULL) | 1057 | if (mpic == NULL) |
| 1057 | return NULL; | 1058 | return NULL; |
| 1058 | 1059 | ||
| 1059 | memset(mpic, 0, sizeof(struct mpic)); | ||
| 1060 | mpic->name = name; | 1060 | mpic->name = name; |
| 1061 | 1061 | ||
| 1062 | mpic->hc_irq = mpic_irq_chip; | 1062 | mpic->hc_irq = mpic_irq_chip; |
| @@ -1152,8 +1152,8 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1152 | } | 1152 | } |
| 1153 | 1153 | ||
| 1154 | /* Map the global registers */ | 1154 | /* Map the global registers */ |
| 1155 | mpic_map(mpic, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); | 1155 | mpic_map(mpic, node, paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); |
| 1156 | mpic_map(mpic, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); | 1156 | mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); |
| 1157 | 1157 | ||
| 1158 | /* Reset */ | 1158 | /* Reset */ |
| 1159 | if (flags & MPIC_WANTS_RESET) { | 1159 | if (flags & MPIC_WANTS_RESET) { |
| @@ -1194,7 +1194,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1194 | 1194 | ||
| 1195 | /* Map the per-CPU registers */ | 1195 | /* Map the per-CPU registers */ |
| 1196 | for (i = 0; i < mpic->num_cpus; i++) { | 1196 | for (i = 0; i < mpic->num_cpus; i++) { |
| 1197 | mpic_map(mpic, paddr, &mpic->cpuregs[i], | 1197 | mpic_map(mpic, node, paddr, &mpic->cpuregs[i], |
| 1198 | MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), | 1198 | MPIC_INFO(CPU_BASE) + i * MPIC_INFO(CPU_STRIDE), |
| 1199 | 0x1000); | 1199 | 0x1000); |
| 1200 | } | 1200 | } |
| @@ -1202,7 +1202,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1202 | /* Initialize main ISU if none provided */ | 1202 | /* Initialize main ISU if none provided */ |
| 1203 | if (mpic->isu_size == 0) { | 1203 | if (mpic->isu_size == 0) { |
| 1204 | mpic->isu_size = mpic->num_sources; | 1204 | mpic->isu_size = mpic->num_sources; |
| 1205 | mpic_map(mpic, paddr, &mpic->isus[0], | 1205 | mpic_map(mpic, node, paddr, &mpic->isus[0], |
| 1206 | MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1206 | MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
| 1207 | } | 1207 | } |
| 1208 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); | 1208 | mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1); |
| @@ -1256,8 +1256,10 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | |||
| 1256 | 1256 | ||
| 1257 | BUG_ON(isu_num >= MPIC_MAX_ISU); | 1257 | BUG_ON(isu_num >= MPIC_MAX_ISU); |
| 1258 | 1258 | ||
| 1259 | mpic_map(mpic, paddr, &mpic->isus[isu_num], 0, | 1259 | mpic_map(mpic, mpic->irqhost->of_node, |
| 1260 | paddr, &mpic->isus[isu_num], 0, | ||
| 1260 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); | 1261 | MPIC_INFO(IRQ_STRIDE) * mpic->isu_size); |
| 1262 | |||
| 1261 | if ((isu_first + mpic->isu_size) > mpic->num_sources) | 1263 | if ((isu_first + mpic->isu_size) > mpic->num_sources) |
| 1262 | mpic->num_sources = isu_first + mpic->isu_size; | 1264 | mpic->num_sources = isu_first + mpic->isu_size; |
| 1263 | } | 1265 | } |
diff --git a/arch/powerpc/sysdev/qe_lib/qe.c b/arch/powerpc/sysdev/qe_lib/qe.c index b28b0e512d67..237e3654f48c 100644 --- a/arch/powerpc/sysdev/qe_lib/qe.c +++ b/arch/powerpc/sysdev/qe_lib/qe.c | |||
| @@ -112,6 +112,7 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input) | |||
| 112 | { | 112 | { |
| 113 | unsigned long flags; | 113 | unsigned long flags; |
| 114 | u8 mcn_shift = 0, dev_shift = 0; | 114 | u8 mcn_shift = 0, dev_shift = 0; |
| 115 | u32 ret; | ||
| 115 | 116 | ||
| 116 | spin_lock_irqsave(&qe_lock, flags); | 117 | spin_lock_irqsave(&qe_lock, flags); |
| 117 | if (cmd == QE_RESET) { | 118 | if (cmd == QE_RESET) { |
| @@ -139,11 +140,13 @@ int qe_issue_cmd(u32 cmd, u32 device, u8 mcn_protocol, u32 cmd_input) | |||
| 139 | } | 140 | } |
| 140 | 141 | ||
| 141 | /* wait for the QE_CR_FLG to clear */ | 142 | /* wait for the QE_CR_FLG to clear */ |
| 142 | while(in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) | 143 | ret = spin_event_timeout((in_be32(&qe_immr->cp.cecr) & QE_CR_FLG) == 0, |
| 143 | cpu_relax(); | 144 | 100, 0); |
| 145 | /* On timeout (e.g. failure), the expression will be false (ret == 0), | ||
| 146 | otherwise it will be true (ret == 1). */ | ||
| 144 | spin_unlock_irqrestore(&qe_lock, flags); | 147 | spin_unlock_irqrestore(&qe_lock, flags); |
| 145 | 148 | ||
| 146 | return 0; | 149 | return ret == 1; |
| 147 | } | 150 | } |
| 148 | EXPORT_SYMBOL(qe_issue_cmd); | 151 | EXPORT_SYMBOL(qe_issue_cmd); |
| 149 | 152 | ||
diff --git a/arch/sparc/boot/Makefile b/arch/sparc/boot/Makefile index 96041a8d39e8..1ff0fd924756 100644 --- a/arch/sparc/boot/Makefile +++ b/arch/sparc/boot/Makefile | |||
| @@ -15,7 +15,7 @@ quiet_cmd_elftoaout = ELFTOAOUT $@ | |||
| 15 | 15 | ||
| 16 | ifeq ($(CONFIG_SPARC32),y) | 16 | ifeq ($(CONFIG_SPARC32),y) |
| 17 | quiet_cmd_piggy = PIGGY $@ | 17 | quiet_cmd_piggy = PIGGY $@ |
| 18 | cmd_piggy = $(obj)/piggyback_32 $@ $(obj)/System.map $(ROOT_IMG) | 18 | cmd_piggy = $(obj)/piggyback_32 $@ System.map $(ROOT_IMG) |
| 19 | quiet_cmd_btfix = BTFIX $@ | 19 | quiet_cmd_btfix = BTFIX $@ |
| 20 | cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ | 20 | cmd_btfix = $(OBJDUMP) -x vmlinux | $(obj)/btfixupprep > $@ |
| 21 | quiet_cmd_sysmap = SYSMAP $(obj)/System.map | 21 | quiet_cmd_sysmap = SYSMAP $(obj)/System.map |
| @@ -58,7 +58,7 @@ $(obj)/image: $(obj)/btfix.o FORCE | |||
| 58 | $(obj)/zImage: $(obj)/image | 58 | $(obj)/zImage: $(obj)/image |
| 59 | $(call if_changed,strip) | 59 | $(call if_changed,strip) |
| 60 | 60 | ||
| 61 | $(obj)/tftpboot.img: $(obj)/piggyback $(obj)/System.map $(obj)/image FORCE | 61 | $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_32 System.map $(ROOT_IMG) FORCE |
| 62 | $(call if_changed,elftoaout) | 62 | $(call if_changed,elftoaout) |
| 63 | $(call if_changed,piggy) | 63 | $(call if_changed,piggy) |
| 64 | 64 | ||
| @@ -79,7 +79,7 @@ $(obj)/image: vmlinux FORCE | |||
| 79 | $(call if_changed,strip) | 79 | $(call if_changed,strip) |
| 80 | @echo ' kernel: $@ is ready' | 80 | @echo ' kernel: $@ is ready' |
| 81 | 81 | ||
| 82 | $(obj)/tftpboot.img: vmlinux $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE | 82 | $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback_64 System.map $(ROOT_IMG) FORCE |
| 83 | $(call if_changed,elftoaout) | 83 | $(call if_changed,elftoaout) |
| 84 | $(call if_changed,piggy) | 84 | $(call if_changed,piggy) |
| 85 | @echo ' kernel: $@ is ready' | 85 | @echo ' kernel: $@ is ready' |
diff --git a/arch/sparc/boot/piggyback_32.c b/arch/sparc/boot/piggyback_32.c index c9f500c1a8b2..e8dc9adfcd61 100644 --- a/arch/sparc/boot/piggyback_32.c +++ b/arch/sparc/boot/piggyback_32.c | |||
| @@ -70,7 +70,7 @@ void die(char *str) | |||
| 70 | int main(int argc,char **argv) | 70 | int main(int argc,char **argv) |
| 71 | { | 71 | { |
| 72 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; | 72 | static char aout_magic[] = { 0x01, 0x03, 0x01, 0x07 }; |
| 73 | unsigned char buffer[1024], *q, *r; | 73 | char buffer[1024], *q, *r; |
| 74 | unsigned int i, j, k, start, end, offset; | 74 | unsigned int i, j, k, start, end, offset; |
| 75 | FILE *map; | 75 | FILE *map; |
| 76 | struct stat s; | 76 | struct stat s; |
| @@ -84,7 +84,7 @@ int main(int argc,char **argv) | |||
| 84 | while (fgets (buffer, 1024, map)) { | 84 | while (fgets (buffer, 1024, map)) { |
| 85 | if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n")) | 85 | if (!strcmp (buffer + 8, " T start\n") || !strcmp (buffer + 16, " T start\n")) |
| 86 | start = strtoul (buffer, NULL, 16); | 86 | start = strtoul (buffer, NULL, 16); |
| 87 | else if (!strcmp (buffer + 8, " A end\n") || !strcmp (buffer + 16, " A end\n")) | 87 | else if (!strcmp (buffer + 8, " A _end\n") || !strcmp (buffer + 16, " A _end\n")) |
| 88 | end = strtoul (buffer, NULL, 16); | 88 | end = strtoul (buffer, NULL, 16); |
| 89 | } | 89 | } |
| 90 | fclose (map); | 90 | fclose (map); |
diff --git a/arch/sparc/boot/piggyback_64.c b/arch/sparc/boot/piggyback_64.c index de364bfed0bb..c63fd1b6bdd4 100644 --- a/arch/sparc/boot/piggyback_64.c +++ b/arch/sparc/boot/piggyback_64.c | |||
| @@ -46,6 +46,7 @@ int main(int argc,char **argv) | |||
| 46 | struct stat s; | 46 | struct stat s; |
| 47 | int image, tail; | 47 | int image, tail; |
| 48 | 48 | ||
| 49 | start = end = 0; | ||
| 49 | if (stat (argv[3], &s) < 0) die (argv[3]); | 50 | if (stat (argv[3], &s) < 0) die (argv[3]); |
| 50 | map = fopen (argv[2], "r"); | 51 | map = fopen (argv[2], "r"); |
| 51 | if (!map) die(argv[2]); | 52 | if (!map) die(argv[2]); |
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index bd075054942b..f0ee79055409 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c | |||
| @@ -20,7 +20,6 @@ | |||
| 20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
| 21 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include <linux/bootmem.h> | ||
| 24 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
| 25 | 24 | ||
| 26 | #include <asm/ptrace.h> | 25 | #include <asm/ptrace.h> |
| @@ -914,25 +913,19 @@ void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu) | |||
| 914 | tb->nonresum_qmask); | 913 | tb->nonresum_qmask); |
| 915 | } | 914 | } |
| 916 | 915 | ||
| 917 | static void __init alloc_one_mondo(unsigned long *pa_ptr, unsigned long qmask) | 916 | /* Each queue region must be a power of 2 multiple of 64 bytes in |
| 918 | { | 917 | * size. The base real address must be aligned to the size of the |
| 919 | unsigned long size = PAGE_ALIGN(qmask + 1); | 918 | * region. Thus, an 8KB queue must be 8KB aligned, for example. |
| 920 | void *p = __alloc_bootmem(size, size, 0); | 919 | */ |
| 921 | if (!p) { | 920 | static void __init alloc_one_queue(unsigned long *pa_ptr, unsigned long qmask) |
| 922 | prom_printf("SUN4V: Error, cannot allocate mondo queue.\n"); | ||
| 923 | prom_halt(); | ||
| 924 | } | ||
| 925 | |||
| 926 | *pa_ptr = __pa(p); | ||
| 927 | } | ||
| 928 | |||
| 929 | static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask) | ||
| 930 | { | 921 | { |
| 931 | unsigned long size = PAGE_ALIGN(qmask + 1); | 922 | unsigned long size = PAGE_ALIGN(qmask + 1); |
| 932 | void *p = __alloc_bootmem(size, size, 0); | 923 | unsigned long order = get_order(size); |
| 924 | unsigned long p; | ||
| 933 | 925 | ||
| 926 | p = __get_free_pages(GFP_KERNEL, order); | ||
| 934 | if (!p) { | 927 | if (!p) { |
| 935 | prom_printf("SUN4V: Error, cannot allocate kbuf page.\n"); | 928 | prom_printf("SUN4V: Error, cannot allocate queue.\n"); |
| 936 | prom_halt(); | 929 | prom_halt(); |
| 937 | } | 930 | } |
| 938 | 931 | ||
| @@ -942,11 +935,11 @@ static void __init alloc_one_kbuf(unsigned long *pa_ptr, unsigned long qmask) | |||
| 942 | static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb) | 935 | static void __init init_cpu_send_mondo_info(struct trap_per_cpu *tb) |
| 943 | { | 936 | { |
| 944 | #ifdef CONFIG_SMP | 937 | #ifdef CONFIG_SMP |
| 945 | void *page; | 938 | unsigned long page; |
| 946 | 939 | ||
| 947 | BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64)); | 940 | BUILD_BUG_ON((NR_CPUS * sizeof(u16)) > (PAGE_SIZE - 64)); |
| 948 | 941 | ||
| 949 | page = alloc_bootmem_pages(PAGE_SIZE); | 942 | page = get_zeroed_page(GFP_KERNEL); |
| 950 | if (!page) { | 943 | if (!page) { |
| 951 | prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n"); | 944 | prom_printf("SUN4V: Error, cannot allocate cpu mondo page.\n"); |
| 952 | prom_halt(); | 945 | prom_halt(); |
| @@ -965,13 +958,13 @@ static void __init sun4v_init_mondo_queues(void) | |||
| 965 | for_each_possible_cpu(cpu) { | 958 | for_each_possible_cpu(cpu) { |
| 966 | struct trap_per_cpu *tb = &trap_block[cpu]; | 959 | struct trap_per_cpu *tb = &trap_block[cpu]; |
| 967 | 960 | ||
| 968 | alloc_one_mondo(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask); | 961 | alloc_one_queue(&tb->cpu_mondo_pa, tb->cpu_mondo_qmask); |
| 969 | alloc_one_mondo(&tb->dev_mondo_pa, tb->dev_mondo_qmask); | 962 | alloc_one_queue(&tb->dev_mondo_pa, tb->dev_mondo_qmask); |
| 970 | alloc_one_mondo(&tb->resum_mondo_pa, tb->resum_qmask); | 963 | alloc_one_queue(&tb->resum_mondo_pa, tb->resum_qmask); |
| 971 | alloc_one_kbuf(&tb->resum_kernel_buf_pa, tb->resum_qmask); | 964 | alloc_one_queue(&tb->resum_kernel_buf_pa, tb->resum_qmask); |
| 972 | alloc_one_mondo(&tb->nonresum_mondo_pa, tb->nonresum_qmask); | 965 | alloc_one_queue(&tb->nonresum_mondo_pa, tb->nonresum_qmask); |
| 973 | alloc_one_kbuf(&tb->nonresum_kernel_buf_pa, | 966 | alloc_one_queue(&tb->nonresum_kernel_buf_pa, |
| 974 | tb->nonresum_qmask); | 967 | tb->nonresum_qmask); |
| 975 | } | 968 | } |
| 976 | } | 969 | } |
| 977 | 970 | ||
| @@ -999,7 +992,7 @@ void __init init_IRQ(void) | |||
| 999 | kill_prom_timer(); | 992 | kill_prom_timer(); |
| 1000 | 993 | ||
| 1001 | size = sizeof(struct ino_bucket) * NUM_IVECS; | 994 | size = sizeof(struct ino_bucket) * NUM_IVECS; |
| 1002 | ivector_table = alloc_bootmem(size); | 995 | ivector_table = kzalloc(size, GFP_KERNEL); |
| 1003 | if (!ivector_table) { | 996 | if (!ivector_table) { |
| 1004 | prom_printf("Fatal error, cannot allocate ivector_table\n"); | 997 | prom_printf("Fatal error, cannot allocate ivector_table\n"); |
| 1005 | prom_halt(); | 998 | prom_halt(); |
diff --git a/arch/um/drivers/slip_kern.c b/arch/um/drivers/slip_kern.c index 5ec17563142e..dd2aadc14af0 100644 --- a/arch/um/drivers/slip_kern.c +++ b/arch/um/drivers/slip_kern.c | |||
| @@ -30,7 +30,6 @@ static void slip_init(struct net_device *dev, void *data) | |||
| 30 | 30 | ||
| 31 | slip_proto_init(&spri->slip); | 31 | slip_proto_init(&spri->slip); |
| 32 | 32 | ||
| 33 | dev->init = NULL; | ||
| 34 | dev->hard_header_len = 0; | 33 | dev->hard_header_len = 0; |
| 35 | dev->header_ops = NULL; | 34 | dev->header_ops = NULL; |
| 36 | dev->addr_len = 0; | 35 | dev->addr_len = 0; |
diff --git a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c index f15a6e7654f3..e376284f0fb7 100644 --- a/arch/um/drivers/slirp_kern.c +++ b/arch/um/drivers/slirp_kern.c | |||
| @@ -32,7 +32,6 @@ void slirp_init(struct net_device *dev, void *data) | |||
| 32 | 32 | ||
| 33 | slip_proto_init(&spri->slip); | 33 | slip_proto_init(&spri->slip); |
| 34 | 34 | ||
| 35 | dev->init = NULL; | ||
| 36 | dev->hard_header_len = 0; | 35 | dev->hard_header_len = 0; |
| 37 | dev->header_ops = NULL; | 36 | dev->header_ops = NULL; |
| 38 | dev->addr_len = 0; | 37 | dev->addr_len = 0; |
diff --git a/arch/um/include/asm/dma-mapping.h b/arch/um/include/asm/dma-mapping.h index 90fc708b320e..378de4bbf49f 100644 --- a/arch/um/include/asm/dma-mapping.h +++ b/arch/um/include/asm/dma-mapping.h | |||
| @@ -79,14 +79,14 @@ dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | static inline void | 81 | static inline void |
| 82 | dma_sync_single(struct device *dev, dma_addr_t dma_handle, size_t size, | 82 | dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, |
| 83 | enum dma_data_direction direction) | 83 | enum dma_data_direction direction) |
| 84 | { | 84 | { |
| 85 | BUG(); | 85 | BUG(); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static inline void | 88 | static inline void |
| 89 | dma_sync_sg(struct device *dev, struct scatterlist *sg, int nelems, | 89 | dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, |
| 90 | enum dma_data_direction direction) | 90 | enum dma_data_direction direction) |
| 91 | { | 91 | { |
| 92 | BUG(); | 92 | BUG(); |
diff --git a/arch/x86/include/asm/boot.h b/arch/x86/include/asm/boot.h index 418e632d4a80..7a1065958ba9 100644 --- a/arch/x86/include/asm/boot.h +++ b/arch/x86/include/asm/boot.h | |||
| @@ -8,7 +8,7 @@ | |||
| 8 | 8 | ||
| 9 | #ifdef __KERNEL__ | 9 | #ifdef __KERNEL__ |
| 10 | 10 | ||
| 11 | #include <asm/page_types.h> | 11 | #include <asm/pgtable_types.h> |
| 12 | 12 | ||
| 13 | /* Physical address where kernel should be loaded. */ | 13 | /* Physical address where kernel should be loaded. */ |
| 14 | #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ | 14 | #define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ |
| @@ -16,10 +16,10 @@ | |||
| 16 | & ~(CONFIG_PHYSICAL_ALIGN - 1)) | 16 | & ~(CONFIG_PHYSICAL_ALIGN - 1)) |
| 17 | 17 | ||
| 18 | /* Minimum kernel alignment, as a power of two */ | 18 | /* Minimum kernel alignment, as a power of two */ |
| 19 | #ifdef CONFIG_x86_64 | 19 | #ifdef CONFIG_X86_64 |
| 20 | #define MIN_KERNEL_ALIGN_LG2 PMD_SHIFT | 20 | #define MIN_KERNEL_ALIGN_LG2 PMD_SHIFT |
| 21 | #else | 21 | #else |
| 22 | #define MIN_KERNEL_ALIGN_LG2 (PAGE_SHIFT+1) | 22 | #define MIN_KERNEL_ALIGN_LG2 (PAGE_SHIFT + THREAD_ORDER) |
| 23 | #endif | 23 | #endif |
| 24 | #define MIN_KERNEL_ALIGN (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2) | 24 | #define MIN_KERNEL_ALIGN (_AC(1, UL) << MIN_KERNEL_ALIGN_LG2) |
| 25 | 25 | ||
diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index 02ecb30982a3..103f1ddb0d85 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | #else /* ...!ASSEMBLY */ | 43 | #else /* ...!ASSEMBLY */ |
| 44 | 44 | ||
| 45 | #include <linux/kernel.h> | ||
| 45 | #include <linux/stringify.h> | 46 | #include <linux/stringify.h> |
| 46 | 47 | ||
| 47 | #ifdef CONFIG_SMP | 48 | #ifdef CONFIG_SMP |
| @@ -155,6 +156,15 @@ do { \ | |||
| 155 | /* We can use this directly for local CPU (faster). */ | 156 | /* We can use this directly for local CPU (faster). */ |
| 156 | DECLARE_PER_CPU(unsigned long, this_cpu_off); | 157 | DECLARE_PER_CPU(unsigned long, this_cpu_off); |
| 157 | 158 | ||
| 159 | #ifdef CONFIG_NEED_MULTIPLE_NODES | ||
| 160 | void *pcpu_lpage_remapped(void *kaddr); | ||
| 161 | #else | ||
| 162 | static inline void *pcpu_lpage_remapped(void *kaddr) | ||
| 163 | { | ||
| 164 | return NULL; | ||
| 165 | } | ||
| 166 | #endif | ||
| 167 | |||
| 158 | #endif /* !__ASSEMBLY__ */ | 168 | #endif /* !__ASSEMBLY__ */ |
| 159 | 169 | ||
| 160 | #ifdef CONFIG_SMP | 170 | #ifdef CONFIG_SMP |
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index e5b27d8f1b47..28e5f5956042 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c | |||
| @@ -258,13 +258,15 @@ static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) | |||
| 258 | { | 258 | { |
| 259 | #ifdef CONFIG_X86_HT | 259 | #ifdef CONFIG_X86_HT |
| 260 | unsigned bits; | 260 | unsigned bits; |
| 261 | int cpu = smp_processor_id(); | ||
| 261 | 262 | ||
| 262 | bits = c->x86_coreid_bits; | 263 | bits = c->x86_coreid_bits; |
| 263 | |||
| 264 | /* Low order bits define the core id (index of core in socket) */ | 264 | /* Low order bits define the core id (index of core in socket) */ |
| 265 | c->cpu_core_id = c->initial_apicid & ((1 << bits)-1); | 265 | c->cpu_core_id = c->initial_apicid & ((1 << bits)-1); |
| 266 | /* Convert the initial APIC ID into the socket ID */ | 266 | /* Convert the initial APIC ID into the socket ID */ |
| 267 | c->phys_proc_id = c->initial_apicid >> bits; | 267 | c->phys_proc_id = c->initial_apicid >> bits; |
| 268 | /* use socket ID also for last level cache */ | ||
| 269 | per_cpu(cpu_llc_id, cpu) = c->phys_proc_id; | ||
| 268 | #endif | 270 | #endif |
| 269 | } | 271 | } |
| 270 | 272 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 284d1de968bc..af425b83202b 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c | |||
| @@ -1117,7 +1117,7 @@ static void mcheck_timer(unsigned long data) | |||
| 1117 | *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ)); | 1117 | *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ)); |
| 1118 | 1118 | ||
| 1119 | t->expires = jiffies + *n; | 1119 | t->expires = jiffies + *n; |
| 1120 | add_timer(t); | 1120 | add_timer_on(t, smp_processor_id()); |
| 1121 | } | 1121 | } |
| 1122 | 1122 | ||
| 1123 | static void mce_do_trigger(struct work_struct *work) | 1123 | static void mce_do_trigger(struct work_struct *work) |
| @@ -1321,7 +1321,7 @@ static void mce_init_timer(void) | |||
| 1321 | return; | 1321 | return; |
| 1322 | setup_timer(t, mcheck_timer, smp_processor_id()); | 1322 | setup_timer(t, mcheck_timer, smp_processor_id()); |
| 1323 | t->expires = round_jiffies(jiffies + *n); | 1323 | t->expires = round_jiffies(jiffies + *n); |
| 1324 | add_timer(t); | 1324 | add_timer_on(t, smp_processor_id()); |
| 1325 | } | 1325 | } |
| 1326 | 1326 | ||
| 1327 | /* | 1327 | /* |
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 95ea5fa7d444..c8405718a4c3 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "dumpstack.h" | 22 | #include "dumpstack.h" |
| 23 | 23 | ||
| 24 | int panic_on_unrecovered_nmi; | 24 | int panic_on_unrecovered_nmi; |
| 25 | int panic_on_io_nmi; | ||
| 25 | unsigned int code_bytes = 64; | 26 | unsigned int code_bytes = 64; |
| 26 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; | 27 | int kstack_depth_to_print = 3 * STACKSLOTS_PER_LINE; |
| 27 | static int die_counter; | 28 | static int die_counter; |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index be5ae80f897f..de2cab132844 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
| @@ -289,6 +289,20 @@ void * __init extend_brk(size_t size, size_t align) | |||
| 289 | return ret; | 289 | return ret; |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | #ifdef CONFIG_X86_64 | ||
| 293 | static void __init init_gbpages(void) | ||
| 294 | { | ||
| 295 | if (direct_gbpages && cpu_has_gbpages) | ||
| 296 | printk(KERN_INFO "Using GB pages for direct mapping\n"); | ||
| 297 | else | ||
| 298 | direct_gbpages = 0; | ||
| 299 | } | ||
| 300 | #else | ||
| 301 | static inline void init_gbpages(void) | ||
| 302 | { | ||
| 303 | } | ||
| 304 | #endif | ||
| 305 | |||
| 292 | static void __init reserve_brk(void) | 306 | static void __init reserve_brk(void) |
| 293 | { | 307 | { |
| 294 | if (_brk_end > _brk_start) | 308 | if (_brk_end > _brk_start) |
| @@ -871,6 +885,8 @@ void __init setup_arch(char **cmdline_p) | |||
| 871 | 885 | ||
| 872 | reserve_brk(); | 886 | reserve_brk(); |
| 873 | 887 | ||
| 888 | init_gbpages(); | ||
| 889 | |||
| 874 | /* max_pfn_mapped is updated here */ | 890 | /* max_pfn_mapped is updated here */ |
| 875 | max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); | 891 | max_low_pfn_mapped = init_memory_mapping(0, max_low_pfn<<PAGE_SHIFT); |
| 876 | max_pfn_mapped = max_low_pfn_mapped; | 892 | max_pfn_mapped = max_low_pfn_mapped; |
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 9c3f0823e6aa..29a3eef7cf4a 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
| @@ -124,7 +124,7 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, | |||
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | /* | 126 | /* |
| 127 | * Remap allocator | 127 | * Large page remap allocator |
| 128 | * | 128 | * |
| 129 | * This allocator uses PMD page as unit. A PMD page is allocated for | 129 | * This allocator uses PMD page as unit. A PMD page is allocated for |
| 130 | * each cpu and each is remapped into vmalloc area using PMD mapping. | 130 | * each cpu and each is remapped into vmalloc area using PMD mapping. |
| @@ -137,105 +137,185 @@ static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size, | |||
| 137 | * better than only using 4k mappings while still being NUMA friendly. | 137 | * better than only using 4k mappings while still being NUMA friendly. |
| 138 | */ | 138 | */ |
| 139 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 139 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
| 140 | static size_t pcpur_size __initdata; | 140 | struct pcpul_ent { |
| 141 | static void **pcpur_ptrs __initdata; | 141 | unsigned int cpu; |
| 142 | void *ptr; | ||
| 143 | }; | ||
| 144 | |||
| 145 | static size_t pcpul_size; | ||
| 146 | static struct pcpul_ent *pcpul_map; | ||
| 147 | static struct vm_struct pcpul_vm; | ||
| 142 | 148 | ||
| 143 | static struct page * __init pcpur_get_page(unsigned int cpu, int pageno) | 149 | static struct page * __init pcpul_get_page(unsigned int cpu, int pageno) |
| 144 | { | 150 | { |
| 145 | size_t off = (size_t)pageno << PAGE_SHIFT; | 151 | size_t off = (size_t)pageno << PAGE_SHIFT; |
| 146 | 152 | ||
| 147 | if (off >= pcpur_size) | 153 | if (off >= pcpul_size) |
| 148 | return NULL; | 154 | return NULL; |
| 149 | 155 | ||
| 150 | return virt_to_page(pcpur_ptrs[cpu] + off); | 156 | return virt_to_page(pcpul_map[cpu].ptr + off); |
| 151 | } | 157 | } |
| 152 | 158 | ||
| 153 | static ssize_t __init setup_pcpu_remap(size_t static_size) | 159 | static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen) |
| 154 | { | 160 | { |
| 155 | static struct vm_struct vm; | 161 | size_t map_size, dyn_size; |
| 156 | size_t ptrs_size, dyn_size; | ||
| 157 | unsigned int cpu; | 162 | unsigned int cpu; |
| 163 | int i, j; | ||
| 158 | ssize_t ret; | 164 | ssize_t ret; |
| 159 | 165 | ||
| 160 | /* | 166 | if (!chosen) { |
| 161 | * If large page isn't supported, there's no benefit in doing | 167 | size_t vm_size = VMALLOC_END - VMALLOC_START; |
| 162 | * this. Also, on non-NUMA, embedding is better. | 168 | size_t tot_size = num_possible_cpus() * PMD_SIZE; |
| 163 | * | 169 | |
| 164 | * NOTE: disabled for now. | 170 | /* on non-NUMA, embedding is better */ |
| 165 | */ | 171 | if (!pcpu_need_numa()) |
| 166 | if (true || !cpu_has_pse || !pcpu_need_numa()) | 172 | return -EINVAL; |
| 173 | |||
| 174 | /* don't consume more than 20% of vmalloc area */ | ||
| 175 | if (tot_size > vm_size / 5) { | ||
| 176 | pr_info("PERCPU: too large chunk size %zuMB for " | ||
| 177 | "large page remap\n", tot_size >> 20); | ||
| 178 | return -EINVAL; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | |||
| 182 | /* need PSE */ | ||
| 183 | if (!cpu_has_pse) { | ||
| 184 | pr_warning("PERCPU: lpage allocator requires PSE\n"); | ||
| 167 | return -EINVAL; | 185 | return -EINVAL; |
| 186 | } | ||
| 168 | 187 | ||
| 169 | /* | 188 | /* |
| 170 | * Currently supports only single page. Supporting multiple | 189 | * Currently supports only single page. Supporting multiple |
| 171 | * pages won't be too difficult if it ever becomes necessary. | 190 | * pages won't be too difficult if it ever becomes necessary. |
| 172 | */ | 191 | */ |
| 173 | pcpur_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + | 192 | pcpul_size = PFN_ALIGN(static_size + PERCPU_MODULE_RESERVE + |
| 174 | PERCPU_DYNAMIC_RESERVE); | 193 | PERCPU_DYNAMIC_RESERVE); |
| 175 | if (pcpur_size > PMD_SIZE) { | 194 | if (pcpul_size > PMD_SIZE) { |
| 176 | pr_warning("PERCPU: static data is larger than large page, " | 195 | pr_warning("PERCPU: static data is larger than large page, " |
| 177 | "can't use large page\n"); | 196 | "can't use large page\n"); |
| 178 | return -EINVAL; | 197 | return -EINVAL; |
| 179 | } | 198 | } |
| 180 | dyn_size = pcpur_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; | 199 | dyn_size = pcpul_size - static_size - PERCPU_FIRST_CHUNK_RESERVE; |
| 181 | 200 | ||
| 182 | /* allocate pointer array and alloc large pages */ | 201 | /* allocate pointer array and alloc large pages */ |
| 183 | ptrs_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpur_ptrs[0])); | 202 | map_size = PFN_ALIGN(num_possible_cpus() * sizeof(pcpul_map[0])); |
| 184 | pcpur_ptrs = alloc_bootmem(ptrs_size); | 203 | pcpul_map = alloc_bootmem(map_size); |
| 185 | 204 | ||
| 186 | for_each_possible_cpu(cpu) { | 205 | for_each_possible_cpu(cpu) { |
| 187 | pcpur_ptrs[cpu] = pcpu_alloc_bootmem(cpu, PMD_SIZE, PMD_SIZE); | 206 | pcpul_map[cpu].cpu = cpu; |
| 188 | if (!pcpur_ptrs[cpu]) | 207 | pcpul_map[cpu].ptr = pcpu_alloc_bootmem(cpu, PMD_SIZE, |
| 208 | PMD_SIZE); | ||
| 209 | if (!pcpul_map[cpu].ptr) { | ||
| 210 | pr_warning("PERCPU: failed to allocate large page " | ||
| 211 | "for cpu%u\n", cpu); | ||
| 189 | goto enomem; | 212 | goto enomem; |
| 213 | } | ||
| 190 | 214 | ||
| 191 | /* | 215 | /* |
| 192 | * Only use pcpur_size bytes and give back the rest. | 216 | * Only use pcpul_size bytes and give back the rest. |
| 193 | * | 217 | * |
| 194 | * Ingo: The 2MB up-rounding bootmem is needed to make | 218 | * Ingo: The 2MB up-rounding bootmem is needed to make |
| 195 | * sure the partial 2MB page is still fully RAM - it's | 219 | * sure the partial 2MB page is still fully RAM - it's |
| 196 | * not well-specified to have a PAT-incompatible area | 220 | * not well-specified to have a PAT-incompatible area |
| 197 | * (unmapped RAM, device memory, etc.) in that hole. | 221 | * (unmapped RAM, device memory, etc.) in that hole. |
| 198 | */ | 222 | */ |
| 199 | free_bootmem(__pa(pcpur_ptrs[cpu] + pcpur_size), | 223 | free_bootmem(__pa(pcpul_map[cpu].ptr + pcpul_size), |
| 200 | PMD_SIZE - pcpur_size); | 224 | PMD_SIZE - pcpul_size); |
| 201 | 225 | ||
| 202 | memcpy(pcpur_ptrs[cpu], __per_cpu_load, static_size); | 226 | memcpy(pcpul_map[cpu].ptr, __per_cpu_load, static_size); |
| 203 | } | 227 | } |
| 204 | 228 | ||
| 205 | /* allocate address and map */ | 229 | /* allocate address and map */ |
| 206 | vm.flags = VM_ALLOC; | 230 | pcpul_vm.flags = VM_ALLOC; |
| 207 | vm.size = num_possible_cpus() * PMD_SIZE; | 231 | pcpul_vm.size = num_possible_cpus() * PMD_SIZE; |
| 208 | vm_area_register_early(&vm, PMD_SIZE); | 232 | vm_area_register_early(&pcpul_vm, PMD_SIZE); |
| 209 | 233 | ||
| 210 | for_each_possible_cpu(cpu) { | 234 | for_each_possible_cpu(cpu) { |
| 211 | pmd_t *pmd; | 235 | pmd_t *pmd, pmd_v; |
| 212 | 236 | ||
| 213 | pmd = populate_extra_pmd((unsigned long)vm.addr | 237 | pmd = populate_extra_pmd((unsigned long)pcpul_vm.addr + |
| 214 | + cpu * PMD_SIZE); | 238 | cpu * PMD_SIZE); |
| 215 | set_pmd(pmd, pfn_pmd(page_to_pfn(virt_to_page(pcpur_ptrs[cpu])), | 239 | pmd_v = pfn_pmd(page_to_pfn(virt_to_page(pcpul_map[cpu].ptr)), |
| 216 | PAGE_KERNEL_LARGE)); | 240 | PAGE_KERNEL_LARGE); |
| 241 | set_pmd(pmd, pmd_v); | ||
| 217 | } | 242 | } |
| 218 | 243 | ||
| 219 | /* we're ready, commit */ | 244 | /* we're ready, commit */ |
| 220 | pr_info("PERCPU: Remapped at %p with large pages, static data " | 245 | pr_info("PERCPU: Remapped at %p with large pages, static data " |
| 221 | "%zu bytes\n", vm.addr, static_size); | 246 | "%zu bytes\n", pcpul_vm.addr, static_size); |
| 222 | 247 | ||
| 223 | ret = pcpu_setup_first_chunk(pcpur_get_page, static_size, | 248 | ret = pcpu_setup_first_chunk(pcpul_get_page, static_size, |
| 224 | PERCPU_FIRST_CHUNK_RESERVE, dyn_size, | 249 | PERCPU_FIRST_CHUNK_RESERVE, dyn_size, |
| 225 | PMD_SIZE, vm.addr, NULL); | 250 | PMD_SIZE, pcpul_vm.addr, NULL); |
| 226 | goto out_free_ar; | 251 | |
| 252 | /* sort pcpul_map array for pcpu_lpage_remapped() */ | ||
| 253 | for (i = 0; i < num_possible_cpus() - 1; i++) | ||
| 254 | for (j = i + 1; j < num_possible_cpus(); j++) | ||
| 255 | if (pcpul_map[i].ptr > pcpul_map[j].ptr) { | ||
| 256 | struct pcpul_ent tmp = pcpul_map[i]; | ||
| 257 | pcpul_map[i] = pcpul_map[j]; | ||
| 258 | pcpul_map[j] = tmp; | ||
| 259 | } | ||
| 260 | |||
| 261 | return ret; | ||
| 227 | 262 | ||
| 228 | enomem: | 263 | enomem: |
| 229 | for_each_possible_cpu(cpu) | 264 | for_each_possible_cpu(cpu) |
| 230 | if (pcpur_ptrs[cpu]) | 265 | if (pcpul_map[cpu].ptr) |
| 231 | free_bootmem(__pa(pcpur_ptrs[cpu]), PMD_SIZE); | 266 | free_bootmem(__pa(pcpul_map[cpu].ptr), pcpul_size); |
| 232 | ret = -ENOMEM; | 267 | free_bootmem(__pa(pcpul_map), map_size); |
| 233 | out_free_ar: | 268 | return -ENOMEM; |
| 234 | free_bootmem(__pa(pcpur_ptrs), ptrs_size); | 269 | } |
| 235 | return ret; | 270 | |
| 271 | /** | ||
| 272 | * pcpu_lpage_remapped - determine whether a kaddr is in pcpul recycled area | ||
| 273 | * @kaddr: the kernel address in question | ||
| 274 | * | ||
| 275 | * Determine whether @kaddr falls in the pcpul recycled area. This is | ||
| 276 | * used by pageattr to detect VM aliases and break up the pcpu PMD | ||
| 277 | * mapping such that the same physical page is not mapped under | ||
| 278 | * different attributes. | ||
| 279 | * | ||
| 280 | * The recycled area is always at the tail of a partially used PMD | ||
| 281 | * page. | ||
| 282 | * | ||
| 283 | * RETURNS: | ||
| 284 | * Address of corresponding remapped pcpu address if match is found; | ||
| 285 | * otherwise, NULL. | ||
| 286 | */ | ||
| 287 | void *pcpu_lpage_remapped(void *kaddr) | ||
| 288 | { | ||
| 289 | void *pmd_addr = (void *)((unsigned long)kaddr & PMD_MASK); | ||
| 290 | unsigned long offset = (unsigned long)kaddr & ~PMD_MASK; | ||
| 291 | int left = 0, right = num_possible_cpus() - 1; | ||
| 292 | int pos; | ||
| 293 | |||
| 294 | /* pcpul in use at all? */ | ||
| 295 | if (!pcpul_map) | ||
| 296 | return NULL; | ||
| 297 | |||
| 298 | /* okay, perform binary search */ | ||
| 299 | while (left <= right) { | ||
| 300 | pos = (left + right) / 2; | ||
| 301 | |||
| 302 | if (pcpul_map[pos].ptr < pmd_addr) | ||
| 303 | left = pos + 1; | ||
| 304 | else if (pcpul_map[pos].ptr > pmd_addr) | ||
| 305 | right = pos - 1; | ||
| 306 | else { | ||
| 307 | /* it shouldn't be in the area for the first chunk */ | ||
| 308 | WARN_ON(offset < pcpul_size); | ||
| 309 | |||
| 310 | return pcpul_vm.addr + | ||
| 311 | pcpul_map[pos].cpu * PMD_SIZE + offset; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | return NULL; | ||
| 236 | } | 316 | } |
| 237 | #else | 317 | #else |
| 238 | static ssize_t __init setup_pcpu_remap(size_t static_size) | 318 | static ssize_t __init setup_pcpu_lpage(size_t static_size, bool chosen) |
| 239 | { | 319 | { |
| 240 | return -EINVAL; | 320 | return -EINVAL; |
| 241 | } | 321 | } |
| @@ -249,7 +329,7 @@ static ssize_t __init setup_pcpu_remap(size_t static_size) | |||
| 249 | * mapping so that it can use PMD mapping without additional TLB | 329 | * mapping so that it can use PMD mapping without additional TLB |
| 250 | * pressure. | 330 | * pressure. |
| 251 | */ | 331 | */ |
| 252 | static ssize_t __init setup_pcpu_embed(size_t static_size) | 332 | static ssize_t __init setup_pcpu_embed(size_t static_size, bool chosen) |
| 253 | { | 333 | { |
| 254 | size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; | 334 | size_t reserve = PERCPU_MODULE_RESERVE + PERCPU_DYNAMIC_RESERVE; |
| 255 | 335 | ||
| @@ -258,7 +338,7 @@ static ssize_t __init setup_pcpu_embed(size_t static_size) | |||
| 258 | * this. Also, embedding allocation doesn't play well with | 338 | * this. Also, embedding allocation doesn't play well with |
| 259 | * NUMA. | 339 | * NUMA. |
| 260 | */ | 340 | */ |
| 261 | if (!cpu_has_pse || pcpu_need_numa()) | 341 | if (!chosen && (!cpu_has_pse || pcpu_need_numa())) |
| 262 | return -EINVAL; | 342 | return -EINVAL; |
| 263 | 343 | ||
| 264 | return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE, | 344 | return pcpu_embed_first_chunk(static_size, PERCPU_FIRST_CHUNK_RESERVE, |
| @@ -308,8 +388,11 @@ static ssize_t __init setup_pcpu_4k(size_t static_size) | |||
| 308 | void *ptr; | 388 | void *ptr; |
| 309 | 389 | ||
| 310 | ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE); | 390 | ptr = pcpu_alloc_bootmem(cpu, PAGE_SIZE, PAGE_SIZE); |
| 311 | if (!ptr) | 391 | if (!ptr) { |
| 392 | pr_warning("PERCPU: failed to allocate " | ||
| 393 | "4k page for cpu%u\n", cpu); | ||
| 312 | goto enomem; | 394 | goto enomem; |
| 395 | } | ||
| 313 | 396 | ||
| 314 | memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE); | 397 | memcpy(ptr, __per_cpu_load + i * PAGE_SIZE, PAGE_SIZE); |
| 315 | pcpu4k_pages[j++] = virt_to_page(ptr); | 398 | pcpu4k_pages[j++] = virt_to_page(ptr); |
| @@ -333,6 +416,16 @@ out_free_ar: | |||
| 333 | return ret; | 416 | return ret; |
| 334 | } | 417 | } |
| 335 | 418 | ||
| 419 | /* for explicit first chunk allocator selection */ | ||
| 420 | static char pcpu_chosen_alloc[16] __initdata; | ||
| 421 | |||
| 422 | static int __init percpu_alloc_setup(char *str) | ||
| 423 | { | ||
| 424 | strncpy(pcpu_chosen_alloc, str, sizeof(pcpu_chosen_alloc) - 1); | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | early_param("percpu_alloc", percpu_alloc_setup); | ||
| 428 | |||
| 336 | static inline void setup_percpu_segment(int cpu) | 429 | static inline void setup_percpu_segment(int cpu) |
| 337 | { | 430 | { |
| 338 | #ifdef CONFIG_X86_32 | 431 | #ifdef CONFIG_X86_32 |
| @@ -346,11 +439,6 @@ static inline void setup_percpu_segment(int cpu) | |||
| 346 | #endif | 439 | #endif |
| 347 | } | 440 | } |
| 348 | 441 | ||
| 349 | /* | ||
| 350 | * Great future plan: | ||
| 351 | * Declare PDA itself and support (irqstack,tss,pgd) as per cpu data. | ||
| 352 | * Always point %gs to its beginning | ||
| 353 | */ | ||
| 354 | void __init setup_per_cpu_areas(void) | 442 | void __init setup_per_cpu_areas(void) |
| 355 | { | 443 | { |
| 356 | size_t static_size = __per_cpu_end - __per_cpu_start; | 444 | size_t static_size = __per_cpu_end - __per_cpu_start; |
| @@ -367,9 +455,26 @@ void __init setup_per_cpu_areas(void) | |||
| 367 | * of large page mappings. Please read comments on top of | 455 | * of large page mappings. Please read comments on top of |
| 368 | * each allocator for details. | 456 | * each allocator for details. |
| 369 | */ | 457 | */ |
| 370 | ret = setup_pcpu_remap(static_size); | 458 | ret = -EINVAL; |
| 371 | if (ret < 0) | 459 | if (strlen(pcpu_chosen_alloc)) { |
| 372 | ret = setup_pcpu_embed(static_size); | 460 | if (strcmp(pcpu_chosen_alloc, "4k")) { |
| 461 | if (!strcmp(pcpu_chosen_alloc, "lpage")) | ||
| 462 | ret = setup_pcpu_lpage(static_size, true); | ||
| 463 | else if (!strcmp(pcpu_chosen_alloc, "embed")) | ||
| 464 | ret = setup_pcpu_embed(static_size, true); | ||
| 465 | else | ||
| 466 | pr_warning("PERCPU: unknown allocator %s " | ||
| 467 | "specified\n", pcpu_chosen_alloc); | ||
| 468 | if (ret < 0) | ||
| 469 | pr_warning("PERCPU: %s allocator failed (%zd), " | ||
| 470 | "falling back to 4k\n", | ||
| 471 | pcpu_chosen_alloc, ret); | ||
| 472 | } | ||
| 473 | } else { | ||
| 474 | ret = setup_pcpu_lpage(static_size, false); | ||
| 475 | if (ret < 0) | ||
| 476 | ret = setup_pcpu_embed(static_size, false); | ||
| 477 | } | ||
| 373 | if (ret < 0) | 478 | if (ret < 0) |
| 374 | ret = setup_pcpu_4k(static_size); | 479 | ret = setup_pcpu_4k(static_size); |
| 375 | if (ret < 0) | 480 | if (ret < 0) |
diff --git a/arch/x86/kernel/tlb_uv.c b/arch/x86/kernel/tlb_uv.c index 124d40c575df..8ccabb8a2f6a 100644 --- a/arch/x86/kernel/tlb_uv.c +++ b/arch/x86/kernel/tlb_uv.c | |||
| @@ -711,7 +711,6 @@ uv_activation_descriptor_init(int node, int pnode) | |||
| 711 | unsigned long pa; | 711 | unsigned long pa; |
| 712 | unsigned long m; | 712 | unsigned long m; |
| 713 | unsigned long n; | 713 | unsigned long n; |
| 714 | unsigned long mmr_image; | ||
| 715 | struct bau_desc *adp; | 714 | struct bau_desc *adp; |
| 716 | struct bau_desc *ad2; | 715 | struct bau_desc *ad2; |
| 717 | 716 | ||
| @@ -727,12 +726,8 @@ uv_activation_descriptor_init(int node, int pnode) | |||
| 727 | n = pa >> uv_nshift; | 726 | n = pa >> uv_nshift; |
| 728 | m = pa & uv_mmask; | 727 | m = pa & uv_mmask; |
| 729 | 728 | ||
| 730 | mmr_image = uv_read_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE); | 729 | uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE, |
| 731 | if (mmr_image) { | 730 | (n << UV_DESC_BASE_PNODE_SHIFT | m)); |
| 732 | uv_write_global_mmr64(pnode, (unsigned long) | ||
| 733 | UVH_LB_BAU_SB_DESCRIPTOR_BASE, | ||
| 734 | (n << UV_DESC_BASE_PNODE_SHIFT | m)); | ||
| 735 | } | ||
| 736 | 731 | ||
| 737 | /* | 732 | /* |
| 738 | * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each | 733 | * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a0f48f5671c0..5204332f475d 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -346,6 +346,9 @@ io_check_error(unsigned char reason, struct pt_regs *regs) | |||
| 346 | printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n"); | 346 | printk(KERN_EMERG "NMI: IOCK error (debug interrupt?)\n"); |
| 347 | show_registers(regs); | 347 | show_registers(regs); |
| 348 | 348 | ||
| 349 | if (panic_on_io_nmi) | ||
| 350 | panic("NMI IOCK error: Not continuing"); | ||
| 351 | |||
| 349 | /* Re-enable the IOCK line, wait for a few seconds */ | 352 | /* Re-enable the IOCK line, wait for a few seconds */ |
| 350 | reason = (reason & 0xf) | 8; | 353 | reason = (reason & 0xf) | 8; |
| 351 | outb(reason, 0x61); | 354 | outb(reason, 0x61); |
diff --git a/arch/x86/lib/delay.c b/arch/x86/lib/delay.c index f4568605d7d5..ff485d361182 100644 --- a/arch/x86/lib/delay.c +++ b/arch/x86/lib/delay.c | |||
| @@ -55,8 +55,10 @@ static void delay_tsc(unsigned long loops) | |||
| 55 | 55 | ||
| 56 | preempt_disable(); | 56 | preempt_disable(); |
| 57 | cpu = smp_processor_id(); | 57 | cpu = smp_processor_id(); |
| 58 | rdtsc_barrier(); | ||
| 58 | rdtscl(bclock); | 59 | rdtscl(bclock); |
| 59 | for (;;) { | 60 | for (;;) { |
| 61 | rdtsc_barrier(); | ||
| 60 | rdtscl(now); | 62 | rdtscl(now); |
| 61 | if ((now - bclock) >= loops) | 63 | if ((now - bclock) >= loops) |
| 62 | break; | 64 | break; |
| @@ -78,6 +80,7 @@ static void delay_tsc(unsigned long loops) | |||
| 78 | if (unlikely(cpu != smp_processor_id())) { | 80 | if (unlikely(cpu != smp_processor_id())) { |
| 79 | loops -= (now - bclock); | 81 | loops -= (now - bclock); |
| 80 | cpu = smp_processor_id(); | 82 | cpu = smp_processor_id(); |
| 83 | rdtsc_barrier(); | ||
| 81 | rdtscl(bclock); | 84 | rdtscl(bclock); |
| 82 | } | 85 | } |
| 83 | } | 86 | } |
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index f53b57e4086f..47ce9a2ce5e7 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c | |||
| @@ -177,20 +177,6 @@ static int __meminit save_mr(struct map_range *mr, int nr_range, | |||
| 177 | return nr_range; | 177 | return nr_range; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | #ifdef CONFIG_X86_64 | ||
| 181 | static void __init init_gbpages(void) | ||
| 182 | { | ||
| 183 | if (direct_gbpages && cpu_has_gbpages) | ||
| 184 | printk(KERN_INFO "Using GB pages for direct mapping\n"); | ||
| 185 | else | ||
| 186 | direct_gbpages = 0; | ||
| 187 | } | ||
| 188 | #else | ||
| 189 | static inline void init_gbpages(void) | ||
| 190 | { | ||
| 191 | } | ||
| 192 | #endif | ||
| 193 | |||
| 194 | /* | 180 | /* |
| 195 | * Setup the direct mapping of the physical memory at PAGE_OFFSET. | 181 | * Setup the direct mapping of the physical memory at PAGE_OFFSET. |
| 196 | * This runs before bootmem is initialized and gets pages directly from | 182 | * This runs before bootmem is initialized and gets pages directly from |
| @@ -210,9 +196,6 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, | |||
| 210 | 196 | ||
| 211 | printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end); | 197 | printk(KERN_INFO "init_memory_mapping: %016lx-%016lx\n", start, end); |
| 212 | 198 | ||
| 213 | if (!after_bootmem) | ||
| 214 | init_gbpages(); | ||
| 215 | |||
| 216 | #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK) | 199 | #if defined(CONFIG_DEBUG_PAGEALLOC) || defined(CONFIG_KMEMCHECK) |
| 217 | /* | 200 | /* |
| 218 | * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages. | 201 | * For CONFIG_DEBUG_PAGEALLOC, identity mapping will use small pages. |
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index 3cfe9ced8a4c..1b734d7a8966 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 12 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
| 13 | #include <linux/debugfs.h> | 13 | #include <linux/debugfs.h> |
| 14 | #include <linux/pfn.h> | ||
| 14 | 15 | ||
| 15 | #include <asm/e820.h> | 16 | #include <asm/e820.h> |
| 16 | #include <asm/processor.h> | 17 | #include <asm/processor.h> |
| @@ -681,8 +682,9 @@ static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias); | |||
| 681 | static int cpa_process_alias(struct cpa_data *cpa) | 682 | static int cpa_process_alias(struct cpa_data *cpa) |
| 682 | { | 683 | { |
| 683 | struct cpa_data alias_cpa; | 684 | struct cpa_data alias_cpa; |
| 684 | int ret = 0; | 685 | unsigned long laddr = (unsigned long)__va(cpa->pfn << PAGE_SHIFT); |
| 685 | unsigned long temp_cpa_vaddr, vaddr; | 686 | unsigned long vaddr, remapped; |
| 687 | int ret; | ||
| 686 | 688 | ||
| 687 | if (cpa->pfn >= max_pfn_mapped) | 689 | if (cpa->pfn >= max_pfn_mapped) |
| 688 | return 0; | 690 | return 0; |
| @@ -706,42 +708,55 @@ static int cpa_process_alias(struct cpa_data *cpa) | |||
| 706 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) { | 708 | PAGE_OFFSET + (max_pfn_mapped << PAGE_SHIFT)))) { |
| 707 | 709 | ||
| 708 | alias_cpa = *cpa; | 710 | alias_cpa = *cpa; |
| 709 | temp_cpa_vaddr = (unsigned long) __va(cpa->pfn << PAGE_SHIFT); | 711 | alias_cpa.vaddr = &laddr; |
| 710 | alias_cpa.vaddr = &temp_cpa_vaddr; | ||
| 711 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | 712 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); |
| 712 | 713 | ||
| 713 | |||
| 714 | ret = __change_page_attr_set_clr(&alias_cpa, 0); | 714 | ret = __change_page_attr_set_clr(&alias_cpa, 0); |
| 715 | if (ret) | ||
| 716 | return ret; | ||
| 715 | } | 717 | } |
| 716 | 718 | ||
| 717 | #ifdef CONFIG_X86_64 | 719 | #ifdef CONFIG_X86_64 |
| 718 | if (ret) | ||
| 719 | return ret; | ||
| 720 | /* | 720 | /* |
| 721 | * No need to redo, when the primary call touched the high | 721 | * If the primary call didn't touch the high mapping already |
| 722 | * mapping already: | 722 | * and the physical address is inside the kernel map, we need |
| 723 | */ | ||
| 724 | if (within(vaddr, (unsigned long) _text, _brk_end)) | ||
| 725 | return 0; | ||
| 726 | |||
| 727 | /* | ||
| 728 | * If the physical address is inside the kernel map, we need | ||
| 729 | * to touch the high mapped kernel as well: | 723 | * to touch the high mapped kernel as well: |
| 730 | */ | 724 | */ |
| 731 | if (!within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) | 725 | if (!within(vaddr, (unsigned long)_text, _brk_end) && |
| 732 | return 0; | 726 | within(cpa->pfn, highmap_start_pfn(), highmap_end_pfn())) { |
| 727 | unsigned long temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + | ||
| 728 | __START_KERNEL_map - phys_base; | ||
| 729 | alias_cpa = *cpa; | ||
| 730 | alias_cpa.vaddr = &temp_cpa_vaddr; | ||
| 731 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | ||
| 733 | 732 | ||
| 734 | alias_cpa = *cpa; | 733 | /* |
| 735 | temp_cpa_vaddr = (cpa->pfn << PAGE_SHIFT) + __START_KERNEL_map - phys_base; | 734 | * The high mapping range is imprecise, so ignore the |
| 736 | alias_cpa.vaddr = &temp_cpa_vaddr; | 735 | * return value. |
| 737 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | 736 | */ |
| 737 | __change_page_attr_set_clr(&alias_cpa, 0); | ||
| 738 | } | ||
| 739 | #endif | ||
| 738 | 740 | ||
| 739 | /* | 741 | /* |
| 740 | * The high mapping range is imprecise, so ignore the return value. | 742 | * If the PMD page was partially used for per-cpu remapping, |
| 743 | * the recycled area needs to be split and modified. Because | ||
| 744 | * the area is always proper subset of a PMD page | ||
| 745 | * cpa->numpages is guaranteed to be 1 for these areas, so | ||
| 746 | * there's no need to loop over and check for further remaps. | ||
| 741 | */ | 747 | */ |
| 742 | __change_page_attr_set_clr(&alias_cpa, 0); | 748 | remapped = (unsigned long)pcpu_lpage_remapped((void *)laddr); |
| 743 | #endif | 749 | if (remapped) { |
| 744 | return ret; | 750 | WARN_ON(cpa->numpages > 1); |
| 751 | alias_cpa = *cpa; | ||
| 752 | alias_cpa.vaddr = &remapped; | ||
| 753 | alias_cpa.flags &= ~(CPA_PAGES_ARRAY | CPA_ARRAY); | ||
| 754 | ret = __change_page_attr_set_clr(&alias_cpa, 0); | ||
| 755 | if (ret) | ||
| 756 | return ret; | ||
| 757 | } | ||
| 758 | |||
| 759 | return 0; | ||
| 745 | } | 760 | } |
| 746 | 761 | ||
| 747 | static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) | 762 | static int __change_page_attr_set_clr(struct cpa_data *cpa, int checkalias) |
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index d277ef1eea51..b3d20b9cac63 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c | |||
| @@ -244,7 +244,7 @@ static void __restore_processor_state(struct saved_context *ctxt) | |||
| 244 | do_fpu_end(); | 244 | do_fpu_end(); |
| 245 | mtrr_ap_init(); | 245 | mtrr_ap_init(); |
| 246 | 246 | ||
| 247 | #ifdef CONFIG_X86_32 | 247 | #ifdef CONFIG_X86_OLD_MCE |
| 248 | mcheck_init(&boot_cpu_data); | 248 | mcheck_init(&boot_cpu_data); |
| 249 | #endif | 249 | #endif |
| 250 | } | 250 | } |
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 8a5bf3b356fa..55b5b90c2a44 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -395,7 +395,7 @@ struct pci_dev *acpi_get_pci_dev(acpi_handle handle) | |||
| 395 | fn = adr & 0xffff; | 395 | fn = adr & 0xffff; |
| 396 | 396 | ||
| 397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); | 397 | pdev = pci_get_slot(pbus, PCI_DEVFN(dev, fn)); |
| 398 | if (hnd == handle) | 398 | if (!pdev || hnd == handle) |
| 399 | break; | 399 | break; |
| 400 | 400 | ||
| 401 | pbus = pdev->subordinate; | 401 | pbus = pdev->subordinate; |
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 140ea10ecb88..c02db01f736e 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <linux/cdev.h> | 27 | #include <linux/cdev.h> |
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
| 30 | #include <asm/pgtable.h> | ||
| 30 | #include <asm/io.h> | 31 | #include <asm/io.h> |
| 31 | 32 | ||
| 32 | /* | 33 | /* |
| @@ -75,12 +76,13 @@ static struct class *bsr_class; | |||
| 75 | static int bsr_major; | 76 | static int bsr_major; |
| 76 | 77 | ||
| 77 | enum { | 78 | enum { |
| 78 | BSR_8 = 0, | 79 | BSR_8 = 0, |
| 79 | BSR_16 = 1, | 80 | BSR_16 = 1, |
| 80 | BSR_64 = 2, | 81 | BSR_64 = 2, |
| 81 | BSR_128 = 3, | 82 | BSR_128 = 3, |
| 82 | BSR_UNKNOWN = 4, | 83 | BSR_4096 = 4, |
| 83 | BSR_MAX = 5, | 84 | BSR_UNKNOWN = 5, |
| 85 | BSR_MAX = 6, | ||
| 84 | }; | 86 | }; |
| 85 | 87 | ||
| 86 | static unsigned bsr_types[BSR_MAX]; | 88 | static unsigned bsr_types[BSR_MAX]; |
| @@ -117,15 +119,22 @@ static int bsr_mmap(struct file *filp, struct vm_area_struct *vma) | |||
| 117 | { | 119 | { |
| 118 | unsigned long size = vma->vm_end - vma->vm_start; | 120 | unsigned long size = vma->vm_end - vma->vm_start; |
| 119 | struct bsr_dev *dev = filp->private_data; | 121 | struct bsr_dev *dev = filp->private_data; |
| 122 | int ret; | ||
| 120 | 123 | ||
| 121 | if (size > dev->bsr_len || (size & (PAGE_SIZE-1))) | ||
| 122 | return -EINVAL; | ||
| 123 | |||
| 124 | vma->vm_flags |= (VM_IO | VM_DONTEXPAND); | ||
| 125 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 124 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 126 | 125 | ||
| 127 | if (io_remap_pfn_range(vma, vma->vm_start, dev->bsr_addr >> PAGE_SHIFT, | 126 | /* check for the case of a small BSR device and map one 4k page for it*/ |
| 128 | size, vma->vm_page_prot)) | 127 | if (dev->bsr_len < PAGE_SIZE && size == PAGE_SIZE) |
| 128 | ret = remap_4k_pfn(vma, vma->vm_start, dev->bsr_addr >> 12, | ||
| 129 | vma->vm_page_prot); | ||
| 130 | else if (size <= dev->bsr_len) | ||
| 131 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
| 132 | dev->bsr_addr >> PAGE_SHIFT, | ||
| 133 | size, vma->vm_page_prot); | ||
| 134 | else | ||
| 135 | return -EINVAL; | ||
| 136 | |||
| 137 | if (ret) | ||
| 129 | return -EAGAIN; | 138 | return -EAGAIN; |
| 130 | 139 | ||
| 131 | return 0; | 140 | return 0; |
| @@ -205,6 +214,11 @@ static int bsr_add_node(struct device_node *bn) | |||
| 205 | cur->bsr_stride = bsr_stride[i]; | 214 | cur->bsr_stride = bsr_stride[i]; |
| 206 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); | 215 | cur->bsr_dev = MKDEV(bsr_major, i + total_bsr_devs); |
| 207 | 216 | ||
| 217 | /* if we have a bsr_len of > 4k and less then PAGE_SIZE (64k pages) */ | ||
| 218 | /* we can only map 4k of it, so only advertise the 4k in sysfs */ | ||
| 219 | if (cur->bsr_len > 4096 && cur->bsr_len < PAGE_SIZE) | ||
| 220 | cur->bsr_len = 4096; | ||
| 221 | |||
| 208 | switch(cur->bsr_bytes) { | 222 | switch(cur->bsr_bytes) { |
| 209 | case 8: | 223 | case 8: |
| 210 | cur->bsr_type = BSR_8; | 224 | cur->bsr_type = BSR_8; |
| @@ -218,9 +232,11 @@ static int bsr_add_node(struct device_node *bn) | |||
| 218 | case 128: | 232 | case 128: |
| 219 | cur->bsr_type = BSR_128; | 233 | cur->bsr_type = BSR_128; |
| 220 | break; | 234 | break; |
| 235 | case 4096: | ||
| 236 | cur->bsr_type = BSR_4096; | ||
| 237 | break; | ||
| 221 | default: | 238 | default: |
| 222 | cur->bsr_type = BSR_UNKNOWN; | 239 | cur->bsr_type = BSR_UNKNOWN; |
| 223 | printk(KERN_INFO "unknown BSR size %d\n",cur->bsr_bytes); | ||
| 224 | } | 240 | } |
| 225 | 241 | ||
| 226 | cur->bsr_num = bsr_types[cur->bsr_type]; | 242 | cur->bsr_num = bsr_types[cur->bsr_type]; |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index c36bf40568cf..858fe6037223 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
| @@ -754,13 +754,13 @@ static void amd64_cpu_display_info(struct amd64_pvt *pvt) | |||
| 754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) | 754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) |
| 755 | { | 755 | { |
| 756 | int bit; | 756 | int bit; |
| 757 | enum dev_type edac_cap = EDAC_NONE; | 757 | enum dev_type edac_cap = EDAC_FLAG_NONE; |
| 758 | 758 | ||
| 759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) | 759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) |
| 760 | ? 19 | 760 | ? 19 |
| 761 | : 17; | 761 | : 17; |
| 762 | 762 | ||
| 763 | if (pvt->dclr0 >> BIT(bit)) | 763 | if (pvt->dclr0 & BIT(bit)) |
| 764 | edac_cap = EDAC_FLAG_SECDED; | 764 | edac_cap = EDAC_FLAG_SECDED; |
| 765 | 765 | ||
| 766 | return edac_cap; | 766 | return edac_cap; |
| @@ -1269,7 +1269,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) | |||
| 1269 | if (channels == 0) | 1269 | if (channels == 0) |
| 1270 | channels = 1; | 1270 | channels = 1; |
| 1271 | 1271 | ||
| 1272 | debugf0("DIMM count= %d\n", channels); | 1272 | debugf0("MCT channel count: %d\n", channels); |
| 1273 | 1273 | ||
| 1274 | return channels; | 1274 | return channels; |
| 1275 | 1275 | ||
| @@ -2966,7 +2966,12 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) | |||
| 2966 | " Use of the override can cause " | 2966 | " Use of the override can cause " |
| 2967 | "unknown side effects.\n"); | 2967 | "unknown side effects.\n"); |
| 2968 | ret = -ENODEV; | 2968 | ret = -ENODEV; |
| 2969 | } | 2969 | } else |
| 2970 | /* | ||
| 2971 | * enable further driver loading if ECC enable is | ||
| 2972 | * overridden. | ||
| 2973 | */ | ||
| 2974 | ret = 0; | ||
| 2970 | } else { | 2975 | } else { |
| 2971 | amd64_printk(KERN_INFO, | 2976 | amd64_printk(KERN_INFO, |
| 2972 | "ECC is enabled by BIOS, Proceeding " | 2977 | "ECC is enabled by BIOS, Proceeding " |
| @@ -3006,7 +3011,6 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | |||
| 3006 | 3011 | ||
| 3007 | mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; | 3012 | mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; |
| 3008 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | 3013 | mci->edac_ctl_cap = EDAC_FLAG_NONE; |
| 3009 | mci->edac_cap = EDAC_FLAG_NONE; | ||
| 3010 | 3014 | ||
| 3011 | if (pvt->nbcap & K8_NBCAP_SECDED) | 3015 | if (pvt->nbcap & K8_NBCAP_SECDED) |
| 3012 | mci->edac_ctl_cap |= EDAC_FLAG_SECDED; | 3016 | mci->edac_ctl_cap |= EDAC_FLAG_SECDED; |
| @@ -3052,7 +3056,7 @@ static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, | |||
| 3052 | if (!pvt) | 3056 | if (!pvt) |
| 3053 | goto err_exit; | 3057 | goto err_exit; |
| 3054 | 3058 | ||
| 3055 | pvt->mc_node_id = get_mc_node_id_from_pdev(dram_f2_ctl); | 3059 | pvt->mc_node_id = get_node_id(dram_f2_ctl); |
| 3056 | 3060 | ||
| 3057 | pvt->dram_f2_ctl = dram_f2_ctl; | 3061 | pvt->dram_f2_ctl = dram_f2_ctl; |
| 3058 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | 3062 | pvt->ext_model = boot_cpu_data.x86_model >> 4; |
| @@ -3179,8 +3183,7 @@ static int __devinit amd64_init_one_instance(struct pci_dev *pdev, | |||
| 3179 | { | 3183 | { |
| 3180 | int ret = 0; | 3184 | int ret = 0; |
| 3181 | 3185 | ||
| 3182 | debugf0("(MC node=%d,mc_type='%s')\n", | 3186 | debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev), |
| 3183 | get_mc_node_id_from_pdev(pdev), | ||
| 3184 | get_amd_family_name(mc_type->driver_data)); | 3187 | get_amd_family_name(mc_type->driver_data)); |
| 3185 | 3188 | ||
| 3186 | ret = pci_enable_device(pdev); | 3189 | ret = pci_enable_device(pdev); |
| @@ -3319,15 +3322,17 @@ static int __init amd64_edac_init(void) | |||
| 3319 | 3322 | ||
| 3320 | err = amd64_init_2nd_stage(pvt_lookup[nb]); | 3323 | err = amd64_init_2nd_stage(pvt_lookup[nb]); |
| 3321 | if (err) | 3324 | if (err) |
| 3322 | goto err_exit; | 3325 | goto err_2nd_stage; |
| 3323 | } | 3326 | } |
| 3324 | 3327 | ||
| 3325 | amd64_setup_pci_device(); | 3328 | amd64_setup_pci_device(); |
| 3326 | 3329 | ||
| 3327 | return 0; | 3330 | return 0; |
| 3328 | 3331 | ||
| 3332 | err_2nd_stage: | ||
| 3333 | debugf0("2nd stage failed\n"); | ||
| 3334 | |||
| 3329 | err_exit: | 3335 | err_exit: |
| 3330 | debugf0("'finish_setup' stage failed\n"); | ||
| 3331 | pci_unregister_driver(&amd64_pci_driver); | 3336 | pci_unregister_driver(&amd64_pci_driver); |
| 3332 | 3337 | ||
| 3333 | return err; | 3338 | return err; |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index a159957e167b..ba73015af8e4 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
| @@ -444,7 +444,7 @@ enum { | |||
| 444 | #define K8_MSR_MC4ADDR 0x0412 | 444 | #define K8_MSR_MC4ADDR 0x0412 |
| 445 | 445 | ||
| 446 | /* AMD sets the first MC device at device ID 0x18. */ | 446 | /* AMD sets the first MC device at device ID 0x18. */ |
| 447 | static inline int get_mc_node_id_from_pdev(struct pci_dev *pdev) | 447 | static inline int get_node_id(struct pci_dev *pdev) |
| 448 | { | 448 | { |
| 449 | return PCI_SLOT(pdev->devfn) - 0x18; | 449 | return PCI_SLOT(pdev->devfn) - 0x18; |
| 450 | } | 450 | } |
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index c961fe415aef..39b393d38bb3 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -81,6 +81,7 @@ config DRM_I830 | |||
| 81 | 81 | ||
| 82 | config DRM_I915 | 82 | config DRM_I915 |
| 83 | tristate "i915 driver" | 83 | tristate "i915 driver" |
| 84 | depends on AGP_INTEL | ||
| 84 | select FB_CFB_FILLRECT | 85 | select FB_CFB_FILLRECT |
| 85 | select FB_CFB_COPYAREA | 86 | select FB_CFB_COPYAREA |
| 86 | select FB_CFB_IMAGEBLIT | 87 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 4e89ab08b7b8..fe23f29f7cba 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile | |||
| @@ -16,6 +16,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ | |||
| 16 | drm-$(CONFIG_COMPAT) += drm_ioc32.o | 16 | drm-$(CONFIG_COMPAT) += drm_ioc32.o |
| 17 | 17 | ||
| 18 | obj-$(CONFIG_DRM) += drm.o | 18 | obj-$(CONFIG_DRM) += drm.o |
| 19 | obj-$(CONFIG_DRM_TTM) += ttm/ | ||
| 19 | obj-$(CONFIG_DRM_TDFX) += tdfx/ | 20 | obj-$(CONFIG_DRM_TDFX) += tdfx/ |
| 20 | obj-$(CONFIG_DRM_R128) += r128/ | 21 | obj-$(CONFIG_DRM_R128) += r128/ |
| 21 | obj-$(CONFIG_DRM_RADEON)+= radeon/ | 22 | obj-$(CONFIG_DRM_RADEON)+= radeon/ |
| @@ -26,4 +27,3 @@ obj-$(CONFIG_DRM_I915) += i915/ | |||
| 26 | obj-$(CONFIG_DRM_SIS) += sis/ | 27 | obj-$(CONFIG_DRM_SIS) += sis/ |
| 27 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ | 28 | obj-$(CONFIG_DRM_SAVAGE)+= savage/ |
| 28 | obj-$(CONFIG_DRM_VIA) +=via/ | 29 | obj-$(CONFIG_DRM_VIA) +=via/ |
| 29 | obj-$(CONFIG_DRM_TTM) += ttm/ | ||
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 7d0835226f6e..80cc6d06d61b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -294,10 +294,10 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
| 294 | unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; | 294 | unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; |
| 295 | unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; | 295 | unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; |
| 296 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; | 296 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; |
| 297 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 8 | pt->hsync_offset_lo; | 297 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; |
| 298 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 6 | pt->hsync_pulse_width_lo; | 298 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; |
| 299 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) | (pt->vsync_offset_pulse_width_lo & 0xf); | 299 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; |
| 300 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; | 300 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); |
| 301 | 301 | ||
| 302 | /* ignore tiny modes */ | 302 | /* ignore tiny modes */ |
| 303 | if (hactive < 64 || vactive < 64) | 303 | if (hactive < 64 || vactive < 64) |
| @@ -347,8 +347,8 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
| 347 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? | 347 | mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? |
| 348 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; | 348 | DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; |
| 349 | 349 | ||
| 350 | mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; | 350 | mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; |
| 351 | mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; | 351 | mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; |
| 352 | 352 | ||
| 353 | if (quirks & EDID_QUIRK_DETAILED_IN_CM) { | 353 | if (quirks & EDID_QUIRK_DETAILED_IN_CM) { |
| 354 | mode->width_mm *= 10; | 354 | mode->width_mm *= 10; |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 51c5a050aa73..30d6b99fb302 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
| @@ -13,6 +13,8 @@ i915-y := i915_drv.o i915_dma.o i915_irq.o i915_mem.o \ | |||
| 13 | intel_crt.o \ | 13 | intel_crt.o \ |
| 14 | intel_lvds.o \ | 14 | intel_lvds.o \ |
| 15 | intel_bios.o \ | 15 | intel_bios.o \ |
| 16 | intel_dp.o \ | ||
| 17 | intel_dp_i2c.o \ | ||
| 16 | intel_hdmi.o \ | 18 | intel_hdmi.o \ |
| 17 | intel_sdvo.o \ | 19 | intel_sdvo.o \ |
| 18 | intel_modes.o \ | 20 | intel_modes.o \ |
diff --git a/drivers/gpu/drm/i915/dvo.h b/drivers/gpu/drm/i915/dvo.h index e747ac42fe3a..288fc50627e2 100644 --- a/drivers/gpu/drm/i915/dvo.h +++ b/drivers/gpu/drm/i915/dvo.h | |||
| @@ -37,7 +37,7 @@ struct intel_dvo_device { | |||
| 37 | /* GPIO register used for i2c bus to control this device */ | 37 | /* GPIO register used for i2c bus to control this device */ |
| 38 | u32 gpio; | 38 | u32 gpio; |
| 39 | int slave_addr; | 39 | int slave_addr; |
| 40 | struct intel_i2c_chan *i2c_bus; | 40 | struct i2c_adapter *i2c_bus; |
| 41 | 41 | ||
| 42 | const struct intel_dvo_dev_ops *dev_ops; | 42 | const struct intel_dvo_dev_ops *dev_ops; |
| 43 | void *dev_priv; | 43 | void *dev_priv; |
| @@ -52,7 +52,7 @@ struct intel_dvo_dev_ops { | |||
| 52 | * Returns NULL if the device does not exist. | 52 | * Returns NULL if the device does not exist. |
| 53 | */ | 53 | */ |
| 54 | bool (*init)(struct intel_dvo_device *dvo, | 54 | bool (*init)(struct intel_dvo_device *dvo, |
| 55 | struct intel_i2c_chan *i2cbus); | 55 | struct i2c_adapter *i2cbus); |
| 56 | 56 | ||
| 57 | /* | 57 | /* |
| 58 | * Called to allow the output a chance to create properties after the | 58 | * Called to allow the output a chance to create properties after the |
diff --git a/drivers/gpu/drm/i915/dvo_ch7017.c b/drivers/gpu/drm/i915/dvo_ch7017.c index 03d4b4973b02..621815b531db 100644 --- a/drivers/gpu/drm/i915/dvo_ch7017.c +++ b/drivers/gpu/drm/i915/dvo_ch7017.c | |||
| @@ -176,19 +176,20 @@ static void ch7017_dpms(struct intel_dvo_device *dvo, int mode); | |||
| 176 | 176 | ||
| 177 | static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) | 177 | static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) |
| 178 | { | 178 | { |
| 179 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 179 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 180 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 180 | u8 out_buf[2]; | 181 | u8 out_buf[2]; |
| 181 | u8 in_buf[2]; | 182 | u8 in_buf[2]; |
| 182 | 183 | ||
| 183 | struct i2c_msg msgs[] = { | 184 | struct i2c_msg msgs[] = { |
| 184 | { | 185 | { |
| 185 | .addr = i2cbus->slave_addr, | 186 | .addr = dvo->slave_addr, |
| 186 | .flags = 0, | 187 | .flags = 0, |
| 187 | .len = 1, | 188 | .len = 1, |
| 188 | .buf = out_buf, | 189 | .buf = out_buf, |
| 189 | }, | 190 | }, |
| 190 | { | 191 | { |
| 191 | .addr = i2cbus->slave_addr, | 192 | .addr = dvo->slave_addr, |
| 192 | .flags = I2C_M_RD, | 193 | .flags = I2C_M_RD, |
| 193 | .len = 1, | 194 | .len = 1, |
| 194 | .buf = in_buf, | 195 | .buf = in_buf, |
| @@ -208,10 +209,11 @@ static bool ch7017_read(struct intel_dvo_device *dvo, int addr, uint8_t *val) | |||
| 208 | 209 | ||
| 209 | static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) | 210 | static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) |
| 210 | { | 211 | { |
| 211 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 212 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 213 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 212 | uint8_t out_buf[2]; | 214 | uint8_t out_buf[2]; |
| 213 | struct i2c_msg msg = { | 215 | struct i2c_msg msg = { |
| 214 | .addr = i2cbus->slave_addr, | 216 | .addr = dvo->slave_addr, |
| 215 | .flags = 0, | 217 | .flags = 0, |
| 216 | .len = 2, | 218 | .len = 2, |
| 217 | .buf = out_buf, | 219 | .buf = out_buf, |
| @@ -228,8 +230,9 @@ static bool ch7017_write(struct intel_dvo_device *dvo, int addr, uint8_t val) | |||
| 228 | 230 | ||
| 229 | /** Probes for a CH7017 on the given bus and slave address. */ | 231 | /** Probes for a CH7017 on the given bus and slave address. */ |
| 230 | static bool ch7017_init(struct intel_dvo_device *dvo, | 232 | static bool ch7017_init(struct intel_dvo_device *dvo, |
| 231 | struct intel_i2c_chan *i2cbus) | 233 | struct i2c_adapter *adapter) |
| 232 | { | 234 | { |
| 235 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 233 | struct ch7017_priv *priv; | 236 | struct ch7017_priv *priv; |
| 234 | uint8_t val; | 237 | uint8_t val; |
| 235 | 238 | ||
| @@ -237,8 +240,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, | |||
| 237 | if (priv == NULL) | 240 | if (priv == NULL) |
| 238 | return false; | 241 | return false; |
| 239 | 242 | ||
| 240 | dvo->i2c_bus = i2cbus; | 243 | dvo->i2c_bus = adapter; |
| 241 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 242 | dvo->dev_priv = priv; | 244 | dvo->dev_priv = priv; |
| 243 | 245 | ||
| 244 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) | 246 | if (!ch7017_read(dvo, CH7017_DEVICE_ID, &val)) |
| @@ -248,7 +250,7 @@ static bool ch7017_init(struct intel_dvo_device *dvo, | |||
| 248 | val != CH7018_DEVICE_ID_VALUE && | 250 | val != CH7018_DEVICE_ID_VALUE && |
| 249 | val != CH7019_DEVICE_ID_VALUE) { | 251 | val != CH7019_DEVICE_ID_VALUE) { |
| 250 | DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", | 252 | DRM_DEBUG("ch701x not detected, got %d: from %s Slave %d.\n", |
| 251 | val, i2cbus->adapter.name,i2cbus->slave_addr); | 253 | val, i2cbus->adapter.name,dvo->slave_addr); |
| 252 | goto fail; | 254 | goto fail; |
| 253 | } | 255 | } |
| 254 | 256 | ||
diff --git a/drivers/gpu/drm/i915/dvo_ch7xxx.c b/drivers/gpu/drm/i915/dvo_ch7xxx.c index d2fd95dbd034..a9b896289680 100644 --- a/drivers/gpu/drm/i915/dvo_ch7xxx.c +++ b/drivers/gpu/drm/i915/dvo_ch7xxx.c | |||
| @@ -123,19 +123,20 @@ static char *ch7xxx_get_id(uint8_t vid) | |||
| 123 | static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 123 | static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
| 124 | { | 124 | { |
| 125 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; | 125 | struct ch7xxx_priv *ch7xxx= dvo->dev_priv; |
| 126 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 126 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 127 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 127 | u8 out_buf[2]; | 128 | u8 out_buf[2]; |
| 128 | u8 in_buf[2]; | 129 | u8 in_buf[2]; |
| 129 | 130 | ||
| 130 | struct i2c_msg msgs[] = { | 131 | struct i2c_msg msgs[] = { |
| 131 | { | 132 | { |
| 132 | .addr = i2cbus->slave_addr, | 133 | .addr = dvo->slave_addr, |
| 133 | .flags = 0, | 134 | .flags = 0, |
| 134 | .len = 1, | 135 | .len = 1, |
| 135 | .buf = out_buf, | 136 | .buf = out_buf, |
| 136 | }, | 137 | }, |
| 137 | { | 138 | { |
| 138 | .addr = i2cbus->slave_addr, | 139 | .addr = dvo->slave_addr, |
| 139 | .flags = I2C_M_RD, | 140 | .flags = I2C_M_RD, |
| 140 | .len = 1, | 141 | .len = 1, |
| 141 | .buf = in_buf, | 142 | .buf = in_buf, |
| @@ -152,7 +153,7 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 152 | 153 | ||
| 153 | if (!ch7xxx->quiet) { | 154 | if (!ch7xxx->quiet) { |
| 154 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 155 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 155 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 156 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 156 | } | 157 | } |
| 157 | return false; | 158 | return false; |
| 158 | } | 159 | } |
| @@ -161,10 +162,11 @@ static bool ch7xxx_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 161 | static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 162 | static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
| 162 | { | 163 | { |
| 163 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; | 164 | struct ch7xxx_priv *ch7xxx = dvo->dev_priv; |
| 164 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 165 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 166 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 165 | uint8_t out_buf[2]; | 167 | uint8_t out_buf[2]; |
| 166 | struct i2c_msg msg = { | 168 | struct i2c_msg msg = { |
| 167 | .addr = i2cbus->slave_addr, | 169 | .addr = dvo->slave_addr, |
| 168 | .flags = 0, | 170 | .flags = 0, |
| 169 | .len = 2, | 171 | .len = 2, |
| 170 | .buf = out_buf, | 172 | .buf = out_buf, |
| @@ -178,14 +180,14 @@ static bool ch7xxx_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 178 | 180 | ||
| 179 | if (!ch7xxx->quiet) { | 181 | if (!ch7xxx->quiet) { |
| 180 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 182 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 181 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 183 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 182 | } | 184 | } |
| 183 | 185 | ||
| 184 | return false; | 186 | return false; |
| 185 | } | 187 | } |
| 186 | 188 | ||
| 187 | static bool ch7xxx_init(struct intel_dvo_device *dvo, | 189 | static bool ch7xxx_init(struct intel_dvo_device *dvo, |
| 188 | struct intel_i2c_chan *i2cbus) | 190 | struct i2c_adapter *adapter) |
| 189 | { | 191 | { |
| 190 | /* this will detect the CH7xxx chip on the specified i2c bus */ | 192 | /* this will detect the CH7xxx chip on the specified i2c bus */ |
| 191 | struct ch7xxx_priv *ch7xxx; | 193 | struct ch7xxx_priv *ch7xxx; |
| @@ -196,8 +198,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
| 196 | if (ch7xxx == NULL) | 198 | if (ch7xxx == NULL) |
| 197 | return false; | 199 | return false; |
| 198 | 200 | ||
| 199 | dvo->i2c_bus = i2cbus; | 201 | dvo->i2c_bus = adapter; |
| 200 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 201 | dvo->dev_priv = ch7xxx; | 202 | dvo->dev_priv = ch7xxx; |
| 202 | ch7xxx->quiet = true; | 203 | ch7xxx->quiet = true; |
| 203 | 204 | ||
| @@ -207,7 +208,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
| 207 | name = ch7xxx_get_id(vendor); | 208 | name = ch7xxx_get_id(vendor); |
| 208 | if (!name) { | 209 | if (!name) { |
| 209 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", | 210 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", |
| 210 | vendor, i2cbus->adapter.name, i2cbus->slave_addr); | 211 | vendor, adapter->name, dvo->slave_addr); |
| 211 | goto out; | 212 | goto out; |
| 212 | } | 213 | } |
| 213 | 214 | ||
| @@ -217,7 +218,7 @@ static bool ch7xxx_init(struct intel_dvo_device *dvo, | |||
| 217 | 218 | ||
| 218 | if (device != CH7xxx_DID) { | 219 | if (device != CH7xxx_DID) { |
| 219 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", | 220 | DRM_DEBUG("ch7xxx not detected; got 0x%02x from %s slave %d.\n", |
| 220 | vendor, i2cbus->adapter.name, i2cbus->slave_addr); | 221 | vendor, adapter->name, dvo->slave_addr); |
| 221 | goto out; | 222 | goto out; |
| 222 | } | 223 | } |
| 223 | 224 | ||
diff --git a/drivers/gpu/drm/i915/dvo_ivch.c b/drivers/gpu/drm/i915/dvo_ivch.c index 0c8d375e8e37..aa176f9921fe 100644 --- a/drivers/gpu/drm/i915/dvo_ivch.c +++ b/drivers/gpu/drm/i915/dvo_ivch.c | |||
| @@ -169,13 +169,14 @@ static void ivch_dump_regs(struct intel_dvo_device *dvo); | |||
| 169 | static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | 169 | static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) |
| 170 | { | 170 | { |
| 171 | struct ivch_priv *priv = dvo->dev_priv; | 171 | struct ivch_priv *priv = dvo->dev_priv; |
| 172 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 172 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 173 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 173 | u8 out_buf[1]; | 174 | u8 out_buf[1]; |
| 174 | u8 in_buf[2]; | 175 | u8 in_buf[2]; |
| 175 | 176 | ||
| 176 | struct i2c_msg msgs[] = { | 177 | struct i2c_msg msgs[] = { |
| 177 | { | 178 | { |
| 178 | .addr = i2cbus->slave_addr, | 179 | .addr = dvo->slave_addr, |
| 179 | .flags = I2C_M_RD, | 180 | .flags = I2C_M_RD, |
| 180 | .len = 0, | 181 | .len = 0, |
| 181 | }, | 182 | }, |
| @@ -186,7 +187,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
| 186 | .buf = out_buf, | 187 | .buf = out_buf, |
| 187 | }, | 188 | }, |
| 188 | { | 189 | { |
| 189 | .addr = i2cbus->slave_addr, | 190 | .addr = dvo->slave_addr, |
| 190 | .flags = I2C_M_RD | I2C_M_NOSTART, | 191 | .flags = I2C_M_RD | I2C_M_NOSTART, |
| 191 | .len = 2, | 192 | .len = 2, |
| 192 | .buf = in_buf, | 193 | .buf = in_buf, |
| @@ -202,7 +203,7 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
| 202 | 203 | ||
| 203 | if (!priv->quiet) { | 204 | if (!priv->quiet) { |
| 204 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 205 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 205 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 206 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 206 | } | 207 | } |
| 207 | return false; | 208 | return false; |
| 208 | } | 209 | } |
| @@ -211,10 +212,11 @@ static bool ivch_read(struct intel_dvo_device *dvo, int addr, uint16_t *data) | |||
| 211 | static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | 212 | static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) |
| 212 | { | 213 | { |
| 213 | struct ivch_priv *priv = dvo->dev_priv; | 214 | struct ivch_priv *priv = dvo->dev_priv; |
| 214 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 215 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 216 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 215 | u8 out_buf[3]; | 217 | u8 out_buf[3]; |
| 216 | struct i2c_msg msg = { | 218 | struct i2c_msg msg = { |
| 217 | .addr = i2cbus->slave_addr, | 219 | .addr = dvo->slave_addr, |
| 218 | .flags = 0, | 220 | .flags = 0, |
| 219 | .len = 3, | 221 | .len = 3, |
| 220 | .buf = out_buf, | 222 | .buf = out_buf, |
| @@ -229,7 +231,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
| 229 | 231 | ||
| 230 | if (!priv->quiet) { | 232 | if (!priv->quiet) { |
| 231 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 233 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 232 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 234 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 233 | } | 235 | } |
| 234 | 236 | ||
| 235 | return false; | 237 | return false; |
| @@ -237,7 +239,7 @@ static bool ivch_write(struct intel_dvo_device *dvo, int addr, uint16_t data) | |||
| 237 | 239 | ||
| 238 | /** Probes the given bus and slave address for an ivch */ | 240 | /** Probes the given bus and slave address for an ivch */ |
| 239 | static bool ivch_init(struct intel_dvo_device *dvo, | 241 | static bool ivch_init(struct intel_dvo_device *dvo, |
| 240 | struct intel_i2c_chan *i2cbus) | 242 | struct i2c_adapter *adapter) |
| 241 | { | 243 | { |
| 242 | struct ivch_priv *priv; | 244 | struct ivch_priv *priv; |
| 243 | uint16_t temp; | 245 | uint16_t temp; |
| @@ -246,8 +248,7 @@ static bool ivch_init(struct intel_dvo_device *dvo, | |||
| 246 | if (priv == NULL) | 248 | if (priv == NULL) |
| 247 | return false; | 249 | return false; |
| 248 | 250 | ||
| 249 | dvo->i2c_bus = i2cbus; | 251 | dvo->i2c_bus = adapter; |
| 250 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 251 | dvo->dev_priv = priv; | 252 | dvo->dev_priv = priv; |
| 252 | priv->quiet = true; | 253 | priv->quiet = true; |
| 253 | 254 | ||
diff --git a/drivers/gpu/drm/i915/dvo_sil164.c b/drivers/gpu/drm/i915/dvo_sil164.c index 033a4bb070b2..e1c1f7341e5c 100644 --- a/drivers/gpu/drm/i915/dvo_sil164.c +++ b/drivers/gpu/drm/i915/dvo_sil164.c | |||
| @@ -76,19 +76,20 @@ struct sil164_priv { | |||
| 76 | static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 76 | static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
| 77 | { | 77 | { |
| 78 | struct sil164_priv *sil = dvo->dev_priv; | 78 | struct sil164_priv *sil = dvo->dev_priv; |
| 79 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 79 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 80 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 80 | u8 out_buf[2]; | 81 | u8 out_buf[2]; |
| 81 | u8 in_buf[2]; | 82 | u8 in_buf[2]; |
| 82 | 83 | ||
| 83 | struct i2c_msg msgs[] = { | 84 | struct i2c_msg msgs[] = { |
| 84 | { | 85 | { |
| 85 | .addr = i2cbus->slave_addr, | 86 | .addr = dvo->slave_addr, |
| 86 | .flags = 0, | 87 | .flags = 0, |
| 87 | .len = 1, | 88 | .len = 1, |
| 88 | .buf = out_buf, | 89 | .buf = out_buf, |
| 89 | }, | 90 | }, |
| 90 | { | 91 | { |
| 91 | .addr = i2cbus->slave_addr, | 92 | .addr = dvo->slave_addr, |
| 92 | .flags = I2C_M_RD, | 93 | .flags = I2C_M_RD, |
| 93 | .len = 1, | 94 | .len = 1, |
| 94 | .buf = in_buf, | 95 | .buf = in_buf, |
| @@ -105,7 +106,7 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 105 | 106 | ||
| 106 | if (!sil->quiet) { | 107 | if (!sil->quiet) { |
| 107 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 108 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 108 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 109 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 109 | } | 110 | } |
| 110 | return false; | 111 | return false; |
| 111 | } | 112 | } |
| @@ -113,10 +114,11 @@ static bool sil164_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 113 | static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 114 | static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
| 114 | { | 115 | { |
| 115 | struct sil164_priv *sil= dvo->dev_priv; | 116 | struct sil164_priv *sil= dvo->dev_priv; |
| 116 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 117 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 118 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 117 | uint8_t out_buf[2]; | 119 | uint8_t out_buf[2]; |
| 118 | struct i2c_msg msg = { | 120 | struct i2c_msg msg = { |
| 119 | .addr = i2cbus->slave_addr, | 121 | .addr = dvo->slave_addr, |
| 120 | .flags = 0, | 122 | .flags = 0, |
| 121 | .len = 2, | 123 | .len = 2, |
| 122 | .buf = out_buf, | 124 | .buf = out_buf, |
| @@ -130,7 +132,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 130 | 132 | ||
| 131 | if (!sil->quiet) { | 133 | if (!sil->quiet) { |
| 132 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 134 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 133 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 135 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 134 | } | 136 | } |
| 135 | 137 | ||
| 136 | return false; | 138 | return false; |
| @@ -138,7 +140,7 @@ static bool sil164_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 138 | 140 | ||
| 139 | /* Silicon Image 164 driver for chip on i2c bus */ | 141 | /* Silicon Image 164 driver for chip on i2c bus */ |
| 140 | static bool sil164_init(struct intel_dvo_device *dvo, | 142 | static bool sil164_init(struct intel_dvo_device *dvo, |
| 141 | struct intel_i2c_chan *i2cbus) | 143 | struct i2c_adapter *adapter) |
| 142 | { | 144 | { |
| 143 | /* this will detect the SIL164 chip on the specified i2c bus */ | 145 | /* this will detect the SIL164 chip on the specified i2c bus */ |
| 144 | struct sil164_priv *sil; | 146 | struct sil164_priv *sil; |
| @@ -148,8 +150,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
| 148 | if (sil == NULL) | 150 | if (sil == NULL) |
| 149 | return false; | 151 | return false; |
| 150 | 152 | ||
| 151 | dvo->i2c_bus = i2cbus; | 153 | dvo->i2c_bus = adapter; |
| 152 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 153 | dvo->dev_priv = sil; | 154 | dvo->dev_priv = sil; |
| 154 | sil->quiet = true; | 155 | sil->quiet = true; |
| 155 | 156 | ||
| @@ -158,7 +159,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
| 158 | 159 | ||
| 159 | if (ch != (SIL164_VID & 0xff)) { | 160 | if (ch != (SIL164_VID & 0xff)) { |
| 160 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", | 161 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", |
| 161 | ch, i2cbus->adapter.name, i2cbus->slave_addr); | 162 | ch, adapter->name, dvo->slave_addr); |
| 162 | goto out; | 163 | goto out; |
| 163 | } | 164 | } |
| 164 | 165 | ||
| @@ -167,7 +168,7 @@ static bool sil164_init(struct intel_dvo_device *dvo, | |||
| 167 | 168 | ||
| 168 | if (ch != (SIL164_DID & 0xff)) { | 169 | if (ch != (SIL164_DID & 0xff)) { |
| 169 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", | 170 | DRM_DEBUG("sil164 not detected got %d: from %s Slave %d.\n", |
| 170 | ch, i2cbus->adapter.name, i2cbus->slave_addr); | 171 | ch, adapter->name, dvo->slave_addr); |
| 171 | goto out; | 172 | goto out; |
| 172 | } | 173 | } |
| 173 | sil->quiet = false; | 174 | sil->quiet = false; |
diff --git a/drivers/gpu/drm/i915/dvo_tfp410.c b/drivers/gpu/drm/i915/dvo_tfp410.c index 207fda806ebf..9ecc907384ec 100644 --- a/drivers/gpu/drm/i915/dvo_tfp410.c +++ b/drivers/gpu/drm/i915/dvo_tfp410.c | |||
| @@ -101,19 +101,20 @@ struct tfp410_priv { | |||
| 101 | static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | 101 | static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) |
| 102 | { | 102 | { |
| 103 | struct tfp410_priv *tfp = dvo->dev_priv; | 103 | struct tfp410_priv *tfp = dvo->dev_priv; |
| 104 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 104 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 105 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 105 | u8 out_buf[2]; | 106 | u8 out_buf[2]; |
| 106 | u8 in_buf[2]; | 107 | u8 in_buf[2]; |
| 107 | 108 | ||
| 108 | struct i2c_msg msgs[] = { | 109 | struct i2c_msg msgs[] = { |
| 109 | { | 110 | { |
| 110 | .addr = i2cbus->slave_addr, | 111 | .addr = dvo->slave_addr, |
| 111 | .flags = 0, | 112 | .flags = 0, |
| 112 | .len = 1, | 113 | .len = 1, |
| 113 | .buf = out_buf, | 114 | .buf = out_buf, |
| 114 | }, | 115 | }, |
| 115 | { | 116 | { |
| 116 | .addr = i2cbus->slave_addr, | 117 | .addr = dvo->slave_addr, |
| 117 | .flags = I2C_M_RD, | 118 | .flags = I2C_M_RD, |
| 118 | .len = 1, | 119 | .len = 1, |
| 119 | .buf = in_buf, | 120 | .buf = in_buf, |
| @@ -130,7 +131,7 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 130 | 131 | ||
| 131 | if (!tfp->quiet) { | 132 | if (!tfp->quiet) { |
| 132 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", | 133 | DRM_DEBUG("Unable to read register 0x%02x from %s:%02x.\n", |
| 133 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 134 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 134 | } | 135 | } |
| 135 | return false; | 136 | return false; |
| 136 | } | 137 | } |
| @@ -138,10 +139,11 @@ static bool tfp410_readb(struct intel_dvo_device *dvo, int addr, uint8_t *ch) | |||
| 138 | static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | 139 | static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) |
| 139 | { | 140 | { |
| 140 | struct tfp410_priv *tfp = dvo->dev_priv; | 141 | struct tfp410_priv *tfp = dvo->dev_priv; |
| 141 | struct intel_i2c_chan *i2cbus = dvo->i2c_bus; | 142 | struct i2c_adapter *adapter = dvo->i2c_bus; |
| 143 | struct intel_i2c_chan *i2cbus = container_of(adapter, struct intel_i2c_chan, adapter); | ||
| 142 | uint8_t out_buf[2]; | 144 | uint8_t out_buf[2]; |
| 143 | struct i2c_msg msg = { | 145 | struct i2c_msg msg = { |
| 144 | .addr = i2cbus->slave_addr, | 146 | .addr = dvo->slave_addr, |
| 145 | .flags = 0, | 147 | .flags = 0, |
| 146 | .len = 2, | 148 | .len = 2, |
| 147 | .buf = out_buf, | 149 | .buf = out_buf, |
| @@ -155,7 +157,7 @@ static bool tfp410_writeb(struct intel_dvo_device *dvo, int addr, uint8_t ch) | |||
| 155 | 157 | ||
| 156 | if (!tfp->quiet) { | 158 | if (!tfp->quiet) { |
| 157 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", | 159 | DRM_DEBUG("Unable to write register 0x%02x to %s:%d.\n", |
| 158 | addr, i2cbus->adapter.name, i2cbus->slave_addr); | 160 | addr, i2cbus->adapter.name, dvo->slave_addr); |
| 159 | } | 161 | } |
| 160 | 162 | ||
| 161 | return false; | 163 | return false; |
| @@ -174,7 +176,7 @@ static int tfp410_getid(struct intel_dvo_device *dvo, int addr) | |||
| 174 | 176 | ||
| 175 | /* Ti TFP410 driver for chip on i2c bus */ | 177 | /* Ti TFP410 driver for chip on i2c bus */ |
| 176 | static bool tfp410_init(struct intel_dvo_device *dvo, | 178 | static bool tfp410_init(struct intel_dvo_device *dvo, |
| 177 | struct intel_i2c_chan *i2cbus) | 179 | struct i2c_adapter *adapter) |
| 178 | { | 180 | { |
| 179 | /* this will detect the tfp410 chip on the specified i2c bus */ | 181 | /* this will detect the tfp410 chip on the specified i2c bus */ |
| 180 | struct tfp410_priv *tfp; | 182 | struct tfp410_priv *tfp; |
| @@ -184,20 +186,19 @@ static bool tfp410_init(struct intel_dvo_device *dvo, | |||
| 184 | if (tfp == NULL) | 186 | if (tfp == NULL) |
| 185 | return false; | 187 | return false; |
| 186 | 188 | ||
| 187 | dvo->i2c_bus = i2cbus; | 189 | dvo->i2c_bus = adapter; |
| 188 | dvo->i2c_bus->slave_addr = dvo->slave_addr; | ||
| 189 | dvo->dev_priv = tfp; | 190 | dvo->dev_priv = tfp; |
| 190 | tfp->quiet = true; | 191 | tfp->quiet = true; |
| 191 | 192 | ||
| 192 | if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { | 193 | if ((id = tfp410_getid(dvo, TFP410_VID_LO)) != TFP410_VID) { |
| 193 | DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", | 194 | DRM_DEBUG("tfp410 not detected got VID %X: from %s Slave %d.\n", |
| 194 | id, i2cbus->adapter.name, i2cbus->slave_addr); | 195 | id, adapter->name, dvo->slave_addr); |
| 195 | goto out; | 196 | goto out; |
| 196 | } | 197 | } |
| 197 | 198 | ||
| 198 | if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { | 199 | if ((id = tfp410_getid(dvo, TFP410_DID_LO)) != TFP410_DID) { |
| 199 | DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", | 200 | DRM_DEBUG("tfp410 not detected got DID %X: from %s Slave %d.\n", |
| 200 | id, i2cbus->adapter.name, i2cbus->slave_addr); | 201 | id, adapter->name, dvo->slave_addr); |
| 201 | goto out; | 202 | goto out; |
| 202 | } | 203 | } |
| 203 | tfp->quiet = false; | 204 | tfp->quiet = false; |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 98560e1e899a..e3cb4025e323 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -67,8 +67,6 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 67 | 67 | ||
| 68 | pci_save_state(dev->pdev); | 68 | pci_save_state(dev->pdev); |
| 69 | 69 | ||
| 70 | i915_save_state(dev); | ||
| 71 | |||
| 72 | /* If KMS is active, we do the leavevt stuff here */ | 70 | /* If KMS is active, we do the leavevt stuff here */ |
| 73 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { | 71 | if (drm_core_check_feature(dev, DRIVER_MODESET)) { |
| 74 | if (i915_gem_idle(dev)) | 72 | if (i915_gem_idle(dev)) |
| @@ -77,6 +75,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state) | |||
| 77 | drm_irq_uninstall(dev); | 75 | drm_irq_uninstall(dev); |
| 78 | } | 76 | } |
| 79 | 77 | ||
| 78 | i915_save_state(dev); | ||
| 79 | |||
| 80 | intel_opregion_free(dev, 1); | 80 | intel_opregion_free(dev, 1); |
| 81 | 81 | ||
| 82 | if (state.event == PM_EVENT_SUSPEND) { | 82 | if (state.event == PM_EVENT_SUSPEND) { |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 7a84f04e8439..bb4c2d387b6c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -306,6 +306,17 @@ typedef struct drm_i915_private { | |||
| 306 | u32 saveCURBPOS; | 306 | u32 saveCURBPOS; |
| 307 | u32 saveCURBBASE; | 307 | u32 saveCURBBASE; |
| 308 | u32 saveCURSIZE; | 308 | u32 saveCURSIZE; |
| 309 | u32 saveDP_B; | ||
| 310 | u32 saveDP_C; | ||
| 311 | u32 saveDP_D; | ||
| 312 | u32 savePIPEA_GMCH_DATA_M; | ||
| 313 | u32 savePIPEB_GMCH_DATA_M; | ||
| 314 | u32 savePIPEA_GMCH_DATA_N; | ||
| 315 | u32 savePIPEB_GMCH_DATA_N; | ||
| 316 | u32 savePIPEA_DP_LINK_M; | ||
| 317 | u32 savePIPEB_DP_LINK_M; | ||
| 318 | u32 savePIPEA_DP_LINK_N; | ||
| 319 | u32 savePIPEB_DP_LINK_N; | ||
| 309 | 320 | ||
| 310 | struct { | 321 | struct { |
| 311 | struct drm_mm gtt_space; | 322 | struct drm_mm gtt_space; |
| @@ -857,6 +868,7 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); | |||
| 857 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ | 868 | #define HAS_128_BYTE_Y_TILING(dev) (IS_I9XX(dev) && !(IS_I915G(dev) || \ |
| 858 | IS_I915GM(dev))) | 869 | IS_I915GM(dev))) |
| 859 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | 870 | #define SUPPORTS_INTEGRATED_HDMI(dev) (IS_G4X(dev) || IS_IGDNG(dev)) |
| 871 | #define SUPPORTS_INTEGRATED_DP(dev) (IS_G4X(dev) || IS_IGDNG(dev)) | ||
| 860 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) | 872 | #define I915_HAS_HOTPLUG(dev) (IS_I945G(dev) || IS_I945GM(dev) || IS_I965G(dev)) |
| 861 | 873 | ||
| 862 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) | 874 | #define PRIMARY_RINGBUFFER_SIZE (128*1024) |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index fd2b8bdffe3f..876b65cb7629 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1006,7 +1006,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, | |||
| 1006 | 1006 | ||
| 1007 | mutex_lock(&dev->struct_mutex); | 1007 | mutex_lock(&dev->struct_mutex); |
| 1008 | #if WATCH_BUF | 1008 | #if WATCH_BUF |
| 1009 | DRM_INFO("set_domain_ioctl %p(%d), %08x %08x\n", | 1009 | DRM_INFO("set_domain_ioctl %p(%zd), %08x %08x\n", |
| 1010 | obj, obj->size, read_domains, write_domain); | 1010 | obj, obj->size, read_domains, write_domain); |
| 1011 | #endif | 1011 | #endif |
| 1012 | if (read_domains & I915_GEM_DOMAIN_GTT) { | 1012 | if (read_domains & I915_GEM_DOMAIN_GTT) { |
| @@ -1050,7 +1050,7 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, | |||
| 1050 | } | 1050 | } |
| 1051 | 1051 | ||
| 1052 | #if WATCH_BUF | 1052 | #if WATCH_BUF |
| 1053 | DRM_INFO("%s: sw_finish %d (%p %d)\n", | 1053 | DRM_INFO("%s: sw_finish %d (%p %zd)\n", |
| 1054 | __func__, args->handle, obj, obj->size); | 1054 | __func__, args->handle, obj, obj->size); |
| 1055 | #endif | 1055 | #endif |
| 1056 | obj_priv = obj->driver_private; | 1056 | obj_priv = obj->driver_private; |
| @@ -2423,7 +2423,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) | |||
| 2423 | } | 2423 | } |
| 2424 | 2424 | ||
| 2425 | #if WATCH_BUF | 2425 | #if WATCH_BUF |
| 2426 | DRM_INFO("Binding object of size %d at 0x%08x\n", | 2426 | DRM_INFO("Binding object of size %zd at 0x%08x\n", |
| 2427 | obj->size, obj_priv->gtt_offset); | 2427 | obj->size, obj_priv->gtt_offset); |
| 2428 | #endif | 2428 | #endif |
| 2429 | ret = i915_gem_object_get_pages(obj); | 2429 | ret = i915_gem_object_get_pages(obj); |
| @@ -4227,6 +4227,7 @@ i915_gem_lastclose(struct drm_device *dev) | |||
| 4227 | void | 4227 | void |
| 4228 | i915_gem_load(struct drm_device *dev) | 4228 | i915_gem_load(struct drm_device *dev) |
| 4229 | { | 4229 | { |
| 4230 | int i; | ||
| 4230 | drm_i915_private_t *dev_priv = dev->dev_private; | 4231 | drm_i915_private_t *dev_priv = dev->dev_private; |
| 4231 | 4232 | ||
| 4232 | spin_lock_init(&dev_priv->mm.active_list_lock); | 4233 | spin_lock_init(&dev_priv->mm.active_list_lock); |
| @@ -4246,6 +4247,18 @@ i915_gem_load(struct drm_device *dev) | |||
| 4246 | else | 4247 | else |
| 4247 | dev_priv->num_fence_regs = 8; | 4248 | dev_priv->num_fence_regs = 8; |
| 4248 | 4249 | ||
| 4250 | /* Initialize fence registers to zero */ | ||
| 4251 | if (IS_I965G(dev)) { | ||
| 4252 | for (i = 0; i < 16; i++) | ||
| 4253 | I915_WRITE64(FENCE_REG_965_0 + (i * 8), 0); | ||
| 4254 | } else { | ||
| 4255 | for (i = 0; i < 8; i++) | ||
| 4256 | I915_WRITE(FENCE_REG_830_0 + (i * 4), 0); | ||
| 4257 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) | ||
| 4258 | for (i = 0; i < 8; i++) | ||
| 4259 | I915_WRITE(FENCE_REG_945_8 + (i * 4), 0); | ||
| 4260 | } | ||
| 4261 | |||
| 4249 | i915_gem_detect_bit_6_swizzle(dev); | 4262 | i915_gem_detect_bit_6_swizzle(dev); |
| 4250 | } | 4263 | } |
| 4251 | 4264 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_debug.c b/drivers/gpu/drm/i915/i915_gem_debug.c index 8d0b943e2c5a..e602614bd3f8 100644 --- a/drivers/gpu/drm/i915/i915_gem_debug.c +++ b/drivers/gpu/drm/i915/i915_gem_debug.c | |||
| @@ -87,7 +87,7 @@ i915_gem_dump_object(struct drm_gem_object *obj, int len, | |||
| 87 | chunk_len = page_len - chunk; | 87 | chunk_len = page_len - chunk; |
| 88 | if (chunk_len > 128) | 88 | if (chunk_len > 128) |
| 89 | chunk_len = 128; | 89 | chunk_len = 128; |
| 90 | i915_gem_dump_page(obj_priv->page_list[page], | 90 | i915_gem_dump_page(obj_priv->pages[page], |
| 91 | chunk, chunk + chunk_len, | 91 | chunk, chunk + chunk_len, |
| 92 | obj_priv->gtt_offset + | 92 | obj_priv->gtt_offset + |
| 93 | page * PAGE_SIZE, | 93 | page * PAGE_SIZE, |
| @@ -143,7 +143,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) | |||
| 143 | uint32_t *backing_map = NULL; | 143 | uint32_t *backing_map = NULL; |
| 144 | int bad_count = 0; | 144 | int bad_count = 0; |
| 145 | 145 | ||
| 146 | DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %dkb):\n", | 146 | DRM_INFO("%s: checking coherency of object %p@0x%08x (%d, %zdkb):\n", |
| 147 | __func__, obj, obj_priv->gtt_offset, handle, | 147 | __func__, obj, obj_priv->gtt_offset, handle, |
| 148 | obj->size / 1024); | 148 | obj->size / 1024); |
| 149 | 149 | ||
| @@ -157,7 +157,7 @@ i915_gem_object_check_coherency(struct drm_gem_object *obj, int handle) | |||
| 157 | for (page = 0; page < obj->size / PAGE_SIZE; page++) { | 157 | for (page = 0; page < obj->size / PAGE_SIZE; page++) { |
| 158 | int i; | 158 | int i; |
| 159 | 159 | ||
| 160 | backing_map = kmap_atomic(obj_priv->page_list[page], KM_USER0); | 160 | backing_map = kmap_atomic(obj_priv->pages[page], KM_USER0); |
| 161 | 161 | ||
| 162 | if (backing_map == NULL) { | 162 | if (backing_map == NULL) { |
| 163 | DRM_ERROR("failed to map backing page\n"); | 163 | DRM_ERROR("failed to map backing page\n"); |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 5c1ceec49f5b..daeae62e1c28 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -114,11 +114,13 @@ intel_alloc_mchbar_resource(struct drm_device *dev) | |||
| 114 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; | 114 | mchbar_addr = ((u64)temp_hi << 32) | temp_lo; |
| 115 | 115 | ||
| 116 | /* If ACPI doesn't have it, assume we need to allocate it ourselves */ | 116 | /* If ACPI doesn't have it, assume we need to allocate it ourselves */ |
| 117 | #ifdef CONFIG_PNP | ||
| 117 | if (mchbar_addr && | 118 | if (mchbar_addr && |
| 118 | pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { | 119 | pnp_range_reserved(mchbar_addr, mchbar_addr + MCHBAR_SIZE)) { |
| 119 | ret = 0; | 120 | ret = 0; |
| 120 | goto out_put; | 121 | goto out_put; |
| 121 | } | 122 | } |
| 123 | #endif | ||
| 122 | 124 | ||
| 123 | /* Get some space for it */ | 125 | /* Get some space for it */ |
| 124 | ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, | 126 | ret = pci_bus_alloc_resource(bridge_dev->bus, &dev_priv->mch_res, |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b86b7b7130c6..228546f6eaa4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -232,7 +232,17 @@ static void i915_hotplug_work_func(struct work_struct *work) | |||
| 232 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, | 232 | drm_i915_private_t *dev_priv = container_of(work, drm_i915_private_t, |
| 233 | hotplug_work); | 233 | hotplug_work); |
| 234 | struct drm_device *dev = dev_priv->dev; | 234 | struct drm_device *dev = dev_priv->dev; |
| 235 | 235 | struct drm_mode_config *mode_config = &dev->mode_config; | |
| 236 | struct drm_connector *connector; | ||
| 237 | |||
| 238 | if (mode_config->num_connector) { | ||
| 239 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
| 240 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 241 | |||
| 242 | if (intel_output->hot_plug) | ||
| 243 | (*intel_output->hot_plug) (intel_output); | ||
| 244 | } | ||
| 245 | } | ||
| 236 | /* Just fire off a uevent and let userspace tell us what to do */ | 246 | /* Just fire off a uevent and let userspace tell us what to do */ |
| 237 | drm_sysfs_hotplug_event(dev); | 247 | drm_sysfs_hotplug_event(dev); |
| 238 | } | 248 | } |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f6237a0b1133..88bf7521405f 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -569,6 +569,19 @@ | |||
| 569 | #define C0DRB3 0x10206 | 569 | #define C0DRB3 0x10206 |
| 570 | #define C1DRB3 0x10606 | 570 | #define C1DRB3 0x10606 |
| 571 | 571 | ||
| 572 | /* Clocking configuration register */ | ||
| 573 | #define CLKCFG 0x10c00 | ||
| 574 | #define CLKCFG_FSB_400 (0 << 0) /* hrawclk 100 */ | ||
| 575 | #define CLKCFG_FSB_533 (1 << 0) /* hrawclk 133 */ | ||
| 576 | #define CLKCFG_FSB_667 (3 << 0) /* hrawclk 166 */ | ||
| 577 | #define CLKCFG_FSB_800 (2 << 0) /* hrawclk 200 */ | ||
| 578 | #define CLKCFG_FSB_1067 (6 << 0) /* hrawclk 266 */ | ||
| 579 | #define CLKCFG_FSB_1333 (7 << 0) /* hrawclk 333 */ | ||
| 580 | /* this is a guess, could be 5 as well */ | ||
| 581 | #define CLKCFG_FSB_1600 (4 << 0) /* hrawclk 400 */ | ||
| 582 | #define CLKCFG_FSB_1600_ALT (5 << 0) /* hrawclk 400 */ | ||
| 583 | #define CLKCFG_FSB_MASK (7 << 0) | ||
| 584 | |||
| 572 | /** GM965 GM45 render standby register */ | 585 | /** GM965 GM45 render standby register */ |
| 573 | #define MCHBAR_RENDER_STANDBY 0x111B8 | 586 | #define MCHBAR_RENDER_STANDBY 0x111B8 |
| 574 | 587 | ||
| @@ -834,9 +847,25 @@ | |||
| 834 | #define HORIZ_INTERP_MASK (3 << 6) | 847 | #define HORIZ_INTERP_MASK (3 << 6) |
| 835 | #define HORIZ_AUTO_SCALE (1 << 5) | 848 | #define HORIZ_AUTO_SCALE (1 << 5) |
| 836 | #define PANEL_8TO6_DITHER_ENABLE (1 << 3) | 849 | #define PANEL_8TO6_DITHER_ENABLE (1 << 3) |
| 850 | #define PFIT_FILTER_FUZZY (0 << 24) | ||
| 851 | #define PFIT_SCALING_AUTO (0 << 26) | ||
| 852 | #define PFIT_SCALING_PROGRAMMED (1 << 26) | ||
| 853 | #define PFIT_SCALING_PILLAR (2 << 26) | ||
| 854 | #define PFIT_SCALING_LETTER (3 << 26) | ||
| 837 | #define PFIT_PGM_RATIOS 0x61234 | 855 | #define PFIT_PGM_RATIOS 0x61234 |
| 838 | #define PFIT_VERT_SCALE_MASK 0xfff00000 | 856 | #define PFIT_VERT_SCALE_MASK 0xfff00000 |
| 839 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 | 857 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 |
| 858 | /* Pre-965 */ | ||
| 859 | #define PFIT_VERT_SCALE_SHIFT 20 | ||
| 860 | #define PFIT_VERT_SCALE_MASK 0xfff00000 | ||
| 861 | #define PFIT_HORIZ_SCALE_SHIFT 4 | ||
| 862 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 | ||
| 863 | /* 965+ */ | ||
| 864 | #define PFIT_VERT_SCALE_SHIFT_965 16 | ||
| 865 | #define PFIT_VERT_SCALE_MASK_965 0x1fff0000 | ||
| 866 | #define PFIT_HORIZ_SCALE_SHIFT_965 0 | ||
| 867 | #define PFIT_HORIZ_SCALE_MASK_965 0x00001fff | ||
| 868 | |||
| 840 | #define PFIT_AUTO_RATIOS 0x61238 | 869 | #define PFIT_AUTO_RATIOS 0x61238 |
| 841 | 870 | ||
| 842 | /* Backlight control */ | 871 | /* Backlight control */ |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a98e2831ed31..8d8e083d14ab 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -322,6 +322,20 @@ int i915_save_state(struct drm_device *dev) | |||
| 322 | dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); | 322 | dev_priv->savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS); |
| 323 | dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); | 323 | dev_priv->savePP_DIVISOR = I915_READ(PP_DIVISOR); |
| 324 | 324 | ||
| 325 | /* Display Port state */ | ||
| 326 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
| 327 | dev_priv->saveDP_B = I915_READ(DP_B); | ||
| 328 | dev_priv->saveDP_C = I915_READ(DP_C); | ||
| 329 | dev_priv->saveDP_D = I915_READ(DP_D); | ||
| 330 | dev_priv->savePIPEA_GMCH_DATA_M = I915_READ(PIPEA_GMCH_DATA_M); | ||
| 331 | dev_priv->savePIPEB_GMCH_DATA_M = I915_READ(PIPEB_GMCH_DATA_M); | ||
| 332 | dev_priv->savePIPEA_GMCH_DATA_N = I915_READ(PIPEA_GMCH_DATA_N); | ||
| 333 | dev_priv->savePIPEB_GMCH_DATA_N = I915_READ(PIPEB_GMCH_DATA_N); | ||
| 334 | dev_priv->savePIPEA_DP_LINK_M = I915_READ(PIPEA_DP_LINK_M); | ||
| 335 | dev_priv->savePIPEB_DP_LINK_M = I915_READ(PIPEB_DP_LINK_M); | ||
| 336 | dev_priv->savePIPEA_DP_LINK_N = I915_READ(PIPEA_DP_LINK_N); | ||
| 337 | dev_priv->savePIPEB_DP_LINK_N = I915_READ(PIPEB_DP_LINK_N); | ||
| 338 | } | ||
| 325 | /* FIXME: save TV & SDVO state */ | 339 | /* FIXME: save TV & SDVO state */ |
| 326 | 340 | ||
| 327 | /* FBC state */ | 341 | /* FBC state */ |
| @@ -404,7 +418,19 @@ int i915_restore_state(struct drm_device *dev) | |||
| 404 | for (i = 0; i < 8; i++) | 418 | for (i = 0; i < 8; i++) |
| 405 | I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); | 419 | I915_WRITE(FENCE_REG_945_8 + (i * 4), dev_priv->saveFENCE[i+8]); |
| 406 | } | 420 | } |
| 407 | 421 | ||
| 422 | /* Display port ratios (must be done before clock is set) */ | ||
| 423 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
| 424 | I915_WRITE(PIPEA_GMCH_DATA_M, dev_priv->savePIPEA_GMCH_DATA_M); | ||
| 425 | I915_WRITE(PIPEB_GMCH_DATA_M, dev_priv->savePIPEB_GMCH_DATA_M); | ||
| 426 | I915_WRITE(PIPEA_GMCH_DATA_N, dev_priv->savePIPEA_GMCH_DATA_N); | ||
| 427 | I915_WRITE(PIPEB_GMCH_DATA_N, dev_priv->savePIPEB_GMCH_DATA_N); | ||
| 428 | I915_WRITE(PIPEA_DP_LINK_M, dev_priv->savePIPEA_DP_LINK_M); | ||
| 429 | I915_WRITE(PIPEB_DP_LINK_M, dev_priv->savePIPEB_DP_LINK_M); | ||
| 430 | I915_WRITE(PIPEA_DP_LINK_N, dev_priv->savePIPEA_DP_LINK_N); | ||
| 431 | I915_WRITE(PIPEB_DP_LINK_N, dev_priv->savePIPEB_DP_LINK_N); | ||
| 432 | } | ||
| 433 | |||
| 408 | /* Pipe & plane A info */ | 434 | /* Pipe & plane A info */ |
| 409 | /* Prime the clock */ | 435 | /* Prime the clock */ |
| 410 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { | 436 | if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) { |
| @@ -518,6 +544,12 @@ int i915_restore_state(struct drm_device *dev) | |||
| 518 | I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); | 544 | I915_WRITE(PP_DIVISOR, dev_priv->savePP_DIVISOR); |
| 519 | I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); | 545 | I915_WRITE(PP_CONTROL, dev_priv->savePP_CONTROL); |
| 520 | 546 | ||
| 547 | /* Display Port state */ | ||
| 548 | if (SUPPORTS_INTEGRATED_DP(dev)) { | ||
| 549 | I915_WRITE(DP_B, dev_priv->saveDP_B); | ||
| 550 | I915_WRITE(DP_C, dev_priv->saveDP_C); | ||
| 551 | I915_WRITE(DP_D, dev_priv->saveDP_D); | ||
| 552 | } | ||
| 521 | /* FIXME: restore TV & SDVO state */ | 553 | /* FIXME: restore TV & SDVO state */ |
| 522 | 554 | ||
| 523 | /* FBC info */ | 555 | /* FBC info */ |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index cdd126d068a7..716409a57244 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -99,9 +99,11 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
| 99 | { | 99 | { |
| 100 | struct bdb_lvds_options *lvds_options; | 100 | struct bdb_lvds_options *lvds_options; |
| 101 | struct bdb_lvds_lfp_data *lvds_lfp_data; | 101 | struct bdb_lvds_lfp_data *lvds_lfp_data; |
| 102 | struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; | ||
| 102 | struct bdb_lvds_lfp_data_entry *entry; | 103 | struct bdb_lvds_lfp_data_entry *entry; |
| 103 | struct lvds_dvo_timing *dvo_timing; | 104 | struct lvds_dvo_timing *dvo_timing; |
| 104 | struct drm_display_mode *panel_fixed_mode; | 105 | struct drm_display_mode *panel_fixed_mode; |
| 106 | int lfp_data_size; | ||
| 105 | 107 | ||
| 106 | /* Defaults if we can't find VBT info */ | 108 | /* Defaults if we can't find VBT info */ |
| 107 | dev_priv->lvds_dither = 0; | 109 | dev_priv->lvds_dither = 0; |
| @@ -119,9 +121,17 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, | |||
| 119 | if (!lvds_lfp_data) | 121 | if (!lvds_lfp_data) |
| 120 | return; | 122 | return; |
| 121 | 123 | ||
| 124 | lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS); | ||
| 125 | if (!lvds_lfp_data_ptrs) | ||
| 126 | return; | ||
| 127 | |||
| 122 | dev_priv->lvds_vbt = 1; | 128 | dev_priv->lvds_vbt = 1; |
| 123 | 129 | ||
| 124 | entry = &lvds_lfp_data->data[lvds_options->panel_type]; | 130 | lfp_data_size = lvds_lfp_data_ptrs->ptr[1].dvo_timing_offset - |
| 131 | lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset; | ||
| 132 | entry = (struct bdb_lvds_lfp_data_entry *) | ||
| 133 | ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * | ||
| 134 | lvds_options->panel_type)); | ||
| 125 | dvo_timing = &entry->dvo_timing; | 135 | dvo_timing = &entry->dvo_timing; |
| 126 | 136 | ||
| 127 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | 137 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3e1c78162119..73e7b9cecac8 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -29,6 +29,7 @@ | |||
| 29 | #include "intel_drv.h" | 29 | #include "intel_drv.h" |
| 30 | #include "i915_drm.h" | 30 | #include "i915_drm.h" |
| 31 | #include "i915_drv.h" | 31 | #include "i915_drv.h" |
| 32 | #include "intel_dp.h" | ||
| 32 | 33 | ||
| 33 | #include "drm_crtc_helper.h" | 34 | #include "drm_crtc_helper.h" |
| 34 | 35 | ||
| @@ -127,19 +128,6 @@ struct intel_limit { | |||
| 127 | #define I9XX_P2_LVDS_FAST 7 | 128 | #define I9XX_P2_LVDS_FAST 7 |
| 128 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 | 129 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 |
| 129 | 130 | ||
| 130 | #define INTEL_LIMIT_I8XX_DVO_DAC 0 | ||
| 131 | #define INTEL_LIMIT_I8XX_LVDS 1 | ||
| 132 | #define INTEL_LIMIT_I9XX_SDVO_DAC 2 | ||
| 133 | #define INTEL_LIMIT_I9XX_LVDS 3 | ||
| 134 | #define INTEL_LIMIT_G4X_SDVO 4 | ||
| 135 | #define INTEL_LIMIT_G4X_HDMI_DAC 5 | ||
| 136 | #define INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS 6 | ||
| 137 | #define INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS 7 | ||
| 138 | #define INTEL_LIMIT_IGD_SDVO_DAC 8 | ||
| 139 | #define INTEL_LIMIT_IGD_LVDS 9 | ||
| 140 | #define INTEL_LIMIT_IGDNG_SDVO_DAC 10 | ||
| 141 | #define INTEL_LIMIT_IGDNG_LVDS 11 | ||
| 142 | |||
| 143 | /*The parameter is for SDVO on G4x platform*/ | 131 | /*The parameter is for SDVO on G4x platform*/ |
| 144 | #define G4X_DOT_SDVO_MIN 25000 | 132 | #define G4X_DOT_SDVO_MIN 25000 |
| 145 | #define G4X_DOT_SDVO_MAX 270000 | 133 | #define G4X_DOT_SDVO_MAX 270000 |
| @@ -218,6 +206,25 @@ struct intel_limit { | |||
| 218 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 | 206 | #define G4X_P2_DUAL_CHANNEL_LVDS_FAST 7 |
| 219 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 | 207 | #define G4X_P2_DUAL_CHANNEL_LVDS_LIMIT 0 |
| 220 | 208 | ||
| 209 | /*The parameter is for DISPLAY PORT on G4x platform*/ | ||
| 210 | #define G4X_DOT_DISPLAY_PORT_MIN 161670 | ||
| 211 | #define G4X_DOT_DISPLAY_PORT_MAX 227000 | ||
| 212 | #define G4X_N_DISPLAY_PORT_MIN 1 | ||
| 213 | #define G4X_N_DISPLAY_PORT_MAX 2 | ||
| 214 | #define G4X_M_DISPLAY_PORT_MIN 97 | ||
| 215 | #define G4X_M_DISPLAY_PORT_MAX 108 | ||
| 216 | #define G4X_M1_DISPLAY_PORT_MIN 0x10 | ||
| 217 | #define G4X_M1_DISPLAY_PORT_MAX 0x12 | ||
| 218 | #define G4X_M2_DISPLAY_PORT_MIN 0x05 | ||
| 219 | #define G4X_M2_DISPLAY_PORT_MAX 0x06 | ||
| 220 | #define G4X_P_DISPLAY_PORT_MIN 10 | ||
| 221 | #define G4X_P_DISPLAY_PORT_MAX 20 | ||
| 222 | #define G4X_P1_DISPLAY_PORT_MIN 1 | ||
| 223 | #define G4X_P1_DISPLAY_PORT_MAX 2 | ||
| 224 | #define G4X_P2_DISPLAY_PORT_SLOW 10 | ||
| 225 | #define G4X_P2_DISPLAY_PORT_FAST 10 | ||
| 226 | #define G4X_P2_DISPLAY_PORT_LIMIT 0 | ||
| 227 | |||
| 221 | /* IGDNG */ | 228 | /* IGDNG */ |
| 222 | /* as we calculate clock using (register_value + 2) for | 229 | /* as we calculate clock using (register_value + 2) for |
| 223 | N/M1/M2, so here the range value for them is (actual_value-2). | 230 | N/M1/M2, so here the range value for them is (actual_value-2). |
| @@ -256,8 +263,11 @@ static bool | |||
| 256 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, | 263 | intel_igdng_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, |
| 257 | int target, int refclk, intel_clock_t *best_clock); | 264 | int target, int refclk, intel_clock_t *best_clock); |
| 258 | 265 | ||
| 259 | static const intel_limit_t intel_limits[] = { | 266 | static bool |
| 260 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ | 267 | intel_find_pll_g4x_dp(const intel_limit_t *, struct drm_crtc *crtc, |
| 268 | int target, int refclk, intel_clock_t *best_clock); | ||
| 269 | |||
| 270 | static const intel_limit_t intel_limits_i8xx_dvo = { | ||
| 261 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 271 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
| 262 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 272 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
| 263 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 273 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
| @@ -269,8 +279,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 269 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 279 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
| 270 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, | 280 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST }, |
| 271 | .find_pll = intel_find_best_PLL, | 281 | .find_pll = intel_find_best_PLL, |
| 272 | }, | 282 | }; |
| 273 | { /* INTEL_LIMIT_I8XX_LVDS */ | 283 | |
| 284 | static const intel_limit_t intel_limits_i8xx_lvds = { | ||
| 274 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, | 285 | .dot = { .min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX }, |
| 275 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, | 286 | .vco = { .min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX }, |
| 276 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, | 287 | .n = { .min = I8XX_N_MIN, .max = I8XX_N_MAX }, |
| @@ -282,8 +293,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 282 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, | 293 | .p2 = { .dot_limit = I8XX_P2_SLOW_LIMIT, |
| 283 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, | 294 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST }, |
| 284 | .find_pll = intel_find_best_PLL, | 295 | .find_pll = intel_find_best_PLL, |
| 285 | }, | 296 | }; |
| 286 | { /* INTEL_LIMIT_I9XX_SDVO_DAC */ | 297 | |
| 298 | static const intel_limit_t intel_limits_i9xx_sdvo = { | ||
| 287 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 299 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
| 288 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 300 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
| 289 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 301 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
| @@ -295,8 +307,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 295 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 307 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
| 296 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 308 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
| 297 | .find_pll = intel_find_best_PLL, | 309 | .find_pll = intel_find_best_PLL, |
| 298 | }, | 310 | }; |
| 299 | { /* INTEL_LIMIT_I9XX_LVDS */ | 311 | |
| 312 | static const intel_limit_t intel_limits_i9xx_lvds = { | ||
| 300 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 313 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
| 301 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, | 314 | .vco = { .min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX }, |
| 302 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, | 315 | .n = { .min = I9XX_N_MIN, .max = I9XX_N_MAX }, |
| @@ -311,9 +324,10 @@ static const intel_limit_t intel_limits[] = { | |||
| 311 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 324 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
| 312 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, | 325 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST }, |
| 313 | .find_pll = intel_find_best_PLL, | 326 | .find_pll = intel_find_best_PLL, |
| 314 | }, | 327 | }; |
| 328 | |||
| 315 | /* below parameter and function is for G4X Chipset Family*/ | 329 | /* below parameter and function is for G4X Chipset Family*/ |
| 316 | { /* INTEL_LIMIT_G4X_SDVO */ | 330 | static const intel_limit_t intel_limits_g4x_sdvo = { |
| 317 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, | 331 | .dot = { .min = G4X_DOT_SDVO_MIN, .max = G4X_DOT_SDVO_MAX }, |
| 318 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 332 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
| 319 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, | 333 | .n = { .min = G4X_N_SDVO_MIN, .max = G4X_N_SDVO_MAX }, |
| @@ -327,8 +341,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 327 | .p2_fast = G4X_P2_SDVO_FAST | 341 | .p2_fast = G4X_P2_SDVO_FAST |
| 328 | }, | 342 | }, |
| 329 | .find_pll = intel_g4x_find_best_PLL, | 343 | .find_pll = intel_g4x_find_best_PLL, |
| 330 | }, | 344 | }; |
| 331 | { /* INTEL_LIMIT_G4X_HDMI_DAC */ | 345 | |
| 346 | static const intel_limit_t intel_limits_g4x_hdmi = { | ||
| 332 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, | 347 | .dot = { .min = G4X_DOT_HDMI_DAC_MIN, .max = G4X_DOT_HDMI_DAC_MAX }, |
| 333 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, | 348 | .vco = { .min = G4X_VCO_MIN, .max = G4X_VCO_MAX}, |
| 334 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, | 349 | .n = { .min = G4X_N_HDMI_DAC_MIN, .max = G4X_N_HDMI_DAC_MAX }, |
| @@ -342,8 +357,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 342 | .p2_fast = G4X_P2_HDMI_DAC_FAST | 357 | .p2_fast = G4X_P2_HDMI_DAC_FAST |
| 343 | }, | 358 | }, |
| 344 | .find_pll = intel_g4x_find_best_PLL, | 359 | .find_pll = intel_g4x_find_best_PLL, |
| 345 | }, | 360 | }; |
| 346 | { /* INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS */ | 361 | |
| 362 | static const intel_limit_t intel_limits_g4x_single_channel_lvds = { | ||
| 347 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, | 363 | .dot = { .min = G4X_DOT_SINGLE_CHANNEL_LVDS_MIN, |
| 348 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, | 364 | .max = G4X_DOT_SINGLE_CHANNEL_LVDS_MAX }, |
| 349 | .vco = { .min = G4X_VCO_MIN, | 365 | .vco = { .min = G4X_VCO_MIN, |
| @@ -365,8 +381,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 365 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST | 381 | .p2_fast = G4X_P2_SINGLE_CHANNEL_LVDS_FAST |
| 366 | }, | 382 | }, |
| 367 | .find_pll = intel_g4x_find_best_PLL, | 383 | .find_pll = intel_g4x_find_best_PLL, |
| 368 | }, | 384 | }; |
| 369 | { /* INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS */ | 385 | |
| 386 | static const intel_limit_t intel_limits_g4x_dual_channel_lvds = { | ||
| 370 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, | 387 | .dot = { .min = G4X_DOT_DUAL_CHANNEL_LVDS_MIN, |
| 371 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, | 388 | .max = G4X_DOT_DUAL_CHANNEL_LVDS_MAX }, |
| 372 | .vco = { .min = G4X_VCO_MIN, | 389 | .vco = { .min = G4X_VCO_MIN, |
| @@ -388,8 +405,32 @@ static const intel_limit_t intel_limits[] = { | |||
| 388 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST | 405 | .p2_fast = G4X_P2_DUAL_CHANNEL_LVDS_FAST |
| 389 | }, | 406 | }, |
| 390 | .find_pll = intel_g4x_find_best_PLL, | 407 | .find_pll = intel_g4x_find_best_PLL, |
| 391 | }, | 408 | }; |
| 392 | { /* INTEL_LIMIT_IGD_SDVO */ | 409 | |
| 410 | static const intel_limit_t intel_limits_g4x_display_port = { | ||
| 411 | .dot = { .min = G4X_DOT_DISPLAY_PORT_MIN, | ||
| 412 | .max = G4X_DOT_DISPLAY_PORT_MAX }, | ||
| 413 | .vco = { .min = G4X_VCO_MIN, | ||
| 414 | .max = G4X_VCO_MAX}, | ||
| 415 | .n = { .min = G4X_N_DISPLAY_PORT_MIN, | ||
| 416 | .max = G4X_N_DISPLAY_PORT_MAX }, | ||
| 417 | .m = { .min = G4X_M_DISPLAY_PORT_MIN, | ||
| 418 | .max = G4X_M_DISPLAY_PORT_MAX }, | ||
| 419 | .m1 = { .min = G4X_M1_DISPLAY_PORT_MIN, | ||
| 420 | .max = G4X_M1_DISPLAY_PORT_MAX }, | ||
| 421 | .m2 = { .min = G4X_M2_DISPLAY_PORT_MIN, | ||
| 422 | .max = G4X_M2_DISPLAY_PORT_MAX }, | ||
| 423 | .p = { .min = G4X_P_DISPLAY_PORT_MIN, | ||
| 424 | .max = G4X_P_DISPLAY_PORT_MAX }, | ||
| 425 | .p1 = { .min = G4X_P1_DISPLAY_PORT_MIN, | ||
| 426 | .max = G4X_P1_DISPLAY_PORT_MAX}, | ||
| 427 | .p2 = { .dot_limit = G4X_P2_DISPLAY_PORT_LIMIT, | ||
| 428 | .p2_slow = G4X_P2_DISPLAY_PORT_SLOW, | ||
| 429 | .p2_fast = G4X_P2_DISPLAY_PORT_FAST }, | ||
| 430 | .find_pll = intel_find_pll_g4x_dp, | ||
| 431 | }; | ||
| 432 | |||
| 433 | static const intel_limit_t intel_limits_igd_sdvo = { | ||
| 393 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, | 434 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, |
| 394 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 435 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
| 395 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 436 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
| @@ -401,8 +442,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 401 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | 442 | .p2 = { .dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, |
| 402 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, | 443 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = I9XX_P2_SDVO_DAC_FAST }, |
| 403 | .find_pll = intel_find_best_PLL, | 444 | .find_pll = intel_find_best_PLL, |
| 404 | }, | 445 | }; |
| 405 | { /* INTEL_LIMIT_IGD_LVDS */ | 446 | |
| 447 | static const intel_limit_t intel_limits_igd_lvds = { | ||
| 406 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, | 448 | .dot = { .min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX }, |
| 407 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, | 449 | .vco = { .min = IGD_VCO_MIN, .max = IGD_VCO_MAX }, |
| 408 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, | 450 | .n = { .min = IGD_N_MIN, .max = IGD_N_MAX }, |
| @@ -415,8 +457,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 415 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | 457 | .p2 = { .dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, |
| 416 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, | 458 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_SLOW }, |
| 417 | .find_pll = intel_find_best_PLL, | 459 | .find_pll = intel_find_best_PLL, |
| 418 | }, | 460 | }; |
| 419 | { /* INTEL_LIMIT_IGDNG_SDVO_DAC */ | 461 | |
| 462 | static const intel_limit_t intel_limits_igdng_sdvo = { | ||
| 420 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 463 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
| 421 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 464 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
| 422 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 465 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
| @@ -429,8 +472,9 @@ static const intel_limit_t intel_limits[] = { | |||
| 429 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, | 472 | .p2_slow = IGDNG_P2_SDVO_DAC_SLOW, |
| 430 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, | 473 | .p2_fast = IGDNG_P2_SDVO_DAC_FAST }, |
| 431 | .find_pll = intel_igdng_find_best_PLL, | 474 | .find_pll = intel_igdng_find_best_PLL, |
| 432 | }, | 475 | }; |
| 433 | { /* INTEL_LIMIT_IGDNG_LVDS */ | 476 | |
| 477 | static const intel_limit_t intel_limits_igdng_lvds = { | ||
| 434 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, | 478 | .dot = { .min = IGDNG_DOT_MIN, .max = IGDNG_DOT_MAX }, |
| 435 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, | 479 | .vco = { .min = IGDNG_VCO_MIN, .max = IGDNG_VCO_MAX }, |
| 436 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, | 480 | .n = { .min = IGDNG_N_MIN, .max = IGDNG_N_MAX }, |
| @@ -443,16 +487,15 @@ static const intel_limit_t intel_limits[] = { | |||
| 443 | .p2_slow = IGDNG_P2_LVDS_SLOW, | 487 | .p2_slow = IGDNG_P2_LVDS_SLOW, |
| 444 | .p2_fast = IGDNG_P2_LVDS_FAST }, | 488 | .p2_fast = IGDNG_P2_LVDS_FAST }, |
| 445 | .find_pll = intel_igdng_find_best_PLL, | 489 | .find_pll = intel_igdng_find_best_PLL, |
| 446 | }, | ||
| 447 | }; | 490 | }; |
| 448 | 491 | ||
| 449 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) | 492 | static const intel_limit_t *intel_igdng_limit(struct drm_crtc *crtc) |
| 450 | { | 493 | { |
| 451 | const intel_limit_t *limit; | 494 | const intel_limit_t *limit; |
| 452 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 495 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 453 | limit = &intel_limits[INTEL_LIMIT_IGDNG_LVDS]; | 496 | limit = &intel_limits_igdng_lvds; |
| 454 | else | 497 | else |
| 455 | limit = &intel_limits[INTEL_LIMIT_IGDNG_SDVO_DAC]; | 498 | limit = &intel_limits_igdng_sdvo; |
| 456 | 499 | ||
| 457 | return limit; | 500 | return limit; |
| 458 | } | 501 | } |
| @@ -467,19 +510,19 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) | |||
| 467 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | 510 | if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == |
| 468 | LVDS_CLKB_POWER_UP) | 511 | LVDS_CLKB_POWER_UP) |
| 469 | /* LVDS with dual channel */ | 512 | /* LVDS with dual channel */ |
| 470 | limit = &intel_limits | 513 | limit = &intel_limits_g4x_dual_channel_lvds; |
| 471 | [INTEL_LIMIT_G4X_DUAL_CHANNEL_LVDS]; | ||
| 472 | else | 514 | else |
| 473 | /* LVDS with dual channel */ | 515 | /* LVDS with dual channel */ |
| 474 | limit = &intel_limits | 516 | limit = &intel_limits_g4x_single_channel_lvds; |
| 475 | [INTEL_LIMIT_G4X_SINGLE_CHANNEL_LVDS]; | ||
| 476 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || | 517 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI) || |
| 477 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { | 518 | intel_pipe_has_type(crtc, INTEL_OUTPUT_ANALOG)) { |
| 478 | limit = &intel_limits[INTEL_LIMIT_G4X_HDMI_DAC]; | 519 | limit = &intel_limits_g4x_hdmi; |
| 479 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { | 520 | } else if (intel_pipe_has_type(crtc, INTEL_OUTPUT_SDVO)) { |
| 480 | limit = &intel_limits[INTEL_LIMIT_G4X_SDVO]; | 521 | limit = &intel_limits_g4x_sdvo; |
| 522 | } else if (intel_pipe_has_type (crtc, INTEL_OUTPUT_DISPLAYPORT)) { | ||
| 523 | limit = &intel_limits_g4x_display_port; | ||
| 481 | } else /* The option is for other outputs */ | 524 | } else /* The option is for other outputs */ |
| 482 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 525 | limit = &intel_limits_i9xx_sdvo; |
| 483 | 526 | ||
| 484 | return limit; | 527 | return limit; |
| 485 | } | 528 | } |
| @@ -495,19 +538,19 @@ static const intel_limit_t *intel_limit(struct drm_crtc *crtc) | |||
| 495 | limit = intel_g4x_limit(crtc); | 538 | limit = intel_g4x_limit(crtc); |
| 496 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { | 539 | } else if (IS_I9XX(dev) && !IS_IGD(dev)) { |
| 497 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 540 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 498 | limit = &intel_limits[INTEL_LIMIT_I9XX_LVDS]; | 541 | limit = &intel_limits_i9xx_lvds; |
| 499 | else | 542 | else |
| 500 | limit = &intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | 543 | limit = &intel_limits_i9xx_sdvo; |
| 501 | } else if (IS_IGD(dev)) { | 544 | } else if (IS_IGD(dev)) { |
| 502 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 545 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 503 | limit = &intel_limits[INTEL_LIMIT_IGD_LVDS]; | 546 | limit = &intel_limits_igd_lvds; |
| 504 | else | 547 | else |
| 505 | limit = &intel_limits[INTEL_LIMIT_IGD_SDVO_DAC]; | 548 | limit = &intel_limits_igd_sdvo; |
| 506 | } else { | 549 | } else { |
| 507 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | 550 | if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) |
| 508 | limit = &intel_limits[INTEL_LIMIT_I8XX_LVDS]; | 551 | limit = &intel_limits_i8xx_lvds; |
| 509 | else | 552 | else |
| 510 | limit = &intel_limits[INTEL_LIMIT_I8XX_DVO_DAC]; | 553 | limit = &intel_limits_i8xx_dvo; |
| 511 | } | 554 | } |
| 512 | return limit; | 555 | return limit; |
| 513 | } | 556 | } |
| @@ -764,6 +807,35 @@ out: | |||
| 764 | return found; | 807 | return found; |
| 765 | } | 808 | } |
| 766 | 809 | ||
| 810 | /* DisplayPort has only two frequencies, 162MHz and 270MHz */ | ||
| 811 | static bool | ||
| 812 | intel_find_pll_g4x_dp(const intel_limit_t *limit, struct drm_crtc *crtc, | ||
| 813 | int target, int refclk, intel_clock_t *best_clock) | ||
| 814 | { | ||
| 815 | intel_clock_t clock; | ||
| 816 | if (target < 200000) { | ||
| 817 | clock.dot = 161670; | ||
| 818 | clock.p = 20; | ||
| 819 | clock.p1 = 2; | ||
| 820 | clock.p2 = 10; | ||
| 821 | clock.n = 0x01; | ||
| 822 | clock.m = 97; | ||
| 823 | clock.m1 = 0x10; | ||
| 824 | clock.m2 = 0x05; | ||
| 825 | } else { | ||
| 826 | clock.dot = 270000; | ||
| 827 | clock.p = 10; | ||
| 828 | clock.p1 = 1; | ||
| 829 | clock.p2 = 10; | ||
| 830 | clock.n = 0x02; | ||
| 831 | clock.m = 108; | ||
| 832 | clock.m1 = 0x12; | ||
| 833 | clock.m2 = 0x06; | ||
| 834 | } | ||
| 835 | memcpy(best_clock, &clock, sizeof(intel_clock_t)); | ||
| 836 | return true; | ||
| 837 | } | ||
| 838 | |||
| 767 | void | 839 | void |
| 768 | intel_wait_for_vblank(struct drm_device *dev) | 840 | intel_wait_for_vblank(struct drm_device *dev) |
| 769 | { | 841 | { |
| @@ -1541,7 +1613,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1541 | intel_clock_t clock; | 1613 | intel_clock_t clock; |
| 1542 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | 1614 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; |
| 1543 | bool ok, is_sdvo = false, is_dvo = false; | 1615 | bool ok, is_sdvo = false, is_dvo = false; |
| 1544 | bool is_crt = false, is_lvds = false, is_tv = false; | 1616 | bool is_crt = false, is_lvds = false, is_tv = false, is_dp = false; |
| 1545 | struct drm_mode_config *mode_config = &dev->mode_config; | 1617 | struct drm_mode_config *mode_config = &dev->mode_config; |
| 1546 | struct drm_connector *connector; | 1618 | struct drm_connector *connector; |
| 1547 | const intel_limit_t *limit; | 1619 | const intel_limit_t *limit; |
| @@ -1585,6 +1657,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1585 | case INTEL_OUTPUT_ANALOG: | 1657 | case INTEL_OUTPUT_ANALOG: |
| 1586 | is_crt = true; | 1658 | is_crt = true; |
| 1587 | break; | 1659 | break; |
| 1660 | case INTEL_OUTPUT_DISPLAYPORT: | ||
| 1661 | is_dp = true; | ||
| 1662 | break; | ||
| 1588 | } | 1663 | } |
| 1589 | 1664 | ||
| 1590 | num_outputs++; | 1665 | num_outputs++; |
| @@ -1600,6 +1675,7 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1600 | } else { | 1675 | } else { |
| 1601 | refclk = 48000; | 1676 | refclk = 48000; |
| 1602 | } | 1677 | } |
| 1678 | |||
| 1603 | 1679 | ||
| 1604 | /* | 1680 | /* |
| 1605 | * Returns a set of divisors for the desired target clock with the given | 1681 | * Returns a set of divisors for the desired target clock with the given |
| @@ -1662,6 +1738,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1662 | else if (IS_IGDNG(dev)) | 1738 | else if (IS_IGDNG(dev)) |
| 1663 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; | 1739 | dpll |= (sdvo_pixel_multiply - 1) << PLL_REF_SDVO_HDMI_MULTIPLIER_SHIFT; |
| 1664 | } | 1740 | } |
| 1741 | if (is_dp) | ||
| 1742 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
| 1665 | 1743 | ||
| 1666 | /* compute bitmask from p1 value */ | 1744 | /* compute bitmask from p1 value */ |
| 1667 | if (IS_IGD(dev)) | 1745 | if (IS_IGD(dev)) |
| @@ -1809,6 +1887,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
| 1809 | I915_WRITE(lvds_reg, lvds); | 1887 | I915_WRITE(lvds_reg, lvds); |
| 1810 | I915_READ(lvds_reg); | 1888 | I915_READ(lvds_reg); |
| 1811 | } | 1889 | } |
| 1890 | if (is_dp) | ||
| 1891 | intel_dp_set_m_n(crtc, mode, adjusted_mode); | ||
| 1812 | 1892 | ||
| 1813 | I915_WRITE(fp_reg, fp); | 1893 | I915_WRITE(fp_reg, fp); |
| 1814 | I915_WRITE(dpll_reg, dpll); | 1894 | I915_WRITE(dpll_reg, dpll); |
| @@ -2475,6 +2555,8 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 2475 | found = intel_sdvo_init(dev, SDVOB); | 2555 | found = intel_sdvo_init(dev, SDVOB); |
| 2476 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2556 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
| 2477 | intel_hdmi_init(dev, SDVOB); | 2557 | intel_hdmi_init(dev, SDVOB); |
| 2558 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
| 2559 | intel_dp_init(dev, DP_B); | ||
| 2478 | } | 2560 | } |
| 2479 | 2561 | ||
| 2480 | /* Before G4X SDVOC doesn't have its own detect register */ | 2562 | /* Before G4X SDVOC doesn't have its own detect register */ |
| @@ -2487,7 +2569,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 2487 | found = intel_sdvo_init(dev, SDVOC); | 2569 | found = intel_sdvo_init(dev, SDVOC); |
| 2488 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) | 2570 | if (!found && SUPPORTS_INTEGRATED_HDMI(dev)) |
| 2489 | intel_hdmi_init(dev, SDVOC); | 2571 | intel_hdmi_init(dev, SDVOC); |
| 2572 | if (!found && SUPPORTS_INTEGRATED_DP(dev)) | ||
| 2573 | intel_dp_init(dev, DP_C); | ||
| 2490 | } | 2574 | } |
| 2575 | if (SUPPORTS_INTEGRATED_DP(dev) && (I915_READ(DP_D) & DP_DETECTED)) | ||
| 2576 | intel_dp_init(dev, DP_D); | ||
| 2491 | } else | 2577 | } else |
| 2492 | intel_dvo_init(dev); | 2578 | intel_dvo_init(dev); |
| 2493 | 2579 | ||
| @@ -2530,6 +2616,11 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 2530 | (1 << 1)); | 2616 | (1 << 1)); |
| 2531 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); | 2617 | clone_mask = (1 << INTEL_OUTPUT_TVOUT); |
| 2532 | break; | 2618 | break; |
| 2619 | case INTEL_OUTPUT_DISPLAYPORT: | ||
| 2620 | crtc_mask = ((1 << 0) | | ||
| 2621 | (1 << 1)); | ||
| 2622 | clone_mask = (1 << INTEL_OUTPUT_DISPLAYPORT); | ||
| 2623 | break; | ||
| 2533 | } | 2624 | } |
| 2534 | encoder->possible_crtcs = crtc_mask; | 2625 | encoder->possible_crtcs = crtc_mask; |
| 2535 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); | 2626 | encoder->possible_clones = intel_connector_clones(dev, clone_mask); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c new file mode 100644 index 000000000000..8f8d37d5663a --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -0,0 +1,1153 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Intel Corporation | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 21 | * IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Keith Packard <keithp@keithp.com> | ||
| 25 | * | ||
| 26 | */ | ||
| 27 | |||
| 28 | #include <linux/i2c.h> | ||
| 29 | #include "drmP.h" | ||
| 30 | #include "drm.h" | ||
| 31 | #include "drm_crtc.h" | ||
| 32 | #include "drm_crtc_helper.h" | ||
| 33 | #include "intel_drv.h" | ||
| 34 | #include "i915_drm.h" | ||
| 35 | #include "i915_drv.h" | ||
| 36 | #include "intel_dp.h" | ||
| 37 | |||
| 38 | #define DP_LINK_STATUS_SIZE 6 | ||
| 39 | #define DP_LINK_CHECK_TIMEOUT (10 * 1000) | ||
| 40 | |||
| 41 | #define DP_LINK_CONFIGURATION_SIZE 9 | ||
| 42 | |||
| 43 | struct intel_dp_priv { | ||
| 44 | uint32_t output_reg; | ||
| 45 | uint32_t DP; | ||
| 46 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; | ||
| 47 | uint32_t save_DP; | ||
| 48 | uint8_t save_link_configuration[DP_LINK_CONFIGURATION_SIZE]; | ||
| 49 | bool has_audio; | ||
| 50 | int dpms_mode; | ||
| 51 | uint8_t link_bw; | ||
| 52 | uint8_t lane_count; | ||
| 53 | uint8_t dpcd[4]; | ||
| 54 | struct intel_output *intel_output; | ||
| 55 | struct i2c_adapter adapter; | ||
| 56 | struct i2c_algo_dp_aux_data algo; | ||
| 57 | }; | ||
| 58 | |||
| 59 | static void | ||
| 60 | intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, | ||
| 61 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]); | ||
| 62 | |||
| 63 | static void | ||
| 64 | intel_dp_link_down(struct intel_output *intel_output, uint32_t DP); | ||
| 65 | |||
| 66 | static int | ||
| 67 | intel_dp_max_lane_count(struct intel_output *intel_output) | ||
| 68 | { | ||
| 69 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 70 | int max_lane_count = 4; | ||
| 71 | |||
| 72 | if (dp_priv->dpcd[0] >= 0x11) { | ||
| 73 | max_lane_count = dp_priv->dpcd[2] & 0x1f; | ||
| 74 | switch (max_lane_count) { | ||
| 75 | case 1: case 2: case 4: | ||
| 76 | break; | ||
| 77 | default: | ||
| 78 | max_lane_count = 4; | ||
| 79 | } | ||
| 80 | } | ||
| 81 | return max_lane_count; | ||
| 82 | } | ||
| 83 | |||
| 84 | static int | ||
| 85 | intel_dp_max_link_bw(struct intel_output *intel_output) | ||
| 86 | { | ||
| 87 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 88 | int max_link_bw = dp_priv->dpcd[1]; | ||
| 89 | |||
| 90 | switch (max_link_bw) { | ||
| 91 | case DP_LINK_BW_1_62: | ||
| 92 | case DP_LINK_BW_2_7: | ||
| 93 | break; | ||
| 94 | default: | ||
| 95 | max_link_bw = DP_LINK_BW_1_62; | ||
| 96 | break; | ||
| 97 | } | ||
| 98 | return max_link_bw; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int | ||
| 102 | intel_dp_link_clock(uint8_t link_bw) | ||
| 103 | { | ||
| 104 | if (link_bw == DP_LINK_BW_2_7) | ||
| 105 | return 270000; | ||
| 106 | else | ||
| 107 | return 162000; | ||
| 108 | } | ||
| 109 | |||
| 110 | /* I think this is a fiction */ | ||
| 111 | static int | ||
| 112 | intel_dp_link_required(int pixel_clock) | ||
| 113 | { | ||
| 114 | return pixel_clock * 3; | ||
| 115 | } | ||
| 116 | |||
| 117 | static int | ||
| 118 | intel_dp_mode_valid(struct drm_connector *connector, | ||
| 119 | struct drm_display_mode *mode) | ||
| 120 | { | ||
| 121 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 122 | int max_link_clock = intel_dp_link_clock(intel_dp_max_link_bw(intel_output)); | ||
| 123 | int max_lanes = intel_dp_max_lane_count(intel_output); | ||
| 124 | |||
| 125 | if (intel_dp_link_required(mode->clock) > max_link_clock * max_lanes) | ||
| 126 | return MODE_CLOCK_HIGH; | ||
| 127 | |||
| 128 | if (mode->clock < 10000) | ||
| 129 | return MODE_CLOCK_LOW; | ||
| 130 | |||
| 131 | return MODE_OK; | ||
| 132 | } | ||
| 133 | |||
| 134 | static uint32_t | ||
| 135 | pack_aux(uint8_t *src, int src_bytes) | ||
| 136 | { | ||
| 137 | int i; | ||
| 138 | uint32_t v = 0; | ||
| 139 | |||
| 140 | if (src_bytes > 4) | ||
| 141 | src_bytes = 4; | ||
| 142 | for (i = 0; i < src_bytes; i++) | ||
| 143 | v |= ((uint32_t) src[i]) << ((3-i) * 8); | ||
| 144 | return v; | ||
| 145 | } | ||
| 146 | |||
| 147 | static void | ||
| 148 | unpack_aux(uint32_t src, uint8_t *dst, int dst_bytes) | ||
| 149 | { | ||
| 150 | int i; | ||
| 151 | if (dst_bytes > 4) | ||
| 152 | dst_bytes = 4; | ||
| 153 | for (i = 0; i < dst_bytes; i++) | ||
| 154 | dst[i] = src >> ((3-i) * 8); | ||
| 155 | } | ||
| 156 | |||
| 157 | /* hrawclock is 1/4 the FSB frequency */ | ||
| 158 | static int | ||
| 159 | intel_hrawclk(struct drm_device *dev) | ||
| 160 | { | ||
| 161 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 162 | uint32_t clkcfg; | ||
| 163 | |||
| 164 | clkcfg = I915_READ(CLKCFG); | ||
| 165 | switch (clkcfg & CLKCFG_FSB_MASK) { | ||
| 166 | case CLKCFG_FSB_400: | ||
| 167 | return 100; | ||
| 168 | case CLKCFG_FSB_533: | ||
| 169 | return 133; | ||
| 170 | case CLKCFG_FSB_667: | ||
| 171 | return 166; | ||
| 172 | case CLKCFG_FSB_800: | ||
| 173 | return 200; | ||
| 174 | case CLKCFG_FSB_1067: | ||
| 175 | return 266; | ||
| 176 | case CLKCFG_FSB_1333: | ||
| 177 | return 333; | ||
| 178 | /* these two are just a guess; one of them might be right */ | ||
| 179 | case CLKCFG_FSB_1600: | ||
| 180 | case CLKCFG_FSB_1600_ALT: | ||
| 181 | return 400; | ||
| 182 | default: | ||
| 183 | return 133; | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 187 | static int | ||
| 188 | intel_dp_aux_ch(struct intel_output *intel_output, | ||
| 189 | uint8_t *send, int send_bytes, | ||
| 190 | uint8_t *recv, int recv_size) | ||
| 191 | { | ||
| 192 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 193 | uint32_t output_reg = dp_priv->output_reg; | ||
| 194 | struct drm_device *dev = intel_output->base.dev; | ||
| 195 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 196 | uint32_t ch_ctl = output_reg + 0x10; | ||
| 197 | uint32_t ch_data = ch_ctl + 4; | ||
| 198 | int i; | ||
| 199 | int recv_bytes; | ||
| 200 | uint32_t ctl; | ||
| 201 | uint32_t status; | ||
| 202 | uint32_t aux_clock_divider; | ||
| 203 | int try; | ||
| 204 | |||
| 205 | /* The clock divider is based off the hrawclk, | ||
| 206 | * and would like to run at 2MHz. So, take the | ||
| 207 | * hrawclk value and divide by 2 and use that | ||
| 208 | */ | ||
| 209 | aux_clock_divider = intel_hrawclk(dev) / 2; | ||
| 210 | /* Must try at least 3 times according to DP spec */ | ||
| 211 | for (try = 0; try < 5; try++) { | ||
| 212 | /* Load the send data into the aux channel data registers */ | ||
| 213 | for (i = 0; i < send_bytes; i += 4) { | ||
| 214 | uint32_t d = pack_aux(send + i, send_bytes - i);; | ||
| 215 | |||
| 216 | I915_WRITE(ch_data + i, d); | ||
| 217 | } | ||
| 218 | |||
| 219 | ctl = (DP_AUX_CH_CTL_SEND_BUSY | | ||
| 220 | DP_AUX_CH_CTL_TIME_OUT_400us | | ||
| 221 | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | | ||
| 222 | (5 << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) | | ||
| 223 | (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT) | | ||
| 224 | DP_AUX_CH_CTL_DONE | | ||
| 225 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
| 226 | DP_AUX_CH_CTL_RECEIVE_ERROR); | ||
| 227 | |||
| 228 | /* Send the command and wait for it to complete */ | ||
| 229 | I915_WRITE(ch_ctl, ctl); | ||
| 230 | (void) I915_READ(ch_ctl); | ||
| 231 | for (;;) { | ||
| 232 | udelay(100); | ||
| 233 | status = I915_READ(ch_ctl); | ||
| 234 | if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0) | ||
| 235 | break; | ||
| 236 | } | ||
| 237 | |||
| 238 | /* Clear done status and any errors */ | ||
| 239 | I915_WRITE(ch_ctl, (ctl | | ||
| 240 | DP_AUX_CH_CTL_DONE | | ||
| 241 | DP_AUX_CH_CTL_TIME_OUT_ERROR | | ||
| 242 | DP_AUX_CH_CTL_RECEIVE_ERROR)); | ||
| 243 | (void) I915_READ(ch_ctl); | ||
| 244 | if ((status & DP_AUX_CH_CTL_TIME_OUT_ERROR) == 0) | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | |||
| 248 | if ((status & DP_AUX_CH_CTL_DONE) == 0) { | ||
| 249 | printk(KERN_ERR "dp_aux_ch not done status 0x%08x\n", status); | ||
| 250 | return -EBUSY; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* Check for timeout or receive error. | ||
| 254 | * Timeouts occur when the sink is not connected | ||
| 255 | */ | ||
| 256 | if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) { | ||
| 257 | printk(KERN_ERR "dp_aux_ch receive error status 0x%08x\n", status); | ||
| 258 | return -EIO; | ||
| 259 | } | ||
| 260 | if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) { | ||
| 261 | printk(KERN_ERR "dp_aux_ch timeout status 0x%08x\n", status); | ||
| 262 | return -ETIMEDOUT; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* Unload any bytes sent back from the other side */ | ||
| 266 | recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> | ||
| 267 | DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT); | ||
| 268 | |||
| 269 | if (recv_bytes > recv_size) | ||
| 270 | recv_bytes = recv_size; | ||
| 271 | |||
| 272 | for (i = 0; i < recv_bytes; i += 4) { | ||
| 273 | uint32_t d = I915_READ(ch_data + i); | ||
| 274 | |||
| 275 | unpack_aux(d, recv + i, recv_bytes - i); | ||
| 276 | } | ||
| 277 | |||
| 278 | return recv_bytes; | ||
| 279 | } | ||
| 280 | |||
| 281 | /* Write data to the aux channel in native mode */ | ||
| 282 | static int | ||
| 283 | intel_dp_aux_native_write(struct intel_output *intel_output, | ||
| 284 | uint16_t address, uint8_t *send, int send_bytes) | ||
| 285 | { | ||
| 286 | int ret; | ||
| 287 | uint8_t msg[20]; | ||
| 288 | int msg_bytes; | ||
| 289 | uint8_t ack; | ||
| 290 | |||
| 291 | if (send_bytes > 16) | ||
| 292 | return -1; | ||
| 293 | msg[0] = AUX_NATIVE_WRITE << 4; | ||
| 294 | msg[1] = address >> 8; | ||
| 295 | msg[2] = address; | ||
| 296 | msg[3] = send_bytes - 1; | ||
| 297 | memcpy(&msg[4], send, send_bytes); | ||
| 298 | msg_bytes = send_bytes + 4; | ||
| 299 | for (;;) { | ||
| 300 | ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, &ack, 1); | ||
| 301 | if (ret < 0) | ||
| 302 | return ret; | ||
| 303 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) | ||
| 304 | break; | ||
| 305 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) | ||
| 306 | udelay(100); | ||
| 307 | else | ||
| 308 | return -EIO; | ||
| 309 | } | ||
| 310 | return send_bytes; | ||
| 311 | } | ||
| 312 | |||
| 313 | /* Write a single byte to the aux channel in native mode */ | ||
| 314 | static int | ||
| 315 | intel_dp_aux_native_write_1(struct intel_output *intel_output, | ||
| 316 | uint16_t address, uint8_t byte) | ||
| 317 | { | ||
| 318 | return intel_dp_aux_native_write(intel_output, address, &byte, 1); | ||
| 319 | } | ||
| 320 | |||
| 321 | /* read bytes from a native aux channel */ | ||
| 322 | static int | ||
| 323 | intel_dp_aux_native_read(struct intel_output *intel_output, | ||
| 324 | uint16_t address, uint8_t *recv, int recv_bytes) | ||
| 325 | { | ||
| 326 | uint8_t msg[4]; | ||
| 327 | int msg_bytes; | ||
| 328 | uint8_t reply[20]; | ||
| 329 | int reply_bytes; | ||
| 330 | uint8_t ack; | ||
| 331 | int ret; | ||
| 332 | |||
| 333 | msg[0] = AUX_NATIVE_READ << 4; | ||
| 334 | msg[1] = address >> 8; | ||
| 335 | msg[2] = address & 0xff; | ||
| 336 | msg[3] = recv_bytes - 1; | ||
| 337 | |||
| 338 | msg_bytes = 4; | ||
| 339 | reply_bytes = recv_bytes + 1; | ||
| 340 | |||
| 341 | for (;;) { | ||
| 342 | ret = intel_dp_aux_ch(intel_output, msg, msg_bytes, | ||
| 343 | reply, reply_bytes); | ||
| 344 | if (ret == 0) | ||
| 345 | return -EPROTO; | ||
| 346 | if (ret < 0) | ||
| 347 | return ret; | ||
| 348 | ack = reply[0]; | ||
| 349 | if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_ACK) { | ||
| 350 | memcpy(recv, reply + 1, ret - 1); | ||
| 351 | return ret - 1; | ||
| 352 | } | ||
| 353 | else if ((ack & AUX_NATIVE_REPLY_MASK) == AUX_NATIVE_REPLY_DEFER) | ||
| 354 | udelay(100); | ||
| 355 | else | ||
| 356 | return -EIO; | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 360 | static int | ||
| 361 | intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, | ||
| 362 | uint8_t *send, int send_bytes, | ||
| 363 | uint8_t *recv, int recv_bytes) | ||
| 364 | { | ||
| 365 | struct intel_dp_priv *dp_priv = container_of(adapter, | ||
| 366 | struct intel_dp_priv, | ||
| 367 | adapter); | ||
| 368 | struct intel_output *intel_output = dp_priv->intel_output; | ||
| 369 | |||
| 370 | return intel_dp_aux_ch(intel_output, | ||
| 371 | send, send_bytes, recv, recv_bytes); | ||
| 372 | } | ||
| 373 | |||
| 374 | static int | ||
| 375 | intel_dp_i2c_init(struct intel_output *intel_output, const char *name) | ||
| 376 | { | ||
| 377 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 378 | |||
| 379 | DRM_ERROR("i2c_init %s\n", name); | ||
| 380 | dp_priv->algo.running = false; | ||
| 381 | dp_priv->algo.address = 0; | ||
| 382 | dp_priv->algo.aux_ch = intel_dp_i2c_aux_ch; | ||
| 383 | |||
| 384 | memset(&dp_priv->adapter, '\0', sizeof (dp_priv->adapter)); | ||
| 385 | dp_priv->adapter.owner = THIS_MODULE; | ||
| 386 | dp_priv->adapter.class = I2C_CLASS_DDC; | ||
| 387 | strncpy (dp_priv->adapter.name, name, sizeof dp_priv->adapter.name - 1); | ||
| 388 | dp_priv->adapter.name[sizeof dp_priv->adapter.name - 1] = '\0'; | ||
| 389 | dp_priv->adapter.algo_data = &dp_priv->algo; | ||
| 390 | dp_priv->adapter.dev.parent = &intel_output->base.kdev; | ||
| 391 | |||
| 392 | return i2c_dp_aux_add_bus(&dp_priv->adapter); | ||
| 393 | } | ||
| 394 | |||
| 395 | static bool | ||
| 396 | intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||
| 397 | struct drm_display_mode *adjusted_mode) | ||
| 398 | { | ||
| 399 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 400 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 401 | int lane_count, clock; | ||
| 402 | int max_lane_count = intel_dp_max_lane_count(intel_output); | ||
| 403 | int max_clock = intel_dp_max_link_bw(intel_output) == DP_LINK_BW_2_7 ? 1 : 0; | ||
| 404 | static int bws[2] = { DP_LINK_BW_1_62, DP_LINK_BW_2_7 }; | ||
| 405 | |||
| 406 | for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { | ||
| 407 | for (clock = 0; clock <= max_clock; clock++) { | ||
| 408 | int link_avail = intel_dp_link_clock(bws[clock]) * lane_count; | ||
| 409 | |||
| 410 | if (intel_dp_link_required(mode->clock) <= link_avail) { | ||
| 411 | dp_priv->link_bw = bws[clock]; | ||
| 412 | dp_priv->lane_count = lane_count; | ||
| 413 | adjusted_mode->clock = intel_dp_link_clock(dp_priv->link_bw); | ||
| 414 | printk(KERN_ERR "link bw %02x lane count %d clock %d\n", | ||
| 415 | dp_priv->link_bw, dp_priv->lane_count, | ||
| 416 | adjusted_mode->clock); | ||
| 417 | return true; | ||
| 418 | } | ||
| 419 | } | ||
| 420 | } | ||
| 421 | return false; | ||
| 422 | } | ||
| 423 | |||
| 424 | struct intel_dp_m_n { | ||
| 425 | uint32_t tu; | ||
| 426 | uint32_t gmch_m; | ||
| 427 | uint32_t gmch_n; | ||
| 428 | uint32_t link_m; | ||
| 429 | uint32_t link_n; | ||
| 430 | }; | ||
| 431 | |||
| 432 | static void | ||
| 433 | intel_reduce_ratio(uint32_t *num, uint32_t *den) | ||
| 434 | { | ||
| 435 | while (*num > 0xffffff || *den > 0xffffff) { | ||
| 436 | *num >>= 1; | ||
| 437 | *den >>= 1; | ||
| 438 | } | ||
| 439 | } | ||
| 440 | |||
| 441 | static void | ||
| 442 | intel_dp_compute_m_n(int bytes_per_pixel, | ||
| 443 | int nlanes, | ||
| 444 | int pixel_clock, | ||
| 445 | int link_clock, | ||
| 446 | struct intel_dp_m_n *m_n) | ||
| 447 | { | ||
| 448 | m_n->tu = 64; | ||
| 449 | m_n->gmch_m = pixel_clock * bytes_per_pixel; | ||
| 450 | m_n->gmch_n = link_clock * nlanes; | ||
| 451 | intel_reduce_ratio(&m_n->gmch_m, &m_n->gmch_n); | ||
| 452 | m_n->link_m = pixel_clock; | ||
| 453 | m_n->link_n = link_clock; | ||
| 454 | intel_reduce_ratio(&m_n->link_m, &m_n->link_n); | ||
| 455 | } | ||
| 456 | |||
| 457 | void | ||
| 458 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
| 459 | struct drm_display_mode *adjusted_mode) | ||
| 460 | { | ||
| 461 | struct drm_device *dev = crtc->dev; | ||
| 462 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
| 463 | struct drm_connector *connector; | ||
| 464 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 465 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 466 | int lane_count = 4; | ||
| 467 | struct intel_dp_m_n m_n; | ||
| 468 | |||
| 469 | /* | ||
| 470 | * Find the lane count in the intel_output private | ||
| 471 | */ | ||
| 472 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
| 473 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 474 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 475 | |||
| 476 | if (!connector->encoder || connector->encoder->crtc != crtc) | ||
| 477 | continue; | ||
| 478 | |||
| 479 | if (intel_output->type == INTEL_OUTPUT_DISPLAYPORT) { | ||
| 480 | lane_count = dp_priv->lane_count; | ||
| 481 | break; | ||
| 482 | } | ||
| 483 | } | ||
| 484 | |||
| 485 | /* | ||
| 486 | * Compute the GMCH and Link ratios. The '3' here is | ||
| 487 | * the number of bytes_per_pixel post-LUT, which we always | ||
| 488 | * set up for 8-bits of R/G/B, or 3 bytes total. | ||
| 489 | */ | ||
| 490 | intel_dp_compute_m_n(3, lane_count, | ||
| 491 | mode->clock, adjusted_mode->clock, &m_n); | ||
| 492 | |||
| 493 | if (intel_crtc->pipe == 0) { | ||
| 494 | I915_WRITE(PIPEA_GMCH_DATA_M, | ||
| 495 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
| 496 | m_n.gmch_m); | ||
| 497 | I915_WRITE(PIPEA_GMCH_DATA_N, | ||
| 498 | m_n.gmch_n); | ||
| 499 | I915_WRITE(PIPEA_DP_LINK_M, m_n.link_m); | ||
| 500 | I915_WRITE(PIPEA_DP_LINK_N, m_n.link_n); | ||
| 501 | } else { | ||
| 502 | I915_WRITE(PIPEB_GMCH_DATA_M, | ||
| 503 | ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) | | ||
| 504 | m_n.gmch_m); | ||
| 505 | I915_WRITE(PIPEB_GMCH_DATA_N, | ||
| 506 | m_n.gmch_n); | ||
| 507 | I915_WRITE(PIPEB_DP_LINK_M, m_n.link_m); | ||
| 508 | I915_WRITE(PIPEB_DP_LINK_N, m_n.link_n); | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | static void | ||
| 513 | intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||
| 514 | struct drm_display_mode *adjusted_mode) | ||
| 515 | { | ||
| 516 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 517 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 518 | struct drm_crtc *crtc = intel_output->enc.crtc; | ||
| 519 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 520 | |||
| 521 | dp_priv->DP = (DP_LINK_TRAIN_OFF | | ||
| 522 | DP_VOLTAGE_0_4 | | ||
| 523 | DP_PRE_EMPHASIS_0 | | ||
| 524 | DP_SYNC_VS_HIGH | | ||
| 525 | DP_SYNC_HS_HIGH); | ||
| 526 | |||
| 527 | switch (dp_priv->lane_count) { | ||
| 528 | case 1: | ||
| 529 | dp_priv->DP |= DP_PORT_WIDTH_1; | ||
| 530 | break; | ||
| 531 | case 2: | ||
| 532 | dp_priv->DP |= DP_PORT_WIDTH_2; | ||
| 533 | break; | ||
| 534 | case 4: | ||
| 535 | dp_priv->DP |= DP_PORT_WIDTH_4; | ||
| 536 | break; | ||
| 537 | } | ||
| 538 | if (dp_priv->has_audio) | ||
| 539 | dp_priv->DP |= DP_AUDIO_OUTPUT_ENABLE; | ||
| 540 | |||
| 541 | memset(dp_priv->link_configuration, 0, DP_LINK_CONFIGURATION_SIZE); | ||
| 542 | dp_priv->link_configuration[0] = dp_priv->link_bw; | ||
| 543 | dp_priv->link_configuration[1] = dp_priv->lane_count; | ||
| 544 | |||
| 545 | /* | ||
| 546 | * Check for DPCD version > 1.1, | ||
| 547 | * enable enahanced frame stuff in that case | ||
| 548 | */ | ||
| 549 | if (dp_priv->dpcd[0] >= 0x11) { | ||
| 550 | dp_priv->link_configuration[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; | ||
| 551 | dp_priv->DP |= DP_ENHANCED_FRAMING; | ||
| 552 | } | ||
| 553 | |||
| 554 | if (intel_crtc->pipe == 1) | ||
| 555 | dp_priv->DP |= DP_PIPEB_SELECT; | ||
| 556 | } | ||
| 557 | |||
| 558 | |||
| 559 | static void | ||
| 560 | intel_dp_dpms(struct drm_encoder *encoder, int mode) | ||
| 561 | { | ||
| 562 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 563 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 564 | struct drm_device *dev = intel_output->base.dev; | ||
| 565 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 566 | uint32_t dp_reg = I915_READ(dp_priv->output_reg); | ||
| 567 | |||
| 568 | if (mode != DRM_MODE_DPMS_ON) { | ||
| 569 | if (dp_reg & DP_PORT_EN) | ||
| 570 | intel_dp_link_down(intel_output, dp_priv->DP); | ||
| 571 | } else { | ||
| 572 | if (!(dp_reg & DP_PORT_EN)) | ||
| 573 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | ||
| 574 | } | ||
| 575 | dp_priv->dpms_mode = mode; | ||
| 576 | } | ||
| 577 | |||
| 578 | /* | ||
| 579 | * Fetch AUX CH registers 0x202 - 0x207 which contain | ||
| 580 | * link status information | ||
| 581 | */ | ||
| 582 | static bool | ||
| 583 | intel_dp_get_link_status(struct intel_output *intel_output, | ||
| 584 | uint8_t link_status[DP_LINK_STATUS_SIZE]) | ||
| 585 | { | ||
| 586 | int ret; | ||
| 587 | |||
| 588 | ret = intel_dp_aux_native_read(intel_output, | ||
| 589 | DP_LANE0_1_STATUS, | ||
| 590 | link_status, DP_LINK_STATUS_SIZE); | ||
| 591 | if (ret != DP_LINK_STATUS_SIZE) | ||
| 592 | return false; | ||
| 593 | return true; | ||
| 594 | } | ||
| 595 | |||
| 596 | static uint8_t | ||
| 597 | intel_dp_link_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 598 | int r) | ||
| 599 | { | ||
| 600 | return link_status[r - DP_LANE0_1_STATUS]; | ||
| 601 | } | ||
| 602 | |||
| 603 | static void | ||
| 604 | intel_dp_save(struct drm_connector *connector) | ||
| 605 | { | ||
| 606 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 607 | struct drm_device *dev = intel_output->base.dev; | ||
| 608 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 609 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 610 | |||
| 611 | dp_priv->save_DP = I915_READ(dp_priv->output_reg); | ||
| 612 | intel_dp_aux_native_read(intel_output, DP_LINK_BW_SET, | ||
| 613 | dp_priv->save_link_configuration, | ||
| 614 | sizeof (dp_priv->save_link_configuration)); | ||
| 615 | } | ||
| 616 | |||
| 617 | static uint8_t | ||
| 618 | intel_get_adjust_request_voltage(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 619 | int lane) | ||
| 620 | { | ||
| 621 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
| 622 | int s = ((lane & 1) ? | ||
| 623 | DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT : | ||
| 624 | DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT); | ||
| 625 | uint8_t l = intel_dp_link_status(link_status, i); | ||
| 626 | |||
| 627 | return ((l >> s) & 3) << DP_TRAIN_VOLTAGE_SWING_SHIFT; | ||
| 628 | } | ||
| 629 | |||
| 630 | static uint8_t | ||
| 631 | intel_get_adjust_request_pre_emphasis(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 632 | int lane) | ||
| 633 | { | ||
| 634 | int i = DP_ADJUST_REQUEST_LANE0_1 + (lane >> 1); | ||
| 635 | int s = ((lane & 1) ? | ||
| 636 | DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT : | ||
| 637 | DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT); | ||
| 638 | uint8_t l = intel_dp_link_status(link_status, i); | ||
| 639 | |||
| 640 | return ((l >> s) & 3) << DP_TRAIN_PRE_EMPHASIS_SHIFT; | ||
| 641 | } | ||
| 642 | |||
| 643 | |||
| 644 | #if 0 | ||
| 645 | static char *voltage_names[] = { | ||
| 646 | "0.4V", "0.6V", "0.8V", "1.2V" | ||
| 647 | }; | ||
| 648 | static char *pre_emph_names[] = { | ||
| 649 | "0dB", "3.5dB", "6dB", "9.5dB" | ||
| 650 | }; | ||
| 651 | static char *link_train_names[] = { | ||
| 652 | "pattern 1", "pattern 2", "idle", "off" | ||
| 653 | }; | ||
| 654 | #endif | ||
| 655 | |||
| 656 | /* | ||
| 657 | * These are source-specific values; current Intel hardware supports | ||
| 658 | * a maximum voltage of 800mV and a maximum pre-emphasis of 6dB | ||
| 659 | */ | ||
| 660 | #define I830_DP_VOLTAGE_MAX DP_TRAIN_VOLTAGE_SWING_800 | ||
| 661 | |||
| 662 | static uint8_t | ||
| 663 | intel_dp_pre_emphasis_max(uint8_t voltage_swing) | ||
| 664 | { | ||
| 665 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | ||
| 666 | case DP_TRAIN_VOLTAGE_SWING_400: | ||
| 667 | return DP_TRAIN_PRE_EMPHASIS_6; | ||
| 668 | case DP_TRAIN_VOLTAGE_SWING_600: | ||
| 669 | return DP_TRAIN_PRE_EMPHASIS_6; | ||
| 670 | case DP_TRAIN_VOLTAGE_SWING_800: | ||
| 671 | return DP_TRAIN_PRE_EMPHASIS_3_5; | ||
| 672 | case DP_TRAIN_VOLTAGE_SWING_1200: | ||
| 673 | default: | ||
| 674 | return DP_TRAIN_PRE_EMPHASIS_0; | ||
| 675 | } | ||
| 676 | } | ||
| 677 | |||
| 678 | static void | ||
| 679 | intel_get_adjust_train(struct intel_output *intel_output, | ||
| 680 | uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 681 | int lane_count, | ||
| 682 | uint8_t train_set[4]) | ||
| 683 | { | ||
| 684 | uint8_t v = 0; | ||
| 685 | uint8_t p = 0; | ||
| 686 | int lane; | ||
| 687 | |||
| 688 | for (lane = 0; lane < lane_count; lane++) { | ||
| 689 | uint8_t this_v = intel_get_adjust_request_voltage(link_status, lane); | ||
| 690 | uint8_t this_p = intel_get_adjust_request_pre_emphasis(link_status, lane); | ||
| 691 | |||
| 692 | if (this_v > v) | ||
| 693 | v = this_v; | ||
| 694 | if (this_p > p) | ||
| 695 | p = this_p; | ||
| 696 | } | ||
| 697 | |||
| 698 | if (v >= I830_DP_VOLTAGE_MAX) | ||
| 699 | v = I830_DP_VOLTAGE_MAX | DP_TRAIN_MAX_SWING_REACHED; | ||
| 700 | |||
| 701 | if (p >= intel_dp_pre_emphasis_max(v)) | ||
| 702 | p = intel_dp_pre_emphasis_max(v) | DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; | ||
| 703 | |||
| 704 | for (lane = 0; lane < 4; lane++) | ||
| 705 | train_set[lane] = v | p; | ||
| 706 | } | ||
| 707 | |||
| 708 | static uint32_t | ||
| 709 | intel_dp_signal_levels(uint8_t train_set, int lane_count) | ||
| 710 | { | ||
| 711 | uint32_t signal_levels = 0; | ||
| 712 | |||
| 713 | switch (train_set & DP_TRAIN_VOLTAGE_SWING_MASK) { | ||
| 714 | case DP_TRAIN_VOLTAGE_SWING_400: | ||
| 715 | default: | ||
| 716 | signal_levels |= DP_VOLTAGE_0_4; | ||
| 717 | break; | ||
| 718 | case DP_TRAIN_VOLTAGE_SWING_600: | ||
| 719 | signal_levels |= DP_VOLTAGE_0_6; | ||
| 720 | break; | ||
| 721 | case DP_TRAIN_VOLTAGE_SWING_800: | ||
| 722 | signal_levels |= DP_VOLTAGE_0_8; | ||
| 723 | break; | ||
| 724 | case DP_TRAIN_VOLTAGE_SWING_1200: | ||
| 725 | signal_levels |= DP_VOLTAGE_1_2; | ||
| 726 | break; | ||
| 727 | } | ||
| 728 | switch (train_set & DP_TRAIN_PRE_EMPHASIS_MASK) { | ||
| 729 | case DP_TRAIN_PRE_EMPHASIS_0: | ||
| 730 | default: | ||
| 731 | signal_levels |= DP_PRE_EMPHASIS_0; | ||
| 732 | break; | ||
| 733 | case DP_TRAIN_PRE_EMPHASIS_3_5: | ||
| 734 | signal_levels |= DP_PRE_EMPHASIS_3_5; | ||
| 735 | break; | ||
| 736 | case DP_TRAIN_PRE_EMPHASIS_6: | ||
| 737 | signal_levels |= DP_PRE_EMPHASIS_6; | ||
| 738 | break; | ||
| 739 | case DP_TRAIN_PRE_EMPHASIS_9_5: | ||
| 740 | signal_levels |= DP_PRE_EMPHASIS_9_5; | ||
| 741 | break; | ||
| 742 | } | ||
| 743 | return signal_levels; | ||
| 744 | } | ||
| 745 | |||
| 746 | static uint8_t | ||
| 747 | intel_get_lane_status(uint8_t link_status[DP_LINK_STATUS_SIZE], | ||
| 748 | int lane) | ||
| 749 | { | ||
| 750 | int i = DP_LANE0_1_STATUS + (lane >> 1); | ||
| 751 | int s = (lane & 1) * 4; | ||
| 752 | uint8_t l = intel_dp_link_status(link_status, i); | ||
| 753 | |||
| 754 | return (l >> s) & 0xf; | ||
| 755 | } | ||
| 756 | |||
| 757 | /* Check for clock recovery is done on all channels */ | ||
| 758 | static bool | ||
| 759 | intel_clock_recovery_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | ||
| 760 | { | ||
| 761 | int lane; | ||
| 762 | uint8_t lane_status; | ||
| 763 | |||
| 764 | for (lane = 0; lane < lane_count; lane++) { | ||
| 765 | lane_status = intel_get_lane_status(link_status, lane); | ||
| 766 | if ((lane_status & DP_LANE_CR_DONE) == 0) | ||
| 767 | return false; | ||
| 768 | } | ||
| 769 | return true; | ||
| 770 | } | ||
| 771 | |||
| 772 | /* Check to see if channel eq is done on all channels */ | ||
| 773 | #define CHANNEL_EQ_BITS (DP_LANE_CR_DONE|\ | ||
| 774 | DP_LANE_CHANNEL_EQ_DONE|\ | ||
| 775 | DP_LANE_SYMBOL_LOCKED) | ||
| 776 | static bool | ||
| 777 | intel_channel_eq_ok(uint8_t link_status[DP_LINK_STATUS_SIZE], int lane_count) | ||
| 778 | { | ||
| 779 | uint8_t lane_align; | ||
| 780 | uint8_t lane_status; | ||
| 781 | int lane; | ||
| 782 | |||
| 783 | lane_align = intel_dp_link_status(link_status, | ||
| 784 | DP_LANE_ALIGN_STATUS_UPDATED); | ||
| 785 | if ((lane_align & DP_INTERLANE_ALIGN_DONE) == 0) | ||
| 786 | return false; | ||
| 787 | for (lane = 0; lane < lane_count; lane++) { | ||
| 788 | lane_status = intel_get_lane_status(link_status, lane); | ||
| 789 | if ((lane_status & CHANNEL_EQ_BITS) != CHANNEL_EQ_BITS) | ||
| 790 | return false; | ||
| 791 | } | ||
| 792 | return true; | ||
| 793 | } | ||
| 794 | |||
| 795 | static bool | ||
| 796 | intel_dp_set_link_train(struct intel_output *intel_output, | ||
| 797 | uint32_t dp_reg_value, | ||
| 798 | uint8_t dp_train_pat, | ||
| 799 | uint8_t train_set[4], | ||
| 800 | bool first) | ||
| 801 | { | ||
| 802 | struct drm_device *dev = intel_output->base.dev; | ||
| 803 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 804 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 805 | int ret; | ||
| 806 | |||
| 807 | I915_WRITE(dp_priv->output_reg, dp_reg_value); | ||
| 808 | POSTING_READ(dp_priv->output_reg); | ||
| 809 | if (first) | ||
| 810 | intel_wait_for_vblank(dev); | ||
| 811 | |||
| 812 | intel_dp_aux_native_write_1(intel_output, | ||
| 813 | DP_TRAINING_PATTERN_SET, | ||
| 814 | dp_train_pat); | ||
| 815 | |||
| 816 | ret = intel_dp_aux_native_write(intel_output, | ||
| 817 | DP_TRAINING_LANE0_SET, train_set, 4); | ||
| 818 | if (ret != 4) | ||
| 819 | return false; | ||
| 820 | |||
| 821 | return true; | ||
| 822 | } | ||
| 823 | |||
| 824 | static void | ||
| 825 | intel_dp_link_train(struct intel_output *intel_output, uint32_t DP, | ||
| 826 | uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]) | ||
| 827 | { | ||
| 828 | struct drm_device *dev = intel_output->base.dev; | ||
| 829 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 830 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 831 | uint8_t train_set[4]; | ||
| 832 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
| 833 | int i; | ||
| 834 | uint8_t voltage; | ||
| 835 | bool clock_recovery = false; | ||
| 836 | bool channel_eq = false; | ||
| 837 | bool first = true; | ||
| 838 | int tries; | ||
| 839 | |||
| 840 | /* Write the link configuration data */ | ||
| 841 | intel_dp_aux_native_write(intel_output, 0x100, | ||
| 842 | link_configuration, DP_LINK_CONFIGURATION_SIZE); | ||
| 843 | |||
| 844 | DP |= DP_PORT_EN; | ||
| 845 | DP &= ~DP_LINK_TRAIN_MASK; | ||
| 846 | memset(train_set, 0, 4); | ||
| 847 | voltage = 0xff; | ||
| 848 | tries = 0; | ||
| 849 | clock_recovery = false; | ||
| 850 | for (;;) { | ||
| 851 | /* Use train_set[0] to set the voltage and pre emphasis values */ | ||
| 852 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
| 853 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
| 854 | |||
| 855 | if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_1, | ||
| 856 | DP_TRAINING_PATTERN_1, train_set, first)) | ||
| 857 | break; | ||
| 858 | first = false; | ||
| 859 | /* Set training pattern 1 */ | ||
| 860 | |||
| 861 | udelay(100); | ||
| 862 | if (!intel_dp_get_link_status(intel_output, link_status)) | ||
| 863 | break; | ||
| 864 | |||
| 865 | if (intel_clock_recovery_ok(link_status, dp_priv->lane_count)) { | ||
| 866 | clock_recovery = true; | ||
| 867 | break; | ||
| 868 | } | ||
| 869 | |||
| 870 | /* Check to see if we've tried the max voltage */ | ||
| 871 | for (i = 0; i < dp_priv->lane_count; i++) | ||
| 872 | if ((train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | ||
| 873 | break; | ||
| 874 | if (i == dp_priv->lane_count) | ||
| 875 | break; | ||
| 876 | |||
| 877 | /* Check to see if we've tried the same voltage 5 times */ | ||
| 878 | if ((train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK) == voltage) { | ||
| 879 | ++tries; | ||
| 880 | if (tries == 5) | ||
| 881 | break; | ||
| 882 | } else | ||
| 883 | tries = 0; | ||
| 884 | voltage = train_set[0] & DP_TRAIN_VOLTAGE_SWING_MASK; | ||
| 885 | |||
| 886 | /* Compute new train_set as requested by target */ | ||
| 887 | intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); | ||
| 888 | } | ||
| 889 | |||
| 890 | /* channel equalization */ | ||
| 891 | tries = 0; | ||
| 892 | channel_eq = false; | ||
| 893 | for (;;) { | ||
| 894 | /* Use train_set[0] to set the voltage and pre emphasis values */ | ||
| 895 | uint32_t signal_levels = intel_dp_signal_levels(train_set[0], dp_priv->lane_count); | ||
| 896 | DP = (DP & ~(DP_VOLTAGE_MASK|DP_PRE_EMPHASIS_MASK)) | signal_levels; | ||
| 897 | |||
| 898 | /* channel eq pattern */ | ||
| 899 | if (!intel_dp_set_link_train(intel_output, DP | DP_LINK_TRAIN_PAT_2, | ||
| 900 | DP_TRAINING_PATTERN_2, train_set, | ||
| 901 | false)) | ||
| 902 | break; | ||
| 903 | |||
| 904 | udelay(400); | ||
| 905 | if (!intel_dp_get_link_status(intel_output, link_status)) | ||
| 906 | break; | ||
| 907 | |||
| 908 | if (intel_channel_eq_ok(link_status, dp_priv->lane_count)) { | ||
| 909 | channel_eq = true; | ||
| 910 | break; | ||
| 911 | } | ||
| 912 | |||
| 913 | /* Try 5 times */ | ||
| 914 | if (tries > 5) | ||
| 915 | break; | ||
| 916 | |||
| 917 | /* Compute new train_set as requested by target */ | ||
| 918 | intel_get_adjust_train(intel_output, link_status, dp_priv->lane_count, train_set); | ||
| 919 | ++tries; | ||
| 920 | } | ||
| 921 | |||
| 922 | I915_WRITE(dp_priv->output_reg, DP | DP_LINK_TRAIN_OFF); | ||
| 923 | POSTING_READ(dp_priv->output_reg); | ||
| 924 | intel_dp_aux_native_write_1(intel_output, | ||
| 925 | DP_TRAINING_PATTERN_SET, DP_TRAINING_PATTERN_DISABLE); | ||
| 926 | } | ||
| 927 | |||
| 928 | static void | ||
| 929 | intel_dp_link_down(struct intel_output *intel_output, uint32_t DP) | ||
| 930 | { | ||
| 931 | struct drm_device *dev = intel_output->base.dev; | ||
| 932 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 933 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 934 | |||
| 935 | I915_WRITE(dp_priv->output_reg, DP & ~DP_PORT_EN); | ||
| 936 | POSTING_READ(dp_priv->output_reg); | ||
| 937 | } | ||
| 938 | |||
| 939 | static void | ||
| 940 | intel_dp_restore(struct drm_connector *connector) | ||
| 941 | { | ||
| 942 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 943 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 944 | |||
| 945 | if (dp_priv->save_DP & DP_PORT_EN) | ||
| 946 | intel_dp_link_train(intel_output, dp_priv->save_DP, dp_priv->save_link_configuration); | ||
| 947 | else | ||
| 948 | intel_dp_link_down(intel_output, dp_priv->save_DP); | ||
| 949 | } | ||
| 950 | |||
| 951 | /* | ||
| 952 | * According to DP spec | ||
| 953 | * 5.1.2: | ||
| 954 | * 1. Read DPCD | ||
| 955 | * 2. Configure link according to Receiver Capabilities | ||
| 956 | * 3. Use Link Training from 2.5.3.3 and 3.5.1.3 | ||
| 957 | * 4. Check link status on receipt of hot-plug interrupt | ||
| 958 | */ | ||
| 959 | |||
| 960 | static void | ||
| 961 | intel_dp_check_link_status(struct intel_output *intel_output) | ||
| 962 | { | ||
| 963 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 964 | uint8_t link_status[DP_LINK_STATUS_SIZE]; | ||
| 965 | |||
| 966 | if (!intel_output->enc.crtc) | ||
| 967 | return; | ||
| 968 | |||
| 969 | if (!intel_dp_get_link_status(intel_output, link_status)) { | ||
| 970 | intel_dp_link_down(intel_output, dp_priv->DP); | ||
| 971 | return; | ||
| 972 | } | ||
| 973 | |||
| 974 | if (!intel_channel_eq_ok(link_status, dp_priv->lane_count)) | ||
| 975 | intel_dp_link_train(intel_output, dp_priv->DP, dp_priv->link_configuration); | ||
| 976 | } | ||
| 977 | |||
| 978 | /** | ||
| 979 | * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect DP connection. | ||
| 980 | * | ||
| 981 | * \return true if DP port is connected. | ||
| 982 | * \return false if DP port is disconnected. | ||
| 983 | */ | ||
| 984 | static enum drm_connector_status | ||
| 985 | intel_dp_detect(struct drm_connector *connector) | ||
| 986 | { | ||
| 987 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 988 | struct drm_device *dev = intel_output->base.dev; | ||
| 989 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 990 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 991 | uint32_t temp, bit; | ||
| 992 | enum drm_connector_status status; | ||
| 993 | |||
| 994 | dp_priv->has_audio = false; | ||
| 995 | |||
| 996 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
| 997 | |||
| 998 | I915_WRITE(PORT_HOTPLUG_EN, | ||
| 999 | temp | | ||
| 1000 | DPB_HOTPLUG_INT_EN | | ||
| 1001 | DPC_HOTPLUG_INT_EN | | ||
| 1002 | DPD_HOTPLUG_INT_EN); | ||
| 1003 | |||
| 1004 | POSTING_READ(PORT_HOTPLUG_EN); | ||
| 1005 | |||
| 1006 | switch (dp_priv->output_reg) { | ||
| 1007 | case DP_B: | ||
| 1008 | bit = DPB_HOTPLUG_INT_STATUS; | ||
| 1009 | break; | ||
| 1010 | case DP_C: | ||
| 1011 | bit = DPC_HOTPLUG_INT_STATUS; | ||
| 1012 | break; | ||
| 1013 | case DP_D: | ||
| 1014 | bit = DPD_HOTPLUG_INT_STATUS; | ||
| 1015 | break; | ||
| 1016 | default: | ||
| 1017 | return connector_status_unknown; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | temp = I915_READ(PORT_HOTPLUG_STAT); | ||
| 1021 | |||
| 1022 | if ((temp & bit) == 0) | ||
| 1023 | return connector_status_disconnected; | ||
| 1024 | |||
| 1025 | status = connector_status_disconnected; | ||
| 1026 | if (intel_dp_aux_native_read(intel_output, | ||
| 1027 | 0x000, dp_priv->dpcd, | ||
| 1028 | sizeof (dp_priv->dpcd)) == sizeof (dp_priv->dpcd)) | ||
| 1029 | { | ||
| 1030 | if (dp_priv->dpcd[0] != 0) | ||
| 1031 | status = connector_status_connected; | ||
| 1032 | } | ||
| 1033 | return status; | ||
| 1034 | } | ||
| 1035 | |||
| 1036 | static int intel_dp_get_modes(struct drm_connector *connector) | ||
| 1037 | { | ||
| 1038 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 1039 | |||
| 1040 | /* We should parse the EDID data and find out if it has an audio sink | ||
| 1041 | */ | ||
| 1042 | |||
| 1043 | return intel_ddc_get_modes(intel_output); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static void | ||
| 1047 | intel_dp_destroy (struct drm_connector *connector) | ||
| 1048 | { | ||
| 1049 | struct intel_output *intel_output = to_intel_output(connector); | ||
| 1050 | |||
| 1051 | if (intel_output->i2c_bus) | ||
| 1052 | intel_i2c_destroy(intel_output->i2c_bus); | ||
| 1053 | drm_sysfs_connector_remove(connector); | ||
| 1054 | drm_connector_cleanup(connector); | ||
| 1055 | kfree(intel_output); | ||
| 1056 | } | ||
| 1057 | |||
| 1058 | static const struct drm_encoder_helper_funcs intel_dp_helper_funcs = { | ||
| 1059 | .dpms = intel_dp_dpms, | ||
| 1060 | .mode_fixup = intel_dp_mode_fixup, | ||
| 1061 | .prepare = intel_encoder_prepare, | ||
| 1062 | .mode_set = intel_dp_mode_set, | ||
| 1063 | .commit = intel_encoder_commit, | ||
| 1064 | }; | ||
| 1065 | |||
| 1066 | static const struct drm_connector_funcs intel_dp_connector_funcs = { | ||
| 1067 | .dpms = drm_helper_connector_dpms, | ||
| 1068 | .save = intel_dp_save, | ||
| 1069 | .restore = intel_dp_restore, | ||
| 1070 | .detect = intel_dp_detect, | ||
| 1071 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
| 1072 | .destroy = intel_dp_destroy, | ||
| 1073 | }; | ||
| 1074 | |||
| 1075 | static const struct drm_connector_helper_funcs intel_dp_connector_helper_funcs = { | ||
| 1076 | .get_modes = intel_dp_get_modes, | ||
| 1077 | .mode_valid = intel_dp_mode_valid, | ||
| 1078 | .best_encoder = intel_best_encoder, | ||
| 1079 | }; | ||
| 1080 | |||
| 1081 | static void intel_dp_enc_destroy(struct drm_encoder *encoder) | ||
| 1082 | { | ||
| 1083 | drm_encoder_cleanup(encoder); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static const struct drm_encoder_funcs intel_dp_enc_funcs = { | ||
| 1087 | .destroy = intel_dp_enc_destroy, | ||
| 1088 | }; | ||
| 1089 | |||
| 1090 | void | ||
| 1091 | intel_dp_hot_plug(struct intel_output *intel_output) | ||
| 1092 | { | ||
| 1093 | struct intel_dp_priv *dp_priv = intel_output->dev_priv; | ||
| 1094 | |||
| 1095 | if (dp_priv->dpms_mode == DRM_MODE_DPMS_ON) | ||
| 1096 | intel_dp_check_link_status(intel_output); | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | void | ||
| 1100 | intel_dp_init(struct drm_device *dev, int output_reg) | ||
| 1101 | { | ||
| 1102 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 1103 | struct drm_connector *connector; | ||
| 1104 | struct intel_output *intel_output; | ||
| 1105 | struct intel_dp_priv *dp_priv; | ||
| 1106 | |||
| 1107 | intel_output = kcalloc(sizeof(struct intel_output) + | ||
| 1108 | sizeof(struct intel_dp_priv), 1, GFP_KERNEL); | ||
| 1109 | if (!intel_output) | ||
| 1110 | return; | ||
| 1111 | |||
| 1112 | dp_priv = (struct intel_dp_priv *)(intel_output + 1); | ||
| 1113 | |||
| 1114 | connector = &intel_output->base; | ||
| 1115 | drm_connector_init(dev, connector, &intel_dp_connector_funcs, | ||
| 1116 | DRM_MODE_CONNECTOR_DisplayPort); | ||
| 1117 | drm_connector_helper_add(connector, &intel_dp_connector_helper_funcs); | ||
| 1118 | |||
| 1119 | intel_output->type = INTEL_OUTPUT_DISPLAYPORT; | ||
| 1120 | |||
| 1121 | connector->interlace_allowed = true; | ||
| 1122 | connector->doublescan_allowed = 0; | ||
| 1123 | |||
| 1124 | dp_priv->intel_output = intel_output; | ||
| 1125 | dp_priv->output_reg = output_reg; | ||
| 1126 | dp_priv->has_audio = false; | ||
| 1127 | dp_priv->dpms_mode = DRM_MODE_DPMS_ON; | ||
| 1128 | intel_output->dev_priv = dp_priv; | ||
| 1129 | |||
| 1130 | drm_encoder_init(dev, &intel_output->enc, &intel_dp_enc_funcs, | ||
| 1131 | DRM_MODE_ENCODER_TMDS); | ||
| 1132 | drm_encoder_helper_add(&intel_output->enc, &intel_dp_helper_funcs); | ||
| 1133 | |||
| 1134 | drm_mode_connector_attach_encoder(&intel_output->base, | ||
| 1135 | &intel_output->enc); | ||
| 1136 | drm_sysfs_connector_add(connector); | ||
| 1137 | |||
| 1138 | /* Set up the DDC bus. */ | ||
| 1139 | intel_dp_i2c_init(intel_output, | ||
| 1140 | (output_reg == DP_B) ? "DPDDC-B" : | ||
| 1141 | (output_reg == DP_C) ? "DPDDC-C" : "DPDDC-D"); | ||
| 1142 | intel_output->ddc_bus = &dp_priv->adapter; | ||
| 1143 | intel_output->hot_plug = intel_dp_hot_plug; | ||
| 1144 | |||
| 1145 | /* For G4X desktop chip, PEG_BAND_GAP_DATA 3:0 must first be written | ||
| 1146 | * 0xd. Failure to do so will result in spurious interrupts being | ||
| 1147 | * generated on the port when a cable is not attached. | ||
| 1148 | */ | ||
| 1149 | if (IS_G4X(dev) && !IS_GM45(dev)) { | ||
| 1150 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | ||
| 1151 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | ||
| 1152 | } | ||
| 1153 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.h b/drivers/gpu/drm/i915/intel_dp.h new file mode 100644 index 000000000000..2b38054d3b6d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp.h | |||
| @@ -0,0 +1,144 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2008 Keith Packard | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
| 5 | * documentation for any purpose is hereby granted without fee, provided that | ||
| 6 | * the above copyright notice appear in all copies and that both that copyright | ||
| 7 | * notice and this permission notice appear in supporting documentation, and | ||
| 8 | * that the name of the copyright holders not be used in advertising or | ||
| 9 | * publicity pertaining to distribution of the software without specific, | ||
| 10 | * written prior permission. The copyright holders make no representations | ||
| 11 | * about the suitability of this software for any purpose. It is provided "as | ||
| 12 | * is" without express or implied warranty. | ||
| 13 | * | ||
| 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
| 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
| 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
| 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
| 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
| 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
| 20 | * OF THIS SOFTWARE. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef _INTEL_DP_H_ | ||
| 24 | #define _INTEL_DP_H_ | ||
| 25 | |||
| 26 | /* From the VESA DisplayPort spec */ | ||
| 27 | |||
| 28 | #define AUX_NATIVE_WRITE 0x8 | ||
| 29 | #define AUX_NATIVE_READ 0x9 | ||
| 30 | #define AUX_I2C_WRITE 0x0 | ||
| 31 | #define AUX_I2C_READ 0x1 | ||
| 32 | #define AUX_I2C_STATUS 0x2 | ||
| 33 | #define AUX_I2C_MOT 0x4 | ||
| 34 | |||
| 35 | #define AUX_NATIVE_REPLY_ACK (0x0 << 4) | ||
| 36 | #define AUX_NATIVE_REPLY_NACK (0x1 << 4) | ||
| 37 | #define AUX_NATIVE_REPLY_DEFER (0x2 << 4) | ||
| 38 | #define AUX_NATIVE_REPLY_MASK (0x3 << 4) | ||
| 39 | |||
| 40 | #define AUX_I2C_REPLY_ACK (0x0 << 6) | ||
| 41 | #define AUX_I2C_REPLY_NACK (0x1 << 6) | ||
| 42 | #define AUX_I2C_REPLY_DEFER (0x2 << 6) | ||
| 43 | #define AUX_I2C_REPLY_MASK (0x3 << 6) | ||
| 44 | |||
| 45 | /* AUX CH addresses */ | ||
| 46 | #define DP_LINK_BW_SET 0x100 | ||
| 47 | # define DP_LINK_BW_1_62 0x06 | ||
| 48 | # define DP_LINK_BW_2_7 0x0a | ||
| 49 | |||
| 50 | #define DP_LANE_COUNT_SET 0x101 | ||
| 51 | # define DP_LANE_COUNT_MASK 0x0f | ||
| 52 | # define DP_LANE_COUNT_ENHANCED_FRAME_EN (1 << 7) | ||
| 53 | |||
| 54 | #define DP_TRAINING_PATTERN_SET 0x102 | ||
| 55 | |||
| 56 | # define DP_TRAINING_PATTERN_DISABLE 0 | ||
| 57 | # define DP_TRAINING_PATTERN_1 1 | ||
| 58 | # define DP_TRAINING_PATTERN_2 2 | ||
| 59 | # define DP_TRAINING_PATTERN_MASK 0x3 | ||
| 60 | |||
| 61 | # define DP_LINK_QUAL_PATTERN_DISABLE (0 << 2) | ||
| 62 | # define DP_LINK_QUAL_PATTERN_D10_2 (1 << 2) | ||
| 63 | # define DP_LINK_QUAL_PATTERN_ERROR_RATE (2 << 2) | ||
| 64 | # define DP_LINK_QUAL_PATTERN_PRBS7 (3 << 2) | ||
| 65 | # define DP_LINK_QUAL_PATTERN_MASK (3 << 2) | ||
| 66 | |||
| 67 | # define DP_RECOVERED_CLOCK_OUT_EN (1 << 4) | ||
| 68 | # define DP_LINK_SCRAMBLING_DISABLE (1 << 5) | ||
| 69 | |||
| 70 | # define DP_SYMBOL_ERROR_COUNT_BOTH (0 << 6) | ||
| 71 | # define DP_SYMBOL_ERROR_COUNT_DISPARITY (1 << 6) | ||
| 72 | # define DP_SYMBOL_ERROR_COUNT_SYMBOL (2 << 6) | ||
| 73 | # define DP_SYMBOL_ERROR_COUNT_MASK (3 << 6) | ||
| 74 | |||
| 75 | #define DP_TRAINING_LANE0_SET 0x103 | ||
| 76 | #define DP_TRAINING_LANE1_SET 0x104 | ||
| 77 | #define DP_TRAINING_LANE2_SET 0x105 | ||
| 78 | #define DP_TRAINING_LANE3_SET 0x106 | ||
| 79 | |||
| 80 | # define DP_TRAIN_VOLTAGE_SWING_MASK 0x3 | ||
| 81 | # define DP_TRAIN_VOLTAGE_SWING_SHIFT 0 | ||
| 82 | # define DP_TRAIN_MAX_SWING_REACHED (1 << 2) | ||
| 83 | # define DP_TRAIN_VOLTAGE_SWING_400 (0 << 0) | ||
| 84 | # define DP_TRAIN_VOLTAGE_SWING_600 (1 << 0) | ||
| 85 | # define DP_TRAIN_VOLTAGE_SWING_800 (2 << 0) | ||
| 86 | # define DP_TRAIN_VOLTAGE_SWING_1200 (3 << 0) | ||
| 87 | |||
| 88 | # define DP_TRAIN_PRE_EMPHASIS_MASK (3 << 3) | ||
| 89 | # define DP_TRAIN_PRE_EMPHASIS_0 (0 << 3) | ||
| 90 | # define DP_TRAIN_PRE_EMPHASIS_3_5 (1 << 3) | ||
| 91 | # define DP_TRAIN_PRE_EMPHASIS_6 (2 << 3) | ||
| 92 | # define DP_TRAIN_PRE_EMPHASIS_9_5 (3 << 3) | ||
| 93 | |||
| 94 | # define DP_TRAIN_PRE_EMPHASIS_SHIFT 3 | ||
| 95 | # define DP_TRAIN_MAX_PRE_EMPHASIS_REACHED (1 << 5) | ||
| 96 | |||
| 97 | #define DP_DOWNSPREAD_CTRL 0x107 | ||
| 98 | # define DP_SPREAD_AMP_0_5 (1 << 4) | ||
| 99 | |||
| 100 | #define DP_MAIN_LINK_CHANNEL_CODING_SET 0x108 | ||
| 101 | # define DP_SET_ANSI_8B10B (1 << 0) | ||
| 102 | |||
| 103 | #define DP_LANE0_1_STATUS 0x202 | ||
| 104 | #define DP_LANE2_3_STATUS 0x203 | ||
| 105 | |||
| 106 | # define DP_LANE_CR_DONE (1 << 0) | ||
| 107 | # define DP_LANE_CHANNEL_EQ_DONE (1 << 1) | ||
| 108 | # define DP_LANE_SYMBOL_LOCKED (1 << 2) | ||
| 109 | |||
| 110 | #define DP_LANE_ALIGN_STATUS_UPDATED 0x204 | ||
| 111 | |||
| 112 | #define DP_INTERLANE_ALIGN_DONE (1 << 0) | ||
| 113 | #define DP_DOWNSTREAM_PORT_STATUS_CHANGED (1 << 6) | ||
| 114 | #define DP_LINK_STATUS_UPDATED (1 << 7) | ||
| 115 | |||
| 116 | #define DP_SINK_STATUS 0x205 | ||
| 117 | |||
| 118 | #define DP_RECEIVE_PORT_0_STATUS (1 << 0) | ||
| 119 | #define DP_RECEIVE_PORT_1_STATUS (1 << 1) | ||
| 120 | |||
| 121 | #define DP_ADJUST_REQUEST_LANE0_1 0x206 | ||
| 122 | #define DP_ADJUST_REQUEST_LANE2_3 0x207 | ||
| 123 | |||
| 124 | #define DP_ADJUST_VOLTAGE_SWING_LANE0_MASK 0x03 | ||
| 125 | #define DP_ADJUST_VOLTAGE_SWING_LANE0_SHIFT 0 | ||
| 126 | #define DP_ADJUST_PRE_EMPHASIS_LANE0_MASK 0x0c | ||
| 127 | #define DP_ADJUST_PRE_EMPHASIS_LANE0_SHIFT 2 | ||
| 128 | #define DP_ADJUST_VOLTAGE_SWING_LANE1_MASK 0x30 | ||
| 129 | #define DP_ADJUST_VOLTAGE_SWING_LANE1_SHIFT 4 | ||
| 130 | #define DP_ADJUST_PRE_EMPHASIS_LANE1_MASK 0xc0 | ||
| 131 | #define DP_ADJUST_PRE_EMPHASIS_LANE1_SHIFT 6 | ||
| 132 | |||
| 133 | struct i2c_algo_dp_aux_data { | ||
| 134 | bool running; | ||
| 135 | u16 address; | ||
| 136 | int (*aux_ch) (struct i2c_adapter *adapter, | ||
| 137 | uint8_t *send, int send_bytes, | ||
| 138 | uint8_t *recv, int recv_bytes); | ||
| 139 | }; | ||
| 140 | |||
| 141 | int | ||
| 142 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter); | ||
| 143 | |||
| 144 | #endif /* _INTEL_DP_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/intel_dp_i2c.c b/drivers/gpu/drm/i915/intel_dp_i2c.c new file mode 100644 index 000000000000..4e60f14b1a6d --- /dev/null +++ b/drivers/gpu/drm/i915/intel_dp_i2c.c | |||
| @@ -0,0 +1,272 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2009 Keith Packard | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, distribute, and sell this software and its | ||
| 5 | * documentation for any purpose is hereby granted without fee, provided that | ||
| 6 | * the above copyright notice appear in all copies and that both that copyright | ||
| 7 | * notice and this permission notice appear in supporting documentation, and | ||
| 8 | * that the name of the copyright holders not be used in advertising or | ||
| 9 | * publicity pertaining to distribution of the software without specific, | ||
| 10 | * written prior permission. The copyright holders make no representations | ||
| 11 | * about the suitability of this software for any purpose. It is provided "as | ||
| 12 | * is" without express or implied warranty. | ||
| 13 | * | ||
| 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
| 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | ||
| 16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | ||
| 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | ||
| 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | ||
| 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | ||
| 20 | * OF THIS SOFTWARE. | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <linux/init.h> | ||
| 28 | #include <linux/errno.h> | ||
| 29 | #include <linux/sched.h> | ||
| 30 | #include <linux/i2c.h> | ||
| 31 | #include "intel_dp.h" | ||
| 32 | |||
| 33 | /* Run a single AUX_CH I2C transaction, writing/reading data as necessary */ | ||
| 34 | |||
| 35 | #define MODE_I2C_START 1 | ||
| 36 | #define MODE_I2C_WRITE 2 | ||
| 37 | #define MODE_I2C_READ 4 | ||
| 38 | #define MODE_I2C_STOP 8 | ||
| 39 | |||
| 40 | static int | ||
| 41 | i2c_algo_dp_aux_transaction(struct i2c_adapter *adapter, int mode, | ||
| 42 | uint8_t write_byte, uint8_t *read_byte) | ||
| 43 | { | ||
| 44 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 45 | uint16_t address = algo_data->address; | ||
| 46 | uint8_t msg[5]; | ||
| 47 | uint8_t reply[2]; | ||
| 48 | int msg_bytes; | ||
| 49 | int reply_bytes; | ||
| 50 | int ret; | ||
| 51 | |||
| 52 | /* Set up the command byte */ | ||
| 53 | if (mode & MODE_I2C_READ) | ||
| 54 | msg[0] = AUX_I2C_READ << 4; | ||
| 55 | else | ||
| 56 | msg[0] = AUX_I2C_WRITE << 4; | ||
| 57 | |||
| 58 | if (!(mode & MODE_I2C_STOP)) | ||
| 59 | msg[0] |= AUX_I2C_MOT << 4; | ||
| 60 | |||
| 61 | msg[1] = address >> 8; | ||
| 62 | msg[2] = address; | ||
| 63 | |||
| 64 | switch (mode) { | ||
| 65 | case MODE_I2C_WRITE: | ||
| 66 | msg[3] = 0; | ||
| 67 | msg[4] = write_byte; | ||
| 68 | msg_bytes = 5; | ||
| 69 | reply_bytes = 1; | ||
| 70 | break; | ||
| 71 | case MODE_I2C_READ: | ||
| 72 | msg[3] = 0; | ||
| 73 | msg_bytes = 4; | ||
| 74 | reply_bytes = 2; | ||
| 75 | break; | ||
| 76 | default: | ||
| 77 | msg_bytes = 3; | ||
| 78 | reply_bytes = 1; | ||
| 79 | break; | ||
| 80 | } | ||
| 81 | |||
| 82 | for (;;) { | ||
| 83 | ret = (*algo_data->aux_ch)(adapter, | ||
| 84 | msg, msg_bytes, | ||
| 85 | reply, reply_bytes); | ||
| 86 | if (ret < 0) { | ||
| 87 | printk(KERN_ERR "aux_ch failed %d\n", ret); | ||
| 88 | return ret; | ||
| 89 | } | ||
| 90 | switch (reply[0] & AUX_I2C_REPLY_MASK) { | ||
| 91 | case AUX_I2C_REPLY_ACK: | ||
| 92 | if (mode == MODE_I2C_READ) { | ||
| 93 | *read_byte = reply[1]; | ||
| 94 | } | ||
| 95 | return reply_bytes - 1; | ||
| 96 | case AUX_I2C_REPLY_NACK: | ||
| 97 | printk(KERN_ERR "aux_ch nack\n"); | ||
| 98 | return -EREMOTEIO; | ||
| 99 | case AUX_I2C_REPLY_DEFER: | ||
| 100 | printk(KERN_ERR "aux_ch defer\n"); | ||
| 101 | udelay(100); | ||
| 102 | break; | ||
| 103 | default: | ||
| 104 | printk(KERN_ERR "aux_ch invalid reply 0x%02x\n", reply[0]); | ||
| 105 | return -EREMOTEIO; | ||
| 106 | } | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | /* | ||
| 111 | * I2C over AUX CH | ||
| 112 | */ | ||
| 113 | |||
| 114 | /* | ||
| 115 | * Send the address. If the I2C link is running, this 'restarts' | ||
| 116 | * the connection with the new address, this is used for doing | ||
| 117 | * a write followed by a read (as needed for DDC) | ||
| 118 | */ | ||
| 119 | static int | ||
| 120 | i2c_algo_dp_aux_address(struct i2c_adapter *adapter, u16 address, bool reading) | ||
| 121 | { | ||
| 122 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 123 | int mode = MODE_I2C_START; | ||
| 124 | int ret; | ||
| 125 | |||
| 126 | if (reading) | ||
| 127 | mode |= MODE_I2C_READ; | ||
| 128 | else | ||
| 129 | mode |= MODE_I2C_WRITE; | ||
| 130 | algo_data->address = address; | ||
| 131 | algo_data->running = true; | ||
| 132 | ret = i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | /* | ||
| 137 | * Stop the I2C transaction. This closes out the link, sending | ||
| 138 | * a bare address packet with the MOT bit turned off | ||
| 139 | */ | ||
| 140 | static void | ||
| 141 | i2c_algo_dp_aux_stop(struct i2c_adapter *adapter, bool reading) | ||
| 142 | { | ||
| 143 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 144 | int mode = MODE_I2C_STOP; | ||
| 145 | |||
| 146 | if (reading) | ||
| 147 | mode |= MODE_I2C_READ; | ||
| 148 | else | ||
| 149 | mode |= MODE_I2C_WRITE; | ||
| 150 | if (algo_data->running) { | ||
| 151 | (void) i2c_algo_dp_aux_transaction(adapter, mode, 0, NULL); | ||
| 152 | algo_data->running = false; | ||
| 153 | } | ||
| 154 | } | ||
| 155 | |||
| 156 | /* | ||
| 157 | * Write a single byte to the current I2C address, the | ||
| 158 | * the I2C link must be running or this returns -EIO | ||
| 159 | */ | ||
| 160 | static int | ||
| 161 | i2c_algo_dp_aux_put_byte(struct i2c_adapter *adapter, u8 byte) | ||
| 162 | { | ||
| 163 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 164 | int ret; | ||
| 165 | |||
| 166 | if (!algo_data->running) | ||
| 167 | return -EIO; | ||
| 168 | |||
| 169 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_WRITE, byte, NULL); | ||
| 170 | return ret; | ||
| 171 | } | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Read a single byte from the current I2C address, the | ||
| 175 | * I2C link must be running or this returns -EIO | ||
| 176 | */ | ||
| 177 | static int | ||
| 178 | i2c_algo_dp_aux_get_byte(struct i2c_adapter *adapter, u8 *byte_ret) | ||
| 179 | { | ||
| 180 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | ||
| 181 | int ret; | ||
| 182 | |||
| 183 | if (!algo_data->running) | ||
| 184 | return -EIO; | ||
| 185 | |||
| 186 | ret = i2c_algo_dp_aux_transaction(adapter, MODE_I2C_READ, 0, byte_ret); | ||
| 187 | return ret; | ||
| 188 | } | ||
| 189 | |||
| 190 | static int | ||
| 191 | i2c_algo_dp_aux_xfer(struct i2c_adapter *adapter, | ||
| 192 | struct i2c_msg *msgs, | ||
| 193 | int num) | ||
| 194 | { | ||
| 195 | int ret = 0; | ||
| 196 | bool reading = false; | ||
| 197 | int m; | ||
| 198 | int b; | ||
| 199 | |||
| 200 | for (m = 0; m < num; m++) { | ||
| 201 | u16 len = msgs[m].len; | ||
| 202 | u8 *buf = msgs[m].buf; | ||
| 203 | reading = (msgs[m].flags & I2C_M_RD) != 0; | ||
| 204 | ret = i2c_algo_dp_aux_address(adapter, msgs[m].addr, reading); | ||
| 205 | if (ret < 0) | ||
| 206 | break; | ||
| 207 | if (reading) { | ||
| 208 | for (b = 0; b < len; b++) { | ||
| 209 | ret = i2c_algo_dp_aux_get_byte(adapter, &buf[b]); | ||
| 210 | if (ret < 0) | ||
| 211 | break; | ||
| 212 | } | ||
| 213 | } else { | ||
| 214 | for (b = 0; b < len; b++) { | ||
| 215 | ret = i2c_algo_dp_aux_put_byte(adapter, buf[b]); | ||
| 216 | if (ret < 0) | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | if (ret < 0) | ||
| 221 | break; | ||
| 222 | } | ||
| 223 | if (ret >= 0) | ||
| 224 | ret = num; | ||
| 225 | i2c_algo_dp_aux_stop(adapter, reading); | ||
| 226 | printk(KERN_ERR "dp_aux_xfer return %d\n", ret); | ||
| 227 | return ret; | ||
| 228 | } | ||
| 229 | |||
| 230 | static u32 | ||
| 231 | i2c_algo_dp_aux_functionality(struct i2c_adapter *adapter) | ||
| 232 | { | ||
| 233 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | | ||
| 234 | I2C_FUNC_SMBUS_READ_BLOCK_DATA | | ||
| 235 | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | | ||
| 236 | I2C_FUNC_10BIT_ADDR; | ||
| 237 | } | ||
| 238 | |||
| 239 | static const struct i2c_algorithm i2c_dp_aux_algo = { | ||
| 240 | .master_xfer = i2c_algo_dp_aux_xfer, | ||
| 241 | .functionality = i2c_algo_dp_aux_functionality, | ||
| 242 | }; | ||
| 243 | |||
| 244 | static void | ||
| 245 | i2c_dp_aux_reset_bus(struct i2c_adapter *adapter) | ||
| 246 | { | ||
| 247 | (void) i2c_algo_dp_aux_address(adapter, 0, false); | ||
| 248 | (void) i2c_algo_dp_aux_stop(adapter, false); | ||
| 249 | |||
| 250 | } | ||
| 251 | |||
| 252 | static int | ||
| 253 | i2c_dp_aux_prepare_bus(struct i2c_adapter *adapter) | ||
| 254 | { | ||
| 255 | adapter->algo = &i2c_dp_aux_algo; | ||
| 256 | adapter->retries = 3; | ||
| 257 | i2c_dp_aux_reset_bus(adapter); | ||
| 258 | return 0; | ||
| 259 | } | ||
| 260 | |||
| 261 | int | ||
| 262 | i2c_dp_aux_add_bus(struct i2c_adapter *adapter) | ||
| 263 | { | ||
| 264 | int error; | ||
| 265 | |||
| 266 | error = i2c_dp_aux_prepare_bus(adapter); | ||
| 267 | if (error) | ||
| 268 | return error; | ||
| 269 | error = i2c_add_adapter(adapter); | ||
| 270 | return error; | ||
| 271 | } | ||
| 272 | EXPORT_SYMBOL(i2c_dp_aux_add_bus); | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index cd4b9c5f715e..004541c935a8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #define INTEL_OUTPUT_LVDS 4 | 54 | #define INTEL_OUTPUT_LVDS 4 |
| 55 | #define INTEL_OUTPUT_TVOUT 5 | 55 | #define INTEL_OUTPUT_TVOUT 5 |
| 56 | #define INTEL_OUTPUT_HDMI 6 | 56 | #define INTEL_OUTPUT_HDMI 6 |
| 57 | #define INTEL_OUTPUT_DISPLAYPORT 7 | ||
| 57 | 58 | ||
| 58 | #define INTEL_DVO_CHIP_NONE 0 | 59 | #define INTEL_DVO_CHIP_NONE 0 |
| 59 | #define INTEL_DVO_CHIP_LVDS 1 | 60 | #define INTEL_DVO_CHIP_LVDS 1 |
| @@ -65,7 +66,6 @@ struct intel_i2c_chan { | |||
| 65 | u32 reg; /* GPIO reg */ | 66 | u32 reg; /* GPIO reg */ |
| 66 | struct i2c_adapter adapter; | 67 | struct i2c_adapter adapter; |
| 67 | struct i2c_algo_bit_data algo; | 68 | struct i2c_algo_bit_data algo; |
| 68 | u8 slave_addr; | ||
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | struct intel_framebuffer { | 71 | struct intel_framebuffer { |
| @@ -79,11 +79,12 @@ struct intel_output { | |||
| 79 | 79 | ||
| 80 | struct drm_encoder enc; | 80 | struct drm_encoder enc; |
| 81 | int type; | 81 | int type; |
| 82 | struct intel_i2c_chan *i2c_bus; /* for control functions */ | 82 | struct i2c_adapter *i2c_bus; |
| 83 | struct intel_i2c_chan *ddc_bus; /* for DDC only stuff */ | 83 | struct i2c_adapter *ddc_bus; |
| 84 | bool load_detect_temp; | 84 | bool load_detect_temp; |
| 85 | bool needs_tv_clock; | 85 | bool needs_tv_clock; |
| 86 | void *dev_priv; | 86 | void *dev_priv; |
| 87 | void (*hot_plug)(struct intel_output *); | ||
| 87 | }; | 88 | }; |
| 88 | 89 | ||
| 89 | struct intel_crtc { | 90 | struct intel_crtc { |
| @@ -104,9 +105,9 @@ struct intel_crtc { | |||
| 104 | #define enc_to_intel_output(x) container_of(x, struct intel_output, enc) | 105 | #define enc_to_intel_output(x) container_of(x, struct intel_output, enc) |
| 105 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) | 106 | #define to_intel_framebuffer(x) container_of(x, struct intel_framebuffer, base) |
| 106 | 107 | ||
| 107 | struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | 108 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, |
| 108 | const char *name); | 109 | const char *name); |
| 109 | void intel_i2c_destroy(struct intel_i2c_chan *chan); | 110 | void intel_i2c_destroy(struct i2c_adapter *adapter); |
| 110 | int intel_ddc_get_modes(struct intel_output *intel_output); | 111 | int intel_ddc_get_modes(struct intel_output *intel_output); |
| 111 | extern bool intel_ddc_probe(struct intel_output *intel_output); | 112 | extern bool intel_ddc_probe(struct intel_output *intel_output); |
| 112 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable); | 113 | void intel_i2c_quirk_set(struct drm_device *dev, bool enable); |
| @@ -116,6 +117,10 @@ extern bool intel_sdvo_init(struct drm_device *dev, int output_device); | |||
| 116 | extern void intel_dvo_init(struct drm_device *dev); | 117 | extern void intel_dvo_init(struct drm_device *dev); |
| 117 | extern void intel_tv_init(struct drm_device *dev); | 118 | extern void intel_tv_init(struct drm_device *dev); |
| 118 | extern void intel_lvds_init(struct drm_device *dev); | 119 | extern void intel_lvds_init(struct drm_device *dev); |
| 120 | extern void intel_dp_init(struct drm_device *dev, int dp_reg); | ||
| 121 | void | ||
| 122 | intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||
| 123 | struct drm_display_mode *adjusted_mode); | ||
| 119 | 124 | ||
| 120 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); | 125 | extern void intel_crtc_load_lut(struct drm_crtc *crtc); |
| 121 | extern void intel_encoder_prepare (struct drm_encoder *encoder); | 126 | extern void intel_encoder_prepare (struct drm_encoder *encoder); |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 1ee3007d6ec0..13bff20930e8 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -384,10 +384,9 @@ void intel_dvo_init(struct drm_device *dev) | |||
| 384 | { | 384 | { |
| 385 | struct intel_output *intel_output; | 385 | struct intel_output *intel_output; |
| 386 | struct intel_dvo_device *dvo; | 386 | struct intel_dvo_device *dvo; |
| 387 | struct intel_i2c_chan *i2cbus = NULL; | 387 | struct i2c_adapter *i2cbus = NULL; |
| 388 | int ret = 0; | 388 | int ret = 0; |
| 389 | int i; | 389 | int i; |
| 390 | int gpio_inited = 0; | ||
| 391 | int encoder_type = DRM_MODE_ENCODER_NONE; | 390 | int encoder_type = DRM_MODE_ENCODER_NONE; |
| 392 | intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); | 391 | intel_output = kzalloc (sizeof(struct intel_output), GFP_KERNEL); |
| 393 | if (!intel_output) | 392 | if (!intel_output) |
| @@ -420,14 +419,11 @@ void intel_dvo_init(struct drm_device *dev) | |||
| 420 | * It appears that everything is on GPIOE except for panels | 419 | * It appears that everything is on GPIOE except for panels |
| 421 | * on i830 laptops, which are on GPIOB (DVOA). | 420 | * on i830 laptops, which are on GPIOB (DVOA). |
| 422 | */ | 421 | */ |
| 423 | if (gpio_inited != gpio) { | 422 | if (i2cbus != NULL) |
| 424 | if (i2cbus != NULL) | 423 | intel_i2c_destroy(i2cbus); |
| 425 | intel_i2c_destroy(i2cbus); | 424 | if (!(i2cbus = intel_i2c_create(dev, gpio, |
| 426 | if (!(i2cbus = intel_i2c_create(dev, gpio, | 425 | gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { |
| 427 | gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E"))) { | 426 | continue; |
| 428 | continue; | ||
| 429 | } | ||
| 430 | gpio_inited = gpio; | ||
| 431 | } | 427 | } |
| 432 | 428 | ||
| 433 | if (dvo->dev_ops!= NULL) | 429 | if (dvo->dev_ops!= NULL) |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4ea2a651b92c..9e30daae37dc 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "drmP.h" | 31 | #include "drmP.h" |
| 32 | #include "drm.h" | 32 | #include "drm.h" |
| 33 | #include "drm_crtc.h" | 33 | #include "drm_crtc.h" |
| 34 | #include "drm_edid.h" | ||
| 34 | #include "intel_drv.h" | 35 | #include "intel_drv.h" |
| 35 | #include "i915_drm.h" | 36 | #include "i915_drm.h" |
| 36 | #include "i915_drv.h" | 37 | #include "i915_drv.h" |
| @@ -56,8 +57,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, | |||
| 56 | sdvox = SDVO_ENCODING_HDMI | | 57 | sdvox = SDVO_ENCODING_HDMI | |
| 57 | SDVO_BORDER_ENABLE | | 58 | SDVO_BORDER_ENABLE | |
| 58 | SDVO_VSYNC_ACTIVE_HIGH | | 59 | SDVO_VSYNC_ACTIVE_HIGH | |
| 59 | SDVO_HSYNC_ACTIVE_HIGH | | 60 | SDVO_HSYNC_ACTIVE_HIGH; |
| 60 | SDVO_NULL_PACKETS_DURING_VSYNC; | ||
| 61 | 61 | ||
| 62 | if (hdmi_priv->has_hdmi_sink) | 62 | if (hdmi_priv->has_hdmi_sink) |
| 63 | sdvox |= SDVO_AUDIO_ENABLE; | 63 | sdvox |= SDVO_AUDIO_ENABLE; |
| @@ -129,20 +129,26 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder, | |||
| 129 | return true; | 129 | return true; |
| 130 | } | 130 | } |
| 131 | 131 | ||
| 132 | static void | 132 | static enum drm_connector_status |
| 133 | intel_hdmi_sink_detect(struct drm_connector *connector) | 133 | intel_hdmi_edid_detect(struct drm_connector *connector) |
| 134 | { | 134 | { |
| 135 | struct intel_output *intel_output = to_intel_output(connector); | 135 | struct intel_output *intel_output = to_intel_output(connector); |
| 136 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; | 136 | struct intel_hdmi_priv *hdmi_priv = intel_output->dev_priv; |
| 137 | struct edid *edid = NULL; | 137 | struct edid *edid = NULL; |
| 138 | enum drm_connector_status status = connector_status_disconnected; | ||
| 138 | 139 | ||
| 139 | edid = drm_get_edid(&intel_output->base, | 140 | edid = drm_get_edid(&intel_output->base, |
| 140 | &intel_output->ddc_bus->adapter); | 141 | intel_output->ddc_bus); |
| 141 | if (edid != NULL) { | 142 | hdmi_priv->has_hdmi_sink = false; |
| 142 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | 143 | if (edid) { |
| 143 | kfree(edid); | 144 | if (edid->input & DRM_EDID_INPUT_DIGITAL) { |
| 145 | status = connector_status_connected; | ||
| 146 | hdmi_priv->has_hdmi_sink = drm_detect_hdmi_monitor(edid); | ||
| 147 | } | ||
| 144 | intel_output->base.display_info.raw_edid = NULL; | 148 | intel_output->base.display_info.raw_edid = NULL; |
| 149 | kfree(edid); | ||
| 145 | } | 150 | } |
| 151 | return status; | ||
| 146 | } | 152 | } |
| 147 | 153 | ||
| 148 | static enum drm_connector_status | 154 | static enum drm_connector_status |
| @@ -154,11 +160,7 @@ igdng_hdmi_detect(struct drm_connector *connector) | |||
| 154 | /* FIXME hotplug detect */ | 160 | /* FIXME hotplug detect */ |
| 155 | 161 | ||
| 156 | hdmi_priv->has_hdmi_sink = false; | 162 | hdmi_priv->has_hdmi_sink = false; |
| 157 | intel_hdmi_sink_detect(connector); | 163 | return intel_hdmi_edid_detect(connector); |
| 158 | if (hdmi_priv->has_hdmi_sink) | ||
| 159 | return connector_status_connected; | ||
| 160 | else | ||
| 161 | return connector_status_disconnected; | ||
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | static enum drm_connector_status | 166 | static enum drm_connector_status |
| @@ -201,10 +203,9 @@ intel_hdmi_detect(struct drm_connector *connector) | |||
| 201 | return connector_status_unknown; | 203 | return connector_status_unknown; |
| 202 | } | 204 | } |
| 203 | 205 | ||
| 204 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) { | 206 | if ((I915_READ(PORT_HOTPLUG_STAT) & bit) != 0) |
| 205 | intel_hdmi_sink_detect(connector); | 207 | return intel_hdmi_edid_detect(connector); |
| 206 | return connector_status_connected; | 208 | else |
| 207 | } else | ||
| 208 | return connector_status_disconnected; | 209 | return connector_status_disconnected; |
| 209 | } | 210 | } |
| 210 | 211 | ||
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index f7061f68d050..62b8bead7652 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
| @@ -124,6 +124,7 @@ static void set_data(void *data, int state_high) | |||
| 124 | * @output: driver specific output device | 124 | * @output: driver specific output device |
| 125 | * @reg: GPIO reg to use | 125 | * @reg: GPIO reg to use |
| 126 | * @name: name for this bus | 126 | * @name: name for this bus |
| 127 | * @slave_addr: slave address (if fixed) | ||
| 127 | * | 128 | * |
| 128 | * Creates and registers a new i2c bus with the Linux i2c layer, for use | 129 | * Creates and registers a new i2c bus with the Linux i2c layer, for use |
| 129 | * in output probing and control (e.g. DDC or SDVO control functions). | 130 | * in output probing and control (e.g. DDC or SDVO control functions). |
| @@ -139,8 +140,8 @@ static void set_data(void *data, int state_high) | |||
| 139 | * %GPIOH | 140 | * %GPIOH |
| 140 | * see PRM for details on how these different busses are used. | 141 | * see PRM for details on how these different busses are used. |
| 141 | */ | 142 | */ |
| 142 | struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | 143 | struct i2c_adapter *intel_i2c_create(struct drm_device *dev, const u32 reg, |
| 143 | const char *name) | 144 | const char *name) |
| 144 | { | 145 | { |
| 145 | struct intel_i2c_chan *chan; | 146 | struct intel_i2c_chan *chan; |
| 146 | 147 | ||
| @@ -174,7 +175,7 @@ struct intel_i2c_chan *intel_i2c_create(struct drm_device *dev, const u32 reg, | |||
| 174 | intel_i2c_quirk_set(dev, false); | 175 | intel_i2c_quirk_set(dev, false); |
| 175 | udelay(20); | 176 | udelay(20); |
| 176 | 177 | ||
| 177 | return chan; | 178 | return &chan->adapter; |
| 178 | 179 | ||
| 179 | out_free: | 180 | out_free: |
| 180 | kfree(chan); | 181 | kfree(chan); |
| @@ -187,11 +188,16 @@ out_free: | |||
| 187 | * | 188 | * |
| 188 | * Unregister the adapter from the i2c layer, then free the structure. | 189 | * Unregister the adapter from the i2c layer, then free the structure. |
| 189 | */ | 190 | */ |
| 190 | void intel_i2c_destroy(struct intel_i2c_chan *chan) | 191 | void intel_i2c_destroy(struct i2c_adapter *adapter) |
| 191 | { | 192 | { |
| 192 | if (!chan) | 193 | struct intel_i2c_chan *chan; |
| 194 | |||
| 195 | if (!adapter) | ||
| 193 | return; | 196 | return; |
| 194 | 197 | ||
| 198 | chan = container_of(adapter, | ||
| 199 | struct intel_i2c_chan, | ||
| 200 | adapter); | ||
| 195 | i2c_del_adapter(&chan->adapter); | 201 | i2c_del_adapter(&chan->adapter); |
| 196 | kfree(chan); | 202 | kfree(chan); |
| 197 | } | 203 | } |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index f073ed8432e8..9564ca44a977 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -39,6 +39,21 @@ | |||
| 39 | 39 | ||
| 40 | #define I915_LVDS "i915_lvds" | 40 | #define I915_LVDS "i915_lvds" |
| 41 | 41 | ||
| 42 | /* | ||
| 43 | * the following four scaling options are defined. | ||
| 44 | * #define DRM_MODE_SCALE_NON_GPU 0 | ||
| 45 | * #define DRM_MODE_SCALE_FULLSCREEN 1 | ||
| 46 | * #define DRM_MODE_SCALE_NO_SCALE 2 | ||
| 47 | * #define DRM_MODE_SCALE_ASPECT 3 | ||
| 48 | */ | ||
| 49 | |||
| 50 | /* Private structure for the integrated LVDS support */ | ||
| 51 | struct intel_lvds_priv { | ||
| 52 | int fitting_mode; | ||
| 53 | u32 pfit_control; | ||
| 54 | u32 pfit_pgm_ratios; | ||
| 55 | }; | ||
| 56 | |||
| 42 | /** | 57 | /** |
| 43 | * Sets the backlight level. | 58 | * Sets the backlight level. |
| 44 | * | 59 | * |
| @@ -213,10 +228,27 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 213 | struct drm_display_mode *mode, | 228 | struct drm_display_mode *mode, |
| 214 | struct drm_display_mode *adjusted_mode) | 229 | struct drm_display_mode *adjusted_mode) |
| 215 | { | 230 | { |
| 231 | /* | ||
| 232 | * float point operation is not supported . So the PANEL_RATIO_FACTOR | ||
| 233 | * is defined, which can avoid the float point computation when | ||
| 234 | * calculating the panel ratio. | ||
| 235 | */ | ||
| 236 | #define PANEL_RATIO_FACTOR 8192 | ||
| 216 | struct drm_device *dev = encoder->dev; | 237 | struct drm_device *dev = encoder->dev; |
| 217 | struct drm_i915_private *dev_priv = dev->dev_private; | 238 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 218 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 239 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
| 219 | struct drm_encoder *tmp_encoder; | 240 | struct drm_encoder *tmp_encoder; |
| 241 | struct intel_output *intel_output = enc_to_intel_output(encoder); | ||
| 242 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | ||
| 243 | u32 pfit_control = 0, pfit_pgm_ratios = 0; | ||
| 244 | int left_border = 0, right_border = 0, top_border = 0; | ||
| 245 | int bottom_border = 0; | ||
| 246 | bool border = 0; | ||
| 247 | int panel_ratio, desired_ratio, vert_scale, horiz_scale; | ||
| 248 | int horiz_ratio, vert_ratio; | ||
| 249 | u32 hsync_width, vsync_width; | ||
| 250 | u32 hblank_width, vblank_width; | ||
| 251 | u32 hsync_pos, vsync_pos; | ||
| 220 | 252 | ||
| 221 | /* Should never happen!! */ | 253 | /* Should never happen!! */ |
| 222 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { | 254 | if (!IS_I965G(dev) && intel_crtc->pipe == 0) { |
| @@ -232,7 +264,9 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 232 | return false; | 264 | return false; |
| 233 | } | 265 | } |
| 234 | } | 266 | } |
| 235 | 267 | /* If we don't have a panel mode, there is nothing we can do */ | |
| 268 | if (dev_priv->panel_fixed_mode == NULL) | ||
| 269 | return true; | ||
| 236 | /* | 270 | /* |
| 237 | * If we have timings from the BIOS for the panel, put them in | 271 | * If we have timings from the BIOS for the panel, put them in |
| 238 | * to the adjusted mode. The CRTC will be set up for this mode, | 272 | * to the adjusted mode. The CRTC will be set up for this mode, |
| @@ -256,6 +290,243 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
| 256 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | 290 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); |
| 257 | } | 291 | } |
| 258 | 292 | ||
| 293 | /* Make sure pre-965s set dither correctly */ | ||
| 294 | if (!IS_I965G(dev)) { | ||
| 295 | if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) | ||
| 296 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
| 297 | } | ||
| 298 | |||
| 299 | /* Native modes don't need fitting */ | ||
| 300 | if (adjusted_mode->hdisplay == mode->hdisplay && | ||
| 301 | adjusted_mode->vdisplay == mode->vdisplay) { | ||
| 302 | pfit_pgm_ratios = 0; | ||
| 303 | border = 0; | ||
| 304 | goto out; | ||
| 305 | } | ||
| 306 | |||
| 307 | /* 965+ wants fuzzy fitting */ | ||
| 308 | if (IS_I965G(dev)) | ||
| 309 | pfit_control |= (intel_crtc->pipe << PFIT_PIPE_SHIFT) | | ||
| 310 | PFIT_FILTER_FUZZY; | ||
| 311 | |||
| 312 | hsync_width = adjusted_mode->crtc_hsync_end - | ||
| 313 | adjusted_mode->crtc_hsync_start; | ||
| 314 | vsync_width = adjusted_mode->crtc_vsync_end - | ||
| 315 | adjusted_mode->crtc_vsync_start; | ||
| 316 | hblank_width = adjusted_mode->crtc_hblank_end - | ||
| 317 | adjusted_mode->crtc_hblank_start; | ||
| 318 | vblank_width = adjusted_mode->crtc_vblank_end - | ||
| 319 | adjusted_mode->crtc_vblank_start; | ||
| 320 | /* | ||
| 321 | * Deal with panel fitting options. Figure out how to stretch the | ||
| 322 | * image based on its aspect ratio & the current panel fitting mode. | ||
| 323 | */ | ||
| 324 | panel_ratio = adjusted_mode->hdisplay * PANEL_RATIO_FACTOR / | ||
| 325 | adjusted_mode->vdisplay; | ||
| 326 | desired_ratio = mode->hdisplay * PANEL_RATIO_FACTOR / | ||
| 327 | mode->vdisplay; | ||
| 328 | /* | ||
| 329 | * Enable automatic panel scaling for non-native modes so that they fill | ||
| 330 | * the screen. Should be enabled before the pipe is enabled, according | ||
| 331 | * to register description and PRM. | ||
| 332 | * Change the value here to see the borders for debugging | ||
| 333 | */ | ||
| 334 | I915_WRITE(BCLRPAT_A, 0); | ||
| 335 | I915_WRITE(BCLRPAT_B, 0); | ||
| 336 | |||
| 337 | switch (lvds_priv->fitting_mode) { | ||
| 338 | case DRM_MODE_SCALE_NO_SCALE: | ||
| 339 | /* | ||
| 340 | * For centered modes, we have to calculate border widths & | ||
| 341 | * heights and modify the values programmed into the CRTC. | ||
| 342 | */ | ||
| 343 | left_border = (adjusted_mode->hdisplay - mode->hdisplay) / 2; | ||
| 344 | right_border = left_border; | ||
| 345 | if (mode->hdisplay & 1) | ||
| 346 | right_border++; | ||
| 347 | top_border = (adjusted_mode->vdisplay - mode->vdisplay) / 2; | ||
| 348 | bottom_border = top_border; | ||
| 349 | if (mode->vdisplay & 1) | ||
| 350 | bottom_border++; | ||
| 351 | /* Set active & border values */ | ||
| 352 | adjusted_mode->crtc_hdisplay = mode->hdisplay; | ||
| 353 | /* Keep the boder be even */ | ||
| 354 | if (right_border & 1) | ||
| 355 | right_border++; | ||
| 356 | /* use the border directly instead of border minuse one */ | ||
| 357 | adjusted_mode->crtc_hblank_start = mode->hdisplay + | ||
| 358 | right_border; | ||
| 359 | /* keep the blank width constant */ | ||
| 360 | adjusted_mode->crtc_hblank_end = | ||
| 361 | adjusted_mode->crtc_hblank_start + hblank_width; | ||
| 362 | /* get the hsync pos relative to hblank start */ | ||
| 363 | hsync_pos = (hblank_width - hsync_width) / 2; | ||
| 364 | /* keep the hsync pos be even */ | ||
| 365 | if (hsync_pos & 1) | ||
| 366 | hsync_pos++; | ||
| 367 | adjusted_mode->crtc_hsync_start = | ||
| 368 | adjusted_mode->crtc_hblank_start + hsync_pos; | ||
| 369 | /* keep the hsync width constant */ | ||
| 370 | adjusted_mode->crtc_hsync_end = | ||
| 371 | adjusted_mode->crtc_hsync_start + hsync_width; | ||
| 372 | adjusted_mode->crtc_vdisplay = mode->vdisplay; | ||
| 373 | /* use the border instead of border minus one */ | ||
| 374 | adjusted_mode->crtc_vblank_start = mode->vdisplay + | ||
| 375 | bottom_border; | ||
| 376 | /* keep the vblank width constant */ | ||
| 377 | adjusted_mode->crtc_vblank_end = | ||
| 378 | adjusted_mode->crtc_vblank_start + vblank_width; | ||
| 379 | /* get the vsync start postion relative to vblank start */ | ||
| 380 | vsync_pos = (vblank_width - vsync_width) / 2; | ||
| 381 | adjusted_mode->crtc_vsync_start = | ||
| 382 | adjusted_mode->crtc_vblank_start + vsync_pos; | ||
| 383 | /* keep the vsync width constant */ | ||
| 384 | adjusted_mode->crtc_vsync_end = | ||
| 385 | adjusted_mode->crtc_vblank_start + vsync_width; | ||
| 386 | border = 1; | ||
| 387 | break; | ||
| 388 | case DRM_MODE_SCALE_ASPECT: | ||
| 389 | /* Scale but preserve the spect ratio */ | ||
| 390 | pfit_control |= PFIT_ENABLE; | ||
| 391 | if (IS_I965G(dev)) { | ||
| 392 | /* 965+ is easy, it does everything in hw */ | ||
| 393 | if (panel_ratio > desired_ratio) | ||
| 394 | pfit_control |= PFIT_SCALING_PILLAR; | ||
| 395 | else if (panel_ratio < desired_ratio) | ||
| 396 | pfit_control |= PFIT_SCALING_LETTER; | ||
| 397 | else | ||
| 398 | pfit_control |= PFIT_SCALING_AUTO; | ||
| 399 | } else { | ||
| 400 | /* | ||
| 401 | * For earlier chips we have to calculate the scaling | ||
| 402 | * ratio by hand and program it into the | ||
| 403 | * PFIT_PGM_RATIO register | ||
| 404 | */ | ||
| 405 | u32 horiz_bits, vert_bits, bits = 12; | ||
| 406 | horiz_ratio = mode->hdisplay * PANEL_RATIO_FACTOR/ | ||
| 407 | adjusted_mode->hdisplay; | ||
| 408 | vert_ratio = mode->vdisplay * PANEL_RATIO_FACTOR/ | ||
| 409 | adjusted_mode->vdisplay; | ||
| 410 | horiz_scale = adjusted_mode->hdisplay * | ||
| 411 | PANEL_RATIO_FACTOR / mode->hdisplay; | ||
| 412 | vert_scale = adjusted_mode->vdisplay * | ||
| 413 | PANEL_RATIO_FACTOR / mode->vdisplay; | ||
| 414 | |||
| 415 | /* retain aspect ratio */ | ||
| 416 | if (panel_ratio > desired_ratio) { /* Pillar */ | ||
| 417 | u32 scaled_width; | ||
| 418 | scaled_width = mode->hdisplay * vert_scale / | ||
| 419 | PANEL_RATIO_FACTOR; | ||
| 420 | horiz_ratio = vert_ratio; | ||
| 421 | pfit_control |= (VERT_AUTO_SCALE | | ||
| 422 | VERT_INTERP_BILINEAR | | ||
| 423 | HORIZ_INTERP_BILINEAR); | ||
| 424 | /* Pillar will have left/right borders */ | ||
| 425 | left_border = (adjusted_mode->hdisplay - | ||
| 426 | scaled_width) / 2; | ||
| 427 | right_border = left_border; | ||
| 428 | if (mode->hdisplay & 1) /* odd resolutions */ | ||
| 429 | right_border++; | ||
| 430 | /* keep the border be even */ | ||
| 431 | if (right_border & 1) | ||
| 432 | right_border++; | ||
| 433 | adjusted_mode->crtc_hdisplay = scaled_width; | ||
| 434 | /* use border instead of border minus one */ | ||
| 435 | adjusted_mode->crtc_hblank_start = | ||
| 436 | scaled_width + right_border; | ||
| 437 | /* keep the hblank width constant */ | ||
| 438 | adjusted_mode->crtc_hblank_end = | ||
| 439 | adjusted_mode->crtc_hblank_start + | ||
| 440 | hblank_width; | ||
| 441 | /* | ||
| 442 | * get the hsync start pos relative to | ||
| 443 | * hblank start | ||
| 444 | */ | ||
| 445 | hsync_pos = (hblank_width - hsync_width) / 2; | ||
| 446 | /* keep the hsync_pos be even */ | ||
| 447 | if (hsync_pos & 1) | ||
| 448 | hsync_pos++; | ||
| 449 | adjusted_mode->crtc_hsync_start = | ||
| 450 | adjusted_mode->crtc_hblank_start + | ||
| 451 | hsync_pos; | ||
| 452 | /* keept hsync width constant */ | ||
| 453 | adjusted_mode->crtc_hsync_end = | ||
| 454 | adjusted_mode->crtc_hsync_start + | ||
| 455 | hsync_width; | ||
| 456 | border = 1; | ||
| 457 | } else if (panel_ratio < desired_ratio) { /* letter */ | ||
| 458 | u32 scaled_height = mode->vdisplay * | ||
| 459 | horiz_scale / PANEL_RATIO_FACTOR; | ||
| 460 | vert_ratio = horiz_ratio; | ||
| 461 | pfit_control |= (HORIZ_AUTO_SCALE | | ||
| 462 | VERT_INTERP_BILINEAR | | ||
| 463 | HORIZ_INTERP_BILINEAR); | ||
| 464 | /* Letterbox will have top/bottom border */ | ||
| 465 | top_border = (adjusted_mode->vdisplay - | ||
| 466 | scaled_height) / 2; | ||
| 467 | bottom_border = top_border; | ||
| 468 | if (mode->vdisplay & 1) | ||
| 469 | bottom_border++; | ||
| 470 | adjusted_mode->crtc_vdisplay = scaled_height; | ||
| 471 | /* use border instead of border minus one */ | ||
| 472 | adjusted_mode->crtc_vblank_start = | ||
| 473 | scaled_height + bottom_border; | ||
| 474 | /* keep the vblank width constant */ | ||
| 475 | adjusted_mode->crtc_vblank_end = | ||
| 476 | adjusted_mode->crtc_vblank_start + | ||
| 477 | vblank_width; | ||
| 478 | /* | ||
| 479 | * get the vsync start pos relative to | ||
| 480 | * vblank start | ||
| 481 | */ | ||
| 482 | vsync_pos = (vblank_width - vsync_width) / 2; | ||
| 483 | adjusted_mode->crtc_vsync_start = | ||
| 484 | adjusted_mode->crtc_vblank_start + | ||
| 485 | vsync_pos; | ||
| 486 | /* keep the vsync width constant */ | ||
| 487 | adjusted_mode->crtc_vsync_end = | ||
| 488 | adjusted_mode->crtc_vsync_start + | ||
| 489 | vsync_width; | ||
| 490 | border = 1; | ||
| 491 | } else { | ||
| 492 | /* Aspects match, Let hw scale both directions */ | ||
| 493 | pfit_control |= (VERT_AUTO_SCALE | | ||
| 494 | HORIZ_AUTO_SCALE | | ||
| 495 | VERT_INTERP_BILINEAR | | ||
| 496 | HORIZ_INTERP_BILINEAR); | ||
| 497 | } | ||
| 498 | horiz_bits = (1 << bits) * horiz_ratio / | ||
| 499 | PANEL_RATIO_FACTOR; | ||
| 500 | vert_bits = (1 << bits) * vert_ratio / | ||
| 501 | PANEL_RATIO_FACTOR; | ||
| 502 | pfit_pgm_ratios = | ||
| 503 | ((vert_bits << PFIT_VERT_SCALE_SHIFT) & | ||
| 504 | PFIT_VERT_SCALE_MASK) | | ||
| 505 | ((horiz_bits << PFIT_HORIZ_SCALE_SHIFT) & | ||
| 506 | PFIT_HORIZ_SCALE_MASK); | ||
| 507 | } | ||
| 508 | break; | ||
| 509 | |||
| 510 | case DRM_MODE_SCALE_FULLSCREEN: | ||
| 511 | /* | ||
| 512 | * Full scaling, even if it changes the aspect ratio. | ||
| 513 | * Fortunately this is all done for us in hw. | ||
| 514 | */ | ||
| 515 | pfit_control |= PFIT_ENABLE; | ||
| 516 | if (IS_I965G(dev)) | ||
| 517 | pfit_control |= PFIT_SCALING_AUTO; | ||
| 518 | else | ||
| 519 | pfit_control |= (VERT_AUTO_SCALE | HORIZ_AUTO_SCALE | | ||
| 520 | VERT_INTERP_BILINEAR | | ||
| 521 | HORIZ_INTERP_BILINEAR); | ||
| 522 | break; | ||
| 523 | default: | ||
| 524 | break; | ||
| 525 | } | ||
| 526 | |||
| 527 | out: | ||
| 528 | lvds_priv->pfit_control = pfit_control; | ||
| 529 | lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios; | ||
| 259 | /* | 530 | /* |
| 260 | * XXX: It would be nice to support lower refresh rates on the | 531 | * XXX: It would be nice to support lower refresh rates on the |
| 261 | * panels to reduce power consumption, and perhaps match the | 532 | * panels to reduce power consumption, and perhaps match the |
| @@ -301,8 +572,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 301 | { | 572 | { |
| 302 | struct drm_device *dev = encoder->dev; | 573 | struct drm_device *dev = encoder->dev; |
| 303 | struct drm_i915_private *dev_priv = dev->dev_private; | 574 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 304 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 575 | struct intel_output *intel_output = enc_to_intel_output(encoder); |
| 305 | u32 pfit_control; | 576 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; |
| 306 | 577 | ||
| 307 | /* | 578 | /* |
| 308 | * The LVDS pin pair will already have been turned on in the | 579 | * The LVDS pin pair will already have been turned on in the |
| @@ -319,22 +590,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 319 | * screen. Should be enabled before the pipe is enabled, according to | 590 | * screen. Should be enabled before the pipe is enabled, according to |
| 320 | * register description and PRM. | 591 | * register description and PRM. |
| 321 | */ | 592 | */ |
| 322 | if (mode->hdisplay != adjusted_mode->hdisplay || | 593 | I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios); |
| 323 | mode->vdisplay != adjusted_mode->vdisplay) | 594 | I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); |
| 324 | pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | | ||
| 325 | HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | | ||
| 326 | HORIZ_INTERP_BILINEAR); | ||
| 327 | else | ||
| 328 | pfit_control = 0; | ||
| 329 | |||
| 330 | if (!IS_I965G(dev)) { | ||
| 331 | if (dev_priv->panel_wants_dither || dev_priv->lvds_dither) | ||
| 332 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
| 333 | } | ||
| 334 | else | ||
| 335 | pfit_control |= intel_crtc->pipe << PFIT_PIPE_SHIFT; | ||
| 336 | |||
| 337 | I915_WRITE(PFIT_CONTROL, pfit_control); | ||
| 338 | } | 595 | } |
| 339 | 596 | ||
| 340 | /** | 597 | /** |
| @@ -406,6 +663,34 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
| 406 | struct drm_property *property, | 663 | struct drm_property *property, |
| 407 | uint64_t value) | 664 | uint64_t value) |
| 408 | { | 665 | { |
| 666 | struct drm_device *dev = connector->dev; | ||
| 667 | struct intel_output *intel_output = | ||
| 668 | to_intel_output(connector); | ||
| 669 | |||
| 670 | if (property == dev->mode_config.scaling_mode_property && | ||
| 671 | connector->encoder) { | ||
| 672 | struct drm_crtc *crtc = connector->encoder->crtc; | ||
| 673 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | ||
| 674 | if (value == DRM_MODE_SCALE_NON_GPU) { | ||
| 675 | DRM_DEBUG_KMS(I915_LVDS, | ||
| 676 | "non_GPU property is unsupported\n"); | ||
| 677 | return 0; | ||
| 678 | } | ||
| 679 | if (lvds_priv->fitting_mode == value) { | ||
| 680 | /* the LVDS scaling property is not changed */ | ||
| 681 | return 0; | ||
| 682 | } | ||
| 683 | lvds_priv->fitting_mode = value; | ||
| 684 | if (crtc && crtc->enabled) { | ||
| 685 | /* | ||
| 686 | * If the CRTC is enabled, the display will be changed | ||
| 687 | * according to the new panel fitting mode. | ||
| 688 | */ | ||
| 689 | drm_crtc_helper_set_mode(crtc, &crtc->mode, | ||
| 690 | crtc->x, crtc->y, crtc->fb); | ||
| 691 | } | ||
| 692 | } | ||
| 693 | |||
| 409 | return 0; | 694 | return 0; |
| 410 | } | 695 | } |
| 411 | 696 | ||
| @@ -456,7 +741,7 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 456 | .callback = intel_no_lvds_dmi_callback, | 741 | .callback = intel_no_lvds_dmi_callback, |
| 457 | .ident = "Apple Mac Mini (Core series)", | 742 | .ident = "Apple Mac Mini (Core series)", |
| 458 | .matches = { | 743 | .matches = { |
| 459 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 744 | DMI_MATCH(DMI_SYS_VENDOR, "Apple"), |
| 460 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), | 745 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), |
| 461 | }, | 746 | }, |
| 462 | }, | 747 | }, |
| @@ -464,7 +749,7 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
| 464 | .callback = intel_no_lvds_dmi_callback, | 749 | .callback = intel_no_lvds_dmi_callback, |
| 465 | .ident = "Apple Mac Mini (Core 2 series)", | 750 | .ident = "Apple Mac Mini (Core 2 series)", |
| 466 | .matches = { | 751 | .matches = { |
| 467 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 752 | DMI_MATCH(DMI_SYS_VENDOR, "Apple"), |
| 468 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"), | 753 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"), |
| 469 | }, | 754 | }, |
| 470 | }, | 755 | }, |
| @@ -518,6 +803,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 518 | struct drm_encoder *encoder; | 803 | struct drm_encoder *encoder; |
| 519 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 804 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
| 520 | struct drm_crtc *crtc; | 805 | struct drm_crtc *crtc; |
| 806 | struct intel_lvds_priv *lvds_priv; | ||
| 521 | u32 lvds; | 807 | u32 lvds; |
| 522 | int pipe, gpio = GPIOC; | 808 | int pipe, gpio = GPIOC; |
| 523 | 809 | ||
| @@ -531,7 +817,8 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 531 | gpio = PCH_GPIOC; | 817 | gpio = PCH_GPIOC; |
| 532 | } | 818 | } |
| 533 | 819 | ||
| 534 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 820 | intel_output = kzalloc(sizeof(struct intel_output) + |
| 821 | sizeof(struct intel_lvds_priv), GFP_KERNEL); | ||
| 535 | if (!intel_output) { | 822 | if (!intel_output) { |
| 536 | return; | 823 | return; |
| 537 | } | 824 | } |
| @@ -553,7 +840,18 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 553 | connector->interlace_allowed = false; | 840 | connector->interlace_allowed = false; |
| 554 | connector->doublescan_allowed = false; | 841 | connector->doublescan_allowed = false; |
| 555 | 842 | ||
| 843 | lvds_priv = (struct intel_lvds_priv *)(intel_output + 1); | ||
| 844 | intel_output->dev_priv = lvds_priv; | ||
| 845 | /* create the scaling mode property */ | ||
| 846 | drm_mode_create_scaling_mode_property(dev); | ||
| 847 | /* | ||
| 848 | * the initial panel fitting mode will be FULL_SCREEN. | ||
| 849 | */ | ||
| 556 | 850 | ||
| 851 | drm_connector_attach_property(&intel_output->base, | ||
| 852 | dev->mode_config.scaling_mode_property, | ||
| 853 | DRM_MODE_SCALE_FULLSCREEN); | ||
| 854 | lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; | ||
| 557 | /* | 855 | /* |
| 558 | * LVDS discovery: | 856 | * LVDS discovery: |
| 559 | * 1) check for EDID on DDC | 857 | * 1) check for EDID on DDC |
| @@ -649,5 +947,5 @@ failed: | |||
| 649 | if (intel_output->ddc_bus) | 947 | if (intel_output->ddc_bus) |
| 650 | intel_i2c_destroy(intel_output->ddc_bus); | 948 | intel_i2c_destroy(intel_output->ddc_bus); |
| 651 | drm_connector_cleanup(connector); | 949 | drm_connector_cleanup(connector); |
| 652 | kfree(connector); | 950 | kfree(intel_output); |
| 653 | } | 951 | } |
diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index e0910fefce87..67e2f4632a24 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c | |||
| @@ -53,10 +53,9 @@ bool intel_ddc_probe(struct intel_output *intel_output) | |||
| 53 | } | 53 | } |
| 54 | }; | 54 | }; |
| 55 | 55 | ||
| 56 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); | 56 | intel_i2c_quirk_set(intel_output->base.dev, true); |
| 57 | ret = i2c_transfer(&intel_output->ddc_bus->adapter, msgs, 2); | 57 | ret = i2c_transfer(intel_output->ddc_bus, msgs, 2); |
| 58 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); | 58 | intel_i2c_quirk_set(intel_output->base.dev, false); |
| 59 | |||
| 60 | if (ret == 2) | 59 | if (ret == 2) |
| 61 | return true; | 60 | return true; |
| 62 | 61 | ||
| @@ -74,10 +73,9 @@ int intel_ddc_get_modes(struct intel_output *intel_output) | |||
| 74 | struct edid *edid; | 73 | struct edid *edid; |
| 75 | int ret = 0; | 74 | int ret = 0; |
| 76 | 75 | ||
| 77 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, true); | 76 | intel_i2c_quirk_set(intel_output->base.dev, true); |
| 78 | edid = drm_get_edid(&intel_output->base, | 77 | edid = drm_get_edid(&intel_output->base, intel_output->ddc_bus); |
| 79 | &intel_output->ddc_bus->adapter); | 78 | intel_i2c_quirk_set(intel_output->base.dev, false); |
| 80 | intel_i2c_quirk_set(intel_output->ddc_bus->drm_dev, false); | ||
| 81 | if (edid) { | 79 | if (edid) { |
| 82 | drm_mode_connector_update_edid_property(&intel_output->base, | 80 | drm_mode_connector_update_edid_property(&intel_output->base, |
| 83 | edid); | 81 | edid); |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 9a00adb3a508..f03473779feb 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -38,8 +38,7 @@ | |||
| 38 | #undef SDVO_DEBUG | 38 | #undef SDVO_DEBUG |
| 39 | #define I915_SDVO "i915_sdvo" | 39 | #define I915_SDVO "i915_sdvo" |
| 40 | struct intel_sdvo_priv { | 40 | struct intel_sdvo_priv { |
| 41 | struct intel_i2c_chan *i2c_bus; | 41 | u8 slave_addr; |
| 42 | int slaveaddr; | ||
| 43 | 42 | ||
| 44 | /* Register for the SDVO device: SDVOB or SDVOC */ | 43 | /* Register for the SDVO device: SDVOB or SDVOC */ |
| 45 | int output_device; | 44 | int output_device; |
| @@ -146,13 +145,13 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
| 146 | 145 | ||
| 147 | struct i2c_msg msgs[] = { | 146 | struct i2c_msg msgs[] = { |
| 148 | { | 147 | { |
| 149 | .addr = sdvo_priv->i2c_bus->slave_addr, | 148 | .addr = sdvo_priv->slave_addr >> 1, |
| 150 | .flags = 0, | 149 | .flags = 0, |
| 151 | .len = 1, | 150 | .len = 1, |
| 152 | .buf = out_buf, | 151 | .buf = out_buf, |
| 153 | }, | 152 | }, |
| 154 | { | 153 | { |
| 155 | .addr = sdvo_priv->i2c_bus->slave_addr, | 154 | .addr = sdvo_priv->slave_addr >> 1, |
| 156 | .flags = I2C_M_RD, | 155 | .flags = I2C_M_RD, |
| 157 | .len = 1, | 156 | .len = 1, |
| 158 | .buf = buf, | 157 | .buf = buf, |
| @@ -162,7 +161,7 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
| 162 | out_buf[0] = addr; | 161 | out_buf[0] = addr; |
| 163 | out_buf[1] = 0; | 162 | out_buf[1] = 0; |
| 164 | 163 | ||
| 165 | if ((ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2)) == 2) | 164 | if ((ret = i2c_transfer(intel_output->i2c_bus, msgs, 2)) == 2) |
| 166 | { | 165 | { |
| 167 | *ch = buf[0]; | 166 | *ch = buf[0]; |
| 168 | return true; | 167 | return true; |
| @@ -175,10 +174,11 @@ static bool intel_sdvo_read_byte(struct intel_output *intel_output, u8 addr, | |||
| 175 | static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | 174 | static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, |
| 176 | u8 ch) | 175 | u8 ch) |
| 177 | { | 176 | { |
| 177 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 178 | u8 out_buf[2]; | 178 | u8 out_buf[2]; |
| 179 | struct i2c_msg msgs[] = { | 179 | struct i2c_msg msgs[] = { |
| 180 | { | 180 | { |
| 181 | .addr = intel_output->i2c_bus->slave_addr, | 181 | .addr = sdvo_priv->slave_addr >> 1, |
| 182 | .flags = 0, | 182 | .flags = 0, |
| 183 | .len = 2, | 183 | .len = 2, |
| 184 | .buf = out_buf, | 184 | .buf = out_buf, |
| @@ -188,7 +188,7 @@ static bool intel_sdvo_write_byte(struct intel_output *intel_output, int addr, | |||
| 188 | out_buf[0] = addr; | 188 | out_buf[0] = addr; |
| 189 | out_buf[1] = ch; | 189 | out_buf[1] = ch; |
| 190 | 190 | ||
| 191 | if (i2c_transfer(&intel_output->i2c_bus->adapter, msgs, 1) == 1) | 191 | if (i2c_transfer(intel_output->i2c_bus, msgs, 1) == 1) |
| 192 | { | 192 | { |
| 193 | return true; | 193 | return true; |
| 194 | } | 194 | } |
| @@ -1369,9 +1369,8 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector) | |||
| 1369 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | 1369 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; |
| 1370 | struct edid *edid = NULL; | 1370 | struct edid *edid = NULL; |
| 1371 | 1371 | ||
| 1372 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | ||
| 1373 | edid = drm_get_edid(&intel_output->base, | 1372 | edid = drm_get_edid(&intel_output->base, |
| 1374 | &intel_output->ddc_bus->adapter); | 1373 | intel_output->ddc_bus); |
| 1375 | if (edid != NULL) { | 1374 | if (edid != NULL) { |
| 1376 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); | 1375 | sdvo_priv->is_hdmi = drm_detect_hdmi_monitor(edid); |
| 1377 | kfree(edid); | 1376 | kfree(edid); |
| @@ -1549,7 +1548,6 @@ static void intel_sdvo_get_tv_modes(struct drm_connector *connector) | |||
| 1549 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | 1548 | static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) |
| 1550 | { | 1549 | { |
| 1551 | struct intel_output *intel_output = to_intel_output(connector); | 1550 | struct intel_output *intel_output = to_intel_output(connector); |
| 1552 | struct intel_sdvo_priv *sdvo_priv = intel_output->dev_priv; | ||
| 1553 | struct drm_i915_private *dev_priv = connector->dev->dev_private; | 1551 | struct drm_i915_private *dev_priv = connector->dev->dev_private; |
| 1554 | 1552 | ||
| 1555 | /* | 1553 | /* |
| @@ -1557,8 +1555,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) | |||
| 1557 | * Assume that the preferred modes are | 1555 | * Assume that the preferred modes are |
| 1558 | * arranged in priority order. | 1556 | * arranged in priority order. |
| 1559 | */ | 1557 | */ |
| 1560 | /* set the bus switch and get the modes */ | ||
| 1561 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | ||
| 1562 | intel_ddc_get_modes(intel_output); | 1558 | intel_ddc_get_modes(intel_output); |
| 1563 | if (list_empty(&connector->probed_modes) == false) | 1559 | if (list_empty(&connector->probed_modes) == false) |
| 1564 | return; | 1560 | return; |
| @@ -1709,7 +1705,7 @@ intel_sdvo_chan_to_intel_output(struct intel_i2c_chan *chan) | |||
| 1709 | 1705 | ||
| 1710 | list_for_each_entry(connector, | 1706 | list_for_each_entry(connector, |
| 1711 | &dev->mode_config.connector_list, head) { | 1707 | &dev->mode_config.connector_list, head) { |
| 1712 | if (to_intel_output(connector)->ddc_bus == chan) { | 1708 | if (to_intel_output(connector)->ddc_bus == &chan->adapter) { |
| 1713 | intel_output = to_intel_output(connector); | 1709 | intel_output = to_intel_output(connector); |
| 1714 | break; | 1710 | break; |
| 1715 | } | 1711 | } |
| @@ -1723,7 +1719,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, | |||
| 1723 | struct intel_output *intel_output; | 1719 | struct intel_output *intel_output; |
| 1724 | struct intel_sdvo_priv *sdvo_priv; | 1720 | struct intel_sdvo_priv *sdvo_priv; |
| 1725 | struct i2c_algo_bit_data *algo_data; | 1721 | struct i2c_algo_bit_data *algo_data; |
| 1726 | struct i2c_algorithm *algo; | 1722 | const struct i2c_algorithm *algo; |
| 1727 | 1723 | ||
| 1728 | algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; | 1724 | algo_data = (struct i2c_algo_bit_data *)i2c_adap->algo_data; |
| 1729 | intel_output = | 1725 | intel_output = |
| @@ -1733,7 +1729,7 @@ static int intel_sdvo_master_xfer(struct i2c_adapter *i2c_adap, | |||
| 1733 | return -EINVAL; | 1729 | return -EINVAL; |
| 1734 | 1730 | ||
| 1735 | sdvo_priv = intel_output->dev_priv; | 1731 | sdvo_priv = intel_output->dev_priv; |
| 1736 | algo = (struct i2c_algorithm *)intel_output->i2c_bus->adapter.algo; | 1732 | algo = intel_output->i2c_bus->algo; |
| 1737 | 1733 | ||
| 1738 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); | 1734 | intel_sdvo_set_control_bus_switch(intel_output, sdvo_priv->ddc_bus); |
| 1739 | return algo->master_xfer(i2c_adap, msgs, num); | 1735 | return algo->master_xfer(i2c_adap, msgs, num); |
| @@ -1785,13 +1781,11 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1785 | struct drm_connector *connector; | 1781 | struct drm_connector *connector; |
| 1786 | struct intel_output *intel_output; | 1782 | struct intel_output *intel_output; |
| 1787 | struct intel_sdvo_priv *sdvo_priv; | 1783 | struct intel_sdvo_priv *sdvo_priv; |
| 1788 | struct intel_i2c_chan *i2cbus = NULL; | 1784 | |
| 1789 | struct intel_i2c_chan *ddcbus = NULL; | ||
| 1790 | int connector_type; | 1785 | int connector_type; |
| 1791 | u8 ch[0x40]; | 1786 | u8 ch[0x40]; |
| 1792 | int i; | 1787 | int i; |
| 1793 | int encoder_type, output_id; | 1788 | int encoder_type; |
| 1794 | u8 slave_addr; | ||
| 1795 | 1789 | ||
| 1796 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); | 1790 | intel_output = kcalloc(sizeof(struct intel_output)+sizeof(struct intel_sdvo_priv), 1, GFP_KERNEL); |
| 1797 | if (!intel_output) { | 1791 | if (!intel_output) { |
| @@ -1799,29 +1793,24 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1799 | } | 1793 | } |
| 1800 | 1794 | ||
| 1801 | sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); | 1795 | sdvo_priv = (struct intel_sdvo_priv *)(intel_output + 1); |
| 1796 | sdvo_priv->output_device = output_device; | ||
| 1797 | |||
| 1798 | intel_output->dev_priv = sdvo_priv; | ||
| 1802 | intel_output->type = INTEL_OUTPUT_SDVO; | 1799 | intel_output->type = INTEL_OUTPUT_SDVO; |
| 1803 | 1800 | ||
| 1804 | /* setup the DDC bus. */ | 1801 | /* setup the DDC bus. */ |
| 1805 | if (output_device == SDVOB) | 1802 | if (output_device == SDVOB) |
| 1806 | i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); | 1803 | intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); |
| 1807 | else | 1804 | else |
| 1808 | i2cbus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); | 1805 | intel_output->i2c_bus = intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); |
| 1809 | 1806 | ||
| 1810 | if (!i2cbus) | 1807 | if (!intel_output->i2c_bus) |
| 1811 | goto err_inteloutput; | 1808 | goto err_inteloutput; |
| 1812 | 1809 | ||
| 1813 | slave_addr = intel_sdvo_get_slave_addr(dev, output_device); | 1810 | sdvo_priv->slave_addr = intel_sdvo_get_slave_addr(dev, output_device); |
| 1814 | sdvo_priv->i2c_bus = i2cbus; | ||
| 1815 | 1811 | ||
| 1816 | if (output_device == SDVOB) { | 1812 | /* Save the bit-banging i2c functionality for use by the DDC wrapper */ |
| 1817 | output_id = 1; | 1813 | intel_sdvo_i2c_bit_algo.functionality = intel_output->i2c_bus->algo->functionality; |
| 1818 | } else { | ||
| 1819 | output_id = 2; | ||
| 1820 | } | ||
| 1821 | sdvo_priv->i2c_bus->slave_addr = slave_addr >> 1; | ||
| 1822 | sdvo_priv->output_device = output_device; | ||
| 1823 | intel_output->i2c_bus = i2cbus; | ||
| 1824 | intel_output->dev_priv = sdvo_priv; | ||
| 1825 | 1814 | ||
| 1826 | /* Read the regs to test if we can talk to the device */ | 1815 | /* Read the regs to test if we can talk to the device */ |
| 1827 | for (i = 0; i < 0x40; i++) { | 1816 | for (i = 0; i < 0x40; i++) { |
| @@ -1835,17 +1824,15 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1835 | 1824 | ||
| 1836 | /* setup the DDC bus. */ | 1825 | /* setup the DDC bus. */ |
| 1837 | if (output_device == SDVOB) | 1826 | if (output_device == SDVOB) |
| 1838 | ddcbus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); | 1827 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOB DDC BUS"); |
| 1839 | else | 1828 | else |
| 1840 | ddcbus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); | 1829 | intel_output->ddc_bus = intel_i2c_create(dev, GPIOE, "SDVOC DDC BUS"); |
| 1841 | 1830 | ||
| 1842 | if (ddcbus == NULL) | 1831 | if (intel_output->ddc_bus == NULL) |
| 1843 | goto err_i2c; | 1832 | goto err_i2c; |
| 1844 | 1833 | ||
| 1845 | intel_sdvo_i2c_bit_algo.functionality = | 1834 | /* Wrap with our custom algo which switches to DDC mode */ |
| 1846 | intel_output->i2c_bus->adapter.algo->functionality; | 1835 | intel_output->ddc_bus->algo = &intel_sdvo_i2c_bit_algo; |
| 1847 | ddcbus->adapter.algo = &intel_sdvo_i2c_bit_algo; | ||
| 1848 | intel_output->ddc_bus = ddcbus; | ||
| 1849 | 1836 | ||
| 1850 | /* In defaut case sdvo lvds is false */ | 1837 | /* In defaut case sdvo lvds is false */ |
| 1851 | sdvo_priv->is_lvds = false; | 1838 | sdvo_priv->is_lvds = false; |
| @@ -1965,9 +1952,10 @@ bool intel_sdvo_init(struct drm_device *dev, int output_device) | |||
| 1965 | return true; | 1952 | return true; |
| 1966 | 1953 | ||
| 1967 | err_i2c: | 1954 | err_i2c: |
| 1968 | if (ddcbus != NULL) | 1955 | if (intel_output->ddc_bus != NULL) |
| 1969 | intel_i2c_destroy(intel_output->ddc_bus); | 1956 | intel_i2c_destroy(intel_output->ddc_bus); |
| 1970 | intel_i2c_destroy(intel_output->i2c_bus); | 1957 | if (intel_output->i2c_bus != NULL) |
| 1958 | intel_i2c_destroy(intel_output->i2c_bus); | ||
| 1971 | err_inteloutput: | 1959 | err_inteloutput: |
| 1972 | kfree(intel_output); | 1960 | kfree(intel_output); |
| 1973 | 1961 | ||
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index ea68992e4416..a43c98e3f077 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -1383,34 +1383,31 @@ intel_tv_detect_type (struct drm_crtc *crtc, struct intel_output *intel_output) | |||
| 1383 | /* | 1383 | /* |
| 1384 | * Detect TV by polling) | 1384 | * Detect TV by polling) |
| 1385 | */ | 1385 | */ |
| 1386 | if (intel_output->load_detect_temp) { | 1386 | save_tv_dac = tv_dac; |
| 1387 | /* TV not currently running, prod it with destructive detect */ | 1387 | tv_ctl = I915_READ(TV_CTL); |
| 1388 | save_tv_dac = tv_dac; | 1388 | save_tv_ctl = tv_ctl; |
| 1389 | tv_ctl = I915_READ(TV_CTL); | 1389 | tv_ctl &= ~TV_ENC_ENABLE; |
| 1390 | save_tv_ctl = tv_ctl; | 1390 | tv_ctl &= ~TV_TEST_MODE_MASK; |
| 1391 | tv_ctl &= ~TV_ENC_ENABLE; | 1391 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; |
| 1392 | tv_ctl &= ~TV_TEST_MODE_MASK; | 1392 | tv_dac &= ~TVDAC_SENSE_MASK; |
| 1393 | tv_ctl |= TV_TEST_MODE_MONITOR_DETECT; | 1393 | tv_dac &= ~DAC_A_MASK; |
| 1394 | tv_dac &= ~TVDAC_SENSE_MASK; | 1394 | tv_dac &= ~DAC_B_MASK; |
| 1395 | tv_dac &= ~DAC_A_MASK; | 1395 | tv_dac &= ~DAC_C_MASK; |
| 1396 | tv_dac &= ~DAC_B_MASK; | 1396 | tv_dac |= (TVDAC_STATE_CHG_EN | |
| 1397 | tv_dac &= ~DAC_C_MASK; | 1397 | TVDAC_A_SENSE_CTL | |
| 1398 | tv_dac |= (TVDAC_STATE_CHG_EN | | 1398 | TVDAC_B_SENSE_CTL | |
| 1399 | TVDAC_A_SENSE_CTL | | 1399 | TVDAC_C_SENSE_CTL | |
| 1400 | TVDAC_B_SENSE_CTL | | 1400 | DAC_CTL_OVERRIDE | |
| 1401 | TVDAC_C_SENSE_CTL | | 1401 | DAC_A_0_7_V | |
| 1402 | DAC_CTL_OVERRIDE | | 1402 | DAC_B_0_7_V | |
| 1403 | DAC_A_0_7_V | | 1403 | DAC_C_0_7_V); |
| 1404 | DAC_B_0_7_V | | 1404 | I915_WRITE(TV_CTL, tv_ctl); |
| 1405 | DAC_C_0_7_V); | 1405 | I915_WRITE(TV_DAC, tv_dac); |
| 1406 | I915_WRITE(TV_CTL, tv_ctl); | 1406 | intel_wait_for_vblank(dev); |
| 1407 | I915_WRITE(TV_DAC, tv_dac); | 1407 | tv_dac = I915_READ(TV_DAC); |
| 1408 | intel_wait_for_vblank(dev); | 1408 | I915_WRITE(TV_DAC, save_tv_dac); |
| 1409 | tv_dac = I915_READ(TV_DAC); | 1409 | I915_WRITE(TV_CTL, save_tv_ctl); |
| 1410 | I915_WRITE(TV_DAC, save_tv_dac); | 1410 | intel_wait_for_vblank(dev); |
| 1411 | I915_WRITE(TV_CTL, save_tv_ctl); | ||
| 1412 | intel_wait_for_vblank(dev); | ||
| 1413 | } | ||
| 1414 | /* | 1411 | /* |
| 1415 | * A B C | 1412 | * A B C |
| 1416 | * 0 1 1 Composite | 1413 | * 0 1 1 Composite |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index f30aa7274a54..f97563db4e59 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
| @@ -35,6 +35,23 @@ | |||
| 35 | #include "atom.h" | 35 | #include "atom.h" |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| 38 | * Clear GPU surface registers. | ||
| 39 | */ | ||
| 40 | static void radeon_surface_init(struct radeon_device *rdev) | ||
| 41 | { | ||
| 42 | /* FIXME: check this out */ | ||
| 43 | if (rdev->family < CHIP_R600) { | ||
| 44 | int i; | ||
| 45 | |||
| 46 | for (i = 0; i < 8; i++) { | ||
| 47 | WREG32(RADEON_SURFACE0_INFO + | ||
| 48 | i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), | ||
| 49 | 0); | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | |||
| 54 | /* | ||
| 38 | * GPU scratch registers helpers function. | 55 | * GPU scratch registers helpers function. |
| 39 | */ | 56 | */ |
| 40 | static void radeon_scratch_init(struct radeon_device *rdev) | 57 | static void radeon_scratch_init(struct radeon_device *rdev) |
| @@ -496,6 +513,8 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 496 | radeon_errata(rdev); | 513 | radeon_errata(rdev); |
| 497 | /* Initialize scratch registers */ | 514 | /* Initialize scratch registers */ |
| 498 | radeon_scratch_init(rdev); | 515 | radeon_scratch_init(rdev); |
| 516 | /* Initialize surface registers */ | ||
| 517 | radeon_surface_init(rdev); | ||
| 499 | 518 | ||
| 500 | /* TODO: disable VGA need to use VGA request */ | 519 | /* TODO: disable VGA need to use VGA request */ |
| 501 | /* BIOS*/ | 520 | /* BIOS*/ |
| @@ -604,9 +623,6 @@ int radeon_device_init(struct radeon_device *rdev, | |||
| 604 | if (r) { | 623 | if (r) { |
| 605 | return r; | 624 | return r; |
| 606 | } | 625 | } |
| 607 | if (rdev->fbdev_rfb && rdev->fbdev_rfb->obj) { | ||
| 608 | rdev->fbdev_robj = rdev->fbdev_rfb->obj->driver_private; | ||
| 609 | } | ||
| 610 | if (!ret) { | 626 | if (!ret) { |
| 611 | DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); | 627 | DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); |
| 612 | } | 628 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 09c9fb9f6210..84ba69f48784 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -345,7 +345,7 @@ static void __exit radeon_exit(void) | |||
| 345 | drm_exit(driver); | 345 | drm_exit(driver); |
| 346 | } | 346 | } |
| 347 | 347 | ||
| 348 | late_initcall(radeon_init); | 348 | module_init(radeon_init); |
| 349 | module_exit(radeon_exit); | 349 | module_exit(radeon_exit); |
| 350 | 350 | ||
| 351 | MODULE_AUTHOR(DRIVER_AUTHOR); | 351 | MODULE_AUTHOR(DRIVER_AUTHOR); |
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index fa86d398945e..9e8f191eb64a 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c | |||
| @@ -478,14 +478,16 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 478 | { | 478 | { |
| 479 | struct fb_info *info; | 479 | struct fb_info *info; |
| 480 | struct radeon_fb_device *rfbdev; | 480 | struct radeon_fb_device *rfbdev; |
| 481 | struct drm_framebuffer *fb; | 481 | struct drm_framebuffer *fb = NULL; |
| 482 | struct radeon_framebuffer *rfb; | 482 | struct radeon_framebuffer *rfb; |
| 483 | struct drm_mode_fb_cmd mode_cmd; | 483 | struct drm_mode_fb_cmd mode_cmd; |
| 484 | struct drm_gem_object *gobj = NULL; | 484 | struct drm_gem_object *gobj = NULL; |
| 485 | struct radeon_object *robj = NULL; | 485 | struct radeon_object *robj = NULL; |
| 486 | struct device *device = &rdev->pdev->dev; | 486 | struct device *device = &rdev->pdev->dev; |
| 487 | int size, aligned_size, ret; | 487 | int size, aligned_size, ret; |
| 488 | u64 fb_gpuaddr; | ||
| 488 | void *fbptr = NULL; | 489 | void *fbptr = NULL; |
| 490 | unsigned long tmp; | ||
| 489 | 491 | ||
| 490 | mode_cmd.width = surface_width; | 492 | mode_cmd.width = surface_width; |
| 491 | mode_cmd.height = surface_height; | 493 | mode_cmd.height = surface_height; |
| @@ -498,11 +500,12 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 498 | aligned_size = ALIGN(size, PAGE_SIZE); | 500 | aligned_size = ALIGN(size, PAGE_SIZE); |
| 499 | 501 | ||
| 500 | ret = radeon_gem_object_create(rdev, aligned_size, 0, | 502 | ret = radeon_gem_object_create(rdev, aligned_size, 0, |
| 501 | RADEON_GEM_DOMAIN_VRAM, | 503 | RADEON_GEM_DOMAIN_VRAM, |
| 502 | false, ttm_bo_type_kernel, | 504 | false, ttm_bo_type_kernel, |
| 503 | false, &gobj); | 505 | false, &gobj); |
| 504 | if (ret) { | 506 | if (ret) { |
| 505 | printk(KERN_ERR "failed to allocate framebuffer\n"); | 507 | printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", |
| 508 | surface_width, surface_height); | ||
| 506 | ret = -ENOMEM; | 509 | ret = -ENOMEM; |
| 507 | goto out; | 510 | goto out; |
| 508 | } | 511 | } |
| @@ -515,12 +518,19 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 515 | ret = -ENOMEM; | 518 | ret = -ENOMEM; |
| 516 | goto out_unref; | 519 | goto out_unref; |
| 517 | } | 520 | } |
| 521 | ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); | ||
| 522 | if (ret) { | ||
| 523 | printk(KERN_ERR "failed to pin framebuffer\n"); | ||
| 524 | ret = -ENOMEM; | ||
| 525 | goto out_unref; | ||
| 526 | } | ||
| 518 | 527 | ||
| 519 | list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); | 528 | list_add(&fb->filp_head, &rdev->ddev->mode_config.fb_kernel_list); |
| 520 | 529 | ||
| 521 | rfb = to_radeon_framebuffer(fb); | 530 | rfb = to_radeon_framebuffer(fb); |
| 522 | *rfb_p = rfb; | 531 | *rfb_p = rfb; |
| 523 | rdev->fbdev_rfb = rfb; | 532 | rdev->fbdev_rfb = rfb; |
| 533 | rdev->fbdev_robj = robj; | ||
| 524 | 534 | ||
| 525 | info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); | 535 | info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); |
| 526 | if (info == NULL) { | 536 | if (info == NULL) { |
| @@ -541,13 +551,13 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 541 | info->fix.xpanstep = 1; /* doing it in hw */ | 551 | info->fix.xpanstep = 1; /* doing it in hw */ |
| 542 | info->fix.ypanstep = 1; /* doing it in hw */ | 552 | info->fix.ypanstep = 1; /* doing it in hw */ |
| 543 | info->fix.ywrapstep = 0; | 553 | info->fix.ywrapstep = 0; |
| 544 | info->fix.accel = FB_ACCEL_I830; | 554 | info->fix.accel = FB_ACCEL_NONE; |
| 545 | info->fix.type_aux = 0; | 555 | info->fix.type_aux = 0; |
| 546 | info->flags = FBINFO_DEFAULT; | 556 | info->flags = FBINFO_DEFAULT; |
| 547 | info->fbops = &radeonfb_ops; | 557 | info->fbops = &radeonfb_ops; |
| 548 | info->fix.line_length = fb->pitch; | 558 | info->fix.line_length = fb->pitch; |
| 549 | info->screen_base = fbptr; | 559 | tmp = fb_gpuaddr - rdev->mc.vram_location; |
| 550 | info->fix.smem_start = (unsigned long)fbptr; | 560 | info->fix.smem_start = rdev->mc.aper_base + tmp; |
| 551 | info->fix.smem_len = size; | 561 | info->fix.smem_len = size; |
| 552 | info->screen_base = fbptr; | 562 | info->screen_base = fbptr; |
| 553 | info->screen_size = size; | 563 | info->screen_size = size; |
| @@ -562,8 +572,8 @@ int radeonfb_create(struct radeon_device *rdev, | |||
| 562 | info->var.width = -1; | 572 | info->var.width = -1; |
| 563 | info->var.xres = fb_width; | 573 | info->var.xres = fb_width; |
| 564 | info->var.yres = fb_height; | 574 | info->var.yres = fb_height; |
| 565 | info->fix.mmio_start = pci_resource_start(rdev->pdev, 2); | 575 | info->fix.mmio_start = 0; |
| 566 | info->fix.mmio_len = pci_resource_len(rdev->pdev, 2); | 576 | info->fix.mmio_len = 0; |
| 567 | info->pixmap.size = 64*1024; | 577 | info->pixmap.size = 64*1024; |
| 568 | info->pixmap.buf_align = 8; | 578 | info->pixmap.buf_align = 8; |
| 569 | info->pixmap.access_align = 32; | 579 | info->pixmap.access_align = 32; |
| @@ -644,7 +654,7 @@ out_unref: | |||
| 644 | if (robj) { | 654 | if (robj) { |
| 645 | radeon_object_kunmap(robj); | 655 | radeon_object_kunmap(robj); |
| 646 | } | 656 | } |
| 647 | if (ret) { | 657 | if (fb && ret) { |
| 648 | list_del(&fb->filp_head); | 658 | list_del(&fb->filp_head); |
| 649 | drm_gem_object_unreference(gobj); | 659 | drm_gem_object_unreference(gobj); |
| 650 | drm_framebuffer_cleanup(fb); | 660 | drm_framebuffer_cleanup(fb); |
| @@ -813,6 +823,7 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | |||
| 813 | robj = rfb->obj->driver_private; | 823 | robj = rfb->obj->driver_private; |
| 814 | unregister_framebuffer(info); | 824 | unregister_framebuffer(info); |
| 815 | radeon_object_kunmap(robj); | 825 | radeon_object_kunmap(robj); |
| 826 | radeon_object_unpin(robj); | ||
| 816 | framebuffer_release(info); | 827 | framebuffer_release(info); |
| 817 | } | 828 | } |
| 818 | 829 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 983e8df5e000..bac0d06c52ac 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
| @@ -223,7 +223,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
| 223 | { | 223 | { |
| 224 | uint32_t flags; | 224 | uint32_t flags; |
| 225 | uint32_t tmp; | 225 | uint32_t tmp; |
| 226 | void *fbptr; | ||
| 227 | int r; | 226 | int r; |
| 228 | 227 | ||
| 229 | flags = radeon_object_flags_from_domain(domain); | 228 | flags = radeon_object_flags_from_domain(domain); |
| @@ -242,10 +241,6 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
| 242 | DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); | 241 | DRM_ERROR("radeon: failed to reserve object for pinning it.\n"); |
| 243 | return r; | 242 | return r; |
| 244 | } | 243 | } |
| 245 | if (robj->rdev->fbdev_robj == robj) { | ||
| 246 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
| 247 | radeon_object_kunmap(robj); | ||
| 248 | } | ||
| 249 | tmp = robj->tobj.mem.placement; | 244 | tmp = robj->tobj.mem.placement; |
| 250 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); | 245 | ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM); |
| 251 | robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; | 246 | robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING; |
| @@ -261,23 +256,12 @@ int radeon_object_pin(struct radeon_object *robj, uint32_t domain, | |||
| 261 | DRM_ERROR("radeon: failed to pin object.\n"); | 256 | DRM_ERROR("radeon: failed to pin object.\n"); |
| 262 | } | 257 | } |
| 263 | radeon_object_unreserve(robj); | 258 | radeon_object_unreserve(robj); |
| 264 | if (robj->rdev->fbdev_robj == robj) { | ||
| 265 | if (!r) { | ||
| 266 | r = radeon_object_kmap(robj, &fbptr); | ||
| 267 | } | ||
| 268 | if (!r) { | ||
| 269 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
| 270 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
| 271 | } | ||
| 272 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
| 273 | } | ||
| 274 | return r; | 259 | return r; |
| 275 | } | 260 | } |
| 276 | 261 | ||
| 277 | void radeon_object_unpin(struct radeon_object *robj) | 262 | void radeon_object_unpin(struct radeon_object *robj) |
| 278 | { | 263 | { |
| 279 | uint32_t flags; | 264 | uint32_t flags; |
| 280 | void *fbptr; | ||
| 281 | int r; | 265 | int r; |
| 282 | 266 | ||
| 283 | spin_lock(&robj->tobj.lock); | 267 | spin_lock(&robj->tobj.lock); |
| @@ -297,10 +281,6 @@ void radeon_object_unpin(struct radeon_object *robj) | |||
| 297 | DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); | 281 | DRM_ERROR("radeon: failed to reserve object for unpinning it.\n"); |
| 298 | return; | 282 | return; |
| 299 | } | 283 | } |
| 300 | if (robj->rdev->fbdev_robj == robj) { | ||
| 301 | mutex_lock(&robj->rdev->fbdev_info->lock); | ||
| 302 | radeon_object_kunmap(robj); | ||
| 303 | } | ||
| 304 | flags = robj->tobj.mem.placement; | 284 | flags = robj->tobj.mem.placement; |
| 305 | robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; | 285 | robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT; |
| 306 | r = ttm_buffer_object_validate(&robj->tobj, | 286 | r = ttm_buffer_object_validate(&robj->tobj, |
| @@ -310,16 +290,6 @@ void radeon_object_unpin(struct radeon_object *robj) | |||
| 310 | DRM_ERROR("radeon: failed to unpin buffer.\n"); | 290 | DRM_ERROR("radeon: failed to unpin buffer.\n"); |
| 311 | } | 291 | } |
| 312 | radeon_object_unreserve(robj); | 292 | radeon_object_unreserve(robj); |
| 313 | if (robj->rdev->fbdev_robj == robj) { | ||
| 314 | if (!r) { | ||
| 315 | r = radeon_object_kmap(robj, &fbptr); | ||
| 316 | } | ||
| 317 | if (!r) { | ||
| 318 | robj->rdev->fbdev_info->screen_base = fbptr; | ||
| 319 | robj->rdev->fbdev_info->fix.smem_start = (unsigned long)fbptr; | ||
| 320 | } | ||
| 321 | mutex_unlock(&robj->rdev->fbdev_info->lock); | ||
| 322 | } | ||
| 323 | } | 293 | } |
| 324 | 294 | ||
| 325 | int radeon_object_wait(struct radeon_object *robj) | 295 | int radeon_object_wait(struct radeon_object *robj) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 517c84559633..bdec583901eb 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <linux/highmem.h> | 34 | #include <linux/highmem.h> |
| 35 | #include <linux/wait.h> | 35 | #include <linux/wait.h> |
| 36 | #include <linux/vmalloc.h> | 36 | #include <linux/vmalloc.h> |
| 37 | #include <linux/version.h> | ||
| 38 | #include <linux/module.h> | 37 | #include <linux/module.h> |
| 39 | 38 | ||
| 40 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) | 39 | void ttm_bo_free_old_node(struct ttm_buffer_object *bo) |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 27b146c54fbc..40b75032ea47 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c | |||
| @@ -32,7 +32,6 @@ | |||
| 32 | #include <ttm/ttm_bo_driver.h> | 32 | #include <ttm/ttm_bo_driver.h> |
| 33 | #include <ttm/ttm_placement.h> | 33 | #include <ttm/ttm_placement.h> |
| 34 | #include <linux/mm.h> | 34 | #include <linux/mm.h> |
| 35 | #include <linux/version.h> | ||
| 36 | #include <linux/rbtree.h> | 35 | #include <linux/rbtree.h> |
| 37 | #include <linux/module.h> | 36 | #include <linux/module.h> |
| 38 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 0331fa74cd3f..75dc8bd24592 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> | 28 | * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> |
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | #include <linux/version.h> | ||
| 32 | #include <linux/vmalloc.h> | 31 | #include <linux/vmalloc.h> |
| 33 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
| 34 | #include <linux/highmem.h> | 33 | #include <linux/highmem.h> |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index aa87b6a3bbef..8206442fbabd 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
| @@ -328,6 +328,7 @@ config I2C_DAVINCI | |||
| 328 | 328 | ||
| 329 | config I2C_DESIGNWARE | 329 | config I2C_DESIGNWARE |
| 330 | tristate "Synopsys DesignWare" | 330 | tristate "Synopsys DesignWare" |
| 331 | depends on HAVE_CLK | ||
| 331 | help | 332 | help |
| 332 | If you say yes to this option, support will be included for the | 333 | If you say yes to this option, support will be included for the |
| 333 | Synopsys DesignWare I2C adapter. Only master mode is supported. | 334 | Synopsys DesignWare I2C adapter. Only master mode is supported. |
diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index bd066bb9d611..09f98ed0731f 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c | |||
| @@ -135,6 +135,7 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic | |||
| 135 | 135 | ||
| 136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); | 136 | ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); |
| 137 | hw[0].irq = 14; | 137 | hw[0].irq = 14; |
| 138 | hw[1].irq = 15; | ||
| 138 | 139 | ||
| 139 | return ide_host_add(d, hws, 2, NULL); | 140 | return ide_host_add(d, hws, 2, NULL); |
| 140 | } | 141 | } |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 4a19686fcfe9..f0ede5953af8 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -876,9 +876,12 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
| 876 | return stat; | 876 | return stat; |
| 877 | 877 | ||
| 878 | /* | 878 | /* |
| 879 | * Sanity check the given block size | 879 | * Sanity check the given block size, in so far as making |
| 880 | * sure the sectors_per_frame we give to the caller won't | ||
| 881 | * end up being bogus. | ||
| 880 | */ | 882 | */ |
| 881 | blocklen = be32_to_cpu(capbuf.blocklen); | 883 | blocklen = be32_to_cpu(capbuf.blocklen); |
| 884 | blocklen = (blocklen >> SECTOR_BITS) << SECTOR_BITS; | ||
| 882 | switch (blocklen) { | 885 | switch (blocklen) { |
| 883 | case 512: | 886 | case 512: |
| 884 | case 1024: | 887 | case 1024: |
| @@ -886,10 +889,9 @@ static int cdrom_read_capacity(ide_drive_t *drive, unsigned long *capacity, | |||
| 886 | case 4096: | 889 | case 4096: |
| 887 | break; | 890 | break; |
| 888 | default: | 891 | default: |
| 889 | printk(KERN_ERR PFX "%s: weird block size %u\n", | 892 | printk_once(KERN_ERR PFX "%s: weird block size %u; " |
| 893 | "setting default block size to 2048\n", | ||
| 890 | drive->name, blocklen); | 894 | drive->name, blocklen); |
| 891 | printk(KERN_ERR PFX "%s: default to 2kb block size\n", | ||
| 892 | drive->name); | ||
| 893 | blocklen = 2048; | 895 | blocklen = 2048; |
| 894 | break; | 896 | break; |
| 895 | } | 897 | } |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 219e6fb78dc6..ee58c88dee5a 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
| @@ -361,9 +361,6 @@ static int ide_tune_dma(ide_drive_t *drive) | |||
| 361 | if (__ide_dma_bad_drive(drive)) | 361 | if (__ide_dma_bad_drive(drive)) |
| 362 | return 0; | 362 | return 0; |
| 363 | 363 | ||
| 364 | if (ide_id_dma_bug(drive)) | ||
| 365 | return 0; | ||
| 366 | |||
| 367 | if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) | 364 | if (hwif->host_flags & IDE_HFLAG_TRUST_BIOS_FOR_DMA) |
| 368 | return config_drive_for_dma(drive); | 365 | return config_drive_for_dma(drive); |
| 369 | 366 | ||
| @@ -394,24 +391,6 @@ static int ide_dma_check(ide_drive_t *drive) | |||
| 394 | return -1; | 391 | return -1; |
| 395 | } | 392 | } |
| 396 | 393 | ||
| 397 | int ide_id_dma_bug(ide_drive_t *drive) | ||
| 398 | { | ||
| 399 | u16 *id = drive->id; | ||
| 400 | |||
| 401 | if (id[ATA_ID_FIELD_VALID] & 4) { | ||
| 402 | if ((id[ATA_ID_UDMA_MODES] >> 8) && | ||
| 403 | (id[ATA_ID_MWDMA_MODES] >> 8)) | ||
| 404 | goto err_out; | ||
| 405 | } else if ((id[ATA_ID_MWDMA_MODES] >> 8) && | ||
| 406 | (id[ATA_ID_SWDMA_MODES] >> 8)) | ||
| 407 | goto err_out; | ||
| 408 | |||
| 409 | return 0; | ||
| 410 | err_out: | ||
| 411 | printk(KERN_ERR "%s: bad DMA info in identify block\n", drive->name); | ||
| 412 | return 1; | ||
| 413 | } | ||
| 414 | |||
| 415 | int ide_set_dma(ide_drive_t *drive) | 394 | int ide_set_dma(ide_drive_t *drive) |
| 416 | { | 395 | { |
| 417 | int rc; | 396 | int rc; |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 1059f809b809..93b7886a2d6e 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
| @@ -476,10 +476,14 @@ void do_ide_request(struct request_queue *q) | |||
| 476 | 476 | ||
| 477 | if (!ide_lock_port(hwif)) { | 477 | if (!ide_lock_port(hwif)) { |
| 478 | ide_hwif_t *prev_port; | 478 | ide_hwif_t *prev_port; |
| 479 | |||
| 480 | WARN_ON_ONCE(hwif->rq); | ||
| 481 | repeat: | 479 | repeat: |
| 482 | prev_port = hwif->host->cur_port; | 480 | prev_port = hwif->host->cur_port; |
| 481 | |||
| 482 | if (drive->dev_flags & IDE_DFLAG_BLOCKED) | ||
| 483 | rq = hwif->rq; | ||
| 484 | else | ||
| 485 | WARN_ON_ONCE(hwif->rq); | ||
| 486 | |||
| 483 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && | 487 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && |
| 484 | time_after(drive->sleep, jiffies)) { | 488 | time_after(drive->sleep, jiffies)) { |
| 485 | ide_unlock_port(hwif); | 489 | ide_unlock_port(hwif); |
| @@ -506,43 +510,29 @@ repeat: | |||
| 506 | hwif->cur_dev = drive; | 510 | hwif->cur_dev = drive; |
| 507 | drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); | 511 | drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); |
| 508 | 512 | ||
| 509 | spin_unlock_irq(&hwif->lock); | 513 | if (rq == NULL) { |
| 510 | spin_lock_irq(q->queue_lock); | 514 | spin_unlock_irq(&hwif->lock); |
| 511 | /* | 515 | spin_lock_irq(q->queue_lock); |
| 512 | * we know that the queue isn't empty, but this can happen | 516 | /* |
| 513 | * if the q->prep_rq_fn() decides to kill a request | 517 | * we know that the queue isn't empty, but this can |
| 514 | */ | 518 | * happen if ->prep_rq_fn() decides to kill a request |
| 515 | if (!rq) | 519 | */ |
| 516 | rq = blk_fetch_request(drive->queue); | 520 | rq = blk_fetch_request(drive->queue); |
| 521 | spin_unlock_irq(q->queue_lock); | ||
| 522 | spin_lock_irq(&hwif->lock); | ||
| 517 | 523 | ||
| 518 | spin_unlock_irq(q->queue_lock); | 524 | if (rq == NULL) { |
| 519 | spin_lock_irq(&hwif->lock); | 525 | ide_unlock_port(hwif); |
| 520 | 526 | goto out; | |
| 521 | if (!rq) { | 527 | } |
| 522 | ide_unlock_port(hwif); | ||
| 523 | goto out; | ||
| 524 | } | 528 | } |
| 525 | 529 | ||
| 526 | /* | 530 | /* |
| 527 | * Sanity: don't accept a request that isn't a PM request | 531 | * Sanity: don't accept a request that isn't a PM request |
| 528 | * if we are currently power managed. This is very important as | 532 | * if we are currently power managed. |
| 529 | * blk_stop_queue() doesn't prevent the blk_fetch_request() | ||
| 530 | * above to return us whatever is in the queue. Since we call | ||
| 531 | * ide_do_request() ourselves, we end up taking requests while | ||
| 532 | * the queue is blocked... | ||
| 533 | * | ||
| 534 | * We let requests forced at head of queue with ide-preempt | ||
| 535 | * though. I hope that doesn't happen too much, hopefully not | ||
| 536 | * unless the subdriver triggers such a thing in its own PM | ||
| 537 | * state machine. | ||
| 538 | */ | 533 | */ |
| 539 | if ((drive->dev_flags & IDE_DFLAG_BLOCKED) && | 534 | BUG_ON((drive->dev_flags & IDE_DFLAG_BLOCKED) && |
| 540 | blk_pm_request(rq) == 0 && | 535 | blk_pm_request(rq) == 0); |
| 541 | (rq->cmd_flags & REQ_PREEMPT) == 0) { | ||
| 542 | /* there should be no pending command at this point */ | ||
| 543 | ide_unlock_port(hwif); | ||
| 544 | goto plug_device; | ||
| 545 | } | ||
| 546 | 536 | ||
| 547 | hwif->rq = rq; | 537 | hwif->rq = rq; |
| 548 | 538 | ||
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index fa047150a1c6..2892b242bbe1 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
| @@ -210,6 +210,7 @@ EXPORT_SYMBOL_GPL(ide_in_drive_list); | |||
| 210 | */ | 210 | */ |
| 211 | static const struct drive_list_entry ivb_list[] = { | 211 | static const struct drive_list_entry ivb_list[] = { |
| 212 | { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, | 212 | { "QUANTUM FIREBALLlct10 05" , "A03.0900" }, |
| 213 | { "QUANTUM FIREBALLlct20 30" , "APL.0900" }, | ||
| 213 | { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, | 214 | { "TSSTcorp CDDVDW SH-S202J" , "SB00" }, |
| 214 | { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, | 215 | { "TSSTcorp CDDVDW SH-S202J" , "SB01" }, |
| 215 | { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, | 216 | { "TSSTcorp CDDVDW SH-S202N" , "SB00" }, |
| @@ -329,9 +330,6 @@ int ide_driveid_update(ide_drive_t *drive) | |||
| 329 | 330 | ||
| 330 | kfree(id); | 331 | kfree(id); |
| 331 | 332 | ||
| 332 | if ((drive->dev_flags & IDE_DFLAG_USING_DMA) && ide_id_dma_bug(drive)) | ||
| 333 | ide_dma_off(drive); | ||
| 334 | |||
| 335 | return 1; | 333 | return 1; |
| 336 | out_err: | 334 | out_err: |
| 337 | if (rc == 2) | 335 | if (rc == 2) |
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 51af4eea0d36..1bb106f6221a 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
| @@ -818,6 +818,24 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) | |||
| 818 | return j; | 818 | return j; |
| 819 | } | 819 | } |
| 820 | 820 | ||
| 821 | static void ide_host_enable_irqs(struct ide_host *host) | ||
| 822 | { | ||
| 823 | ide_hwif_t *hwif; | ||
| 824 | int i; | ||
| 825 | |||
| 826 | ide_host_for_each_port(i, hwif, host) { | ||
| 827 | if (hwif == NULL) | ||
| 828 | continue; | ||
| 829 | |||
| 830 | /* clear any pending IRQs */ | ||
| 831 | hwif->tp_ops->read_status(hwif); | ||
| 832 | |||
| 833 | /* unmask IRQs */ | ||
| 834 | if (hwif->io_ports.ctl_addr) | ||
| 835 | hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | ||
| 836 | } | ||
| 837 | } | ||
| 838 | |||
| 821 | /* | 839 | /* |
| 822 | * This routine sets up the IRQ for an IDE interface. | 840 | * This routine sets up the IRQ for an IDE interface. |
| 823 | */ | 841 | */ |
| @@ -831,9 +849,6 @@ static int init_irq (ide_hwif_t *hwif) | |||
| 831 | if (irq_handler == NULL) | 849 | if (irq_handler == NULL) |
| 832 | irq_handler = ide_intr; | 850 | irq_handler = ide_intr; |
| 833 | 851 | ||
| 834 | if (io_ports->ctl_addr) | ||
| 835 | hwif->tp_ops->write_devctl(hwif, ATA_DEVCTL_OBS); | ||
| 836 | |||
| 837 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) | 852 | if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) |
| 838 | goto out_up; | 853 | goto out_up; |
| 839 | 854 | ||
| @@ -1404,6 +1419,8 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, | |||
| 1404 | ide_port_tune_devices(hwif); | 1419 | ide_port_tune_devices(hwif); |
| 1405 | } | 1420 | } |
| 1406 | 1421 | ||
| 1422 | ide_host_enable_irqs(host); | ||
| 1423 | |||
| 1407 | ide_host_for_each_port(i, hwif, host) { | 1424 | ide_host_for_each_port(i, hwif, host) { |
| 1408 | if (hwif == NULL) | 1425 | if (hwif == NULL) |
| 1409 | continue; | 1426 | continue; |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 9b60b6b684d9..7c8e7122aaa9 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
| @@ -75,6 +75,7 @@ config LEDS_ALIX2 | |||
| 75 | depends on LEDS_CLASS && X86 && EXPERIMENTAL | 75 | depends on LEDS_CLASS && X86 && EXPERIMENTAL |
| 76 | help | 76 | help |
| 77 | This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. | 77 | This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. |
| 78 | You have to set leds-alix2.force=1 for boards with Award BIOS. | ||
| 78 | 79 | ||
| 79 | config LEDS_H1940 | 80 | config LEDS_H1940 |
| 80 | tristate "LED Support for iPAQ H1940 device" | 81 | tristate "LED Support for iPAQ H1940 device" |
| @@ -145,15 +146,16 @@ config LEDS_GPIO_OF | |||
| 145 | of_platform devices. For instance, LEDs which are listed in a "dts" | 146 | of_platform devices. For instance, LEDs which are listed in a "dts" |
| 146 | file. | 147 | file. |
| 147 | 148 | ||
| 148 | config LEDS_LP5521 | 149 | config LEDS_LP3944 |
| 149 | tristate "LED Support for the LP5521 LEDs" | 150 | tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip" |
| 150 | depends on LEDS_CLASS && I2C | 151 | depends on LEDS_CLASS && I2C |
| 151 | help | 152 | help |
| 152 | If you say 'Y' here you get support for the National Semiconductor | 153 | This option enables support for LEDs connected to the National |
| 153 | LP5521 LED driver used in n8x0 boards. | 154 | Semiconductor LP3944 Lighting Management Unit (LMU) also known as |
| 155 | Fun Light Chip. | ||
| 154 | 156 | ||
| 155 | This driver can be built as a module by choosing 'M'. The module | 157 | To compile this driver as a module, choose M here: the |
| 156 | will be called leds-lp5521. | 158 | module will be called leds-lp3944. |
| 157 | 159 | ||
| 158 | config LEDS_CLEVO_MAIL | 160 | config LEDS_CLEVO_MAIL |
| 159 | tristate "Mail LED on Clevo notebook" | 161 | tristate "Mail LED on Clevo notebook" |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 2d41c4dcf92f..e8cdcf77a4c3 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
| @@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o | |||
| 20 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o | 20 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o |
| 21 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o | 21 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o |
| 22 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | 22 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o |
| 23 | obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o | ||
| 23 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o | 24 | obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o |
| 24 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o | 25 | obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o |
| 25 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o | 26 | obj-$(CONFIG_LEDS_FSG) += leds-fsg.o |
diff --git a/drivers/leds/leds-alix2.c b/drivers/leds/leds-alix2.c index ddbd7730dfc8..731d4eef3425 100644 --- a/drivers/leds/leds-alix2.c +++ b/drivers/leds/leds-alix2.c | |||
| @@ -14,7 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | static int force = 0; | 15 | static int force = 0; |
| 16 | module_param(force, bool, 0444); | 16 | module_param(force, bool, 0444); |
| 17 | MODULE_PARM_DESC(force, "Assume system has ALIX.2 style LEDs"); | 17 | MODULE_PARM_DESC(force, "Assume system has ALIX.2/ALIX.3 style LEDs"); |
| 18 | 18 | ||
| 19 | struct alix_led { | 19 | struct alix_led { |
| 20 | struct led_classdev cdev; | 20 | struct led_classdev cdev; |
| @@ -155,6 +155,11 @@ static int __init alix_led_init(void) | |||
| 155 | goto out; | 155 | goto out; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | /* enable output on GPIO for LED 1,2,3 */ | ||
| 159 | outl(1 << 6, 0x6104); | ||
| 160 | outl(1 << 9, 0x6184); | ||
| 161 | outl(1 << 11, 0x6184); | ||
| 162 | |||
| 158 | pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0); | 163 | pdev = platform_device_register_simple(KBUILD_MODNAME, -1, NULL, 0); |
| 159 | if (!IS_ERR(pdev)) { | 164 | if (!IS_ERR(pdev)) { |
| 160 | ret = platform_driver_probe(&alix_led_driver, alix_led_probe); | 165 | ret = platform_driver_probe(&alix_led_driver, alix_led_probe); |
diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 4149ecb3a9b2..779d7f262c04 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c | |||
| @@ -97,6 +97,10 @@ struct bd2802_led { | |||
| 97 | enum led_ids led_id; | 97 | enum led_ids led_id; |
| 98 | enum led_colors color; | 98 | enum led_colors color; |
| 99 | enum led_bits state; | 99 | enum led_bits state; |
| 100 | |||
| 101 | /* General attributes of RGB LEDs */ | ||
| 102 | int wave_pattern; | ||
| 103 | int rgb_current; | ||
| 100 | }; | 104 | }; |
| 101 | 105 | ||
| 102 | 106 | ||
| @@ -254,7 +258,7 @@ static void bd2802_set_on(struct bd2802_led *led, enum led_ids id, | |||
| 254 | bd2802_reset_cancel(led); | 258 | bd2802_reset_cancel(led); |
| 255 | 259 | ||
| 256 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
| 257 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 261 | bd2802_write_byte(led->client, reg, led->rgb_current); |
| 258 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 262 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
| 259 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 263 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
| 260 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 264 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
| @@ -275,9 +279,9 @@ static void bd2802_set_blink(struct bd2802_led *led, enum led_ids id, | |||
| 275 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); | 279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT1SETUP); |
| 276 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); | 280 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_000); |
| 277 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); | 281 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_CURRENT2SETUP); |
| 278 | bd2802_write_byte(led->client, reg, BD2802_CURRENT_032); | 282 | bd2802_write_byte(led->client, reg, led->rgb_current); |
| 279 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); | 283 | reg = bd2802_get_reg_addr(id, color, BD2802_REG_WAVEPATTERN); |
| 280 | bd2802_write_byte(led->client, reg, BD2802_PATTERN_HALF); | 284 | bd2802_write_byte(led->client, reg, led->wave_pattern); |
| 281 | 285 | ||
| 282 | bd2802_enable(led, id); | 286 | bd2802_enable(led, id); |
| 283 | bd2802_update_state(led, id, color, BD2802_BLINK); | 287 | bd2802_update_state(led, id, color, BD2802_BLINK); |
| @@ -406,7 +410,7 @@ static void bd2802_enable_adv_conf(struct bd2802_led *led) | |||
| 406 | ret = device_create_file(&led->client->dev, | 410 | ret = device_create_file(&led->client->dev, |
| 407 | bd2802_addr_attributes[i]); | 411 | bd2802_addr_attributes[i]); |
| 408 | if (ret) { | 412 | if (ret) { |
| 409 | dev_err(&led->client->dev, "failed to sysfs file %s\n", | 413 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
| 410 | bd2802_addr_attributes[i]->attr.name); | 414 | bd2802_addr_attributes[i]->attr.name); |
| 411 | goto failed_remove_files; | 415 | goto failed_remove_files; |
| 412 | } | 416 | } |
| @@ -483,6 +487,52 @@ static struct device_attribute bd2802_adv_conf_attr = { | |||
| 483 | .store = bd2802_store_adv_conf, | 487 | .store = bd2802_store_adv_conf, |
| 484 | }; | 488 | }; |
| 485 | 489 | ||
| 490 | #define BD2802_CONTROL_ATTR(attr_name, name_str) \ | ||
| 491 | static ssize_t bd2802_show_##attr_name(struct device *dev, \ | ||
| 492 | struct device_attribute *attr, char *buf) \ | ||
| 493 | { \ | ||
| 494 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
| 495 | ssize_t ret; \ | ||
| 496 | down_read(&led->rwsem); \ | ||
| 497 | ret = sprintf(buf, "0x%02x\n", led->attr_name); \ | ||
| 498 | up_read(&led->rwsem); \ | ||
| 499 | return ret; \ | ||
| 500 | } \ | ||
| 501 | static ssize_t bd2802_store_##attr_name(struct device *dev, \ | ||
| 502 | struct device_attribute *attr, const char *buf, size_t count) \ | ||
| 503 | { \ | ||
| 504 | struct bd2802_led *led = i2c_get_clientdata(to_i2c_client(dev));\ | ||
| 505 | unsigned long val; \ | ||
| 506 | int ret; \ | ||
| 507 | if (!count) \ | ||
| 508 | return -EINVAL; \ | ||
| 509 | ret = strict_strtoul(buf, 16, &val); \ | ||
| 510 | if (ret) \ | ||
| 511 | return ret; \ | ||
| 512 | down_write(&led->rwsem); \ | ||
| 513 | led->attr_name = val; \ | ||
| 514 | up_write(&led->rwsem); \ | ||
| 515 | return count; \ | ||
| 516 | } \ | ||
| 517 | static struct device_attribute bd2802_##attr_name##_attr = { \ | ||
| 518 | .attr = { \ | ||
| 519 | .name = name_str, \ | ||
| 520 | .mode = 0644, \ | ||
| 521 | .owner = THIS_MODULE \ | ||
| 522 | }, \ | ||
| 523 | .show = bd2802_show_##attr_name, \ | ||
| 524 | .store = bd2802_store_##attr_name, \ | ||
| 525 | }; | ||
| 526 | |||
| 527 | BD2802_CONTROL_ATTR(wave_pattern, "wave_pattern"); | ||
| 528 | BD2802_CONTROL_ATTR(rgb_current, "rgb_current"); | ||
| 529 | |||
| 530 | static struct device_attribute *bd2802_attributes[] = { | ||
| 531 | &bd2802_adv_conf_attr, | ||
| 532 | &bd2802_wave_pattern_attr, | ||
| 533 | &bd2802_rgb_current_attr, | ||
| 534 | }; | ||
| 535 | |||
| 486 | static void bd2802_led_work(struct work_struct *work) | 536 | static void bd2802_led_work(struct work_struct *work) |
| 487 | { | 537 | { |
| 488 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); | 538 | struct bd2802_led *led = container_of(work, struct bd2802_led, work); |
| @@ -538,7 +588,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 538 | led->cdev_led1r.brightness = LED_OFF; | 588 | led->cdev_led1r.brightness = LED_OFF; |
| 539 | led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness; | 589 | led->cdev_led1r.brightness_set = bd2802_set_led1r_brightness; |
| 540 | led->cdev_led1r.blink_set = bd2802_set_led1r_blink; | 590 | led->cdev_led1r.blink_set = bd2802_set_led1r_blink; |
| 541 | led->cdev_led1r.flags |= LED_CORE_SUSPENDRESUME; | ||
| 542 | 591 | ||
| 543 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1r); | 592 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1r); |
| 544 | if (ret < 0) { | 593 | if (ret < 0) { |
| @@ -551,7 +600,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 551 | led->cdev_led1g.brightness = LED_OFF; | 600 | led->cdev_led1g.brightness = LED_OFF; |
| 552 | led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness; | 601 | led->cdev_led1g.brightness_set = bd2802_set_led1g_brightness; |
| 553 | led->cdev_led1g.blink_set = bd2802_set_led1g_blink; | 602 | led->cdev_led1g.blink_set = bd2802_set_led1g_blink; |
| 554 | led->cdev_led1g.flags |= LED_CORE_SUSPENDRESUME; | ||
| 555 | 603 | ||
| 556 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1g); | 604 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1g); |
| 557 | if (ret < 0) { | 605 | if (ret < 0) { |
| @@ -564,7 +612,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 564 | led->cdev_led1b.brightness = LED_OFF; | 612 | led->cdev_led1b.brightness = LED_OFF; |
| 565 | led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness; | 613 | led->cdev_led1b.brightness_set = bd2802_set_led1b_brightness; |
| 566 | led->cdev_led1b.blink_set = bd2802_set_led1b_blink; | 614 | led->cdev_led1b.blink_set = bd2802_set_led1b_blink; |
| 567 | led->cdev_led1b.flags |= LED_CORE_SUSPENDRESUME; | ||
| 568 | 615 | ||
| 569 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1b); | 616 | ret = led_classdev_register(&led->client->dev, &led->cdev_led1b); |
| 570 | if (ret < 0) { | 617 | if (ret < 0) { |
| @@ -577,7 +624,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 577 | led->cdev_led2r.brightness = LED_OFF; | 624 | led->cdev_led2r.brightness = LED_OFF; |
| 578 | led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness; | 625 | led->cdev_led2r.brightness_set = bd2802_set_led2r_brightness; |
| 579 | led->cdev_led2r.blink_set = bd2802_set_led2r_blink; | 626 | led->cdev_led2r.blink_set = bd2802_set_led2r_blink; |
| 580 | led->cdev_led2r.flags |= LED_CORE_SUSPENDRESUME; | ||
| 581 | 627 | ||
| 582 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2r); | 628 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2r); |
| 583 | if (ret < 0) { | 629 | if (ret < 0) { |
| @@ -590,7 +636,6 @@ static int bd2802_register_led_classdev(struct bd2802_led *led) | |||
| 590 | led->cdev_led2g.brightness = LED_OFF; | 636 | led->cdev_led2g.brightness = LED_OFF; |
| 591 | led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness; | 637 | led->cdev_led2g.brightness_set = bd2802_set_led2g_brightness; |
| 592 | led->cdev_led2g.blink_set = bd2802_set_led2g_blink; | 638 | led->cdev_led2g.blink_set = bd2802_set_led2g_blink; |
| 593 | led->cdev_led2g.flags |= LED_CORE_SUSPENDRESUME; | ||
| 594 | 639 | ||
| 595 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2g); | 640 | ret = led_classdev_register(&led->client->dev, &led->cdev_led2g); |
| 596 | if (ret < 0) { | 641 | if (ret < 0) { |
| @@ -640,7 +685,7 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
| 640 | { | 685 | { |
| 641 | struct bd2802_led *led; | 686 | struct bd2802_led *led; |
| 642 | struct bd2802_led_platform_data *pdata; | 687 | struct bd2802_led_platform_data *pdata; |
| 643 | int ret; | 688 | int ret, i; |
| 644 | 689 | ||
| 645 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); | 690 | led = kzalloc(sizeof(struct bd2802_led), GFP_KERNEL); |
| 646 | if (!led) { | 691 | if (!led) { |
| @@ -670,13 +715,20 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
| 670 | /* To save the power, reset BD2802 after detecting */ | 715 | /* To save the power, reset BD2802 after detecting */ |
| 671 | gpio_set_value(led->pdata->reset_gpio, 0); | 716 | gpio_set_value(led->pdata->reset_gpio, 0); |
| 672 | 717 | ||
| 718 | /* Default attributes */ | ||
| 719 | led->wave_pattern = BD2802_PATTERN_HALF; | ||
| 720 | led->rgb_current = BD2802_CURRENT_032; | ||
| 721 | |||
| 673 | init_rwsem(&led->rwsem); | 722 | init_rwsem(&led->rwsem); |
| 674 | 723 | ||
| 675 | ret = device_create_file(&client->dev, &bd2802_adv_conf_attr); | 724 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) { |
| 676 | if (ret) { | 725 | ret = device_create_file(&led->client->dev, |
| 677 | dev_err(&client->dev, "failed to create sysfs file %s\n", | 726 | bd2802_attributes[i]); |
| 678 | bd2802_adv_conf_attr.attr.name); | 727 | if (ret) { |
| 679 | goto failed_free; | 728 | dev_err(&led->client->dev, "failed: sysfs file %s\n", |
| 729 | bd2802_attributes[i]->attr.name); | ||
| 730 | goto failed_unregister_dev_file; | ||
| 731 | } | ||
| 680 | } | 732 | } |
| 681 | 733 | ||
| 682 | ret = bd2802_register_led_classdev(led); | 734 | ret = bd2802_register_led_classdev(led); |
| @@ -686,7 +738,8 @@ static int __devinit bd2802_probe(struct i2c_client *client, | |||
| 686 | return 0; | 738 | return 0; |
| 687 | 739 | ||
| 688 | failed_unregister_dev_file: | 740 | failed_unregister_dev_file: |
| 689 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 741 | for (i--; i >= 0; i--) |
| 742 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
| 690 | failed_free: | 743 | failed_free: |
| 691 | i2c_set_clientdata(client, NULL); | 744 | i2c_set_clientdata(client, NULL); |
| 692 | kfree(led); | 745 | kfree(led); |
| @@ -697,12 +750,14 @@ failed_free: | |||
| 697 | static int __exit bd2802_remove(struct i2c_client *client) | 750 | static int __exit bd2802_remove(struct i2c_client *client) |
| 698 | { | 751 | { |
| 699 | struct bd2802_led *led = i2c_get_clientdata(client); | 752 | struct bd2802_led *led = i2c_get_clientdata(client); |
| 753 | int i; | ||
| 700 | 754 | ||
| 701 | bd2802_unregister_led_classdev(led); | ||
| 702 | gpio_set_value(led->pdata->reset_gpio, 0); | 755 | gpio_set_value(led->pdata->reset_gpio, 0); |
| 756 | bd2802_unregister_led_classdev(led); | ||
| 703 | if (led->adf_on) | 757 | if (led->adf_on) |
| 704 | bd2802_disable_adv_conf(led); | 758 | bd2802_disable_adv_conf(led); |
| 705 | device_remove_file(&client->dev, &bd2802_adv_conf_attr); | 759 | for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) |
| 760 | device_remove_file(&led->client->dev, bd2802_attributes[i]); | ||
| 706 | i2c_set_clientdata(client, NULL); | 761 | i2c_set_clientdata(client, NULL); |
| 707 | kfree(led); | 762 | kfree(led); |
| 708 | 763 | ||
| @@ -723,8 +778,7 @@ static int bd2802_resume(struct i2c_client *client) | |||
| 723 | struct bd2802_led *led = i2c_get_clientdata(client); | 778 | struct bd2802_led *led = i2c_get_clientdata(client); |
| 724 | 779 | ||
| 725 | if (!bd2802_is_all_off(led) || led->adf_on) { | 780 | if (!bd2802_is_all_off(led) || led->adf_on) { |
| 726 | gpio_set_value(led->pdata->reset_gpio, 1); | 781 | bd2802_reset_cancel(led); |
| 727 | udelay(100); | ||
| 728 | bd2802_restore_state(led); | 782 | bd2802_restore_state(led); |
| 729 | } | 783 | } |
| 730 | 784 | ||
| @@ -762,4 +816,4 @@ module_exit(bd2802_exit); | |||
| 762 | 816 | ||
| 763 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); | 817 | MODULE_AUTHOR("Kim Kyuwon <q1.kim@samsung.com>"); |
| 764 | MODULE_DESCRIPTION("BD2802 LED driver"); | 818 | MODULE_DESCRIPTION("BD2802 LED driver"); |
| 765 | MODULE_LICENSE("GPL"); | 819 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index d2109054de85..6b06638eb5b4 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
| @@ -76,7 +76,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
| 76 | struct gpio_led_data *led_dat, struct device *parent, | 76 | struct gpio_led_data *led_dat, struct device *parent, |
| 77 | int (*blink_set)(unsigned, unsigned long *, unsigned long *)) | 77 | int (*blink_set)(unsigned, unsigned long *, unsigned long *)) |
| 78 | { | 78 | { |
| 79 | int ret; | 79 | int ret, state; |
| 80 | 80 | ||
| 81 | /* skip leds that aren't available */ | 81 | /* skip leds that aren't available */ |
| 82 | if (!gpio_is_valid(template->gpio)) { | 82 | if (!gpio_is_valid(template->gpio)) { |
| @@ -99,11 +99,15 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
| 99 | led_dat->cdev.blink_set = gpio_blink_set; | 99 | led_dat->cdev.blink_set = gpio_blink_set; |
| 100 | } | 100 | } |
| 101 | led_dat->cdev.brightness_set = gpio_led_set; | 101 | led_dat->cdev.brightness_set = gpio_led_set; |
| 102 | led_dat->cdev.brightness = LED_OFF; | 102 | if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP) |
| 103 | state = !!gpio_get_value(led_dat->gpio) ^ led_dat->active_low; | ||
| 104 | else | ||
| 105 | state = (template->default_state == LEDS_GPIO_DEFSTATE_ON); | ||
| 106 | led_dat->cdev.brightness = state ? LED_FULL : LED_OFF; | ||
| 103 | if (!template->retain_state_suspended) | 107 | if (!template->retain_state_suspended) |
| 104 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; | 108 | led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME; |
| 105 | 109 | ||
| 106 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low); | 110 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); |
| 107 | if (ret < 0) | 111 | if (ret < 0) |
| 108 | goto err; | 112 | goto err; |
| 109 | 113 | ||
| @@ -129,7 +133,7 @@ static void delete_gpio_led(struct gpio_led_data *led) | |||
| 129 | } | 133 | } |
| 130 | 134 | ||
| 131 | #ifdef CONFIG_LEDS_GPIO_PLATFORM | 135 | #ifdef CONFIG_LEDS_GPIO_PLATFORM |
| 132 | static int gpio_led_probe(struct platform_device *pdev) | 136 | static int __devinit gpio_led_probe(struct platform_device *pdev) |
| 133 | { | 137 | { |
| 134 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; | 138 | struct gpio_led_platform_data *pdata = pdev->dev.platform_data; |
| 135 | struct gpio_led_data *leds_data; | 139 | struct gpio_led_data *leds_data; |
| @@ -223,12 +227,22 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev, | |||
| 223 | memset(&led, 0, sizeof(led)); | 227 | memset(&led, 0, sizeof(led)); |
| 224 | for_each_child_of_node(np, child) { | 228 | for_each_child_of_node(np, child) { |
| 225 | enum of_gpio_flags flags; | 229 | enum of_gpio_flags flags; |
| 230 | const char *state; | ||
| 226 | 231 | ||
| 227 | led.gpio = of_get_gpio_flags(child, 0, &flags); | 232 | led.gpio = of_get_gpio_flags(child, 0, &flags); |
| 228 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; | 233 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; |
| 229 | led.name = of_get_property(child, "label", NULL) ? : child->name; | 234 | led.name = of_get_property(child, "label", NULL) ? : child->name; |
| 230 | led.default_trigger = | 235 | led.default_trigger = |
| 231 | of_get_property(child, "linux,default-trigger", NULL); | 236 | of_get_property(child, "linux,default-trigger", NULL); |
| 237 | state = of_get_property(child, "default-state", NULL); | ||
| 238 | if (state) { | ||
| 239 | if (!strcmp(state, "keep")) | ||
| 240 | led.default_state = LEDS_GPIO_DEFSTATE_KEEP; | ||
| 241 | else if(!strcmp(state, "on")) | ||
| 242 | led.default_state = LEDS_GPIO_DEFSTATE_ON; | ||
| 243 | else | ||
| 244 | led.default_state = LEDS_GPIO_DEFSTATE_OFF; | ||
| 245 | } | ||
| 232 | 246 | ||
| 233 | ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], | 247 | ret = create_gpio_led(&led, &pdata->led_data[pdata->num_leds++], |
| 234 | &ofdev->dev, NULL); | 248 | &ofdev->dev, NULL); |
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c new file mode 100644 index 000000000000..5946208ba26e --- /dev/null +++ b/drivers/leds/leds-lp3944.c | |||
| @@ -0,0 +1,466 @@ | |||
| 1 | /* | ||
| 2 | * leds-lp3944.c - driver for National Semiconductor LP3944 Funlight Chip | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | /* | ||
| 13 | * I2C driver for National Semiconductor LP3944 Funlight Chip | ||
| 14 | * http://www.national.com/pf/LP/LP3944.html | ||
| 15 | * | ||
| 16 | * This helper chip can drive up to 8 leds, with two programmable DIM modes; | ||
| 17 | * it could even be used as a gpio expander but this driver assumes it is used | ||
| 18 | * as a led controller. | ||
| 19 | * | ||
| 20 | * The DIM modes are used to set _blink_ patterns for leds, the pattern is | ||
| 21 | * specified supplying two parameters: | ||
| 22 | * - period: from 0s to 1.6s | ||
| 23 | * - duty cycle: percentage of the period the led is on, from 0 to 100 | ||
| 24 | * | ||
| 25 | * LP3944 can be found on Motorola A910 smartphone, where it drives the rgb | ||
| 26 | * leds, the camera flash light and the displays backlights. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/module.h> | ||
| 30 | #include <linux/i2c.h> | ||
| 31 | #include <linux/leds.h> | ||
| 32 | #include <linux/mutex.h> | ||
| 33 | #include <linux/workqueue.h> | ||
| 34 | #include <linux/leds-lp3944.h> | ||
| 35 | |||
| 36 | /* Read Only Registers */ | ||
| 37 | #define LP3944_REG_INPUT1 0x00 /* LEDs 0-7 InputRegister (Read Only) */ | ||
| 38 | #define LP3944_REG_REGISTER1 0x01 /* None (Read Only) */ | ||
| 39 | |||
| 40 | #define LP3944_REG_PSC0 0x02 /* Frequency Prescaler 0 (R/W) */ | ||
| 41 | #define LP3944_REG_PWM0 0x03 /* PWM Register 0 (R/W) */ | ||
| 42 | #define LP3944_REG_PSC1 0x04 /* Frequency Prescaler 1 (R/W) */ | ||
| 43 | #define LP3944_REG_PWM1 0x05 /* PWM Register 1 (R/W) */ | ||
| 44 | #define LP3944_REG_LS0 0x06 /* LEDs 0-3 Selector (R/W) */ | ||
| 45 | #define LP3944_REG_LS1 0x07 /* LEDs 4-7 Selector (R/W) */ | ||
| 46 | |||
| 47 | /* These registers are not used to control leds in LP3944, they can store | ||
| 48 | * arbitrary values which the chip will ignore. | ||
| 49 | */ | ||
| 50 | #define LP3944_REG_REGISTER8 0x08 | ||
| 51 | #define LP3944_REG_REGISTER9 0x09 | ||
| 52 | |||
| 53 | #define LP3944_DIM0 0 | ||
| 54 | #define LP3944_DIM1 1 | ||
| 55 | |||
| 56 | /* period in ms */ | ||
| 57 | #define LP3944_PERIOD_MIN 0 | ||
| 58 | #define LP3944_PERIOD_MAX 1600 | ||
| 59 | |||
| 60 | /* duty cycle is a percentage */ | ||
| 61 | #define LP3944_DUTY_CYCLE_MIN 0 | ||
| 62 | #define LP3944_DUTY_CYCLE_MAX 100 | ||
| 63 | |||
| 64 | #define ldev_to_led(c) container_of(c, struct lp3944_led_data, ldev) | ||
| 65 | |||
| 66 | /* Saved data */ | ||
| 67 | struct lp3944_led_data { | ||
| 68 | u8 id; | ||
| 69 | enum lp3944_type type; | ||
| 70 | enum lp3944_status status; | ||
| 71 | struct led_classdev ldev; | ||
| 72 | struct i2c_client *client; | ||
| 73 | struct work_struct work; | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct lp3944_data { | ||
| 77 | struct mutex lock; | ||
| 78 | struct i2c_client *client; | ||
| 79 | struct lp3944_led_data leds[LP3944_LEDS_MAX]; | ||
| 80 | }; | ||
| 81 | |||
| 82 | static int lp3944_reg_read(struct i2c_client *client, u8 reg, u8 *value) | ||
| 83 | { | ||
| 84 | int tmp; | ||
| 85 | |||
| 86 | tmp = i2c_smbus_read_byte_data(client, reg); | ||
| 87 | if (tmp < 0) | ||
| 88 | return -EINVAL; | ||
| 89 | |||
| 90 | *value = tmp; | ||
| 91 | |||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int lp3944_reg_write(struct i2c_client *client, u8 reg, u8 value) | ||
| 96 | { | ||
| 97 | return i2c_smbus_write_byte_data(client, reg, value); | ||
| 98 | } | ||
| 99 | |||
| 100 | /** | ||
| 101 | * Set the period for DIM status | ||
| 102 | * | ||
| 103 | * @client: the i2c client | ||
| 104 | * @dim: either LP3944_DIM0 or LP3944_DIM1 | ||
| 105 | * @period: period of a blink, that is a on/off cycle, expressed in ms. | ||
| 106 | */ | ||
| 107 | static int lp3944_dim_set_period(struct i2c_client *client, u8 dim, u16 period) | ||
| 108 | { | ||
| 109 | u8 psc_reg; | ||
| 110 | u8 psc_value; | ||
| 111 | int err; | ||
| 112 | |||
| 113 | if (dim == LP3944_DIM0) | ||
| 114 | psc_reg = LP3944_REG_PSC0; | ||
| 115 | else if (dim == LP3944_DIM1) | ||
| 116 | psc_reg = LP3944_REG_PSC1; | ||
| 117 | else | ||
| 118 | return -EINVAL; | ||
| 119 | |||
| 120 | /* Convert period to Prescaler value */ | ||
| 121 | if (period > LP3944_PERIOD_MAX) | ||
| 122 | return -EINVAL; | ||
| 123 | |||
| 124 | psc_value = (period * 255) / LP3944_PERIOD_MAX; | ||
| 125 | |||
| 126 | err = lp3944_reg_write(client, psc_reg, psc_value); | ||
| 127 | |||
| 128 | return err; | ||
| 129 | } | ||
| 130 | |||
| 131 | /** | ||
| 132 | * Set the duty cycle for DIM status | ||
| 133 | * | ||
| 134 | * @client: the i2c client | ||
| 135 | * @dim: either LP3944_DIM0 or LP3944_DIM1 | ||
| 136 | * @duty_cycle: percentage of a period during which a led is ON | ||
| 137 | */ | ||
| 138 | static int lp3944_dim_set_dutycycle(struct i2c_client *client, u8 dim, | ||
| 139 | u8 duty_cycle) | ||
| 140 | { | ||
| 141 | u8 pwm_reg; | ||
| 142 | u8 pwm_value; | ||
| 143 | int err; | ||
| 144 | |||
| 145 | if (dim == LP3944_DIM0) | ||
| 146 | pwm_reg = LP3944_REG_PWM0; | ||
| 147 | else if (dim == LP3944_DIM1) | ||
| 148 | pwm_reg = LP3944_REG_PWM1; | ||
| 149 | else | ||
| 150 | return -EINVAL; | ||
| 151 | |||
| 152 | /* Convert duty cycle to PWM value */ | ||
| 153 | if (duty_cycle > LP3944_DUTY_CYCLE_MAX) | ||
| 154 | return -EINVAL; | ||
| 155 | |||
| 156 | pwm_value = (duty_cycle * 255) / LP3944_DUTY_CYCLE_MAX; | ||
| 157 | |||
| 158 | err = lp3944_reg_write(client, pwm_reg, pwm_value); | ||
| 159 | |||
| 160 | return err; | ||
| 161 | } | ||
| 162 | |||
| 163 | /** | ||
| 164 | * Set the led status | ||
| 165 | * | ||
| 166 | * @led: a lp3944_led_data structure | ||
| 167 | * @status: one of LP3944_LED_STATUS_OFF | ||
| 168 | * LP3944_LED_STATUS_ON | ||
| 169 | * LP3944_LED_STATUS_DIM0 | ||
| 170 | * LP3944_LED_STATUS_DIM1 | ||
| 171 | */ | ||
| 172 | static int lp3944_led_set(struct lp3944_led_data *led, u8 status) | ||
| 173 | { | ||
| 174 | struct lp3944_data *data = i2c_get_clientdata(led->client); | ||
| 175 | u8 id = led->id; | ||
| 176 | u8 reg; | ||
| 177 | u8 val = 0; | ||
| 178 | int err; | ||
| 179 | |||
| 180 | dev_dbg(&led->client->dev, "%s: %s, status before normalization:%d\n", | ||
| 181 | __func__, led->ldev.name, status); | ||
| 182 | |||
| 183 | switch (id) { | ||
| 184 | case LP3944_LED0: | ||
| 185 | case LP3944_LED1: | ||
| 186 | case LP3944_LED2: | ||
| 187 | case LP3944_LED3: | ||
| 188 | reg = LP3944_REG_LS0; | ||
| 189 | break; | ||
| 190 | case LP3944_LED4: | ||
| 191 | case LP3944_LED5: | ||
| 192 | case LP3944_LED6: | ||
| 193 | case LP3944_LED7: | ||
| 194 | id -= LP3944_LED4; | ||
| 195 | reg = LP3944_REG_LS1; | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | return -EINVAL; | ||
| 199 | } | ||
| 200 | |||
| 201 | if (status > LP3944_LED_STATUS_DIM1) | ||
| 202 | return -EINVAL; | ||
| 203 | |||
| 204 | /* invert only 0 and 1, leave unchanged the other values, | ||
| 205 | * remember we are abusing status to set blink patterns | ||
| 206 | */ | ||
| 207 | if (led->type == LP3944_LED_TYPE_LED_INVERTED && status < 2) | ||
| 208 | status = 1 - status; | ||
| 209 | |||
| 210 | mutex_lock(&data->lock); | ||
| 211 | lp3944_reg_read(led->client, reg, &val); | ||
| 212 | |||
| 213 | val &= ~(LP3944_LED_STATUS_MASK << (id << 1)); | ||
| 214 | val |= (status << (id << 1)); | ||
| 215 | |||
| 216 | dev_dbg(&led->client->dev, "%s: %s, reg:%d id:%d status:%d val:%#x\n", | ||
| 217 | __func__, led->ldev.name, reg, id, status, val); | ||
| 218 | |||
| 219 | /* set led status */ | ||
| 220 | err = lp3944_reg_write(led->client, reg, val); | ||
| 221 | mutex_unlock(&data->lock); | ||
| 222 | |||
| 223 | return err; | ||
| 224 | } | ||
| 225 | |||
| 226 | static int lp3944_led_set_blink(struct led_classdev *led_cdev, | ||
| 227 | unsigned long *delay_on, | ||
| 228 | unsigned long *delay_off) | ||
| 229 | { | ||
| 230 | struct lp3944_led_data *led = ldev_to_led(led_cdev); | ||
| 231 | u16 period; | ||
| 232 | u8 duty_cycle; | ||
| 233 | int err; | ||
| 234 | |||
| 235 | /* units are in ms */ | ||
| 236 | if (*delay_on + *delay_off > LP3944_PERIOD_MAX) | ||
| 237 | return -EINVAL; | ||
| 238 | |||
| 239 | if (*delay_on == 0 && *delay_off == 0) { | ||
| 240 | /* Special case: the leds subsystem requires a default user | ||
| 241 | * friendly blink pattern for the LED. Let's blink the led | ||
| 242 | * slowly (1Hz). | ||
| 243 | */ | ||
| 244 | *delay_on = 500; | ||
| 245 | *delay_off = 500; | ||
| 246 | } | ||
| 247 | |||
| 248 | period = (*delay_on) + (*delay_off); | ||
| 249 | |||
| 250 | /* duty_cycle is the percentage of period during which the led is ON */ | ||
| 251 | duty_cycle = 100 * (*delay_on) / period; | ||
| 252 | |||
| 253 | /* invert duty cycle for inverted leds, this has the same effect of | ||
| 254 | * swapping delay_on and delay_off | ||
| 255 | */ | ||
| 256 | if (led->type == LP3944_LED_TYPE_LED_INVERTED) | ||
| 257 | duty_cycle = 100 - duty_cycle; | ||
| 258 | |||
| 259 | /* NOTE: using always the first DIM mode, this means that all leds | ||
| 260 | * will have the same blinking pattern. | ||
| 261 | * | ||
| 262 | * We could find a way later to have two leds blinking in hardware | ||
| 263 | * with different patterns at the same time, falling back to software | ||
| 264 | * control for the other ones. | ||
| 265 | */ | ||
| 266 | err = lp3944_dim_set_period(led->client, LP3944_DIM0, period); | ||
| 267 | if (err) | ||
| 268 | return err; | ||
| 269 | |||
| 270 | err = lp3944_dim_set_dutycycle(led->client, LP3944_DIM0, duty_cycle); | ||
| 271 | if (err) | ||
| 272 | return err; | ||
| 273 | |||
| 274 | dev_dbg(&led->client->dev, "%s: OK hardware accelerated blink!\n", | ||
| 275 | __func__); | ||
| 276 | |||
| 277 | led->status = LP3944_LED_STATUS_DIM0; | ||
| 278 | schedule_work(&led->work); | ||
| 279 | |||
| 280 | return 0; | ||
| 281 | } | ||
| 282 | |||
| 283 | static void lp3944_led_set_brightness(struct led_classdev *led_cdev, | ||
| 284 | enum led_brightness brightness) | ||
| 285 | { | ||
| 286 | struct lp3944_led_data *led = ldev_to_led(led_cdev); | ||
| 287 | |||
| 288 | dev_dbg(&led->client->dev, "%s: %s, %d\n", | ||
| 289 | __func__, led_cdev->name, brightness); | ||
| 290 | |||
| 291 | led->status = brightness; | ||
| 292 | schedule_work(&led->work); | ||
| 293 | } | ||
| 294 | |||
| 295 | static void lp3944_led_work(struct work_struct *work) | ||
| 296 | { | ||
| 297 | struct lp3944_led_data *led; | ||
| 298 | |||
| 299 | led = container_of(work, struct lp3944_led_data, work); | ||
| 300 | lp3944_led_set(led, led->status); | ||
| 301 | } | ||
| 302 | |||
| 303 | static int lp3944_configure(struct i2c_client *client, | ||
| 304 | struct lp3944_data *data, | ||
| 305 | struct lp3944_platform_data *pdata) | ||
| 306 | { | ||
| 307 | int i, err = 0; | ||
| 308 | |||
| 309 | for (i = 0; i < pdata->leds_size; i++) { | ||
| 310 | struct lp3944_led *pled = &pdata->leds[i]; | ||
| 311 | struct lp3944_led_data *led = &data->leds[i]; | ||
| 312 | led->client = client; | ||
| 313 | led->id = i; | ||
| 314 | |||
| 315 | switch (pled->type) { | ||
| 316 | |||
| 317 | case LP3944_LED_TYPE_LED: | ||
| 318 | case LP3944_LED_TYPE_LED_INVERTED: | ||
| 319 | led->type = pled->type; | ||
| 320 | led->status = pled->status; | ||
| 321 | led->ldev.name = pled->name; | ||
| 322 | led->ldev.max_brightness = 1; | ||
| 323 | led->ldev.brightness_set = lp3944_led_set_brightness; | ||
| 324 | led->ldev.blink_set = lp3944_led_set_blink; | ||
| 325 | led->ldev.flags = LED_CORE_SUSPENDRESUME; | ||
| 326 | |||
| 327 | INIT_WORK(&led->work, lp3944_led_work); | ||
| 328 | err = led_classdev_register(&client->dev, &led->ldev); | ||
| 329 | if (err < 0) { | ||
| 330 | dev_err(&client->dev, | ||
| 331 | "couldn't register LED %s\n", | ||
| 332 | led->ldev.name); | ||
| 333 | goto exit; | ||
| 334 | } | ||
| 335 | |||
| 336 | /* to expose the default value to userspace */ | ||
| 337 | led->ldev.brightness = led->status; | ||
| 338 | |||
| 339 | /* Set the default led status */ | ||
| 340 | err = lp3944_led_set(led, led->status); | ||
| 341 | if (err < 0) { | ||
| 342 | dev_err(&client->dev, | ||
| 343 | "%s couldn't set STATUS %d\n", | ||
| 344 | led->ldev.name, led->status); | ||
| 345 | goto exit; | ||
| 346 | } | ||
| 347 | break; | ||
| 348 | |||
| 349 | case LP3944_LED_TYPE_NONE: | ||
| 350 | default: | ||
| 351 | break; | ||
| 352 | |||
| 353 | } | ||
| 354 | } | ||
| 355 | return 0; | ||
| 356 | |||
| 357 | exit: | ||
| 358 | if (i > 0) | ||
| 359 | for (i = i - 1; i >= 0; i--) | ||
| 360 | switch (pdata->leds[i].type) { | ||
| 361 | |||
| 362 | case LP3944_LED_TYPE_LED: | ||
| 363 | case LP3944_LED_TYPE_LED_INVERTED: | ||
| 364 | led_classdev_unregister(&data->leds[i].ldev); | ||
| 365 | cancel_work_sync(&data->leds[i].work); | ||
| 366 | break; | ||
| 367 | |||
| 368 | case LP3944_LED_TYPE_NONE: | ||
| 369 | default: | ||
| 370 | break; | ||
| 371 | } | ||
| 372 | |||
| 373 | return err; | ||
| 374 | } | ||
| 375 | |||
| 376 | static int __devinit lp3944_probe(struct i2c_client *client, | ||
| 377 | const struct i2c_device_id *id) | ||
| 378 | { | ||
| 379 | struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; | ||
| 380 | struct lp3944_data *data; | ||
| 381 | |||
| 382 | if (lp3944_pdata == NULL) { | ||
| 383 | dev_err(&client->dev, "no platform data\n"); | ||
| 384 | return -EINVAL; | ||
| 385 | } | ||
| 386 | |||
| 387 | /* Let's see whether this adapter can support what we need. */ | ||
| 388 | if (!i2c_check_functionality(client->adapter, | ||
| 389 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
| 390 | dev_err(&client->dev, "insufficient functionality!\n"); | ||
| 391 | return -ENODEV; | ||
| 392 | } | ||
| 393 | |||
| 394 | data = kzalloc(sizeof(struct lp3944_data), GFP_KERNEL); | ||
| 395 | if (!data) | ||
| 396 | return -ENOMEM; | ||
| 397 | |||
| 398 | data->client = client; | ||
| 399 | i2c_set_clientdata(client, data); | ||
| 400 | |||
| 401 | mutex_init(&data->lock); | ||
| 402 | |||
| 403 | dev_info(&client->dev, "lp3944 enabled\n"); | ||
| 404 | |||
| 405 | lp3944_configure(client, data, lp3944_pdata); | ||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | static int __devexit lp3944_remove(struct i2c_client *client) | ||
| 410 | { | ||
| 411 | struct lp3944_platform_data *pdata = client->dev.platform_data; | ||
| 412 | struct lp3944_data *data = i2c_get_clientdata(client); | ||
| 413 | int i; | ||
| 414 | |||
| 415 | for (i = 0; i < pdata->leds_size; i++) | ||
| 416 | switch (data->leds[i].type) { | ||
| 417 | case LP3944_LED_TYPE_LED: | ||
| 418 | case LP3944_LED_TYPE_LED_INVERTED: | ||
| 419 | led_classdev_unregister(&data->leds[i].ldev); | ||
| 420 | cancel_work_sync(&data->leds[i].work); | ||
| 421 | break; | ||
| 422 | |||
| 423 | case LP3944_LED_TYPE_NONE: | ||
| 424 | default: | ||
| 425 | break; | ||
| 426 | } | ||
| 427 | |||
| 428 | kfree(data); | ||
| 429 | i2c_set_clientdata(client, NULL); | ||
| 430 | |||
| 431 | return 0; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* lp3944 i2c driver struct */ | ||
| 435 | static const struct i2c_device_id lp3944_id[] = { | ||
| 436 | {"lp3944", 0}, | ||
| 437 | {} | ||
| 438 | }; | ||
| 439 | |||
| 440 | MODULE_DEVICE_TABLE(i2c, lp3944_id); | ||
| 441 | |||
| 442 | static struct i2c_driver lp3944_driver = { | ||
| 443 | .driver = { | ||
| 444 | .name = "lp3944", | ||
| 445 | }, | ||
| 446 | .probe = lp3944_probe, | ||
| 447 | .remove = __devexit_p(lp3944_remove), | ||
| 448 | .id_table = lp3944_id, | ||
| 449 | }; | ||
| 450 | |||
| 451 | static int __init lp3944_module_init(void) | ||
| 452 | { | ||
| 453 | return i2c_add_driver(&lp3944_driver); | ||
| 454 | } | ||
| 455 | |||
| 456 | static void __exit lp3944_module_exit(void) | ||
| 457 | { | ||
| 458 | i2c_del_driver(&lp3944_driver); | ||
| 459 | } | ||
| 460 | |||
| 461 | module_init(lp3944_module_init); | ||
| 462 | module_exit(lp3944_module_exit); | ||
| 463 | |||
| 464 | MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>"); | ||
| 465 | MODULE_DESCRIPTION("LP3944 Fun Light Chip"); | ||
| 466 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 3937244fdcab..dba8921240f2 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c | |||
| @@ -35,7 +35,7 @@ struct pca9532_data { | |||
| 35 | struct pca9532_led leds[16]; | 35 | struct pca9532_led leds[16]; |
| 36 | struct mutex update_lock; | 36 | struct mutex update_lock; |
| 37 | struct input_dev *idev; | 37 | struct input_dev *idev; |
| 38 | struct work_struct work; | 38 | struct work_struct work; |
| 39 | u8 pwm[2]; | 39 | u8 pwm[2]; |
| 40 | u8 psc[2]; | 40 | u8 psc[2]; |
| 41 | }; | 41 | }; |
| @@ -87,14 +87,14 @@ static int pca9532_calcpwm(struct i2c_client *client, int pwm, int blink, | |||
| 87 | if (b > 0xFF) | 87 | if (b > 0xFF) |
| 88 | return -EINVAL; | 88 | return -EINVAL; |
| 89 | data->pwm[pwm] = b; | 89 | data->pwm[pwm] = b; |
| 90 | data->psc[pwm] = blink; | 90 | data->psc[pwm] = blink; |
| 91 | return 0; | 91 | return 0; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static int pca9532_setpwm(struct i2c_client *client, int pwm) | 94 | static int pca9532_setpwm(struct i2c_client *client, int pwm) |
| 95 | { | 95 | { |
| 96 | struct pca9532_data *data = i2c_get_clientdata(client); | 96 | struct pca9532_data *data = i2c_get_clientdata(client); |
| 97 | mutex_lock(&data->update_lock); | 97 | mutex_lock(&data->update_lock); |
| 98 | i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm), | 98 | i2c_smbus_write_byte_data(client, PCA9532_REG_PWM(pwm), |
| 99 | data->pwm[pwm]); | 99 | data->pwm[pwm]); |
| 100 | i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm), | 100 | i2c_smbus_write_byte_data(client, PCA9532_REG_PSC(pwm), |
| @@ -132,11 +132,11 @@ static void pca9532_set_brightness(struct led_classdev *led_cdev, | |||
| 132 | led->state = PCA9532_ON; | 132 | led->state = PCA9532_ON; |
| 133 | else { | 133 | else { |
| 134 | led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */ | 134 | led->state = PCA9532_PWM0; /* Thecus: hardcode one pwm */ |
| 135 | err = pca9532_calcpwm(led->client, 0, 0, value); | 135 | err = pca9532_calcpwm(led->client, 0, 0, value); |
| 136 | if (err) | 136 | if (err) |
| 137 | return; /* XXX: led api doesn't allow error code? */ | 137 | return; /* XXX: led api doesn't allow error code? */ |
| 138 | } | 138 | } |
| 139 | schedule_work(&led->work); | 139 | schedule_work(&led->work); |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | static int pca9532_set_blink(struct led_classdev *led_cdev, | 142 | static int pca9532_set_blink(struct led_classdev *led_cdev, |
| @@ -145,7 +145,7 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, | |||
| 145 | struct pca9532_led *led = ldev_to_led(led_cdev); | 145 | struct pca9532_led *led = ldev_to_led(led_cdev); |
| 146 | struct i2c_client *client = led->client; | 146 | struct i2c_client *client = led->client; |
| 147 | int psc; | 147 | int psc; |
| 148 | int err = 0; | 148 | int err = 0; |
| 149 | 149 | ||
| 150 | if (*delay_on == 0 && *delay_off == 0) { | 150 | if (*delay_on == 0 && *delay_off == 0) { |
| 151 | /* led subsystem ask us for a blink rate */ | 151 | /* led subsystem ask us for a blink rate */ |
| @@ -157,11 +157,11 @@ static int pca9532_set_blink(struct led_classdev *led_cdev, | |||
| 157 | 157 | ||
| 158 | /* Thecus specific: only use PSC/PWM 0 */ | 158 | /* Thecus specific: only use PSC/PWM 0 */ |
| 159 | psc = (*delay_on * 152-1)/1000; | 159 | psc = (*delay_on * 152-1)/1000; |
| 160 | err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); | 160 | err = pca9532_calcpwm(client, 0, psc, led_cdev->brightness); |
| 161 | if (err) | 161 | if (err) |
| 162 | return err; | 162 | return err; |
| 163 | schedule_work(&led->work); | 163 | schedule_work(&led->work); |
| 164 | return 0; | 164 | return 0; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | static int pca9532_event(struct input_dev *dev, unsigned int type, | 167 | static int pca9532_event(struct input_dev *dev, unsigned int type, |
| @@ -178,15 +178,15 @@ static int pca9532_event(struct input_dev *dev, unsigned int type, | |||
| 178 | else | 178 | else |
| 179 | data->pwm[1] = 0; | 179 | data->pwm[1] = 0; |
| 180 | 180 | ||
| 181 | schedule_work(&data->work); | 181 | schedule_work(&data->work); |
| 182 | 182 | ||
| 183 | return 0; | 183 | return 0; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | static void pca9532_input_work(struct work_struct *work) | 186 | static void pca9532_input_work(struct work_struct *work) |
| 187 | { | 187 | { |
| 188 | struct pca9532_data *data; | 188 | struct pca9532_data *data; |
| 189 | data = container_of(work, struct pca9532_data, work); | 189 | data = container_of(work, struct pca9532_data, work); |
| 190 | mutex_lock(&data->update_lock); | 190 | mutex_lock(&data->update_lock); |
| 191 | i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1), | 191 | i2c_smbus_write_byte_data(data->client, PCA9532_REG_PWM(1), |
| 192 | data->pwm[1]); | 192 | data->pwm[1]); |
| @@ -195,11 +195,11 @@ static void pca9532_input_work(struct work_struct *work) | |||
| 195 | 195 | ||
| 196 | static void pca9532_led_work(struct work_struct *work) | 196 | static void pca9532_led_work(struct work_struct *work) |
| 197 | { | 197 | { |
| 198 | struct pca9532_led *led; | 198 | struct pca9532_led *led; |
| 199 | led = container_of(work, struct pca9532_led, work); | 199 | led = container_of(work, struct pca9532_led, work); |
| 200 | if (led->state == PCA9532_PWM0) | 200 | if (led->state == PCA9532_PWM0) |
| 201 | pca9532_setpwm(led->client, 0); | 201 | pca9532_setpwm(led->client, 0); |
| 202 | pca9532_setled(led); | 202 | pca9532_setled(led); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static int pca9532_configure(struct i2c_client *client, | 205 | static int pca9532_configure(struct i2c_client *client, |
| @@ -232,7 +232,7 @@ static int pca9532_configure(struct i2c_client *client, | |||
| 232 | led->ldev.brightness = LED_OFF; | 232 | led->ldev.brightness = LED_OFF; |
| 233 | led->ldev.brightness_set = pca9532_set_brightness; | 233 | led->ldev.brightness_set = pca9532_set_brightness; |
| 234 | led->ldev.blink_set = pca9532_set_blink; | 234 | led->ldev.blink_set = pca9532_set_blink; |
| 235 | INIT_WORK(&led->work, pca9532_led_work); | 235 | INIT_WORK(&led->work, pca9532_led_work); |
| 236 | err = led_classdev_register(&client->dev, &led->ldev); | 236 | err = led_classdev_register(&client->dev, &led->ldev); |
| 237 | if (err < 0) { | 237 | if (err < 0) { |
| 238 | dev_err(&client->dev, | 238 | dev_err(&client->dev, |
| @@ -262,11 +262,11 @@ static int pca9532_configure(struct i2c_client *client, | |||
| 262 | BIT_MASK(SND_TONE); | 262 | BIT_MASK(SND_TONE); |
| 263 | data->idev->event = pca9532_event; | 263 | data->idev->event = pca9532_event; |
| 264 | input_set_drvdata(data->idev, data); | 264 | input_set_drvdata(data->idev, data); |
| 265 | INIT_WORK(&data->work, pca9532_input_work); | 265 | INIT_WORK(&data->work, pca9532_input_work); |
| 266 | err = input_register_device(data->idev); | 266 | err = input_register_device(data->idev); |
| 267 | if (err) { | 267 | if (err) { |
| 268 | input_free_device(data->idev); | 268 | input_free_device(data->idev); |
| 269 | cancel_work_sync(&data->work); | 269 | cancel_work_sync(&data->work); |
| 270 | data->idev = NULL; | 270 | data->idev = NULL; |
| 271 | goto exit; | 271 | goto exit; |
| 272 | } | 272 | } |
| @@ -283,13 +283,13 @@ exit: | |||
| 283 | break; | 283 | break; |
| 284 | case PCA9532_TYPE_LED: | 284 | case PCA9532_TYPE_LED: |
| 285 | led_classdev_unregister(&data->leds[i].ldev); | 285 | led_classdev_unregister(&data->leds[i].ldev); |
| 286 | cancel_work_sync(&data->leds[i].work); | 286 | cancel_work_sync(&data->leds[i].work); |
| 287 | break; | 287 | break; |
| 288 | case PCA9532_TYPE_N2100_BEEP: | 288 | case PCA9532_TYPE_N2100_BEEP: |
| 289 | if (data->idev != NULL) { | 289 | if (data->idev != NULL) { |
| 290 | input_unregister_device(data->idev); | 290 | input_unregister_device(data->idev); |
| 291 | input_free_device(data->idev); | 291 | input_free_device(data->idev); |
| 292 | cancel_work_sync(&data->work); | 292 | cancel_work_sync(&data->work); |
| 293 | data->idev = NULL; | 293 | data->idev = NULL; |
| 294 | } | 294 | } |
| 295 | break; | 295 | break; |
| @@ -340,13 +340,13 @@ static int pca9532_remove(struct i2c_client *client) | |||
| 340 | break; | 340 | break; |
| 341 | case PCA9532_TYPE_LED: | 341 | case PCA9532_TYPE_LED: |
| 342 | led_classdev_unregister(&data->leds[i].ldev); | 342 | led_classdev_unregister(&data->leds[i].ldev); |
| 343 | cancel_work_sync(&data->leds[i].work); | 343 | cancel_work_sync(&data->leds[i].work); |
| 344 | break; | 344 | break; |
| 345 | case PCA9532_TYPE_N2100_BEEP: | 345 | case PCA9532_TYPE_N2100_BEEP: |
| 346 | if (data->idev != NULL) { | 346 | if (data->idev != NULL) { |
| 347 | input_unregister_device(data->idev); | 347 | input_unregister_device(data->idev); |
| 348 | input_free_device(data->idev); | 348 | input_free_device(data->idev); |
| 349 | cancel_work_sync(&data->work); | 349 | cancel_work_sync(&data->work); |
| 350 | data->idev = NULL; | 350 | data->idev = NULL; |
| 351 | } | 351 | } |
| 352 | break; | 352 | break; |
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 6e149f4a1fff..a0f68386c12f 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c | |||
| @@ -378,6 +378,17 @@ static struct macio_dev * macio_add_one_device(struct macio_chip *chip, | |||
| 378 | dev->ofdev.dev.bus = &macio_bus_type; | 378 | dev->ofdev.dev.bus = &macio_bus_type; |
| 379 | dev->ofdev.dev.release = macio_release_dev; | 379 | dev->ofdev.dev.release = macio_release_dev; |
| 380 | 380 | ||
| 381 | #ifdef CONFIG_PCI | ||
| 382 | /* Set the DMA ops to the ones from the PCI device, this could be | ||
| 383 | * fishy if we didn't know that on PowerMac it's always direct ops | ||
| 384 | * or iommu ops that will work fine | ||
| 385 | */ | ||
| 386 | dev->ofdev.dev.archdata.dma_ops = | ||
| 387 | chip->lbus.pdev->dev.archdata.dma_ops; | ||
| 388 | dev->ofdev.dev.archdata.dma_data = | ||
| 389 | chip->lbus.pdev->dev.archdata.dma_data; | ||
| 390 | #endif /* CONFIG_PCI */ | ||
| 391 | |||
| 381 | #ifdef DEBUG | 392 | #ifdef DEBUG |
| 382 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", | 393 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", |
| 383 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); | 394 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); |
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index 7232fe7104aa..fee6a4022bc1 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig | |||
| @@ -357,6 +357,8 @@ config EEEPC_LAPTOP | |||
| 357 | depends on RFKILL || RFKILL = n | 357 | depends on RFKILL || RFKILL = n |
| 358 | select BACKLIGHT_CLASS_DEVICE | 358 | select BACKLIGHT_CLASS_DEVICE |
| 359 | select HWMON | 359 | select HWMON |
| 360 | select HOTPLUG | ||
| 361 | select HOTPLUG_PCI if PCI | ||
| 360 | ---help--- | 362 | ---help--- |
| 361 | This driver supports the Fn-Fx keys on Eee PC laptops. | 363 | This driver supports the Fn-Fx keys on Eee PC laptops. |
| 362 | 364 | ||
diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 4207b26ff990..ec560f16d720 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | * GNU General Public License for more details. | 16 | * GNU General Public License for more details. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 20 | |||
| 19 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 20 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 21 | #include <linux/init.h> | 23 | #include <linux/init.h> |
| @@ -31,6 +33,7 @@ | |||
| 31 | #include <linux/input.h> | 33 | #include <linux/input.h> |
| 32 | #include <linux/rfkill.h> | 34 | #include <linux/rfkill.h> |
| 33 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
| 36 | #include <linux/pci_hotplug.h> | ||
| 34 | 37 | ||
| 35 | #define EEEPC_LAPTOP_VERSION "0.1" | 38 | #define EEEPC_LAPTOP_VERSION "0.1" |
| 36 | 39 | ||
| @@ -40,11 +43,6 @@ | |||
| 40 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" | 43 | #define EEEPC_HOTK_DEVICE_NAME "Hotkey" |
| 41 | #define EEEPC_HOTK_HID "ASUS010" | 44 | #define EEEPC_HOTK_HID "ASUS010" |
| 42 | 45 | ||
| 43 | #define EEEPC_LOG EEEPC_HOTK_FILE ": " | ||
| 44 | #define EEEPC_ERR KERN_ERR EEEPC_LOG | ||
| 45 | #define EEEPC_WARNING KERN_WARNING EEEPC_LOG | ||
| 46 | #define EEEPC_NOTICE KERN_NOTICE EEEPC_LOG | ||
| 47 | #define EEEPC_INFO KERN_INFO EEEPC_LOG | ||
| 48 | 46 | ||
| 49 | /* | 47 | /* |
| 50 | * Definitions for Asus EeePC | 48 | * Definitions for Asus EeePC |
| @@ -141,8 +139,10 @@ struct eeepc_hotk { | |||
| 141 | u16 event_count[128]; /* count for each event */ | 139 | u16 event_count[128]; /* count for each event */ |
| 142 | struct input_dev *inputdev; | 140 | struct input_dev *inputdev; |
| 143 | u16 *keycode_map; | 141 | u16 *keycode_map; |
| 144 | struct rfkill *eeepc_wlan_rfkill; | 142 | struct rfkill *wlan_rfkill; |
| 145 | struct rfkill *eeepc_bluetooth_rfkill; | 143 | struct rfkill *bluetooth_rfkill; |
| 144 | struct rfkill *wwan3g_rfkill; | ||
| 145 | struct hotplug_slot *hotplug_slot; | ||
| 146 | }; | 146 | }; |
| 147 | 147 | ||
| 148 | /* The actual device the driver binds to */ | 148 | /* The actual device the driver binds to */ |
| @@ -213,6 +213,15 @@ static struct acpi_driver eeepc_hotk_driver = { | |||
| 213 | }, | 213 | }, |
| 214 | }; | 214 | }; |
| 215 | 215 | ||
| 216 | /* PCI hotplug ops */ | ||
| 217 | static int eeepc_get_adapter_status(struct hotplug_slot *slot, u8 *value); | ||
| 218 | |||
| 219 | static struct hotplug_slot_ops eeepc_hotplug_slot_ops = { | ||
| 220 | .owner = THIS_MODULE, | ||
| 221 | .get_adapter_status = eeepc_get_adapter_status, | ||
| 222 | .get_power_status = eeepc_get_adapter_status, | ||
| 223 | }; | ||
| 224 | |||
| 216 | /* The backlight device /sys/class/backlight */ | 225 | /* The backlight device /sys/class/backlight */ |
| 217 | static struct backlight_device *eeepc_backlight_device; | 226 | static struct backlight_device *eeepc_backlight_device; |
| 218 | 227 | ||
| @@ -274,20 +283,20 @@ static int set_acpi(int cm, int value) | |||
| 274 | if (method == NULL) | 283 | if (method == NULL) |
| 275 | return -ENODEV; | 284 | return -ENODEV; |
| 276 | if (write_acpi_int(ehotk->handle, method, value, NULL)) | 285 | if (write_acpi_int(ehotk->handle, method, value, NULL)) |
| 277 | printk(EEEPC_WARNING "Error writing %s\n", method); | 286 | pr_warning("Error writing %s\n", method); |
| 278 | } | 287 | } |
| 279 | return 0; | 288 | return 0; |
| 280 | } | 289 | } |
| 281 | 290 | ||
| 282 | static int get_acpi(int cm) | 291 | static int get_acpi(int cm) |
| 283 | { | 292 | { |
| 284 | int value = -1; | 293 | int value = -ENODEV; |
| 285 | if ((ehotk->cm_supported & (0x1 << cm))) { | 294 | if ((ehotk->cm_supported & (0x1 << cm))) { |
| 286 | const char *method = cm_getv[cm]; | 295 | const char *method = cm_getv[cm]; |
| 287 | if (method == NULL) | 296 | if (method == NULL) |
| 288 | return -ENODEV; | 297 | return -ENODEV; |
| 289 | if (read_acpi_int(ehotk->handle, method, &value)) | 298 | if (read_acpi_int(ehotk->handle, method, &value)) |
| 290 | printk(EEEPC_WARNING "Error reading %s\n", method); | 299 | pr_warning("Error reading %s\n", method); |
| 291 | } | 300 | } |
| 292 | return value; | 301 | return value; |
| 293 | } | 302 | } |
| @@ -359,13 +368,19 @@ static ssize_t store_sys_acpi(int cm, const char *buf, size_t count) | |||
| 359 | 368 | ||
| 360 | rv = parse_arg(buf, count, &value); | 369 | rv = parse_arg(buf, count, &value); |
| 361 | if (rv > 0) | 370 | if (rv > 0) |
| 362 | set_acpi(cm, value); | 371 | value = set_acpi(cm, value); |
| 372 | if (value < 0) | ||
| 373 | return value; | ||
| 363 | return rv; | 374 | return rv; |
| 364 | } | 375 | } |
| 365 | 376 | ||
| 366 | static ssize_t show_sys_acpi(int cm, char *buf) | 377 | static ssize_t show_sys_acpi(int cm, char *buf) |
| 367 | { | 378 | { |
| 368 | return sprintf(buf, "%d\n", get_acpi(cm)); | 379 | int value = get_acpi(cm); |
| 380 | |||
| 381 | if (value < 0) | ||
| 382 | return value; | ||
| 383 | return sprintf(buf, "%d\n", value); | ||
| 369 | } | 384 | } |
| 370 | 385 | ||
| 371 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ | 386 | #define EEEPC_CREATE_DEVICE_ATTR(_name, _cm) \ |
| @@ -539,6 +554,28 @@ static int eeepc_setkeycode(struct input_dev *dev, int scancode, int keycode) | |||
| 539 | return -EINVAL; | 554 | return -EINVAL; |
| 540 | } | 555 | } |
| 541 | 556 | ||
| 557 | static void cmsg_quirk(int cm, const char *name) | ||
| 558 | { | ||
| 559 | int dummy; | ||
| 560 | |||
| 561 | /* Some BIOSes do not report cm although it is avaliable. | ||
| 562 | Check if cm_getv[cm] works and, if yes, assume cm should be set. */ | ||
| 563 | if (!(ehotk->cm_supported & (1 << cm)) | ||
| 564 | && !read_acpi_int(ehotk->handle, cm_getv[cm], &dummy)) { | ||
| 565 | pr_info("%s (%x) not reported by BIOS," | ||
| 566 | " enabling anyway\n", name, 1 << cm); | ||
| 567 | ehotk->cm_supported |= 1 << cm; | ||
| 568 | } | ||
| 569 | } | ||
| 570 | |||
| 571 | static void cmsg_quirks(void) | ||
| 572 | { | ||
| 573 | cmsg_quirk(CM_ASL_LID, "LID"); | ||
| 574 | cmsg_quirk(CM_ASL_TYPE, "TYPE"); | ||
| 575 | cmsg_quirk(CM_ASL_PANELPOWER, "PANELPOWER"); | ||
| 576 | cmsg_quirk(CM_ASL_TPD, "TPD"); | ||
| 577 | } | ||
| 578 | |||
| 542 | static int eeepc_hotk_check(void) | 579 | static int eeepc_hotk_check(void) |
| 543 | { | 580 | { |
| 544 | const struct key_entry *key; | 581 | const struct key_entry *key; |
| @@ -551,26 +588,24 @@ static int eeepc_hotk_check(void) | |||
| 551 | if (ehotk->device->status.present) { | 588 | if (ehotk->device->status.present) { |
| 552 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, | 589 | if (write_acpi_int(ehotk->handle, "INIT", ehotk->init_flag, |
| 553 | &buffer)) { | 590 | &buffer)) { |
| 554 | printk(EEEPC_ERR "Hotkey initialization failed\n"); | 591 | pr_err("Hotkey initialization failed\n"); |
| 555 | return -ENODEV; | 592 | return -ENODEV; |
| 556 | } else { | 593 | } else { |
| 557 | printk(EEEPC_NOTICE "Hotkey init flags 0x%x\n", | 594 | pr_notice("Hotkey init flags 0x%x\n", ehotk->init_flag); |
| 558 | ehotk->init_flag); | ||
| 559 | } | 595 | } |
| 560 | /* get control methods supported */ | 596 | /* get control methods supported */ |
| 561 | if (read_acpi_int(ehotk->handle, "CMSG" | 597 | if (read_acpi_int(ehotk->handle, "CMSG" |
| 562 | , &ehotk->cm_supported)) { | 598 | , &ehotk->cm_supported)) { |
| 563 | printk(EEEPC_ERR | 599 | pr_err("Get control methods supported failed\n"); |
| 564 | "Get control methods supported failed\n"); | ||
| 565 | return -ENODEV; | 600 | return -ENODEV; |
| 566 | } else { | 601 | } else { |
| 567 | printk(EEEPC_INFO | 602 | cmsg_quirks(); |
| 568 | "Get control methods supported: 0x%x\n", | 603 | pr_info("Get control methods supported: 0x%x\n", |
| 569 | ehotk->cm_supported); | 604 | ehotk->cm_supported); |
| 570 | } | 605 | } |
| 571 | ehotk->inputdev = input_allocate_device(); | 606 | ehotk->inputdev = input_allocate_device(); |
| 572 | if (!ehotk->inputdev) { | 607 | if (!ehotk->inputdev) { |
| 573 | printk(EEEPC_INFO "Unable to allocate input device\n"); | 608 | pr_info("Unable to allocate input device\n"); |
| 574 | return 0; | 609 | return 0; |
| 575 | } | 610 | } |
| 576 | ehotk->inputdev->name = "Asus EeePC extra buttons"; | 611 | ehotk->inputdev->name = "Asus EeePC extra buttons"; |
| @@ -589,12 +624,12 @@ static int eeepc_hotk_check(void) | |||
| 589 | } | 624 | } |
| 590 | result = input_register_device(ehotk->inputdev); | 625 | result = input_register_device(ehotk->inputdev); |
| 591 | if (result) { | 626 | if (result) { |
| 592 | printk(EEEPC_INFO "Unable to register input device\n"); | 627 | pr_info("Unable to register input device\n"); |
| 593 | input_free_device(ehotk->inputdev); | 628 | input_free_device(ehotk->inputdev); |
| 594 | return 0; | 629 | return 0; |
| 595 | } | 630 | } |
| 596 | } else { | 631 | } else { |
| 597 | printk(EEEPC_ERR "Hotkey device not present, aborting\n"); | 632 | pr_err("Hotkey device not present, aborting\n"); |
| 598 | return -EINVAL; | 633 | return -EINVAL; |
| 599 | } | 634 | } |
| 600 | return 0; | 635 | return 0; |
| @@ -612,6 +647,19 @@ static int notify_brn(void) | |||
| 612 | return -1; | 647 | return -1; |
| 613 | } | 648 | } |
| 614 | 649 | ||
| 650 | static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, | ||
| 651 | u8 *value) | ||
| 652 | { | ||
| 653 | int val = get_acpi(CM_ASL_WLAN); | ||
| 654 | |||
| 655 | if (val == 1 || val == 0) | ||
| 656 | *value = val; | ||
| 657 | else | ||
| 658 | return -EINVAL; | ||
| 659 | |||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 615 | static void eeepc_rfkill_hotplug(void) | 663 | static void eeepc_rfkill_hotplug(void) |
| 616 | { | 664 | { |
| 617 | struct pci_dev *dev; | 665 | struct pci_dev *dev; |
| @@ -619,7 +667,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 619 | bool blocked; | 667 | bool blocked; |
| 620 | 668 | ||
| 621 | if (!bus) { | 669 | if (!bus) { |
| 622 | printk(EEEPC_WARNING "Unable to find PCI bus 1?\n"); | 670 | pr_warning("Unable to find PCI bus 1?\n"); |
| 623 | return; | 671 | return; |
| 624 | } | 672 | } |
| 625 | 673 | ||
| @@ -635,7 +683,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 635 | if (dev) { | 683 | if (dev) { |
| 636 | pci_bus_assign_resources(bus); | 684 | pci_bus_assign_resources(bus); |
| 637 | if (pci_bus_add_device(dev)) | 685 | if (pci_bus_add_device(dev)) |
| 638 | printk(EEEPC_ERR "Unable to hotplug wifi\n"); | 686 | pr_err("Unable to hotplug wifi\n"); |
| 639 | } | 687 | } |
| 640 | } else { | 688 | } else { |
| 641 | dev = pci_get_slot(bus, 0); | 689 | dev = pci_get_slot(bus, 0); |
| @@ -645,7 +693,7 @@ static void eeepc_rfkill_hotplug(void) | |||
| 645 | } | 693 | } |
| 646 | } | 694 | } |
| 647 | 695 | ||
| 648 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, blocked); | 696 | rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); |
| 649 | } | 697 | } |
| 650 | 698 | ||
| 651 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) | 699 | static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) |
| @@ -718,8 +766,7 @@ static int eeepc_register_rfkill_notifier(char *node) | |||
| 718 | eeepc_rfkill_notify, | 766 | eeepc_rfkill_notify, |
| 719 | NULL); | 767 | NULL); |
| 720 | if (ACPI_FAILURE(status)) | 768 | if (ACPI_FAILURE(status)) |
| 721 | printk(EEEPC_WARNING | 769 | pr_warning("Failed to register notify on %s\n", node); |
| 722 | "Failed to register notify on %s\n", node); | ||
| 723 | } else | 770 | } else |
| 724 | return -ENODEV; | 771 | return -ENODEV; |
| 725 | 772 | ||
| @@ -738,19 +785,66 @@ static void eeepc_unregister_rfkill_notifier(char *node) | |||
| 738 | ACPI_SYSTEM_NOTIFY, | 785 | ACPI_SYSTEM_NOTIFY, |
| 739 | eeepc_rfkill_notify); | 786 | eeepc_rfkill_notify); |
| 740 | if (ACPI_FAILURE(status)) | 787 | if (ACPI_FAILURE(status)) |
| 741 | printk(EEEPC_ERR | 788 | pr_err("Error removing rfkill notify handler %s\n", |
| 742 | "Error removing rfkill notify handler %s\n", | ||
| 743 | node); | 789 | node); |
| 744 | } | 790 | } |
| 745 | } | 791 | } |
| 746 | 792 | ||
| 793 | static void eeepc_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot) | ||
| 794 | { | ||
| 795 | kfree(hotplug_slot->info); | ||
| 796 | kfree(hotplug_slot); | ||
| 797 | } | ||
| 798 | |||
| 799 | static int eeepc_setup_pci_hotplug(void) | ||
| 800 | { | ||
| 801 | int ret = -ENOMEM; | ||
| 802 | struct pci_bus *bus = pci_find_bus(0, 1); | ||
| 803 | |||
| 804 | if (!bus) { | ||
| 805 | pr_err("Unable to find wifi PCI bus\n"); | ||
| 806 | return -ENODEV; | ||
| 807 | } | ||
| 808 | |||
| 809 | ehotk->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL); | ||
| 810 | if (!ehotk->hotplug_slot) | ||
| 811 | goto error_slot; | ||
| 812 | |||
| 813 | ehotk->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info), | ||
| 814 | GFP_KERNEL); | ||
| 815 | if (!ehotk->hotplug_slot->info) | ||
| 816 | goto error_info; | ||
| 817 | |||
| 818 | ehotk->hotplug_slot->private = ehotk; | ||
| 819 | ehotk->hotplug_slot->release = &eeepc_cleanup_pci_hotplug; | ||
| 820 | ehotk->hotplug_slot->ops = &eeepc_hotplug_slot_ops; | ||
| 821 | eeepc_get_adapter_status(ehotk->hotplug_slot, | ||
| 822 | &ehotk->hotplug_slot->info->adapter_status); | ||
| 823 | |||
| 824 | ret = pci_hp_register(ehotk->hotplug_slot, bus, 0, "eeepc-wifi"); | ||
| 825 | if (ret) { | ||
| 826 | pr_err("Unable to register hotplug slot - %d\n", ret); | ||
| 827 | goto error_register; | ||
| 828 | } | ||
| 829 | |||
| 830 | return 0; | ||
| 831 | |||
| 832 | error_register: | ||
| 833 | kfree(ehotk->hotplug_slot->info); | ||
| 834 | error_info: | ||
| 835 | kfree(ehotk->hotplug_slot); | ||
| 836 | ehotk->hotplug_slot = NULL; | ||
| 837 | error_slot: | ||
| 838 | return ret; | ||
| 839 | } | ||
| 840 | |||
| 747 | static int eeepc_hotk_add(struct acpi_device *device) | 841 | static int eeepc_hotk_add(struct acpi_device *device) |
| 748 | { | 842 | { |
| 749 | int result; | 843 | int result; |
| 750 | 844 | ||
| 751 | if (!device) | 845 | if (!device) |
| 752 | return -EINVAL; | 846 | return -EINVAL; |
| 753 | printk(EEEPC_NOTICE EEEPC_HOTK_NAME "\n"); | 847 | pr_notice(EEEPC_HOTK_NAME "\n"); |
| 754 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); | 848 | ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); |
| 755 | if (!ehotk) | 849 | if (!ehotk) |
| 756 | return -ENOMEM; | 850 | return -ENOMEM; |
| @@ -764,53 +858,8 @@ static int eeepc_hotk_add(struct acpi_device *device) | |||
| 764 | if (result) | 858 | if (result) |
| 765 | goto ehotk_fail; | 859 | goto ehotk_fail; |
| 766 | 860 | ||
| 767 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 768 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 769 | |||
| 770 | if (get_acpi(CM_ASL_WLAN) != -1) { | ||
| 771 | ehotk->eeepc_wlan_rfkill = rfkill_alloc("eeepc-wlan", | ||
| 772 | &device->dev, | ||
| 773 | RFKILL_TYPE_WLAN, | ||
| 774 | &eeepc_rfkill_ops, | ||
| 775 | (void *)CM_ASL_WLAN); | ||
| 776 | |||
| 777 | if (!ehotk->eeepc_wlan_rfkill) | ||
| 778 | goto wlan_fail; | ||
| 779 | |||
| 780 | rfkill_init_sw_state(ehotk->eeepc_wlan_rfkill, | ||
| 781 | get_acpi(CM_ASL_WLAN) != 1); | ||
| 782 | result = rfkill_register(ehotk->eeepc_wlan_rfkill); | ||
| 783 | if (result) | ||
| 784 | goto wlan_fail; | ||
| 785 | } | ||
| 786 | |||
| 787 | if (get_acpi(CM_ASL_BLUETOOTH) != -1) { | ||
| 788 | ehotk->eeepc_bluetooth_rfkill = | ||
| 789 | rfkill_alloc("eeepc-bluetooth", | ||
| 790 | &device->dev, | ||
| 791 | RFKILL_TYPE_BLUETOOTH, | ||
| 792 | &eeepc_rfkill_ops, | ||
| 793 | (void *)CM_ASL_BLUETOOTH); | ||
| 794 | |||
| 795 | if (!ehotk->eeepc_bluetooth_rfkill) | ||
| 796 | goto bluetooth_fail; | ||
| 797 | |||
| 798 | rfkill_init_sw_state(ehotk->eeepc_bluetooth_rfkill, | ||
| 799 | get_acpi(CM_ASL_BLUETOOTH) != 1); | ||
| 800 | result = rfkill_register(ehotk->eeepc_bluetooth_rfkill); | ||
| 801 | if (result) | ||
| 802 | goto bluetooth_fail; | ||
| 803 | } | ||
| 804 | |||
| 805 | return 0; | 861 | return 0; |
| 806 | 862 | ||
| 807 | bluetooth_fail: | ||
| 808 | rfkill_destroy(ehotk->eeepc_bluetooth_rfkill); | ||
| 809 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | ||
| 810 | wlan_fail: | ||
| 811 | rfkill_destroy(ehotk->eeepc_wlan_rfkill); | ||
| 812 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 813 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 814 | ehotk_fail: | 863 | ehotk_fail: |
| 815 | kfree(ehotk); | 864 | kfree(ehotk); |
| 816 | ehotk = NULL; | 865 | ehotk = NULL; |
| @@ -823,16 +872,13 @@ static int eeepc_hotk_remove(struct acpi_device *device, int type) | |||
| 823 | if (!device || !acpi_driver_data(device)) | 872 | if (!device || !acpi_driver_data(device)) |
| 824 | return -EINVAL; | 873 | return -EINVAL; |
| 825 | 874 | ||
| 826 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 827 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 828 | |||
| 829 | kfree(ehotk); | 875 | kfree(ehotk); |
| 830 | return 0; | 876 | return 0; |
| 831 | } | 877 | } |
| 832 | 878 | ||
| 833 | static int eeepc_hotk_resume(struct acpi_device *device) | 879 | static int eeepc_hotk_resume(struct acpi_device *device) |
| 834 | { | 880 | { |
| 835 | if (ehotk->eeepc_wlan_rfkill) { | 881 | if (ehotk->wlan_rfkill) { |
| 836 | bool wlan; | 882 | bool wlan; |
| 837 | 883 | ||
| 838 | /* Workaround - it seems that _PTS disables the wireless | 884 | /* Workaround - it seems that _PTS disables the wireless |
| @@ -844,14 +890,13 @@ static int eeepc_hotk_resume(struct acpi_device *device) | |||
| 844 | wlan = get_acpi(CM_ASL_WLAN); | 890 | wlan = get_acpi(CM_ASL_WLAN); |
| 845 | set_acpi(CM_ASL_WLAN, wlan); | 891 | set_acpi(CM_ASL_WLAN, wlan); |
| 846 | 892 | ||
| 847 | rfkill_set_sw_state(ehotk->eeepc_wlan_rfkill, | 893 | rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); |
| 848 | wlan != 1); | ||
| 849 | 894 | ||
| 850 | eeepc_rfkill_hotplug(); | 895 | eeepc_rfkill_hotplug(); |
| 851 | } | 896 | } |
| 852 | 897 | ||
| 853 | if (ehotk->eeepc_bluetooth_rfkill) | 898 | if (ehotk->bluetooth_rfkill) |
| 854 | rfkill_set_sw_state(ehotk->eeepc_bluetooth_rfkill, | 899 | rfkill_set_sw_state(ehotk->bluetooth_rfkill, |
| 855 | get_acpi(CM_ASL_BLUETOOTH) != 1); | 900 | get_acpi(CM_ASL_BLUETOOTH) != 1); |
| 856 | 901 | ||
| 857 | return 0; | 902 | return 0; |
| @@ -973,10 +1018,16 @@ static void eeepc_backlight_exit(void) | |||
| 973 | 1018 | ||
| 974 | static void eeepc_rfkill_exit(void) | 1019 | static void eeepc_rfkill_exit(void) |
| 975 | { | 1020 | { |
| 976 | if (ehotk->eeepc_wlan_rfkill) | 1021 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); |
| 977 | rfkill_unregister(ehotk->eeepc_wlan_rfkill); | 1022 | eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); |
| 978 | if (ehotk->eeepc_bluetooth_rfkill) | 1023 | if (ehotk->wlan_rfkill) |
| 979 | rfkill_unregister(ehotk->eeepc_bluetooth_rfkill); | 1024 | rfkill_unregister(ehotk->wlan_rfkill); |
| 1025 | if (ehotk->bluetooth_rfkill) | ||
| 1026 | rfkill_unregister(ehotk->bluetooth_rfkill); | ||
| 1027 | if (ehotk->wwan3g_rfkill) | ||
| 1028 | rfkill_unregister(ehotk->wwan3g_rfkill); | ||
| 1029 | if (ehotk->hotplug_slot) | ||
| 1030 | pci_hp_deregister(ehotk->hotplug_slot); | ||
| 980 | } | 1031 | } |
| 981 | 1032 | ||
| 982 | static void eeepc_input_exit(void) | 1033 | static void eeepc_input_exit(void) |
| @@ -1011,6 +1062,75 @@ static void __exit eeepc_laptop_exit(void) | |||
| 1011 | platform_driver_unregister(&platform_driver); | 1062 | platform_driver_unregister(&platform_driver); |
| 1012 | } | 1063 | } |
| 1013 | 1064 | ||
| 1065 | static int eeepc_new_rfkill(struct rfkill **rfkill, | ||
| 1066 | const char *name, struct device *dev, | ||
| 1067 | enum rfkill_type type, int cm) | ||
| 1068 | { | ||
| 1069 | int result; | ||
| 1070 | |||
| 1071 | result = get_acpi(cm); | ||
| 1072 | if (result < 0) | ||
| 1073 | return result; | ||
| 1074 | |||
| 1075 | *rfkill = rfkill_alloc(name, dev, type, | ||
| 1076 | &eeepc_rfkill_ops, (void *)(unsigned long)cm); | ||
| 1077 | |||
| 1078 | if (!*rfkill) | ||
| 1079 | return -EINVAL; | ||
| 1080 | |||
| 1081 | rfkill_init_sw_state(*rfkill, get_acpi(cm) != 1); | ||
| 1082 | result = rfkill_register(*rfkill); | ||
| 1083 | if (result) { | ||
| 1084 | rfkill_destroy(*rfkill); | ||
| 1085 | *rfkill = NULL; | ||
| 1086 | return result; | ||
| 1087 | } | ||
| 1088 | return 0; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | |||
| 1092 | static int eeepc_rfkill_init(struct device *dev) | ||
| 1093 | { | ||
| 1094 | int result = 0; | ||
| 1095 | |||
| 1096 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); | ||
| 1097 | eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); | ||
| 1098 | |||
| 1099 | result = eeepc_new_rfkill(&ehotk->wlan_rfkill, | ||
| 1100 | "eeepc-wlan", dev, | ||
| 1101 | RFKILL_TYPE_WLAN, CM_ASL_WLAN); | ||
| 1102 | |||
| 1103 | if (result && result != -ENODEV) | ||
| 1104 | goto exit; | ||
| 1105 | |||
| 1106 | result = eeepc_new_rfkill(&ehotk->bluetooth_rfkill, | ||
| 1107 | "eeepc-bluetooth", dev, | ||
| 1108 | RFKILL_TYPE_BLUETOOTH, CM_ASL_BLUETOOTH); | ||
| 1109 | |||
| 1110 | if (result && result != -ENODEV) | ||
| 1111 | goto exit; | ||
| 1112 | |||
| 1113 | result = eeepc_new_rfkill(&ehotk->wwan3g_rfkill, | ||
| 1114 | "eeepc-wwan3g", dev, | ||
| 1115 | RFKILL_TYPE_WWAN, CM_ASL_3G); | ||
| 1116 | |||
| 1117 | if (result && result != -ENODEV) | ||
| 1118 | goto exit; | ||
| 1119 | |||
| 1120 | result = eeepc_setup_pci_hotplug(); | ||
| 1121 | /* | ||
| 1122 | * If we get -EBUSY then something else is handling the PCI hotplug - | ||
| 1123 | * don't fail in this case | ||
| 1124 | */ | ||
| 1125 | if (result == -EBUSY) | ||
| 1126 | result = 0; | ||
| 1127 | |||
| 1128 | exit: | ||
| 1129 | if (result && result != -ENODEV) | ||
| 1130 | eeepc_rfkill_exit(); | ||
| 1131 | return result; | ||
| 1132 | } | ||
| 1133 | |||
| 1014 | static int eeepc_backlight_init(struct device *dev) | 1134 | static int eeepc_backlight_init(struct device *dev) |
| 1015 | { | 1135 | { |
| 1016 | struct backlight_device *bd; | 1136 | struct backlight_device *bd; |
| @@ -1018,8 +1138,7 @@ static int eeepc_backlight_init(struct device *dev) | |||
| 1018 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, | 1138 | bd = backlight_device_register(EEEPC_HOTK_FILE, dev, |
| 1019 | NULL, &eeepcbl_ops); | 1139 | NULL, &eeepcbl_ops); |
| 1020 | if (IS_ERR(bd)) { | 1140 | if (IS_ERR(bd)) { |
| 1021 | printk(EEEPC_ERR | 1141 | pr_err("Could not register eeepc backlight device\n"); |
| 1022 | "Could not register eeepc backlight device\n"); | ||
| 1023 | eeepc_backlight_device = NULL; | 1142 | eeepc_backlight_device = NULL; |
| 1024 | return PTR_ERR(bd); | 1143 | return PTR_ERR(bd); |
| 1025 | } | 1144 | } |
| @@ -1038,8 +1157,7 @@ static int eeepc_hwmon_init(struct device *dev) | |||
| 1038 | 1157 | ||
| 1039 | hwmon = hwmon_device_register(dev); | 1158 | hwmon = hwmon_device_register(dev); |
| 1040 | if (IS_ERR(hwmon)) { | 1159 | if (IS_ERR(hwmon)) { |
| 1041 | printk(EEEPC_ERR | 1160 | pr_err("Could not register eeepc hwmon device\n"); |
| 1042 | "Could not register eeepc hwmon device\n"); | ||
| 1043 | eeepc_hwmon_device = NULL; | 1161 | eeepc_hwmon_device = NULL; |
| 1044 | return PTR_ERR(hwmon); | 1162 | return PTR_ERR(hwmon); |
| 1045 | } | 1163 | } |
| @@ -1065,19 +1183,6 @@ static int __init eeepc_laptop_init(void) | |||
| 1065 | acpi_bus_unregister_driver(&eeepc_hotk_driver); | 1183 | acpi_bus_unregister_driver(&eeepc_hotk_driver); |
| 1066 | return -ENODEV; | 1184 | return -ENODEV; |
| 1067 | } | 1185 | } |
| 1068 | dev = acpi_get_physical_device(ehotk->device->handle); | ||
| 1069 | |||
| 1070 | if (!acpi_video_backlight_support()) { | ||
| 1071 | result = eeepc_backlight_init(dev); | ||
| 1072 | if (result) | ||
| 1073 | goto fail_backlight; | ||
| 1074 | } else | ||
| 1075 | printk(EEEPC_INFO "Backlight controlled by ACPI video " | ||
| 1076 | "driver\n"); | ||
| 1077 | |||
| 1078 | result = eeepc_hwmon_init(dev); | ||
| 1079 | if (result) | ||
| 1080 | goto fail_hwmon; | ||
| 1081 | 1186 | ||
| 1082 | eeepc_enable_camera(); | 1187 | eeepc_enable_camera(); |
| 1083 | 1188 | ||
| @@ -1097,7 +1202,33 @@ static int __init eeepc_laptop_init(void) | |||
| 1097 | &platform_attribute_group); | 1202 | &platform_attribute_group); |
| 1098 | if (result) | 1203 | if (result) |
| 1099 | goto fail_sysfs; | 1204 | goto fail_sysfs; |
| 1205 | |||
| 1206 | dev = &platform_device->dev; | ||
| 1207 | |||
| 1208 | if (!acpi_video_backlight_support()) { | ||
| 1209 | result = eeepc_backlight_init(dev); | ||
| 1210 | if (result) | ||
| 1211 | goto fail_backlight; | ||
| 1212 | } else | ||
| 1213 | pr_info("Backlight controlled by ACPI video " | ||
| 1214 | "driver\n"); | ||
| 1215 | |||
| 1216 | result = eeepc_hwmon_init(dev); | ||
| 1217 | if (result) | ||
| 1218 | goto fail_hwmon; | ||
| 1219 | |||
| 1220 | result = eeepc_rfkill_init(dev); | ||
| 1221 | if (result) | ||
| 1222 | goto fail_rfkill; | ||
| 1223 | |||
| 1100 | return 0; | 1224 | return 0; |
| 1225 | fail_rfkill: | ||
| 1226 | eeepc_hwmon_exit(); | ||
| 1227 | fail_hwmon: | ||
| 1228 | eeepc_backlight_exit(); | ||
| 1229 | fail_backlight: | ||
| 1230 | sysfs_remove_group(&platform_device->dev.kobj, | ||
| 1231 | &platform_attribute_group); | ||
| 1101 | fail_sysfs: | 1232 | fail_sysfs: |
| 1102 | platform_device_del(platform_device); | 1233 | platform_device_del(platform_device); |
| 1103 | fail_platform_device2: | 1234 | fail_platform_device2: |
| @@ -1105,12 +1236,7 @@ fail_platform_device2: | |||
| 1105 | fail_platform_device1: | 1236 | fail_platform_device1: |
| 1106 | platform_driver_unregister(&platform_driver); | 1237 | platform_driver_unregister(&platform_driver); |
| 1107 | fail_platform_driver: | 1238 | fail_platform_driver: |
| 1108 | eeepc_hwmon_exit(); | ||
| 1109 | fail_hwmon: | ||
| 1110 | eeepc_backlight_exit(); | ||
| 1111 | fail_backlight: | ||
| 1112 | eeepc_input_exit(); | 1239 | eeepc_input_exit(); |
| 1113 | eeepc_rfkill_exit(); | ||
| 1114 | return result; | 1240 | return result; |
| 1115 | } | 1241 | } |
| 1116 | 1242 | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 38bfdb0f6660..3f1045993474 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -550,7 +550,7 @@ static void acm_waker(struct work_struct *waker) | |||
| 550 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) | 550 | static int acm_tty_open(struct tty_struct *tty, struct file *filp) |
| 551 | { | 551 | { |
| 552 | struct acm *acm; | 552 | struct acm *acm; |
| 553 | int rv = -EINVAL; | 553 | int rv = -ENODEV; |
| 554 | int i; | 554 | int i; |
| 555 | dbg("Entering acm_tty_open."); | 555 | dbg("Entering acm_tty_open."); |
| 556 | 556 | ||
| @@ -677,7 +677,7 @@ static void acm_tty_close(struct tty_struct *tty, struct file *filp) | |||
| 677 | 677 | ||
| 678 | /* Perform the closing process and see if we need to do the hardware | 678 | /* Perform the closing process and see if we need to do the hardware |
| 679 | shutdown */ | 679 | shutdown */ |
| 680 | if (tty_port_close_start(&acm->port, tty, filp) == 0) | 680 | if (!acm || tty_port_close_start(&acm->port, tty, filp) == 0) |
| 681 | return; | 681 | return; |
| 682 | acm_port_down(acm, 0); | 682 | acm_port_down(acm, 0); |
| 683 | tty_port_close_end(&acm->port, tty); | 683 | tty_port_close_end(&acm->port, tty); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index d595aa5586a7..a84216464ca0 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -333,6 +333,9 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
| 333 | { | 333 | { |
| 334 | struct usb_serial_port *port = tty->driver_data; | 334 | struct usb_serial_port *port = tty->driver_data; |
| 335 | 335 | ||
| 336 | if (!port) | ||
| 337 | return; | ||
| 338 | |||
| 336 | dbg("%s - port %d", __func__, port->number); | 339 | dbg("%s - port %d", __func__, port->number); |
| 337 | 340 | ||
| 338 | 341 | ||
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index a4fe7a38d9b0..3bde56bce63a 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c | |||
| @@ -218,16 +218,14 @@ static void wdrtas_timer_keepalive(void) | |||
| 218 | */ | 218 | */ |
| 219 | static int wdrtas_get_temperature(void) | 219 | static int wdrtas_get_temperature(void) |
| 220 | { | 220 | { |
| 221 | long result; | 221 | int result; |
| 222 | int temperature = 0; | 222 | int temperature = 0; |
| 223 | 223 | ||
| 224 | result = rtas_call(wdrtas_token_get_sensor_state, 2, 2, | 224 | result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature); |
| 225 | (void *)__pa(&temperature), | ||
| 226 | WDRTAS_THERMAL_SENSOR, 0); | ||
| 227 | 225 | ||
| 228 | if (result < 0) | 226 | if (result < 0) |
| 229 | printk(KERN_WARNING "wdrtas: reading the thermal sensor " | 227 | printk(KERN_WARNING "wdrtas: reading the thermal sensor " |
| 230 | "faild: %li\n", result); | 228 | "failed: %i\n", result); |
| 231 | else | 229 | else |
| 232 | temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ | 230 | temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */ |
| 233 | 231 | ||
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index b48689839428..3a9b7a58a51d 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES | |||
| @@ -5,7 +5,7 @@ client generated ones by default (mount option "serverino" turned | |||
| 5 | on by default if server supports it). Add forceuid and forcegid | 5 | on by default if server supports it). Add forceuid and forcegid |
| 6 | mount options (so that when negotiating unix extensions specifying | 6 | mount options (so that when negotiating unix extensions specifying |
| 7 | which uid mounted does not immediately force the server's reported | 7 | which uid mounted does not immediately force the server's reported |
| 8 | uids to be overridden). | 8 | uids to be overridden). Add support for scope moutn parm. |
| 9 | 9 | ||
| 10 | Version 1.58 | 10 | Version 1.58 |
| 11 | ------------ | 11 | ------------ |
diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index 1b09f1670061..20692fbfdb24 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #define ASN1_OJI 6 /* Object Identifier */ | 49 | #define ASN1_OJI 6 /* Object Identifier */ |
| 50 | #define ASN1_OJD 7 /* Object Description */ | 50 | #define ASN1_OJD 7 /* Object Description */ |
| 51 | #define ASN1_EXT 8 /* External */ | 51 | #define ASN1_EXT 8 /* External */ |
| 52 | #define ASN1_ENUM 10 /* Enumerated */ | ||
| 52 | #define ASN1_SEQ 16 /* Sequence */ | 53 | #define ASN1_SEQ 16 /* Sequence */ |
| 53 | #define ASN1_SET 17 /* Set */ | 54 | #define ASN1_SET 17 /* Set */ |
| 54 | #define ASN1_NUMSTR 18 /* Numerical String */ | 55 | #define ASN1_NUMSTR 18 /* Numerical String */ |
| @@ -78,10 +79,12 @@ | |||
| 78 | #define SPNEGO_OID_LEN 7 | 79 | #define SPNEGO_OID_LEN 7 |
| 79 | #define NTLMSSP_OID_LEN 10 | 80 | #define NTLMSSP_OID_LEN 10 |
| 80 | #define KRB5_OID_LEN 7 | 81 | #define KRB5_OID_LEN 7 |
| 82 | #define KRB5U2U_OID_LEN 8 | ||
| 81 | #define MSKRB5_OID_LEN 7 | 83 | #define MSKRB5_OID_LEN 7 |
| 82 | static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; | 84 | static unsigned long SPNEGO_OID[7] = { 1, 3, 6, 1, 5, 5, 2 }; |
| 83 | static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; | 85 | static unsigned long NTLMSSP_OID[10] = { 1, 3, 6, 1, 4, 1, 311, 2, 2, 10 }; |
| 84 | static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 }; | 86 | static unsigned long KRB5_OID[7] = { 1, 2, 840, 113554, 1, 2, 2 }; |
| 87 | static unsigned long KRB5U2U_OID[8] = { 1, 2, 840, 113554, 1, 2, 2, 3 }; | ||
| 85 | static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 }; | 88 | static unsigned long MSKRB5_OID[7] = { 1, 2, 840, 48018, 1, 2, 2 }; |
| 86 | 89 | ||
| 87 | /* | 90 | /* |
| @@ -122,6 +125,28 @@ asn1_octet_decode(struct asn1_ctx *ctx, unsigned char *ch) | |||
| 122 | return 1; | 125 | return 1; |
| 123 | } | 126 | } |
| 124 | 127 | ||
| 128 | #if 0 /* will be needed later by spnego decoding/encoding of ntlmssp */ | ||
| 129 | static unsigned char | ||
| 130 | asn1_enum_decode(struct asn1_ctx *ctx, __le32 *val) | ||
| 131 | { | ||
| 132 | unsigned char ch; | ||
| 133 | |||
| 134 | if (ctx->pointer >= ctx->end) { | ||
| 135 | ctx->error = ASN1_ERR_DEC_EMPTY; | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | ch = *(ctx->pointer)++; /* ch has 0xa, ptr points to lenght octet */ | ||
| 140 | if ((ch) == ASN1_ENUM) /* if ch value is ENUM, 0xa */ | ||
| 141 | *val = *(++(ctx->pointer)); /* value has enum value */ | ||
| 142 | else | ||
| 143 | return 0; | ||
| 144 | |||
| 145 | ctx->pointer++; | ||
| 146 | return 1; | ||
| 147 | } | ||
| 148 | #endif | ||
| 149 | |||
| 125 | static unsigned char | 150 | static unsigned char |
| 126 | asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) | 151 | asn1_tag_decode(struct asn1_ctx *ctx, unsigned int *tag) |
| 127 | { | 152 | { |
| @@ -476,10 +501,9 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 476 | unsigned int cls, con, tag, oidlen, rc; | 501 | unsigned int cls, con, tag, oidlen, rc; |
| 477 | bool use_ntlmssp = false; | 502 | bool use_ntlmssp = false; |
| 478 | bool use_kerberos = false; | 503 | bool use_kerberos = false; |
| 504 | bool use_kerberosu2u = false; | ||
| 479 | bool use_mskerberos = false; | 505 | bool use_mskerberos = false; |
| 480 | 506 | ||
| 481 | *secType = NTLM; /* BB eventually make Kerberos or NLTMSSP the default*/ | ||
| 482 | |||
| 483 | /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ | 507 | /* cifs_dump_mem(" Received SecBlob ", security_blob, length); */ |
| 484 | 508 | ||
| 485 | asn1_open(&ctx, security_blob, length); | 509 | asn1_open(&ctx, security_blob, length); |
| @@ -515,6 +539,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 515 | return 0; | 539 | return 0; |
| 516 | } | 540 | } |
| 517 | 541 | ||
| 542 | /* SPNEGO */ | ||
| 518 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 543 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
| 519 | cFYI(1, ("Error decoding negTokenInit")); | 544 | cFYI(1, ("Error decoding negTokenInit")); |
| 520 | return 0; | 545 | return 0; |
| @@ -526,6 +551,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 526 | return 0; | 551 | return 0; |
| 527 | } | 552 | } |
| 528 | 553 | ||
| 554 | /* negTokenInit */ | ||
| 529 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 555 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
| 530 | cFYI(1, ("Error decoding negTokenInit")); | 556 | cFYI(1, ("Error decoding negTokenInit")); |
| 531 | return 0; | 557 | return 0; |
| @@ -537,6 +563,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 537 | return 0; | 563 | return 0; |
| 538 | } | 564 | } |
| 539 | 565 | ||
| 566 | /* sequence */ | ||
| 540 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 567 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
| 541 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); | 568 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); |
| 542 | return 0; | 569 | return 0; |
| @@ -548,6 +575,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 548 | return 0; | 575 | return 0; |
| 549 | } | 576 | } |
| 550 | 577 | ||
| 578 | /* sequence of */ | ||
| 551 | if (asn1_header_decode | 579 | if (asn1_header_decode |
| 552 | (&ctx, &sequence_end, &cls, &con, &tag) == 0) { | 580 | (&ctx, &sequence_end, &cls, &con, &tag) == 0) { |
| 553 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); | 581 | cFYI(1, ("Error decoding 2nd part of negTokenInit")); |
| @@ -560,6 +588,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 560 | return 0; | 588 | return 0; |
| 561 | } | 589 | } |
| 562 | 590 | ||
| 591 | /* list of security mechanisms */ | ||
| 563 | while (!asn1_eoc_decode(&ctx, sequence_end)) { | 592 | while (!asn1_eoc_decode(&ctx, sequence_end)) { |
| 564 | rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); | 593 | rc = asn1_header_decode(&ctx, &end, &cls, &con, &tag); |
| 565 | if (!rc) { | 594 | if (!rc) { |
| @@ -576,11 +605,15 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 576 | 605 | ||
| 577 | if (compare_oid(oid, oidlen, MSKRB5_OID, | 606 | if (compare_oid(oid, oidlen, MSKRB5_OID, |
| 578 | MSKRB5_OID_LEN) && | 607 | MSKRB5_OID_LEN) && |
| 579 | !use_kerberos) | 608 | !use_mskerberos) |
| 580 | use_mskerberos = true; | 609 | use_mskerberos = true; |
| 610 | else if (compare_oid(oid, oidlen, KRB5U2U_OID, | ||
| 611 | KRB5U2U_OID_LEN) && | ||
| 612 | !use_kerberosu2u) | ||
| 613 | use_kerberosu2u = true; | ||
| 581 | else if (compare_oid(oid, oidlen, KRB5_OID, | 614 | else if (compare_oid(oid, oidlen, KRB5_OID, |
| 582 | KRB5_OID_LEN) && | 615 | KRB5_OID_LEN) && |
| 583 | !use_mskerberos) | 616 | !use_kerberos) |
| 584 | use_kerberos = true; | 617 | use_kerberos = true; |
| 585 | else if (compare_oid(oid, oidlen, NTLMSSP_OID, | 618 | else if (compare_oid(oid, oidlen, NTLMSSP_OID, |
| 586 | NTLMSSP_OID_LEN)) | 619 | NTLMSSP_OID_LEN)) |
| @@ -593,7 +626,12 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 593 | } | 626 | } |
| 594 | } | 627 | } |
| 595 | 628 | ||
| 629 | /* mechlistMIC */ | ||
| 596 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 630 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
| 631 | /* Check if we have reached the end of the blob, but with | ||
| 632 | no mechListMic (e.g. NTLMSSP instead of KRB5) */ | ||
| 633 | if (ctx.error == ASN1_ERR_DEC_EMPTY) | ||
| 634 | goto decode_negtoken_exit; | ||
| 597 | cFYI(1, ("Error decoding last part negTokenInit exit3")); | 635 | cFYI(1, ("Error decoding last part negTokenInit exit3")); |
| 598 | return 0; | 636 | return 0; |
| 599 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { | 637 | } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { |
| @@ -602,6 +640,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 602 | cls, con, tag, end, *end)); | 640 | cls, con, tag, end, *end)); |
| 603 | return 0; | 641 | return 0; |
| 604 | } | 642 | } |
| 643 | |||
| 644 | /* sequence */ | ||
| 605 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 645 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
| 606 | cFYI(1, ("Error decoding last part negTokenInit exit5")); | 646 | cFYI(1, ("Error decoding last part negTokenInit exit5")); |
| 607 | return 0; | 647 | return 0; |
| @@ -611,6 +651,7 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 611 | cls, con, tag, end, *end)); | 651 | cls, con, tag, end, *end)); |
| 612 | } | 652 | } |
| 613 | 653 | ||
| 654 | /* sequence of */ | ||
| 614 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 655 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
| 615 | cFYI(1, ("Error decoding last part negTokenInit exit 7")); | 656 | cFYI(1, ("Error decoding last part negTokenInit exit 7")); |
| 616 | return 0; | 657 | return 0; |
| @@ -619,6 +660,8 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 619 | cls, con, tag, end, *end)); | 660 | cls, con, tag, end, *end)); |
| 620 | return 0; | 661 | return 0; |
| 621 | } | 662 | } |
| 663 | |||
| 664 | /* general string */ | ||
| 622 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { | 665 | if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { |
| 623 | cFYI(1, ("Error decoding last part negTokenInit exit9")); | 666 | cFYI(1, ("Error decoding last part negTokenInit exit9")); |
| 624 | return 0; | 667 | return 0; |
| @@ -630,13 +673,13 @@ decode_negTokenInit(unsigned char *security_blob, int length, | |||
| 630 | } | 673 | } |
| 631 | cFYI(1, ("Need to call asn1_octets_decode() function for %s", | 674 | cFYI(1, ("Need to call asn1_octets_decode() function for %s", |
| 632 | ctx.pointer)); /* is this UTF-8 or ASCII? */ | 675 | ctx.pointer)); /* is this UTF-8 or ASCII? */ |
| 633 | 676 | decode_negtoken_exit: | |
| 634 | if (use_kerberos) | 677 | if (use_kerberos) |
| 635 | *secType = Kerberos; | 678 | *secType = Kerberos; |
| 636 | else if (use_mskerberos) | 679 | else if (use_mskerberos) |
| 637 | *secType = MSKerberos; | 680 | *secType = MSKerberos; |
| 638 | else if (use_ntlmssp) | 681 | else if (use_ntlmssp) |
| 639 | *secType = NTLMSSP; | 682 | *secType = RawNTLMSSP; |
| 640 | 683 | ||
| 641 | return 1; | 684 | return 1; |
| 642 | } | 685 | } |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 0d92114195ab..9f669f982c4d 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -333,6 +333,27 @@ cifs_destroy_inode(struct inode *inode) | |||
| 333 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | 333 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | static void | ||
| 337 | cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | ||
| 338 | { | ||
| 339 | seq_printf(s, ",addr="); | ||
| 340 | |||
| 341 | switch (server->addr.sockAddr.sin_family) { | ||
| 342 | case AF_INET: | ||
| 343 | seq_printf(s, "%pI4", &server->addr.sockAddr.sin_addr.s_addr); | ||
| 344 | break; | ||
| 345 | case AF_INET6: | ||
| 346 | seq_printf(s, "%pI6", | ||
| 347 | &server->addr.sockAddr6.sin6_addr.s6_addr); | ||
| 348 | if (server->addr.sockAddr6.sin6_scope_id) | ||
| 349 | seq_printf(s, "%%%u", | ||
| 350 | server->addr.sockAddr6.sin6_scope_id); | ||
| 351 | break; | ||
| 352 | default: | ||
| 353 | seq_printf(s, "(unknown)"); | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 336 | /* | 357 | /* |
| 337 | * cifs_show_options() is for displaying mount options in /proc/mounts. | 358 | * cifs_show_options() is for displaying mount options in /proc/mounts. |
| 338 | * Not all settable options are displayed but most of the important | 359 | * Not all settable options are displayed but most of the important |
| @@ -343,83 +364,64 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
| 343 | { | 364 | { |
| 344 | struct cifs_sb_info *cifs_sb; | 365 | struct cifs_sb_info *cifs_sb; |
| 345 | struct cifsTconInfo *tcon; | 366 | struct cifsTconInfo *tcon; |
| 346 | struct TCP_Server_Info *server; | ||
| 347 | 367 | ||
| 348 | cifs_sb = CIFS_SB(m->mnt_sb); | 368 | cifs_sb = CIFS_SB(m->mnt_sb); |
| 369 | tcon = cifs_sb->tcon; | ||
| 349 | 370 | ||
| 350 | if (cifs_sb) { | 371 | seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); |
| 351 | tcon = cifs_sb->tcon; | 372 | if (tcon->ses->userName) |
| 352 | if (tcon) { | 373 | seq_printf(s, ",username=%s", tcon->ses->userName); |
| 353 | seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); | 374 | if (tcon->ses->domainName) |
| 354 | if (tcon->ses) { | 375 | seq_printf(s, ",domain=%s", tcon->ses->domainName); |
| 355 | if (tcon->ses->userName) | 376 | |
| 356 | seq_printf(s, ",username=%s", | 377 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); |
| 357 | tcon->ses->userName); | 378 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) |
| 358 | if (tcon->ses->domainName) | 379 | seq_printf(s, ",forceuid"); |
| 359 | seq_printf(s, ",domain=%s", | 380 | |
| 360 | tcon->ses->domainName); | 381 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); |
| 361 | server = tcon->ses->server; | 382 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) |
| 362 | if (server) { | 383 | seq_printf(s, ",forcegid"); |
| 363 | seq_printf(s, ",addr="); | 384 | |
| 364 | switch (server->addr.sockAddr6. | 385 | cifs_show_address(s, tcon->ses->server); |
| 365 | sin6_family) { | 386 | |
| 366 | case AF_INET6: | 387 | if (!tcon->unix_ext) |
| 367 | seq_printf(s, "%pI6", | 388 | seq_printf(s, ",file_mode=0%o,dir_mode=0%o", |
| 368 | &server->addr.sockAddr6.sin6_addr); | ||
| 369 | break; | ||
| 370 | case AF_INET: | ||
| 371 | seq_printf(s, "%pI4", | ||
| 372 | &server->addr.sockAddr.sin_addr.s_addr); | ||
| 373 | break; | ||
| 374 | } | ||
| 375 | } | ||
| 376 | } | ||
| 377 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) || | ||
| 378 | !(tcon->unix_ext)) | ||
| 379 | seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); | ||
| 380 | if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) || | ||
| 381 | !(tcon->unix_ext)) | ||
| 382 | seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); | ||
| 383 | if (!tcon->unix_ext) { | ||
| 384 | seq_printf(s, ",file_mode=0%o,dir_mode=0%o", | ||
| 385 | cifs_sb->mnt_file_mode, | 389 | cifs_sb->mnt_file_mode, |
| 386 | cifs_sb->mnt_dir_mode); | 390 | cifs_sb->mnt_dir_mode); |
| 387 | } | 391 | if (tcon->seal) |
| 388 | if (tcon->seal) | 392 | seq_printf(s, ",seal"); |
| 389 | seq_printf(s, ",seal"); | 393 | if (tcon->nocase) |
| 390 | if (tcon->nocase) | 394 | seq_printf(s, ",nocase"); |
| 391 | seq_printf(s, ",nocase"); | 395 | if (tcon->retry) |
| 392 | if (tcon->retry) | 396 | seq_printf(s, ",hard"); |
| 393 | seq_printf(s, ",hard"); | 397 | if (cifs_sb->prepath) |
| 394 | } | 398 | seq_printf(s, ",prepath=%s", cifs_sb->prepath); |
| 395 | if (cifs_sb->prepath) | 399 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) |
| 396 | seq_printf(s, ",prepath=%s", cifs_sb->prepath); | 400 | seq_printf(s, ",posixpaths"); |
| 397 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) | 401 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) |
| 398 | seq_printf(s, ",posixpaths"); | 402 | seq_printf(s, ",setuids"); |
| 399 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) | 403 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) |
| 400 | seq_printf(s, ",setuids"); | 404 | seq_printf(s, ",serverino"); |
| 401 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) | 405 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) |
| 402 | seq_printf(s, ",serverino"); | 406 | seq_printf(s, ",directio"); |
| 403 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DIRECT_IO) | 407 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) |
| 404 | seq_printf(s, ",directio"); | 408 | seq_printf(s, ",nouser_xattr"); |
| 405 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) | 409 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) |
| 406 | seq_printf(s, ",nouser_xattr"); | 410 | seq_printf(s, ",mapchars"); |
| 407 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR) | 411 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) |
| 408 | seq_printf(s, ",mapchars"); | 412 | seq_printf(s, ",sfu"); |
| 409 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) | 413 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
| 410 | seq_printf(s, ",sfu"); | 414 | seq_printf(s, ",nobrl"); |
| 411 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 415 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) |
| 412 | seq_printf(s, ",nobrl"); | 416 | seq_printf(s, ",cifsacl"); |
| 413 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 417 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) |
| 414 | seq_printf(s, ",cifsacl"); | 418 | seq_printf(s, ",dynperm"); |
| 415 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM) | 419 | if (m->mnt_sb->s_flags & MS_POSIXACL) |
| 416 | seq_printf(s, ",dynperm"); | 420 | seq_printf(s, ",acl"); |
| 417 | if (m->mnt_sb->s_flags & MS_POSIXACL) | 421 | |
| 418 | seq_printf(s, ",acl"); | 422 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); |
| 419 | 423 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | |
| 420 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 424 | |
| 421 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | ||
| 422 | } | ||
| 423 | return 0; | 425 | return 0; |
| 424 | } | 426 | } |
| 425 | 427 | ||
| @@ -535,9 +537,14 @@ static void cifs_umount_begin(struct super_block *sb) | |||
| 535 | if (tcon == NULL) | 537 | if (tcon == NULL) |
| 536 | return; | 538 | return; |
| 537 | 539 | ||
| 538 | lock_kernel(); | ||
| 539 | read_lock(&cifs_tcp_ses_lock); | 540 | read_lock(&cifs_tcp_ses_lock); |
| 540 | if (tcon->tc_count == 1) | 541 | if ((tcon->tc_count > 1) || (tcon->tidStatus == CifsExiting)) { |
| 542 | /* we have other mounts to same share or we have | ||
| 543 | already tried to force umount this and woken up | ||
| 544 | all waiting network requests, nothing to do */ | ||
| 545 | read_unlock(&cifs_tcp_ses_lock); | ||
| 546 | return; | ||
| 547 | } else if (tcon->tc_count == 1) | ||
| 541 | tcon->tidStatus = CifsExiting; | 548 | tcon->tidStatus = CifsExiting; |
| 542 | read_unlock(&cifs_tcp_ses_lock); | 549 | read_unlock(&cifs_tcp_ses_lock); |
| 543 | 550 | ||
| @@ -552,9 +559,7 @@ static void cifs_umount_begin(struct super_block *sb) | |||
| 552 | wake_up_all(&tcon->ses->server->response_q); | 559 | wake_up_all(&tcon->ses->server->response_q); |
| 553 | msleep(1); | 560 | msleep(1); |
| 554 | } | 561 | } |
| 555 | /* BB FIXME - finish add checks for tidStatus BB */ | ||
| 556 | 562 | ||
| 557 | unlock_kernel(); | ||
| 558 | return; | 563 | return; |
| 559 | } | 564 | } |
| 560 | 565 | ||
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index a61ab772c6f6..e1225e6ded2f 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h | |||
| @@ -83,7 +83,7 @@ enum securityEnum { | |||
| 83 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ | 83 | NTLM, /* Legacy NTLM012 auth with NTLM hash */ |
| 84 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ | 84 | NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */ |
| 85 | RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ | 85 | RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */ |
| 86 | NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */ | 86 | /* NTLMSSP, */ /* can use rawNTLMSSP instead of NTLMSSP via SPNEGO */ |
| 87 | Kerberos, /* Kerberos via SPNEGO */ | 87 | Kerberos, /* Kerberos via SPNEGO */ |
| 88 | MSKerberos, /* MS Kerberos via SPNEGO */ | 88 | MSKerberos, /* MS Kerberos via SPNEGO */ |
| 89 | }; | 89 | }; |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index f9452329bcce..c419416a42ee 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -74,7 +74,7 @@ extern unsigned int smbCalcSize(struct smb_hdr *ptr); | |||
| 74 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); | 74 | extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr); |
| 75 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 75 | extern int decode_negTokenInit(unsigned char *security_blob, int length, |
| 76 | enum securityEnum *secType); | 76 | enum securityEnum *secType); |
| 77 | extern int cifs_inet_pton(const int, const char *source, void *dst); | 77 | extern int cifs_convert_address(char *src, void *dst); |
| 78 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); | 78 | extern int map_smb_to_linux_error(struct smb_hdr *smb, int logErr); |
| 79 | extern void header_assemble(struct smb_hdr *, char /* command */ , | 79 | extern void header_assemble(struct smb_hdr *, char /* command */ , |
| 80 | const struct cifsTconInfo *, int /* length of | 80 | const struct cifsTconInfo *, int /* length of |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index b84c61d5bca4..61007c627497 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
| @@ -594,7 +594,7 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) | |||
| 594 | else if (secFlags & CIFSSEC_MAY_KRB5) | 594 | else if (secFlags & CIFSSEC_MAY_KRB5) |
| 595 | server->secType = Kerberos; | 595 | server->secType = Kerberos; |
| 596 | else if (secFlags & CIFSSEC_MAY_NTLMSSP) | 596 | else if (secFlags & CIFSSEC_MAY_NTLMSSP) |
| 597 | server->secType = NTLMSSP; | 597 | server->secType = RawNTLMSSP; |
| 598 | else if (secFlags & CIFSSEC_MAY_LANMAN) | 598 | else if (secFlags & CIFSSEC_MAY_LANMAN) |
| 599 | server->secType = LANMAN; | 599 | server->secType = LANMAN; |
| 600 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL | 600 | /* #ifdef CONFIG_CIFS_EXPERIMENTAL |
| @@ -729,7 +729,7 @@ CIFSSMBTDis(const int xid, struct cifsTconInfo *tcon) | |||
| 729 | * the tcon is no longer on the list, so no need to take lock before | 729 | * the tcon is no longer on the list, so no need to take lock before |
| 730 | * checking this. | 730 | * checking this. |
| 731 | */ | 731 | */ |
| 732 | if (tcon->need_reconnect) | 732 | if ((tcon->need_reconnect) || (tcon->ses->need_reconnect)) |
| 733 | return 0; | 733 | return 0; |
| 734 | 734 | ||
| 735 | rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, | 735 | rc = small_smb_init(SMB_COM_TREE_DISCONNECT, 0, tcon, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 97f4311b9a8e..e16d7592116a 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -70,7 +70,6 @@ struct smb_vol { | |||
| 70 | mode_t file_mode; | 70 | mode_t file_mode; |
| 71 | mode_t dir_mode; | 71 | mode_t dir_mode; |
| 72 | unsigned secFlg; | 72 | unsigned secFlg; |
| 73 | bool rw:1; | ||
| 74 | bool retry:1; | 73 | bool retry:1; |
| 75 | bool intr:1; | 74 | bool intr:1; |
| 76 | bool setuids:1; | 75 | bool setuids:1; |
| @@ -832,7 +831,6 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 832 | vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; | 831 | vol->dir_mode = vol->file_mode = S_IRUGO | S_IXUGO | S_IWUSR; |
| 833 | 832 | ||
| 834 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ | 833 | /* vol->retry default is 0 (i.e. "soft" limited retry not hard retry) */ |
| 835 | vol->rw = true; | ||
| 836 | /* default is always to request posix paths. */ | 834 | /* default is always to request posix paths. */ |
| 837 | vol->posix_paths = 1; | 835 | vol->posix_paths = 1; |
| 838 | /* default to using server inode numbers where available */ | 836 | /* default to using server inode numbers where available */ |
| @@ -1199,7 +1197,9 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1199 | } else if (strnicmp(data, "guest", 5) == 0) { | 1197 | } else if (strnicmp(data, "guest", 5) == 0) { |
| 1200 | /* ignore */ | 1198 | /* ignore */ |
| 1201 | } else if (strnicmp(data, "rw", 2) == 0) { | 1199 | } else if (strnicmp(data, "rw", 2) == 0) { |
| 1202 | vol->rw = true; | 1200 | /* ignore */ |
| 1201 | } else if (strnicmp(data, "ro", 2) == 0) { | ||
| 1202 | /* ignore */ | ||
| 1203 | } else if (strnicmp(data, "noblocksend", 11) == 0) { | 1203 | } else if (strnicmp(data, "noblocksend", 11) == 0) { |
| 1204 | vol->noblocksnd = 1; | 1204 | vol->noblocksnd = 1; |
| 1205 | } else if (strnicmp(data, "noautotune", 10) == 0) { | 1205 | } else if (strnicmp(data, "noautotune", 10) == 0) { |
| @@ -1218,8 +1218,6 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1218 | parse these options again and set anything and it | 1218 | parse these options again and set anything and it |
| 1219 | is ok to just ignore them */ | 1219 | is ok to just ignore them */ |
| 1220 | continue; | 1220 | continue; |
| 1221 | } else if (strnicmp(data, "ro", 2) == 0) { | ||
| 1222 | vol->rw = false; | ||
| 1223 | } else if (strnicmp(data, "hard", 4) == 0) { | 1221 | } else if (strnicmp(data, "hard", 4) == 0) { |
| 1224 | vol->retry = 1; | 1222 | vol->retry = 1; |
| 1225 | } else if (strnicmp(data, "soft", 4) == 0) { | 1223 | } else if (strnicmp(data, "soft", 4) == 0) { |
| @@ -1386,8 +1384,10 @@ cifs_find_tcp_session(struct sockaddr_storage *addr) | |||
| 1386 | server->addr.sockAddr.sin_addr.s_addr)) | 1384 | server->addr.sockAddr.sin_addr.s_addr)) |
| 1387 | continue; | 1385 | continue; |
| 1388 | else if (addr->ss_family == AF_INET6 && | 1386 | else if (addr->ss_family == AF_INET6 && |
| 1389 | !ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, | 1387 | (!ipv6_addr_equal(&server->addr.sockAddr6.sin6_addr, |
| 1390 | &addr6->sin6_addr)) | 1388 | &addr6->sin6_addr) || |
| 1389 | server->addr.sockAddr6.sin6_scope_id != | ||
| 1390 | addr6->sin6_scope_id)) | ||
| 1391 | continue; | 1391 | continue; |
| 1392 | 1392 | ||
| 1393 | ++server->srv_count; | 1393 | ++server->srv_count; |
| @@ -1433,28 +1433,15 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
| 1433 | 1433 | ||
| 1434 | memset(&addr, 0, sizeof(struct sockaddr_storage)); | 1434 | memset(&addr, 0, sizeof(struct sockaddr_storage)); |
| 1435 | 1435 | ||
| 1436 | if (volume_info->UNCip && volume_info->UNC) { | 1436 | cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, volume_info->UNCip)); |
| 1437 | rc = cifs_inet_pton(AF_INET, volume_info->UNCip, | ||
| 1438 | &sin_server->sin_addr.s_addr); | ||
| 1439 | |||
| 1440 | if (rc <= 0) { | ||
| 1441 | /* not ipv4 address, try ipv6 */ | ||
| 1442 | rc = cifs_inet_pton(AF_INET6, volume_info->UNCip, | ||
| 1443 | &sin_server6->sin6_addr.in6_u); | ||
| 1444 | if (rc > 0) | ||
| 1445 | addr.ss_family = AF_INET6; | ||
| 1446 | } else { | ||
| 1447 | addr.ss_family = AF_INET; | ||
| 1448 | } | ||
| 1449 | 1437 | ||
| 1450 | if (rc <= 0) { | 1438 | if (volume_info->UNCip && volume_info->UNC) { |
| 1439 | rc = cifs_convert_address(volume_info->UNCip, &addr); | ||
| 1440 | if (!rc) { | ||
| 1451 | /* we failed translating address */ | 1441 | /* we failed translating address */ |
| 1452 | rc = -EINVAL; | 1442 | rc = -EINVAL; |
| 1453 | goto out_err; | 1443 | goto out_err; |
| 1454 | } | 1444 | } |
| 1455 | |||
| 1456 | cFYI(1, ("UNC: %s ip: %s", volume_info->UNC, | ||
| 1457 | volume_info->UNCip)); | ||
| 1458 | } else if (volume_info->UNCip) { | 1445 | } else if (volume_info->UNCip) { |
| 1459 | /* BB using ip addr as tcp_ses name to connect to the | 1446 | /* BB using ip addr as tcp_ses name to connect to the |
| 1460 | DFS root below */ | 1447 | DFS root below */ |
| @@ -1513,14 +1500,14 @@ cifs_get_tcp_session(struct smb_vol *volume_info) | |||
| 1513 | cFYI(1, ("attempting ipv6 connect")); | 1500 | cFYI(1, ("attempting ipv6 connect")); |
| 1514 | /* BB should we allow ipv6 on port 139? */ | 1501 | /* BB should we allow ipv6 on port 139? */ |
| 1515 | /* other OS never observed in Wild doing 139 with v6 */ | 1502 | /* other OS never observed in Wild doing 139 with v6 */ |
| 1503 | sin_server6->sin6_port = htons(volume_info->port); | ||
| 1516 | memcpy(&tcp_ses->addr.sockAddr6, sin_server6, | 1504 | memcpy(&tcp_ses->addr.sockAddr6, sin_server6, |
| 1517 | sizeof(struct sockaddr_in6)); | 1505 | sizeof(struct sockaddr_in6)); |
| 1518 | sin_server6->sin6_port = htons(volume_info->port); | ||
| 1519 | rc = ipv6_connect(tcp_ses); | 1506 | rc = ipv6_connect(tcp_ses); |
| 1520 | } else { | 1507 | } else { |
| 1508 | sin_server->sin_port = htons(volume_info->port); | ||
| 1521 | memcpy(&tcp_ses->addr.sockAddr, sin_server, | 1509 | memcpy(&tcp_ses->addr.sockAddr, sin_server, |
| 1522 | sizeof(struct sockaddr_in)); | 1510 | sizeof(struct sockaddr_in)); |
| 1523 | sin_server->sin_port = htons(volume_info->port); | ||
| 1524 | rc = ipv4_connect(tcp_ses); | 1511 | rc = ipv4_connect(tcp_ses); |
| 1525 | } | 1512 | } |
| 1526 | if (rc < 0) { | 1513 | if (rc < 0) { |
diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 3758965d73d5..7dc6b74f9def 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c | |||
| @@ -307,8 +307,9 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, | |||
| 307 | 307 | ||
| 308 | full_path = build_path_from_dentry(direntry); | 308 | full_path = build_path_from_dentry(direntry); |
| 309 | if (full_path == NULL) { | 309 | if (full_path == NULL) { |
| 310 | rc = -ENOMEM; | ||
| 310 | FreeXid(xid); | 311 | FreeXid(xid); |
| 311 | return -ENOMEM; | 312 | return rc; |
| 312 | } | 313 | } |
| 313 | 314 | ||
| 314 | if (oplockEnabled) | 315 | if (oplockEnabled) |
| @@ -540,8 +541,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, | |||
| 540 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); | 541 | buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL); |
| 541 | if (buf == NULL) { | 542 | if (buf == NULL) { |
| 542 | kfree(full_path); | 543 | kfree(full_path); |
| 544 | rc = -ENOMEM; | ||
| 543 | FreeXid(xid); | 545 | FreeXid(xid); |
| 544 | return -ENOMEM; | 546 | return rc; |
| 545 | } | 547 | } |
| 546 | 548 | ||
| 547 | rc = CIFSSMBOpen(xid, pTcon, full_path, | 549 | rc = CIFSSMBOpen(xid, pTcon, full_path, |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index df4a306f697e..87948147d7ec 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
| @@ -35,26 +35,11 @@ | |||
| 35 | * 0 - name is not IP | 35 | * 0 - name is not IP |
| 36 | */ | 36 | */ |
| 37 | static int | 37 | static int |
| 38 | is_ip(const char *name) | 38 | is_ip(char *name) |
| 39 | { | 39 | { |
| 40 | int rc; | 40 | struct sockaddr_storage ss; |
| 41 | struct sockaddr_in sin_server; | 41 | |
| 42 | struct sockaddr_in6 sin_server6; | 42 | return cifs_convert_address(name, &ss); |
| 43 | |||
| 44 | rc = cifs_inet_pton(AF_INET, name, | ||
| 45 | &sin_server.sin_addr.s_addr); | ||
| 46 | |||
| 47 | if (rc <= 0) { | ||
| 48 | /* not ipv4 address, try ipv6 */ | ||
| 49 | rc = cifs_inet_pton(AF_INET6, name, | ||
| 50 | &sin_server6.sin6_addr.in6_u); | ||
| 51 | if (rc > 0) | ||
| 52 | return 1; | ||
| 53 | } else { | ||
| 54 | return 1; | ||
| 55 | } | ||
| 56 | /* we failed translating address */ | ||
| 57 | return 0; | ||
| 58 | } | 43 | } |
| 59 | 44 | ||
| 60 | static int | 45 | static int |
| @@ -72,7 +57,7 @@ dns_resolver_instantiate(struct key *key, const void *data, | |||
| 72 | ip[datalen] = '\0'; | 57 | ip[datalen] = '\0'; |
| 73 | 58 | ||
| 74 | /* make sure this looks like an address */ | 59 | /* make sure this looks like an address */ |
| 75 | if (!is_ip((const char *) ip)) { | 60 | if (!is_ip(ip)) { |
| 76 | kfree(ip); | 61 | kfree(ip); |
| 77 | return -EINVAL; | 62 | return -EINVAL; |
| 78 | } | 63 | } |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 06866841b97f..ebdbe62a829c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -300,14 +300,16 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 300 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); | 300 | pCifsInode = CIFS_I(file->f_path.dentry->d_inode); |
| 301 | pCifsFile = cifs_fill_filedata(file); | 301 | pCifsFile = cifs_fill_filedata(file); |
| 302 | if (pCifsFile) { | 302 | if (pCifsFile) { |
| 303 | rc = 0; | ||
| 303 | FreeXid(xid); | 304 | FreeXid(xid); |
| 304 | return 0; | 305 | return rc; |
| 305 | } | 306 | } |
| 306 | 307 | ||
| 307 | full_path = build_path_from_dentry(file->f_path.dentry); | 308 | full_path = build_path_from_dentry(file->f_path.dentry); |
| 308 | if (full_path == NULL) { | 309 | if (full_path == NULL) { |
| 310 | rc = -ENOMEM; | ||
| 309 | FreeXid(xid); | 311 | FreeXid(xid); |
| 310 | return -ENOMEM; | 312 | return rc; |
| 311 | } | 313 | } |
| 312 | 314 | ||
| 313 | cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", | 315 | cFYI(1, ("inode = 0x%p file flags are 0x%x for %s", |
| @@ -494,8 +496,9 @@ static int cifs_reopen_file(struct file *file, bool can_flush) | |||
| 494 | mutex_unlock(&pCifsFile->fh_mutex); | 496 | mutex_unlock(&pCifsFile->fh_mutex); |
| 495 | if (!pCifsFile->invalidHandle) { | 497 | if (!pCifsFile->invalidHandle) { |
| 496 | mutex_lock(&pCifsFile->fh_mutex); | 498 | mutex_lock(&pCifsFile->fh_mutex); |
| 499 | rc = 0; | ||
| 497 | FreeXid(xid); | 500 | FreeXid(xid); |
| 498 | return 0; | 501 | return rc; |
| 499 | } | 502 | } |
| 500 | 503 | ||
| 501 | if (file->f_path.dentry == NULL) { | 504 | if (file->f_path.dentry == NULL) { |
| @@ -845,8 +848,9 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 845 | tcon = cifs_sb->tcon; | 848 | tcon = cifs_sb->tcon; |
| 846 | 849 | ||
| 847 | if (file->private_data == NULL) { | 850 | if (file->private_data == NULL) { |
| 851 | rc = -EBADF; | ||
| 848 | FreeXid(xid); | 852 | FreeXid(xid); |
| 849 | return -EBADF; | 853 | return rc; |
| 850 | } | 854 | } |
| 851 | netfid = ((struct cifsFileInfo *)file->private_data)->netfid; | 855 | netfid = ((struct cifsFileInfo *)file->private_data)->netfid; |
| 852 | 856 | ||
| @@ -1805,8 +1809,9 @@ ssize_t cifs_user_read(struct file *file, char __user *read_data, | |||
| 1805 | pTcon = cifs_sb->tcon; | 1809 | pTcon = cifs_sb->tcon; |
| 1806 | 1810 | ||
| 1807 | if (file->private_data == NULL) { | 1811 | if (file->private_data == NULL) { |
| 1812 | rc = -EBADF; | ||
| 1808 | FreeXid(xid); | 1813 | FreeXid(xid); |
| 1809 | return -EBADF; | 1814 | return rc; |
| 1810 | } | 1815 | } |
| 1811 | open_file = (struct cifsFileInfo *)file->private_data; | 1816 | open_file = (struct cifsFileInfo *)file->private_data; |
| 1812 | 1817 | ||
| @@ -1885,8 +1890,9 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, | |||
| 1885 | pTcon = cifs_sb->tcon; | 1890 | pTcon = cifs_sb->tcon; |
| 1886 | 1891 | ||
| 1887 | if (file->private_data == NULL) { | 1892 | if (file->private_data == NULL) { |
| 1893 | rc = -EBADF; | ||
| 1888 | FreeXid(xid); | 1894 | FreeXid(xid); |
| 1889 | return -EBADF; | 1895 | return rc; |
| 1890 | } | 1896 | } |
| 1891 | open_file = (struct cifsFileInfo *)file->private_data; | 1897 | open_file = (struct cifsFileInfo *)file->private_data; |
| 1892 | 1898 | ||
| @@ -2019,8 +2025,9 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, | |||
| 2019 | 2025 | ||
| 2020 | xid = GetXid(); | 2026 | xid = GetXid(); |
| 2021 | if (file->private_data == NULL) { | 2027 | if (file->private_data == NULL) { |
| 2028 | rc = -EBADF; | ||
| 2022 | FreeXid(xid); | 2029 | FreeXid(xid); |
| 2023 | return -EBADF; | 2030 | return rc; |
| 2024 | } | 2031 | } |
| 2025 | open_file = (struct cifsFileInfo *)file->private_data; | 2032 | open_file = (struct cifsFileInfo *)file->private_data; |
| 2026 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 2033 | cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| @@ -2185,8 +2192,9 @@ static int cifs_readpage(struct file *file, struct page *page) | |||
| 2185 | xid = GetXid(); | 2192 | xid = GetXid(); |
| 2186 | 2193 | ||
| 2187 | if (file->private_data == NULL) { | 2194 | if (file->private_data == NULL) { |
| 2195 | rc = -EBADF; | ||
| 2188 | FreeXid(xid); | 2196 | FreeXid(xid); |
| 2189 | return -EBADF; | 2197 | return rc; |
| 2190 | } | 2198 | } |
| 2191 | 2199 | ||
| 2192 | cFYI(1, ("readpage %p at offset %d 0x%x\n", | 2200 | cFYI(1, ("readpage %p at offset %d 0x%x\n", |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index fad882b075ba..155c9e785d0c 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -988,8 +988,9 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 988 | * sb->s_vfs_rename_mutex here */ | 988 | * sb->s_vfs_rename_mutex here */ |
| 989 | full_path = build_path_from_dentry(dentry); | 989 | full_path = build_path_from_dentry(dentry); |
| 990 | if (full_path == NULL) { | 990 | if (full_path == NULL) { |
| 991 | rc = -ENOMEM; | ||
| 991 | FreeXid(xid); | 992 | FreeXid(xid); |
| 992 | return -ENOMEM; | 993 | return rc; |
| 993 | } | 994 | } |
| 994 | 995 | ||
| 995 | if ((tcon->ses->capabilities & CAP_UNIX) && | 996 | if ((tcon->ses->capabilities & CAP_UNIX) && |
| @@ -1118,8 +1119,9 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) | |||
| 1118 | 1119 | ||
| 1119 | full_path = build_path_from_dentry(direntry); | 1120 | full_path = build_path_from_dentry(direntry); |
| 1120 | if (full_path == NULL) { | 1121 | if (full_path == NULL) { |
| 1122 | rc = -ENOMEM; | ||
| 1121 | FreeXid(xid); | 1123 | FreeXid(xid); |
| 1122 | return -ENOMEM; | 1124 | return rc; |
| 1123 | } | 1125 | } |
| 1124 | 1126 | ||
| 1125 | if ((pTcon->ses->capabilities & CAP_UNIX) && | 1127 | if ((pTcon->ses->capabilities & CAP_UNIX) && |
| @@ -1303,8 +1305,9 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) | |||
| 1303 | 1305 | ||
| 1304 | full_path = build_path_from_dentry(direntry); | 1306 | full_path = build_path_from_dentry(direntry); |
| 1305 | if (full_path == NULL) { | 1307 | if (full_path == NULL) { |
| 1308 | rc = -ENOMEM; | ||
| 1306 | FreeXid(xid); | 1309 | FreeXid(xid); |
| 1307 | return -ENOMEM; | 1310 | return rc; |
| 1308 | } | 1311 | } |
| 1309 | 1312 | ||
| 1310 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, | 1313 | rc = CIFSSMBRmDir(xid, pTcon, full_path, cifs_sb->local_nls, |
| @@ -1508,8 +1511,9 @@ int cifs_revalidate(struct dentry *direntry) | |||
| 1508 | since that would deadlock */ | 1511 | since that would deadlock */ |
| 1509 | full_path = build_path_from_dentry(direntry); | 1512 | full_path = build_path_from_dentry(direntry); |
| 1510 | if (full_path == NULL) { | 1513 | if (full_path == NULL) { |
| 1514 | rc = -ENOMEM; | ||
| 1511 | FreeXid(xid); | 1515 | FreeXid(xid); |
| 1512 | return -ENOMEM; | 1516 | return rc; |
| 1513 | } | 1517 | } |
| 1514 | cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " | 1518 | cFYI(1, ("Revalidate: %s inode 0x%p count %d dentry: 0x%p d_time %ld " |
| 1515 | "jiffies %ld", full_path, direntry->d_inode, | 1519 | "jiffies %ld", full_path, direntry->d_inode, |
| @@ -1911,8 +1915,9 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
| 1911 | 1915 | ||
| 1912 | full_path = build_path_from_dentry(direntry); | 1916 | full_path = build_path_from_dentry(direntry); |
| 1913 | if (full_path == NULL) { | 1917 | if (full_path == NULL) { |
| 1918 | rc = -ENOMEM; | ||
| 1914 | FreeXid(xid); | 1919 | FreeXid(xid); |
| 1915 | return -ENOMEM; | 1920 | return rc; |
| 1916 | } | 1921 | } |
| 1917 | 1922 | ||
| 1918 | /* | 1923 | /* |
diff --git a/fs/cifs/link.c b/fs/cifs/link.c index cd83c53fcbb5..fc1e0487eaee 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c | |||
| @@ -172,8 +172,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) | |||
| 172 | full_path = build_path_from_dentry(direntry); | 172 | full_path = build_path_from_dentry(direntry); |
| 173 | 173 | ||
| 174 | if (full_path == NULL) { | 174 | if (full_path == NULL) { |
| 175 | rc = -ENOMEM; | ||
| 175 | FreeXid(xid); | 176 | FreeXid(xid); |
| 176 | return -ENOMEM; | 177 | return rc; |
| 177 | } | 178 | } |
| 178 | 179 | ||
| 179 | cFYI(1, ("Full path: %s", full_path)); | 180 | cFYI(1, ("Full path: %s", full_path)); |
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 32d6baa0a54f..bd6d6895730d 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -133,10 +133,12 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { | |||
| 133 | {0, 0} | 133 | {0, 0} |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | /* Convert string containing dotted ip address to binary form */ | 136 | /* |
| 137 | /* returns 0 if invalid address */ | 137 | * Convert a string containing text IPv4 or IPv6 address to binary form. |
| 138 | 138 | * | |
| 139 | int | 139 | * Returns 0 on failure. |
| 140 | */ | ||
| 141 | static int | ||
| 140 | cifs_inet_pton(const int address_family, const char *cp, void *dst) | 142 | cifs_inet_pton(const int address_family, const char *cp, void *dst) |
| 141 | { | 143 | { |
| 142 | int ret = 0; | 144 | int ret = 0; |
| @@ -153,6 +155,52 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) | |||
| 153 | return ret; | 155 | return ret; |
| 154 | } | 156 | } |
| 155 | 157 | ||
| 158 | /* | ||
| 159 | * Try to convert a string to an IPv4 address and then attempt to convert | ||
| 160 | * it to an IPv6 address if that fails. Set the family field if either | ||
| 161 | * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to | ||
| 162 | * treat the part following it as a numeric sin6_scope_id. | ||
| 163 | * | ||
| 164 | * Returns 0 on failure. | ||
| 165 | */ | ||
| 166 | int | ||
| 167 | cifs_convert_address(char *src, void *dst) | ||
| 168 | { | ||
| 169 | int rc; | ||
| 170 | char *pct, *endp; | ||
| 171 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; | ||
| 172 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; | ||
| 173 | |||
| 174 | /* IPv4 address */ | ||
| 175 | if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { | ||
| 176 | s4->sin_family = AF_INET; | ||
| 177 | return 1; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* temporarily terminate string */ | ||
| 181 | pct = strchr(src, '%'); | ||
| 182 | if (pct) | ||
| 183 | *pct = '\0'; | ||
| 184 | |||
| 185 | rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr); | ||
| 186 | |||
| 187 | /* repair temp termination (if any) and make pct point to scopeid */ | ||
| 188 | if (pct) | ||
| 189 | *pct++ = '%'; | ||
| 190 | |||
| 191 | if (!rc) | ||
| 192 | return rc; | ||
| 193 | |||
| 194 | s6->sin6_family = AF_INET6; | ||
| 195 | if (pct) { | ||
| 196 | s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); | ||
| 197 | if (!*pct || *endp) | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | return rc; | ||
| 202 | } | ||
| 203 | |||
| 156 | /***************************************************************************** | 204 | /***************************************************************************** |
| 157 | convert a NT status code to a dos class/code | 205 | convert a NT status code to a dos class/code |
| 158 | *****************************************************************************/ | 206 | *****************************************************************************/ |
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 897a052270f9..7085a6275c4c 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c | |||
| @@ -802,7 +802,7 @@ ssetup_ntlmssp_authenticate: | |||
| 802 | #endif /* CONFIG_CIFS_UPCALL */ | 802 | #endif /* CONFIG_CIFS_UPCALL */ |
| 803 | } else { | 803 | } else { |
| 804 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 804 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 805 | if ((experimEnabled > 1) && (type == RawNTLMSSP)) { | 805 | if (type == RawNTLMSSP) { |
| 806 | if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { | 806 | if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) { |
| 807 | cERROR(1, ("NTLMSSP requires Unicode support")); | 807 | cERROR(1, ("NTLMSSP requires Unicode support")); |
| 808 | rc = -ENOSYS; | 808 | rc = -ENOSYS; |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index e9527eedc639..a75afa3dd9e1 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
| @@ -64,8 +64,9 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) | |||
| 64 | 64 | ||
| 65 | full_path = build_path_from_dentry(direntry); | 65 | full_path = build_path_from_dentry(direntry); |
| 66 | if (full_path == NULL) { | 66 | if (full_path == NULL) { |
| 67 | rc = -ENOMEM; | ||
| 67 | FreeXid(xid); | 68 | FreeXid(xid); |
| 68 | return -ENOMEM; | 69 | return rc; |
| 69 | } | 70 | } |
| 70 | if (ea_name == NULL) { | 71 | if (ea_name == NULL) { |
| 71 | cFYI(1, ("Null xattr names not supported")); | 72 | cFYI(1, ("Null xattr names not supported")); |
| @@ -118,8 +119,9 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, | |||
| 118 | 119 | ||
| 119 | full_path = build_path_from_dentry(direntry); | 120 | full_path = build_path_from_dentry(direntry); |
| 120 | if (full_path == NULL) { | 121 | if (full_path == NULL) { |
| 122 | rc = -ENOMEM; | ||
| 121 | FreeXid(xid); | 123 | FreeXid(xid); |
| 122 | return -ENOMEM; | 124 | return rc; |
| 123 | } | 125 | } |
| 124 | /* return dos attributes as pseudo xattr */ | 126 | /* return dos attributes as pseudo xattr */ |
| 125 | /* return alt name if available as pseudo attr */ | 127 | /* return alt name if available as pseudo attr */ |
| @@ -225,8 +227,9 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
| 225 | 227 | ||
| 226 | full_path = build_path_from_dentry(direntry); | 228 | full_path = build_path_from_dentry(direntry); |
| 227 | if (full_path == NULL) { | 229 | if (full_path == NULL) { |
| 230 | rc = -ENOMEM; | ||
| 228 | FreeXid(xid); | 231 | FreeXid(xid); |
| 229 | return -ENOMEM; | 232 | return rc; |
| 230 | } | 233 | } |
| 231 | /* return dos attributes as pseudo xattr */ | 234 | /* return dos attributes as pseudo xattr */ |
| 232 | /* return alt name if available as pseudo attr */ | 235 | /* return alt name if available as pseudo attr */ |
| @@ -351,8 +354,9 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size) | |||
| 351 | 354 | ||
| 352 | full_path = build_path_from_dentry(direntry); | 355 | full_path = build_path_from_dentry(direntry); |
| 353 | if (full_path == NULL) { | 356 | if (full_path == NULL) { |
| 357 | rc = -ENOMEM; | ||
| 354 | FreeXid(xid); | 358 | FreeXid(xid); |
| 355 | return -ENOMEM; | 359 | return rc; |
| 356 | } | 360 | } |
| 357 | /* return dos attributes as pseudo xattr */ | 361 | /* return dos attributes as pseudo xattr */ |
| 358 | /* return alt name if available as pseudo attr */ | 362 | /* return alt name if available as pseudo attr */ |
diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index c263e4d71754..7d6c9a2dfcbb 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h | |||
| @@ -35,11 +35,11 @@ struct est_timings { | |||
| 35 | } __attribute__((packed)); | 35 | } __attribute__((packed)); |
| 36 | 36 | ||
| 37 | /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ | 37 | /* 00=16:10, 01=4:3, 10=5:4, 11=16:9 */ |
| 38 | #define EDID_TIMING_ASPECT_SHIFT 0 | 38 | #define EDID_TIMING_ASPECT_SHIFT 6 |
| 39 | #define EDID_TIMING_ASPECT_MASK (0x3 << EDID_TIMING_ASPECT_SHIFT) | 39 | #define EDID_TIMING_ASPECT_MASK (0x3 << EDID_TIMING_ASPECT_SHIFT) |
| 40 | 40 | ||
| 41 | /* need to add 60 */ | 41 | /* need to add 60 */ |
| 42 | #define EDID_TIMING_VFREQ_SHIFT 2 | 42 | #define EDID_TIMING_VFREQ_SHIFT 0 |
| 43 | #define EDID_TIMING_VFREQ_MASK (0x3f << EDID_TIMING_VFREQ_SHIFT) | 43 | #define EDID_TIMING_VFREQ_MASK (0x3f << EDID_TIMING_VFREQ_SHIFT) |
| 44 | 44 | ||
| 45 | struct std_timing { | 45 | struct std_timing { |
| @@ -47,11 +47,11 @@ struct std_timing { | |||
| 47 | u8 vfreq_aspect; | 47 | u8 vfreq_aspect; |
| 48 | } __attribute__((packed)); | 48 | } __attribute__((packed)); |
| 49 | 49 | ||
| 50 | #define DRM_EDID_PT_HSYNC_POSITIVE (1 << 6) | 50 | #define DRM_EDID_PT_HSYNC_POSITIVE (1 << 1) |
| 51 | #define DRM_EDID_PT_VSYNC_POSITIVE (1 << 5) | 51 | #define DRM_EDID_PT_VSYNC_POSITIVE (1 << 2) |
| 52 | #define DRM_EDID_PT_SEPARATE_SYNC (3 << 3) | 52 | #define DRM_EDID_PT_SEPARATE_SYNC (3 << 3) |
| 53 | #define DRM_EDID_PT_STEREO (1 << 2) | 53 | #define DRM_EDID_PT_STEREO (1 << 5) |
| 54 | #define DRM_EDID_PT_INTERLACED (1 << 1) | 54 | #define DRM_EDID_PT_INTERLACED (1 << 7) |
| 55 | 55 | ||
| 56 | /* If detailed data is pixel timing */ | 56 | /* If detailed data is pixel timing */ |
| 57 | struct detailed_pixel_timing { | 57 | struct detailed_pixel_timing { |
| @@ -93,7 +93,7 @@ struct detailed_data_monitor_range { | |||
| 93 | } __attribute__((packed)); | 93 | } __attribute__((packed)); |
| 94 | 94 | ||
| 95 | struct detailed_data_wpindex { | 95 | struct detailed_data_wpindex { |
| 96 | u8 white_xy_lo; /* Upper 2 bits each */ | 96 | u8 white_yx_lo; /* Lower 2 bits each */ |
| 97 | u8 white_x_hi; | 97 | u8 white_x_hi; |
| 98 | u8 white_y_hi; | 98 | u8 white_y_hi; |
| 99 | u8 gamma; /* need to divide by 100 then add 1 */ | 99 | u8 gamma; /* need to divide by 100 then add 1 */ |
| @@ -135,21 +135,21 @@ struct detailed_timing { | |||
| 135 | } data; | 135 | } data; |
| 136 | } __attribute__((packed)); | 136 | } __attribute__((packed)); |
| 137 | 137 | ||
| 138 | #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 7) | 138 | #define DRM_EDID_INPUT_SERRATION_VSYNC (1 << 0) |
| 139 | #define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 5) | 139 | #define DRM_EDID_INPUT_SYNC_ON_GREEN (1 << 1) |
| 140 | #define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 4) | 140 | #define DRM_EDID_INPUT_COMPOSITE_SYNC (1 << 2) |
| 141 | #define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3) | 141 | #define DRM_EDID_INPUT_SEPARATE_SYNCS (1 << 3) |
| 142 | #define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 2) | 142 | #define DRM_EDID_INPUT_BLANK_TO_BLACK (1 << 4) |
| 143 | #define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 1) | 143 | #define DRM_EDID_INPUT_VIDEO_LEVEL (3 << 5) |
| 144 | #define DRM_EDID_INPUT_DIGITAL (1 << 0) /* bits above must be zero if set */ | 144 | #define DRM_EDID_INPUT_DIGITAL (1 << 7) /* bits below must be zero if set */ |
| 145 | 145 | ||
| 146 | #define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 7) | 146 | #define DRM_EDID_FEATURE_DEFAULT_GTF (1 << 0) |
| 147 | #define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 6) | 147 | #define DRM_EDID_FEATURE_PREFERRED_TIMING (1 << 1) |
| 148 | #define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 5) | 148 | #define DRM_EDID_FEATURE_STANDARD_COLOR (1 << 2) |
| 149 | #define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ | 149 | #define DRM_EDID_FEATURE_DISPLAY_TYPE (3 << 3) /* 00=mono, 01=rgb, 10=non-rgb, 11=unknown */ |
| 150 | #define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 2) | 150 | #define DRM_EDID_FEATURE_PM_ACTIVE_OFF (1 << 5) |
| 151 | #define DRM_EDID_FEATURE_PM_SUSPEND (1 << 1) | 151 | #define DRM_EDID_FEATURE_PM_SUSPEND (1 << 6) |
| 152 | #define DRM_EDID_FEATURE_PM_STANDBY (1 << 0) | 152 | #define DRM_EDID_FEATURE_PM_STANDBY (1 << 7) |
| 153 | 153 | ||
| 154 | struct edid { | 154 | struct edid { |
| 155 | u8 header[8]; | 155 | u8 header[8]; |
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 7400900de94a..54648e625efd 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
| 22 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
| 23 | #include <linux/percpu.h> | 23 | #include <linux/percpu.h> |
| 24 | #include <linux/timer.h> | ||
| 24 | 25 | ||
| 25 | 26 | ||
| 26 | struct hrtimer_clock_base; | 27 | struct hrtimer_clock_base; |
| @@ -447,6 +448,8 @@ extern void timer_stats_update_stats(void *timer, pid_t pid, void *startf, | |||
| 447 | 448 | ||
| 448 | static inline void timer_stats_account_hrtimer(struct hrtimer *timer) | 449 | static inline void timer_stats_account_hrtimer(struct hrtimer *timer) |
| 449 | { | 450 | { |
| 451 | if (likely(!timer->start_pid)) | ||
| 452 | return; | ||
| 450 | timer_stats_update_stats(timer, timer->start_pid, timer->start_site, | 453 | timer_stats_update_stats(timer, timer->start_pid, timer->start_site, |
| 451 | timer->function, timer->start_comm, 0); | 454 | timer->function, timer->start_comm, 0); |
| 452 | } | 455 | } |
| @@ -456,6 +459,8 @@ extern void __timer_stats_hrtimer_set_start_info(struct hrtimer *timer, | |||
| 456 | 459 | ||
| 457 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) | 460 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) |
| 458 | { | 461 | { |
| 462 | if (likely(!timer_stats_active)) | ||
| 463 | return; | ||
| 459 | __timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0)); | 464 | __timer_stats_hrtimer_set_start_info(timer, __builtin_return_address(0)); |
| 460 | } | 465 | } |
| 461 | 466 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index 95c6e00a72e8..cf1f3888067c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
| @@ -1361,7 +1361,6 @@ int ide_in_drive_list(u16 *, const struct drive_list_entry *); | |||
| 1361 | #ifdef CONFIG_BLK_DEV_IDEDMA | 1361 | #ifdef CONFIG_BLK_DEV_IDEDMA |
| 1362 | int ide_dma_good_drive(ide_drive_t *); | 1362 | int ide_dma_good_drive(ide_drive_t *); |
| 1363 | int __ide_dma_bad_drive(ide_drive_t *); | 1363 | int __ide_dma_bad_drive(ide_drive_t *); |
| 1364 | int ide_id_dma_bug(ide_drive_t *); | ||
| 1365 | 1364 | ||
| 1366 | u8 ide_find_dma_mode(ide_drive_t *, u8); | 1365 | u8 ide_find_dma_mode(ide_drive_t *, u8); |
| 1367 | 1366 | ||
| @@ -1402,7 +1401,6 @@ void ide_dma_lost_irq(ide_drive_t *); | |||
| 1402 | ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int); | 1401 | ide_startstop_t ide_dma_timeout_retry(ide_drive_t *, int); |
| 1403 | 1402 | ||
| 1404 | #else | 1403 | #else |
| 1405 | static inline int ide_id_dma_bug(ide_drive_t *drive) { return 0; } | ||
| 1406 | static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; } | 1404 | static inline u8 ide_find_dma_mode(ide_drive_t *drive, u8 speed) { return 0; } |
| 1407 | static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } | 1405 | static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } |
| 1408 | static inline void ide_dma_off_quietly(ide_drive_t *drive) { ; } | 1406 | static inline void ide_dma_off_quietly(ide_drive_t *drive) { ; } |
diff --git a/include/linux/kernel.h b/include/linux/kernel.h index fac104e7186a..d6320a3e8def 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h | |||
| @@ -303,6 +303,7 @@ extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in | |||
| 303 | extern int panic_timeout; | 303 | extern int panic_timeout; |
| 304 | extern int panic_on_oops; | 304 | extern int panic_on_oops; |
| 305 | extern int panic_on_unrecovered_nmi; | 305 | extern int panic_on_unrecovered_nmi; |
| 306 | extern int panic_on_io_nmi; | ||
| 306 | extern const char *print_tainted(void); | 307 | extern const char *print_tainted(void); |
| 307 | extern void add_taint(unsigned flag); | 308 | extern void add_taint(unsigned flag); |
| 308 | extern int test_taint(unsigned flag); | 309 | extern int test_taint(unsigned flag); |
diff --git a/include/linux/leds-lp3944.h b/include/linux/leds-lp3944.h new file mode 100644 index 000000000000..afc9f9fd70f5 --- /dev/null +++ b/include/linux/leds-lp3944.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* | ||
| 2 | * leds-lp3944.h - platform data structure for lp3944 led controller | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Antonio Ospite <ospite@studenti.unina.it> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef __LINUX_LEDS_LP3944_H | ||
| 13 | #define __LINUX_LEDS_LP3944_H | ||
| 14 | |||
| 15 | #include <linux/leds.h> | ||
| 16 | #include <linux/workqueue.h> | ||
| 17 | |||
| 18 | #define LP3944_LED0 0 | ||
| 19 | #define LP3944_LED1 1 | ||
| 20 | #define LP3944_LED2 2 | ||
| 21 | #define LP3944_LED3 3 | ||
| 22 | #define LP3944_LED4 4 | ||
| 23 | #define LP3944_LED5 5 | ||
| 24 | #define LP3944_LED6 6 | ||
| 25 | #define LP3944_LED7 7 | ||
| 26 | #define LP3944_LEDS_MAX 8 | ||
| 27 | |||
| 28 | #define LP3944_LED_STATUS_MASK 0x03 | ||
| 29 | enum lp3944_status { | ||
| 30 | LP3944_LED_STATUS_OFF = 0x0, | ||
| 31 | LP3944_LED_STATUS_ON = 0x1, | ||
| 32 | LP3944_LED_STATUS_DIM0 = 0x2, | ||
| 33 | LP3944_LED_STATUS_DIM1 = 0x3 | ||
| 34 | }; | ||
| 35 | |||
| 36 | enum lp3944_type { | ||
| 37 | LP3944_LED_TYPE_NONE, | ||
| 38 | LP3944_LED_TYPE_LED, | ||
| 39 | LP3944_LED_TYPE_LED_INVERTED, | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct lp3944_led { | ||
| 43 | char *name; | ||
| 44 | enum lp3944_type type; | ||
| 45 | enum lp3944_status status; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct lp3944_platform_data { | ||
| 49 | struct lp3944_led leds[LP3944_LEDS_MAX]; | ||
| 50 | u8 leds_size; | ||
| 51 | }; | ||
| 52 | |||
| 53 | #endif /* __LINUX_LEDS_LP3944_H */ | ||
diff --git a/include/linux/leds.h b/include/linux/leds.h index 376fe07732ea..d8bf9665e70c 100644 --- a/include/linux/leds.h +++ b/include/linux/leds.h | |||
| @@ -45,7 +45,10 @@ struct led_classdev { | |||
| 45 | /* Get LED brightness level */ | 45 | /* Get LED brightness level */ |
| 46 | enum led_brightness (*brightness_get)(struct led_classdev *led_cdev); | 46 | enum led_brightness (*brightness_get)(struct led_classdev *led_cdev); |
| 47 | 47 | ||
| 48 | /* Activate hardware accelerated blink */ | 48 | /* Activate hardware accelerated blink, delays are in |
| 49 | * miliseconds and if none is provided then a sensible default | ||
| 50 | * should be chosen. The call can adjust the timings if it can't | ||
| 51 | * match the values specified exactly. */ | ||
| 49 | int (*blink_set)(struct led_classdev *led_cdev, | 52 | int (*blink_set)(struct led_classdev *led_cdev, |
| 50 | unsigned long *delay_on, | 53 | unsigned long *delay_on, |
| 51 | unsigned long *delay_off); | 54 | unsigned long *delay_off); |
| @@ -141,9 +144,14 @@ struct gpio_led { | |||
| 141 | const char *name; | 144 | const char *name; |
| 142 | const char *default_trigger; | 145 | const char *default_trigger; |
| 143 | unsigned gpio; | 146 | unsigned gpio; |
| 144 | u8 active_low : 1; | 147 | unsigned active_low : 1; |
| 145 | u8 retain_state_suspended : 1; | 148 | unsigned retain_state_suspended : 1; |
| 149 | unsigned default_state : 2; | ||
| 150 | /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */ | ||
| 146 | }; | 151 | }; |
| 152 | #define LEDS_GPIO_DEFSTATE_OFF 0 | ||
| 153 | #define LEDS_GPIO_DEFSTATE_ON 1 | ||
| 154 | #define LEDS_GPIO_DEFSTATE_KEEP 2 | ||
| 147 | 155 | ||
| 148 | struct gpio_led_platform_data { | 156 | struct gpio_led_platform_data { |
| 149 | int num_leds; | 157 | int num_leds; |
diff --git a/include/linux/mm.h b/include/linux/mm.h index d006e93d5c93..ba3a7cb1eaa0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -826,7 +826,7 @@ extern int make_pages_present(unsigned long addr, unsigned long end); | |||
| 826 | extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); | 826 | extern int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); |
| 827 | 827 | ||
| 828 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 828 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
| 829 | unsigned long start, int len, int write, int force, | 829 | unsigned long start, int nr_pages, int write, int force, |
| 830 | struct page **pages, struct vm_area_struct **vmas); | 830 | struct page **pages, struct vm_area_struct **vmas); |
| 831 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, | 831 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, |
| 832 | struct page **pages); | 832 | struct page **pages); |
diff --git a/include/linux/timer.h b/include/linux/timer.h index ccf882eed8f8..be62ec2ebea5 100644 --- a/include/linux/timer.h +++ b/include/linux/timer.h | |||
| @@ -190,6 +190,8 @@ extern unsigned long get_next_timer_interrupt(unsigned long now); | |||
| 190 | */ | 190 | */ |
| 191 | #ifdef CONFIG_TIMER_STATS | 191 | #ifdef CONFIG_TIMER_STATS |
| 192 | 192 | ||
| 193 | extern int timer_stats_active; | ||
| 194 | |||
| 193 | #define TIMER_STATS_FLAG_DEFERRABLE 0x1 | 195 | #define TIMER_STATS_FLAG_DEFERRABLE 0x1 |
| 194 | 196 | ||
| 195 | extern void init_timer_stats(void); | 197 | extern void init_timer_stats(void); |
| @@ -203,6 +205,8 @@ extern void __timer_stats_timer_set_start_info(struct timer_list *timer, | |||
| 203 | 205 | ||
| 204 | static inline void timer_stats_timer_set_start_info(struct timer_list *timer) | 206 | static inline void timer_stats_timer_set_start_info(struct timer_list *timer) |
| 205 | { | 207 | { |
| 208 | if (likely(!timer_stats_active)) | ||
| 209 | return; | ||
| 206 | __timer_stats_timer_set_start_info(timer, __builtin_return_address(0)); | 210 | __timer_stats_timer_set_start_info(timer, __builtin_return_address(0)); |
| 207 | } | 211 | } |
| 208 | 212 | ||
diff --git a/kernel/Makefile b/kernel/Makefile index 780c8dcf4516..2093a691f1c2 100644 --- a/kernel/Makefile +++ b/kernel/Makefile | |||
| @@ -96,6 +96,7 @@ obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o | |||
| 96 | obj-$(CONFIG_FUNCTION_TRACER) += trace/ | 96 | obj-$(CONFIG_FUNCTION_TRACER) += trace/ |
| 97 | obj-$(CONFIG_TRACING) += trace/ | 97 | obj-$(CONFIG_TRACING) += trace/ |
| 98 | obj-$(CONFIG_X86_DS) += trace/ | 98 | obj-$(CONFIG_X86_DS) += trace/ |
| 99 | obj-$(CONFIG_RING_BUFFER) += trace/ | ||
| 99 | obj-$(CONFIG_SMP) += sched_cpupri.o | 100 | obj-$(CONFIG_SMP) += sched_cpupri.o |
| 100 | obj-$(CONFIG_SLOW_WORK) += slow-work.o | 101 | obj-$(CONFIG_SLOW_WORK) += slow-work.o |
| 101 | obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o | 102 | obj-$(CONFIG_PERF_COUNTERS) += perf_counter.o |
diff --git a/kernel/futex.c b/kernel/futex.c index 1c337112335c..794c862125fe 100644 --- a/kernel/futex.c +++ b/kernel/futex.c | |||
| @@ -299,7 +299,7 @@ void put_futex_key(int fshared, union futex_key *key) | |||
| 299 | static int fault_in_user_writeable(u32 __user *uaddr) | 299 | static int fault_in_user_writeable(u32 __user *uaddr) |
| 300 | { | 300 | { |
| 301 | int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, | 301 | int ret = get_user_pages(current, current->mm, (unsigned long)uaddr, |
| 302 | sizeof(*uaddr), 1, 0, NULL, NULL); | 302 | 1, 1, 0, NULL, NULL); |
| 303 | return ret < 0 ? ret : 0; | 303 | return ret < 0 ? ret : 0; |
| 304 | } | 304 | } |
| 305 | 305 | ||
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 62e4ff9968b5..98e02328c67d 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -335,7 +335,10 @@ static struct ctl_table kern_table[] = { | |||
| 335 | .data = &sysctl_timer_migration, | 335 | .data = &sysctl_timer_migration, |
| 336 | .maxlen = sizeof(unsigned int), | 336 | .maxlen = sizeof(unsigned int), |
| 337 | .mode = 0644, | 337 | .mode = 0644, |
| 338 | .proc_handler = &proc_dointvec, | 338 | .proc_handler = &proc_dointvec_minmax, |
| 339 | .strategy = &sysctl_intvec, | ||
| 340 | .extra1 = &zero, | ||
| 341 | .extra2 = &one, | ||
| 339 | }, | 342 | }, |
| 340 | #endif | 343 | #endif |
| 341 | { | 344 | { |
| @@ -744,6 +747,14 @@ static struct ctl_table kern_table[] = { | |||
| 744 | .proc_handler = &proc_dointvec, | 747 | .proc_handler = &proc_dointvec, |
| 745 | }, | 748 | }, |
| 746 | { | 749 | { |
| 750 | .ctl_name = CTL_UNNUMBERED, | ||
| 751 | .procname = "panic_on_io_nmi", | ||
| 752 | .data = &panic_on_io_nmi, | ||
| 753 | .maxlen = sizeof(int), | ||
| 754 | .mode = 0644, | ||
| 755 | .proc_handler = &proc_dointvec, | ||
| 756 | }, | ||
| 757 | { | ||
| 747 | .ctl_name = KERN_BOOTLOADER_TYPE, | 758 | .ctl_name = KERN_BOOTLOADER_TYPE, |
| 748 | .procname = "bootloader_type", | 759 | .procname = "bootloader_type", |
| 749 | .data = &bootloader_type, | 760 | .data = &bootloader_type, |
diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c index c994530d166d..4cde8b9c716f 100644 --- a/kernel/time/timer_stats.c +++ b/kernel/time/timer_stats.c | |||
| @@ -96,7 +96,7 @@ static DEFINE_MUTEX(show_mutex); | |||
| 96 | /* | 96 | /* |
| 97 | * Collection status, active/inactive: | 97 | * Collection status, active/inactive: |
| 98 | */ | 98 | */ |
| 99 | static int __read_mostly active; | 99 | int __read_mostly timer_stats_active; |
| 100 | 100 | ||
| 101 | /* | 101 | /* |
| 102 | * Beginning/end timestamps of measurement: | 102 | * Beginning/end timestamps of measurement: |
| @@ -242,7 +242,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf, | |||
| 242 | struct entry *entry, input; | 242 | struct entry *entry, input; |
| 243 | unsigned long flags; | 243 | unsigned long flags; |
| 244 | 244 | ||
| 245 | if (likely(!active)) | 245 | if (likely(!timer_stats_active)) |
| 246 | return; | 246 | return; |
| 247 | 247 | ||
| 248 | lock = &per_cpu(lookup_lock, raw_smp_processor_id()); | 248 | lock = &per_cpu(lookup_lock, raw_smp_processor_id()); |
| @@ -254,7 +254,7 @@ void timer_stats_update_stats(void *timer, pid_t pid, void *startf, | |||
| 254 | input.timer_flag = timer_flag; | 254 | input.timer_flag = timer_flag; |
| 255 | 255 | ||
| 256 | spin_lock_irqsave(lock, flags); | 256 | spin_lock_irqsave(lock, flags); |
| 257 | if (!active) | 257 | if (!timer_stats_active) |
| 258 | goto out_unlock; | 258 | goto out_unlock; |
| 259 | 259 | ||
| 260 | entry = tstat_lookup(&input, comm); | 260 | entry = tstat_lookup(&input, comm); |
| @@ -290,7 +290,7 @@ static int tstats_show(struct seq_file *m, void *v) | |||
| 290 | /* | 290 | /* |
| 291 | * If still active then calculate up to now: | 291 | * If still active then calculate up to now: |
| 292 | */ | 292 | */ |
| 293 | if (active) | 293 | if (timer_stats_active) |
| 294 | time_stop = ktime_get(); | 294 | time_stop = ktime_get(); |
| 295 | 295 | ||
| 296 | time = ktime_sub(time_stop, time_start); | 296 | time = ktime_sub(time_stop, time_start); |
| @@ -368,18 +368,18 @@ static ssize_t tstats_write(struct file *file, const char __user *buf, | |||
| 368 | mutex_lock(&show_mutex); | 368 | mutex_lock(&show_mutex); |
| 369 | switch (ctl[0]) { | 369 | switch (ctl[0]) { |
| 370 | case '0': | 370 | case '0': |
| 371 | if (active) { | 371 | if (timer_stats_active) { |
| 372 | active = 0; | 372 | timer_stats_active = 0; |
| 373 | time_stop = ktime_get(); | 373 | time_stop = ktime_get(); |
| 374 | sync_access(); | 374 | sync_access(); |
| 375 | } | 375 | } |
| 376 | break; | 376 | break; |
| 377 | case '1': | 377 | case '1': |
| 378 | if (!active) { | 378 | if (!timer_stats_active) { |
| 379 | reset_entries(); | 379 | reset_entries(); |
| 380 | time_start = ktime_get(); | 380 | time_start = ktime_get(); |
| 381 | smp_mb(); | 381 | smp_mb(); |
| 382 | active = 1; | 382 | timer_stats_active = 1; |
| 383 | } | 383 | } |
| 384 | break; | 384 | break; |
| 385 | default: | 385 | default: |
diff --git a/kernel/timer.c b/kernel/timer.c index 54d3912f8cad..0b36b9e5cc8b 100644 --- a/kernel/timer.c +++ b/kernel/timer.c | |||
| @@ -380,6 +380,8 @@ static void timer_stats_account_timer(struct timer_list *timer) | |||
| 380 | { | 380 | { |
| 381 | unsigned int flag = 0; | 381 | unsigned int flag = 0; |
| 382 | 382 | ||
| 383 | if (likely(!timer->start_site)) | ||
| 384 | return; | ||
| 383 | if (unlikely(tbase_get_deferrable(timer->base))) | 385 | if (unlikely(tbase_get_deferrable(timer->base))) |
| 384 | flag |= TIMER_STATS_FLAG_DEFERRABLE; | 386 | flag |= TIMER_STATS_FLAG_DEFERRABLE; |
| 385 | 387 | ||
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 3718d55fb4c3..f3716bf04df6 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
| @@ -291,7 +291,9 @@ function_stat_next(void *v, int idx) | |||
| 291 | pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK); | 291 | pg = (struct ftrace_profile_page *)((unsigned long)rec & PAGE_MASK); |
| 292 | 292 | ||
| 293 | again: | 293 | again: |
| 294 | rec++; | 294 | if (idx != 0) |
| 295 | rec++; | ||
| 296 | |||
| 295 | if ((void *)rec >= (void *)&pg->records[pg->index]) { | 297 | if ((void *)rec >= (void *)&pg->records[pg->index]) { |
| 296 | pg = pg->next; | 298 | pg = pg->next; |
| 297 | if (!pg) | 299 | if (!pg) |
| @@ -1417,10 +1419,20 @@ static void *t_hash_start(struct seq_file *m, loff_t *pos) | |||
| 1417 | { | 1419 | { |
| 1418 | struct ftrace_iterator *iter = m->private; | 1420 | struct ftrace_iterator *iter = m->private; |
| 1419 | void *p = NULL; | 1421 | void *p = NULL; |
| 1422 | loff_t l; | ||
| 1423 | |||
| 1424 | if (!(iter->flags & FTRACE_ITER_HASH)) | ||
| 1425 | *pos = 0; | ||
| 1420 | 1426 | ||
| 1421 | iter->flags |= FTRACE_ITER_HASH; | 1427 | iter->flags |= FTRACE_ITER_HASH; |
| 1422 | 1428 | ||
| 1423 | return t_hash_next(m, p, pos); | 1429 | iter->hidx = 0; |
| 1430 | for (l = 0; l <= *pos; ) { | ||
| 1431 | p = t_hash_next(m, p, &l); | ||
| 1432 | if (!p) | ||
| 1433 | break; | ||
| 1434 | } | ||
| 1435 | return p; | ||
| 1424 | } | 1436 | } |
| 1425 | 1437 | ||
| 1426 | static int t_hash_show(struct seq_file *m, void *v) | 1438 | static int t_hash_show(struct seq_file *m, void *v) |
| @@ -1467,8 +1479,6 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 1467 | iter->pg = iter->pg->next; | 1479 | iter->pg = iter->pg->next; |
| 1468 | iter->idx = 0; | 1480 | iter->idx = 0; |
| 1469 | goto retry; | 1481 | goto retry; |
| 1470 | } else { | ||
| 1471 | iter->idx = -1; | ||
| 1472 | } | 1482 | } |
| 1473 | } else { | 1483 | } else { |
| 1474 | rec = &iter->pg->records[iter->idx++]; | 1484 | rec = &iter->pg->records[iter->idx++]; |
| @@ -1497,6 +1507,7 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
| 1497 | { | 1507 | { |
| 1498 | struct ftrace_iterator *iter = m->private; | 1508 | struct ftrace_iterator *iter = m->private; |
| 1499 | void *p = NULL; | 1509 | void *p = NULL; |
| 1510 | loff_t l; | ||
| 1500 | 1511 | ||
| 1501 | mutex_lock(&ftrace_lock); | 1512 | mutex_lock(&ftrace_lock); |
| 1502 | /* | 1513 | /* |
| @@ -1508,23 +1519,21 @@ static void *t_start(struct seq_file *m, loff_t *pos) | |||
| 1508 | if (*pos > 0) | 1519 | if (*pos > 0) |
| 1509 | return t_hash_start(m, pos); | 1520 | return t_hash_start(m, pos); |
| 1510 | iter->flags |= FTRACE_ITER_PRINTALL; | 1521 | iter->flags |= FTRACE_ITER_PRINTALL; |
| 1511 | (*pos)++; | ||
| 1512 | return iter; | 1522 | return iter; |
| 1513 | } | 1523 | } |
| 1514 | 1524 | ||
| 1515 | if (iter->flags & FTRACE_ITER_HASH) | 1525 | if (iter->flags & FTRACE_ITER_HASH) |
| 1516 | return t_hash_start(m, pos); | 1526 | return t_hash_start(m, pos); |
| 1517 | 1527 | ||
| 1518 | if (*pos > 0) { | 1528 | iter->pg = ftrace_pages_start; |
| 1519 | if (iter->idx < 0) | 1529 | iter->idx = 0; |
| 1520 | return p; | 1530 | for (l = 0; l <= *pos; ) { |
| 1521 | (*pos)--; | 1531 | p = t_next(m, p, &l); |
| 1522 | iter->idx--; | 1532 | if (!p) |
| 1533 | break; | ||
| 1523 | } | 1534 | } |
| 1524 | 1535 | ||
| 1525 | p = t_next(m, p, pos); | 1536 | if (!p && iter->flags & FTRACE_ITER_FILTER) |
| 1526 | |||
| 1527 | if (!p) | ||
| 1528 | return t_hash_start(m, pos); | 1537 | return t_hash_start(m, pos); |
| 1529 | 1538 | ||
| 1530 | return p; | 1539 | return p; |
| @@ -2500,32 +2509,31 @@ int ftrace_graph_count; | |||
| 2500 | unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; | 2509 | unsigned long ftrace_graph_funcs[FTRACE_GRAPH_MAX_FUNCS] __read_mostly; |
| 2501 | 2510 | ||
| 2502 | static void * | 2511 | static void * |
| 2503 | g_next(struct seq_file *m, void *v, loff_t *pos) | 2512 | __g_next(struct seq_file *m, loff_t *pos) |
| 2504 | { | 2513 | { |
| 2505 | unsigned long *array = m->private; | 2514 | unsigned long *array = m->private; |
| 2506 | int index = *pos; | ||
| 2507 | 2515 | ||
| 2508 | (*pos)++; | 2516 | if (*pos >= ftrace_graph_count) |
| 2509 | |||
| 2510 | if (index >= ftrace_graph_count) | ||
| 2511 | return NULL; | 2517 | return NULL; |
| 2518 | return &array[*pos]; | ||
| 2519 | } | ||
| 2512 | 2520 | ||
| 2513 | return &array[index]; | 2521 | static void * |
| 2522 | g_next(struct seq_file *m, void *v, loff_t *pos) | ||
| 2523 | { | ||
| 2524 | (*pos)++; | ||
| 2525 | return __g_next(m, pos); | ||
| 2514 | } | 2526 | } |
| 2515 | 2527 | ||
| 2516 | static void *g_start(struct seq_file *m, loff_t *pos) | 2528 | static void *g_start(struct seq_file *m, loff_t *pos) |
| 2517 | { | 2529 | { |
| 2518 | void *p = NULL; | ||
| 2519 | |||
| 2520 | mutex_lock(&graph_lock); | 2530 | mutex_lock(&graph_lock); |
| 2521 | 2531 | ||
| 2522 | /* Nothing, tell g_show to print all functions are enabled */ | 2532 | /* Nothing, tell g_show to print all functions are enabled */ |
| 2523 | if (!ftrace_graph_count && !*pos) | 2533 | if (!ftrace_graph_count && !*pos) |
| 2524 | return (void *)1; | 2534 | return (void *)1; |
| 2525 | 2535 | ||
| 2526 | p = g_next(m, p, pos); | 2536 | return __g_next(m, pos); |
| 2527 | |||
| 2528 | return p; | ||
| 2529 | } | 2537 | } |
| 2530 | 2538 | ||
| 2531 | static void g_stop(struct seq_file *m, void *p) | 2539 | static void g_stop(struct seq_file *m, void *p) |
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 04dac2638258..bf27bb7a63e2 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c | |||
| @@ -1563,6 +1563,8 @@ rb_reserve_next_event(struct ring_buffer_per_cpu *cpu_buffer, | |||
| 1563 | return NULL; | 1563 | return NULL; |
| 1564 | } | 1564 | } |
| 1565 | 1565 | ||
| 1566 | #ifdef CONFIG_TRACING | ||
| 1567 | |||
| 1566 | #define TRACE_RECURSIVE_DEPTH 16 | 1568 | #define TRACE_RECURSIVE_DEPTH 16 |
| 1567 | 1569 | ||
| 1568 | static int trace_recursive_lock(void) | 1570 | static int trace_recursive_lock(void) |
| @@ -1593,6 +1595,13 @@ static void trace_recursive_unlock(void) | |||
| 1593 | current->trace_recursion--; | 1595 | current->trace_recursion--; |
| 1594 | } | 1596 | } |
| 1595 | 1597 | ||
| 1598 | #else | ||
| 1599 | |||
| 1600 | #define trace_recursive_lock() (0) | ||
| 1601 | #define trace_recursive_unlock() do { } while (0) | ||
| 1602 | |||
| 1603 | #endif | ||
| 1604 | |||
| 1596 | static DEFINE_PER_CPU(int, rb_need_resched); | 1605 | static DEFINE_PER_CPU(int, rb_need_resched); |
| 1597 | 1606 | ||
| 1598 | /** | 1607 | /** |
| @@ -3104,6 +3113,7 @@ int ring_buffer_read_page(struct ring_buffer *buffer, | |||
| 3104 | } | 3113 | } |
| 3105 | EXPORT_SYMBOL_GPL(ring_buffer_read_page); | 3114 | EXPORT_SYMBOL_GPL(ring_buffer_read_page); |
| 3106 | 3115 | ||
| 3116 | #ifdef CONFIG_TRACING | ||
| 3107 | static ssize_t | 3117 | static ssize_t |
| 3108 | rb_simple_read(struct file *filp, char __user *ubuf, | 3118 | rb_simple_read(struct file *filp, char __user *ubuf, |
| 3109 | size_t cnt, loff_t *ppos) | 3119 | size_t cnt, loff_t *ppos) |
| @@ -3171,6 +3181,7 @@ static __init int rb_init_debugfs(void) | |||
| 3171 | } | 3181 | } |
| 3172 | 3182 | ||
| 3173 | fs_initcall(rb_init_debugfs); | 3183 | fs_initcall(rb_init_debugfs); |
| 3184 | #endif | ||
| 3174 | 3185 | ||
| 3175 | #ifdef CONFIG_HOTPLUG_CPU | 3186 | #ifdef CONFIG_HOTPLUG_CPU |
| 3176 | static int rb_cpu_notify(struct notifier_block *self, | 3187 | static int rb_cpu_notify(struct notifier_block *self, |
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 076fa6f0ee48..3aa0a0dfdfa8 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -284,13 +284,12 @@ void trace_wake_up(void) | |||
| 284 | static int __init set_buf_size(char *str) | 284 | static int __init set_buf_size(char *str) |
| 285 | { | 285 | { |
| 286 | unsigned long buf_size; | 286 | unsigned long buf_size; |
| 287 | int ret; | ||
| 288 | 287 | ||
| 289 | if (!str) | 288 | if (!str) |
| 290 | return 0; | 289 | return 0; |
| 291 | ret = strict_strtoul(str, 0, &buf_size); | 290 | buf_size = memparse(str, &str); |
| 292 | /* nr_entries can not be zero */ | 291 | /* nr_entries can not be zero */ |
| 293 | if (ret < 0 || buf_size == 0) | 292 | if (buf_size == 0) |
| 294 | return 0; | 293 | return 0; |
| 295 | trace_buf_size = buf_size; | 294 | trace_buf_size = buf_size; |
| 296 | return 1; | 295 | return 1; |
| @@ -2053,25 +2052,23 @@ static int tracing_open(struct inode *inode, struct file *file) | |||
| 2053 | static void * | 2052 | static void * |
| 2054 | t_next(struct seq_file *m, void *v, loff_t *pos) | 2053 | t_next(struct seq_file *m, void *v, loff_t *pos) |
| 2055 | { | 2054 | { |
| 2056 | struct tracer *t = m->private; | 2055 | struct tracer *t = v; |
| 2057 | 2056 | ||
| 2058 | (*pos)++; | 2057 | (*pos)++; |
| 2059 | 2058 | ||
| 2060 | if (t) | 2059 | if (t) |
| 2061 | t = t->next; | 2060 | t = t->next; |
| 2062 | 2061 | ||
| 2063 | m->private = t; | ||
| 2064 | |||
| 2065 | return t; | 2062 | return t; |
| 2066 | } | 2063 | } |
| 2067 | 2064 | ||
| 2068 | static void *t_start(struct seq_file *m, loff_t *pos) | 2065 | static void *t_start(struct seq_file *m, loff_t *pos) |
| 2069 | { | 2066 | { |
| 2070 | struct tracer *t = m->private; | 2067 | struct tracer *t; |
| 2071 | loff_t l = 0; | 2068 | loff_t l = 0; |
| 2072 | 2069 | ||
| 2073 | mutex_lock(&trace_types_lock); | 2070 | mutex_lock(&trace_types_lock); |
| 2074 | for (; t && l < *pos; t = t_next(m, t, &l)) | 2071 | for (t = trace_types; t && l < *pos; t = t_next(m, t, &l)) |
| 2075 | ; | 2072 | ; |
| 2076 | 2073 | ||
| 2077 | return t; | 2074 | return t; |
| @@ -2107,18 +2104,10 @@ static struct seq_operations show_traces_seq_ops = { | |||
| 2107 | 2104 | ||
| 2108 | static int show_traces_open(struct inode *inode, struct file *file) | 2105 | static int show_traces_open(struct inode *inode, struct file *file) |
| 2109 | { | 2106 | { |
| 2110 | int ret; | ||
| 2111 | |||
| 2112 | if (tracing_disabled) | 2107 | if (tracing_disabled) |
| 2113 | return -ENODEV; | 2108 | return -ENODEV; |
| 2114 | 2109 | ||
| 2115 | ret = seq_open(file, &show_traces_seq_ops); | 2110 | return seq_open(file, &show_traces_seq_ops); |
| 2116 | if (!ret) { | ||
| 2117 | struct seq_file *m = file->private_data; | ||
| 2118 | m->private = trace_types; | ||
| 2119 | } | ||
| 2120 | |||
| 2121 | return ret; | ||
| 2122 | } | 2111 | } |
| 2123 | 2112 | ||
| 2124 | static ssize_t | 2113 | static ssize_t |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 6e735d4771f8..3548ae5cc780 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
| @@ -597,6 +597,7 @@ print_graph_function(struct trace_iterator *iter) | |||
| 597 | 597 | ||
| 598 | extern struct pid *ftrace_pid_trace; | 598 | extern struct pid *ftrace_pid_trace; |
| 599 | 599 | ||
| 600 | #ifdef CONFIG_FUNCTION_TRACER | ||
| 600 | static inline int ftrace_trace_task(struct task_struct *task) | 601 | static inline int ftrace_trace_task(struct task_struct *task) |
| 601 | { | 602 | { |
| 602 | if (!ftrace_pid_trace) | 603 | if (!ftrace_pid_trace) |
| @@ -604,6 +605,12 @@ static inline int ftrace_trace_task(struct task_struct *task) | |||
| 604 | 605 | ||
| 605 | return test_tsk_trace_trace(task); | 606 | return test_tsk_trace_trace(task); |
| 606 | } | 607 | } |
| 608 | #else | ||
| 609 | static inline int ftrace_trace_task(struct task_struct *task) | ||
| 610 | { | ||
| 611 | return 1; | ||
| 612 | } | ||
| 613 | #endif | ||
| 607 | 614 | ||
| 608 | /* | 615 | /* |
| 609 | * trace_iterator_flags is an enumeration that defines bit | 616 | * trace_iterator_flags is an enumeration that defines bit |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index aa08be69a1b6..53c8fd376a88 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -300,10 +300,18 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 300 | 300 | ||
| 301 | static void *t_start(struct seq_file *m, loff_t *pos) | 301 | static void *t_start(struct seq_file *m, loff_t *pos) |
| 302 | { | 302 | { |
| 303 | struct ftrace_event_call *call = NULL; | ||
| 304 | loff_t l; | ||
| 305 | |||
| 303 | mutex_lock(&event_mutex); | 306 | mutex_lock(&event_mutex); |
| 304 | if (*pos == 0) | 307 | |
| 305 | m->private = ftrace_events.next; | 308 | m->private = ftrace_events.next; |
| 306 | return t_next(m, NULL, pos); | 309 | for (l = 0; l <= *pos; ) { |
| 310 | call = t_next(m, NULL, &l); | ||
| 311 | if (!call) | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | return call; | ||
| 307 | } | 315 | } |
| 308 | 316 | ||
| 309 | static void * | 317 | static void * |
| @@ -332,10 +340,18 @@ s_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 332 | 340 | ||
| 333 | static void *s_start(struct seq_file *m, loff_t *pos) | 341 | static void *s_start(struct seq_file *m, loff_t *pos) |
| 334 | { | 342 | { |
| 343 | struct ftrace_event_call *call = NULL; | ||
| 344 | loff_t l; | ||
| 345 | |||
| 335 | mutex_lock(&event_mutex); | 346 | mutex_lock(&event_mutex); |
| 336 | if (*pos == 0) | 347 | |
| 337 | m->private = ftrace_events.next; | 348 | m->private = ftrace_events.next; |
| 338 | return s_next(m, NULL, pos); | 349 | for (l = 0; l <= *pos; ) { |
| 350 | call = s_next(m, NULL, &l); | ||
| 351 | if (!call) | ||
| 352 | break; | ||
| 353 | } | ||
| 354 | return call; | ||
| 339 | } | 355 | } |
| 340 | 356 | ||
| 341 | static int t_show(struct seq_file *m, void *v) | 357 | static int t_show(struct seq_file *m, void *v) |
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index 90f134764837..7402144bff21 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c | |||
| @@ -302,8 +302,7 @@ ftrace_trace_onoff_print(struct seq_file *m, unsigned long ip, | |||
| 302 | if (count == -1) | 302 | if (count == -1) |
| 303 | seq_printf(m, ":unlimited\n"); | 303 | seq_printf(m, ":unlimited\n"); |
| 304 | else | 304 | else |
| 305 | seq_printf(m, ":count=%ld", count); | 305 | seq_printf(m, ":count=%ld\n", count); |
| 306 | seq_putc(m, '\n'); | ||
| 307 | 306 | ||
| 308 | return 0; | 307 | return 0; |
| 309 | } | 308 | } |
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c index 9bece9687b62..7b6278110827 100644 --- a/kernel/trace/trace_printk.c +++ b/kernel/trace/trace_printk.c | |||
| @@ -155,25 +155,19 @@ int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap) | |||
| 155 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); | 155 | EXPORT_SYMBOL_GPL(__ftrace_vprintk); |
| 156 | 156 | ||
| 157 | static void * | 157 | static void * |
| 158 | t_next(struct seq_file *m, void *v, loff_t *pos) | 158 | t_start(struct seq_file *m, loff_t *pos) |
| 159 | { | 159 | { |
| 160 | const char **fmt = m->private; | 160 | const char **fmt = __start___trace_bprintk_fmt + *pos; |
| 161 | const char **next = fmt; | ||
| 162 | |||
| 163 | (*pos)++; | ||
| 164 | 161 | ||
| 165 | if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt) | 162 | if ((unsigned long)fmt >= (unsigned long)__stop___trace_bprintk_fmt) |
| 166 | return NULL; | 163 | return NULL; |
| 167 | |||
| 168 | next = fmt; | ||
| 169 | m->private = ++next; | ||
| 170 | |||
| 171 | return fmt; | 164 | return fmt; |
| 172 | } | 165 | } |
| 173 | 166 | ||
| 174 | static void *t_start(struct seq_file *m, loff_t *pos) | 167 | static void *t_next(struct seq_file *m, void * v, loff_t *pos) |
| 175 | { | 168 | { |
| 176 | return t_next(m, NULL, pos); | 169 | (*pos)++; |
| 170 | return t_start(m, pos); | ||
| 177 | } | 171 | } |
| 178 | 172 | ||
| 179 | static int t_show(struct seq_file *m, void *v) | 173 | static int t_show(struct seq_file *m, void *v) |
| @@ -224,15 +218,7 @@ static const struct seq_operations show_format_seq_ops = { | |||
| 224 | static int | 218 | static int |
| 225 | ftrace_formats_open(struct inode *inode, struct file *file) | 219 | ftrace_formats_open(struct inode *inode, struct file *file) |
| 226 | { | 220 | { |
| 227 | int ret; | 221 | return seq_open(file, &show_format_seq_ops); |
| 228 | |||
| 229 | ret = seq_open(file, &show_format_seq_ops); | ||
| 230 | if (!ret) { | ||
| 231 | struct seq_file *m = file->private_data; | ||
| 232 | |||
| 233 | m->private = __start___trace_bprintk_fmt; | ||
| 234 | } | ||
| 235 | return ret; | ||
| 236 | } | 222 | } |
| 237 | 223 | ||
| 238 | static const struct file_operations ftrace_formats_fops = { | 224 | static const struct file_operations ftrace_formats_fops = { |
diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c index c00643733f4c..e66f5e493342 100644 --- a/kernel/trace/trace_stat.c +++ b/kernel/trace/trace_stat.c | |||
| @@ -199,17 +199,13 @@ static void *stat_seq_start(struct seq_file *s, loff_t *pos) | |||
| 199 | mutex_lock(&session->stat_mutex); | 199 | mutex_lock(&session->stat_mutex); |
| 200 | 200 | ||
| 201 | /* If we are in the beginning of the file, print the headers */ | 201 | /* If we are in the beginning of the file, print the headers */ |
| 202 | if (!*pos && session->ts->stat_headers) { | 202 | if (!*pos && session->ts->stat_headers) |
| 203 | (*pos)++; | ||
| 204 | return SEQ_START_TOKEN; | 203 | return SEQ_START_TOKEN; |
| 205 | } | ||
| 206 | 204 | ||
| 207 | node = rb_first(&session->stat_root); | 205 | node = rb_first(&session->stat_root); |
| 208 | for (i = 0; node && i < *pos; i++) | 206 | for (i = 0; node && i < *pos; i++) |
| 209 | node = rb_next(node); | 207 | node = rb_next(node); |
| 210 | 208 | ||
| 211 | (*pos)++; | ||
| 212 | |||
| 213 | return node; | 209 | return node; |
| 214 | } | 210 | } |
| 215 | 211 | ||
diff --git a/mm/memory.c b/mm/memory.c index f46ac18ba231..65216194eb8d 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
| @@ -1207,8 +1207,8 @@ static inline int use_zero_page(struct vm_area_struct *vma) | |||
| 1207 | 1207 | ||
| 1208 | 1208 | ||
| 1209 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 1209 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
| 1210 | unsigned long start, int len, int flags, | 1210 | unsigned long start, int nr_pages, int flags, |
| 1211 | struct page **pages, struct vm_area_struct **vmas) | 1211 | struct page **pages, struct vm_area_struct **vmas) |
| 1212 | { | 1212 | { |
| 1213 | int i; | 1213 | int i; |
| 1214 | unsigned int vm_flags = 0; | 1214 | unsigned int vm_flags = 0; |
| @@ -1217,7 +1217,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1217 | int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS); | 1217 | int ignore = !!(flags & GUP_FLAGS_IGNORE_VMA_PERMISSIONS); |
| 1218 | int ignore_sigkill = !!(flags & GUP_FLAGS_IGNORE_SIGKILL); | 1218 | int ignore_sigkill = !!(flags & GUP_FLAGS_IGNORE_SIGKILL); |
| 1219 | 1219 | ||
| 1220 | if (len <= 0) | 1220 | if (nr_pages <= 0) |
| 1221 | return 0; | 1221 | return 0; |
| 1222 | /* | 1222 | /* |
| 1223 | * Require read or write permissions. | 1223 | * Require read or write permissions. |
| @@ -1269,7 +1269,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1269 | vmas[i] = gate_vma; | 1269 | vmas[i] = gate_vma; |
| 1270 | i++; | 1270 | i++; |
| 1271 | start += PAGE_SIZE; | 1271 | start += PAGE_SIZE; |
| 1272 | len--; | 1272 | nr_pages--; |
| 1273 | continue; | 1273 | continue; |
| 1274 | } | 1274 | } |
| 1275 | 1275 | ||
| @@ -1280,7 +1280,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1280 | 1280 | ||
| 1281 | if (is_vm_hugetlb_page(vma)) { | 1281 | if (is_vm_hugetlb_page(vma)) { |
| 1282 | i = follow_hugetlb_page(mm, vma, pages, vmas, | 1282 | i = follow_hugetlb_page(mm, vma, pages, vmas, |
| 1283 | &start, &len, i, write); | 1283 | &start, &nr_pages, i, write); |
| 1284 | continue; | 1284 | continue; |
| 1285 | } | 1285 | } |
| 1286 | 1286 | ||
| @@ -1357,9 +1357,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1357 | vmas[i] = vma; | 1357 | vmas[i] = vma; |
| 1358 | i++; | 1358 | i++; |
| 1359 | start += PAGE_SIZE; | 1359 | start += PAGE_SIZE; |
| 1360 | len--; | 1360 | nr_pages--; |
| 1361 | } while (len && start < vma->vm_end); | 1361 | } while (nr_pages && start < vma->vm_end); |
| 1362 | } while (len); | 1362 | } while (nr_pages); |
| 1363 | return i; | 1363 | return i; |
| 1364 | } | 1364 | } |
| 1365 | 1365 | ||
| @@ -1368,7 +1368,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1368 | * @tsk: task_struct of target task | 1368 | * @tsk: task_struct of target task |
| 1369 | * @mm: mm_struct of target mm | 1369 | * @mm: mm_struct of target mm |
| 1370 | * @start: starting user address | 1370 | * @start: starting user address |
| 1371 | * @len: number of pages from start to pin | 1371 | * @nr_pages: number of pages from start to pin |
| 1372 | * @write: whether pages will be written to by the caller | 1372 | * @write: whether pages will be written to by the caller |
| 1373 | * @force: whether to force write access even if user mapping is | 1373 | * @force: whether to force write access even if user mapping is |
| 1374 | * readonly. This will result in the page being COWed even | 1374 | * readonly. This will result in the page being COWed even |
| @@ -1380,7 +1380,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1380 | * Or NULL if the caller does not require them. | 1380 | * Or NULL if the caller does not require them. |
| 1381 | * | 1381 | * |
| 1382 | * Returns number of pages pinned. This may be fewer than the number | 1382 | * Returns number of pages pinned. This may be fewer than the number |
| 1383 | * requested. If len is 0 or negative, returns 0. If no pages | 1383 | * requested. If nr_pages is 0 or negative, returns 0. If no pages |
| 1384 | * were pinned, returns -errno. Each page returned must be released | 1384 | * were pinned, returns -errno. Each page returned must be released |
| 1385 | * with a put_page() call when it is finished with. vmas will only | 1385 | * with a put_page() call when it is finished with. vmas will only |
| 1386 | * remain valid while mmap_sem is held. | 1386 | * remain valid while mmap_sem is held. |
| @@ -1414,7 +1414,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1414 | * See also get_user_pages_fast, for performance critical applications. | 1414 | * See also get_user_pages_fast, for performance critical applications. |
| 1415 | */ | 1415 | */ |
| 1416 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 1416 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
| 1417 | unsigned long start, int len, int write, int force, | 1417 | unsigned long start, int nr_pages, int write, int force, |
| 1418 | struct page **pages, struct vm_area_struct **vmas) | 1418 | struct page **pages, struct vm_area_struct **vmas) |
| 1419 | { | 1419 | { |
| 1420 | int flags = 0; | 1420 | int flags = 0; |
| @@ -1424,9 +1424,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 1424 | if (force) | 1424 | if (force) |
| 1425 | flags |= GUP_FLAGS_FORCE; | 1425 | flags |= GUP_FLAGS_FORCE; |
| 1426 | 1426 | ||
| 1427 | return __get_user_pages(tsk, mm, | 1427 | return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); |
| 1428 | start, len, flags, | ||
| 1429 | pages, vmas); | ||
| 1430 | } | 1428 | } |
| 1431 | 1429 | ||
| 1432 | EXPORT_SYMBOL(get_user_pages); | 1430 | EXPORT_SYMBOL(get_user_pages); |
diff --git a/mm/nommu.c b/mm/nommu.c index 2fd2ad5da98e..bf0cc762a7d2 100644 --- a/mm/nommu.c +++ b/mm/nommu.c | |||
| @@ -173,8 +173,8 @@ unsigned int kobjsize(const void *objp) | |||
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 175 | int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
| 176 | unsigned long start, int len, int flags, | 176 | unsigned long start, int nr_pages, int flags, |
| 177 | struct page **pages, struct vm_area_struct **vmas) | 177 | struct page **pages, struct vm_area_struct **vmas) |
| 178 | { | 178 | { |
| 179 | struct vm_area_struct *vma; | 179 | struct vm_area_struct *vma; |
| 180 | unsigned long vm_flags; | 180 | unsigned long vm_flags; |
| @@ -189,7 +189,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 189 | vm_flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); | 189 | vm_flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD); |
| 190 | vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); | 190 | vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); |
| 191 | 191 | ||
| 192 | for (i = 0; i < len; i++) { | 192 | for (i = 0; i < nr_pages; i++) { |
| 193 | vma = find_vma(mm, start); | 193 | vma = find_vma(mm, start); |
| 194 | if (!vma) | 194 | if (!vma) |
| 195 | goto finish_or_fault; | 195 | goto finish_or_fault; |
| @@ -224,7 +224,7 @@ finish_or_fault: | |||
| 224 | * - don't permit access to VMAs that don't support it, such as I/O mappings | 224 | * - don't permit access to VMAs that don't support it, such as I/O mappings |
| 225 | */ | 225 | */ |
| 226 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | 226 | int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, |
| 227 | unsigned long start, int len, int write, int force, | 227 | unsigned long start, int nr_pages, int write, int force, |
| 228 | struct page **pages, struct vm_area_struct **vmas) | 228 | struct page **pages, struct vm_area_struct **vmas) |
| 229 | { | 229 | { |
| 230 | int flags = 0; | 230 | int flags = 0; |
| @@ -234,9 +234,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, | |||
| 234 | if (force) | 234 | if (force) |
| 235 | flags |= GUP_FLAGS_FORCE; | 235 | flags |= GUP_FLAGS_FORCE; |
| 236 | 236 | ||
| 237 | return __get_user_pages(tsk, mm, | 237 | return __get_user_pages(tsk, mm, start, nr_pages, flags, pages, vmas); |
| 238 | start, len, flags, | ||
| 239 | pages, vmas); | ||
| 240 | } | 238 | } |
| 241 | EXPORT_SYMBOL(get_user_pages); | 239 | EXPORT_SYMBOL(get_user_pages); |
| 242 | 240 | ||
diff --git a/mm/percpu.c b/mm/percpu.c index c0b2c1a76e81..b70f2acd8853 100644 --- a/mm/percpu.c +++ b/mm/percpu.c | |||
| @@ -549,14 +549,14 @@ static void pcpu_free_area(struct pcpu_chunk *chunk, int freeme) | |||
| 549 | * @chunk: chunk of interest | 549 | * @chunk: chunk of interest |
| 550 | * @page_start: page index of the first page to unmap | 550 | * @page_start: page index of the first page to unmap |
| 551 | * @page_end: page index of the last page to unmap + 1 | 551 | * @page_end: page index of the last page to unmap + 1 |
| 552 | * @flush: whether to flush cache and tlb or not | 552 | * @flush_tlb: whether to flush tlb or not |
| 553 | * | 553 | * |
| 554 | * For each cpu, unmap pages [@page_start,@page_end) out of @chunk. | 554 | * For each cpu, unmap pages [@page_start,@page_end) out of @chunk. |
| 555 | * If @flush is true, vcache is flushed before unmapping and tlb | 555 | * If @flush is true, vcache is flushed before unmapping and tlb |
| 556 | * after. | 556 | * after. |
| 557 | */ | 557 | */ |
| 558 | static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | 558 | static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, |
| 559 | bool flush) | 559 | bool flush_tlb) |
| 560 | { | 560 | { |
| 561 | unsigned int last = num_possible_cpus() - 1; | 561 | unsigned int last = num_possible_cpus() - 1; |
| 562 | unsigned int cpu; | 562 | unsigned int cpu; |
| @@ -569,9 +569,8 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | |||
| 569 | * the whole region at once rather than doing it for each cpu. | 569 | * the whole region at once rather than doing it for each cpu. |
| 570 | * This could be an overkill but is more scalable. | 570 | * This could be an overkill but is more scalable. |
| 571 | */ | 571 | */ |
| 572 | if (flush) | 572 | flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start), |
| 573 | flush_cache_vunmap(pcpu_chunk_addr(chunk, 0, page_start), | 573 | pcpu_chunk_addr(chunk, last, page_end)); |
| 574 | pcpu_chunk_addr(chunk, last, page_end)); | ||
| 575 | 574 | ||
| 576 | for_each_possible_cpu(cpu) | 575 | for_each_possible_cpu(cpu) |
| 577 | unmap_kernel_range_noflush( | 576 | unmap_kernel_range_noflush( |
| @@ -579,7 +578,7 @@ static void pcpu_unmap(struct pcpu_chunk *chunk, int page_start, int page_end, | |||
| 579 | (page_end - page_start) << PAGE_SHIFT); | 578 | (page_end - page_start) << PAGE_SHIFT); |
| 580 | 579 | ||
| 581 | /* ditto as flush_cache_vunmap() */ | 580 | /* ditto as flush_cache_vunmap() */ |
| 582 | if (flush) | 581 | if (flush_tlb) |
| 583 | flush_tlb_kernel_range(pcpu_chunk_addr(chunk, 0, page_start), | 582 | flush_tlb_kernel_range(pcpu_chunk_addr(chunk, 0, page_start), |
| 584 | pcpu_chunk_addr(chunk, last, page_end)); | 583 | pcpu_chunk_addr(chunk, last, page_end)); |
| 585 | } | 584 | } |
| @@ -1234,6 +1233,7 @@ static struct page * __init pcpue_get_page(unsigned int cpu, int pageno) | |||
| 1234 | ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, | 1233 | ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, |
| 1235 | ssize_t dyn_size, ssize_t unit_size) | 1234 | ssize_t dyn_size, ssize_t unit_size) |
| 1236 | { | 1235 | { |
| 1236 | size_t chunk_size; | ||
| 1237 | unsigned int cpu; | 1237 | unsigned int cpu; |
| 1238 | 1238 | ||
| 1239 | /* determine parameters and allocate */ | 1239 | /* determine parameters and allocate */ |
| @@ -1248,11 +1248,15 @@ ssize_t __init pcpu_embed_first_chunk(size_t static_size, size_t reserved_size, | |||
| 1248 | } else | 1248 | } else |
| 1249 | pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); | 1249 | pcpue_unit_size = max_t(size_t, pcpue_size, PCPU_MIN_UNIT_SIZE); |
| 1250 | 1250 | ||
| 1251 | pcpue_ptr = __alloc_bootmem_nopanic( | 1251 | chunk_size = pcpue_unit_size * num_possible_cpus(); |
| 1252 | num_possible_cpus() * pcpue_unit_size, | 1252 | |
| 1253 | PAGE_SIZE, __pa(MAX_DMA_ADDRESS)); | 1253 | pcpue_ptr = __alloc_bootmem_nopanic(chunk_size, PAGE_SIZE, |
| 1254 | if (!pcpue_ptr) | 1254 | __pa(MAX_DMA_ADDRESS)); |
| 1255 | if (!pcpue_ptr) { | ||
| 1256 | pr_warning("PERCPU: failed to allocate %zu bytes for " | ||
| 1257 | "embedding\n", chunk_size); | ||
| 1255 | return -ENOMEM; | 1258 | return -ENOMEM; |
| 1259 | } | ||
| 1256 | 1260 | ||
| 1257 | /* return the leftover and copy */ | 1261 | /* return the leftover and copy */ |
| 1258 | for_each_possible_cpu(cpu) { | 1262 | for_each_possible_cpu(cpu) { |
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore new file mode 100644 index 000000000000..095acb49a374 --- /dev/null +++ b/scripts/dtc/.gitignore | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | dtc | ||
| 2 | dtc-lexer.lex.c | ||
| 3 | dtc-parser.tab.c | ||
| 4 | dtc-parser.tab.h | ||
| 5 | |||
