diff options
70 files changed, 2545 insertions, 707 deletions
diff --git a/Documentation/cciss.txt b/Documentation/cciss.txt index 8244c6442faa..89698e8df7d4 100644 --- a/Documentation/cciss.txt +++ b/Documentation/cciss.txt | |||
@@ -21,11 +21,14 @@ This driver is known to work with the following cards: | |||
21 | * SA E200 | 21 | * SA E200 |
22 | * SA E200i | 22 | * SA E200i |
23 | * SA E500 | 23 | * SA E500 |
24 | * SA P700m | ||
24 | * SA P212 | 25 | * SA P212 |
25 | * SA P410 | 26 | * SA P410 |
26 | * SA P410i | 27 | * SA P410i |
27 | * SA P411 | 28 | * SA P411 |
28 | * SA P812 | 29 | * SA P812 |
30 | * SA P712m | ||
31 | * SA P711m | ||
29 | 32 | ||
30 | Detecting drive failures: | 33 | Detecting drive failures: |
31 | ------------------------- | 34 | ------------------------- |
diff --git a/Documentation/email-clients.txt b/Documentation/email-clients.txt index 2ebb94d6ed8e..a618efab7b15 100644 --- a/Documentation/email-clients.txt +++ b/Documentation/email-clients.txt | |||
@@ -213,4 +213,29 @@ TkRat (GUI) | |||
213 | 213 | ||
214 | Works. Use "Insert file..." or external editor. | 214 | Works. Use "Insert file..." or external editor. |
215 | 215 | ||
216 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
217 | Gmail (Web GUI) | ||
218 | |||
219 | If you just have to use Gmail to send patches, it CAN be made to work. It | ||
220 | requires a bit of external help, though. | ||
221 | |||
222 | The first problem is that Gmail converts tabs to spaces. This will | ||
223 | totally break your patches. To prevent this, you have to use a different | ||
224 | editor. There is a firefox extension called "ViewSourceWith" | ||
225 | (https://addons.mozilla.org/en-US/firefox/addon/394) which allows you to | ||
226 | edit any text box in the editor of your choice. Configure it to launch | ||
227 | your favorite editor. When you want to send a patch, use this technique. | ||
228 | Once you have crafted your messsage + patch, save and exit the editor, | ||
229 | which should reload the Gmail edit box. GMAIL WILL PRESERVE THE TABS. | ||
230 | Hoorah. Apparently you can cut-n-paste literal tabs, but Gmail will | ||
231 | convert those to spaces upon sending! | ||
232 | |||
233 | The second problem is that Gmail converts tabs to spaces on replies. If | ||
234 | you reply to a patch, don't expect to be able to apply it as a patch. | ||
235 | |||
236 | The last problem is that Gmail will base64-encode any message that has a | ||
237 | non-ASCII character. That includes things like European names. Be aware. | ||
238 | |||
239 | Gmail is not convenient for lkml patches, but CAN be made to work. | ||
240 | |||
216 | ### | 241 | ### |
diff --git a/Documentation/filesystems/vfat.txt b/Documentation/filesystems/vfat.txt index bbac4f1d9056..3a5ddc96901a 100644 --- a/Documentation/filesystems/vfat.txt +++ b/Documentation/filesystems/vfat.txt | |||
@@ -8,6 +8,12 @@ if you want to format from within Linux. | |||
8 | 8 | ||
9 | VFAT MOUNT OPTIONS | 9 | VFAT MOUNT OPTIONS |
10 | ---------------------------------------------------------------------- | 10 | ---------------------------------------------------------------------- |
11 | uid=### -- Set the owner of all files on this filesystem. | ||
12 | The default is the uid of current process. | ||
13 | |||
14 | gid=### -- Set the group of all files on this filesystem. | ||
15 | The default is the gid of current process. | ||
16 | |||
11 | umask=### -- The permission mask (for files and directories, see umask(1)). | 17 | umask=### -- The permission mask (for files and directories, see umask(1)). |
12 | The default is the umask of current process. | 18 | The default is the umask of current process. |
13 | 19 | ||
@@ -36,7 +42,7 @@ codepage=### -- Sets the codepage number for converting to shortname | |||
36 | characters on FAT filesystem. | 42 | characters on FAT filesystem. |
37 | By default, FAT_DEFAULT_CODEPAGE setting is used. | 43 | By default, FAT_DEFAULT_CODEPAGE setting is used. |
38 | 44 | ||
39 | iocharset=name -- Character set to use for converting between the | 45 | iocharset=<name> -- Character set to use for converting between the |
40 | encoding is used for user visible filename and 16 bit | 46 | encoding is used for user visible filename and 16 bit |
41 | Unicode characters. Long filenames are stored on disk | 47 | Unicode characters. Long filenames are stored on disk |
42 | in Unicode format, but Unix for the most part doesn't | 48 | in Unicode format, but Unix for the most part doesn't |
@@ -86,6 +92,8 @@ check=s|r|n -- Case sensitivity checking setting. | |||
86 | r: relaxed, case insensitive | 92 | r: relaxed, case insensitive |
87 | n: normal, default setting, currently case insensitive | 93 | n: normal, default setting, currently case insensitive |
88 | 94 | ||
95 | nocase -- This was deprecated for vfat. Use shortname=win95 instead. | ||
96 | |||
89 | shortname=lower|win95|winnt|mixed | 97 | shortname=lower|win95|winnt|mixed |
90 | -- Shortname display/create setting. | 98 | -- Shortname display/create setting. |
91 | lower: convert to lowercase for display, | 99 | lower: convert to lowercase for display, |
@@ -99,11 +107,31 @@ shortname=lower|win95|winnt|mixed | |||
99 | tz=UTC -- Interpret timestamps as UTC rather than local time. | 107 | tz=UTC -- Interpret timestamps as UTC rather than local time. |
100 | This option disables the conversion of timestamps | 108 | This option disables the conversion of timestamps |
101 | between local time (as used by Windows on FAT) and UTC | 109 | between local time (as used by Windows on FAT) and UTC |
102 | (which Linux uses internally). This is particuluarly | 110 | (which Linux uses internally). This is particularly |
103 | useful when mounting devices (like digital cameras) | 111 | useful when mounting devices (like digital cameras) |
104 | that are set to UTC in order to avoid the pitfalls of | 112 | that are set to UTC in order to avoid the pitfalls of |
105 | local time. | 113 | local time. |
106 | 114 | ||
115 | showexec -- If set, the execute permission bits of the file will be | ||
116 | allowed only if the extension part of the name is .EXE, | ||
117 | .COM, or .BAT. Not set by default. | ||
118 | |||
119 | debug -- Can be set, but unused by the current implementation. | ||
120 | |||
121 | sys_immutable -- If set, ATTR_SYS attribute on FAT is handled as | ||
122 | IMMUTABLE flag on Linux. Not set by default. | ||
123 | |||
124 | flush -- If set, the filesystem will try to flush to disk more | ||
125 | early than normal. Not set by default. | ||
126 | |||
127 | rodir -- FAT has the ATTR_RO (read-only) attribute. But on Windows, | ||
128 | the ATTR_RO of the directory will be just ignored actually, | ||
129 | and is used by only applications as flag. E.g. it's setted | ||
130 | for the customized folder. | ||
131 | |||
132 | If you want to use ATTR_RO as read-only flag even for | ||
133 | the directory, set this option. | ||
134 | |||
107 | <bool>: 0,1,yes,no,true,false | 135 | <bool>: 0,1,yes,no,true,false |
108 | 136 | ||
109 | TODO | 137 | TODO |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1bbcaa8982b6..8a8cb0ccc5f4 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -995,13 +995,15 @@ and is between 256 and 4096 characters. It is defined in the file | |||
995 | Format: | 995 | Format: |
996 | <cpu number>,...,<cpu number> | 996 | <cpu number>,...,<cpu number> |
997 | or | 997 | or |
998 | <cpu number>-<cpu number> (must be a positive range in ascending order) | 998 | <cpu number>-<cpu number> |
999 | (must be a positive range in ascending order) | ||
999 | or a mixture | 1000 | or a mixture |
1000 | <cpu number>,...,<cpu number>-<cpu number> | 1001 | <cpu number>,...,<cpu number>-<cpu number> |
1002 | |||
1001 | This option can be used to specify one or more CPUs | 1003 | This option can be used to specify one or more CPUs |
1002 | to isolate from the general SMP balancing and scheduling | 1004 | to isolate from the general SMP balancing and scheduling |
1003 | algorithms. The only way to move a process onto or off | 1005 | algorithms. You can move a process onto or off an |
1004 | an "isolated" CPU is via the CPU affinity syscalls. | 1006 | "isolated" CPU via the CPU affinity syscalls or cpuset. |
1005 | <cpu number> begins at 0 and the maximum value is | 1007 | <cpu number> begins at 0 and the maximum value is |
1006 | "number of CPUs in system - 1". | 1008 | "number of CPUs in system - 1". |
1007 | 1009 | ||
diff --git a/MAINTAINERS b/MAINTAINERS index d643e862b8e4..7e6a17e1de09 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -721,7 +721,7 @@ W: http://sourceforge.net/projects/acpi4asus | |||
721 | W: http://xf.iksaif.net/acpi4asus | 721 | W: http://xf.iksaif.net/acpi4asus |
722 | S: Maintained | 722 | S: Maintained |
723 | 723 | ||
724 | ASYNCHRONOUS TRANSFERS/TRANSFORMS API | 724 | ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API |
725 | P: Dan Williams | 725 | P: Dan Williams |
726 | M: dan.j.williams@intel.com | 726 | M: dan.j.williams@intel.com |
727 | P: Maciej Sosnowski | 727 | P: Maciej Sosnowski |
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index fdf088f2430e..7b4cefa2199b 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/kexec.h> | 16 | #include <linux/kexec.h> |
17 | #include <linux/crash_dump.h> | 17 | #include <linux/crash_dump.h> |
18 | 18 | ||
19 | #include <asm/kexec.h> | ||
19 | #include <asm/reg.h> | 20 | #include <asm/reg.h> |
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 31481dc485de..7190493e9bdc 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -189,7 +189,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
189 | { | 189 | { |
190 | struct pci_controller *phb; | 190 | struct pci_controller *phb; |
191 | int primary; | 191 | int primary; |
192 | struct pci_bus *b; | ||
193 | 192 | ||
194 | primary = list_empty(&hose_list); | 193 | primary = list_empty(&hose_list); |
195 | phb = pcibios_alloc_controller(dn); | 194 | phb = pcibios_alloc_controller(dn); |
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 90ac7718469a..4850e4b02b61 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h | |||
@@ -154,7 +154,7 @@ extern unsigned long node_remap_size[]; | |||
154 | 154 | ||
155 | #endif | 155 | #endif |
156 | 156 | ||
157 | /* sched_domains SD_NODE_INIT for NUMAQ machines */ | 157 | /* sched_domains SD_NODE_INIT for NUMA machines */ |
158 | #define SD_NODE_INIT (struct sched_domain) { \ | 158 | #define SD_NODE_INIT (struct sched_domain) { \ |
159 | .min_interval = 8, \ | 159 | .min_interval = 8, \ |
160 | .max_interval = 32, \ | 160 | .max_interval = 32, \ |
@@ -169,8 +169,9 @@ extern unsigned long node_remap_size[]; | |||
169 | .flags = SD_LOAD_BALANCE \ | 169 | .flags = SD_LOAD_BALANCE \ |
170 | | SD_BALANCE_EXEC \ | 170 | | SD_BALANCE_EXEC \ |
171 | | SD_BALANCE_FORK \ | 171 | | SD_BALANCE_FORK \ |
172 | | SD_SERIALIZE \ | 172 | | SD_WAKE_AFFINE \ |
173 | | SD_WAKE_BALANCE, \ | 173 | | SD_WAKE_BALANCE \ |
174 | | SD_SERIALIZE, \ | ||
174 | .last_balance = jiffies, \ | 175 | .last_balance = jiffies, \ |
175 | .balance_interval = 1, \ | 176 | .balance_interval = 1, \ |
176 | } | 177 | } |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 4023885353e0..12de1fdaa6c6 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -96,6 +96,8 @@ static const struct pci_device_id cciss_pci_device_id[] = { | |||
96 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, | 96 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245}, |
97 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, | 97 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3247}, |
98 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, | 98 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249}, |
99 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324A}, | ||
100 | {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324B}, | ||
99 | {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 101 | {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
100 | PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, | 102 | PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0}, |
101 | {0,} | 103 | {0,} |
@@ -133,6 +135,8 @@ static struct board_type products[] = { | |||
133 | {0x3245103C, "Smart Array P410i", &SA5_access}, | 135 | {0x3245103C, "Smart Array P410i", &SA5_access}, |
134 | {0x3247103C, "Smart Array P411", &SA5_access}, | 136 | {0x3247103C, "Smart Array P411", &SA5_access}, |
135 | {0x3249103C, "Smart Array P812", &SA5_access}, | 137 | {0x3249103C, "Smart Array P812", &SA5_access}, |
138 | {0x324A103C, "Smart Array P712m", &SA5_access}, | ||
139 | {0x324B103C, "Smart Array P711m", &SA5_access}, | ||
136 | {0xFFFF103C, "Unknown Smart Array", &SA5_access}, | 140 | {0xFFFF103C, "Unknown Smart Array", &SA5_access}, |
137 | }; | 141 | }; |
138 | 142 | ||
@@ -1366,6 +1370,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
1366 | disk->first_minor = drv_index << NWD_SHIFT; | 1370 | disk->first_minor = drv_index << NWD_SHIFT; |
1367 | disk->fops = &cciss_fops; | 1371 | disk->fops = &cciss_fops; |
1368 | disk->private_data = &h->drv[drv_index]; | 1372 | disk->private_data = &h->drv[drv_index]; |
1373 | disk->driverfs_dev = &h->pdev->dev; | ||
1369 | 1374 | ||
1370 | /* Set up queue information */ | 1375 | /* Set up queue information */ |
1371 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); | 1376 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); |
@@ -3404,7 +3409,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3404 | int i; | 3409 | int i; |
3405 | int j = 0; | 3410 | int j = 0; |
3406 | int rc; | 3411 | int rc; |
3407 | int dac; | 3412 | int dac, return_code; |
3413 | InquiryData_struct *inq_buff = NULL; | ||
3408 | 3414 | ||
3409 | i = alloc_cciss_hba(); | 3415 | i = alloc_cciss_hba(); |
3410 | if (i < 0) | 3416 | if (i < 0) |
@@ -3510,6 +3516,25 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3510 | /* Turn the interrupts on so we can service requests */ | 3516 | /* Turn the interrupts on so we can service requests */ |
3511 | hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); | 3517 | hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON); |
3512 | 3518 | ||
3519 | /* Get the firmware version */ | ||
3520 | inq_buff = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL); | ||
3521 | if (inq_buff == NULL) { | ||
3522 | printk(KERN_ERR "cciss: out of memory\n"); | ||
3523 | goto clean4; | ||
3524 | } | ||
3525 | |||
3526 | return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff, | ||
3527 | sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD); | ||
3528 | if (return_code == IO_OK) { | ||
3529 | hba[i]->firm_ver[0] = inq_buff->data_byte[32]; | ||
3530 | hba[i]->firm_ver[1] = inq_buff->data_byte[33]; | ||
3531 | hba[i]->firm_ver[2] = inq_buff->data_byte[34]; | ||
3532 | hba[i]->firm_ver[3] = inq_buff->data_byte[35]; | ||
3533 | } else { /* send command failed */ | ||
3534 | printk(KERN_WARNING "cciss: unable to determine firmware" | ||
3535 | " version of controller\n"); | ||
3536 | } | ||
3537 | |||
3513 | cciss_procinit(i); | 3538 | cciss_procinit(i); |
3514 | 3539 | ||
3515 | hba[i]->cciss_max_sectors = 2048; | 3540 | hba[i]->cciss_max_sectors = 2048; |
@@ -3520,6 +3545,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
3520 | return 1; | 3545 | return 1; |
3521 | 3546 | ||
3522 | clean4: | 3547 | clean4: |
3548 | kfree(inq_buff); | ||
3523 | #ifdef CONFIG_CISS_SCSI_TAPE | 3549 | #ifdef CONFIG_CISS_SCSI_TAPE |
3524 | kfree(hba[i]->scsi_rejects.complete); | 3550 | kfree(hba[i]->scsi_rejects.complete); |
3525 | #endif | 3551 | #endif |
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 47d233c6d0b3..5d39df14ed90 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c | |||
@@ -567,7 +567,12 @@ static int __init cpqarray_init(void) | |||
567 | num_cntlrs_reg++; | 567 | num_cntlrs_reg++; |
568 | } | 568 | } |
569 | 569 | ||
570 | return(num_cntlrs_reg); | 570 | if (num_cntlrs_reg) |
571 | return 0; | ||
572 | else { | ||
573 | pci_unregister_driver(&cpqarray_pci_driver); | ||
574 | return -ENODEV; | ||
575 | } | ||
571 | } | 576 | } |
572 | 577 | ||
573 | /* Function to find the first free pointer into our hba[] array */ | 578 | /* Function to find the first free pointer into our hba[] array */ |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index d8f83e26e4a4..a5af6072e2b3 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -1644,7 +1644,10 @@ static void reset_terminal(struct vc_data *vc, int do_clear) | |||
1644 | vc->vc_tab_stop[1] = | 1644 | vc->vc_tab_stop[1] = |
1645 | vc->vc_tab_stop[2] = | 1645 | vc->vc_tab_stop[2] = |
1646 | vc->vc_tab_stop[3] = | 1646 | vc->vc_tab_stop[3] = |
1647 | vc->vc_tab_stop[4] = 0x01010101; | 1647 | vc->vc_tab_stop[4] = |
1648 | vc->vc_tab_stop[5] = | ||
1649 | vc->vc_tab_stop[6] = | ||
1650 | vc->vc_tab_stop[7] = 0x01010101; | ||
1648 | 1651 | ||
1649 | vc->vc_bell_pitch = DEFAULT_BELL_PITCH; | 1652 | vc->vc_bell_pitch = DEFAULT_BELL_PITCH; |
1650 | vc->vc_bell_duration = DEFAULT_BELL_DURATION; | 1653 | vc->vc_bell_duration = DEFAULT_BELL_DURATION; |
@@ -1935,7 +1938,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) | |||
1935 | vc->vc_tab_stop[1] = | 1938 | vc->vc_tab_stop[1] = |
1936 | vc->vc_tab_stop[2] = | 1939 | vc->vc_tab_stop[2] = |
1937 | vc->vc_tab_stop[3] = | 1940 | vc->vc_tab_stop[3] = |
1938 | vc->vc_tab_stop[4] = 0; | 1941 | vc->vc_tab_stop[4] = |
1942 | vc->vc_tab_stop[5] = | ||
1943 | vc->vc_tab_stop[6] = | ||
1944 | vc->vc_tab_stop[7] = 0; | ||
1939 | } | 1945 | } |
1940 | return; | 1946 | return; |
1941 | case 'm': | 1947 | case 'm': |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index bc011da79e14..be3285912cb7 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
@@ -116,6 +116,18 @@ static const char* temperature_sensors_sets[][36] = { | |||
116 | /* Set 9: Macbook Pro 3,1 (Santa Rosa) */ | 116 | /* Set 9: Macbook Pro 3,1 (Santa Rosa) */ |
117 | { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", | 117 | { "TALP", "TB0T", "TC0D", "TC0P", "TG0D", "TG0H", "TTF0", "TW0P", |
118 | "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, | 118 | "Th0H", "Th1H", "Th2H", "Tm0P", "Ts0P", NULL }, |
119 | /* Set 10: iMac 5,1 */ | ||
120 | { "TA0P", "TC0D", "TC0P", "TG0D", "TH0P", "TO0P", "Tm0P", NULL }, | ||
121 | /* Set 11: Macbook 5,1 */ | ||
122 | { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0P", "TN0D", "TN0P", | ||
123 | "TTF0", "Th0H", "Th1H", "ThFH", "Ts0P", "Ts0S", NULL }, | ||
124 | /* Set 12: Macbook Pro 5,1 */ | ||
125 | { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D", | ||
126 | "TG0F", "TG0H", "TG0P", "TG0T", "TG1H", "TN0D", "TN0P", "TTF0", | ||
127 | "Th2H", "Tm0P", "Ts0P", "Ts0S", NULL }, | ||
128 | /* Set 13: iMac 8,1 */ | ||
129 | { "TA0P", "TC0D", "TC0H", "TC0P", "TG0D", "TG0H", "TG0P", "TH0P", | ||
130 | "TL0P", "TO0P", "TW0P", "Tm0P", "Tp0P", NULL }, | ||
119 | }; | 131 | }; |
120 | 132 | ||
121 | /* List of keys used to read/write fan speeds */ | 133 | /* List of keys used to read/write fan speeds */ |
@@ -1276,6 +1288,14 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { | |||
1276 | { .accelerometer = 1, .light = 1, .temperature_set = 8 }, | 1288 | { .accelerometer = 1, .light = 1, .temperature_set = 8 }, |
1277 | /* MacBook Pro 3: accelerometer, backlight and temperature set 9 */ | 1289 | /* MacBook Pro 3: accelerometer, backlight and temperature set 9 */ |
1278 | { .accelerometer = 1, .light = 1, .temperature_set = 9 }, | 1290 | { .accelerometer = 1, .light = 1, .temperature_set = 9 }, |
1291 | /* iMac 5: light sensor only, temperature set 10 */ | ||
1292 | { .accelerometer = 0, .light = 0, .temperature_set = 10 }, | ||
1293 | /* MacBook 5: accelerometer, backlight and temperature set 11 */ | ||
1294 | { .accelerometer = 1, .light = 1, .temperature_set = 11 }, | ||
1295 | /* MacBook Pro 5: accelerometer, backlight and temperature set 12 */ | ||
1296 | { .accelerometer = 1, .light = 1, .temperature_set = 12 }, | ||
1297 | /* iMac 8: light sensor only, temperature set 13 */ | ||
1298 | { .accelerometer = 0, .light = 0, .temperature_set = 13 }, | ||
1279 | }; | 1299 | }; |
1280 | 1300 | ||
1281 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". | 1301 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". |
@@ -1285,6 +1305,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
1285 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1305 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
1286 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, | 1306 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, |
1287 | &applesmc_dmi_data[7]}, | 1307 | &applesmc_dmi_data[7]}, |
1308 | { applesmc_dmi_match, "Apple MacBook Pro 5", { | ||
1309 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1310 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") }, | ||
1311 | &applesmc_dmi_data[12]}, | ||
1288 | { applesmc_dmi_match, "Apple MacBook Pro 4", { | 1312 | { applesmc_dmi_match, "Apple MacBook Pro 4", { |
1289 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1313 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
1290 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") }, | 1314 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro4") }, |
@@ -1305,6 +1329,10 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
1305 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1329 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1306 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, | 1330 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") }, |
1307 | &applesmc_dmi_data[6]}, | 1331 | &applesmc_dmi_data[6]}, |
1332 | { applesmc_dmi_match, "Apple MacBook 5", { | ||
1333 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1334 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook5") }, | ||
1335 | &applesmc_dmi_data[11]}, | ||
1308 | { applesmc_dmi_match, "Apple MacBook", { | 1336 | { applesmc_dmi_match, "Apple MacBook", { |
1309 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1337 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1310 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, | 1338 | DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") }, |
@@ -1317,6 +1345,14 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
1317 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1345 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1318 | DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, | 1346 | DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") }, |
1319 | &applesmc_dmi_data[4]}, | 1347 | &applesmc_dmi_data[4]}, |
1348 | { applesmc_dmi_match, "Apple iMac 8", { | ||
1349 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1350 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac8") }, | ||
1351 | &applesmc_dmi_data[13]}, | ||
1352 | { applesmc_dmi_match, "Apple iMac 5", { | ||
1353 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1354 | DMI_MATCH(DMI_PRODUCT_NAME, "iMac5") }, | ||
1355 | &applesmc_dmi_data[10]}, | ||
1320 | { applesmc_dmi_match, "Apple iMac", { | 1356 | { applesmc_dmi_match, "Apple iMac", { |
1321 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), | 1357 | DMI_MATCH(DMI_BOARD_VENDOR,"Apple"), |
1322 | DMI_MATCH(DMI_PRODUCT_NAME,"iMac") }, | 1358 | DMI_MATCH(DMI_PRODUCT_NAME,"iMac") }, |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 190147c79e79..3b90c5c924ec 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
@@ -148,6 +148,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
148 | 148 | ||
149 | min_sectors = conf->array_sectors; | 149 | min_sectors = conf->array_sectors; |
150 | sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *)); | 150 | sector_div(min_sectors, PAGE_SIZE/sizeof(struct dev_info *)); |
151 | if (min_sectors == 0) | ||
152 | min_sectors = 1; | ||
151 | 153 | ||
152 | /* min_sectors is the minimum spacing that will fit the hash | 154 | /* min_sectors is the minimum spacing that will fit the hash |
153 | * table in one PAGE. This may be much smaller than needed. | 155 | * table in one PAGE. This may be much smaller than needed. |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 9abf6ed16535..1b1d32694f6f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3884,7 +3884,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
3884 | if (mode == 0) { | 3884 | if (mode == 0) { |
3885 | mdk_rdev_t *rdev; | 3885 | mdk_rdev_t *rdev; |
3886 | struct list_head *tmp; | 3886 | struct list_head *tmp; |
3887 | struct block_device *bdev; | ||
3888 | 3887 | ||
3889 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); | 3888 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); |
3890 | 3889 | ||
@@ -3941,11 +3940,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
3941 | mddev->degraded = 0; | 3940 | mddev->degraded = 0; |
3942 | mddev->barriers_work = 0; | 3941 | mddev->barriers_work = 0; |
3943 | mddev->safemode = 0; | 3942 | mddev->safemode = 0; |
3944 | bdev = bdget_disk(mddev->gendisk, 0); | ||
3945 | if (bdev) { | ||
3946 | blkdev_ioctl(bdev, 0, BLKRRPART, 0); | ||
3947 | bdput(bdev); | ||
3948 | } | ||
3949 | kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); | 3943 | kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); |
3950 | 3944 | ||
3951 | } else if (mddev->pers) | 3945 | } else if (mddev->pers) |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index da5129a24b18..970a96ef9b18 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -1137,7 +1137,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
1137 | if (!enough(conf)) | 1137 | if (!enough(conf)) |
1138 | return -EINVAL; | 1138 | return -EINVAL; |
1139 | 1139 | ||
1140 | if (rdev->raid_disk) | 1140 | if (rdev->raid_disk >= 0) |
1141 | first = last = rdev->raid_disk; | 1141 | first = last = rdev->raid_disk; |
1142 | 1142 | ||
1143 | if (rdev->saved_raid_disk >= 0 && | 1143 | if (rdev->saved_raid_disk >= 0 && |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 3e6f5d8609e8..d74ec46aa032 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
@@ -406,19 +406,6 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) | |||
406 | /* Set the default CFI lock/unlock addresses */ | 406 | /* Set the default CFI lock/unlock addresses */ |
407 | cfi->addr_unlock1 = 0x555; | 407 | cfi->addr_unlock1 = 0x555; |
408 | cfi->addr_unlock2 = 0x2aa; | 408 | cfi->addr_unlock2 = 0x2aa; |
409 | /* Modify the unlock address if we are in compatibility mode */ | ||
410 | if ( /* x16 in x8 mode */ | ||
411 | ((cfi->device_type == CFI_DEVICETYPE_X8) && | ||
412 | (cfi->cfiq->InterfaceDesc == | ||
413 | CFI_INTERFACE_X8_BY_X16_ASYNC)) || | ||
414 | /* x32 in x16 mode */ | ||
415 | ((cfi->device_type == CFI_DEVICETYPE_X16) && | ||
416 | (cfi->cfiq->InterfaceDesc == | ||
417 | CFI_INTERFACE_X16_BY_X32_ASYNC))) | ||
418 | { | ||
419 | cfi->addr_unlock1 = 0xaaa; | ||
420 | cfi->addr_unlock2 = 0x555; | ||
421 | } | ||
422 | 409 | ||
423 | } /* CFI mode */ | 410 | } /* CFI mode */ |
424 | else if (cfi->cfi_mode == CFI_MODE_JEDEC) { | 411 | else if (cfi->cfi_mode == CFI_MODE_JEDEC) { |
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index f84ab6182148..2f3f2f719ba4 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
@@ -1808,9 +1808,7 @@ static inline u32 jedec_read_mfr(struct map_info *map, uint32_t base, | |||
1808 | * several first banks can contain 0x7f instead of actual ID | 1808 | * several first banks can contain 0x7f instead of actual ID |
1809 | */ | 1809 | */ |
1810 | do { | 1810 | do { |
1811 | uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), | 1811 | uint32_t ofs = cfi_build_cmd_addr(0 + (bank << 8), map, cfi); |
1812 | cfi_interleave(cfi), | ||
1813 | cfi->device_type); | ||
1814 | mask = (1 << (cfi->device_type * 8)) - 1; | 1812 | mask = (1 << (cfi->device_type * 8)) - 1; |
1815 | result = map_read(map, base + ofs); | 1813 | result = map_read(map, base + ofs); |
1816 | bank++; | 1814 | bank++; |
@@ -1824,7 +1822,7 @@ static inline u32 jedec_read_id(struct map_info *map, uint32_t base, | |||
1824 | { | 1822 | { |
1825 | map_word result; | 1823 | map_word result; |
1826 | unsigned long mask; | 1824 | unsigned long mask; |
1827 | u32 ofs = cfi_build_cmd_addr(1, cfi_interleave(cfi), cfi->device_type); | 1825 | u32 ofs = cfi_build_cmd_addr(1, map, cfi); |
1828 | mask = (1 << (cfi->device_type * 8)) -1; | 1826 | mask = (1 << (cfi->device_type * 8)) -1; |
1829 | result = map_read(map, base + ofs); | 1827 | result = map_read(map, base + ofs); |
1830 | return result.x[0] & mask; | 1828 | return result.x[0] & mask; |
@@ -2067,8 +2065,8 @@ static int jedec_probe_chip(struct map_info *map, __u32 base, | |||
2067 | 2065 | ||
2068 | } | 2066 | } |
2069 | /* Ensure the unlock addresses we try stay inside the map */ | 2067 | /* Ensure the unlock addresses we try stay inside the map */ |
2070 | probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, cfi_interleave(cfi), cfi->device_type); | 2068 | probe_offset1 = cfi_build_cmd_addr(cfi->addr_unlock1, map, cfi); |
2071 | probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, cfi_interleave(cfi), cfi->device_type); | 2069 | probe_offset2 = cfi_build_cmd_addr(cfi->addr_unlock2, map, cfi); |
2072 | if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || | 2070 | if ( ((base + probe_offset1 + map_bankwidth(map)) >= map->size) || |
2073 | ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) | 2071 | ((base + probe_offset2 + map_bankwidth(map)) >= map->size)) |
2074 | goto retry; | 2072 | goto retry; |
diff --git a/drivers/ps3/ps3-lpm.c b/drivers/ps3/ps3-lpm.c index 85edf945ab86..204158cf7a55 100644 --- a/drivers/ps3/ps3-lpm.c +++ b/drivers/ps3/ps3-lpm.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
25 | #include <asm/smp.h> | ||
25 | #include <asm/time.h> | 26 | #include <asm/time.h> |
26 | #include <asm/ps3.h> | 27 | #include <asm/ps3.h> |
27 | #include <asm/lv1call.h> | 28 | #include <asm/lv1call.h> |
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 7af60b98d8a4..a04c1b6b1575 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c | |||
@@ -271,7 +271,7 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) | |||
271 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); | 271 | dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year"); |
272 | do { | 272 | do { |
273 | alarm->time.tm_year++; | 273 | alarm->time.tm_year++; |
274 | } while (!rtc_valid_tm(&alarm->time)); | 274 | } while (rtc_valid_tm(&alarm->time) != 0); |
275 | break; | 275 | break; |
276 | 276 | ||
277 | default: | 277 | default: |
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 5549231179a2..6cf8e282338f 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -794,7 +794,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
794 | goto cleanup2; | 794 | goto cleanup2; |
795 | } | 795 | } |
796 | 796 | ||
797 | pr_info("%s: alarms up to one %s%s, %zd bytes nvram, %s irqs\n", | 797 | pr_info("%s: alarms up to one %s%s, %zd bytes nvram%s\n", |
798 | cmos_rtc.rtc->dev.bus_id, | 798 | cmos_rtc.rtc->dev.bus_id, |
799 | is_valid_irq(rtc_irq) | 799 | is_valid_irq(rtc_irq) |
800 | ? (cmos_rtc.mon_alrm | 800 | ? (cmos_rtc.mon_alrm |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 61fb8b6d19af..d5efd6c77904 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
@@ -1258,6 +1258,8 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
1258 | atmel_port->clk = clk_get(&pdev->dev, "usart"); | 1258 | atmel_port->clk = clk_get(&pdev->dev, "usart"); |
1259 | clk_enable(atmel_port->clk); | 1259 | clk_enable(atmel_port->clk); |
1260 | port->uartclk = clk_get_rate(atmel_port->clk); | 1260 | port->uartclk = clk_get_rate(atmel_port->clk); |
1261 | clk_disable(atmel_port->clk); | ||
1262 | /* only enable clock when USART is in use */ | ||
1261 | } | 1263 | } |
1262 | 1264 | ||
1263 | atmel_port->use_dma_rx = data->use_dma_rx; | 1265 | atmel_port->use_dma_rx = data->use_dma_rx; |
@@ -1379,6 +1381,8 @@ static int __init atmel_console_setup(struct console *co, char *options) | |||
1379 | return -ENODEV; | 1381 | return -ENODEV; |
1380 | } | 1382 | } |
1381 | 1383 | ||
1384 | clk_enable(atmel_ports[co->index].clk); | ||
1385 | |||
1382 | UART_PUT_IDR(port, -1); | 1386 | UART_PUT_IDR(port, -1); |
1383 | UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); | 1387 | UART_PUT_CR(port, ATMEL_US_RSTSTA | ATMEL_US_RSTRX); |
1384 | UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); | 1388 | UART_PUT_CR(port, ATMEL_US_TXEN | ATMEL_US_RXEN); |
@@ -1403,7 +1407,7 @@ static struct console atmel_console = { | |||
1403 | .data = &atmel_uart, | 1407 | .data = &atmel_uart, |
1404 | }; | 1408 | }; |
1405 | 1409 | ||
1406 | #define ATMEL_CONSOLE_DEVICE &atmel_console | 1410 | #define ATMEL_CONSOLE_DEVICE (&atmel_console) |
1407 | 1411 | ||
1408 | /* | 1412 | /* |
1409 | * Early console initialization (before VM subsystem initialized). | 1413 | * Early console initialization (before VM subsystem initialized). |
@@ -1534,6 +1538,15 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) | |||
1534 | if (ret) | 1538 | if (ret) |
1535 | goto err_add_port; | 1539 | goto err_add_port; |
1536 | 1540 | ||
1541 | if (atmel_is_console_port(&port->uart) | ||
1542 | && ATMEL_CONSOLE_DEVICE->flags & CON_ENABLED) { | ||
1543 | /* | ||
1544 | * The serial core enabled the clock for us, so undo | ||
1545 | * the clk_enable() in atmel_console_setup() | ||
1546 | */ | ||
1547 | clk_disable(port->clk); | ||
1548 | } | ||
1549 | |||
1537 | device_init_wakeup(&pdev->dev, 1); | 1550 | device_init_wakeup(&pdev->dev, 1); |
1538 | platform_set_drvdata(pdev, port); | 1551 | platform_set_drvdata(pdev, port); |
1539 | 1552 | ||
@@ -1544,7 +1557,6 @@ err_add_port: | |||
1544 | port->rx_ring.buf = NULL; | 1557 | port->rx_ring.buf = NULL; |
1545 | err_alloc_ring: | 1558 | err_alloc_ring: |
1546 | if (!atmel_is_console_port(&port->uart)) { | 1559 | if (!atmel_is_console_port(&port->uart)) { |
1547 | clk_disable(port->clk); | ||
1548 | clk_put(port->clk); | 1560 | clk_put(port->clk); |
1549 | port->clk = NULL; | 1561 | port->clk = NULL; |
1550 | } | 1562 | } |
@@ -1568,7 +1580,6 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) | |||
1568 | 1580 | ||
1569 | /* "port" is allocated statically, so we shouldn't free it */ | 1581 | /* "port" is allocated statically, so we shouldn't free it */ |
1570 | 1582 | ||
1571 | clk_disable(atmel_port->clk); | ||
1572 | clk_put(atmel_port->clk); | 1583 | clk_put(atmel_port->clk); |
1573 | 1584 | ||
1574 | return ret; | 1585 | return ret; |
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 0f13448c6f79..3f3ce13fef43 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -2083,6 +2083,38 @@ config FB_METRONOME | |||
2083 | controller. The pre-release name for this device was 8track | 2083 | controller. The pre-release name for this device was 8track |
2084 | and could also have been called by some vendors as PVI-nnnn. | 2084 | and could also have been called by some vendors as PVI-nnnn. |
2085 | 2085 | ||
2086 | config FB_MB862XX | ||
2087 | tristate "Fujitsu MB862xx GDC support" | ||
2088 | depends on FB | ||
2089 | select FB_CFB_FILLRECT | ||
2090 | select FB_CFB_COPYAREA | ||
2091 | select FB_CFB_IMAGEBLIT | ||
2092 | ---help--- | ||
2093 | Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. | ||
2094 | |||
2095 | config FB_MB862XX_PCI_GDC | ||
2096 | bool "Carmine/Coral-P(A) GDC" | ||
2097 | depends on PCI && FB_MB862XX | ||
2098 | ---help--- | ||
2099 | This enables framebuffer support for Fujitsu Carmine/Coral-P(A) | ||
2100 | PCI graphics controller devices. | ||
2101 | |||
2102 | config FB_MB862XX_LIME | ||
2103 | bool "Lime GDC" | ||
2104 | depends on FB_MB862XX | ||
2105 | depends on OF && !FB_MB862XX_PCI_GDC | ||
2106 | select FB_FOREIGN_ENDIAN | ||
2107 | select FB_LITTLE_ENDIAN | ||
2108 | ---help--- | ||
2109 | Framebuffer support for Fujitsu Lime GDC on host CPU bus. | ||
2110 | |||
2111 | config FB_PRE_INIT_FB | ||
2112 | bool "Don't reinitialize, use bootloader's GDC/Display configuration" | ||
2113 | depends on FB_MB862XX_LIME | ||
2114 | ---help--- | ||
2115 | Select this option if display contents should be inherited as set by | ||
2116 | the bootloader. | ||
2117 | |||
2086 | source "drivers/video/omap/Kconfig" | 2118 | source "drivers/video/omap/Kconfig" |
2087 | 2119 | ||
2088 | source "drivers/video/backlight/Kconfig" | 2120 | source "drivers/video/backlight/Kconfig" |
diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 248bddc8d0b0..e39e33e797da 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile | |||
@@ -122,6 +122,7 @@ obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o | |||
122 | obj-$(CONFIG_FB_OMAP) += omap/ | 122 | obj-$(CONFIG_FB_OMAP) += omap/ |
123 | obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o | 123 | obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o |
124 | obj-$(CONFIG_FB_CARMINE) += carminefb.o | 124 | obj-$(CONFIG_FB_CARMINE) += carminefb.o |
125 | obj-$(CONFIG_FB_MB862XX) += mb862xx/ | ||
125 | 126 | ||
126 | # Platform or fallback drivers go here | 127 | # Platform or fallback drivers go here |
127 | obj-$(CONFIG_FB_UVESA) += uvesafb.o | 128 | obj-$(CONFIG_FB_UVESA) += uvesafb.o |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 6048b55f2878..1d5ae39cb271 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1002,13 +1002,9 @@ fb_blank(struct fb_info *info, int blank) | |||
1002 | return ret; | 1002 | return ret; |
1003 | } | 1003 | } |
1004 | 1004 | ||
1005 | static long | 1005 | static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, |
1006 | fb_ioctl(struct file *file, unsigned int cmd, | 1006 | unsigned long arg) |
1007 | unsigned long arg) | ||
1008 | { | 1007 | { |
1009 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1010 | int fbidx = iminor(inode); | ||
1011 | struct fb_info *info; | ||
1012 | struct fb_ops *fb; | 1008 | struct fb_ops *fb; |
1013 | struct fb_var_screeninfo var; | 1009 | struct fb_var_screeninfo var; |
1014 | struct fb_fix_screeninfo fix; | 1010 | struct fb_fix_screeninfo fix; |
@@ -1018,14 +1014,10 @@ fb_ioctl(struct file *file, unsigned int cmd, | |||
1018 | void __user *argp = (void __user *)arg; | 1014 | void __user *argp = (void __user *)arg; |
1019 | long ret = 0; | 1015 | long ret = 0; |
1020 | 1016 | ||
1021 | info = registered_fb[fbidx]; | ||
1022 | mutex_lock(&info->lock); | ||
1023 | fb = info->fbops; | 1017 | fb = info->fbops; |
1024 | 1018 | if (!fb) | |
1025 | if (!fb) { | ||
1026 | mutex_unlock(&info->lock); | ||
1027 | return -ENODEV; | 1019 | return -ENODEV; |
1028 | } | 1020 | |
1029 | switch (cmd) { | 1021 | switch (cmd) { |
1030 | case FBIOGET_VSCREENINFO: | 1022 | case FBIOGET_VSCREENINFO: |
1031 | ret = copy_to_user(argp, &info->var, | 1023 | ret = copy_to_user(argp, &info->var, |
@@ -1126,6 +1118,21 @@ fb_ioctl(struct file *file, unsigned int cmd, | |||
1126 | else | 1118 | else |
1127 | ret = fb->fb_ioctl(info, cmd, arg); | 1119 | ret = fb->fb_ioctl(info, cmd, arg); |
1128 | } | 1120 | } |
1121 | return ret; | ||
1122 | } | ||
1123 | |||
1124 | static long fb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
1125 | __acquires(&info->lock) | ||
1126 | __releases(&info->lock) | ||
1127 | { | ||
1128 | struct inode *inode = file->f_path.dentry->d_inode; | ||
1129 | int fbidx = iminor(inode); | ||
1130 | struct fb_info *info; | ||
1131 | long ret; | ||
1132 | |||
1133 | info = registered_fb[fbidx]; | ||
1134 | mutex_lock(&info->lock); | ||
1135 | ret = do_fb_ioctl(info, cmd, arg); | ||
1129 | mutex_unlock(&info->lock); | 1136 | mutex_unlock(&info->lock); |
1130 | return ret; | 1137 | return ret; |
1131 | } | 1138 | } |
@@ -1157,8 +1164,8 @@ struct fb_cmap32 { | |||
1157 | compat_caddr_t transp; | 1164 | compat_caddr_t transp; |
1158 | }; | 1165 | }; |
1159 | 1166 | ||
1160 | static int fb_getput_cmap(struct inode *inode, struct file *file, | 1167 | static int fb_getput_cmap(struct fb_info *info, unsigned int cmd, |
1161 | unsigned int cmd, unsigned long arg) | 1168 | unsigned long arg) |
1162 | { | 1169 | { |
1163 | struct fb_cmap_user __user *cmap; | 1170 | struct fb_cmap_user __user *cmap; |
1164 | struct fb_cmap32 __user *cmap32; | 1171 | struct fb_cmap32 __user *cmap32; |
@@ -1181,7 +1188,7 @@ static int fb_getput_cmap(struct inode *inode, struct file *file, | |||
1181 | put_user(compat_ptr(data), &cmap->transp)) | 1188 | put_user(compat_ptr(data), &cmap->transp)) |
1182 | return -EFAULT; | 1189 | return -EFAULT; |
1183 | 1190 | ||
1184 | err = fb_ioctl(file, cmd, (unsigned long) cmap); | 1191 | err = do_fb_ioctl(info, cmd, (unsigned long) cmap); |
1185 | 1192 | ||
1186 | if (!err) { | 1193 | if (!err) { |
1187 | if (copy_in_user(&cmap32->start, | 1194 | if (copy_in_user(&cmap32->start, |
@@ -1223,8 +1230,8 @@ static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, | |||
1223 | return err; | 1230 | return err; |
1224 | } | 1231 | } |
1225 | 1232 | ||
1226 | static int fb_get_fscreeninfo(struct inode *inode, struct file *file, | 1233 | static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd, |
1227 | unsigned int cmd, unsigned long arg) | 1234 | unsigned long arg) |
1228 | { | 1235 | { |
1229 | mm_segment_t old_fs; | 1236 | mm_segment_t old_fs; |
1230 | struct fb_fix_screeninfo fix; | 1237 | struct fb_fix_screeninfo fix; |
@@ -1235,7 +1242,7 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, | |||
1235 | 1242 | ||
1236 | old_fs = get_fs(); | 1243 | old_fs = get_fs(); |
1237 | set_fs(KERNEL_DS); | 1244 | set_fs(KERNEL_DS); |
1238 | err = fb_ioctl(file, cmd, (unsigned long) &fix); | 1245 | err = do_fb_ioctl(info, cmd, (unsigned long) &fix); |
1239 | set_fs(old_fs); | 1246 | set_fs(old_fs); |
1240 | 1247 | ||
1241 | if (!err) | 1248 | if (!err) |
@@ -1244,8 +1251,10 @@ static int fb_get_fscreeninfo(struct inode *inode, struct file *file, | |||
1244 | return err; | 1251 | return err; |
1245 | } | 1252 | } |
1246 | 1253 | ||
1247 | static long | 1254 | static long fb_compat_ioctl(struct file *file, unsigned int cmd, |
1248 | fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 1255 | unsigned long arg) |
1256 | __acquires(&info->lock) | ||
1257 | __releases(&info->lock) | ||
1249 | { | 1258 | { |
1250 | struct inode *inode = file->f_path.dentry->d_inode; | 1259 | struct inode *inode = file->f_path.dentry->d_inode; |
1251 | int fbidx = iminor(inode); | 1260 | int fbidx = iminor(inode); |
@@ -1262,16 +1271,16 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1262 | case FBIOPUT_CON2FBMAP: | 1271 | case FBIOPUT_CON2FBMAP: |
1263 | arg = (unsigned long) compat_ptr(arg); | 1272 | arg = (unsigned long) compat_ptr(arg); |
1264 | case FBIOBLANK: | 1273 | case FBIOBLANK: |
1265 | mutex_unlock(&info->lock); | 1274 | ret = do_fb_ioctl(info, cmd, arg); |
1266 | return fb_ioctl(file, cmd, arg); | 1275 | break; |
1267 | 1276 | ||
1268 | case FBIOGET_FSCREENINFO: | 1277 | case FBIOGET_FSCREENINFO: |
1269 | ret = fb_get_fscreeninfo(inode, file, cmd, arg); | 1278 | ret = fb_get_fscreeninfo(info, cmd, arg); |
1270 | break; | 1279 | break; |
1271 | 1280 | ||
1272 | case FBIOGETCMAP: | 1281 | case FBIOGETCMAP: |
1273 | case FBIOPUTCMAP: | 1282 | case FBIOPUTCMAP: |
1274 | ret = fb_getput_cmap(inode, file, cmd, arg); | 1283 | ret = fb_getput_cmap(info, cmd, arg); |
1275 | break; | 1284 | break; |
1276 | 1285 | ||
1277 | default: | 1286 | default: |
@@ -1286,6 +1295,8 @@ fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1286 | 1295 | ||
1287 | static int | 1296 | static int |
1288 | fb_mmap(struct file *file, struct vm_area_struct * vma) | 1297 | fb_mmap(struct file *file, struct vm_area_struct * vma) |
1298 | __acquires(&info->lock) | ||
1299 | __releases(&info->lock) | ||
1289 | { | 1300 | { |
1290 | int fbidx = iminor(file->f_path.dentry->d_inode); | 1301 | int fbidx = iminor(file->f_path.dentry->d_inode); |
1291 | struct fb_info *info = registered_fb[fbidx]; | 1302 | struct fb_info *info = registered_fb[fbidx]; |
@@ -1339,6 +1350,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) | |||
1339 | 1350 | ||
1340 | static int | 1351 | static int |
1341 | fb_open(struct inode *inode, struct file *file) | 1352 | fb_open(struct inode *inode, struct file *file) |
1353 | __acquires(&info->lock) | ||
1354 | __releases(&info->lock) | ||
1342 | { | 1355 | { |
1343 | int fbidx = iminor(inode); | 1356 | int fbidx = iminor(inode); |
1344 | struct fb_info *info; | 1357 | struct fb_info *info; |
@@ -1374,6 +1387,8 @@ out: | |||
1374 | 1387 | ||
1375 | static int | 1388 | static int |
1376 | fb_release(struct inode *inode, struct file *file) | 1389 | fb_release(struct inode *inode, struct file *file) |
1390 | __acquires(&info->lock) | ||
1391 | __releases(&info->lock) | ||
1377 | { | 1392 | { |
1378 | struct fb_info * const info = file->private_data; | 1393 | struct fb_info * const info = file->private_data; |
1379 | 1394 | ||
diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/mb862xx/Makefile new file mode 100644 index 000000000000..07664814bb1d --- /dev/null +++ b/drivers/video/mb862xx/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for the MB862xx framebuffer driver | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_FB_MB862XX) := mb862xxfb.o | ||
diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/mb862xx/mb862xx_reg.h new file mode 100644 index 000000000000..2ba65e118500 --- /dev/null +++ b/drivers/video/mb862xx/mb862xx_reg.h | |||
@@ -0,0 +1,138 @@ | |||
1 | /* | ||
2 | * Fujitsu MB862xx Graphics Controller Registers/Bits | ||
3 | */ | ||
4 | |||
5 | #ifndef _MB862XX_REG_H | ||
6 | #define _MB862XX_REG_H | ||
7 | |||
8 | #ifdef MB862XX_MMIO_BOTTOM | ||
9 | #define MB862XX_MMIO_BASE 0x03fc0000 | ||
10 | #else | ||
11 | #define MB862XX_MMIO_BASE 0x01fc0000 | ||
12 | #endif | ||
13 | #define MB862XX_I2C_BASE 0x0000c000 | ||
14 | #define MB862XX_DISP_BASE 0x00010000 | ||
15 | #define MB862XX_CAP_BASE 0x00018000 | ||
16 | #define MB862XX_DRAW_BASE 0x00030000 | ||
17 | #define MB862XX_GEO_BASE 0x00038000 | ||
18 | #define MB862XX_PIO_BASE 0x00038000 | ||
19 | #define MB862XX_MMIO_SIZE 0x40000 | ||
20 | |||
21 | /* Host interface/pio registers */ | ||
22 | #define GC_IST 0x00000020 | ||
23 | #define GC_IMASK 0x00000024 | ||
24 | #define GC_SRST 0x0000002c | ||
25 | #define GC_CCF 0x00000038 | ||
26 | #define GC_CID 0x000000f0 | ||
27 | #define GC_REVISION 0x00000084 | ||
28 | |||
29 | #define GC_CCF_CGE_100 0x00000000 | ||
30 | #define GC_CCF_CGE_133 0x00040000 | ||
31 | #define GC_CCF_CGE_166 0x00080000 | ||
32 | #define GC_CCF_COT_100 0x00000000 | ||
33 | #define GC_CCF_COT_133 0x00010000 | ||
34 | #define GC_CID_CNAME_MSK 0x0000ff00 | ||
35 | #define GC_CID_VERSION_MSK 0x000000ff | ||
36 | |||
37 | /* define enabled interrupts hereby */ | ||
38 | #define GC_INT_EN 0x00000000 | ||
39 | |||
40 | /* Memory interface mode register */ | ||
41 | #define GC_MMR 0x0000fffc | ||
42 | |||
43 | /* Display Controller registers */ | ||
44 | #define GC_DCM0 0x00000000 | ||
45 | #define GC_HTP 0x00000004 | ||
46 | #define GC_HDB_HDP 0x00000008 | ||
47 | #define GC_VSW_HSW_HSP 0x0000000c | ||
48 | #define GC_VTR 0x00000010 | ||
49 | #define GC_VDP_VSP 0x00000014 | ||
50 | #define GC_WY_WX 0x00000018 | ||
51 | #define GC_WH_WW 0x0000001c | ||
52 | #define GC_L0M 0x00000020 | ||
53 | #define GC_L0OA0 0x00000024 | ||
54 | #define GC_L0DA0 0x00000028 | ||
55 | #define GC_L0DY_L0DX 0x0000002c | ||
56 | #define GC_DCM1 0x00000100 | ||
57 | #define GC_L0EM 0x00000110 | ||
58 | #define GC_L0WY_L0WX 0x00000114 | ||
59 | #define GC_L0WH_L0WW 0x00000118 | ||
60 | #define GC_DCM2 0x00000104 | ||
61 | #define GC_DCM3 0x00000108 | ||
62 | #define GC_CPM_CUTC 0x000000a0 | ||
63 | #define GC_CUOA0 0x000000a4 | ||
64 | #define GC_CUY0_CUX0 0x000000a8 | ||
65 | #define GC_CUOA1 0x000000ac | ||
66 | #define GC_CUY1_CUX1 0x000000b0 | ||
67 | #define GC_L0PAL0 0x00000400 | ||
68 | |||
69 | #define GC_CPM_CEN0 0x00100000 | ||
70 | #define GC_CPM_CEN1 0x00200000 | ||
71 | |||
72 | #define GC_DCM01_ESY 0x00000004 | ||
73 | #define GC_DCM01_SC 0x00003f00 | ||
74 | #define GC_DCM01_RESV 0x00004000 | ||
75 | #define GC_DCM01_CKS 0x00008000 | ||
76 | #define GC_DCM01_L0E 0x00010000 | ||
77 | #define GC_DCM01_DEN 0x80000000 | ||
78 | #define GC_L0M_L0C_8 0x00000000 | ||
79 | #define GC_L0M_L0C_16 0x80000000 | ||
80 | #define GC_L0EM_L0EC_24 0x40000000 | ||
81 | #define GC_L0M_L0W_UNIT 64 | ||
82 | |||
83 | #define GC_DISP_REFCLK_400 400 | ||
84 | |||
85 | /* Carmine specific */ | ||
86 | #define MB86297_DRAW_BASE 0x00020000 | ||
87 | #define MB86297_DISP0_BASE 0x00100000 | ||
88 | #define MB86297_DISP1_BASE 0x00140000 | ||
89 | #define MB86297_WRBACK_BASE 0x00180000 | ||
90 | #define MB86297_CAP0_BASE 0x00200000 | ||
91 | #define MB86297_CAP1_BASE 0x00280000 | ||
92 | #define MB86297_DRAMCTRL_BASE 0x00300000 | ||
93 | #define MB86297_CTRL_BASE 0x00400000 | ||
94 | #define MB86297_I2C_BASE 0x00500000 | ||
95 | |||
96 | #define GC_CTRL_STATUS 0x00000000 | ||
97 | #define GC_CTRL_INT_MASK 0x00000004 | ||
98 | #define GC_CTRL_CLK_ENABLE 0x0000000c | ||
99 | #define GC_CTRL_SOFT_RST 0x00000010 | ||
100 | |||
101 | #define GC_CTRL_CLK_EN_DRAM 0x00000001 | ||
102 | #define GC_CTRL_CLK_EN_2D3D 0x00000002 | ||
103 | #define GC_CTRL_CLK_EN_DISP0 0x00000020 | ||
104 | #define GC_CTRL_CLK_EN_DISP1 0x00000040 | ||
105 | |||
106 | #define GC_2D3D_REV 0x000004b4 | ||
107 | #define GC_RE_REVISION 0x24240200 | ||
108 | |||
109 | /* define enabled interrupts hereby */ | ||
110 | #define GC_CARMINE_INT_EN 0x00000004 | ||
111 | |||
112 | /* DRAM controller */ | ||
113 | #define GC_DCTL_MODE_ADD 0x00000000 | ||
114 | #define GC_DCTL_SETTIME1_EMODE 0x00000004 | ||
115 | #define GC_DCTL_REFRESH_SETTIME2 0x00000008 | ||
116 | #define GC_DCTL_RSV0_STATES 0x0000000C | ||
117 | #define GC_DCTL_RSV2_RSV1 0x00000010 | ||
118 | #define GC_DCTL_DDRIF2_DDRIF1 0x00000014 | ||
119 | #define GC_DCTL_IOCONT1_IOCONT0 0x00000024 | ||
120 | |||
121 | #define GC_DCTL_STATES_MSK 0x0000000f | ||
122 | #define GC_DCTL_INIT_WAIT_CNT 3000 | ||
123 | #define GC_DCTL_INIT_WAIT_INTERVAL 1 | ||
124 | |||
125 | /* DRAM ctrl values for Carmine PCI Eval. board */ | ||
126 | #define GC_EVB_DCTL_MODE_ADD 0x012105c3 | ||
127 | #define GC_EVB_DCTL_MODE_ADD_AFT_RST 0x002105c3 | ||
128 | #define GC_EVB_DCTL_SETTIME1_EMODE 0x47498000 | ||
129 | #define GC_EVB_DCTL_REFRESH_SETTIME2 0x00422a22 | ||
130 | #define GC_EVB_DCTL_RSV0_STATES 0x00200003 | ||
131 | #define GC_EVB_DCTL_RSV0_STATES_AFT_RST 0x00200002 | ||
132 | #define GC_EVB_DCTL_RSV2_RSV1 0x0000000f | ||
133 | #define GC_EVB_DCTL_DDRIF2_DDRIF1 0x00556646 | ||
134 | #define GC_EVB_DCTL_IOCONT1_IOCONT0 0x05550555 | ||
135 | |||
136 | #define GC_DISP_REFCLK_533 533 | ||
137 | |||
138 | #endif | ||
diff --git a/drivers/video/mb862xx/mb862xxfb.c b/drivers/video/mb862xx/mb862xxfb.c new file mode 100644 index 000000000000..38718d95fbb9 --- /dev/null +++ b/drivers/video/mb862xx/mb862xxfb.c | |||
@@ -0,0 +1,1061 @@ | |||
1 | /* | ||
2 | * drivers/mb862xx/mb862xxfb.c | ||
3 | * | ||
4 | * Fujitsu Carmine/Coral-P(A)/Lime framebuffer driver | ||
5 | * | ||
6 | * (C) 2008 Anatolij Gustschin <agust@denx.de> | ||
7 | * DENX Software Engineering | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #undef DEBUG | ||
16 | |||
17 | #include <linux/fb.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/pci.h> | ||
22 | #if defined(CONFIG_PPC_OF) | ||
23 | #include <linux/of_platform.h> | ||
24 | #endif | ||
25 | #include "mb862xxfb.h" | ||
26 | #include "mb862xx_reg.h" | ||
27 | |||
28 | #define NR_PALETTE 256 | ||
29 | #define MB862XX_MEM_SIZE 0x1000000 | ||
30 | #define CORALP_MEM_SIZE 0x4000000 | ||
31 | #define CARMINE_MEM_SIZE 0x8000000 | ||
32 | #define DRV_NAME "mb862xxfb" | ||
33 | |||
34 | #if defined(CONFIG_LWMON5) | ||
35 | static struct mb862xx_gc_mode lwmon5_gc_mode = { | ||
36 | /* Mode for Sharp LQ104V1DG61 TFT LCD Panel */ | ||
37 | { "640x480", 60, 640, 480, 40000, 48, 16, 32, 11, 96, 2, 0, 0, 0 }, | ||
38 | /* 16 bits/pixel, 32MB, 100MHz, SDRAM memory mode value */ | ||
39 | 16, 0x2000000, GC_CCF_COT_100, 0x414fb7f2 | ||
40 | }; | ||
41 | #endif | ||
42 | |||
43 | #if defined(CONFIG_SOCRATES) | ||
44 | static struct mb862xx_gc_mode socrates_gc_mode = { | ||
45 | /* Mode for Prime View PM070WL4 TFT LCD Panel */ | ||
46 | { "800x480", 45, 800, 480, 40000, 86, 42, 33, 10, 128, 2, 0, 0, 0 }, | ||
47 | /* 16 bits/pixel, 16MB, 133MHz, SDRAM memory mode value */ | ||
48 | 16, 0x1000000, GC_CCF_COT_133, 0x4157ba63 | ||
49 | }; | ||
50 | #endif | ||
51 | |||
52 | /* Helpers */ | ||
53 | static inline int h_total(struct fb_var_screeninfo *var) | ||
54 | { | ||
55 | return var->xres + var->left_margin + | ||
56 | var->right_margin + var->hsync_len; | ||
57 | } | ||
58 | |||
59 | static inline int v_total(struct fb_var_screeninfo *var) | ||
60 | { | ||
61 | return var->yres + var->upper_margin + | ||
62 | var->lower_margin + var->vsync_len; | ||
63 | } | ||
64 | |||
65 | static inline int hsp(struct fb_var_screeninfo *var) | ||
66 | { | ||
67 | return var->xres + var->right_margin - 1; | ||
68 | } | ||
69 | |||
70 | static inline int vsp(struct fb_var_screeninfo *var) | ||
71 | { | ||
72 | return var->yres + var->lower_margin - 1; | ||
73 | } | ||
74 | |||
75 | static inline int d_pitch(struct fb_var_screeninfo *var) | ||
76 | { | ||
77 | return var->xres * var->bits_per_pixel / 8; | ||
78 | } | ||
79 | |||
80 | static inline unsigned int chan_to_field(unsigned int chan, | ||
81 | struct fb_bitfield *bf) | ||
82 | { | ||
83 | chan &= 0xffff; | ||
84 | chan >>= 16 - bf->length; | ||
85 | return chan << bf->offset; | ||
86 | } | ||
87 | |||
88 | static int mb862xxfb_setcolreg(unsigned regno, | ||
89 | unsigned red, unsigned green, unsigned blue, | ||
90 | unsigned transp, struct fb_info *info) | ||
91 | { | ||
92 | struct mb862xxfb_par *par = info->par; | ||
93 | unsigned int val; | ||
94 | |||
95 | switch (info->fix.visual) { | ||
96 | case FB_VISUAL_TRUECOLOR: | ||
97 | if (regno < 16) { | ||
98 | val = chan_to_field(red, &info->var.red); | ||
99 | val |= chan_to_field(green, &info->var.green); | ||
100 | val |= chan_to_field(blue, &info->var.blue); | ||
101 | par->pseudo_palette[regno] = val; | ||
102 | } | ||
103 | break; | ||
104 | case FB_VISUAL_PSEUDOCOLOR: | ||
105 | if (regno < 256) { | ||
106 | val = (red >> 8) << 16; | ||
107 | val |= (green >> 8) << 8; | ||
108 | val |= blue >> 8; | ||
109 | outreg(disp, GC_L0PAL0 + (regno * 4), val); | ||
110 | } | ||
111 | break; | ||
112 | default: | ||
113 | return 1; /* unsupported type */ | ||
114 | } | ||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int mb862xxfb_check_var(struct fb_var_screeninfo *var, | ||
119 | struct fb_info *fbi) | ||
120 | { | ||
121 | unsigned long tmp; | ||
122 | |||
123 | if (fbi->dev) | ||
124 | dev_dbg(fbi->dev, "%s\n", __func__); | ||
125 | |||
126 | /* check if these values fit into the registers */ | ||
127 | if (var->hsync_len > 255 || var->vsync_len > 255) | ||
128 | return -EINVAL; | ||
129 | |||
130 | if ((var->xres + var->right_margin) >= 4096) | ||
131 | return -EINVAL; | ||
132 | |||
133 | if ((var->yres + var->lower_margin) > 4096) | ||
134 | return -EINVAL; | ||
135 | |||
136 | if (h_total(var) > 4096 || v_total(var) > 4096) | ||
137 | return -EINVAL; | ||
138 | |||
139 | if (var->xres_virtual > 4096 || var->yres_virtual > 4096) | ||
140 | return -EINVAL; | ||
141 | |||
142 | if (var->bits_per_pixel <= 8) | ||
143 | var->bits_per_pixel = 8; | ||
144 | else if (var->bits_per_pixel <= 16) | ||
145 | var->bits_per_pixel = 16; | ||
146 | else if (var->bits_per_pixel <= 32) | ||
147 | var->bits_per_pixel = 32; | ||
148 | |||
149 | /* | ||
150 | * can cope with 8,16 or 24/32bpp if resulting | ||
151 | * pitch is divisible by 64 without remainder | ||
152 | */ | ||
153 | if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) { | ||
154 | int r; | ||
155 | |||
156 | var->bits_per_pixel = 0; | ||
157 | do { | ||
158 | var->bits_per_pixel += 8; | ||
159 | r = d_pitch(&fbi->var) % GC_L0M_L0W_UNIT; | ||
160 | } while (r && var->bits_per_pixel <= 32); | ||
161 | |||
162 | if (d_pitch(&fbi->var) % GC_L0M_L0W_UNIT) | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | /* line length is going to be 128 bit aligned */ | ||
167 | tmp = (var->xres * var->bits_per_pixel) / 8; | ||
168 | if ((tmp & 15) != 0) | ||
169 | return -EINVAL; | ||
170 | |||
171 | /* set r/g/b positions and validate bpp */ | ||
172 | switch (var->bits_per_pixel) { | ||
173 | case 8: | ||
174 | var->red.length = var->bits_per_pixel; | ||
175 | var->green.length = var->bits_per_pixel; | ||
176 | var->blue.length = var->bits_per_pixel; | ||
177 | var->red.offset = 0; | ||
178 | var->green.offset = 0; | ||
179 | var->blue.offset = 0; | ||
180 | var->transp.length = 0; | ||
181 | break; | ||
182 | case 16: | ||
183 | var->red.length = 5; | ||
184 | var->green.length = 5; | ||
185 | var->blue.length = 5; | ||
186 | var->red.offset = 10; | ||
187 | var->green.offset = 5; | ||
188 | var->blue.offset = 0; | ||
189 | var->transp.length = 0; | ||
190 | break; | ||
191 | case 24: | ||
192 | case 32: | ||
193 | var->transp.length = 8; | ||
194 | var->red.length = 8; | ||
195 | var->green.length = 8; | ||
196 | var->blue.length = 8; | ||
197 | var->transp.offset = 24; | ||
198 | var->red.offset = 16; | ||
199 | var->green.offset = 8; | ||
200 | var->blue.offset = 0; | ||
201 | break; | ||
202 | default: | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | /* | ||
209 | * set display parameters | ||
210 | */ | ||
211 | static int mb862xxfb_set_par(struct fb_info *fbi) | ||
212 | { | ||
213 | struct mb862xxfb_par *par = fbi->par; | ||
214 | unsigned long reg, sc; | ||
215 | |||
216 | dev_dbg(par->dev, "%s\n", __func__); | ||
217 | |||
218 | if (par->pre_init) | ||
219 | return 0; | ||
220 | |||
221 | /* disp off */ | ||
222 | reg = inreg(disp, GC_DCM1); | ||
223 | reg &= ~GC_DCM01_DEN; | ||
224 | outreg(disp, GC_DCM1, reg); | ||
225 | |||
226 | /* set display reference clock div. */ | ||
227 | sc = par->refclk / (1000000 / fbi->var.pixclock) - 1; | ||
228 | reg = inreg(disp, GC_DCM1); | ||
229 | reg &= ~(GC_DCM01_CKS | GC_DCM01_RESV | GC_DCM01_SC); | ||
230 | reg |= sc << 8; | ||
231 | outreg(disp, GC_DCM1, reg); | ||
232 | dev_dbg(par->dev, "SC 0x%lx\n", sc); | ||
233 | |||
234 | /* disp dimension, format */ | ||
235 | reg = pack(d_pitch(&fbi->var) / GC_L0M_L0W_UNIT, | ||
236 | (fbi->var.yres - 1)); | ||
237 | if (fbi->var.bits_per_pixel == 16) | ||
238 | reg |= GC_L0M_L0C_16; | ||
239 | outreg(disp, GC_L0M, reg); | ||
240 | |||
241 | if (fbi->var.bits_per_pixel == 32) { | ||
242 | reg = inreg(disp, GC_L0EM); | ||
243 | outreg(disp, GC_L0EM, reg | GC_L0EM_L0EC_24); | ||
244 | } | ||
245 | outreg(disp, GC_WY_WX, 0); | ||
246 | reg = pack(fbi->var.yres - 1, fbi->var.xres); | ||
247 | outreg(disp, GC_WH_WW, reg); | ||
248 | outreg(disp, GC_L0OA0, 0); | ||
249 | outreg(disp, GC_L0DA0, 0); | ||
250 | outreg(disp, GC_L0DY_L0DX, 0); | ||
251 | outreg(disp, GC_L0WY_L0WX, 0); | ||
252 | outreg(disp, GC_L0WH_L0WW, reg); | ||
253 | |||
254 | /* both HW-cursors off */ | ||
255 | reg = inreg(disp, GC_CPM_CUTC); | ||
256 | reg &= ~(GC_CPM_CEN0 | GC_CPM_CEN1); | ||
257 | outreg(disp, GC_CPM_CUTC, reg); | ||
258 | |||
259 | /* timings */ | ||
260 | reg = pack(fbi->var.xres - 1, fbi->var.xres - 1); | ||
261 | outreg(disp, GC_HDB_HDP, reg); | ||
262 | reg = pack((fbi->var.yres - 1), vsp(&fbi->var)); | ||
263 | outreg(disp, GC_VDP_VSP, reg); | ||
264 | reg = ((fbi->var.vsync_len - 1) << 24) | | ||
265 | pack((fbi->var.hsync_len - 1), hsp(&fbi->var)); | ||
266 | outreg(disp, GC_VSW_HSW_HSP, reg); | ||
267 | outreg(disp, GC_HTP, pack(h_total(&fbi->var) - 1, 0)); | ||
268 | outreg(disp, GC_VTR, pack(v_total(&fbi->var) - 1, 0)); | ||
269 | |||
270 | /* display on */ | ||
271 | reg = inreg(disp, GC_DCM1); | ||
272 | reg |= GC_DCM01_DEN | GC_DCM01_L0E; | ||
273 | reg &= ~GC_DCM01_ESY; | ||
274 | outreg(disp, GC_DCM1, reg); | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int mb862xxfb_pan(struct fb_var_screeninfo *var, | ||
279 | struct fb_info *info) | ||
280 | { | ||
281 | struct mb862xxfb_par *par = info->par; | ||
282 | unsigned long reg; | ||
283 | |||
284 | reg = pack(var->yoffset, var->xoffset); | ||
285 | outreg(disp, GC_L0WY_L0WX, reg); | ||
286 | |||
287 | reg = pack(var->yres_virtual, var->xres_virtual); | ||
288 | outreg(disp, GC_L0WH_L0WW, reg); | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int mb862xxfb_blank(int mode, struct fb_info *fbi) | ||
293 | { | ||
294 | struct mb862xxfb_par *par = fbi->par; | ||
295 | unsigned long reg; | ||
296 | |||
297 | dev_dbg(fbi->dev, "blank mode=%d\n", mode); | ||
298 | |||
299 | switch (mode) { | ||
300 | case FB_BLANK_POWERDOWN: | ||
301 | reg = inreg(disp, GC_DCM1); | ||
302 | reg &= ~GC_DCM01_DEN; | ||
303 | outreg(disp, GC_DCM1, reg); | ||
304 | break; | ||
305 | case FB_BLANK_UNBLANK: | ||
306 | reg = inreg(disp, GC_DCM1); | ||
307 | reg |= GC_DCM01_DEN; | ||
308 | outreg(disp, GC_DCM1, reg); | ||
309 | break; | ||
310 | case FB_BLANK_NORMAL: | ||
311 | case FB_BLANK_VSYNC_SUSPEND: | ||
312 | case FB_BLANK_HSYNC_SUSPEND: | ||
313 | default: | ||
314 | return 1; | ||
315 | } | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | /* framebuffer ops */ | ||
320 | static struct fb_ops mb862xxfb_ops = { | ||
321 | .owner = THIS_MODULE, | ||
322 | .fb_check_var = mb862xxfb_check_var, | ||
323 | .fb_set_par = mb862xxfb_set_par, | ||
324 | .fb_setcolreg = mb862xxfb_setcolreg, | ||
325 | .fb_blank = mb862xxfb_blank, | ||
326 | .fb_pan_display = mb862xxfb_pan, | ||
327 | .fb_fillrect = cfb_fillrect, | ||
328 | .fb_copyarea = cfb_copyarea, | ||
329 | .fb_imageblit = cfb_imageblit, | ||
330 | }; | ||
331 | |||
332 | /* initialize fb_info data */ | ||
333 | static int mb862xxfb_init_fbinfo(struct fb_info *fbi) | ||
334 | { | ||
335 | struct mb862xxfb_par *par = fbi->par; | ||
336 | struct mb862xx_gc_mode *mode = par->gc_mode; | ||
337 | unsigned long reg; | ||
338 | |||
339 | fbi->fbops = &mb862xxfb_ops; | ||
340 | fbi->pseudo_palette = par->pseudo_palette; | ||
341 | fbi->screen_base = par->fb_base; | ||
342 | fbi->screen_size = par->mapped_vram; | ||
343 | |||
344 | strcpy(fbi->fix.id, DRV_NAME); | ||
345 | fbi->fix.smem_start = (unsigned long)par->fb_base_phys; | ||
346 | fbi->fix.smem_len = par->mapped_vram; | ||
347 | fbi->fix.mmio_start = (unsigned long)par->mmio_base_phys; | ||
348 | fbi->fix.mmio_len = par->mmio_len; | ||
349 | fbi->fix.accel = FB_ACCEL_NONE; | ||
350 | fbi->fix.type = FB_TYPE_PACKED_PIXELS; | ||
351 | fbi->fix.type_aux = 0; | ||
352 | fbi->fix.xpanstep = 1; | ||
353 | fbi->fix.ypanstep = 1; | ||
354 | fbi->fix.ywrapstep = 0; | ||
355 | |||
356 | reg = inreg(disp, GC_DCM1); | ||
357 | if (reg & GC_DCM01_DEN && reg & GC_DCM01_L0E) { | ||
358 | /* get the disp mode from active display cfg */ | ||
359 | unsigned long sc = ((reg & GC_DCM01_SC) >> 8) + 1; | ||
360 | unsigned long hsp, vsp, ht, vt; | ||
361 | |||
362 | dev_dbg(par->dev, "using bootloader's disp. mode\n"); | ||
363 | fbi->var.pixclock = (sc * 1000000) / par->refclk; | ||
364 | fbi->var.xres = (inreg(disp, GC_HDB_HDP) & 0x0fff) + 1; | ||
365 | reg = inreg(disp, GC_VDP_VSP); | ||
366 | fbi->var.yres = ((reg >> 16) & 0x0fff) + 1; | ||
367 | vsp = (reg & 0x0fff) + 1; | ||
368 | fbi->var.xres_virtual = fbi->var.xres; | ||
369 | fbi->var.yres_virtual = fbi->var.yres; | ||
370 | reg = inreg(disp, GC_L0EM); | ||
371 | if (reg & GC_L0EM_L0EC_24) { | ||
372 | fbi->var.bits_per_pixel = 32; | ||
373 | } else { | ||
374 | reg = inreg(disp, GC_L0M); | ||
375 | if (reg & GC_L0M_L0C_16) | ||
376 | fbi->var.bits_per_pixel = 16; | ||
377 | else | ||
378 | fbi->var.bits_per_pixel = 8; | ||
379 | } | ||
380 | reg = inreg(disp, GC_VSW_HSW_HSP); | ||
381 | fbi->var.hsync_len = ((reg & 0xff0000) >> 16) + 1; | ||
382 | fbi->var.vsync_len = ((reg & 0x3f000000) >> 24) + 1; | ||
383 | hsp = (reg & 0xffff) + 1; | ||
384 | ht = ((inreg(disp, GC_HTP) & 0xfff0000) >> 16) + 1; | ||
385 | fbi->var.right_margin = hsp - fbi->var.xres; | ||
386 | fbi->var.left_margin = ht - hsp - fbi->var.hsync_len; | ||
387 | vt = ((inreg(disp, GC_VTR) & 0xfff0000) >> 16) + 1; | ||
388 | fbi->var.lower_margin = vsp - fbi->var.yres; | ||
389 | fbi->var.upper_margin = vt - vsp - fbi->var.vsync_len; | ||
390 | } else if (mode) { | ||
391 | dev_dbg(par->dev, "using supplied mode\n"); | ||
392 | fb_videomode_to_var(&fbi->var, (struct fb_videomode *)mode); | ||
393 | fbi->var.bits_per_pixel = mode->def_bpp ? mode->def_bpp : 8; | ||
394 | } else { | ||
395 | int ret; | ||
396 | |||
397 | ret = fb_find_mode(&fbi->var, fbi, "640x480-16@60", | ||
398 | NULL, 0, NULL, 16); | ||
399 | if (ret == 0 || ret == 4) { | ||
400 | dev_err(par->dev, | ||
401 | "failed to get initial mode\n"); | ||
402 | return -EINVAL; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | fbi->var.xoffset = 0; | ||
407 | fbi->var.yoffset = 0; | ||
408 | fbi->var.grayscale = 0; | ||
409 | fbi->var.nonstd = 0; | ||
410 | fbi->var.height = -1; | ||
411 | fbi->var.width = -1; | ||
412 | fbi->var.accel_flags = 0; | ||
413 | fbi->var.vmode = FB_VMODE_NONINTERLACED; | ||
414 | fbi->var.activate = FB_ACTIVATE_NOW; | ||
415 | fbi->flags = FBINFO_DEFAULT | | ||
416 | #ifdef __BIG_ENDIAN | ||
417 | FBINFO_FOREIGN_ENDIAN | | ||
418 | #endif | ||
419 | FBINFO_HWACCEL_XPAN | | ||
420 | FBINFO_HWACCEL_YPAN; | ||
421 | |||
422 | /* check and possibly fix bpp */ | ||
423 | if ((fbi->fbops->fb_check_var)(&fbi->var, fbi)) | ||
424 | dev_err(par->dev, "check_var() failed on initial setup?\n"); | ||
425 | |||
426 | fbi->fix.visual = fbi->var.bits_per_pixel == 8 ? | ||
427 | FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR; | ||
428 | fbi->fix.line_length = (fbi->var.xres_virtual * | ||
429 | fbi->var.bits_per_pixel) / 8; | ||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | /* | ||
434 | * show some display controller and cursor registers | ||
435 | */ | ||
436 | static ssize_t mb862xxfb_show_dispregs(struct device *dev, | ||
437 | struct device_attribute *attr, char *buf) | ||
438 | { | ||
439 | struct fb_info *fbi = dev_get_drvdata(dev); | ||
440 | struct mb862xxfb_par *par = fbi->par; | ||
441 | char *ptr = buf; | ||
442 | unsigned int reg; | ||
443 | |||
444 | for (reg = GC_DCM0; reg <= GC_L0DY_L0DX; reg += 4) | ||
445 | ptr += sprintf(ptr, "%08x = %08x\n", | ||
446 | reg, inreg(disp, reg)); | ||
447 | |||
448 | for (reg = GC_CPM_CUTC; reg <= GC_CUY1_CUX1; reg += 4) | ||
449 | ptr += sprintf(ptr, "%08x = %08x\n", | ||
450 | reg, inreg(disp, reg)); | ||
451 | |||
452 | for (reg = GC_DCM1; reg <= GC_L0WH_L0WW; reg += 4) | ||
453 | ptr += sprintf(ptr, "%08x = %08x\n", | ||
454 | reg, inreg(disp, reg)); | ||
455 | |||
456 | return ptr - buf; | ||
457 | } | ||
458 | |||
459 | static DEVICE_ATTR(dispregs, 0444, mb862xxfb_show_dispregs, NULL); | ||
460 | |||
461 | irqreturn_t mb862xx_intr(int irq, void *dev_id) | ||
462 | { | ||
463 | struct mb862xxfb_par *par = (struct mb862xxfb_par *) dev_id; | ||
464 | unsigned long reg_ist, mask; | ||
465 | |||
466 | if (!par) | ||
467 | return IRQ_NONE; | ||
468 | |||
469 | if (par->type == BT_CARMINE) { | ||
470 | /* Get Interrupt Status */ | ||
471 | reg_ist = inreg(ctrl, GC_CTRL_STATUS); | ||
472 | mask = inreg(ctrl, GC_CTRL_INT_MASK); | ||
473 | if (reg_ist == 0) | ||
474 | return IRQ_HANDLED; | ||
475 | |||
476 | reg_ist &= mask; | ||
477 | if (reg_ist == 0) | ||
478 | return IRQ_HANDLED; | ||
479 | |||
480 | /* Clear interrupt status */ | ||
481 | outreg(ctrl, 0x0, reg_ist); | ||
482 | } else { | ||
483 | /* Get status */ | ||
484 | reg_ist = inreg(host, GC_IST); | ||
485 | mask = inreg(host, GC_IMASK); | ||
486 | |||
487 | reg_ist &= mask; | ||
488 | if (reg_ist == 0) | ||
489 | return IRQ_HANDLED; | ||
490 | |||
491 | /* Clear status */ | ||
492 | outreg(host, GC_IST, ~reg_ist); | ||
493 | } | ||
494 | return IRQ_HANDLED; | ||
495 | } | ||
496 | |||
497 | #if defined(CONFIG_FB_MB862XX_LIME) | ||
498 | /* | ||
499 | * GDC (Lime, Coral(B/Q), Mint, ...) on host bus | ||
500 | */ | ||
501 | static int mb862xx_gdc_init(struct mb862xxfb_par *par) | ||
502 | { | ||
503 | unsigned long ccf, mmr; | ||
504 | unsigned long ver, rev; | ||
505 | |||
506 | if (!par) | ||
507 | return -ENODEV; | ||
508 | |||
509 | #if defined(CONFIG_FB_PRE_INIT_FB) | ||
510 | par->pre_init = 1; | ||
511 | #endif | ||
512 | par->host = par->mmio_base; | ||
513 | par->i2c = par->mmio_base + MB862XX_I2C_BASE; | ||
514 | par->disp = par->mmio_base + MB862XX_DISP_BASE; | ||
515 | par->cap = par->mmio_base + MB862XX_CAP_BASE; | ||
516 | par->draw = par->mmio_base + MB862XX_DRAW_BASE; | ||
517 | par->geo = par->mmio_base + MB862XX_GEO_BASE; | ||
518 | par->pio = par->mmio_base + MB862XX_PIO_BASE; | ||
519 | |||
520 | par->refclk = GC_DISP_REFCLK_400; | ||
521 | |||
522 | ver = inreg(host, GC_CID); | ||
523 | rev = inreg(pio, GC_REVISION); | ||
524 | if ((ver == 0x303) && (rev & 0xffffff00) == 0x20050100) { | ||
525 | dev_info(par->dev, "Fujitsu Lime v1.%d found\n", | ||
526 | (int)rev & 0xff); | ||
527 | par->type = BT_LIME; | ||
528 | ccf = par->gc_mode ? par->gc_mode->ccf : GC_CCF_COT_100; | ||
529 | mmr = par->gc_mode ? par->gc_mode->mmr : 0x414fb7f2; | ||
530 | } else { | ||
531 | dev_info(par->dev, "? GDC, CID/Rev.: 0x%lx/0x%lx \n", ver, rev); | ||
532 | return -ENODEV; | ||
533 | } | ||
534 | |||
535 | if (!par->pre_init) { | ||
536 | outreg(host, GC_CCF, ccf); | ||
537 | udelay(200); | ||
538 | outreg(host, GC_MMR, mmr); | ||
539 | udelay(10); | ||
540 | } | ||
541 | |||
542 | /* interrupt status */ | ||
543 | outreg(host, GC_IST, 0); | ||
544 | outreg(host, GC_IMASK, GC_INT_EN); | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static int __devinit of_platform_mb862xx_probe(struct of_device *ofdev, | ||
549 | const struct of_device_id *id) | ||
550 | { | ||
551 | struct device_node *np = ofdev->node; | ||
552 | struct device *dev = &ofdev->dev; | ||
553 | struct mb862xxfb_par *par; | ||
554 | struct fb_info *info; | ||
555 | struct resource res; | ||
556 | resource_size_t res_size; | ||
557 | unsigned long ret = -ENODEV; | ||
558 | |||
559 | if (of_address_to_resource(np, 0, &res)) { | ||
560 | dev_err(dev, "Invalid address\n"); | ||
561 | return -ENXIO; | ||
562 | } | ||
563 | |||
564 | info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); | ||
565 | if (info == NULL) { | ||
566 | dev_err(dev, "cannot allocate framebuffer\n"); | ||
567 | return -ENOMEM; | ||
568 | } | ||
569 | |||
570 | par = info->par; | ||
571 | par->info = info; | ||
572 | par->dev = dev; | ||
573 | |||
574 | par->irq = irq_of_parse_and_map(np, 0); | ||
575 | if (par->irq == NO_IRQ) { | ||
576 | dev_err(dev, "failed to map irq\n"); | ||
577 | ret = -ENODEV; | ||
578 | goto fbrel; | ||
579 | } | ||
580 | |||
581 | res_size = 1 + res.end - res.start; | ||
582 | par->res = request_mem_region(res.start, res_size, DRV_NAME); | ||
583 | if (par->res == NULL) { | ||
584 | dev_err(dev, "Cannot claim framebuffer/mmio\n"); | ||
585 | ret = -ENXIO; | ||
586 | goto irqdisp; | ||
587 | } | ||
588 | |||
589 | #if defined(CONFIG_LWMON5) | ||
590 | par->gc_mode = &lwmon5_gc_mode; | ||
591 | #endif | ||
592 | |||
593 | #if defined(CONFIG_SOCRATES) | ||
594 | par->gc_mode = &socrates_gc_mode; | ||
595 | #endif | ||
596 | |||
597 | par->fb_base_phys = res.start; | ||
598 | par->mmio_base_phys = res.start + MB862XX_MMIO_BASE; | ||
599 | par->mmio_len = MB862XX_MMIO_SIZE; | ||
600 | if (par->gc_mode) | ||
601 | par->mapped_vram = par->gc_mode->max_vram; | ||
602 | else | ||
603 | par->mapped_vram = MB862XX_MEM_SIZE; | ||
604 | |||
605 | par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); | ||
606 | if (par->fb_base == NULL) { | ||
607 | dev_err(dev, "Cannot map framebuffer\n"); | ||
608 | goto rel_reg; | ||
609 | } | ||
610 | |||
611 | par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); | ||
612 | if (par->mmio_base == NULL) { | ||
613 | dev_err(dev, "Cannot map registers\n"); | ||
614 | goto fb_unmap; | ||
615 | } | ||
616 | |||
617 | dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", | ||
618 | (u64)par->fb_base_phys, (ulong)par->mapped_vram); | ||
619 | dev_dbg(dev, "mmio phys 0x%llx 0x%lx, (irq = %d)\n", | ||
620 | (u64)par->mmio_base_phys, (ulong)par->mmio_len, par->irq); | ||
621 | |||
622 | if (mb862xx_gdc_init(par)) | ||
623 | goto io_unmap; | ||
624 | |||
625 | if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED, | ||
626 | DRV_NAME, (void *)par)) { | ||
627 | dev_err(dev, "Cannot request irq\n"); | ||
628 | goto io_unmap; | ||
629 | } | ||
630 | |||
631 | mb862xxfb_init_fbinfo(info); | ||
632 | |||
633 | if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { | ||
634 | dev_err(dev, "Could not allocate cmap for fb_info.\n"); | ||
635 | goto free_irq; | ||
636 | } | ||
637 | |||
638 | if ((info->fbops->fb_set_par)(info)) | ||
639 | dev_err(dev, "set_var() failed on initial setup?\n"); | ||
640 | |||
641 | if (register_framebuffer(info)) { | ||
642 | dev_err(dev, "failed to register framebuffer\n"); | ||
643 | goto rel_cmap; | ||
644 | } | ||
645 | |||
646 | dev_set_drvdata(dev, info); | ||
647 | |||
648 | if (device_create_file(dev, &dev_attr_dispregs)) | ||
649 | dev_err(dev, "Can't create sysfs regdump file\n"); | ||
650 | return 0; | ||
651 | |||
652 | rel_cmap: | ||
653 | fb_dealloc_cmap(&info->cmap); | ||
654 | free_irq: | ||
655 | outreg(host, GC_IMASK, 0); | ||
656 | free_irq(par->irq, (void *)par); | ||
657 | io_unmap: | ||
658 | iounmap(par->mmio_base); | ||
659 | fb_unmap: | ||
660 | iounmap(par->fb_base); | ||
661 | rel_reg: | ||
662 | release_mem_region(res.start, res_size); | ||
663 | irqdisp: | ||
664 | irq_dispose_mapping(par->irq); | ||
665 | fbrel: | ||
666 | dev_set_drvdata(dev, NULL); | ||
667 | framebuffer_release(info); | ||
668 | return ret; | ||
669 | } | ||
670 | |||
671 | static int __devexit of_platform_mb862xx_remove(struct of_device *ofdev) | ||
672 | { | ||
673 | struct fb_info *fbi = dev_get_drvdata(&ofdev->dev); | ||
674 | struct mb862xxfb_par *par = fbi->par; | ||
675 | resource_size_t res_size = 1 + par->res->end - par->res->start; | ||
676 | unsigned long reg; | ||
677 | |||
678 | dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); | ||
679 | |||
680 | /* display off */ | ||
681 | reg = inreg(disp, GC_DCM1); | ||
682 | reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); | ||
683 | outreg(disp, GC_DCM1, reg); | ||
684 | |||
685 | /* disable interrupts */ | ||
686 | outreg(host, GC_IMASK, 0); | ||
687 | |||
688 | free_irq(par->irq, (void *)par); | ||
689 | irq_dispose_mapping(par->irq); | ||
690 | |||
691 | device_remove_file(&ofdev->dev, &dev_attr_dispregs); | ||
692 | |||
693 | unregister_framebuffer(fbi); | ||
694 | fb_dealloc_cmap(&fbi->cmap); | ||
695 | |||
696 | iounmap(par->mmio_base); | ||
697 | iounmap(par->fb_base); | ||
698 | |||
699 | dev_set_drvdata(&ofdev->dev, NULL); | ||
700 | release_mem_region(par->res->start, res_size); | ||
701 | framebuffer_release(fbi); | ||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | /* | ||
706 | * common types | ||
707 | */ | ||
708 | static struct of_device_id __devinitdata of_platform_mb862xx_tbl[] = { | ||
709 | { .compatible = "fujitsu,MB86276", }, | ||
710 | { .compatible = "fujitsu,lime", }, | ||
711 | { .compatible = "fujitsu,MB86277", }, | ||
712 | { .compatible = "fujitsu,mint", }, | ||
713 | { .compatible = "fujitsu,MB86293", }, | ||
714 | { .compatible = "fujitsu,MB86294", }, | ||
715 | { .compatible = "fujitsu,coral", }, | ||
716 | { /* end */ } | ||
717 | }; | ||
718 | |||
719 | static struct of_platform_driver of_platform_mb862xxfb_driver = { | ||
720 | .owner = THIS_MODULE, | ||
721 | .name = DRV_NAME, | ||
722 | .match_table = of_platform_mb862xx_tbl, | ||
723 | .probe = of_platform_mb862xx_probe, | ||
724 | .remove = __devexit_p(of_platform_mb862xx_remove), | ||
725 | }; | ||
726 | #endif | ||
727 | |||
728 | #if defined(CONFIG_FB_MB862XX_PCI_GDC) | ||
729 | static int coralp_init(struct mb862xxfb_par *par) | ||
730 | { | ||
731 | int cn, ver; | ||
732 | |||
733 | par->host = par->mmio_base; | ||
734 | par->i2c = par->mmio_base + MB862XX_I2C_BASE; | ||
735 | par->disp = par->mmio_base + MB862XX_DISP_BASE; | ||
736 | par->cap = par->mmio_base + MB862XX_CAP_BASE; | ||
737 | par->draw = par->mmio_base + MB862XX_DRAW_BASE; | ||
738 | par->geo = par->mmio_base + MB862XX_GEO_BASE; | ||
739 | par->pio = par->mmio_base + MB862XX_PIO_BASE; | ||
740 | |||
741 | par->refclk = GC_DISP_REFCLK_400; | ||
742 | |||
743 | ver = inreg(host, GC_CID); | ||
744 | cn = (ver & GC_CID_CNAME_MSK) >> 8; | ||
745 | ver = ver & GC_CID_VERSION_MSK; | ||
746 | if (cn == 3) { | ||
747 | dev_info(par->dev, "Fujitsu Coral-%s GDC Rev.%d found\n",\ | ||
748 | (ver == 6) ? "P" : (ver == 8) ? "PA" : "?", | ||
749 | par->pdev->revision); | ||
750 | outreg(host, GC_CCF, GC_CCF_CGE_166 | GC_CCF_COT_133); | ||
751 | udelay(200); | ||
752 | outreg(host, GC_MMR, GC_MMR_CORALP_EVB_VAL); | ||
753 | udelay(10); | ||
754 | /* Clear interrupt status */ | ||
755 | outreg(host, GC_IST, 0); | ||
756 | } else { | ||
757 | return -ENODEV; | ||
758 | } | ||
759 | return 0; | ||
760 | } | ||
761 | |||
762 | static int init_dram_ctrl(struct mb862xxfb_par *par) | ||
763 | { | ||
764 | unsigned long i = 0; | ||
765 | |||
766 | /* | ||
767 | * Set io mode first! Spec. says IC may be destroyed | ||
768 | * if not set to SSTL2/LVCMOS before init. | ||
769 | */ | ||
770 | outreg(dram_ctrl, GC_DCTL_IOCONT1_IOCONT0, GC_EVB_DCTL_IOCONT1_IOCONT0); | ||
771 | |||
772 | /* DRAM init */ | ||
773 | outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD); | ||
774 | outreg(dram_ctrl, GC_DCTL_SETTIME1_EMODE, GC_EVB_DCTL_SETTIME1_EMODE); | ||
775 | outreg(dram_ctrl, GC_DCTL_REFRESH_SETTIME2, | ||
776 | GC_EVB_DCTL_REFRESH_SETTIME2); | ||
777 | outreg(dram_ctrl, GC_DCTL_RSV2_RSV1, GC_EVB_DCTL_RSV2_RSV1); | ||
778 | outreg(dram_ctrl, GC_DCTL_DDRIF2_DDRIF1, GC_EVB_DCTL_DDRIF2_DDRIF1); | ||
779 | outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES); | ||
780 | |||
781 | /* DLL reset done? */ | ||
782 | while ((inreg(dram_ctrl, GC_DCTL_RSV0_STATES) & GC_DCTL_STATES_MSK)) { | ||
783 | udelay(GC_DCTL_INIT_WAIT_INTERVAL); | ||
784 | if (i++ > GC_DCTL_INIT_WAIT_CNT) { | ||
785 | dev_err(par->dev, "VRAM init failed.\n"); | ||
786 | return -EINVAL; | ||
787 | } | ||
788 | } | ||
789 | outreg(dram_ctrl, GC_DCTL_MODE_ADD, GC_EVB_DCTL_MODE_ADD_AFT_RST); | ||
790 | outreg(dram_ctrl, GC_DCTL_RSV0_STATES, GC_EVB_DCTL_RSV0_STATES_AFT_RST); | ||
791 | return 0; | ||
792 | } | ||
793 | |||
794 | static int carmine_init(struct mb862xxfb_par *par) | ||
795 | { | ||
796 | unsigned long reg; | ||
797 | |||
798 | par->ctrl = par->mmio_base + MB86297_CTRL_BASE; | ||
799 | par->i2c = par->mmio_base + MB86297_I2C_BASE; | ||
800 | par->disp = par->mmio_base + MB86297_DISP0_BASE; | ||
801 | par->disp1 = par->mmio_base + MB86297_DISP1_BASE; | ||
802 | par->cap = par->mmio_base + MB86297_CAP0_BASE; | ||
803 | par->cap1 = par->mmio_base + MB86297_CAP1_BASE; | ||
804 | par->draw = par->mmio_base + MB86297_DRAW_BASE; | ||
805 | par->dram_ctrl = par->mmio_base + MB86297_DRAMCTRL_BASE; | ||
806 | par->wrback = par->mmio_base + MB86297_WRBACK_BASE; | ||
807 | |||
808 | par->refclk = GC_DISP_REFCLK_533; | ||
809 | |||
810 | /* warm up */ | ||
811 | reg = GC_CTRL_CLK_EN_DRAM | GC_CTRL_CLK_EN_2D3D | GC_CTRL_CLK_EN_DISP0; | ||
812 | outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); | ||
813 | |||
814 | /* check for engine module revision */ | ||
815 | if (inreg(draw, GC_2D3D_REV) == GC_RE_REVISION) | ||
816 | dev_info(par->dev, "Fujitsu Carmine GDC Rev.%d found\n", | ||
817 | par->pdev->revision); | ||
818 | else | ||
819 | goto err_init; | ||
820 | |||
821 | reg &= ~GC_CTRL_CLK_EN_2D3D; | ||
822 | outreg(ctrl, GC_CTRL_CLK_ENABLE, reg); | ||
823 | |||
824 | /* set up vram */ | ||
825 | if (init_dram_ctrl(par) < 0) | ||
826 | goto err_init; | ||
827 | |||
828 | outreg(ctrl, GC_CTRL_INT_MASK, 0); | ||
829 | return 0; | ||
830 | |||
831 | err_init: | ||
832 | outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); | ||
833 | return -EINVAL; | ||
834 | } | ||
835 | |||
836 | static inline int mb862xx_pci_gdc_init(struct mb862xxfb_par *par) | ||
837 | { | ||
838 | switch (par->type) { | ||
839 | case BT_CORALP: | ||
840 | return coralp_init(par); | ||
841 | case BT_CARMINE: | ||
842 | return carmine_init(par); | ||
843 | default: | ||
844 | return -ENODEV; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | #define CHIP_ID(id) \ | ||
849 | { PCI_DEVICE(PCI_VENDOR_ID_FUJITSU_LIMITED, id) } | ||
850 | |||
851 | static struct pci_device_id mb862xx_pci_tbl[] __devinitdata = { | ||
852 | /* MB86295/MB86296 */ | ||
853 | CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALP), | ||
854 | CHIP_ID(PCI_DEVICE_ID_FUJITSU_CORALPA), | ||
855 | /* MB86297 */ | ||
856 | CHIP_ID(PCI_DEVICE_ID_FUJITSU_CARMINE), | ||
857 | { 0, } | ||
858 | }; | ||
859 | |||
860 | MODULE_DEVICE_TABLE(pci, mb862xx_pci_tbl); | ||
861 | |||
862 | static int __devinit mb862xx_pci_probe(struct pci_dev *pdev, | ||
863 | const struct pci_device_id *ent) | ||
864 | { | ||
865 | struct mb862xxfb_par *par; | ||
866 | struct fb_info *info; | ||
867 | struct device *dev = &pdev->dev; | ||
868 | int ret; | ||
869 | |||
870 | ret = pci_enable_device(pdev); | ||
871 | if (ret < 0) { | ||
872 | dev_err(dev, "Cannot enable PCI device\n"); | ||
873 | goto out; | ||
874 | } | ||
875 | |||
876 | info = framebuffer_alloc(sizeof(struct mb862xxfb_par), dev); | ||
877 | if (!info) { | ||
878 | dev_err(dev, "framebuffer alloc failed\n"); | ||
879 | ret = -ENOMEM; | ||
880 | goto dis_dev; | ||
881 | } | ||
882 | |||
883 | par = info->par; | ||
884 | par->info = info; | ||
885 | par->dev = dev; | ||
886 | par->pdev = pdev; | ||
887 | par->irq = pdev->irq; | ||
888 | |||
889 | ret = pci_request_regions(pdev, DRV_NAME); | ||
890 | if (ret < 0) { | ||
891 | dev_err(dev, "Cannot reserve region(s) for PCI device\n"); | ||
892 | goto rel_fb; | ||
893 | } | ||
894 | |||
895 | switch (pdev->device) { | ||
896 | case PCI_DEVICE_ID_FUJITSU_CORALP: | ||
897 | case PCI_DEVICE_ID_FUJITSU_CORALPA: | ||
898 | par->fb_base_phys = pci_resource_start(par->pdev, 0); | ||
899 | par->mapped_vram = CORALP_MEM_SIZE; | ||
900 | par->mmio_base_phys = par->fb_base_phys + MB862XX_MMIO_BASE; | ||
901 | par->mmio_len = MB862XX_MMIO_SIZE; | ||
902 | par->type = BT_CORALP; | ||
903 | break; | ||
904 | case PCI_DEVICE_ID_FUJITSU_CARMINE: | ||
905 | par->fb_base_phys = pci_resource_start(par->pdev, 2); | ||
906 | par->mmio_base_phys = pci_resource_start(par->pdev, 3); | ||
907 | par->mmio_len = pci_resource_len(par->pdev, 3); | ||
908 | par->mapped_vram = CARMINE_MEM_SIZE; | ||
909 | par->type = BT_CARMINE; | ||
910 | break; | ||
911 | default: | ||
912 | /* should never occur */ | ||
913 | goto rel_reg; | ||
914 | } | ||
915 | |||
916 | par->fb_base = ioremap(par->fb_base_phys, par->mapped_vram); | ||
917 | if (par->fb_base == NULL) { | ||
918 | dev_err(dev, "Cannot map framebuffer\n"); | ||
919 | goto rel_reg; | ||
920 | } | ||
921 | |||
922 | par->mmio_base = ioremap(par->mmio_base_phys, par->mmio_len); | ||
923 | if (par->mmio_base == NULL) { | ||
924 | dev_err(dev, "Cannot map registers\n"); | ||
925 | ret = -EIO; | ||
926 | goto fb_unmap; | ||
927 | } | ||
928 | |||
929 | dev_dbg(dev, "fb phys 0x%llx 0x%lx\n", | ||
930 | (u64)par->fb_base_phys, (ulong)par->mapped_vram); | ||
931 | dev_dbg(dev, "mmio phys 0x%llx 0x%lx\n", | ||
932 | (u64)par->mmio_base_phys, (ulong)par->mmio_len); | ||
933 | |||
934 | if (mb862xx_pci_gdc_init(par)) | ||
935 | goto io_unmap; | ||
936 | |||
937 | if (request_irq(par->irq, mb862xx_intr, IRQF_DISABLED | IRQF_SHARED, | ||
938 | DRV_NAME, (void *)par)) { | ||
939 | dev_err(dev, "Cannot request irq\n"); | ||
940 | goto io_unmap; | ||
941 | } | ||
942 | |||
943 | mb862xxfb_init_fbinfo(info); | ||
944 | |||
945 | if (fb_alloc_cmap(&info->cmap, NR_PALETTE, 0) < 0) { | ||
946 | dev_err(dev, "Could not allocate cmap for fb_info.\n"); | ||
947 | ret = -ENOMEM; | ||
948 | goto free_irq; | ||
949 | } | ||
950 | |||
951 | if ((info->fbops->fb_set_par)(info)) | ||
952 | dev_err(dev, "set_var() failed on initial setup?\n"); | ||
953 | |||
954 | ret = register_framebuffer(info); | ||
955 | if (ret < 0) { | ||
956 | dev_err(dev, "failed to register framebuffer\n"); | ||
957 | goto rel_cmap; | ||
958 | } | ||
959 | |||
960 | pci_set_drvdata(pdev, info); | ||
961 | |||
962 | if (device_create_file(dev, &dev_attr_dispregs)) | ||
963 | dev_err(dev, "Can't create sysfs regdump file\n"); | ||
964 | |||
965 | if (par->type == BT_CARMINE) | ||
966 | outreg(ctrl, GC_CTRL_INT_MASK, GC_CARMINE_INT_EN); | ||
967 | else | ||
968 | outreg(host, GC_IMASK, GC_INT_EN); | ||
969 | |||
970 | return 0; | ||
971 | |||
972 | rel_cmap: | ||
973 | fb_dealloc_cmap(&info->cmap); | ||
974 | free_irq: | ||
975 | free_irq(par->irq, (void *)par); | ||
976 | io_unmap: | ||
977 | iounmap(par->mmio_base); | ||
978 | fb_unmap: | ||
979 | iounmap(par->fb_base); | ||
980 | rel_reg: | ||
981 | pci_release_regions(pdev); | ||
982 | rel_fb: | ||
983 | framebuffer_release(info); | ||
984 | dis_dev: | ||
985 | pci_disable_device(pdev); | ||
986 | out: | ||
987 | return ret; | ||
988 | } | ||
989 | |||
990 | static void __devexit mb862xx_pci_remove(struct pci_dev *pdev) | ||
991 | { | ||
992 | struct fb_info *fbi = pci_get_drvdata(pdev); | ||
993 | struct mb862xxfb_par *par = fbi->par; | ||
994 | unsigned long reg; | ||
995 | |||
996 | dev_dbg(fbi->dev, "%s release\n", fbi->fix.id); | ||
997 | |||
998 | /* display off */ | ||
999 | reg = inreg(disp, GC_DCM1); | ||
1000 | reg &= ~(GC_DCM01_DEN | GC_DCM01_L0E); | ||
1001 | outreg(disp, GC_DCM1, reg); | ||
1002 | |||
1003 | if (par->type == BT_CARMINE) { | ||
1004 | outreg(ctrl, GC_CTRL_INT_MASK, 0); | ||
1005 | outreg(ctrl, GC_CTRL_CLK_ENABLE, 0); | ||
1006 | } else { | ||
1007 | outreg(host, GC_IMASK, 0); | ||
1008 | } | ||
1009 | |||
1010 | device_remove_file(&pdev->dev, &dev_attr_dispregs); | ||
1011 | |||
1012 | pci_set_drvdata(pdev, NULL); | ||
1013 | unregister_framebuffer(fbi); | ||
1014 | fb_dealloc_cmap(&fbi->cmap); | ||
1015 | |||
1016 | free_irq(par->irq, (void *)par); | ||
1017 | iounmap(par->mmio_base); | ||
1018 | iounmap(par->fb_base); | ||
1019 | |||
1020 | pci_release_regions(pdev); | ||
1021 | framebuffer_release(fbi); | ||
1022 | pci_disable_device(pdev); | ||
1023 | } | ||
1024 | |||
1025 | static struct pci_driver mb862xxfb_pci_driver = { | ||
1026 | .name = DRV_NAME, | ||
1027 | .id_table = mb862xx_pci_tbl, | ||
1028 | .probe = mb862xx_pci_probe, | ||
1029 | .remove = __devexit_p(mb862xx_pci_remove), | ||
1030 | }; | ||
1031 | #endif | ||
1032 | |||
1033 | static int __devinit mb862xxfb_init(void) | ||
1034 | { | ||
1035 | int ret = -ENODEV; | ||
1036 | |||
1037 | #if defined(CONFIG_FB_MB862XX_LIME) | ||
1038 | ret = of_register_platform_driver(&of_platform_mb862xxfb_driver); | ||
1039 | #endif | ||
1040 | #if defined(CONFIG_FB_MB862XX_PCI_GDC) | ||
1041 | ret = pci_register_driver(&mb862xxfb_pci_driver); | ||
1042 | #endif | ||
1043 | return ret; | ||
1044 | } | ||
1045 | |||
1046 | static void __exit mb862xxfb_exit(void) | ||
1047 | { | ||
1048 | #if defined(CONFIG_FB_MB862XX_LIME) | ||
1049 | of_unregister_platform_driver(&of_platform_mb862xxfb_driver); | ||
1050 | #endif | ||
1051 | #if defined(CONFIG_FB_MB862XX_PCI_GDC) | ||
1052 | pci_unregister_driver(&mb862xxfb_pci_driver); | ||
1053 | #endif | ||
1054 | } | ||
1055 | |||
1056 | module_init(mb862xxfb_init); | ||
1057 | module_exit(mb862xxfb_exit); | ||
1058 | |||
1059 | MODULE_DESCRIPTION("Fujitsu MB862xx Framebuffer driver"); | ||
1060 | MODULE_AUTHOR("Anatolij Gustschin <agust@denx.de>"); | ||
1061 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/mb862xx/mb862xxfb.h new file mode 100644 index 000000000000..c4c8f4dd2217 --- /dev/null +++ b/drivers/video/mb862xx/mb862xxfb.h | |||
@@ -0,0 +1,83 @@ | |||
1 | #ifndef __MB862XX_H__ | ||
2 | #define __MB862XX_H__ | ||
3 | |||
4 | #define PCI_VENDOR_ID_FUJITSU_LIMITED 0x10cf | ||
5 | #define PCI_DEVICE_ID_FUJITSU_CORALP 0x2019 | ||
6 | #define PCI_DEVICE_ID_FUJITSU_CORALPA 0x201e | ||
7 | #define PCI_DEVICE_ID_FUJITSU_CARMINE 0x202b | ||
8 | |||
9 | #define GC_MMR_CORALP_EVB_VAL 0x11d7fa13 | ||
10 | |||
11 | enum gdctype { | ||
12 | BT_NONE, | ||
13 | BT_LIME, | ||
14 | BT_MINT, | ||
15 | BT_CORAL, | ||
16 | BT_CORALP, | ||
17 | BT_CARMINE, | ||
18 | }; | ||
19 | |||
20 | struct mb862xx_gc_mode { | ||
21 | struct fb_videomode def_mode; /* mode of connected display */ | ||
22 | unsigned int def_bpp; /* default depth */ | ||
23 | unsigned long max_vram; /* connected SDRAM size */ | ||
24 | unsigned long ccf; /* gdc clk */ | ||
25 | unsigned long mmr; /* memory mode for SDRAM */ | ||
26 | }; | ||
27 | |||
28 | /* private data */ | ||
29 | struct mb862xxfb_par { | ||
30 | struct fb_info *info; /* fb info head */ | ||
31 | struct device *dev; | ||
32 | struct pci_dev *pdev; | ||
33 | struct resource *res; /* framebuffer/mmio resource */ | ||
34 | |||
35 | resource_size_t fb_base_phys; /* fb base, 36-bit PPC440EPx */ | ||
36 | resource_size_t mmio_base_phys; /* io base addr */ | ||
37 | void __iomem *fb_base; /* remapped framebuffer */ | ||
38 | void __iomem *mmio_base; /* remapped registers */ | ||
39 | size_t mapped_vram; /* length of remapped vram */ | ||
40 | size_t mmio_len; /* length of register region */ | ||
41 | |||
42 | void __iomem *host; /* relocatable reg. bases */ | ||
43 | void __iomem *i2c; | ||
44 | void __iomem *disp; | ||
45 | void __iomem *disp1; | ||
46 | void __iomem *cap; | ||
47 | void __iomem *cap1; | ||
48 | void __iomem *draw; | ||
49 | void __iomem *geo; | ||
50 | void __iomem *pio; | ||
51 | void __iomem *ctrl; | ||
52 | void __iomem *dram_ctrl; | ||
53 | void __iomem *wrback; | ||
54 | |||
55 | unsigned int irq; | ||
56 | unsigned int type; /* GDC type */ | ||
57 | unsigned int refclk; /* disp. reference clock */ | ||
58 | struct mb862xx_gc_mode *gc_mode; /* GDC mode init data */ | ||
59 | int pre_init; /* don't init display if 1 */ | ||
60 | |||
61 | u32 pseudo_palette[16]; | ||
62 | }; | ||
63 | |||
64 | #if defined(CONFIG_FB_MB862XX_LIME) && defined(CONFIG_FB_MB862XX_PCI_GDC) | ||
65 | #error "Select Lime GDC or CoralP/Carmine support, but not both together" | ||
66 | #endif | ||
67 | #if defined(CONFIG_FB_MB862XX_LIME) | ||
68 | #define gdc_read __raw_readl | ||
69 | #define gdc_write __raw_writel | ||
70 | #else | ||
71 | #define gdc_read readl | ||
72 | #define gdc_write writel | ||
73 | #endif | ||
74 | |||
75 | #define inreg(type, off) \ | ||
76 | gdc_read((par->type + (off))) | ||
77 | |||
78 | #define outreg(type, off, val) \ | ||
79 | gdc_write((val), (par->type + (off))) | ||
80 | |||
81 | #define pack(a, b) (((a) << 16) | (b)) | ||
82 | |||
83 | #endif | ||
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1a22fe782a27..4fd3fa5546b1 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -67,11 +67,11 @@ config AT91RM9200_WATCHDOG | |||
67 | system when the timeout is reached. | 67 | system when the timeout is reached. |
68 | 68 | ||
69 | config AT91SAM9X_WATCHDOG | 69 | config AT91SAM9X_WATCHDOG |
70 | tristate "AT91SAM9X watchdog" | 70 | tristate "AT91SAM9X / AT91CAP9 watchdog" |
71 | depends on WATCHDOG && (ARCH_AT91SAM9260 || ARCH_AT91SAM9261) | 71 | depends on ARCH_AT91 && !ARCH_AT91RM9200 |
72 | help | 72 | help |
73 | Watchdog timer embedded into AT91SAM9X chips. This will reboot your | 73 | Watchdog timer embedded into AT91SAM9X and AT91CAP9 chips. This will |
74 | system when the timeout is reached. | 74 | reboot your system when the timeout is reached. |
75 | 75 | ||
76 | config 21285_WATCHDOG | 76 | config 21285_WATCHDOG |
77 | tristate "DC21285 watchdog" | 77 | tristate "DC21285 watchdog" |
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c index b4babfc31586..b1da287f90ec 100644 --- a/drivers/watchdog/at91sam9_wdt.c +++ b/drivers/watchdog/at91sam9_wdt.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
31 | #include <linux/uaccess.h> | 31 | #include <linux/uaccess.h> |
32 | 32 | ||
33 | #include <asm/arch/at91_wdt.h> | 33 | #include <mach/at91_wdt.h> |
34 | 34 | ||
35 | #define DRV_NAME "AT91SAM9 Watchdog" | 35 | #define DRV_NAME "AT91SAM9 Watchdog" |
36 | 36 | ||
diff --git a/fs/Makefile b/fs/Makefile index 2168c902d5ca..d9f8afe6f0c4 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -81,8 +81,6 @@ obj-$(CONFIG_HUGETLBFS) += hugetlbfs/ | |||
81 | obj-$(CONFIG_CODA_FS) += coda/ | 81 | obj-$(CONFIG_CODA_FS) += coda/ |
82 | obj-$(CONFIG_MINIX_FS) += minix/ | 82 | obj-$(CONFIG_MINIX_FS) += minix/ |
83 | obj-$(CONFIG_FAT_FS) += fat/ | 83 | obj-$(CONFIG_FAT_FS) += fat/ |
84 | obj-$(CONFIG_MSDOS_FS) += msdos/ | ||
85 | obj-$(CONFIG_VFAT_FS) += vfat/ | ||
86 | obj-$(CONFIG_BFS_FS) += bfs/ | 84 | obj-$(CONFIG_BFS_FS) += bfs/ |
87 | obj-$(CONFIG_ISO9660_FS) += isofs/ | 85 | obj-$(CONFIG_ISO9660_FS) += isofs/ |
88 | obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ | 86 | obj-$(CONFIG_HFSPLUS_FS) += hfsplus/ # Before hfs to find wrapped HFS+ |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index 625abf5422e2..33bf8cbfd051 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
@@ -128,9 +128,10 @@ static inline void free_dev_ioctl(struct autofs_dev_ioctl *param) | |||
128 | */ | 128 | */ |
129 | static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) | 129 | static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) |
130 | { | 130 | { |
131 | int err = -EINVAL; | 131 | int err; |
132 | 132 | ||
133 | if (check_dev_ioctl_version(cmd, param)) { | 133 | err = check_dev_ioctl_version(cmd, param); |
134 | if (err) { | ||
134 | AUTOFS_WARN("invalid device control module version " | 135 | AUTOFS_WARN("invalid device control module version " |
135 | "supplied for cmd(0x%08x)", cmd); | 136 | "supplied for cmd(0x%08x)", cmd); |
136 | goto out; | 137 | goto out; |
diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index cde2f8e8935a..4b6fb3f628c0 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c | |||
@@ -56,12 +56,23 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) | |||
56 | mntget(mnt); | 56 | mntget(mnt); |
57 | dget(dentry); | 57 | dget(dentry); |
58 | 58 | ||
59 | if (!autofs4_follow_mount(&mnt, &dentry)) | 59 | if (!follow_down(&mnt, &dentry)) |
60 | goto done; | 60 | goto done; |
61 | 61 | ||
62 | /* This is an autofs submount, we can't expire it */ | 62 | if (is_autofs4_dentry(dentry)) { |
63 | if (is_autofs4_dentry(dentry)) | 63 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
64 | goto done; | 64 | |
65 | /* This is an autofs submount, we can't expire it */ | ||
66 | if (sbi->type == AUTOFS_TYPE_INDIRECT) | ||
67 | goto done; | ||
68 | |||
69 | /* | ||
70 | * Otherwise it's an offset mount and we need to check | ||
71 | * if we can umount its mount, if there is one. | ||
72 | */ | ||
73 | if (!d_mountpoint(dentry)) | ||
74 | goto done; | ||
75 | } | ||
65 | 76 | ||
66 | /* Update the expiry counter if fs is busy */ | 77 | /* Update the expiry counter if fs is busy */ |
67 | if (!may_umount_tree(mnt)) { | 78 | if (!may_umount_tree(mnt)) { |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index e5717a4fae67..5dec6d1356c4 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -2390,13 +2390,12 @@ static void ext3_write_super (struct super_block * sb) | |||
2390 | 2390 | ||
2391 | static int ext3_sync_fs(struct super_block *sb, int wait) | 2391 | static int ext3_sync_fs(struct super_block *sb, int wait) |
2392 | { | 2392 | { |
2393 | tid_t target; | ||
2394 | |||
2395 | sb->s_dirt = 0; | 2393 | sb->s_dirt = 0; |
2396 | if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) { | 2394 | if (wait) |
2397 | if (wait) | 2395 | ext3_force_commit(sb); |
2398 | log_wait_commit(EXT3_SB(sb)->s_journal, target); | 2396 | else |
2399 | } | 2397 | journal_start_commit(EXT3_SB(sb)->s_journal, NULL); |
2398 | |||
2400 | return 0; | 2399 | return 0; |
2401 | } | 2400 | } |
2402 | 2401 | ||
diff --git a/fs/fat/Makefile b/fs/fat/Makefile index bfb5f06cf2c8..e06190322c1c 100644 --- a/fs/fat/Makefile +++ b/fs/fat/Makefile | |||
@@ -3,5 +3,9 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_FAT_FS) += fat.o | 5 | obj-$(CONFIG_FAT_FS) += fat.o |
6 | obj-$(CONFIG_VFAT_FS) += vfat.o | ||
7 | obj-$(CONFIG_MSDOS_FS) += msdos.o | ||
6 | 8 | ||
7 | fat-objs := cache.o dir.o fatent.o file.o inode.o misc.o | 9 | fat-y := cache.o dir.o fatent.o file.o inode.o misc.o |
10 | vfat-y := namei_vfat.o | ||
11 | msdos-y := namei_msdos.o | ||
diff --git a/fs/fat/cache.c b/fs/fat/cache.c index 3222f51c41cf..b42602298087 100644 --- a/fs/fat/cache.c +++ b/fs/fat/cache.c | |||
@@ -9,8 +9,8 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/msdos_fs.h> | ||
13 | #include <linux/buffer_head.h> | 12 | #include <linux/buffer_head.h> |
13 | #include "fat.h" | ||
14 | 14 | ||
15 | /* this must be > 0. */ | 15 | /* this must be > 0. */ |
16 | #define FAT_MAX_CACHE 8 | 16 | #define FAT_MAX_CACHE 8 |
@@ -293,10 +293,12 @@ static int fat_bmap_cluster(struct inode *inode, int cluster) | |||
293 | } | 293 | } |
294 | 294 | ||
295 | int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | 295 | int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, |
296 | unsigned long *mapped_blocks) | 296 | unsigned long *mapped_blocks, int create) |
297 | { | 297 | { |
298 | struct super_block *sb = inode->i_sb; | 298 | struct super_block *sb = inode->i_sb; |
299 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 299 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
300 | const unsigned long blocksize = sb->s_blocksize; | ||
301 | const unsigned char blocksize_bits = sb->s_blocksize_bits; | ||
300 | sector_t last_block; | 302 | sector_t last_block; |
301 | int cluster, offset; | 303 | int cluster, offset; |
302 | 304 | ||
@@ -309,10 +311,21 @@ int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | |||
309 | } | 311 | } |
310 | return 0; | 312 | return 0; |
311 | } | 313 | } |
312 | last_block = (MSDOS_I(inode)->mmu_private + (sb->s_blocksize - 1)) | 314 | |
313 | >> sb->s_blocksize_bits; | 315 | last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; |
314 | if (sector >= last_block) | 316 | if (sector >= last_block) { |
315 | return 0; | 317 | if (!create) |
318 | return 0; | ||
319 | |||
320 | /* | ||
321 | * ->mmu_private can access on only allocation path. | ||
322 | * (caller must hold ->i_mutex) | ||
323 | */ | ||
324 | last_block = (MSDOS_I(inode)->mmu_private + (blocksize - 1)) | ||
325 | >> blocksize_bits; | ||
326 | if (sector >= last_block) | ||
327 | return 0; | ||
328 | } | ||
316 | 329 | ||
317 | cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits); | 330 | cluster = sector >> (sbi->cluster_bits - sb->s_blocksize_bits); |
318 | offset = sector & (sbi->sec_per_clus - 1); | 331 | offset = sector & (sbi->sec_per_clus - 1); |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index bae1c3292522..67e058357098 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
@@ -16,11 +16,11 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
19 | #include <linux/msdos_fs.h> | ||
20 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
21 | #include <linux/buffer_head.h> | 20 | #include <linux/buffer_head.h> |
22 | #include <linux/compat.h> | 21 | #include <linux/compat.h> |
23 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
23 | #include "fat.h" | ||
24 | 24 | ||
25 | static inline loff_t fat_make_i_pos(struct super_block *sb, | 25 | static inline loff_t fat_make_i_pos(struct super_block *sb, |
26 | struct buffer_head *bh, | 26 | struct buffer_head *bh, |
@@ -77,7 +77,7 @@ next: | |||
77 | 77 | ||
78 | *bh = NULL; | 78 | *bh = NULL; |
79 | iblock = *pos >> sb->s_blocksize_bits; | 79 | iblock = *pos >> sb->s_blocksize_bits; |
80 | err = fat_bmap(dir, iblock, &phys, &mapped_blocks); | 80 | err = fat_bmap(dir, iblock, &phys, &mapped_blocks, 0); |
81 | if (err || !phys) | 81 | if (err || !phys) |
82 | return -1; /* beyond EOF or error */ | 82 | return -1; /* beyond EOF or error */ |
83 | 83 | ||
@@ -86,7 +86,7 @@ next: | |||
86 | *bh = sb_bread(sb, phys); | 86 | *bh = sb_bread(sb, phys); |
87 | if (*bh == NULL) { | 87 | if (*bh == NULL) { |
88 | printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", | 88 | printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n", |
89 | (unsigned long long)phys); | 89 | (llu)phys); |
90 | /* skip this block */ | 90 | /* skip this block */ |
91 | *pos = (iblock + 1) << sb->s_blocksize_bits; | 91 | *pos = (iblock + 1) << sb->s_blocksize_bits; |
92 | goto next; | 92 | goto next; |
@@ -373,9 +373,10 @@ parse_record: | |||
373 | if (de->attr == ATTR_EXT) { | 373 | if (de->attr == ATTR_EXT) { |
374 | int status = fat_parse_long(inode, &cpos, &bh, &de, | 374 | int status = fat_parse_long(inode, &cpos, &bh, &de, |
375 | &unicode, &nr_slots); | 375 | &unicode, &nr_slots); |
376 | if (status < 0) | 376 | if (status < 0) { |
377 | return status; | 377 | err = status; |
378 | else if (status == PARSE_INVALID) | 378 | goto end_of_dir; |
379 | } else if (status == PARSE_INVALID) | ||
379 | continue; | 380 | continue; |
380 | else if (status == PARSE_NOT_LONGNAME) | 381 | else if (status == PARSE_NOT_LONGNAME) |
381 | goto parse_record; | 382 | goto parse_record; |
@@ -832,6 +833,7 @@ static long fat_compat_dir_ioctl(struct file *filp, unsigned cmd, | |||
832 | #endif /* CONFIG_COMPAT */ | 833 | #endif /* CONFIG_COMPAT */ |
833 | 834 | ||
834 | const struct file_operations fat_dir_operations = { | 835 | const struct file_operations fat_dir_operations = { |
836 | .llseek = generic_file_llseek, | ||
835 | .read = generic_read_dir, | 837 | .read = generic_read_dir, |
836 | .readdir = fat_readdir, | 838 | .readdir = fat_readdir, |
837 | .ioctl = fat_dir_ioctl, | 839 | .ioctl = fat_dir_ioctl, |
@@ -1089,6 +1091,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | |||
1089 | struct msdos_dir_entry *de; | 1091 | struct msdos_dir_entry *de; |
1090 | sector_t blknr; | 1092 | sector_t blknr; |
1091 | __le16 date, time; | 1093 | __le16 date, time; |
1094 | u8 time_cs; | ||
1092 | int err, cluster; | 1095 | int err, cluster; |
1093 | 1096 | ||
1094 | err = fat_alloc_clusters(dir, &cluster, 1); | 1097 | err = fat_alloc_clusters(dir, &cluster, 1); |
@@ -1102,7 +1105,7 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | |||
1102 | goto error_free; | 1105 | goto error_free; |
1103 | } | 1106 | } |
1104 | 1107 | ||
1105 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); | 1108 | fat_time_unix2fat(sbi, ts, &time, &date, &time_cs); |
1106 | 1109 | ||
1107 | de = (struct msdos_dir_entry *)bhs[0]->b_data; | 1110 | de = (struct msdos_dir_entry *)bhs[0]->b_data; |
1108 | /* filling the new directory slots ("." and ".." entries) */ | 1111 | /* filling the new directory slots ("." and ".." entries) */ |
@@ -1112,13 +1115,14 @@ int fat_alloc_new_dir(struct inode *dir, struct timespec *ts) | |||
1112 | de[0].lcase = de[1].lcase = 0; | 1115 | de[0].lcase = de[1].lcase = 0; |
1113 | de[0].time = de[1].time = time; | 1116 | de[0].time = de[1].time = time; |
1114 | de[0].date = de[1].date = date; | 1117 | de[0].date = de[1].date = date; |
1115 | de[0].ctime_cs = de[1].ctime_cs = 0; | ||
1116 | if (sbi->options.isvfat) { | 1118 | if (sbi->options.isvfat) { |
1117 | /* extra timestamps */ | 1119 | /* extra timestamps */ |
1118 | de[0].ctime = de[1].ctime = time; | 1120 | de[0].ctime = de[1].ctime = time; |
1121 | de[0].ctime_cs = de[1].ctime_cs = time_cs; | ||
1119 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date; | 1122 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date; |
1120 | } else { | 1123 | } else { |
1121 | de[0].ctime = de[1].ctime = 0; | 1124 | de[0].ctime = de[1].ctime = 0; |
1125 | de[0].ctime_cs = de[1].ctime_cs = 0; | ||
1122 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0; | 1126 | de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0; |
1123 | } | 1127 | } |
1124 | de[0].start = cpu_to_le16(cluster); | 1128 | de[0].start = cpu_to_le16(cluster); |
diff --git a/fs/fat/fat.h b/fs/fat/fat.h new file mode 100644 index 000000000000..ea440d65819c --- /dev/null +++ b/fs/fat/fat.h | |||
@@ -0,0 +1,329 @@ | |||
1 | #ifndef _FAT_H | ||
2 | #define _FAT_H | ||
3 | |||
4 | #include <linux/buffer_head.h> | ||
5 | #include <linux/string.h> | ||
6 | #include <linux/nls.h> | ||
7 | #include <linux/fs.h> | ||
8 | #include <linux/mutex.h> | ||
9 | #include <linux/msdos_fs.h> | ||
10 | |||
11 | /* | ||
12 | * vfat shortname flags | ||
13 | */ | ||
14 | #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ | ||
15 | #define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ | ||
16 | #define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ | ||
17 | #define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ | ||
18 | #define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ | ||
19 | |||
20 | struct fat_mount_options { | ||
21 | uid_t fs_uid; | ||
22 | gid_t fs_gid; | ||
23 | unsigned short fs_fmask; | ||
24 | unsigned short fs_dmask; | ||
25 | unsigned short codepage; /* Codepage for shortname conversions */ | ||
26 | char *iocharset; /* Charset used for filename input/display */ | ||
27 | unsigned short shortname; /* flags for shortname display/create rule */ | ||
28 | unsigned char name_check; /* r = relaxed, n = normal, s = strict */ | ||
29 | unsigned short allow_utime;/* permission for setting the [am]time */ | ||
30 | unsigned quiet:1, /* set = fake successful chmods and chowns */ | ||
31 | showexec:1, /* set = only set x bit for com/exe/bat */ | ||
32 | sys_immutable:1, /* set = system files are immutable */ | ||
33 | dotsOK:1, /* set = hidden and system files are named '.filename' */ | ||
34 | isvfat:1, /* 0=no vfat long filename support, 1=vfat support */ | ||
35 | utf8:1, /* Use of UTF-8 character set (Default) */ | ||
36 | unicode_xlate:1, /* create escape sequences for unhandled Unicode */ | ||
37 | numtail:1, /* Does first alias have a numeric '~1' type tail? */ | ||
38 | flush:1, /* write things quickly */ | ||
39 | nocase:1, /* Does this need case conversion? 0=need case conversion*/ | ||
40 | usefree:1, /* Use free_clusters for FAT32 */ | ||
41 | tz_utc:1, /* Filesystem timestamps are in UTC */ | ||
42 | rodir:1; /* allow ATTR_RO for directory */ | ||
43 | }; | ||
44 | |||
45 | #define FAT_HASH_BITS 8 | ||
46 | #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) | ||
47 | |||
48 | /* | ||
49 | * MS-DOS file system in-core superblock data | ||
50 | */ | ||
51 | struct msdos_sb_info { | ||
52 | unsigned short sec_per_clus; /* sectors/cluster */ | ||
53 | unsigned short cluster_bits; /* log2(cluster_size) */ | ||
54 | unsigned int cluster_size; /* cluster size */ | ||
55 | unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ | ||
56 | unsigned short fat_start; | ||
57 | unsigned long fat_length; /* FAT start & length (sec.) */ | ||
58 | unsigned long dir_start; | ||
59 | unsigned short dir_entries; /* root dir start & entries */ | ||
60 | unsigned long data_start; /* first data sector */ | ||
61 | unsigned long max_cluster; /* maximum cluster number */ | ||
62 | unsigned long root_cluster; /* first cluster of the root directory */ | ||
63 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ | ||
64 | struct mutex fat_lock; | ||
65 | unsigned int prev_free; /* previously allocated cluster number */ | ||
66 | unsigned int free_clusters; /* -1 if undefined */ | ||
67 | unsigned int free_clus_valid; /* is free_clusters valid? */ | ||
68 | struct fat_mount_options options; | ||
69 | struct nls_table *nls_disk; /* Codepage used on disk */ | ||
70 | struct nls_table *nls_io; /* Charset used for input and display */ | ||
71 | const void *dir_ops; /* Opaque; default directory operations */ | ||
72 | int dir_per_block; /* dir entries per block */ | ||
73 | int dir_per_block_bits; /* log2(dir_per_block) */ | ||
74 | |||
75 | int fatent_shift; | ||
76 | struct fatent_operations *fatent_ops; | ||
77 | |||
78 | spinlock_t inode_hash_lock; | ||
79 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; | ||
80 | }; | ||
81 | |||
82 | #define FAT_CACHE_VALID 0 /* special case for valid cache */ | ||
83 | |||
84 | /* | ||
85 | * MS-DOS file system inode data in memory | ||
86 | */ | ||
87 | struct msdos_inode_info { | ||
88 | spinlock_t cache_lru_lock; | ||
89 | struct list_head cache_lru; | ||
90 | int nr_caches; | ||
91 | /* for avoiding the race between fat_free() and fat_get_cluster() */ | ||
92 | unsigned int cache_valid_id; | ||
93 | |||
94 | /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ | ||
95 | loff_t mmu_private; /* physically allocated size */ | ||
96 | |||
97 | int i_start; /* first cluster or 0 */ | ||
98 | int i_logstart; /* logical first cluster */ | ||
99 | int i_attrs; /* unused attribute bits */ | ||
100 | loff_t i_pos; /* on-disk position of directory entry or 0 */ | ||
101 | struct hlist_node i_fat_hash; /* hash by i_location */ | ||
102 | struct inode vfs_inode; | ||
103 | }; | ||
104 | |||
105 | struct fat_slot_info { | ||
106 | loff_t i_pos; /* on-disk position of directory entry */ | ||
107 | loff_t slot_off; /* offset for slot or de start */ | ||
108 | int nr_slots; /* number of slots + 1(de) in filename */ | ||
109 | struct msdos_dir_entry *de; | ||
110 | struct buffer_head *bh; | ||
111 | }; | ||
112 | |||
113 | static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) | ||
114 | { | ||
115 | return sb->s_fs_info; | ||
116 | } | ||
117 | |||
118 | static inline struct msdos_inode_info *MSDOS_I(struct inode *inode) | ||
119 | { | ||
120 | return container_of(inode, struct msdos_inode_info, vfs_inode); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to | ||
125 | * save ATTR_RO instead of ->i_mode. | ||
126 | * | ||
127 | * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only | ||
128 | * bit, it's just used as flag for app. | ||
129 | */ | ||
130 | static inline int fat_mode_can_hold_ro(struct inode *inode) | ||
131 | { | ||
132 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); | ||
133 | mode_t mask; | ||
134 | |||
135 | if (S_ISDIR(inode->i_mode)) { | ||
136 | if (!sbi->options.rodir) | ||
137 | return 0; | ||
138 | mask = ~sbi->options.fs_dmask; | ||
139 | } else | ||
140 | mask = ~sbi->options.fs_fmask; | ||
141 | |||
142 | if (!(mask & S_IWUGO)) | ||
143 | return 0; | ||
144 | return 1; | ||
145 | } | ||
146 | |||
147 | /* Convert attribute bits and a mask to the UNIX mode. */ | ||
148 | static inline mode_t fat_make_mode(struct msdos_sb_info *sbi, | ||
149 | u8 attrs, mode_t mode) | ||
150 | { | ||
151 | if (attrs & ATTR_RO && !((attrs & ATTR_DIR) && !sbi->options.rodir)) | ||
152 | mode &= ~S_IWUGO; | ||
153 | |||
154 | if (attrs & ATTR_DIR) | ||
155 | return (mode & ~sbi->options.fs_dmask) | S_IFDIR; | ||
156 | else | ||
157 | return (mode & ~sbi->options.fs_fmask) | S_IFREG; | ||
158 | } | ||
159 | |||
160 | /* Return the FAT attribute byte for this inode */ | ||
161 | static inline u8 fat_make_attrs(struct inode *inode) | ||
162 | { | ||
163 | u8 attrs = MSDOS_I(inode)->i_attrs; | ||
164 | if (S_ISDIR(inode->i_mode)) | ||
165 | attrs |= ATTR_DIR; | ||
166 | if (fat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO)) | ||
167 | attrs |= ATTR_RO; | ||
168 | return attrs; | ||
169 | } | ||
170 | |||
171 | static inline void fat_save_attrs(struct inode *inode, u8 attrs) | ||
172 | { | ||
173 | if (fat_mode_can_hold_ro(inode)) | ||
174 | MSDOS_I(inode)->i_attrs = attrs & ATTR_UNUSED; | ||
175 | else | ||
176 | MSDOS_I(inode)->i_attrs = attrs & (ATTR_UNUSED | ATTR_RO); | ||
177 | } | ||
178 | |||
179 | static inline unsigned char fat_checksum(const __u8 *name) | ||
180 | { | ||
181 | unsigned char s = name[0]; | ||
182 | s = (s<<7) + (s>>1) + name[1]; s = (s<<7) + (s>>1) + name[2]; | ||
183 | s = (s<<7) + (s>>1) + name[3]; s = (s<<7) + (s>>1) + name[4]; | ||
184 | s = (s<<7) + (s>>1) + name[5]; s = (s<<7) + (s>>1) + name[6]; | ||
185 | s = (s<<7) + (s>>1) + name[7]; s = (s<<7) + (s>>1) + name[8]; | ||
186 | s = (s<<7) + (s>>1) + name[9]; s = (s<<7) + (s>>1) + name[10]; | ||
187 | return s; | ||
188 | } | ||
189 | |||
190 | static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus) | ||
191 | { | ||
192 | return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus | ||
193 | + sbi->data_start; | ||
194 | } | ||
195 | |||
196 | static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) | ||
197 | { | ||
198 | #ifdef __BIG_ENDIAN | ||
199 | while (len--) { | ||
200 | *dst++ = src[0] | (src[1] << 8); | ||
201 | src += 2; | ||
202 | } | ||
203 | #else | ||
204 | memcpy(dst, src, len * 2); | ||
205 | #endif | ||
206 | } | ||
207 | |||
208 | static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) | ||
209 | { | ||
210 | #ifdef __BIG_ENDIAN | ||
211 | while (len--) { | ||
212 | dst[0] = *src & 0x00FF; | ||
213 | dst[1] = (*src & 0xFF00) >> 8; | ||
214 | dst += 2; | ||
215 | src++; | ||
216 | } | ||
217 | #else | ||
218 | memcpy(dst, src, len * 2); | ||
219 | #endif | ||
220 | } | ||
221 | |||
222 | /* fat/cache.c */ | ||
223 | extern void fat_cache_inval_inode(struct inode *inode); | ||
224 | extern int fat_get_cluster(struct inode *inode, int cluster, | ||
225 | int *fclus, int *dclus); | ||
226 | extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | ||
227 | unsigned long *mapped_blocks, int create); | ||
228 | |||
229 | /* fat/dir.c */ | ||
230 | extern const struct file_operations fat_dir_operations; | ||
231 | extern int fat_search_long(struct inode *inode, const unsigned char *name, | ||
232 | int name_len, struct fat_slot_info *sinfo); | ||
233 | extern int fat_dir_empty(struct inode *dir); | ||
234 | extern int fat_subdirs(struct inode *dir); | ||
235 | extern int fat_scan(struct inode *dir, const unsigned char *name, | ||
236 | struct fat_slot_info *sinfo); | ||
237 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, | ||
238 | struct msdos_dir_entry **de, loff_t *i_pos); | ||
239 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); | ||
240 | extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | ||
241 | struct fat_slot_info *sinfo); | ||
242 | extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo); | ||
243 | |||
244 | /* fat/fatent.c */ | ||
245 | struct fat_entry { | ||
246 | int entry; | ||
247 | union { | ||
248 | u8 *ent12_p[2]; | ||
249 | __le16 *ent16_p; | ||
250 | __le32 *ent32_p; | ||
251 | } u; | ||
252 | int nr_bhs; | ||
253 | struct buffer_head *bhs[2]; | ||
254 | }; | ||
255 | |||
256 | static inline void fatent_init(struct fat_entry *fatent) | ||
257 | { | ||
258 | fatent->nr_bhs = 0; | ||
259 | fatent->entry = 0; | ||
260 | fatent->u.ent32_p = NULL; | ||
261 | fatent->bhs[0] = fatent->bhs[1] = NULL; | ||
262 | } | ||
263 | |||
264 | static inline void fatent_set_entry(struct fat_entry *fatent, int entry) | ||
265 | { | ||
266 | fatent->entry = entry; | ||
267 | fatent->u.ent32_p = NULL; | ||
268 | } | ||
269 | |||
270 | static inline void fatent_brelse(struct fat_entry *fatent) | ||
271 | { | ||
272 | int i; | ||
273 | fatent->u.ent32_p = NULL; | ||
274 | for (i = 0; i < fatent->nr_bhs; i++) | ||
275 | brelse(fatent->bhs[i]); | ||
276 | fatent->nr_bhs = 0; | ||
277 | fatent->bhs[0] = fatent->bhs[1] = NULL; | ||
278 | } | ||
279 | |||
280 | extern void fat_ent_access_init(struct super_block *sb); | ||
281 | extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent, | ||
282 | int entry); | ||
283 | extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent, | ||
284 | int new, int wait); | ||
285 | extern int fat_alloc_clusters(struct inode *inode, int *cluster, | ||
286 | int nr_cluster); | ||
287 | extern int fat_free_clusters(struct inode *inode, int cluster); | ||
288 | extern int fat_count_free_clusters(struct super_block *sb); | ||
289 | |||
290 | /* fat/file.c */ | ||
291 | extern int fat_generic_ioctl(struct inode *inode, struct file *filp, | ||
292 | unsigned int cmd, unsigned long arg); | ||
293 | extern const struct file_operations fat_file_operations; | ||
294 | extern const struct inode_operations fat_file_inode_operations; | ||
295 | extern int fat_setattr(struct dentry * dentry, struct iattr * attr); | ||
296 | extern void fat_truncate(struct inode *inode); | ||
297 | extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
298 | struct kstat *stat); | ||
299 | |||
300 | /* fat/inode.c */ | ||
301 | extern void fat_attach(struct inode *inode, loff_t i_pos); | ||
302 | extern void fat_detach(struct inode *inode); | ||
303 | extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); | ||
304 | extern struct inode *fat_build_inode(struct super_block *sb, | ||
305 | struct msdos_dir_entry *de, loff_t i_pos); | ||
306 | extern int fat_sync_inode(struct inode *inode); | ||
307 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, | ||
308 | const struct inode_operations *fs_dir_inode_ops, int isvfat); | ||
309 | |||
310 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | ||
311 | struct inode *i2); | ||
312 | /* fat/misc.c */ | ||
313 | extern void fat_fs_panic(struct super_block *s, const char *fmt, ...) | ||
314 | __attribute__ ((format (printf, 2, 3))) __cold; | ||
315 | extern void fat_clusters_flush(struct super_block *sb); | ||
316 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); | ||
317 | extern void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, | ||
318 | __le16 __time, __le16 __date, u8 time_cs); | ||
319 | extern void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, | ||
320 | __le16 *time, __le16 *date, u8 *time_cs); | ||
321 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); | ||
322 | |||
323 | int fat_cache_init(void); | ||
324 | void fat_cache_destroy(void); | ||
325 | |||
326 | /* helper for printk */ | ||
327 | typedef unsigned long long llu; | ||
328 | |||
329 | #endif /* !_FAT_H */ | ||
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index fb98b3d847ed..da6eea47872f 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
8 | #include <linux/msdos_fs.h> | 8 | #include <linux/msdos_fs.h> |
9 | #include <linux/blkdev.h> | 9 | #include <linux/blkdev.h> |
10 | #include "fat.h" | ||
10 | 11 | ||
11 | struct fatent_operations { | 12 | struct fatent_operations { |
12 | void (*ent_blocknr)(struct super_block *, int, int *, sector_t *); | 13 | void (*ent_blocknr)(struct super_block *, int, int *, sector_t *); |
@@ -92,8 +93,7 @@ static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent, | |||
92 | err_brelse: | 93 | err_brelse: |
93 | brelse(bhs[0]); | 94 | brelse(bhs[0]); |
94 | err: | 95 | err: |
95 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", | 96 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", (llu)blocknr); |
96 | (unsigned long long)blocknr); | ||
97 | return -EIO; | 97 | return -EIO; |
98 | } | 98 | } |
99 | 99 | ||
@@ -106,7 +106,7 @@ static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent, | |||
106 | fatent->bhs[0] = sb_bread(sb, blocknr); | 106 | fatent->bhs[0] = sb_bread(sb, blocknr); |
107 | if (!fatent->bhs[0]) { | 107 | if (!fatent->bhs[0]) { |
108 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", | 108 | printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n", |
109 | (unsigned long long)blocknr); | 109 | (llu)blocknr); |
110 | return -EIO; | 110 | return -EIO; |
111 | } | 111 | } |
112 | fatent->nr_bhs = 1; | 112 | fatent->nr_bhs = 1; |
@@ -316,10 +316,20 @@ static inline int fat_ent_update_ptr(struct super_block *sb, | |||
316 | /* Is this fatent's blocks including this entry? */ | 316 | /* Is this fatent's blocks including this entry? */ |
317 | if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr) | 317 | if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr) |
318 | return 0; | 318 | return 0; |
319 | /* Does this entry need the next block? */ | 319 | if (sbi->fat_bits == 12) { |
320 | if (sbi->fat_bits == 12 && (offset + 1) >= sb->s_blocksize) { | 320 | if ((offset + 1) < sb->s_blocksize) { |
321 | if (fatent->nr_bhs != 2 || bhs[1]->b_blocknr != (blocknr + 1)) | 321 | /* This entry is on bhs[0]. */ |
322 | return 0; | 322 | if (fatent->nr_bhs == 2) { |
323 | brelse(bhs[1]); | ||
324 | fatent->nr_bhs = 1; | ||
325 | } | ||
326 | } else { | ||
327 | /* This entry needs the next block. */ | ||
328 | if (fatent->nr_bhs != 2) | ||
329 | return 0; | ||
330 | if (bhs[1]->b_blocknr != (blocknr + 1)) | ||
331 | return 0; | ||
332 | } | ||
323 | } | 333 | } |
324 | ops->ent_set_ptr(fatent, offset); | 334 | ops->ent_set_ptr(fatent, offset); |
325 | return 1; | 335 | return 1; |
diff --git a/fs/fat/file.c b/fs/fat/file.c index ddde37025ca6..f06a4e525ece 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c | |||
@@ -10,13 +10,13 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
12 | #include <linux/time.h> | 12 | #include <linux/time.h> |
13 | #include <linux/msdos_fs.h> | ||
14 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
15 | #include <linux/writeback.h> | 14 | #include <linux/writeback.h> |
16 | #include <linux/backing-dev.h> | 15 | #include <linux/backing-dev.h> |
17 | #include <linux/blkdev.h> | 16 | #include <linux/blkdev.h> |
18 | #include <linux/fsnotify.h> | 17 | #include <linux/fsnotify.h> |
19 | #include <linux/security.h> | 18 | #include <linux/security.h> |
19 | #include "fat.h" | ||
20 | 20 | ||
21 | int fat_generic_ioctl(struct inode *inode, struct file *filp, | 21 | int fat_generic_ioctl(struct inode *inode, struct file *filp, |
22 | unsigned int cmd, unsigned long arg) | 22 | unsigned int cmd, unsigned long arg) |
@@ -29,10 +29,9 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
29 | { | 29 | { |
30 | u32 attr; | 30 | u32 attr; |
31 | 31 | ||
32 | if (inode->i_ino == MSDOS_ROOT_INO) | 32 | mutex_lock(&inode->i_mutex); |
33 | attr = ATTR_DIR; | 33 | attr = fat_make_attrs(inode); |
34 | else | 34 | mutex_unlock(&inode->i_mutex); |
35 | attr = fat_attr(inode); | ||
36 | 35 | ||
37 | return put_user(attr, user_attr); | 36 | return put_user(attr, user_attr); |
38 | } | 37 | } |
@@ -62,20 +61,16 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
62 | /* Merge in ATTR_VOLUME and ATTR_DIR */ | 61 | /* Merge in ATTR_VOLUME and ATTR_DIR */ |
63 | attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) | | 62 | attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) | |
64 | (is_dir ? ATTR_DIR : 0); | 63 | (is_dir ? ATTR_DIR : 0); |
65 | oldattr = fat_attr(inode); | 64 | oldattr = fat_make_attrs(inode); |
66 | 65 | ||
67 | /* Equivalent to a chmod() */ | 66 | /* Equivalent to a chmod() */ |
68 | ia.ia_valid = ATTR_MODE | ATTR_CTIME; | 67 | ia.ia_valid = ATTR_MODE | ATTR_CTIME; |
69 | ia.ia_ctime = current_fs_time(inode->i_sb); | 68 | ia.ia_ctime = current_fs_time(inode->i_sb); |
70 | if (is_dir) { | 69 | if (is_dir) |
71 | ia.ia_mode = MSDOS_MKMODE(attr, | 70 | ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO); |
72 | S_IRWXUGO & ~sbi->options.fs_dmask) | 71 | else { |
73 | | S_IFDIR; | 72 | ia.ia_mode = fat_make_mode(sbi, attr, |
74 | } else { | 73 | S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO)); |
75 | ia.ia_mode = MSDOS_MKMODE(attr, | ||
76 | (S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO)) | ||
77 | & ~sbi->options.fs_fmask) | ||
78 | | S_IFREG; | ||
79 | } | 74 | } |
80 | 75 | ||
81 | /* The root directory has no attributes */ | 76 | /* The root directory has no attributes */ |
@@ -115,7 +110,7 @@ int fat_generic_ioctl(struct inode *inode, struct file *filp, | |||
115 | inode->i_flags &= S_IMMUTABLE; | 110 | inode->i_flags &= S_IMMUTABLE; |
116 | } | 111 | } |
117 | 112 | ||
118 | MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED; | 113 | fat_save_attrs(inode, attr); |
119 | mark_inode_dirty(inode); | 114 | mark_inode_dirty(inode); |
120 | up: | 115 | up: |
121 | mnt_drop_write(filp->f_path.mnt); | 116 | mnt_drop_write(filp->f_path.mnt); |
@@ -274,7 +269,7 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi, | |||
274 | 269 | ||
275 | /* | 270 | /* |
276 | * Note, the basic check is already done by a caller of | 271 | * Note, the basic check is already done by a caller of |
277 | * (attr->ia_mode & ~MSDOS_VALID_MODE) | 272 | * (attr->ia_mode & ~FAT_VALID_MODE) |
278 | */ | 273 | */ |
279 | 274 | ||
280 | if (S_ISREG(inode->i_mode)) | 275 | if (S_ISREG(inode->i_mode)) |
@@ -287,11 +282,18 @@ static int fat_sanitize_mode(const struct msdos_sb_info *sbi, | |||
287 | /* | 282 | /* |
288 | * Of the r and x bits, all (subject to umask) must be present. Of the | 283 | * Of the r and x bits, all (subject to umask) must be present. Of the |
289 | * w bits, either all (subject to umask) or none must be present. | 284 | * w bits, either all (subject to umask) or none must be present. |
285 | * | ||
286 | * If fat_mode_can_hold_ro(inode) is false, can't change w bits. | ||
290 | */ | 287 | */ |
291 | if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) | 288 | if ((perm & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) |
292 | return -EPERM; | 289 | return -EPERM; |
293 | if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) | 290 | if (fat_mode_can_hold_ro(inode)) { |
294 | return -EPERM; | 291 | if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) |
292 | return -EPERM; | ||
293 | } else { | ||
294 | if ((perm & S_IWUGO) != (S_IWUGO & ~mask)) | ||
295 | return -EPERM; | ||
296 | } | ||
295 | 297 | ||
296 | *mode_ptr &= S_IFMT | perm; | 298 | *mode_ptr &= S_IFMT | perm; |
297 | 299 | ||
@@ -314,13 +316,15 @@ static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode) | |||
314 | } | 316 | } |
315 | 317 | ||
316 | #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) | 318 | #define TIMES_SET_FLAGS (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET) |
319 | /* valid file mode bits */ | ||
320 | #define FAT_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXUGO) | ||
317 | 321 | ||
318 | int fat_setattr(struct dentry *dentry, struct iattr *attr) | 322 | int fat_setattr(struct dentry *dentry, struct iattr *attr) |
319 | { | 323 | { |
320 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); | 324 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); |
321 | struct inode *inode = dentry->d_inode; | 325 | struct inode *inode = dentry->d_inode; |
322 | int error = 0; | ||
323 | unsigned int ia_valid; | 326 | unsigned int ia_valid; |
327 | int error; | ||
324 | 328 | ||
325 | /* | 329 | /* |
326 | * Expand the file. Since inode_setattr() updates ->i_size | 330 | * Expand the file. Since inode_setattr() updates ->i_size |
@@ -356,7 +360,7 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
356 | ((attr->ia_valid & ATTR_GID) && | 360 | ((attr->ia_valid & ATTR_GID) && |
357 | (attr->ia_gid != sbi->options.fs_gid)) || | 361 | (attr->ia_gid != sbi->options.fs_gid)) || |
358 | ((attr->ia_valid & ATTR_MODE) && | 362 | ((attr->ia_valid & ATTR_MODE) && |
359 | (attr->ia_mode & ~MSDOS_VALID_MODE))) | 363 | (attr->ia_mode & ~FAT_VALID_MODE))) |
360 | error = -EPERM; | 364 | error = -EPERM; |
361 | 365 | ||
362 | if (error) { | 366 | if (error) { |
@@ -374,7 +378,8 @@ int fat_setattr(struct dentry *dentry, struct iattr *attr) | |||
374 | attr->ia_valid &= ~ATTR_MODE; | 378 | attr->ia_valid &= ~ATTR_MODE; |
375 | } | 379 | } |
376 | 380 | ||
377 | error = inode_setattr(inode, attr); | 381 | if (attr->ia_valid) |
382 | error = inode_setattr(inode, attr); | ||
378 | out: | 383 | out: |
379 | return error; | 384 | return error; |
380 | } | 385 | } |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 2b2eec1283bf..bdd8fb7be2ca 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/smp_lock.h> | 17 | #include <linux/smp_lock.h> |
18 | #include <linux/seq_file.h> | 18 | #include <linux/seq_file.h> |
19 | #include <linux/msdos_fs.h> | ||
20 | #include <linux/pagemap.h> | 19 | #include <linux/pagemap.h> |
21 | #include <linux/mpage.h> | 20 | #include <linux/mpage.h> |
22 | #include <linux/buffer_head.h> | 21 | #include <linux/buffer_head.h> |
@@ -27,7 +26,9 @@ | |||
27 | #include <linux/uio.h> | 26 | #include <linux/uio.h> |
28 | #include <linux/writeback.h> | 27 | #include <linux/writeback.h> |
29 | #include <linux/log2.h> | 28 | #include <linux/log2.h> |
29 | #include <linux/hash.h> | ||
30 | #include <asm/unaligned.h> | 30 | #include <asm/unaligned.h> |
31 | #include "fat.h" | ||
31 | 32 | ||
32 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET | 33 | #ifndef CONFIG_FAT_DEFAULT_IOCHARSET |
33 | /* if user don't select VFAT, this is undefined. */ | 34 | /* if user don't select VFAT, this is undefined. */ |
@@ -63,7 +64,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock, | |||
63 | sector_t phys; | 64 | sector_t phys; |
64 | int err, offset; | 65 | int err, offset; |
65 | 66 | ||
66 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 67 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create); |
67 | if (err) | 68 | if (err) |
68 | return err; | 69 | return err; |
69 | if (phys) { | 70 | if (phys) { |
@@ -93,7 +94,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock, | |||
93 | *max_blocks = min(mapped_blocks, *max_blocks); | 94 | *max_blocks = min(mapped_blocks, *max_blocks); |
94 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; | 95 | MSDOS_I(inode)->mmu_private += *max_blocks << sb->s_blocksize_bits; |
95 | 96 | ||
96 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks); | 97 | err = fat_bmap(inode, iblock, &phys, &mapped_blocks, create); |
97 | if (err) | 98 | if (err) |
98 | return err; | 99 | return err; |
99 | 100 | ||
@@ -198,7 +199,14 @@ static ssize_t fat_direct_IO(int rw, struct kiocb *iocb, | |||
198 | 199 | ||
199 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) | 200 | static sector_t _fat_bmap(struct address_space *mapping, sector_t block) |
200 | { | 201 | { |
201 | return generic_block_bmap(mapping, block, fat_get_block); | 202 | sector_t blocknr; |
203 | |||
204 | /* fat_get_cluster() assumes the requested blocknr isn't truncated. */ | ||
205 | mutex_lock(&mapping->host->i_mutex); | ||
206 | blocknr = generic_block_bmap(mapping, block, fat_get_block); | ||
207 | mutex_unlock(&mapping->host->i_mutex); | ||
208 | |||
209 | return blocknr; | ||
202 | } | 210 | } |
203 | 211 | ||
204 | static const struct address_space_operations fat_aops = { | 212 | static const struct address_space_operations fat_aops = { |
@@ -247,25 +255,21 @@ static void fat_hash_init(struct super_block *sb) | |||
247 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); | 255 | INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); |
248 | } | 256 | } |
249 | 257 | ||
250 | static inline unsigned long fat_hash(struct super_block *sb, loff_t i_pos) | 258 | static inline unsigned long fat_hash(loff_t i_pos) |
251 | { | 259 | { |
252 | unsigned long tmp = (unsigned long)i_pos | (unsigned long) sb; | 260 | return hash_32(i_pos, FAT_HASH_BITS); |
253 | tmp = tmp + (tmp >> FAT_HASH_BITS) + (tmp >> FAT_HASH_BITS * 2); | ||
254 | return tmp & FAT_HASH_MASK; | ||
255 | } | 261 | } |
256 | 262 | ||
257 | void fat_attach(struct inode *inode, loff_t i_pos) | 263 | void fat_attach(struct inode *inode, loff_t i_pos) |
258 | { | 264 | { |
259 | struct super_block *sb = inode->i_sb; | 265 | struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); |
260 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 266 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
261 | 267 | ||
262 | spin_lock(&sbi->inode_hash_lock); | 268 | spin_lock(&sbi->inode_hash_lock); |
263 | MSDOS_I(inode)->i_pos = i_pos; | 269 | MSDOS_I(inode)->i_pos = i_pos; |
264 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, | 270 | hlist_add_head(&MSDOS_I(inode)->i_fat_hash, head); |
265 | sbi->inode_hashtable + fat_hash(sb, i_pos)); | ||
266 | spin_unlock(&sbi->inode_hash_lock); | 271 | spin_unlock(&sbi->inode_hash_lock); |
267 | } | 272 | } |
268 | |||
269 | EXPORT_SYMBOL_GPL(fat_attach); | 273 | EXPORT_SYMBOL_GPL(fat_attach); |
270 | 274 | ||
271 | void fat_detach(struct inode *inode) | 275 | void fat_detach(struct inode *inode) |
@@ -276,13 +280,12 @@ void fat_detach(struct inode *inode) | |||
276 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 280 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); |
277 | spin_unlock(&sbi->inode_hash_lock); | 281 | spin_unlock(&sbi->inode_hash_lock); |
278 | } | 282 | } |
279 | |||
280 | EXPORT_SYMBOL_GPL(fat_detach); | 283 | EXPORT_SYMBOL_GPL(fat_detach); |
281 | 284 | ||
282 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) | 285 | struct inode *fat_iget(struct super_block *sb, loff_t i_pos) |
283 | { | 286 | { |
284 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 287 | struct msdos_sb_info *sbi = MSDOS_SB(sb); |
285 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(sb, i_pos); | 288 | struct hlist_head *head = sbi->inode_hashtable + fat_hash(i_pos); |
286 | struct hlist_node *_p; | 289 | struct hlist_node *_p; |
287 | struct msdos_inode_info *i; | 290 | struct msdos_inode_info *i; |
288 | struct inode *inode = NULL; | 291 | struct inode *inode = NULL; |
@@ -341,8 +344,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
341 | 344 | ||
342 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { | 345 | if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { |
343 | inode->i_generation &= ~1; | 346 | inode->i_generation &= ~1; |
344 | inode->i_mode = MSDOS_MKMODE(de->attr, | 347 | inode->i_mode = fat_make_mode(sbi, de->attr, S_IRWXUGO); |
345 | S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | ||
346 | inode->i_op = sbi->dir_ops; | 348 | inode->i_op = sbi->dir_ops; |
347 | inode->i_fop = &fat_dir_operations; | 349 | inode->i_fop = &fat_dir_operations; |
348 | 350 | ||
@@ -359,10 +361,9 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
359 | inode->i_nlink = fat_subdirs(inode); | 361 | inode->i_nlink = fat_subdirs(inode); |
360 | } else { /* not a directory */ | 362 | } else { /* not a directory */ |
361 | inode->i_generation |= 1; | 363 | inode->i_generation |= 1; |
362 | inode->i_mode = MSDOS_MKMODE(de->attr, | 364 | inode->i_mode = fat_make_mode(sbi, de->attr, |
363 | ((sbi->options.showexec && !is_exec(de->name + 8)) | 365 | ((sbi->options.showexec && !is_exec(de->name + 8)) |
364 | ? S_IRUGO|S_IWUGO : S_IRWXUGO) | 366 | ? S_IRUGO|S_IWUGO : S_IRWXUGO)); |
365 | & ~sbi->options.fs_fmask) | S_IFREG; | ||
366 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); | 367 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); |
367 | if (sbi->fat_bits == 32) | 368 | if (sbi->fat_bits == 32) |
368 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); | 369 | MSDOS_I(inode)->i_start |= (le16_to_cpu(de->starthi) << 16); |
@@ -378,25 +379,16 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
378 | if (sbi->options.sys_immutable) | 379 | if (sbi->options.sys_immutable) |
379 | inode->i_flags |= S_IMMUTABLE; | 380 | inode->i_flags |= S_IMMUTABLE; |
380 | } | 381 | } |
381 | MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED; | 382 | fat_save_attrs(inode, de->attr); |
383 | |||
382 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) | 384 | inode->i_blocks = ((inode->i_size + (sbi->cluster_size - 1)) |
383 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; | 385 | & ~((loff_t)sbi->cluster_size - 1)) >> 9; |
384 | inode->i_mtime.tv_sec = | 386 | |
385 | date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date), | 387 | fat_time_fat2unix(sbi, &inode->i_mtime, de->time, de->date, 0); |
386 | sbi->options.tz_utc); | ||
387 | inode->i_mtime.tv_nsec = 0; | ||
388 | if (sbi->options.isvfat) { | 388 | if (sbi->options.isvfat) { |
389 | int secs = de->ctime_cs / 100; | 389 | fat_time_fat2unix(sbi, &inode->i_ctime, de->ctime, |
390 | int csecs = de->ctime_cs % 100; | 390 | de->cdate, de->ctime_cs); |
391 | inode->i_ctime.tv_sec = | 391 | fat_time_fat2unix(sbi, &inode->i_atime, 0, de->adate, 0); |
392 | date_dos2unix(le16_to_cpu(de->ctime), | ||
393 | le16_to_cpu(de->cdate), | ||
394 | sbi->options.tz_utc) + secs; | ||
395 | inode->i_ctime.tv_nsec = csecs * 10000000; | ||
396 | inode->i_atime.tv_sec = | ||
397 | date_dos2unix(0, le16_to_cpu(de->adate), | ||
398 | sbi->options.tz_utc); | ||
399 | inode->i_atime.tv_nsec = 0; | ||
400 | } else | 392 | } else |
401 | inode->i_ctime = inode->i_atime = inode->i_mtime; | 393 | inode->i_ctime = inode->i_atime = inode->i_mtime; |
402 | 394 | ||
@@ -443,13 +435,8 @@ static void fat_delete_inode(struct inode *inode) | |||
443 | 435 | ||
444 | static void fat_clear_inode(struct inode *inode) | 436 | static void fat_clear_inode(struct inode *inode) |
445 | { | 437 | { |
446 | struct super_block *sb = inode->i_sb; | ||
447 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | ||
448 | |||
449 | spin_lock(&sbi->inode_hash_lock); | ||
450 | fat_cache_inval_inode(inode); | 438 | fat_cache_inval_inode(inode); |
451 | hlist_del_init(&MSDOS_I(inode)->i_fat_hash); | 439 | fat_detach(inode); |
452 | spin_unlock(&sbi->inode_hash_lock); | ||
453 | } | 440 | } |
454 | 441 | ||
455 | static void fat_write_super(struct super_block *sb) | 442 | static void fat_write_super(struct super_block *sb) |
@@ -555,6 +542,20 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
555 | return 0; | 542 | return 0; |
556 | } | 543 | } |
557 | 544 | ||
545 | static inline loff_t fat_i_pos_read(struct msdos_sb_info *sbi, | ||
546 | struct inode *inode) | ||
547 | { | ||
548 | loff_t i_pos; | ||
549 | #if BITS_PER_LONG == 32 | ||
550 | spin_lock(&sbi->inode_hash_lock); | ||
551 | #endif | ||
552 | i_pos = MSDOS_I(inode)->i_pos; | ||
553 | #if BITS_PER_LONG == 32 | ||
554 | spin_unlock(&sbi->inode_hash_lock); | ||
555 | #endif | ||
556 | return i_pos; | ||
557 | } | ||
558 | |||
558 | static int fat_write_inode(struct inode *inode, int wait) | 559 | static int fat_write_inode(struct inode *inode, int wait) |
559 | { | 560 | { |
560 | struct super_block *sb = inode->i_sb; | 561 | struct super_block *sb = inode->i_sb; |
@@ -564,9 +565,12 @@ static int fat_write_inode(struct inode *inode, int wait) | |||
564 | loff_t i_pos; | 565 | loff_t i_pos; |
565 | int err; | 566 | int err; |
566 | 567 | ||
568 | if (inode->i_ino == MSDOS_ROOT_INO) | ||
569 | return 0; | ||
570 | |||
567 | retry: | 571 | retry: |
568 | i_pos = MSDOS_I(inode)->i_pos; | 572 | i_pos = fat_i_pos_read(sbi, inode); |
569 | if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) | 573 | if (!i_pos) |
570 | return 0; | 574 | return 0; |
571 | 575 | ||
572 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); | 576 | bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits); |
@@ -588,19 +592,17 @@ retry: | |||
588 | raw_entry->size = 0; | 592 | raw_entry->size = 0; |
589 | else | 593 | else |
590 | raw_entry->size = cpu_to_le32(inode->i_size); | 594 | raw_entry->size = cpu_to_le32(inode->i_size); |
591 | raw_entry->attr = fat_attr(inode); | 595 | raw_entry->attr = fat_make_attrs(inode); |
592 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); | 596 | raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart); |
593 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); | 597 | raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16); |
594 | fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, | 598 | fat_time_unix2fat(sbi, &inode->i_mtime, &raw_entry->time, |
595 | &raw_entry->date, sbi->options.tz_utc); | 599 | &raw_entry->date, NULL); |
596 | if (sbi->options.isvfat) { | 600 | if (sbi->options.isvfat) { |
597 | __le16 atime; | 601 | __le16 atime; |
598 | fat_date_unix2dos(inode->i_ctime.tv_sec, &raw_entry->ctime, | 602 | fat_time_unix2fat(sbi, &inode->i_ctime, &raw_entry->ctime, |
599 | &raw_entry->cdate, sbi->options.tz_utc); | 603 | &raw_entry->cdate, &raw_entry->ctime_cs); |
600 | fat_date_unix2dos(inode->i_atime.tv_sec, &atime, | 604 | fat_time_unix2fat(sbi, &inode->i_atime, &atime, |
601 | &raw_entry->adate, sbi->options.tz_utc); | 605 | &raw_entry->adate, NULL); |
602 | raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 + | ||
603 | inode->i_ctime.tv_nsec / 10000000; | ||
604 | } | 606 | } |
605 | spin_unlock(&sbi->inode_hash_lock); | 607 | spin_unlock(&sbi->inode_hash_lock); |
606 | mark_buffer_dirty(bh); | 608 | mark_buffer_dirty(bh); |
@@ -819,8 +821,10 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) | |||
819 | seq_puts(m, ",uni_xlate"); | 821 | seq_puts(m, ",uni_xlate"); |
820 | if (!opts->numtail) | 822 | if (!opts->numtail) |
821 | seq_puts(m, ",nonumtail"); | 823 | seq_puts(m, ",nonumtail"); |
824 | if (opts->rodir) | ||
825 | seq_puts(m, ",rodir"); | ||
822 | } | 826 | } |
823 | if (sbi->options.flush) | 827 | if (opts->flush) |
824 | seq_puts(m, ",flush"); | 828 | seq_puts(m, ",flush"); |
825 | if (opts->tz_utc) | 829 | if (opts->tz_utc) |
826 | seq_puts(m, ",tz=UTC"); | 830 | seq_puts(m, ",tz=UTC"); |
@@ -836,7 +840,7 @@ enum { | |||
836 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, | 840 | Opt_charset, Opt_shortname_lower, Opt_shortname_win95, |
837 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, | 841 | Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, |
838 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, | 842 | Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, |
839 | Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_err, | 843 | Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err, |
840 | }; | 844 | }; |
841 | 845 | ||
842 | static const match_table_t fat_tokens = { | 846 | static const match_table_t fat_tokens = { |
@@ -908,6 +912,7 @@ static const match_table_t vfat_tokens = { | |||
908 | {Opt_nonumtail_yes, "nonumtail=yes"}, | 912 | {Opt_nonumtail_yes, "nonumtail=yes"}, |
909 | {Opt_nonumtail_yes, "nonumtail=true"}, | 913 | {Opt_nonumtail_yes, "nonumtail=true"}, |
910 | {Opt_nonumtail_yes, "nonumtail"}, | 914 | {Opt_nonumtail_yes, "nonumtail"}, |
915 | {Opt_rodir, "rodir"}, | ||
911 | {Opt_err, NULL} | 916 | {Opt_err, NULL} |
912 | }; | 917 | }; |
913 | 918 | ||
@@ -927,10 +932,13 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
927 | opts->allow_utime = -1; | 932 | opts->allow_utime = -1; |
928 | opts->codepage = fat_default_codepage; | 933 | opts->codepage = fat_default_codepage; |
929 | opts->iocharset = fat_default_iocharset; | 934 | opts->iocharset = fat_default_iocharset; |
930 | if (is_vfat) | 935 | if (is_vfat) { |
931 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; | 936 | opts->shortname = VFAT_SFN_DISPLAY_LOWER|VFAT_SFN_CREATE_WIN95; |
932 | else | 937 | opts->rodir = 0; |
938 | } else { | ||
933 | opts->shortname = 0; | 939 | opts->shortname = 0; |
940 | opts->rodir = 1; | ||
941 | } | ||
934 | opts->name_check = 'n'; | 942 | opts->name_check = 'n'; |
935 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; | 943 | opts->quiet = opts->showexec = opts->sys_immutable = opts->dotsOK = 0; |
936 | opts->utf8 = opts->unicode_xlate = 0; | 944 | opts->utf8 = opts->unicode_xlate = 0; |
@@ -1081,6 +1089,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, | |||
1081 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ | 1089 | case Opt_nonumtail_yes: /* empty or 1 or yes or true */ |
1082 | opts->numtail = 0; /* negated option */ | 1090 | opts->numtail = 0; /* negated option */ |
1083 | break; | 1091 | break; |
1092 | case Opt_rodir: | ||
1093 | opts->rodir = 1; | ||
1094 | break; | ||
1084 | 1095 | ||
1085 | /* obsolete mount options */ | 1096 | /* obsolete mount options */ |
1086 | case Opt_obsolate: | 1097 | case Opt_obsolate: |
@@ -1126,7 +1137,7 @@ static int fat_read_root(struct inode *inode) | |||
1126 | inode->i_gid = sbi->options.fs_gid; | 1137 | inode->i_gid = sbi->options.fs_gid; |
1127 | inode->i_version++; | 1138 | inode->i_version++; |
1128 | inode->i_generation = 0; | 1139 | inode->i_generation = 0; |
1129 | inode->i_mode = (S_IRWXUGO & ~sbi->options.fs_dmask) | S_IFDIR; | 1140 | inode->i_mode = fat_make_mode(sbi, ATTR_DIR, S_IRWXUGO); |
1130 | inode->i_op = sbi->dir_ops; | 1141 | inode->i_op = sbi->dir_ops; |
1131 | inode->i_fop = &fat_dir_operations; | 1142 | inode->i_fop = &fat_dir_operations; |
1132 | if (sbi->fat_bits == 32) { | 1143 | if (sbi->fat_bits == 32) { |
@@ -1143,7 +1154,7 @@ static int fat_read_root(struct inode *inode) | |||
1143 | MSDOS_I(inode)->i_logstart = 0; | 1154 | MSDOS_I(inode)->i_logstart = 0; |
1144 | MSDOS_I(inode)->mmu_private = inode->i_size; | 1155 | MSDOS_I(inode)->mmu_private = inode->i_size; |
1145 | 1156 | ||
1146 | MSDOS_I(inode)->i_attrs = ATTR_NONE; | 1157 | fat_save_attrs(inode, ATTR_DIR); |
1147 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; | 1158 | inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0; |
1148 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; | 1159 | inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0; |
1149 | inode->i_nlink = fat_subdirs(inode)+2; | 1160 | inode->i_nlink = fat_subdirs(inode)+2; |
diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 79fb98ad36d4..ac39ebcc1496 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c | |||
@@ -8,8 +8,8 @@ | |||
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/msdos_fs.h> | ||
12 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
12 | #include "fat.h" | ||
13 | 13 | ||
14 | /* | 14 | /* |
15 | * fat_fs_panic reports a severe file system problem and sets the file system | 15 | * fat_fs_panic reports a severe file system problem and sets the file system |
@@ -124,8 +124,9 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster) | |||
124 | mark_inode_dirty(inode); | 124 | mark_inode_dirty(inode); |
125 | } | 125 | } |
126 | if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) { | 126 | if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) { |
127 | fat_fs_panic(sb, "clusters badly computed (%d != %lu)", | 127 | fat_fs_panic(sb, "clusters badly computed (%d != %llu)", |
128 | new_fclus, inode->i_blocks >> (sbi->cluster_bits - 9)); | 128 | new_fclus, |
129 | (llu)(inode->i_blocks >> (sbi->cluster_bits - 9))); | ||
129 | fat_cache_inval_inode(inode); | 130 | fat_cache_inval_inode(inode); |
130 | } | 131 | } |
131 | inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9); | 132 | inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9); |
@@ -135,65 +136,131 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster) | |||
135 | 136 | ||
136 | extern struct timezone sys_tz; | 137 | extern struct timezone sys_tz; |
137 | 138 | ||
139 | /* | ||
140 | * The epoch of FAT timestamp is 1980. | ||
141 | * : bits : value | ||
142 | * date: 0 - 4: day (1 - 31) | ||
143 | * date: 5 - 8: month (1 - 12) | ||
144 | * date: 9 - 15: year (0 - 127) from 1980 | ||
145 | * time: 0 - 4: sec (0 - 29) 2sec counts | ||
146 | * time: 5 - 10: min (0 - 59) | ||
147 | * time: 11 - 15: hour (0 - 23) | ||
148 | */ | ||
149 | #define SECS_PER_MIN 60 | ||
150 | #define SECS_PER_HOUR (60 * 60) | ||
151 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) | ||
152 | #define UNIX_SECS_1980 315532800L | ||
153 | #if BITS_PER_LONG == 64 | ||
154 | #define UNIX_SECS_2108 4354819200L | ||
155 | #endif | ||
156 | /* days between 1.1.70 and 1.1.80 (2 leap days) */ | ||
157 | #define DAYS_DELTA (365 * 10 + 2) | ||
158 | /* 120 (2100 - 1980) isn't leap year */ | ||
159 | #define YEAR_2100 120 | ||
160 | #define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != YEAR_2100) | ||
161 | |||
138 | /* Linear day numbers of the respective 1sts in non-leap years. */ | 162 | /* Linear day numbers of the respective 1sts in non-leap years. */ |
139 | static int day_n[] = { | 163 | static time_t days_in_year[] = { |
140 | /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ | 164 | /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ |
141 | 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, 0 | 165 | 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, |
142 | }; | 166 | }; |
143 | 167 | ||
144 | /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ | 168 | /* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ |
145 | int date_dos2unix(unsigned short time, unsigned short date, int tz_utc) | 169 | void fat_time_fat2unix(struct msdos_sb_info *sbi, struct timespec *ts, |
170 | __le16 __time, __le16 __date, u8 time_cs) | ||
146 | { | 171 | { |
147 | int month, year, secs; | 172 | u16 time = le16_to_cpu(__time), date = le16_to_cpu(__date); |
173 | time_t second, day, leap_day, month, year; | ||
148 | 174 | ||
149 | /* | 175 | year = date >> 9; |
150 | * first subtract and mask after that... Otherwise, if | 176 | month = max(1, (date >> 5) & 0xf); |
151 | * date == 0, bad things happen | 177 | day = max(1, date & 0x1f) - 1; |
152 | */ | 178 | |
153 | month = ((date >> 5) - 1) & 15; | 179 | leap_day = (year + 3) / 4; |
154 | year = date >> 9; | 180 | if (year > YEAR_2100) /* 2100 isn't leap year */ |
155 | secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* | 181 | leap_day--; |
156 | ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && | 182 | if (IS_LEAP_YEAR(year) && month > 2) |
157 | month < 2 ? 1 : 0)+3653); | 183 | leap_day++; |
158 | /* days since 1.1.70 plus 80's leap day */ | 184 | |
159 | if (!tz_utc) | 185 | second = (time & 0x1f) << 1; |
160 | secs += sys_tz.tz_minuteswest*60; | 186 | second += ((time >> 5) & 0x3f) * SECS_PER_MIN; |
161 | return secs; | 187 | second += (time >> 11) * SECS_PER_HOUR; |
188 | second += (year * 365 + leap_day | ||
189 | + days_in_year[month] + day | ||
190 | + DAYS_DELTA) * SECS_PER_DAY; | ||
191 | |||
192 | if (!sbi->options.tz_utc) | ||
193 | second += sys_tz.tz_minuteswest * SECS_PER_MIN; | ||
194 | |||
195 | if (time_cs) { | ||
196 | ts->tv_sec = second + (time_cs / 100); | ||
197 | ts->tv_nsec = (time_cs % 100) * 10000000; | ||
198 | } else { | ||
199 | ts->tv_sec = second; | ||
200 | ts->tv_nsec = 0; | ||
201 | } | ||
162 | } | 202 | } |
163 | 203 | ||
164 | /* Convert linear UNIX date to a MS-DOS time/date pair. */ | 204 | /* Convert linear UNIX date to a FAT time/date pair. */ |
165 | void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, int tz_utc) | 205 | void fat_time_unix2fat(struct msdos_sb_info *sbi, struct timespec *ts, |
206 | __le16 *time, __le16 *date, u8 *time_cs) | ||
166 | { | 207 | { |
167 | int day, year, nl_day, month; | 208 | time_t second = ts->tv_sec; |
209 | time_t day, leap_day, month, year; | ||
168 | 210 | ||
169 | if (!tz_utc) | 211 | if (!sbi->options.tz_utc) |
170 | unix_date -= sys_tz.tz_minuteswest*60; | 212 | second -= sys_tz.tz_minuteswest * SECS_PER_MIN; |
171 | 213 | ||
172 | /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ | 214 | /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ |
173 | if (unix_date < 315532800) | 215 | if (second < UNIX_SECS_1980) { |
174 | unix_date = 315532800; | 216 | *time = 0; |
175 | 217 | *date = cpu_to_le16((0 << 9) | (1 << 5) | 1); | |
176 | *time = cpu_to_le16((unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ | 218 | if (time_cs) |
177 | (((unix_date/3600) % 24) << 11)); | 219 | *time_cs = 0; |
178 | day = unix_date/86400-3652; | 220 | return; |
179 | year = day/365; | 221 | } |
180 | if ((year+3)/4+365*year > day) | 222 | #if BITS_PER_LONG == 64 |
223 | if (second >= UNIX_SECS_2108) { | ||
224 | *time = cpu_to_le16((23 << 11) | (59 << 5) | 29); | ||
225 | *date = cpu_to_le16((127 << 9) | (12 << 5) | 31); | ||
226 | if (time_cs) | ||
227 | *time_cs = 199; | ||
228 | return; | ||
229 | } | ||
230 | #endif | ||
231 | |||
232 | day = second / SECS_PER_DAY - DAYS_DELTA; | ||
233 | year = day / 365; | ||
234 | leap_day = (year + 3) / 4; | ||
235 | if (year > YEAR_2100) /* 2100 isn't leap year */ | ||
236 | leap_day--; | ||
237 | if (year * 365 + leap_day > day) | ||
181 | year--; | 238 | year--; |
182 | day -= (year+3)/4+365*year; | 239 | leap_day = (year + 3) / 4; |
183 | if (day == 59 && !(year & 3)) { | 240 | if (year > YEAR_2100) /* 2100 isn't leap year */ |
184 | nl_day = day; | 241 | leap_day--; |
242 | day -= year * 365 + leap_day; | ||
243 | |||
244 | if (IS_LEAP_YEAR(year) && day == days_in_year[3]) { | ||
185 | month = 2; | 245 | month = 2; |
186 | } else { | 246 | } else { |
187 | nl_day = (year & 3) || day <= 59 ? day : day-1; | 247 | if (IS_LEAP_YEAR(year) && day > days_in_year[3]) |
188 | for (month = 0; month < 12; month++) { | 248 | day--; |
189 | if (day_n[month] > nl_day) | 249 | for (month = 1; month < 12; month++) { |
250 | if (days_in_year[month + 1] > day) | ||
190 | break; | 251 | break; |
191 | } | 252 | } |
192 | } | 253 | } |
193 | *date = cpu_to_le16(nl_day-day_n[month-1]+1+(month << 5)+(year << 9)); | 254 | day -= days_in_year[month]; |
194 | } | ||
195 | 255 | ||
196 | EXPORT_SYMBOL_GPL(fat_date_unix2dos); | 256 | *time = cpu_to_le16(((second / SECS_PER_HOUR) % 24) << 11 |
257 | | ((second / SECS_PER_MIN) % 60) << 5 | ||
258 | | (second % SECS_PER_MIN) >> 1); | ||
259 | *date = cpu_to_le16((year << 9) | (month << 5) | (day + 1)); | ||
260 | if (time_cs) | ||
261 | *time_cs = (ts->tv_sec & 1) * 100 + ts->tv_nsec / 10000000; | ||
262 | } | ||
263 | EXPORT_SYMBOL_GPL(fat_time_unix2fat); | ||
197 | 264 | ||
198 | int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) | 265 | int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) |
199 | { | 266 | { |
diff --git a/fs/msdos/namei.c b/fs/fat/namei_msdos.c index e844b9809d27..7ba03a4acbe0 100644 --- a/fs/msdos/namei.c +++ b/fs/fat/namei_msdos.c | |||
@@ -9,8 +9,8 @@ | |||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/time.h> | 10 | #include <linux/time.h> |
11 | #include <linux/buffer_head.h> | 11 | #include <linux/buffer_head.h> |
12 | #include <linux/msdos_fs.h> | ||
13 | #include <linux/smp_lock.h> | 12 | #include <linux/smp_lock.h> |
13 | #include "fat.h" | ||
14 | 14 | ||
15 | /* Characters that are undesirable in an MS-DOS file name */ | 15 | /* Characters that are undesirable in an MS-DOS file name */ |
16 | static unsigned char bad_chars[] = "*?<>|\""; | 16 | static unsigned char bad_chars[] = "*?<>|\""; |
@@ -203,33 +203,37 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, | |||
203 | { | 203 | { |
204 | struct super_block *sb = dir->i_sb; | 204 | struct super_block *sb = dir->i_sb; |
205 | struct fat_slot_info sinfo; | 205 | struct fat_slot_info sinfo; |
206 | struct inode *inode = NULL; | 206 | struct inode *inode; |
207 | int res; | 207 | int err; |
208 | |||
209 | dentry->d_op = &msdos_dentry_operations; | ||
210 | 208 | ||
211 | lock_super(sb); | 209 | lock_super(sb); |
212 | res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); | 210 | |
213 | if (res == -ENOENT) | 211 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); |
214 | goto add; | 212 | if (err) { |
215 | if (res < 0) | 213 | if (err == -ENOENT) { |
216 | goto out; | 214 | inode = NULL; |
215 | goto out; | ||
216 | } | ||
217 | goto error; | ||
218 | } | ||
219 | |||
217 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); | 220 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); |
218 | brelse(sinfo.bh); | 221 | brelse(sinfo.bh); |
219 | if (IS_ERR(inode)) { | 222 | if (IS_ERR(inode)) { |
220 | res = PTR_ERR(inode); | 223 | err = PTR_ERR(inode); |
221 | goto out; | 224 | goto error; |
222 | } | 225 | } |
223 | add: | 226 | out: |
224 | res = 0; | 227 | unlock_super(sb); |
228 | dentry->d_op = &msdos_dentry_operations; | ||
225 | dentry = d_splice_alias(inode, dentry); | 229 | dentry = d_splice_alias(inode, dentry); |
226 | if (dentry) | 230 | if (dentry) |
227 | dentry->d_op = &msdos_dentry_operations; | 231 | dentry->d_op = &msdos_dentry_operations; |
228 | out: | 232 | return dentry; |
233 | |||
234 | error: | ||
229 | unlock_super(sb); | 235 | unlock_super(sb); |
230 | if (!res) | 236 | return ERR_PTR(err); |
231 | return dentry; | ||
232 | return ERR_PTR(res); | ||
233 | } | 237 | } |
234 | 238 | ||
235 | /***** Creates a directory entry (name is already formatted). */ | 239 | /***** Creates a directory entry (name is already formatted). */ |
@@ -247,7 +251,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, | |||
247 | if (is_hid) | 251 | if (is_hid) |
248 | de.attr |= ATTR_HIDDEN; | 252 | de.attr |= ATTR_HIDDEN; |
249 | de.lcase = 0; | 253 | de.lcase = 0; |
250 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); | 254 | fat_time_unix2fat(sbi, ts, &time, &date, NULL); |
251 | de.cdate = de.adate = 0; | 255 | de.cdate = de.adate = 0; |
252 | de.ctime = 0; | 256 | de.ctime = 0; |
253 | de.ctime_cs = 0; | 257 | de.ctime_cs = 0; |
diff --git a/fs/vfat/namei.c b/fs/fat/namei_vfat.c index 155c10b4adbd..bf326d4356a3 100644 --- a/fs/vfat/namei.c +++ b/fs/fat/namei_vfat.c | |||
@@ -16,36 +16,75 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | |||
20 | #include <linux/jiffies.h> | 19 | #include <linux/jiffies.h> |
21 | #include <linux/msdos_fs.h> | ||
22 | #include <linux/ctype.h> | 20 | #include <linux/ctype.h> |
23 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
24 | #include <linux/smp_lock.h> | 22 | #include <linux/smp_lock.h> |
25 | #include <linux/buffer_head.h> | 23 | #include <linux/buffer_head.h> |
26 | #include <linux/namei.h> | 24 | #include <linux/namei.h> |
25 | #include "fat.h" | ||
27 | 26 | ||
28 | static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) | 27 | /* |
28 | * If new entry was created in the parent, it could create the 8.3 | ||
29 | * alias (the shortname of logname). So, the parent may have the | ||
30 | * negative-dentry which matches the created 8.3 alias. | ||
31 | * | ||
32 | * If it happened, the negative dentry isn't actually negative | ||
33 | * anymore. So, drop it. | ||
34 | */ | ||
35 | static int vfat_revalidate_shortname(struct dentry *dentry) | ||
29 | { | 36 | { |
30 | int ret = 1; | 37 | int ret = 1; |
31 | 38 | spin_lock(&dentry->d_lock); | |
32 | if (!dentry->d_inode && | 39 | if (dentry->d_time != dentry->d_parent->d_inode->i_version) |
33 | nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_CREATE)) | ||
34 | /* | ||
35 | * negative dentry is dropped, in order to make sure | ||
36 | * to use the name which a user desires if this is | ||
37 | * create path. | ||
38 | */ | ||
39 | ret = 0; | 40 | ret = 0; |
40 | else { | 41 | spin_unlock(&dentry->d_lock); |
41 | spin_lock(&dentry->d_lock); | ||
42 | if (dentry->d_time != dentry->d_parent->d_inode->i_version) | ||
43 | ret = 0; | ||
44 | spin_unlock(&dentry->d_lock); | ||
45 | } | ||
46 | return ret; | 42 | return ret; |
47 | } | 43 | } |
48 | 44 | ||
45 | static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd) | ||
46 | { | ||
47 | /* This is not negative dentry. Always valid. */ | ||
48 | if (dentry->d_inode) | ||
49 | return 1; | ||
50 | return vfat_revalidate_shortname(dentry); | ||
51 | } | ||
52 | |||
53 | static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd) | ||
54 | { | ||
55 | /* | ||
56 | * This is not negative dentry. Always valid. | ||
57 | * | ||
58 | * Note, rename() to existing directory entry will have ->d_inode, | ||
59 | * and will use existing name which isn't specified name by user. | ||
60 | * | ||
61 | * We may be able to drop this positive dentry here. But dropping | ||
62 | * positive dentry isn't good idea. So it's unsupported like | ||
63 | * rename("filename", "FILENAME") for now. | ||
64 | */ | ||
65 | if (dentry->d_inode) | ||
66 | return 1; | ||
67 | |||
68 | /* | ||
69 | * This may be nfsd (or something), anyway, we can't see the | ||
70 | * intent of this. So, since this can be for creation, drop it. | ||
71 | */ | ||
72 | if (!nd) | ||
73 | return 0; | ||
74 | |||
75 | /* | ||
76 | * Drop the negative dentry, in order to make sure to use the | ||
77 | * case sensitive name which is specified by user if this is | ||
78 | * for creation. | ||
79 | */ | ||
80 | if (!(nd->flags & (LOOKUP_CONTINUE | LOOKUP_PARENT))) { | ||
81 | if (nd->flags & LOOKUP_CREATE) | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | return vfat_revalidate_shortname(dentry); | ||
86 | } | ||
87 | |||
49 | /* returns the length of a struct qstr, ignoring trailing dots */ | 88 | /* returns the length of a struct qstr, ignoring trailing dots */ |
50 | static unsigned int vfat_striptail_len(struct qstr *qstr) | 89 | static unsigned int vfat_striptail_len(struct qstr *qstr) |
51 | { | 90 | { |
@@ -127,25 +166,16 @@ static int vfat_cmp(struct dentry *dentry, struct qstr *a, struct qstr *b) | |||
127 | return 1; | 166 | return 1; |
128 | } | 167 | } |
129 | 168 | ||
130 | static struct dentry_operations vfat_dentry_ops[4] = { | 169 | static struct dentry_operations vfat_ci_dentry_ops = { |
131 | { | 170 | .d_revalidate = vfat_revalidate_ci, |
132 | .d_hash = vfat_hashi, | 171 | .d_hash = vfat_hashi, |
133 | .d_compare = vfat_cmpi, | 172 | .d_compare = vfat_cmpi, |
134 | }, | 173 | }; |
135 | { | 174 | |
136 | .d_revalidate = vfat_revalidate, | 175 | static struct dentry_operations vfat_dentry_ops = { |
137 | .d_hash = vfat_hashi, | 176 | .d_revalidate = vfat_revalidate, |
138 | .d_compare = vfat_cmpi, | 177 | .d_hash = vfat_hash, |
139 | }, | 178 | .d_compare = vfat_cmp, |
140 | { | ||
141 | .d_hash = vfat_hash, | ||
142 | .d_compare = vfat_cmp, | ||
143 | }, | ||
144 | { | ||
145 | .d_revalidate = vfat_revalidate, | ||
146 | .d_hash = vfat_hash, | ||
147 | .d_compare = vfat_cmp, | ||
148 | } | ||
149 | }; | 179 | }; |
150 | 180 | ||
151 | /* Characters that are undesirable in an MS-DOS file name */ | 181 | /* Characters that are undesirable in an MS-DOS file name */ |
@@ -569,6 +599,7 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, | |||
569 | unsigned char msdos_name[MSDOS_NAME]; | 599 | unsigned char msdos_name[MSDOS_NAME]; |
570 | wchar_t *uname; | 600 | wchar_t *uname; |
571 | __le16 time, date; | 601 | __le16 time, date; |
602 | u8 time_cs; | ||
572 | int err, ulen, usize, i; | 603 | int err, ulen, usize, i; |
573 | loff_t offset; | 604 | loff_t offset; |
574 | 605 | ||
@@ -621,10 +652,10 @@ shortname: | |||
621 | memcpy(de->name, msdos_name, MSDOS_NAME); | 652 | memcpy(de->name, msdos_name, MSDOS_NAME); |
622 | de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; | 653 | de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; |
623 | de->lcase = lcase; | 654 | de->lcase = lcase; |
624 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); | 655 | fat_time_unix2fat(sbi, ts, &time, &date, &time_cs); |
625 | de->time = de->ctime = time; | 656 | de->time = de->ctime = time; |
626 | de->date = de->cdate = de->adate = date; | 657 | de->date = de->cdate = de->adate = date; |
627 | de->ctime_cs = 0; | 658 | de->ctime_cs = time_cs; |
628 | de->start = cpu_to_le16(cluster); | 659 | de->start = cpu_to_le16(cluster); |
629 | de->starthi = cpu_to_le16(cluster >> 16); | 660 | de->starthi = cpu_to_le16(cluster >> 16); |
630 | de->size = 0; | 661 | de->size = 0; |
@@ -683,46 +714,58 @@ static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry, | |||
683 | { | 714 | { |
684 | struct super_block *sb = dir->i_sb; | 715 | struct super_block *sb = dir->i_sb; |
685 | struct fat_slot_info sinfo; | 716 | struct fat_slot_info sinfo; |
686 | struct inode *inode = NULL; | 717 | struct inode *inode; |
687 | struct dentry *alias; | 718 | struct dentry *alias; |
688 | int err, table; | 719 | int err; |
689 | 720 | ||
690 | lock_super(sb); | 721 | lock_super(sb); |
691 | table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0; | ||
692 | dentry->d_op = &vfat_dentry_ops[table]; | ||
693 | 722 | ||
694 | err = vfat_find(dir, &dentry->d_name, &sinfo); | 723 | err = vfat_find(dir, &dentry->d_name, &sinfo); |
695 | if (err) { | 724 | if (err) { |
696 | table++; | 725 | if (err == -ENOENT) { |
726 | inode = NULL; | ||
727 | goto out; | ||
728 | } | ||
697 | goto error; | 729 | goto error; |
698 | } | 730 | } |
731 | |||
699 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); | 732 | inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos); |
700 | brelse(sinfo.bh); | 733 | brelse(sinfo.bh); |
701 | if (IS_ERR(inode)) { | 734 | if (IS_ERR(inode)) { |
702 | unlock_super(sb); | 735 | err = PTR_ERR(inode); |
703 | return ERR_CAST(inode); | 736 | goto error; |
704 | } | 737 | } |
705 | alias = d_find_alias(inode); | ||
706 | if (alias) { | ||
707 | if (d_invalidate(alias) == 0) | ||
708 | dput(alias); | ||
709 | else { | ||
710 | iput(inode); | ||
711 | unlock_super(sb); | ||
712 | return alias; | ||
713 | } | ||
714 | 738 | ||
739 | alias = d_find_alias(inode); | ||
740 | if (alias && !(alias->d_flags & DCACHE_DISCONNECTED)) { | ||
741 | /* | ||
742 | * This inode has non DCACHE_DISCONNECTED dentry. This | ||
743 | * means, the user did ->lookup() by an another name | ||
744 | * (longname vs 8.3 alias of it) in past. | ||
745 | * | ||
746 | * Switch to new one for reason of locality if possible. | ||
747 | */ | ||
748 | BUG_ON(d_unhashed(alias)); | ||
749 | if (!S_ISDIR(inode->i_mode)) | ||
750 | d_move(alias, dentry); | ||
751 | iput(inode); | ||
752 | unlock_super(sb); | ||
753 | return alias; | ||
715 | } | 754 | } |
716 | error: | 755 | out: |
717 | unlock_super(sb); | 756 | unlock_super(sb); |
718 | dentry->d_op = &vfat_dentry_ops[table]; | 757 | dentry->d_op = sb->s_root->d_op; |
719 | dentry->d_time = dentry->d_parent->d_inode->i_version; | 758 | dentry->d_time = dentry->d_parent->d_inode->i_version; |
720 | dentry = d_splice_alias(inode, dentry); | 759 | dentry = d_splice_alias(inode, dentry); |
721 | if (dentry) { | 760 | if (dentry) { |
722 | dentry->d_op = &vfat_dentry_ops[table]; | 761 | dentry->d_op = sb->s_root->d_op; |
723 | dentry->d_time = dentry->d_parent->d_inode->i_version; | 762 | dentry->d_time = dentry->d_parent->d_inode->i_version; |
724 | } | 763 | } |
725 | return dentry; | 764 | return dentry; |
765 | |||
766 | error: | ||
767 | unlock_super(sb); | ||
768 | return ERR_PTR(err); | ||
726 | } | 769 | } |
727 | 770 | ||
728 | static int vfat_create(struct inode *dir, struct dentry *dentry, int mode, | 771 | static int vfat_create(struct inode *dir, struct dentry *dentry, int mode, |
@@ -1014,9 +1057,9 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent) | |||
1014 | return res; | 1057 | return res; |
1015 | 1058 | ||
1016 | if (MSDOS_SB(sb)->options.name_check != 's') | 1059 | if (MSDOS_SB(sb)->options.name_check != 's') |
1017 | sb->s_root->d_op = &vfat_dentry_ops[0]; | 1060 | sb->s_root->d_op = &vfat_ci_dentry_ops; |
1018 | else | 1061 | else |
1019 | sb->s_root->d_op = &vfat_dentry_ops[2]; | 1062 | sb->s_root->d_op = &vfat_dentry_ops; |
1020 | 1063 | ||
1021 | return 0; | 1064 | return 0; |
1022 | } | 1065 | } |
diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 8adebd3e43c6..3cceef4ad2b7 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c | |||
@@ -85,15 +85,15 @@ static int jffs2_garbage_collect_thread(void *_c) | |||
85 | for (;;) { | 85 | for (;;) { |
86 | allow_signal(SIGHUP); | 86 | allow_signal(SIGHUP); |
87 | again: | 87 | again: |
88 | spin_lock(&c->erase_completion_lock); | ||
88 | if (!jffs2_thread_should_wake(c)) { | 89 | if (!jffs2_thread_should_wake(c)) { |
89 | set_current_state (TASK_INTERRUPTIBLE); | 90 | set_current_state (TASK_INTERRUPTIBLE); |
91 | spin_unlock(&c->erase_completion_lock); | ||
90 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); | 92 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); |
91 | /* Yes, there's a race here; we checked jffs2_thread_should_wake() | ||
92 | before setting current->state to TASK_INTERRUPTIBLE. But it doesn't | ||
93 | matter - We don't care if we miss a wakeup, because the GC thread | ||
94 | is only an optimisation anyway. */ | ||
95 | schedule(); | 93 | schedule(); |
96 | } | 94 | } else |
95 | spin_unlock(&c->erase_completion_lock); | ||
96 | |||
97 | 97 | ||
98 | /* This thread is purely an optimisation. But if it runs when | 98 | /* This thread is purely an optimisation. But if it runs when |
99 | other things could be running, it actually makes things a | 99 | other things could be running, it actually makes things a |
diff --git a/fs/jffs2/compr_lzo.c b/fs/jffs2/compr_lzo.c index 47b045797e42..90cb60d09787 100644 --- a/fs/jffs2/compr_lzo.c +++ b/fs/jffs2/compr_lzo.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | static void *lzo_mem; | 20 | static void *lzo_mem; |
21 | static void *lzo_compress_buf; | 21 | static void *lzo_compress_buf; |
22 | static DEFINE_MUTEX(deflate_mutex); | 22 | static DEFINE_MUTEX(deflate_mutex); /* for lzo_mem and lzo_compress_buf */ |
23 | 23 | ||
24 | static void free_workspace(void) | 24 | static void free_workspace(void) |
25 | { | 25 | { |
@@ -49,18 +49,21 @@ static int jffs2_lzo_compress(unsigned char *data_in, unsigned char *cpage_out, | |||
49 | 49 | ||
50 | mutex_lock(&deflate_mutex); | 50 | mutex_lock(&deflate_mutex); |
51 | ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); | 51 | ret = lzo1x_1_compress(data_in, *sourcelen, lzo_compress_buf, &compress_size, lzo_mem); |
52 | mutex_unlock(&deflate_mutex); | ||
53 | |||
54 | if (ret != LZO_E_OK) | 52 | if (ret != LZO_E_OK) |
55 | return -1; | 53 | goto fail; |
56 | 54 | ||
57 | if (compress_size > *dstlen) | 55 | if (compress_size > *dstlen) |
58 | return -1; | 56 | goto fail; |
59 | 57 | ||
60 | memcpy(cpage_out, lzo_compress_buf, compress_size); | 58 | memcpy(cpage_out, lzo_compress_buf, compress_size); |
61 | *dstlen = compress_size; | 59 | mutex_unlock(&deflate_mutex); |
62 | 60 | ||
61 | *dstlen = compress_size; | ||
63 | return 0; | 62 | return 0; |
63 | |||
64 | fail: | ||
65 | mutex_unlock(&deflate_mutex); | ||
66 | return -1; | ||
64 | } | 67 | } |
65 | 68 | ||
66 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, | 69 | static int jffs2_lzo_decompress(unsigned char *data_in, unsigned char *cpage_out, |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 0875b60b4bf7..21a052915aa9 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
@@ -261,9 +261,11 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) | |||
261 | 261 | ||
262 | jffs2_sum_reset_collected(c->summary); /* reset collected summary */ | 262 | jffs2_sum_reset_collected(c->summary); /* reset collected summary */ |
263 | 263 | ||
264 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | ||
264 | /* adjust write buffer offset, else we get a non contiguous write bug */ | 265 | /* adjust write buffer offset, else we get a non contiguous write bug */ |
265 | if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len) | 266 | if (!(c->wbuf_ofs % c->sector_size) && !c->wbuf_len) |
266 | c->wbuf_ofs = 0xffffffff; | 267 | c->wbuf_ofs = 0xffffffff; |
268 | #endif | ||
267 | 269 | ||
268 | D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); | 270 | D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); |
269 | 271 | ||
diff --git a/fs/msdos/Makefile b/fs/msdos/Makefile deleted file mode 100644 index ea67646fcb95..000000000000 --- a/fs/msdos/Makefile +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the Linux msdos filesystem routines. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_MSDOS_FS) += msdos.o | ||
6 | |||
7 | msdos-y := namei.o | ||
diff --git a/fs/vfat/Makefile b/fs/vfat/Makefile deleted file mode 100644 index 40f2798a4f08..000000000000 --- a/fs/vfat/Makefile +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for the linux vfat-filesystem routines. | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_VFAT_FS) += vfat.o | ||
6 | |||
7 | vfat-y := namei.o | ||
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index 2b3645b1acf4..07e510a3b00a 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h | |||
@@ -239,7 +239,7 @@ static inline void hrtimer_add_expires(struct hrtimer *timer, ktime_t time) | |||
239 | timer->_softexpires = ktime_add_safe(timer->_softexpires, time); | 239 | timer->_softexpires = ktime_add_safe(timer->_softexpires, time); |
240 | } | 240 | } |
241 | 241 | ||
242 | static inline void hrtimer_add_expires_ns(struct hrtimer *timer, unsigned long ns) | 242 | static inline void hrtimer_add_expires_ns(struct hrtimer *timer, u64 ns) |
243 | { | 243 | { |
244 | timer->_expires = ktime_add_ns(timer->_expires, ns); | 244 | timer->_expires = ktime_add_ns(timer->_expires, ns); |
245 | timer->_softexpires = ktime_add_ns(timer->_softexpires, ns); | 245 | timer->_softexpires = ktime_add_ns(timer->_softexpires, ns); |
diff --git a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h index ba63858056c7..e0a9b207920d 100644 --- a/include/linux/msdos_fs.h +++ b/include/linux/msdos_fs.h | |||
@@ -46,11 +46,6 @@ | |||
46 | #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ | 46 | #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ |
47 | #define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) | 47 | #define IS_FREE(n) (!*(n) || *(n) == DELETED_FLAG) |
48 | 48 | ||
49 | /* valid file mode bits */ | ||
50 | #define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO) | ||
51 | /* Convert attribute bits and a mask to the UNIX mode. */ | ||
52 | #define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) | ||
53 | |||
54 | #define MSDOS_NAME 11 /* maximum name length */ | 49 | #define MSDOS_NAME 11 /* maximum name length */ |
55 | #define MSDOS_LONGNAME 256 /* maximum name length */ | 50 | #define MSDOS_LONGNAME 256 /* maximum name length */ |
56 | #define MSDOS_SLOTS 21 /* max # of slots for short and long names */ | 51 | #define MSDOS_SLOTS 21 /* max # of slots for short and long names */ |
@@ -167,282 +162,10 @@ struct msdos_dir_slot { | |||
167 | }; | 162 | }; |
168 | 163 | ||
169 | #ifdef __KERNEL__ | 164 | #ifdef __KERNEL__ |
170 | |||
171 | #include <linux/buffer_head.h> | ||
172 | #include <linux/string.h> | ||
173 | #include <linux/nls.h> | ||
174 | #include <linux/fs.h> | ||
175 | #include <linux/mutex.h> | ||
176 | |||
177 | /* | ||
178 | * vfat shortname flags | ||
179 | */ | ||
180 | #define VFAT_SFN_DISPLAY_LOWER 0x0001 /* convert to lowercase for display */ | ||
181 | #define VFAT_SFN_DISPLAY_WIN95 0x0002 /* emulate win95 rule for display */ | ||
182 | #define VFAT_SFN_DISPLAY_WINNT 0x0004 /* emulate winnt rule for display */ | ||
183 | #define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ | ||
184 | #define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ | ||
185 | |||
186 | struct fat_mount_options { | ||
187 | uid_t fs_uid; | ||
188 | gid_t fs_gid; | ||
189 | unsigned short fs_fmask; | ||
190 | unsigned short fs_dmask; | ||
191 | unsigned short codepage; /* Codepage for shortname conversions */ | ||
192 | char *iocharset; /* Charset used for filename input/display */ | ||
193 | unsigned short shortname; /* flags for shortname display/create rule */ | ||
194 | unsigned char name_check; /* r = relaxed, n = normal, s = strict */ | ||
195 | unsigned short allow_utime;/* permission for setting the [am]time */ | ||
196 | unsigned quiet:1, /* set = fake successful chmods and chowns */ | ||
197 | showexec:1, /* set = only set x bit for com/exe/bat */ | ||
198 | sys_immutable:1, /* set = system files are immutable */ | ||
199 | dotsOK:1, /* set = hidden and system files are named '.filename' */ | ||
200 | isvfat:1, /* 0=no vfat long filename support, 1=vfat support */ | ||
201 | utf8:1, /* Use of UTF-8 character set (Default) */ | ||
202 | unicode_xlate:1, /* create escape sequences for unhandled Unicode */ | ||
203 | numtail:1, /* Does first alias have a numeric '~1' type tail? */ | ||
204 | flush:1, /* write things quickly */ | ||
205 | nocase:1, /* Does this need case conversion? 0=need case conversion*/ | ||
206 | usefree:1, /* Use free_clusters for FAT32 */ | ||
207 | tz_utc:1; /* Filesystem timestamps are in UTC */ | ||
208 | }; | ||
209 | |||
210 | #define FAT_HASH_BITS 8 | ||
211 | #define FAT_HASH_SIZE (1UL << FAT_HASH_BITS) | ||
212 | #define FAT_HASH_MASK (FAT_HASH_SIZE-1) | ||
213 | |||
214 | /* | ||
215 | * MS-DOS file system in-core superblock data | ||
216 | */ | ||
217 | struct msdos_sb_info { | ||
218 | unsigned short sec_per_clus; /* sectors/cluster */ | ||
219 | unsigned short cluster_bits; /* log2(cluster_size) */ | ||
220 | unsigned int cluster_size; /* cluster size */ | ||
221 | unsigned char fats,fat_bits; /* number of FATs, FAT bits (12 or 16) */ | ||
222 | unsigned short fat_start; | ||
223 | unsigned long fat_length; /* FAT start & length (sec.) */ | ||
224 | unsigned long dir_start; | ||
225 | unsigned short dir_entries; /* root dir start & entries */ | ||
226 | unsigned long data_start; /* first data sector */ | ||
227 | unsigned long max_cluster; /* maximum cluster number */ | ||
228 | unsigned long root_cluster; /* first cluster of the root directory */ | ||
229 | unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */ | ||
230 | struct mutex fat_lock; | ||
231 | unsigned int prev_free; /* previously allocated cluster number */ | ||
232 | unsigned int free_clusters; /* -1 if undefined */ | ||
233 | unsigned int free_clus_valid; /* is free_clusters valid? */ | ||
234 | struct fat_mount_options options; | ||
235 | struct nls_table *nls_disk; /* Codepage used on disk */ | ||
236 | struct nls_table *nls_io; /* Charset used for input and display */ | ||
237 | const void *dir_ops; /* Opaque; default directory operations */ | ||
238 | int dir_per_block; /* dir entries per block */ | ||
239 | int dir_per_block_bits; /* log2(dir_per_block) */ | ||
240 | |||
241 | int fatent_shift; | ||
242 | struct fatent_operations *fatent_ops; | ||
243 | |||
244 | spinlock_t inode_hash_lock; | ||
245 | struct hlist_head inode_hashtable[FAT_HASH_SIZE]; | ||
246 | }; | ||
247 | |||
248 | #define FAT_CACHE_VALID 0 /* special case for valid cache */ | ||
249 | |||
250 | /* | ||
251 | * MS-DOS file system inode data in memory | ||
252 | */ | ||
253 | struct msdos_inode_info { | ||
254 | spinlock_t cache_lru_lock; | ||
255 | struct list_head cache_lru; | ||
256 | int nr_caches; | ||
257 | /* for avoiding the race between fat_free() and fat_get_cluster() */ | ||
258 | unsigned int cache_valid_id; | ||
259 | |||
260 | loff_t mmu_private; | ||
261 | int i_start; /* first cluster or 0 */ | ||
262 | int i_logstart; /* logical first cluster */ | ||
263 | int i_attrs; /* unused attribute bits */ | ||
264 | loff_t i_pos; /* on-disk position of directory entry or 0 */ | ||
265 | struct hlist_node i_fat_hash; /* hash by i_location */ | ||
266 | struct inode vfs_inode; | ||
267 | }; | ||
268 | |||
269 | struct fat_slot_info { | ||
270 | loff_t i_pos; /* on-disk position of directory entry */ | ||
271 | loff_t slot_off; /* offset for slot or de start */ | ||
272 | int nr_slots; /* number of slots + 1(de) in filename */ | ||
273 | struct msdos_dir_entry *de; | ||
274 | struct buffer_head *bh; | ||
275 | }; | ||
276 | |||
277 | static inline struct msdos_sb_info *MSDOS_SB(struct super_block *sb) | ||
278 | { | ||
279 | return sb->s_fs_info; | ||
280 | } | ||
281 | |||
282 | static inline struct msdos_inode_info *MSDOS_I(struct inode *inode) | ||
283 | { | ||
284 | return container_of(inode, struct msdos_inode_info, vfs_inode); | ||
285 | } | ||
286 | |||
287 | /* Return the FAT attribute byte for this inode */ | ||
288 | static inline u8 fat_attr(struct inode *inode) | ||
289 | { | ||
290 | return ((inode->i_mode & S_IWUGO) ? ATTR_NONE : ATTR_RO) | | ||
291 | (S_ISDIR(inode->i_mode) ? ATTR_DIR : ATTR_NONE) | | ||
292 | MSDOS_I(inode)->i_attrs; | ||
293 | } | ||
294 | |||
295 | static inline unsigned char fat_checksum(const __u8 *name) | ||
296 | { | ||
297 | unsigned char s = name[0]; | ||
298 | s = (s<<7) + (s>>1) + name[1]; s = (s<<7) + (s>>1) + name[2]; | ||
299 | s = (s<<7) + (s>>1) + name[3]; s = (s<<7) + (s>>1) + name[4]; | ||
300 | s = (s<<7) + (s>>1) + name[5]; s = (s<<7) + (s>>1) + name[6]; | ||
301 | s = (s<<7) + (s>>1) + name[7]; s = (s<<7) + (s>>1) + name[8]; | ||
302 | s = (s<<7) + (s>>1) + name[9]; s = (s<<7) + (s>>1) + name[10]; | ||
303 | return s; | ||
304 | } | ||
305 | |||
306 | static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus) | ||
307 | { | ||
308 | return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus | ||
309 | + sbi->data_start; | ||
310 | } | ||
311 | |||
312 | static inline void fat16_towchar(wchar_t *dst, const __u8 *src, size_t len) | ||
313 | { | ||
314 | #ifdef __BIG_ENDIAN | ||
315 | while (len--) { | ||
316 | *dst++ = src[0] | (src[1] << 8); | ||
317 | src += 2; | ||
318 | } | ||
319 | #else | ||
320 | memcpy(dst, src, len * 2); | ||
321 | #endif | ||
322 | } | ||
323 | |||
324 | static inline void fatwchar_to16(__u8 *dst, const wchar_t *src, size_t len) | ||
325 | { | ||
326 | #ifdef __BIG_ENDIAN | ||
327 | while (len--) { | ||
328 | dst[0] = *src & 0x00FF; | ||
329 | dst[1] = (*src & 0xFF00) >> 8; | ||
330 | dst += 2; | ||
331 | src++; | ||
332 | } | ||
333 | #else | ||
334 | memcpy(dst, src, len * 2); | ||
335 | #endif | ||
336 | } | ||
337 | |||
338 | /* media of boot sector */ | 165 | /* media of boot sector */ |
339 | static inline int fat_valid_media(u8 media) | 166 | static inline int fat_valid_media(u8 media) |
340 | { | 167 | { |
341 | return 0xf8 <= media || media == 0xf0; | 168 | return 0xf8 <= media || media == 0xf0; |
342 | } | 169 | } |
343 | 170 | #endif /* !__KERNEL__ */ | |
344 | /* fat/cache.c */ | 171 | #endif /* !_LINUX_MSDOS_FS_H */ |
345 | extern void fat_cache_inval_inode(struct inode *inode); | ||
346 | extern int fat_get_cluster(struct inode *inode, int cluster, | ||
347 | int *fclus, int *dclus); | ||
348 | extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys, | ||
349 | unsigned long *mapped_blocks); | ||
350 | |||
351 | /* fat/dir.c */ | ||
352 | extern const struct file_operations fat_dir_operations; | ||
353 | extern int fat_search_long(struct inode *inode, const unsigned char *name, | ||
354 | int name_len, struct fat_slot_info *sinfo); | ||
355 | extern int fat_dir_empty(struct inode *dir); | ||
356 | extern int fat_subdirs(struct inode *dir); | ||
357 | extern int fat_scan(struct inode *dir, const unsigned char *name, | ||
358 | struct fat_slot_info *sinfo); | ||
359 | extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh, | ||
360 | struct msdos_dir_entry **de, loff_t *i_pos); | ||
361 | extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts); | ||
362 | extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots, | ||
363 | struct fat_slot_info *sinfo); | ||
364 | extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo); | ||
365 | |||
366 | /* fat/fatent.c */ | ||
367 | struct fat_entry { | ||
368 | int entry; | ||
369 | union { | ||
370 | u8 *ent12_p[2]; | ||
371 | __le16 *ent16_p; | ||
372 | __le32 *ent32_p; | ||
373 | } u; | ||
374 | int nr_bhs; | ||
375 | struct buffer_head *bhs[2]; | ||
376 | }; | ||
377 | |||
378 | static inline void fatent_init(struct fat_entry *fatent) | ||
379 | { | ||
380 | fatent->nr_bhs = 0; | ||
381 | fatent->entry = 0; | ||
382 | fatent->u.ent32_p = NULL; | ||
383 | fatent->bhs[0] = fatent->bhs[1] = NULL; | ||
384 | } | ||
385 | |||
386 | static inline void fatent_set_entry(struct fat_entry *fatent, int entry) | ||
387 | { | ||
388 | fatent->entry = entry; | ||
389 | fatent->u.ent32_p = NULL; | ||
390 | } | ||
391 | |||
392 | static inline void fatent_brelse(struct fat_entry *fatent) | ||
393 | { | ||
394 | int i; | ||
395 | fatent->u.ent32_p = NULL; | ||
396 | for (i = 0; i < fatent->nr_bhs; i++) | ||
397 | brelse(fatent->bhs[i]); | ||
398 | fatent->nr_bhs = 0; | ||
399 | fatent->bhs[0] = fatent->bhs[1] = NULL; | ||
400 | } | ||
401 | |||
402 | extern void fat_ent_access_init(struct super_block *sb); | ||
403 | extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent, | ||
404 | int entry); | ||
405 | extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent, | ||
406 | int new, int wait); | ||
407 | extern int fat_alloc_clusters(struct inode *inode, int *cluster, | ||
408 | int nr_cluster); | ||
409 | extern int fat_free_clusters(struct inode *inode, int cluster); | ||
410 | extern int fat_count_free_clusters(struct super_block *sb); | ||
411 | |||
412 | /* fat/file.c */ | ||
413 | extern int fat_generic_ioctl(struct inode *inode, struct file *filp, | ||
414 | unsigned int cmd, unsigned long arg); | ||
415 | extern const struct file_operations fat_file_operations; | ||
416 | extern const struct inode_operations fat_file_inode_operations; | ||
417 | extern int fat_setattr(struct dentry * dentry, struct iattr * attr); | ||
418 | extern void fat_truncate(struct inode *inode); | ||
419 | extern int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
420 | struct kstat *stat); | ||
421 | |||
422 | /* fat/inode.c */ | ||
423 | extern void fat_attach(struct inode *inode, loff_t i_pos); | ||
424 | extern void fat_detach(struct inode *inode); | ||
425 | extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos); | ||
426 | extern struct inode *fat_build_inode(struct super_block *sb, | ||
427 | struct msdos_dir_entry *de, loff_t i_pos); | ||
428 | extern int fat_sync_inode(struct inode *inode); | ||
429 | extern int fat_fill_super(struct super_block *sb, void *data, int silent, | ||
430 | const struct inode_operations *fs_dir_inode_ops, int isvfat); | ||
431 | |||
432 | extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, | ||
433 | struct inode *i2); | ||
434 | /* fat/misc.c */ | ||
435 | extern void fat_fs_panic(struct super_block *s, const char *fmt, ...); | ||
436 | extern void fat_clusters_flush(struct super_block *sb); | ||
437 | extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); | ||
438 | extern int date_dos2unix(unsigned short time, unsigned short date, int tz_utc); | ||
439 | extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date, | ||
440 | int tz_utc); | ||
441 | extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs); | ||
442 | |||
443 | int fat_cache_init(void); | ||
444 | void fat_cache_destroy(void); | ||
445 | |||
446 | #endif /* __KERNEL__ */ | ||
447 | |||
448 | #endif | ||
diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index ee5124ec319e..00e2b575021f 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h | |||
@@ -282,9 +282,25 @@ struct cfi_private { | |||
282 | /* | 282 | /* |
283 | * Returns the command address according to the given geometry. | 283 | * Returns the command address according to the given geometry. |
284 | */ | 284 | */ |
285 | static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int type) | 285 | static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, |
286 | struct map_info *map, struct cfi_private *cfi) | ||
286 | { | 287 | { |
287 | return (cmd_ofs * type) * interleave; | 288 | unsigned bankwidth = map_bankwidth(map); |
289 | unsigned interleave = cfi_interleave(cfi); | ||
290 | unsigned type = cfi->device_type; | ||
291 | uint32_t addr; | ||
292 | |||
293 | addr = (cmd_ofs * type) * interleave; | ||
294 | |||
295 | /* Modify the unlock address if we are in compatiblity mode. | ||
296 | * For 16bit devices on 8 bit busses | ||
297 | * and 32bit devices on 16 bit busses | ||
298 | * set the low bit of the alternating bit sequence of the address. | ||
299 | */ | ||
300 | if (((type * interleave) > bankwidth) && ((uint8_t)cmd_ofs == 0xaa)) | ||
301 | addr |= (type >> 1)*interleave; | ||
302 | |||
303 | return addr; | ||
288 | } | 304 | } |
289 | 305 | ||
290 | /* | 306 | /* |
@@ -430,7 +446,7 @@ static inline uint32_t cfi_send_gen_cmd(u_char cmd, uint32_t cmd_addr, uint32_t | |||
430 | int type, map_word *prev_val) | 446 | int type, map_word *prev_val) |
431 | { | 447 | { |
432 | map_word val; | 448 | map_word val; |
433 | uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, cfi_interleave(cfi), type); | 449 | uint32_t addr = base + cfi_build_cmd_addr(cmd_addr, map, cfi); |
434 | val = cfi_build_cmd(cmd, map, cfi); | 450 | val = cfi_build_cmd(cmd, map, cfi); |
435 | 451 | ||
436 | if (prev_val) | 452 | if (prev_val) |
diff --git a/include/linux/sched.h b/include/linux/sched.h index b483f39a7112..295b7c756ca6 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1349,6 +1349,8 @@ struct task_struct { | |||
1349 | */ | 1349 | */ |
1350 | unsigned long timer_slack_ns; | 1350 | unsigned long timer_slack_ns; |
1351 | unsigned long default_timer_slack_ns; | 1351 | unsigned long default_timer_slack_ns; |
1352 | |||
1353 | struct list_head *scm_work_list; | ||
1352 | }; | 1354 | }; |
1353 | 1355 | ||
1354 | /* | 1356 | /* |
diff --git a/include/linux/topology.h b/include/linux/topology.h index 2158fc0d5a56..34a7ee0ebed2 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h | |||
@@ -146,10 +146,10 @@ void arch_update_cpu_topology(void); | |||
146 | .wake_idx = 1, \ | 146 | .wake_idx = 1, \ |
147 | .forkexec_idx = 1, \ | 147 | .forkexec_idx = 1, \ |
148 | .flags = SD_LOAD_BALANCE \ | 148 | .flags = SD_LOAD_BALANCE \ |
149 | | SD_BALANCE_NEWIDLE \ | ||
150 | | SD_BALANCE_FORK \ | ||
151 | | SD_BALANCE_EXEC \ | 149 | | SD_BALANCE_EXEC \ |
150 | | SD_BALANCE_FORK \ | ||
152 | | SD_WAKE_AFFINE \ | 151 | | SD_WAKE_AFFINE \ |
152 | | SD_WAKE_BALANCE \ | ||
153 | | BALANCE_FOR_PKG_POWER,\ | 153 | | BALANCE_FOR_PKG_POWER,\ |
154 | .last_balance = jiffies, \ | 154 | .last_balance = jiffies, \ |
155 | .balance_interval = 1, \ | 155 | .balance_interval = 1, \ |
diff --git a/include/net/scm.h b/include/net/scm.h index 06df126103ca..33e9986beb86 100644 --- a/include/net/scm.h +++ b/include/net/scm.h | |||
@@ -14,8 +14,9 @@ | |||
14 | 14 | ||
15 | struct scm_fp_list | 15 | struct scm_fp_list |
16 | { | 16 | { |
17 | int count; | 17 | struct list_head list; |
18 | struct file *fp[SCM_MAX_FD]; | 18 | int count; |
19 | struct file *fp[SCM_MAX_FD]; | ||
19 | }; | 20 | }; |
20 | 21 | ||
21 | struct scm_cookie | 22 | struct scm_cookie |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 35eebd5510c2..358e77564e6f 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -2497,7 +2497,6 @@ static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry) | |||
2497 | list_del(&cgrp->sibling); | 2497 | list_del(&cgrp->sibling); |
2498 | spin_lock(&cgrp->dentry->d_lock); | 2498 | spin_lock(&cgrp->dentry->d_lock); |
2499 | d = dget(cgrp->dentry); | 2499 | d = dget(cgrp->dentry); |
2500 | cgrp->dentry = NULL; | ||
2501 | spin_unlock(&d->d_lock); | 2500 | spin_unlock(&d->d_lock); |
2502 | 2501 | ||
2503 | cgroup_d_remove_dir(d); | 2502 | cgroup_d_remove_dir(d); |
diff --git a/kernel/sched.c b/kernel/sched.c index e8819bc6f462..82cc839c9210 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -397,7 +397,7 @@ struct cfs_rq { | |||
397 | * 'curr' points to currently running entity on this cfs_rq. | 397 | * 'curr' points to currently running entity on this cfs_rq. |
398 | * It is set to NULL otherwise (i.e when none are currently running). | 398 | * It is set to NULL otherwise (i.e when none are currently running). |
399 | */ | 399 | */ |
400 | struct sched_entity *curr, *next; | 400 | struct sched_entity *curr, *next, *last; |
401 | 401 | ||
402 | unsigned long nr_spread_over; | 402 | unsigned long nr_spread_over; |
403 | 403 | ||
@@ -1805,7 +1805,9 @@ task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) | |||
1805 | /* | 1805 | /* |
1806 | * Buddy candidates are cache hot: | 1806 | * Buddy candidates are cache hot: |
1807 | */ | 1807 | */ |
1808 | if (sched_feat(CACHE_HOT_BUDDY) && (&p->se == cfs_rq_of(&p->se)->next)) | 1808 | if (sched_feat(CACHE_HOT_BUDDY) && |
1809 | (&p->se == cfs_rq_of(&p->se)->next || | ||
1810 | &p->se == cfs_rq_of(&p->se)->last)) | ||
1809 | return 1; | 1811 | return 1; |
1810 | 1812 | ||
1811 | if (p->sched_class != &fair_sched_class) | 1813 | if (p->sched_class != &fair_sched_class) |
diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index ce514afd78ff..51aa3e102acb 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c | |||
@@ -341,23 +341,20 @@ static void __dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
341 | cfs_rq->rb_leftmost = next_node; | 341 | cfs_rq->rb_leftmost = next_node; |
342 | } | 342 | } |
343 | 343 | ||
344 | if (cfs_rq->next == se) | ||
345 | cfs_rq->next = NULL; | ||
346 | |||
347 | rb_erase(&se->run_node, &cfs_rq->tasks_timeline); | 344 | rb_erase(&se->run_node, &cfs_rq->tasks_timeline); |
348 | } | 345 | } |
349 | 346 | ||
350 | static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq) | ||
351 | { | ||
352 | return cfs_rq->rb_leftmost; | ||
353 | } | ||
354 | |||
355 | static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq) | 347 | static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq) |
356 | { | 348 | { |
357 | return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node); | 349 | struct rb_node *left = cfs_rq->rb_leftmost; |
350 | |||
351 | if (!left) | ||
352 | return NULL; | ||
353 | |||
354 | return rb_entry(left, struct sched_entity, run_node); | ||
358 | } | 355 | } |
359 | 356 | ||
360 | static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) | 357 | static struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) |
361 | { | 358 | { |
362 | struct rb_node *last = rb_last(&cfs_rq->tasks_timeline); | 359 | struct rb_node *last = rb_last(&cfs_rq->tasks_timeline); |
363 | 360 | ||
@@ -741,6 +738,12 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) | |||
741 | #endif | 738 | #endif |
742 | } | 739 | } |
743 | 740 | ||
741 | if (cfs_rq->last == se) | ||
742 | cfs_rq->last = NULL; | ||
743 | |||
744 | if (cfs_rq->next == se) | ||
745 | cfs_rq->next = NULL; | ||
746 | |||
744 | if (se != cfs_rq->curr) | 747 | if (se != cfs_rq->curr) |
745 | __dequeue_entity(cfs_rq, se); | 748 | __dequeue_entity(cfs_rq, se); |
746 | account_entity_dequeue(cfs_rq, se); | 749 | account_entity_dequeue(cfs_rq, se); |
@@ -794,24 +797,15 @@ set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) | |||
794 | static int | 797 | static int |
795 | wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se); | 798 | wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se); |
796 | 799 | ||
797 | static struct sched_entity * | ||
798 | pick_next(struct cfs_rq *cfs_rq, struct sched_entity *se) | ||
799 | { | ||
800 | if (!cfs_rq->next || wakeup_preempt_entity(cfs_rq->next, se) == 1) | ||
801 | return se; | ||
802 | |||
803 | return cfs_rq->next; | ||
804 | } | ||
805 | |||
806 | static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq) | 800 | static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq) |
807 | { | 801 | { |
808 | struct sched_entity *se = NULL; | 802 | struct sched_entity *se = __pick_next_entity(cfs_rq); |
809 | 803 | ||
810 | if (first_fair(cfs_rq)) { | 804 | if (cfs_rq->next && wakeup_preempt_entity(cfs_rq->next, se) < 1) |
811 | se = __pick_next_entity(cfs_rq); | 805 | return cfs_rq->next; |
812 | se = pick_next(cfs_rq, se); | 806 | |
813 | set_next_entity(cfs_rq, se); | 807 | if (cfs_rq->last && wakeup_preempt_entity(cfs_rq->last, se) < 1) |
814 | } | 808 | return cfs_rq->last; |
815 | 809 | ||
816 | return se; | 810 | return se; |
817 | } | 811 | } |
@@ -1325,26 +1319,53 @@ wakeup_preempt_entity(struct sched_entity *curr, struct sched_entity *se) | |||
1325 | return 0; | 1319 | return 0; |
1326 | } | 1320 | } |
1327 | 1321 | ||
1322 | static void set_last_buddy(struct sched_entity *se) | ||
1323 | { | ||
1324 | for_each_sched_entity(se) | ||
1325 | cfs_rq_of(se)->last = se; | ||
1326 | } | ||
1327 | |||
1328 | static void set_next_buddy(struct sched_entity *se) | ||
1329 | { | ||
1330 | for_each_sched_entity(se) | ||
1331 | cfs_rq_of(se)->next = se; | ||
1332 | } | ||
1333 | |||
1328 | /* | 1334 | /* |
1329 | * Preempt the current task with a newly woken task if needed: | 1335 | * Preempt the current task with a newly woken task if needed: |
1330 | */ | 1336 | */ |
1331 | static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync) | 1337 | static void check_preempt_wakeup(struct rq *rq, struct task_struct *p, int sync) |
1332 | { | 1338 | { |
1333 | struct task_struct *curr = rq->curr; | 1339 | struct task_struct *curr = rq->curr; |
1334 | struct cfs_rq *cfs_rq = task_cfs_rq(curr); | ||
1335 | struct sched_entity *se = &curr->se, *pse = &p->se; | 1340 | struct sched_entity *se = &curr->se, *pse = &p->se; |
1336 | 1341 | ||
1337 | if (unlikely(rt_prio(p->prio))) { | 1342 | if (unlikely(rt_prio(p->prio))) { |
1343 | struct cfs_rq *cfs_rq = task_cfs_rq(curr); | ||
1344 | |||
1338 | update_rq_clock(rq); | 1345 | update_rq_clock(rq); |
1339 | update_curr(cfs_rq); | 1346 | update_curr(cfs_rq); |
1340 | resched_task(curr); | 1347 | resched_task(curr); |
1341 | return; | 1348 | return; |
1342 | } | 1349 | } |
1343 | 1350 | ||
1351 | if (unlikely(p->sched_class != &fair_sched_class)) | ||
1352 | return; | ||
1353 | |||
1344 | if (unlikely(se == pse)) | 1354 | if (unlikely(se == pse)) |
1345 | return; | 1355 | return; |
1346 | 1356 | ||
1347 | cfs_rq_of(pse)->next = pse; | 1357 | /* |
1358 | * Only set the backward buddy when the current task is still on the | ||
1359 | * rq. This can happen when a wakeup gets interleaved with schedule on | ||
1360 | * the ->pre_schedule() or idle_balance() point, either of which can | ||
1361 | * drop the rq lock. | ||
1362 | * | ||
1363 | * Also, during early boot the idle thread is in the fair class, for | ||
1364 | * obvious reasons its a bad idea to schedule back to the idle thread. | ||
1365 | */ | ||
1366 | if (sched_feat(LAST_BUDDY) && likely(se->on_rq && curr != rq->idle)) | ||
1367 | set_last_buddy(se); | ||
1368 | set_next_buddy(pse); | ||
1348 | 1369 | ||
1349 | /* | 1370 | /* |
1350 | * We can come here with TIF_NEED_RESCHED already set from new task | 1371 | * We can come here with TIF_NEED_RESCHED already set from new task |
@@ -1396,6 +1417,7 @@ static struct task_struct *pick_next_task_fair(struct rq *rq) | |||
1396 | 1417 | ||
1397 | do { | 1418 | do { |
1398 | se = pick_next_entity(cfs_rq); | 1419 | se = pick_next_entity(cfs_rq); |
1420 | set_next_entity(cfs_rq, se); | ||
1399 | cfs_rq = group_cfs_rq(se); | 1421 | cfs_rq = group_cfs_rq(se); |
1400 | } while (cfs_rq); | 1422 | } while (cfs_rq); |
1401 | 1423 | ||
diff --git a/kernel/sched_features.h b/kernel/sched_features.h index fda016218296..da5d93b5d2c6 100644 --- a/kernel/sched_features.h +++ b/kernel/sched_features.h | |||
@@ -12,3 +12,4 @@ SCHED_FEAT(LB_BIAS, 1) | |||
12 | SCHED_FEAT(LB_WAKEUP_UPDATE, 1) | 12 | SCHED_FEAT(LB_WAKEUP_UPDATE, 1) |
13 | SCHED_FEAT(ASYM_EFF_LOAD, 1) | 13 | SCHED_FEAT(ASYM_EFF_LOAD, 1) |
14 | SCHED_FEAT(WAKEUP_OVERLAP, 0) | 14 | SCHED_FEAT(WAKEUP_OVERLAP, 0) |
15 | SCHED_FEAT(LAST_BUDDY, 1) | ||
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 421aee99b84a..d143ab67be44 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -354,11 +354,26 @@ static int vma_has_reserves(struct vm_area_struct *vma) | |||
354 | return 0; | 354 | return 0; |
355 | } | 355 | } |
356 | 356 | ||
357 | static void clear_gigantic_page(struct page *page, | ||
358 | unsigned long addr, unsigned long sz) | ||
359 | { | ||
360 | int i; | ||
361 | struct page *p = page; | ||
362 | |||
363 | might_sleep(); | ||
364 | for (i = 0; i < sz/PAGE_SIZE; i++, p = mem_map_next(p, page, i)) { | ||
365 | cond_resched(); | ||
366 | clear_user_highpage(p, addr + i * PAGE_SIZE); | ||
367 | } | ||
368 | } | ||
357 | static void clear_huge_page(struct page *page, | 369 | static void clear_huge_page(struct page *page, |
358 | unsigned long addr, unsigned long sz) | 370 | unsigned long addr, unsigned long sz) |
359 | { | 371 | { |
360 | int i; | 372 | int i; |
361 | 373 | ||
374 | if (unlikely(sz > MAX_ORDER_NR_PAGES)) | ||
375 | return clear_gigantic_page(page, addr, sz); | ||
376 | |||
362 | might_sleep(); | 377 | might_sleep(); |
363 | for (i = 0; i < sz/PAGE_SIZE; i++) { | 378 | for (i = 0; i < sz/PAGE_SIZE; i++) { |
364 | cond_resched(); | 379 | cond_resched(); |
@@ -366,12 +381,32 @@ static void clear_huge_page(struct page *page, | |||
366 | } | 381 | } |
367 | } | 382 | } |
368 | 383 | ||
384 | static void copy_gigantic_page(struct page *dst, struct page *src, | ||
385 | unsigned long addr, struct vm_area_struct *vma) | ||
386 | { | ||
387 | int i; | ||
388 | struct hstate *h = hstate_vma(vma); | ||
389 | struct page *dst_base = dst; | ||
390 | struct page *src_base = src; | ||
391 | might_sleep(); | ||
392 | for (i = 0; i < pages_per_huge_page(h); ) { | ||
393 | cond_resched(); | ||
394 | copy_user_highpage(dst, src, addr + i*PAGE_SIZE, vma); | ||
395 | |||
396 | i++; | ||
397 | dst = mem_map_next(dst, dst_base, i); | ||
398 | src = mem_map_next(src, src_base, i); | ||
399 | } | ||
400 | } | ||
369 | static void copy_huge_page(struct page *dst, struct page *src, | 401 | static void copy_huge_page(struct page *dst, struct page *src, |
370 | unsigned long addr, struct vm_area_struct *vma) | 402 | unsigned long addr, struct vm_area_struct *vma) |
371 | { | 403 | { |
372 | int i; | 404 | int i; |
373 | struct hstate *h = hstate_vma(vma); | 405 | struct hstate *h = hstate_vma(vma); |
374 | 406 | ||
407 | if (unlikely(pages_per_huge_page(h) > MAX_ORDER_NR_PAGES)) | ||
408 | return copy_gigantic_page(dst, src, addr, vma); | ||
409 | |||
375 | might_sleep(); | 410 | might_sleep(); |
376 | for (i = 0; i < pages_per_huge_page(h); i++) { | 411 | for (i = 0; i < pages_per_huge_page(h); i++) { |
377 | cond_resched(); | 412 | cond_resched(); |
@@ -456,6 +491,8 @@ static void update_and_free_page(struct hstate *h, struct page *page) | |||
456 | { | 491 | { |
457 | int i; | 492 | int i; |
458 | 493 | ||
494 | VM_BUG_ON(h->order >= MAX_ORDER); | ||
495 | |||
459 | h->nr_huge_pages--; | 496 | h->nr_huge_pages--; |
460 | h->nr_huge_pages_node[page_to_nid(page)]--; | 497 | h->nr_huge_pages_node[page_to_nid(page)]--; |
461 | for (i = 0; i < pages_per_huge_page(h); i++) { | 498 | for (i = 0; i < pages_per_huge_page(h); i++) { |
@@ -970,6 +1007,14 @@ found: | |||
970 | return 1; | 1007 | return 1; |
971 | } | 1008 | } |
972 | 1009 | ||
1010 | static void prep_compound_huge_page(struct page *page, int order) | ||
1011 | { | ||
1012 | if (unlikely(order > (MAX_ORDER - 1))) | ||
1013 | prep_compound_gigantic_page(page, order); | ||
1014 | else | ||
1015 | prep_compound_page(page, order); | ||
1016 | } | ||
1017 | |||
973 | /* Put bootmem huge pages into the standard lists after mem_map is up */ | 1018 | /* Put bootmem huge pages into the standard lists after mem_map is up */ |
974 | static void __init gather_bootmem_prealloc(void) | 1019 | static void __init gather_bootmem_prealloc(void) |
975 | { | 1020 | { |
@@ -980,7 +1025,7 @@ static void __init gather_bootmem_prealloc(void) | |||
980 | struct hstate *h = m->hstate; | 1025 | struct hstate *h = m->hstate; |
981 | __ClearPageReserved(page); | 1026 | __ClearPageReserved(page); |
982 | WARN_ON(page_count(page) != 1); | 1027 | WARN_ON(page_count(page) != 1); |
983 | prep_compound_page(page, h->order); | 1028 | prep_compound_huge_page(page, h->order); |
984 | prep_new_huge_page(h, page, page_to_nid(page)); | 1029 | prep_new_huge_page(h, page, page_to_nid(page)); |
985 | } | 1030 | } |
986 | } | 1031 | } |
@@ -2130,7 +2175,7 @@ same_page: | |||
2130 | if (zeropage_ok) | 2175 | if (zeropage_ok) |
2131 | pages[i] = ZERO_PAGE(0); | 2176 | pages[i] = ZERO_PAGE(0); |
2132 | else | 2177 | else |
2133 | pages[i] = page + pfn_offset; | 2178 | pages[i] = mem_map_offset(page, pfn_offset); |
2134 | get_page(pages[i]); | 2179 | get_page(pages[i]); |
2135 | } | 2180 | } |
2136 | 2181 | ||
diff --git a/mm/internal.h b/mm/internal.h index e4e728bdf324..13333bc2eb68 100644 --- a/mm/internal.h +++ b/mm/internal.h | |||
@@ -17,6 +17,7 @@ void free_pgtables(struct mmu_gather *tlb, struct vm_area_struct *start_vma, | |||
17 | unsigned long floor, unsigned long ceiling); | 17 | unsigned long floor, unsigned long ceiling); |
18 | 18 | ||
19 | extern void prep_compound_page(struct page *page, unsigned long order); | 19 | extern void prep_compound_page(struct page *page, unsigned long order); |
20 | extern void prep_compound_gigantic_page(struct page *page, unsigned long order); | ||
20 | 21 | ||
21 | static inline void set_page_count(struct page *page, int v) | 22 | static inline void set_page_count(struct page *page, int v) |
22 | { | 23 | { |
@@ -176,6 +177,34 @@ static inline void free_page_mlock(struct page *page) { } | |||
176 | #endif /* CONFIG_UNEVICTABLE_LRU */ | 177 | #endif /* CONFIG_UNEVICTABLE_LRU */ |
177 | 178 | ||
178 | /* | 179 | /* |
180 | * Return the mem_map entry representing the 'offset' subpage within | ||
181 | * the maximally aligned gigantic page 'base'. Handle any discontiguity | ||
182 | * in the mem_map at MAX_ORDER_NR_PAGES boundaries. | ||
183 | */ | ||
184 | static inline struct page *mem_map_offset(struct page *base, int offset) | ||
185 | { | ||
186 | if (unlikely(offset >= MAX_ORDER_NR_PAGES)) | ||
187 | return pfn_to_page(page_to_pfn(base) + offset); | ||
188 | return base + offset; | ||
189 | } | ||
190 | |||
191 | /* | ||
192 | * Iterator over all subpages withing the maximally aligned gigantic | ||
193 | * page 'base'. Handle any discontiguity in the mem_map. | ||
194 | */ | ||
195 | static inline struct page *mem_map_next(struct page *iter, | ||
196 | struct page *base, int offset) | ||
197 | { | ||
198 | if (unlikely((offset & (MAX_ORDER_NR_PAGES - 1)) == 0)) { | ||
199 | unsigned long pfn = page_to_pfn(base) + offset; | ||
200 | if (!pfn_valid(pfn)) | ||
201 | return NULL; | ||
202 | return pfn_to_page(pfn); | ||
203 | } | ||
204 | return iter + 1; | ||
205 | } | ||
206 | |||
207 | /* | ||
179 | * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node, | 208 | * FLATMEM and DISCONTIGMEM configurations use alloc_bootmem_node, |
180 | * so all functions starting at paging_init should be marked __init | 209 | * so all functions starting at paging_init should be marked __init |
181 | * in those cases. SPARSEMEM, however, allows for memory hotplug, | 210 | * in those cases. SPARSEMEM, however, allows for memory hotplug, |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 36f42573a335..e9493b1c1117 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -489,12 +489,6 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, | |||
489 | int err; | 489 | int err; |
490 | struct vm_area_struct *first, *vma, *prev; | 490 | struct vm_area_struct *first, *vma, *prev; |
491 | 491 | ||
492 | if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { | ||
493 | |||
494 | err = migrate_prep(); | ||
495 | if (err) | ||
496 | return ERR_PTR(err); | ||
497 | } | ||
498 | 492 | ||
499 | first = find_vma(mm, start); | 493 | first = find_vma(mm, start); |
500 | if (!first) | 494 | if (!first) |
@@ -809,9 +803,13 @@ int do_migrate_pages(struct mm_struct *mm, | |||
809 | const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags) | 803 | const nodemask_t *from_nodes, const nodemask_t *to_nodes, int flags) |
810 | { | 804 | { |
811 | int busy = 0; | 805 | int busy = 0; |
812 | int err = 0; | 806 | int err; |
813 | nodemask_t tmp; | 807 | nodemask_t tmp; |
814 | 808 | ||
809 | err = migrate_prep(); | ||
810 | if (err) | ||
811 | return err; | ||
812 | |||
815 | down_read(&mm->mmap_sem); | 813 | down_read(&mm->mmap_sem); |
816 | 814 | ||
817 | err = migrate_vmas(mm, from_nodes, to_nodes, flags); | 815 | err = migrate_vmas(mm, from_nodes, to_nodes, flags); |
@@ -974,6 +972,12 @@ static long do_mbind(unsigned long start, unsigned long len, | |||
974 | start, start + len, mode, mode_flags, | 972 | start, start + len, mode, mode_flags, |
975 | nmask ? nodes_addr(*nmask)[0] : -1); | 973 | nmask ? nodes_addr(*nmask)[0] : -1); |
976 | 974 | ||
975 | if (flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) { | ||
976 | |||
977 | err = migrate_prep(); | ||
978 | if (err) | ||
979 | return err; | ||
980 | } | ||
977 | down_write(&mm->mmap_sem); | 981 | down_write(&mm->mmap_sem); |
978 | vma = check_range(mm, start, end, nmask, | 982 | vma = check_range(mm, start, end, nmask, |
979 | flags | MPOL_MF_INVERT, &pagelist); | 983 | flags | MPOL_MF_INVERT, &pagelist); |
diff --git a/mm/migrate.c b/mm/migrate.c index 6602941bfab0..385db89f0c33 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -841,12 +841,12 @@ static int do_move_page_to_node_array(struct mm_struct *mm, | |||
841 | struct page_to_node *pp; | 841 | struct page_to_node *pp; |
842 | LIST_HEAD(pagelist); | 842 | LIST_HEAD(pagelist); |
843 | 843 | ||
844 | migrate_prep(); | ||
844 | down_read(&mm->mmap_sem); | 845 | down_read(&mm->mmap_sem); |
845 | 846 | ||
846 | /* | 847 | /* |
847 | * Build a list of pages to migrate | 848 | * Build a list of pages to migrate |
848 | */ | 849 | */ |
849 | migrate_prep(); | ||
850 | for (pp = pm; pp->node != MAX_NUMNODES; pp++) { | 850 | for (pp = pm; pp->node != MAX_NUMNODES; pp++) { |
851 | struct vm_area_struct *vma; | 851 | struct vm_area_struct *vma; |
852 | struct page *page; | 852 | struct page *page; |
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 64e5b4bcd964..a0a01902f551 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -38,7 +38,6 @@ static DEFINE_SPINLOCK(zone_scan_mutex); | |||
38 | * badness - calculate a numeric value for how bad this task has been | 38 | * badness - calculate a numeric value for how bad this task has been |
39 | * @p: task struct of which task we should calculate | 39 | * @p: task struct of which task we should calculate |
40 | * @uptime: current uptime in seconds | 40 | * @uptime: current uptime in seconds |
41 | * @mem: target memory controller | ||
42 | * | 41 | * |
43 | * The formula used is relatively simple and documented inline in the | 42 | * The formula used is relatively simple and documented inline in the |
44 | * function. The main rationale is that we want to select a good task | 43 | * function. The main rationale is that we want to select a good task |
@@ -295,6 +294,8 @@ static void dump_tasks(const struct mem_cgroup *mem) | |||
295 | continue; | 294 | continue; |
296 | if (mem && !task_in_mem_cgroup(p, mem)) | 295 | if (mem && !task_in_mem_cgroup(p, mem)) |
297 | continue; | 296 | continue; |
297 | if (!thread_group_leader(p)) | ||
298 | continue; | ||
298 | 299 | ||
299 | task_lock(p); | 300 | task_lock(p); |
300 | printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n", | 301 | printk(KERN_INFO "[%5d] %5d %5d %8lu %8lu %3d %3d %s\n", |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d0a240fbb8bf..54069e64e3a8 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -263,24 +263,39 @@ void prep_compound_page(struct page *page, unsigned long order) | |||
263 | { | 263 | { |
264 | int i; | 264 | int i; |
265 | int nr_pages = 1 << order; | 265 | int nr_pages = 1 << order; |
266 | |||
267 | set_compound_page_dtor(page, free_compound_page); | ||
268 | set_compound_order(page, order); | ||
269 | __SetPageHead(page); | ||
270 | for (i = 1; i < nr_pages; i++) { | ||
271 | struct page *p = page + i; | ||
272 | |||
273 | __SetPageTail(p); | ||
274 | p->first_page = page; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | #ifdef CONFIG_HUGETLBFS | ||
279 | void prep_compound_gigantic_page(struct page *page, unsigned long order) | ||
280 | { | ||
281 | int i; | ||
282 | int nr_pages = 1 << order; | ||
266 | struct page *p = page + 1; | 283 | struct page *p = page + 1; |
267 | 284 | ||
268 | set_compound_page_dtor(page, free_compound_page); | 285 | set_compound_page_dtor(page, free_compound_page); |
269 | set_compound_order(page, order); | 286 | set_compound_order(page, order); |
270 | __SetPageHead(page); | 287 | __SetPageHead(page); |
271 | for (i = 1; i < nr_pages; i++, p++) { | 288 | for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) { |
272 | if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) | ||
273 | p = pfn_to_page(page_to_pfn(page) + i); | ||
274 | __SetPageTail(p); | 289 | __SetPageTail(p); |
275 | p->first_page = page; | 290 | p->first_page = page; |
276 | } | 291 | } |
277 | } | 292 | } |
293 | #endif | ||
278 | 294 | ||
279 | static void destroy_compound_page(struct page *page, unsigned long order) | 295 | static void destroy_compound_page(struct page *page, unsigned long order) |
280 | { | 296 | { |
281 | int i; | 297 | int i; |
282 | int nr_pages = 1 << order; | 298 | int nr_pages = 1 << order; |
283 | struct page *p = page + 1; | ||
284 | 299 | ||
285 | if (unlikely(compound_order(page) != order)) | 300 | if (unlikely(compound_order(page) != order)) |
286 | bad_page(page); | 301 | bad_page(page); |
@@ -288,9 +303,8 @@ static void destroy_compound_page(struct page *page, unsigned long order) | |||
288 | if (unlikely(!PageHead(page))) | 303 | if (unlikely(!PageHead(page))) |
289 | bad_page(page); | 304 | bad_page(page); |
290 | __ClearPageHead(page); | 305 | __ClearPageHead(page); |
291 | for (i = 1; i < nr_pages; i++, p++) { | 306 | for (i = 1; i < nr_pages; i++) { |
292 | if (unlikely((i & (MAX_ORDER_NR_PAGES - 1)) == 0)) | 307 | struct page *p = page + i; |
293 | p = pfn_to_page(page_to_pfn(page) + i); | ||
294 | 308 | ||
295 | if (unlikely(!PageTail(p) | | 309 | if (unlikely(!PageTail(p) | |
296 | (p->first_page != page))) | 310 | (p->first_page != page))) |
diff --git a/mm/page_isolation.c b/mm/page_isolation.c index b70a7fec1ff6..5e0ffd967452 100644 --- a/mm/page_isolation.c +++ b/mm/page_isolation.c | |||
@@ -130,10 +130,11 @@ int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn) | |||
130 | if (page && get_pageblock_migratetype(page) != MIGRATE_ISOLATE) | 130 | if (page && get_pageblock_migratetype(page) != MIGRATE_ISOLATE) |
131 | break; | 131 | break; |
132 | } | 132 | } |
133 | if (pfn < end_pfn) | 133 | page = __first_valid_page(start_pfn, end_pfn - start_pfn); |
134 | if ((pfn < end_pfn) || !page) | ||
134 | return -EBUSY; | 135 | return -EBUSY; |
135 | /* Check all pages are free or Marked as ISOLATED */ | 136 | /* Check all pages are free or Marked as ISOLATED */ |
136 | zone = page_zone(pfn_to_page(pfn)); | 137 | zone = page_zone(page); |
137 | spin_lock_irqsave(&zone->lock, flags); | 138 | spin_lock_irqsave(&zone->lock, flags); |
138 | ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn); | 139 | ret = __test_page_isolated_in_pageblock(start_pfn, end_pfn); |
139 | spin_unlock_irqrestore(&zone->lock, flags); | 140 | spin_unlock_irqrestore(&zone->lock, flags); |
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index a91b5f8fcaf6..a13ea6401ae7 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c | |||
@@ -64,7 +64,7 @@ void __meminit vmemmap_verify(pte_t *pte, int node, | |||
64 | unsigned long pfn = pte_pfn(*pte); | 64 | unsigned long pfn = pte_pfn(*pte); |
65 | int actual_node = early_pfn_to_nid(pfn); | 65 | int actual_node = early_pfn_to_nid(pfn); |
66 | 66 | ||
67 | if (actual_node != node) | 67 | if (node_distance(actual_node, node) > LOCAL_DISTANCE) |
68 | printk(KERN_WARNING "[%lx-%lx] potential offnode " | 68 | printk(KERN_WARNING "[%lx-%lx] potential offnode " |
69 | "page_structs\n", start, end - 1); | 69 | "page_structs\n", start, end - 1); |
70 | } | 70 | } |
diff --git a/net/9p/client.c b/net/9p/client.c index 67717f69412e..4b529454616d 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -189,6 +189,9 @@ static struct p9_req_t *p9_tag_alloc(struct p9_client *c, u16 tag) | |||
189 | printk(KERN_ERR "Couldn't grow tag array\n"); | 189 | printk(KERN_ERR "Couldn't grow tag array\n"); |
190 | kfree(req->tc); | 190 | kfree(req->tc); |
191 | kfree(req->rc); | 191 | kfree(req->rc); |
192 | kfree(req->wq); | ||
193 | req->tc = req->rc = NULL; | ||
194 | req->wq = NULL; | ||
192 | return ERR_PTR(-ENOMEM); | 195 | return ERR_PTR(-ENOMEM); |
193 | } | 196 | } |
194 | req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); | 197 | req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); |
@@ -311,12 +314,6 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) | |||
311 | r->status = REQ_STATUS_IDLE; | 314 | r->status = REQ_STATUS_IDLE; |
312 | if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool)) | 315 | if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool)) |
313 | p9_idpool_put(tag, c->tagpool); | 316 | p9_idpool_put(tag, c->tagpool); |
314 | |||
315 | /* if this was a flush request we have to free response fcall */ | ||
316 | if (r->rc->id == P9_RFLUSH) { | ||
317 | kfree(r->tc); | ||
318 | kfree(r->rc); | ||
319 | } | ||
320 | } | 317 | } |
321 | 318 | ||
322 | /** | 319 | /** |
@@ -611,19 +608,21 @@ reterr: | |||
611 | 608 | ||
612 | static struct p9_fid *p9_fid_create(struct p9_client *clnt) | 609 | static struct p9_fid *p9_fid_create(struct p9_client *clnt) |
613 | { | 610 | { |
614 | int err; | 611 | int ret; |
615 | struct p9_fid *fid; | 612 | struct p9_fid *fid; |
613 | unsigned long flags; | ||
616 | 614 | ||
617 | P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt); | 615 | P9_DPRINTK(P9_DEBUG_FID, "clnt %p\n", clnt); |
618 | fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); | 616 | fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); |
619 | if (!fid) | 617 | if (!fid) |
620 | return ERR_PTR(-ENOMEM); | 618 | return ERR_PTR(-ENOMEM); |
621 | 619 | ||
622 | fid->fid = p9_idpool_get(clnt->fidpool); | 620 | ret = p9_idpool_get(clnt->fidpool); |
623 | if (fid->fid < 0) { | 621 | if (fid->fid < 0) { |
624 | err = -ENOSPC; | 622 | ret = -ENOSPC; |
625 | goto error; | 623 | goto error; |
626 | } | 624 | } |
625 | fid->fid = ret; | ||
627 | 626 | ||
628 | memset(&fid->qid, 0, sizeof(struct p9_qid)); | 627 | memset(&fid->qid, 0, sizeof(struct p9_qid)); |
629 | fid->mode = -1; | 628 | fid->mode = -1; |
@@ -632,27 +631,28 @@ static struct p9_fid *p9_fid_create(struct p9_client *clnt) | |||
632 | fid->clnt = clnt; | 631 | fid->clnt = clnt; |
633 | fid->aux = NULL; | 632 | fid->aux = NULL; |
634 | 633 | ||
635 | spin_lock(&clnt->lock); | 634 | spin_lock_irqsave(&clnt->lock, flags); |
636 | list_add(&fid->flist, &clnt->fidlist); | 635 | list_add(&fid->flist, &clnt->fidlist); |
637 | spin_unlock(&clnt->lock); | 636 | spin_unlock_irqrestore(&clnt->lock, flags); |
638 | 637 | ||
639 | return fid; | 638 | return fid; |
640 | 639 | ||
641 | error: | 640 | error: |
642 | kfree(fid); | 641 | kfree(fid); |
643 | return ERR_PTR(err); | 642 | return ERR_PTR(ret); |
644 | } | 643 | } |
645 | 644 | ||
646 | static void p9_fid_destroy(struct p9_fid *fid) | 645 | static void p9_fid_destroy(struct p9_fid *fid) |
647 | { | 646 | { |
648 | struct p9_client *clnt; | 647 | struct p9_client *clnt; |
648 | unsigned long flags; | ||
649 | 649 | ||
650 | P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid); | 650 | P9_DPRINTK(P9_DEBUG_FID, "fid %d\n", fid->fid); |
651 | clnt = fid->clnt; | 651 | clnt = fid->clnt; |
652 | p9_idpool_put(fid->fid, clnt->fidpool); | 652 | p9_idpool_put(fid->fid, clnt->fidpool); |
653 | spin_lock(&clnt->lock); | 653 | spin_lock_irqsave(&clnt->lock, flags); |
654 | list_del(&fid->flist); | 654 | list_del(&fid->flist); |
655 | spin_unlock(&clnt->lock); | 655 | spin_unlock_irqrestore(&clnt->lock, flags); |
656 | kfree(fid); | 656 | kfree(fid); |
657 | } | 657 | } |
658 | 658 | ||
@@ -818,7 +818,9 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, | |||
818 | } | 818 | } |
819 | 819 | ||
820 | P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n", | 820 | P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n", |
821 | qid.type, qid.path, qid.version); | 821 | qid.type, |
822 | (unsigned long long)qid.path, | ||
823 | qid.version); | ||
822 | 824 | ||
823 | memmove(&fid->qid, &qid, sizeof(struct p9_qid)); | 825 | memmove(&fid->qid, &qid, sizeof(struct p9_qid)); |
824 | 826 | ||
@@ -865,7 +867,9 @@ p9_client_auth(struct p9_client *clnt, char *uname, u32 n_uname, char *aname) | |||
865 | } | 867 | } |
866 | 868 | ||
867 | P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n", | 869 | P9_DPRINTK(P9_DEBUG_9P, "<<< RAUTH qid %x.%llx.%x\n", |
868 | qid.type, qid.path, qid.version); | 870 | qid.type, |
871 | (unsigned long long)qid.path, | ||
872 | qid.version); | ||
869 | 873 | ||
870 | memmove(&afid->qid, &qid, sizeof(struct p9_qid)); | 874 | memmove(&afid->qid, &qid, sizeof(struct p9_qid)); |
871 | p9_free_req(clnt, req); | 875 | p9_free_req(clnt, req); |
@@ -930,7 +934,8 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames, | |||
930 | 934 | ||
931 | for (count = 0; count < nwqids; count++) | 935 | for (count = 0; count < nwqids; count++) |
932 | P9_DPRINTK(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n", | 936 | P9_DPRINTK(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n", |
933 | count, wqids[count].type, wqids[count].path, | 937 | count, wqids[count].type, |
938 | (unsigned long long)wqids[count].path, | ||
934 | wqids[count].version); | 939 | wqids[count].version); |
935 | 940 | ||
936 | if (nwname) | 941 | if (nwname) |
@@ -980,7 +985,9 @@ int p9_client_open(struct p9_fid *fid, int mode) | |||
980 | } | 985 | } |
981 | 986 | ||
982 | P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n", | 987 | P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n", |
983 | qid.type, qid.path, qid.version, iounit); | 988 | qid.type, |
989 | (unsigned long long)qid.path, | ||
990 | qid.version, iounit); | ||
984 | 991 | ||
985 | fid->mode = mode; | 992 | fid->mode = mode; |
986 | fid->iounit = iounit; | 993 | fid->iounit = iounit; |
@@ -1023,7 +1030,9 @@ int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, | |||
1023 | } | 1030 | } |
1024 | 1031 | ||
1025 | P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n", | 1032 | P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n", |
1026 | qid.type, qid.path, qid.version, iounit); | 1033 | qid.type, |
1034 | (unsigned long long)qid.path, | ||
1035 | qid.version, iounit); | ||
1027 | 1036 | ||
1028 | fid->mode = mode; | 1037 | fid->mode = mode; |
1029 | fid->iounit = iounit; | 1038 | fid->iounit = iounit; |
@@ -1230,9 +1239,9 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid) | |||
1230 | "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n" | 1239 | "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n" |
1231 | "<<< uid=%d gid=%d n_muid=%d\n", | 1240 | "<<< uid=%d gid=%d n_muid=%d\n", |
1232 | ret->size, ret->type, ret->dev, ret->qid.type, | 1241 | ret->size, ret->type, ret->dev, ret->qid.type, |
1233 | ret->qid.path, ret->qid.version, ret->mode, | 1242 | (unsigned long long)ret->qid.path, ret->qid.version, ret->mode, |
1234 | ret->atime, ret->mtime, ret->length, ret->name, | 1243 | ret->atime, ret->mtime, (unsigned long long)ret->length, |
1235 | ret->uid, ret->gid, ret->muid, ret->extension, | 1244 | ret->name, ret->uid, ret->gid, ret->muid, ret->extension, |
1236 | ret->n_uid, ret->n_gid, ret->n_muid); | 1245 | ret->n_uid, ret->n_gid, ret->n_muid); |
1237 | 1246 | ||
1238 | free_and_error: | 1247 | free_and_error: |
@@ -1255,9 +1264,9 @@ int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) | |||
1255 | " name=%s uid=%s gid=%s muid=%s extension=(%s)\n" | 1264 | " name=%s uid=%s gid=%s muid=%s extension=(%s)\n" |
1256 | " uid=%d gid=%d n_muid=%d\n", | 1265 | " uid=%d gid=%d n_muid=%d\n", |
1257 | wst->size, wst->type, wst->dev, wst->qid.type, | 1266 | wst->size, wst->type, wst->dev, wst->qid.type, |
1258 | wst->qid.path, wst->qid.version, wst->mode, | 1267 | (unsigned long long)wst->qid.path, wst->qid.version, wst->mode, |
1259 | wst->atime, wst->mtime, wst->length, wst->name, | 1268 | wst->atime, wst->mtime, (unsigned long long)wst->length, |
1260 | wst->uid, wst->gid, wst->muid, wst->extension, | 1269 | wst->name, wst->uid, wst->gid, wst->muid, wst->extension, |
1261 | wst->n_uid, wst->n_gid, wst->n_muid); | 1270 | wst->n_uid, wst->n_gid, wst->n_muid); |
1262 | err = 0; | 1271 | err = 0; |
1263 | clnt = fid->clnt; | 1272 | clnt = fid->clnt; |
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 8d6cc4777aae..2f1fe5fc1228 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include <net/9p/transport.h> | 45 | #include <net/9p/transport.h> |
46 | #include <rdma/ib_verbs.h> | 46 | #include <rdma/ib_verbs.h> |
47 | #include <rdma/rdma_cm.h> | 47 | #include <rdma/rdma_cm.h> |
48 | #include <rdma/ib_verbs.h> | ||
49 | 48 | ||
50 | #define P9_PORT 5640 | 49 | #define P9_PORT 5640 |
51 | #define P9_RDMA_SQ_DEPTH 32 | 50 | #define P9_RDMA_SQ_DEPTH 32 |
@@ -589,6 +588,9 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args) | |||
589 | if (IS_ERR(rdma->cm_id)) | 588 | if (IS_ERR(rdma->cm_id)) |
590 | goto error; | 589 | goto error; |
591 | 590 | ||
591 | /* Associate the client with the transport */ | ||
592 | client->trans = rdma; | ||
593 | |||
592 | /* Resolve the server's address */ | 594 | /* Resolve the server's address */ |
593 | rdma->addr.sin_family = AF_INET; | 595 | rdma->addr.sin_family = AF_INET; |
594 | rdma->addr.sin_addr.s_addr = in_aton(addr); | 596 | rdma->addr.sin_addr.s_addr = in_aton(addr); |
@@ -669,7 +671,6 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args) | |||
669 | if (err || (rdma->state != P9_RDMA_CONNECTED)) | 671 | if (err || (rdma->state != P9_RDMA_CONNECTED)) |
670 | goto error; | 672 | goto error; |
671 | 673 | ||
672 | client->trans = rdma; | ||
673 | client->status = Connected; | 674 | client->status = Connected; |
674 | 675 | ||
675 | return 0; | 676 | return 0; |
diff --git a/net/core/scm.c b/net/core/scm.c index 10f5c65f6a47..ab242cc1acca 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -75,6 +75,7 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) | |||
75 | if (!fpl) | 75 | if (!fpl) |
76 | return -ENOMEM; | 76 | return -ENOMEM; |
77 | *fplp = fpl; | 77 | *fplp = fpl; |
78 | INIT_LIST_HEAD(&fpl->list); | ||
78 | fpl->count = 0; | 79 | fpl->count = 0; |
79 | } | 80 | } |
80 | fpp = &fpl->fp[fpl->count]; | 81 | fpp = &fpl->fp[fpl->count]; |
@@ -106,9 +107,25 @@ void __scm_destroy(struct scm_cookie *scm) | |||
106 | 107 | ||
107 | if (fpl) { | 108 | if (fpl) { |
108 | scm->fp = NULL; | 109 | scm->fp = NULL; |
109 | for (i=fpl->count-1; i>=0; i--) | 110 | if (current->scm_work_list) { |
110 | fput(fpl->fp[i]); | 111 | list_add_tail(&fpl->list, current->scm_work_list); |
111 | kfree(fpl); | 112 | } else { |
113 | LIST_HEAD(work_list); | ||
114 | |||
115 | current->scm_work_list = &work_list; | ||
116 | |||
117 | list_add(&fpl->list, &work_list); | ||
118 | while (!list_empty(&work_list)) { | ||
119 | fpl = list_first_entry(&work_list, struct scm_fp_list, list); | ||
120 | |||
121 | list_del(&fpl->list); | ||
122 | for (i=fpl->count-1; i>=0; i--) | ||
123 | fput(fpl->fp[i]); | ||
124 | kfree(fpl); | ||
125 | } | ||
126 | |||
127 | current->scm_work_list = NULL; | ||
128 | } | ||
112 | } | 129 | } |
113 | } | 130 | } |
114 | 131 | ||
@@ -284,6 +301,7 @@ struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl) | |||
284 | 301 | ||
285 | new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); | 302 | new_fpl = kmalloc(sizeof(*fpl), GFP_KERNEL); |
286 | if (new_fpl) { | 303 | if (new_fpl) { |
304 | INIT_LIST_HEAD(&new_fpl->list); | ||
287 | for (i=fpl->count-1; i>=0; i--) | 305 | for (i=fpl->count-1; i>=0; i--) |
288 | get_file(fpl->fp[i]); | 306 | get_file(fpl->fp[i]); |
289 | memcpy(new_fpl, fpl, sizeof(*fpl)); | 307 | memcpy(new_fpl, fpl, sizeof(*fpl)); |