diff options
-rw-r--r-- | Documentation/cpu-freq/user-guide.txt | 5 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/Kconfig | 3 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 3 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/longhaul.c | 221 | ||||
-rw-r--r-- | drivers/cpufreq/cpufreq.c | 75 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 12 | ||||
-rw-r--r-- | fs/nfs/namespace.c | 4 | ||||
-rw-r--r-- | fs/nfs/read.c | 2 | ||||
-rw-r--r-- | fs/nfs/write.c | 2 | ||||
-rw-r--r-- | include/linux/lockd/lockd.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 6 | ||||
-rw-r--r-- | include/linux/sunrpc/xprt.h | 2 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 52 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 6 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 21 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 29 |
16 files changed, 265 insertions, 179 deletions
diff --git a/Documentation/cpu-freq/user-guide.txt b/Documentation/cpu-freq/user-guide.txt index 7fedc00c3d30..555c8cf3650a 100644 --- a/Documentation/cpu-freq/user-guide.txt +++ b/Documentation/cpu-freq/user-guide.txt | |||
@@ -153,10 +153,13 @@ scaling_governor, and by "echoing" the name of another | |||
153 | that some governors won't load - they only | 153 | that some governors won't load - they only |
154 | work on some specific architectures or | 154 | work on some specific architectures or |
155 | processors. | 155 | processors. |
156 | scaling_min_freq and | 156 | scaling_min_freq and |
157 | scaling_max_freq show the current "policy limits" (in | 157 | scaling_max_freq show the current "policy limits" (in |
158 | kHz). By echoing new values into these | 158 | kHz). By echoing new values into these |
159 | files, you can change these limits. | 159 | files, you can change these limits. |
160 | NOTE: when setting a policy you need to | ||
161 | first set scaling_max_freq, then | ||
162 | scaling_min_freq. | ||
160 | 163 | ||
161 | 164 | ||
162 | If you have selected the "userspace" governor which allows you to | 165 | If you have selected the "userspace" governor which allows you to |
diff --git a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig index e44a4c6a4fe5..ccc1edff5c97 100644 --- a/arch/i386/kernel/cpu/cpufreq/Kconfig +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig | |||
@@ -96,6 +96,7 @@ config X86_POWERNOW_K8_ACPI | |||
96 | 96 | ||
97 | config X86_GX_SUSPMOD | 97 | config X86_GX_SUSPMOD |
98 | tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" | 98 | tristate "Cyrix MediaGX/NatSemi Geode Suspend Modulation" |
99 | depends on PCI | ||
99 | help | 100 | help |
100 | This add the CPUFreq driver for NatSemi Geode processors which | 101 | This add the CPUFreq driver for NatSemi Geode processors which |
101 | support suspend modulation. | 102 | support suspend modulation. |
@@ -202,7 +203,7 @@ config X86_LONGRUN | |||
202 | config X86_LONGHAUL | 203 | config X86_LONGHAUL |
203 | tristate "VIA Cyrix III Longhaul" | 204 | tristate "VIA Cyrix III Longhaul" |
204 | select CPU_FREQ_TABLE | 205 | select CPU_FREQ_TABLE |
205 | depends on BROKEN | 206 | depends on ACPI_PROCESSOR |
206 | help | 207 | help |
207 | This adds the CPUFreq driver for VIA Samuel/CyrixIII, | 208 | This adds the CPUFreq driver for VIA Samuel/CyrixIII, |
208 | VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T | 209 | VIA Cyrix Samuel/C3, VIA Cyrix Ezra and VIA Cyrix Ezra-T |
diff --git a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index 567b39bea07e..efb41e81351c 100644 --- a/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c | |||
@@ -384,8 +384,7 @@ static int acpi_cpufreq_early_init_acpi(void) | |||
384 | } | 384 | } |
385 | 385 | ||
386 | /* Do initialization in ACPI core */ | 386 | /* Do initialization in ACPI core */ |
387 | acpi_processor_preregister_performance(acpi_perf_data); | 387 | return acpi_processor_preregister_performance(acpi_perf_data); |
388 | return 0; | ||
389 | } | 388 | } |
390 | 389 | ||
391 | static int | 390 | static int |
diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c index 146f607e9c44..4f2c3aeef724 100644 --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c | |||
@@ -29,11 +29,13 @@ | |||
29 | #include <linux/cpufreq.h> | 29 | #include <linux/cpufreq.h> |
30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
31 | #include <linux/string.h> | 31 | #include <linux/string.h> |
32 | #include <linux/pci.h> | ||
33 | 32 | ||
34 | #include <asm/msr.h> | 33 | #include <asm/msr.h> |
35 | #include <asm/timex.h> | 34 | #include <asm/timex.h> |
36 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | #include <asm/acpi.h> | ||
37 | #include <linux/acpi.h> | ||
38 | #include <acpi/processor.h> | ||
37 | 39 | ||
38 | #include "longhaul.h" | 40 | #include "longhaul.h" |
39 | 41 | ||
@@ -56,6 +58,8 @@ static int minvid, maxvid; | |||
56 | static unsigned int minmult, maxmult; | 58 | static unsigned int minmult, maxmult; |
57 | static int can_scale_voltage; | 59 | static int can_scale_voltage; |
58 | static int vrmrev; | 60 | static int vrmrev; |
61 | static struct acpi_processor *pr = NULL; | ||
62 | static struct acpi_processor_cx *cx = NULL; | ||
59 | 63 | ||
60 | /* Module parameters */ | 64 | /* Module parameters */ |
61 | static int dont_scale_voltage; | 65 | static int dont_scale_voltage; |
@@ -118,84 +122,65 @@ static int longhaul_get_cpu_mult(void) | |||
118 | return eblcr_table[invalue]; | 122 | return eblcr_table[invalue]; |
119 | } | 123 | } |
120 | 124 | ||
125 | /* For processor with BCR2 MSR */ | ||
121 | 126 | ||
122 | static void do_powersaver(union msr_longhaul *longhaul, | 127 | static void do_longhaul1(int cx_address, unsigned int clock_ratio_index) |
123 | unsigned int clock_ratio_index) | ||
124 | { | 128 | { |
125 | struct pci_dev *dev; | 129 | union msr_bcr2 bcr2; |
126 | unsigned long flags; | 130 | u32 t; |
127 | unsigned int tmp_mask; | ||
128 | int version; | ||
129 | int i; | ||
130 | u16 pci_cmd; | ||
131 | u16 cmd_state[64]; | ||
132 | 131 | ||
133 | switch (cpu_model) { | 132 | rdmsrl(MSR_VIA_BCR2, bcr2.val); |
134 | case CPU_EZRA_T: | 133 | /* Enable software clock multiplier */ |
135 | version = 3; | 134 | bcr2.bits.ESOFTBF = 1; |
136 | break; | 135 | bcr2.bits.CLOCKMUL = clock_ratio_index; |
137 | case CPU_NEHEMIAH: | ||
138 | version = 0xf; | ||
139 | break; | ||
140 | default: | ||
141 | return; | ||
142 | } | ||
143 | 136 | ||
144 | rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); | 137 | /* Sync to timer tick */ |
145 | longhaul->bits.SoftBusRatio = clock_ratio_index & 0xf; | 138 | safe_halt(); |
146 | longhaul->bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; | 139 | ACPI_FLUSH_CPU_CACHE(); |
147 | longhaul->bits.EnableSoftBusRatio = 1; | 140 | /* Change frequency on next halt or sleep */ |
148 | longhaul->bits.RevisionKey = 0; | 141 | wrmsrl(MSR_VIA_BCR2, bcr2.val); |
142 | /* Invoke C3 */ | ||
143 | inb(cx_address); | ||
144 | /* Dummy op - must do something useless after P_LVL3 read */ | ||
145 | t = inl(acpi_fadt.xpm_tmr_blk.address); | ||
146 | |||
147 | /* Disable software clock multiplier */ | ||
148 | local_irq_disable(); | ||
149 | rdmsrl(MSR_VIA_BCR2, bcr2.val); | ||
150 | bcr2.bits.ESOFTBF = 0; | ||
151 | wrmsrl(MSR_VIA_BCR2, bcr2.val); | ||
152 | } | ||
149 | 153 | ||
150 | preempt_disable(); | 154 | /* For processor with Longhaul MSR */ |
151 | local_irq_save(flags); | ||
152 | 155 | ||
153 | /* | 156 | static void do_powersaver(int cx_address, unsigned int clock_ratio_index) |
154 | * get current pci bus master state for all devices | 157 | { |
155 | * and clear bus master bit | 158 | union msr_longhaul longhaul; |
156 | */ | 159 | u32 t; |
157 | dev = NULL; | ||
158 | i = 0; | ||
159 | do { | ||
160 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
161 | if (dev != NULL) { | ||
162 | pci_read_config_word(dev, PCI_COMMAND, &pci_cmd); | ||
163 | cmd_state[i++] = pci_cmd; | ||
164 | pci_cmd &= ~PCI_COMMAND_MASTER; | ||
165 | pci_write_config_word(dev, PCI_COMMAND, pci_cmd); | ||
166 | } | ||
167 | } while (dev != NULL); | ||
168 | 160 | ||
169 | tmp_mask=inb(0x21); /* works on C3. save mask. */ | 161 | rdmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
170 | outb(0xFE,0x21); /* TMR0 only */ | 162 | longhaul.bits.RevisionKey = longhaul.bits.RevisionID; |
171 | outb(0xFF,0x80); /* delay */ | 163 | longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf; |
164 | longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4; | ||
165 | longhaul.bits.EnableSoftBusRatio = 1; | ||
172 | 166 | ||
167 | /* Sync to timer tick */ | ||
173 | safe_halt(); | 168 | safe_halt(); |
174 | wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); | 169 | ACPI_FLUSH_CPU_CACHE(); |
175 | halt(); | 170 | /* Change frequency on next halt or sleep */ |
176 | 171 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); | |
172 | /* Invoke C3 */ | ||
173 | inb(cx_address); | ||
174 | /* Dummy op - must do something useless after P_LVL3 read */ | ||
175 | t = inl(acpi_fadt.xpm_tmr_blk.address); | ||
176 | |||
177 | /* Disable bus ratio bit */ | ||
177 | local_irq_disable(); | 178 | local_irq_disable(); |
178 | 179 | longhaul.bits.RevisionKey = longhaul.bits.RevisionID; | |
179 | outb(tmp_mask,0x21); /* restore mask */ | 180 | longhaul.bits.EnableSoftBusRatio = 0; |
180 | 181 | longhaul.bits.EnableSoftBSEL = 0; | |
181 | /* restore pci bus master state for all devices */ | 182 | longhaul.bits.EnableSoftVID = 0; |
182 | dev = NULL; | 183 | wrmsrl(MSR_VIA_LONGHAUL, longhaul.val); |
183 | i = 0; | ||
184 | do { | ||
185 | dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev); | ||
186 | if (dev != NULL) { | ||
187 | pci_cmd = cmd_state[i++]; | ||
188 | pci_write_config_byte(dev, PCI_COMMAND, pci_cmd); | ||
189 | } | ||
190 | } while (dev != NULL); | ||
191 | local_irq_restore(flags); | ||
192 | preempt_enable(); | ||
193 | |||
194 | /* disable bus ratio bit */ | ||
195 | rdmsrl(MSR_VIA_LONGHAUL, longhaul->val); | ||
196 | longhaul->bits.EnableSoftBusRatio = 0; | ||
197 | longhaul->bits.RevisionKey = version; | ||
198 | wrmsrl(MSR_VIA_LONGHAUL, longhaul->val); | ||
199 | } | 184 | } |
200 | 185 | ||
201 | /** | 186 | /** |
@@ -209,9 +194,9 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
209 | { | 194 | { |
210 | int speed, mult; | 195 | int speed, mult; |
211 | struct cpufreq_freqs freqs; | 196 | struct cpufreq_freqs freqs; |
212 | union msr_longhaul longhaul; | ||
213 | union msr_bcr2 bcr2; | ||
214 | static unsigned int old_ratio=-1; | 197 | static unsigned int old_ratio=-1; |
198 | unsigned long flags; | ||
199 | unsigned int pic1_mask, pic2_mask; | ||
215 | 200 | ||
216 | if (old_ratio == clock_ratio_index) | 201 | if (old_ratio == clock_ratio_index) |
217 | return; | 202 | return; |
@@ -234,6 +219,20 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
234 | dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", | 219 | dprintk ("Setting to FSB:%dMHz Mult:%d.%dx (%s)\n", |
235 | fsb, mult/10, mult%10, print_speed(speed/1000)); | 220 | fsb, mult/10, mult%10, print_speed(speed/1000)); |
236 | 221 | ||
222 | preempt_disable(); | ||
223 | local_irq_save(flags); | ||
224 | |||
225 | pic2_mask = inb(0xA1); | ||
226 | pic1_mask = inb(0x21); /* works on C3. save mask. */ | ||
227 | outb(0xFF,0xA1); /* Overkill */ | ||
228 | outb(0xFE,0x21); /* TMR0 only */ | ||
229 | |||
230 | /* Disable bus master arbitration */ | ||
231 | if (pr->flags.bm_check) { | ||
232 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1, | ||
233 | ACPI_MTX_DO_NOT_LOCK); | ||
234 | } | ||
235 | |||
237 | switch (longhaul_version) { | 236 | switch (longhaul_version) { |
238 | 237 | ||
239 | /* | 238 | /* |
@@ -245,20 +244,7 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
245 | */ | 244 | */ |
246 | case TYPE_LONGHAUL_V1: | 245 | case TYPE_LONGHAUL_V1: |
247 | case TYPE_LONGHAUL_V2: | 246 | case TYPE_LONGHAUL_V2: |
248 | rdmsrl (MSR_VIA_BCR2, bcr2.val); | 247 | do_longhaul1(cx->address, clock_ratio_index); |
249 | /* Enable software clock multiplier */ | ||
250 | bcr2.bits.ESOFTBF = 1; | ||
251 | bcr2.bits.CLOCKMUL = clock_ratio_index; | ||
252 | local_irq_disable(); | ||
253 | wrmsrl (MSR_VIA_BCR2, bcr2.val); | ||
254 | safe_halt(); | ||
255 | |||
256 | /* Disable software clock multiplier */ | ||
257 | rdmsrl (MSR_VIA_BCR2, bcr2.val); | ||
258 | bcr2.bits.ESOFTBF = 0; | ||
259 | local_irq_disable(); | ||
260 | wrmsrl (MSR_VIA_BCR2, bcr2.val); | ||
261 | local_irq_enable(); | ||
262 | break; | 248 | break; |
263 | 249 | ||
264 | /* | 250 | /* |
@@ -273,10 +259,22 @@ static void longhaul_setstate(unsigned int clock_ratio_index) | |||
273 | * to work in practice. | 259 | * to work in practice. |
274 | */ | 260 | */ |
275 | case TYPE_POWERSAVER: | 261 | case TYPE_POWERSAVER: |
276 | do_powersaver(&longhaul, clock_ratio_index); | 262 | do_powersaver(cx->address, clock_ratio_index); |
277 | break; | 263 | break; |
278 | } | 264 | } |
279 | 265 | ||
266 | /* Enable bus master arbitration */ | ||
267 | if (pr->flags.bm_check) { | ||
268 | acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0, | ||
269 | ACPI_MTX_DO_NOT_LOCK); | ||
270 | } | ||
271 | |||
272 | outb(pic2_mask,0xA1); /* restore mask */ | ||
273 | outb(pic1_mask,0x21); | ||
274 | |||
275 | local_irq_restore(flags); | ||
276 | preempt_enable(); | ||
277 | |||
280 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | 278 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); |
281 | } | 279 | } |
282 | 280 | ||
@@ -324,9 +322,11 @@ static int guess_fsb(void) | |||
324 | static int __init longhaul_get_ranges(void) | 322 | static int __init longhaul_get_ranges(void) |
325 | { | 323 | { |
326 | unsigned long invalue; | 324 | unsigned long invalue; |
327 | unsigned int multipliers[32]= { | 325 | unsigned int ezra_t_multipliers[32]= { |
328 | 50,30,40,100,55,35,45,95,90,70,80,60,120,75,85,65, | 326 | 90, 30, 40, 100, 55, 35, 45, 95, |
329 | -1,110,120,-1,135,115,125,105,130,150,160,140,-1,155,-1,145 }; | 327 | 50, 70, 80, 60, 120, 75, 85, 65, |
328 | -1, 110, 120, -1, 135, 115, 125, 105, | ||
329 | 130, 150, 160, 140, -1, 155, -1, 145 }; | ||
330 | unsigned int j, k = 0; | 330 | unsigned int j, k = 0; |
331 | union msr_longhaul longhaul; | 331 | union msr_longhaul longhaul; |
332 | unsigned long lo, hi; | 332 | unsigned long lo, hi; |
@@ -355,13 +355,13 @@ static int __init longhaul_get_ranges(void) | |||
355 | invalue = longhaul.bits.MaxMHzBR; | 355 | invalue = longhaul.bits.MaxMHzBR; |
356 | if (longhaul.bits.MaxMHzBR4) | 356 | if (longhaul.bits.MaxMHzBR4) |
357 | invalue += 16; | 357 | invalue += 16; |
358 | maxmult=multipliers[invalue]; | 358 | maxmult=ezra_t_multipliers[invalue]; |
359 | 359 | ||
360 | invalue = longhaul.bits.MinMHzBR; | 360 | invalue = longhaul.bits.MinMHzBR; |
361 | if (longhaul.bits.MinMHzBR4 == 1) | 361 | if (longhaul.bits.MinMHzBR4 == 1) |
362 | minmult = 30; | 362 | minmult = 30; |
363 | else | 363 | else |
364 | minmult = multipliers[invalue]; | 364 | minmult = ezra_t_multipliers[invalue]; |
365 | fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; | 365 | fsb = eblcr_fsb_table_v2[longhaul.bits.MaxMHzFSB]; |
366 | break; | 366 | break; |
367 | } | 367 | } |
@@ -527,6 +527,18 @@ static unsigned int longhaul_get(unsigned int cpu) | |||
527 | return calc_speed(longhaul_get_cpu_mult()); | 527 | return calc_speed(longhaul_get_cpu_mult()); |
528 | } | 528 | } |
529 | 529 | ||
530 | static acpi_status longhaul_walk_callback(acpi_handle obj_handle, | ||
531 | u32 nesting_level, | ||
532 | void *context, void **return_value) | ||
533 | { | ||
534 | struct acpi_device *d; | ||
535 | |||
536 | if ( acpi_bus_get_device(obj_handle, &d) ) { | ||
537 | return 0; | ||
538 | } | ||
539 | *return_value = (void *)acpi_driver_data(d); | ||
540 | return 1; | ||
541 | } | ||
530 | 542 | ||
531 | static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | 543 | static int __init longhaul_cpu_init(struct cpufreq_policy *policy) |
532 | { | 544 | { |
@@ -534,6 +546,15 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
534 | char *cpuname=NULL; | 546 | char *cpuname=NULL; |
535 | int ret; | 547 | int ret; |
536 | 548 | ||
549 | /* Check ACPI support for C3 state */ | ||
550 | acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, | ||
551 | &longhaul_walk_callback, NULL, (void *)&pr); | ||
552 | if (pr == NULL) goto err_acpi; | ||
553 | |||
554 | cx = &pr->power.states[ACPI_STATE_C3]; | ||
555 | if (cx->address == 0 || cx->latency > 1000) goto err_acpi; | ||
556 | |||
557 | /* Now check what we have on this motherboard */ | ||
537 | switch (c->x86_model) { | 558 | switch (c->x86_model) { |
538 | case 6: | 559 | case 6: |
539 | cpu_model = CPU_SAMUEL; | 560 | cpu_model = CPU_SAMUEL; |
@@ -634,6 +655,10 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy) | |||
634 | cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu); | 655 | cpufreq_frequency_table_get_attr(longhaul_table, policy->cpu); |
635 | 656 | ||
636 | return 0; | 657 | return 0; |
658 | |||
659 | err_acpi: | ||
660 | printk(KERN_ERR PFX "No ACPI support for CPU frequency changes.\n"); | ||
661 | return -ENODEV; | ||
637 | } | 662 | } |
638 | 663 | ||
639 | static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy) | 664 | static int __devexit longhaul_cpu_exit(struct cpufreq_policy *policy) |
@@ -666,6 +691,18 @@ static int __init longhaul_init(void) | |||
666 | if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) | 691 | if (c->x86_vendor != X86_VENDOR_CENTAUR || c->x86 != 6) |
667 | return -ENODEV; | 692 | return -ENODEV; |
668 | 693 | ||
694 | #ifdef CONFIG_SMP | ||
695 | if (num_online_cpus() > 1) { | ||
696 | return -ENODEV; | ||
697 | printk(KERN_ERR PFX "More than 1 CPU detected, longhaul disabled.\n"); | ||
698 | } | ||
699 | #endif | ||
700 | #ifdef CONFIG_X86_IO_APIC | ||
701 | if (cpu_has_apic) { | ||
702 | printk(KERN_ERR PFX "APIC detected. Longhaul is currently broken in this configuration.\n"); | ||
703 | return -ENODEV; | ||
704 | } | ||
705 | #endif | ||
669 | switch (c->x86_model) { | 706 | switch (c->x86_model) { |
670 | case 6 ... 9: | 707 | case 6 ... 9: |
671 | return cpufreq_register_driver(&longhaul_driver); | 708 | return cpufreq_register_driver(&longhaul_driver); |
@@ -699,6 +736,6 @@ MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>"); | |||
699 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); | 736 | MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors."); |
700 | MODULE_LICENSE ("GPL"); | 737 | MODULE_LICENSE ("GPL"); |
701 | 738 | ||
702 | module_init(longhaul_init); | 739 | late_initcall(longhaul_init); |
703 | module_exit(longhaul_exit); | 740 | module_exit(longhaul_exit); |
704 | 741 | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index bc1088d9b379..b3df613ae4ec 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -284,39 +284,69 @@ EXPORT_SYMBOL_GPL(cpufreq_notify_transition); | |||
284 | * SYSFS INTERFACE * | 284 | * SYSFS INTERFACE * |
285 | *********************************************************************/ | 285 | *********************************************************************/ |
286 | 286 | ||
287 | static struct cpufreq_governor *__find_governor(const char *str_governor) | ||
288 | { | ||
289 | struct cpufreq_governor *t; | ||
290 | |||
291 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) | ||
292 | if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) | ||
293 | return t; | ||
294 | |||
295 | return NULL; | ||
296 | } | ||
297 | |||
287 | /** | 298 | /** |
288 | * cpufreq_parse_governor - parse a governor string | 299 | * cpufreq_parse_governor - parse a governor string |
289 | */ | 300 | */ |
290 | static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, | 301 | static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, |
291 | struct cpufreq_governor **governor) | 302 | struct cpufreq_governor **governor) |
292 | { | 303 | { |
304 | int err = -EINVAL; | ||
305 | |||
293 | if (!cpufreq_driver) | 306 | if (!cpufreq_driver) |
294 | return -EINVAL; | 307 | goto out; |
308 | |||
295 | if (cpufreq_driver->setpolicy) { | 309 | if (cpufreq_driver->setpolicy) { |
296 | if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { | 310 | if (!strnicmp(str_governor, "performance", CPUFREQ_NAME_LEN)) { |
297 | *policy = CPUFREQ_POLICY_PERFORMANCE; | 311 | *policy = CPUFREQ_POLICY_PERFORMANCE; |
298 | return 0; | 312 | err = 0; |
299 | } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { | 313 | } else if (!strnicmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) { |
300 | *policy = CPUFREQ_POLICY_POWERSAVE; | 314 | *policy = CPUFREQ_POLICY_POWERSAVE; |
301 | return 0; | 315 | err = 0; |
302 | } | 316 | } |
303 | return -EINVAL; | 317 | } else if (cpufreq_driver->target) { |
304 | } else { | ||
305 | struct cpufreq_governor *t; | 318 | struct cpufreq_governor *t; |
319 | |||
306 | mutex_lock(&cpufreq_governor_mutex); | 320 | mutex_lock(&cpufreq_governor_mutex); |
307 | if (!cpufreq_driver || !cpufreq_driver->target) | 321 | |
308 | goto out; | 322 | t = __find_governor(str_governor); |
309 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 323 | |
310 | if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) { | 324 | if (t == NULL) { |
311 | *governor = t; | 325 | char *name = kasprintf(GFP_KERNEL, "cpufreq_%s", str_governor); |
326 | |||
327 | if (name) { | ||
328 | int ret; | ||
329 | |||
312 | mutex_unlock(&cpufreq_governor_mutex); | 330 | mutex_unlock(&cpufreq_governor_mutex); |
313 | return 0; | 331 | ret = request_module(name); |
332 | mutex_lock(&cpufreq_governor_mutex); | ||
333 | |||
334 | if (ret == 0) | ||
335 | t = __find_governor(str_governor); | ||
314 | } | 336 | } |
337 | |||
338 | kfree(name); | ||
315 | } | 339 | } |
316 | out: | 340 | |
341 | if (t != NULL) { | ||
342 | *governor = t; | ||
343 | err = 0; | ||
344 | } | ||
345 | |||
317 | mutex_unlock(&cpufreq_governor_mutex); | 346 | mutex_unlock(&cpufreq_governor_mutex); |
318 | } | 347 | } |
319 | return -EINVAL; | 348 | out: |
349 | return err; | ||
320 | } | 350 | } |
321 | 351 | ||
322 | 352 | ||
@@ -1265,23 +1295,21 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) | |||
1265 | 1295 | ||
1266 | int cpufreq_register_governor(struct cpufreq_governor *governor) | 1296 | int cpufreq_register_governor(struct cpufreq_governor *governor) |
1267 | { | 1297 | { |
1268 | struct cpufreq_governor *t; | 1298 | int err; |
1269 | 1299 | ||
1270 | if (!governor) | 1300 | if (!governor) |
1271 | return -EINVAL; | 1301 | return -EINVAL; |
1272 | 1302 | ||
1273 | mutex_lock(&cpufreq_governor_mutex); | 1303 | mutex_lock(&cpufreq_governor_mutex); |
1274 | 1304 | ||
1275 | list_for_each_entry(t, &cpufreq_governor_list, governor_list) { | 1305 | err = -EBUSY; |
1276 | if (!strnicmp(governor->name,t->name,CPUFREQ_NAME_LEN)) { | 1306 | if (__find_governor(governor->name) == NULL) { |
1277 | mutex_unlock(&cpufreq_governor_mutex); | 1307 | err = 0; |
1278 | return -EBUSY; | 1308 | list_add(&governor->governor_list, &cpufreq_governor_list); |
1279 | } | ||
1280 | } | 1309 | } |
1281 | list_add(&governor->governor_list, &cpufreq_governor_list); | ||
1282 | 1310 | ||
1283 | mutex_unlock(&cpufreq_governor_mutex); | 1311 | mutex_unlock(&cpufreq_governor_mutex); |
1284 | return 0; | 1312 | return err; |
1285 | } | 1313 | } |
1286 | EXPORT_SYMBOL_GPL(cpufreq_register_governor); | 1314 | EXPORT_SYMBOL_GPL(cpufreq_register_governor); |
1287 | 1315 | ||
@@ -1343,6 +1371,11 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, struct cpufreq_poli | |||
1343 | 1371 | ||
1344 | memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); | 1372 | memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); |
1345 | 1373 | ||
1374 | if (policy->min > data->min && policy->min > policy->max) { | ||
1375 | ret = -EINVAL; | ||
1376 | goto error_out; | ||
1377 | } | ||
1378 | |||
1346 | /* verify the cpu speed can be set within this limit */ | 1379 | /* verify the cpu speed can be set within this limit */ |
1347 | ret = cpufreq_driver->verify(policy); | 1380 | ret = cpufreq_driver->verify(policy); |
1348 | if (ret) | 1381 | if (ret) |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index baf5ae513481..c9d419703cf3 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -638,9 +638,6 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) | |||
638 | if (task->tk_status < 0) { | 638 | if (task->tk_status < 0) { |
639 | /* RPC error: Re-insert for retransmission */ | 639 | /* RPC error: Re-insert for retransmission */ |
640 | timeout = 10 * HZ; | 640 | timeout = 10 * HZ; |
641 | } else if (block->b_done) { | ||
642 | /* Block already removed, kill it for real */ | ||
643 | timeout = 0; | ||
644 | } else { | 641 | } else { |
645 | /* Call was successful, now wait for client callback */ | 642 | /* Call was successful, now wait for client callback */ |
646 | timeout = 60 * HZ; | 643 | timeout = 60 * HZ; |
@@ -709,13 +706,10 @@ nlmsvc_retry_blocked(void) | |||
709 | break; | 706 | break; |
710 | if (time_after(block->b_when,jiffies)) | 707 | if (time_after(block->b_when,jiffies)) |
711 | break; | 708 | break; |
712 | dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", | 709 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", |
713 | block, block->b_when, block->b_done); | 710 | block, block->b_when); |
714 | kref_get(&block->b_count); | 711 | kref_get(&block->b_count); |
715 | if (block->b_done) | 712 | nlmsvc_grant_blocked(block); |
716 | nlmsvc_unlink_block(block); | ||
717 | else | ||
718 | nlmsvc_grant_blocked(block); | ||
719 | nlmsvc_release_block(block); | 713 | nlmsvc_release_block(block); |
720 | } | 714 | } |
721 | 715 | ||
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 19b98ca468eb..86b3169c8cac 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c | |||
@@ -51,7 +51,7 @@ char *nfs_path(const char *base, const struct dentry *dentry, | |||
51 | namelen = dentry->d_name.len; | 51 | namelen = dentry->d_name.len; |
52 | buflen -= namelen + 1; | 52 | buflen -= namelen + 1; |
53 | if (buflen < 0) | 53 | if (buflen < 0) |
54 | goto Elong; | 54 | goto Elong_unlock; |
55 | end -= namelen; | 55 | end -= namelen; |
56 | memcpy(end, dentry->d_name.name, namelen); | 56 | memcpy(end, dentry->d_name.name, namelen); |
57 | *--end = '/'; | 57 | *--end = '/'; |
@@ -68,6 +68,8 @@ char *nfs_path(const char *base, const struct dentry *dentry, | |||
68 | end -= namelen; | 68 | end -= namelen; |
69 | memcpy(end, base, namelen); | 69 | memcpy(end, base, namelen); |
70 | return end; | 70 | return end; |
71 | Elong_unlock: | ||
72 | spin_unlock(&dcache_lock); | ||
71 | Elong: | 73 | Elong: |
72 | return ERR_PTR(-ENAMETOOLONG); | 74 | return ERR_PTR(-ENAMETOOLONG); |
73 | } | 75 | } |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 52bf634260a1..65c0c5b32351 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -63,7 +63,7 @@ struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | |||
63 | return p; | 63 | return p; |
64 | } | 64 | } |
65 | 65 | ||
66 | void nfs_readdata_free(struct nfs_read_data *p) | 66 | static void nfs_readdata_free(struct nfs_read_data *p) |
67 | { | 67 | { |
68 | if (p && (p->pagevec != &p->page_array[0])) | 68 | if (p && (p->pagevec != &p->page_array[0])) |
69 | kfree(p->pagevec); | 69 | kfree(p->pagevec); |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 86bac6a5008e..50774991f8d5 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -137,7 +137,7 @@ struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | |||
137 | return p; | 137 | return p; |
138 | } | 138 | } |
139 | 139 | ||
140 | void nfs_writedata_free(struct nfs_write_data *p) | 140 | static void nfs_writedata_free(struct nfs_write_data *p) |
141 | { | 141 | { |
142 | if (p && (p->pagevec != &p->page_array[0])) | 142 | if (p && (p->pagevec != &p->page_array[0])) |
143 | kfree(p->pagevec); | 143 | kfree(p->pagevec); |
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index aa4fe905bb4d..0d92c468d55a 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
@@ -123,7 +123,6 @@ struct nlm_block { | |||
123 | unsigned int b_id; /* block id */ | 123 | unsigned int b_id; /* block id */ |
124 | unsigned char b_queued; /* re-queued */ | 124 | unsigned char b_queued; /* re-queued */ |
125 | unsigned char b_granted; /* VFS granted lock */ | 125 | unsigned char b_granted; /* VFS granted lock */ |
126 | unsigned char b_done; /* callback complete */ | ||
127 | struct nlm_file * b_file; /* file in question */ | 126 | struct nlm_file * b_file; /* file in question */ |
128 | }; | 127 | }; |
129 | 128 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 55ea853d57bc..247434553ae8 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -476,10 +476,9 @@ static inline int nfs_wb_page(struct inode *inode, struct page* page) | |||
476 | } | 476 | } |
477 | 477 | ||
478 | /* | 478 | /* |
479 | * Allocate and free nfs_write_data structures | 479 | * Allocate nfs_write_data structures |
480 | */ | 480 | */ |
481 | extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount); | 481 | extern struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount); |
482 | extern void nfs_writedata_free(struct nfs_write_data *p); | ||
483 | 482 | ||
484 | /* | 483 | /* |
485 | * linux/fs/nfs/read.c | 484 | * linux/fs/nfs/read.c |
@@ -491,10 +490,9 @@ extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *); | |||
491 | extern void nfs_readdata_release(void *data); | 490 | extern void nfs_readdata_release(void *data); |
492 | 491 | ||
493 | /* | 492 | /* |
494 | * Allocate and free nfs_read_data structures | 493 | * Allocate nfs_read_data structures |
495 | */ | 494 | */ |
496 | extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount); | 495 | extern struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount); |
497 | extern void nfs_readdata_free(struct nfs_read_data *p); | ||
498 | 496 | ||
499 | /* | 497 | /* |
500 | * linux/fs/nfs3proc.c | 498 | * linux/fs/nfs3proc.c |
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index e8bbe8118de8..840e47a4ccc5 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -229,7 +229,7 @@ int xprt_reserve_xprt(struct rpc_task *task); | |||
229 | int xprt_reserve_xprt_cong(struct rpc_task *task); | 229 | int xprt_reserve_xprt_cong(struct rpc_task *task); |
230 | int xprt_prepare_transmit(struct rpc_task *task); | 230 | int xprt_prepare_transmit(struct rpc_task *task); |
231 | void xprt_transmit(struct rpc_task *task); | 231 | void xprt_transmit(struct rpc_task *task); |
232 | void xprt_abort_transmit(struct rpc_task *task); | 232 | void xprt_end_transmit(struct rpc_task *task); |
233 | int xprt_adjust_timeout(struct rpc_rqst *req); | 233 | int xprt_adjust_timeout(struct rpc_rqst *req); |
234 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); | 234 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); |
235 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); | 235 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 4ba271f892c8..d6409e757219 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -921,26 +921,43 @@ call_transmit(struct rpc_task *task) | |||
921 | task->tk_status = xprt_prepare_transmit(task); | 921 | task->tk_status = xprt_prepare_transmit(task); |
922 | if (task->tk_status != 0) | 922 | if (task->tk_status != 0) |
923 | return; | 923 | return; |
924 | task->tk_action = call_transmit_status; | ||
924 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 925 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
925 | if (rpc_task_need_encode(task)) { | 926 | if (rpc_task_need_encode(task)) { |
926 | task->tk_rqstp->rq_bytes_sent = 0; | 927 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); |
927 | call_encode(task); | 928 | call_encode(task); |
928 | /* Did the encode result in an error condition? */ | 929 | /* Did the encode result in an error condition? */ |
929 | if (task->tk_status != 0) | 930 | if (task->tk_status != 0) |
930 | goto out_nosend; | 931 | return; |
931 | } | 932 | } |
932 | task->tk_action = call_transmit_status; | ||
933 | xprt_transmit(task); | 933 | xprt_transmit(task); |
934 | if (task->tk_status < 0) | 934 | if (task->tk_status < 0) |
935 | return; | 935 | return; |
936 | if (!task->tk_msg.rpc_proc->p_decode) { | 936 | /* |
937 | task->tk_action = rpc_exit_task; | 937 | * On success, ensure that we call xprt_end_transmit() before sleeping |
938 | rpc_wake_up_task(task); | 938 | * in order to allow access to the socket to other RPC requests. |
939 | } | 939 | */ |
940 | return; | 940 | call_transmit_status(task); |
941 | out_nosend: | 941 | if (task->tk_msg.rpc_proc->p_decode != NULL) |
942 | /* release socket write lock before attempting to handle error */ | 942 | return; |
943 | xprt_abort_transmit(task); | 943 | task->tk_action = rpc_exit_task; |
944 | rpc_wake_up_task(task); | ||
945 | } | ||
946 | |||
947 | /* | ||
948 | * 5a. Handle cleanup after a transmission | ||
949 | */ | ||
950 | static void | ||
951 | call_transmit_status(struct rpc_task *task) | ||
952 | { | ||
953 | task->tk_action = call_status; | ||
954 | /* | ||
955 | * Special case: if we've been waiting on the socket's write_space() | ||
956 | * callback, then don't call xprt_end_transmit(). | ||
957 | */ | ||
958 | if (task->tk_status == -EAGAIN) | ||
959 | return; | ||
960 | xprt_end_transmit(task); | ||
944 | rpc_task_force_reencode(task); | 961 | rpc_task_force_reencode(task); |
945 | } | 962 | } |
946 | 963 | ||
@@ -992,18 +1009,7 @@ call_status(struct rpc_task *task) | |||
992 | } | 1009 | } |
993 | 1010 | ||
994 | /* | 1011 | /* |
995 | * 6a. Handle transmission errors. | 1012 | * 6a. Handle RPC timeout |
996 | */ | ||
997 | static void | ||
998 | call_transmit_status(struct rpc_task *task) | ||
999 | { | ||
1000 | if (task->tk_status != -EAGAIN) | ||
1001 | rpc_task_force_reencode(task); | ||
1002 | call_status(task); | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * 6b. Handle RPC timeout | ||
1007 | * We do not release the request slot, so we keep using the | 1013 | * We do not release the request slot, so we keep using the |
1008 | * same XID for all retransmits. | 1014 | * same XID for all retransmits. |
1009 | */ | 1015 | */ |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index dc6cb93c8830..a3bd2db2e024 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -667,10 +667,11 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client) | |||
667 | RPCAUTH_info, RPCAUTH_EOF); | 667 | RPCAUTH_info, RPCAUTH_EOF); |
668 | if (error) | 668 | if (error) |
669 | goto err_depopulate; | 669 | goto err_depopulate; |
670 | dget(dentry); | ||
670 | out: | 671 | out: |
671 | mutex_unlock(&dir->i_mutex); | 672 | mutex_unlock(&dir->i_mutex); |
672 | rpc_release_path(&nd); | 673 | rpc_release_path(&nd); |
673 | return dget(dentry); | 674 | return dentry; |
674 | err_depopulate: | 675 | err_depopulate: |
675 | rpc_depopulate(dentry); | 676 | rpc_depopulate(dentry); |
676 | __rpc_rmdir(dir, dentry); | 677 | __rpc_rmdir(dir, dentry); |
@@ -731,10 +732,11 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags) | |||
731 | rpci->flags = flags; | 732 | rpci->flags = flags; |
732 | rpci->ops = ops; | 733 | rpci->ops = ops; |
733 | inode_dir_notify(dir, DN_CREATE); | 734 | inode_dir_notify(dir, DN_CREATE); |
735 | dget(dentry); | ||
734 | out: | 736 | out: |
735 | mutex_unlock(&dir->i_mutex); | 737 | mutex_unlock(&dir->i_mutex); |
736 | rpc_release_path(&nd); | 738 | rpc_release_path(&nd); |
737 | return dget(dentry); | 739 | return dentry; |
738 | err_dput: | 740 | err_dput: |
739 | dput(dentry); | 741 | dput(dentry); |
740 | dentry = ERR_PTR(-ENOMEM); | 742 | dentry = ERR_PTR(-ENOMEM); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 313b68d892c6..e8c2bc4977f3 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -707,12 +707,9 @@ out_unlock: | |||
707 | return err; | 707 | return err; |
708 | } | 708 | } |
709 | 709 | ||
710 | void | 710 | void xprt_end_transmit(struct rpc_task *task) |
711 | xprt_abort_transmit(struct rpc_task *task) | ||
712 | { | 711 | { |
713 | struct rpc_xprt *xprt = task->tk_xprt; | 712 | xprt_release_write(task->tk_xprt, task); |
714 | |||
715 | xprt_release_write(xprt, task); | ||
716 | } | 713 | } |
717 | 714 | ||
718 | /** | 715 | /** |
@@ -761,8 +758,6 @@ void xprt_transmit(struct rpc_task *task) | |||
761 | task->tk_status = -ENOTCONN; | 758 | task->tk_status = -ENOTCONN; |
762 | else if (!req->rq_received) | 759 | else if (!req->rq_received) |
763 | rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); | 760 | rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); |
764 | |||
765 | xprt->ops->release_xprt(xprt, task); | ||
766 | spin_unlock_bh(&xprt->transport_lock); | 761 | spin_unlock_bh(&xprt->transport_lock); |
767 | return; | 762 | return; |
768 | } | 763 | } |
@@ -772,18 +767,8 @@ void xprt_transmit(struct rpc_task *task) | |||
772 | * schedq, and being picked up by a parallel run of rpciod(). | 767 | * schedq, and being picked up by a parallel run of rpciod(). |
773 | */ | 768 | */ |
774 | task->tk_status = status; | 769 | task->tk_status = status; |
775 | 770 | if (status == -ECONNREFUSED) | |
776 | switch (status) { | ||
777 | case -ECONNREFUSED: | ||
778 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 771 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
779 | case -EAGAIN: | ||
780 | case -ENOTCONN: | ||
781 | return; | ||
782 | default: | ||
783 | break; | ||
784 | } | ||
785 | xprt_release_write(xprt, task); | ||
786 | return; | ||
787 | } | 772 | } |
788 | 773 | ||
789 | static inline void do_xprt_reserve(struct rpc_task *task) | 774 | static inline void do_xprt_reserve(struct rpc_task *task) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ee678ed13b6f..441bd53f5eca 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -414,6 +414,33 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
414 | } | 414 | } |
415 | 415 | ||
416 | /** | 416 | /** |
417 | * xs_tcp_release_xprt - clean up after a tcp transmission | ||
418 | * @xprt: transport | ||
419 | * @task: rpc task | ||
420 | * | ||
421 | * This cleans up if an error causes us to abort the transmission of a request. | ||
422 | * In this case, the socket may need to be reset in order to avoid confusing | ||
423 | * the server. | ||
424 | */ | ||
425 | static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | ||
426 | { | ||
427 | struct rpc_rqst *req; | ||
428 | |||
429 | if (task != xprt->snd_task) | ||
430 | return; | ||
431 | if (task == NULL) | ||
432 | goto out_release; | ||
433 | req = task->tk_rqstp; | ||
434 | if (req->rq_bytes_sent == 0) | ||
435 | goto out_release; | ||
436 | if (req->rq_bytes_sent == req->rq_snd_buf.len) | ||
437 | goto out_release; | ||
438 | set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state); | ||
439 | out_release: | ||
440 | xprt_release_xprt(xprt, task); | ||
441 | } | ||
442 | |||
443 | /** | ||
417 | * xs_close - close a socket | 444 | * xs_close - close a socket |
418 | * @xprt: transport | 445 | * @xprt: transport |
419 | * | 446 | * |
@@ -1250,7 +1277,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
1250 | 1277 | ||
1251 | static struct rpc_xprt_ops xs_tcp_ops = { | 1278 | static struct rpc_xprt_ops xs_tcp_ops = { |
1252 | .reserve_xprt = xprt_reserve_xprt, | 1279 | .reserve_xprt = xprt_reserve_xprt, |
1253 | .release_xprt = xprt_release_xprt, | 1280 | .release_xprt = xs_tcp_release_xprt, |
1254 | .set_port = xs_set_port, | 1281 | .set_port = xs_set_port, |
1255 | .connect = xs_connect, | 1282 | .connect = xs_connect, |
1256 | .buf_alloc = rpc_malloc, | 1283 | .buf_alloc = rpc_malloc, |