diff options
author | Tony Luck <tony.luck@intel.com> | 2005-12-05 14:50:17 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2005-12-05 14:50:17 -0500 |
commit | 3e356b2660eda9da7776144cbc0a038c93dcb335 (patch) | |
tree | 378a38636f6b67a5f092a73850223d11cdfb5ff5 | |
parent | 05f70395c642bed0300bc1955bfa8c0f93de2bc2 (diff) | |
parent | e4f5c82a92c2a546a16af1614114eec19120e40a (diff) |
Auto-update from upstream
36 files changed, 354 insertions, 224 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 1fc80ec4999b..77bb08606912 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1636,6 +1636,15 @@ L: ldm-devel@lists.sourceforge.net | |||
1636 | W: http://ldm.sourceforge.net | 1636 | W: http://ldm.sourceforge.net |
1637 | S: Maintained | 1637 | S: Maintained |
1638 | 1638 | ||
1639 | LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) | ||
1640 | P: Eric Moore | ||
1641 | M: Eric.Moore@lsil.com | ||
1642 | M: support@lsil.com | ||
1643 | L: mpt_linux_developer@lsil.com | ||
1644 | L: linux-scsi@vger.kernel.org | ||
1645 | W: http://www.lsilogic.com/support | ||
1646 | S: Supported | ||
1647 | |||
1639 | LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers | 1648 | LSILOGIC/SYMBIOS/NCR 53C8XX and 53C1010 PCI-SCSI drivers |
1640 | P: Matthew Wilcox | 1649 | P: Matthew Wilcox |
1641 | M: matthew@wil.cx | 1650 | M: matthew@wil.cx |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 15 | 3 | SUBLEVEL = 15 |
4 | EXTRAVERSION =-rc4 | 4 | EXTRAVERSION =-rc5 |
5 | NAME=Affluent Albatross | 5 | NAME=Affluent Albatross |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/drivers/Makefile b/drivers/Makefile index fac1e1603097..ea410b6b7644 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -5,7 +5,7 @@ | |||
5 | # Rewritten to use lists instead of if-statements. | 5 | # Rewritten to use lists instead of if-statements. |
6 | # | 6 | # |
7 | 7 | ||
8 | obj-$(CONFIG_PCI) += pci/ usb/ | 8 | obj-$(CONFIG_PCI) += pci/ |
9 | obj-$(CONFIG_PARISC) += parisc/ | 9 | obj-$(CONFIG_PARISC) += parisc/ |
10 | obj-$(CONFIG_RAPIDIO) += rapidio/ | 10 | obj-$(CONFIG_RAPIDIO) += rapidio/ |
11 | obj-y += video/ | 11 | obj-y += video/ |
@@ -49,6 +49,7 @@ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ | |||
49 | obj-$(CONFIG_PARIDE) += block/paride/ | 49 | obj-$(CONFIG_PARIDE) += block/paride/ |
50 | obj-$(CONFIG_TC) += tc/ | 50 | obj-$(CONFIG_TC) += tc/ |
51 | obj-$(CONFIG_USB) += usb/ | 51 | obj-$(CONFIG_USB) += usb/ |
52 | obj-$(CONFIG_PCI) += usb/ | ||
52 | obj-$(CONFIG_USB_GADGET) += usb/gadget/ | 53 | obj-$(CONFIG_USB_GADGET) += usb/gadget/ |
53 | obj-$(CONFIG_GAMEPORT) += input/gameport/ | 54 | obj-$(CONFIG_GAMEPORT) += input/gameport/ |
54 | obj-$(CONFIG_INPUT) += input/ | 55 | obj-$(CONFIG_INPUT) += input/ |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 83fd1b6c10c4..5f51057518b0 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -169,15 +169,11 @@ acpi_processor_power_activate(struct acpi_processor *pr, | |||
169 | 169 | ||
170 | static void acpi_safe_halt(void) | 170 | static void acpi_safe_halt(void) |
171 | { | 171 | { |
172 | int polling = test_thread_flag(TIF_POLLING_NRFLAG); | 172 | clear_thread_flag(TIF_POLLING_NRFLAG); |
173 | if (polling) { | 173 | smp_mb__after_clear_bit(); |
174 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
175 | smp_mb__after_clear_bit(); | ||
176 | } | ||
177 | if (!need_resched()) | 174 | if (!need_resched()) |
178 | safe_halt(); | 175 | safe_halt(); |
179 | if (polling) | 176 | set_thread_flag(TIF_POLLING_NRFLAG); |
180 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
181 | } | 177 | } |
182 | 178 | ||
183 | static atomic_t c3_cpu_count; | 179 | static atomic_t c3_cpu_count; |
@@ -295,6 +291,16 @@ static void acpi_processor_idle(void) | |||
295 | * ------ | 291 | * ------ |
296 | * Invoke the current Cx state to put the processor to sleep. | 292 | * Invoke the current Cx state to put the processor to sleep. |
297 | */ | 293 | */ |
294 | if (cx->type == ACPI_STATE_C2 || cx->type == ACPI_STATE_C3) { | ||
295 | clear_thread_flag(TIF_POLLING_NRFLAG); | ||
296 | smp_mb__after_clear_bit(); | ||
297 | if (need_resched()) { | ||
298 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
299 | local_irq_enable(); | ||
300 | return; | ||
301 | } | ||
302 | } | ||
303 | |||
298 | switch (cx->type) { | 304 | switch (cx->type) { |
299 | 305 | ||
300 | case ACPI_STATE_C1: | 306 | case ACPI_STATE_C1: |
@@ -327,6 +333,7 @@ static void acpi_processor_idle(void) | |||
327 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); | 333 | t2 = inl(acpi_fadt.xpm_tmr_blk.address); |
328 | /* Re-enable interrupts */ | 334 | /* Re-enable interrupts */ |
329 | local_irq_enable(); | 335 | local_irq_enable(); |
336 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
330 | /* Compute time (ticks) that we were actually asleep */ | 337 | /* Compute time (ticks) that we were actually asleep */ |
331 | sleep_ticks = | 338 | sleep_ticks = |
332 | ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; | 339 | ticks_elapsed(t1, t2) - cx->latency_ticks - C2_OVERHEAD; |
@@ -366,6 +373,7 @@ static void acpi_processor_idle(void) | |||
366 | 373 | ||
367 | /* Re-enable interrupts */ | 374 | /* Re-enable interrupts */ |
368 | local_irq_enable(); | 375 | local_irq_enable(); |
376 | set_thread_flag(TIF_POLLING_NRFLAG); | ||
369 | /* Compute time (ticks) that we were actually asleep */ | 377 | /* Compute time (ticks) that we were actually asleep */ |
370 | sleep_ticks = | 378 | sleep_ticks = |
371 | ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; | 379 | ticks_elapsed(t1, t2) - cx->latency_ticks - C3_OVERHEAD; |
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 24651661630a..951709aa88ba 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -567,6 +567,7 @@ struct cx88_board cx88_boards[] = { | |||
567 | .radio_type = UNSET, | 567 | .radio_type = UNSET, |
568 | .tuner_addr = ADDR_UNSET, | 568 | .tuner_addr = ADDR_UNSET, |
569 | .radio_addr = ADDR_UNSET, | 569 | .radio_addr = ADDR_UNSET, |
570 | .tda9887_conf = TDA9887_PRESENT, | ||
570 | .input = {{ | 571 | .input = {{ |
571 | .type = CX88_VMUX_TELEVISION, | 572 | .type = CX88_VMUX_TELEVISION, |
572 | .vmux = 0, | 573 | .vmux = 0, |
@@ -711,6 +712,7 @@ struct cx88_board cx88_boards[] = { | |||
711 | .radio_type = UNSET, | 712 | .radio_type = UNSET, |
712 | .tuner_addr = ADDR_UNSET, | 713 | .tuner_addr = ADDR_UNSET, |
713 | .radio_addr = ADDR_UNSET, | 714 | .radio_addr = ADDR_UNSET, |
715 | .tda9887_conf = TDA9887_PRESENT, | ||
714 | .input = {{ | 716 | .input = {{ |
715 | .type = CX88_VMUX_TELEVISION, | 717 | .type = CX88_VMUX_TELEVISION, |
716 | .vmux = 0, | 718 | .vmux = 0, |
diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 65c2ec5c421b..4262a22adc22 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c | |||
@@ -1118,6 +1118,65 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp) | |||
1118 | return -1; | 1118 | return -1; |
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | int | ||
1122 | mpt_alt_ioc_wait(MPT_ADAPTER *ioc) | ||
1123 | { | ||
1124 | int loop_count = 30 * 4; /* Wait 30 seconds */ | ||
1125 | int status = -1; /* -1 means failed to get board READY */ | ||
1126 | |||
1127 | do { | ||
1128 | spin_lock(&ioc->initializing_hba_lock); | ||
1129 | if (ioc->initializing_hba_lock_flag == 0) { | ||
1130 | ioc->initializing_hba_lock_flag=1; | ||
1131 | spin_unlock(&ioc->initializing_hba_lock); | ||
1132 | status = 0; | ||
1133 | break; | ||
1134 | } | ||
1135 | spin_unlock(&ioc->initializing_hba_lock); | ||
1136 | set_current_state(TASK_INTERRUPTIBLE); | ||
1137 | schedule_timeout(HZ/4); | ||
1138 | } while (--loop_count); | ||
1139 | |||
1140 | return status; | ||
1141 | } | ||
1142 | |||
1143 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | ||
1144 | /* | ||
1145 | * mpt_bringup_adapter - This is a wrapper function for mpt_do_ioc_recovery | ||
1146 | * @ioc: Pointer to MPT adapter structure | ||
1147 | * @sleepFlag: Use schedule if CAN_SLEEP else use udelay. | ||
1148 | * | ||
1149 | * This routine performs all the steps necessary to bring the IOC | ||
1150 | * to a OPERATIONAL state. | ||
1151 | * | ||
1152 | * Special Note: This function was added with spin lock's so as to allow | ||
1153 | * the dv(domain validation) work thread to succeed on the other channel | ||
1154 | * that maybe occuring at the same time when this function is called. | ||
1155 | * Without this lock, the dv would fail when message frames were | ||
1156 | * requested during hba bringup on the alternate ioc. | ||
1157 | */ | ||
1158 | static int | ||
1159 | mpt_bringup_adapter(MPT_ADAPTER *ioc, int sleepFlag) | ||
1160 | { | ||
1161 | int r; | ||
1162 | |||
1163 | if(ioc->alt_ioc) { | ||
1164 | if((r=mpt_alt_ioc_wait(ioc->alt_ioc)!=0)) | ||
1165 | return r; | ||
1166 | } | ||
1167 | |||
1168 | r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, | ||
1169 | CAN_SLEEP); | ||
1170 | |||
1171 | if(ioc->alt_ioc) { | ||
1172 | spin_lock(&ioc->alt_ioc->initializing_hba_lock); | ||
1173 | ioc->alt_ioc->initializing_hba_lock_flag=0; | ||
1174 | spin_unlock(&ioc->alt_ioc->initializing_hba_lock); | ||
1175 | } | ||
1176 | |||
1177 | return r; | ||
1178 | } | ||
1179 | |||
1121 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 1180 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
1122 | /* | 1181 | /* |
1123 | * mpt_attach - Install a PCI intelligent MPT adapter. | 1182 | * mpt_attach - Install a PCI intelligent MPT adapter. |
@@ -1186,6 +1245,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1186 | ioc->pcidev = pdev; | 1245 | ioc->pcidev = pdev; |
1187 | ioc->diagPending = 0; | 1246 | ioc->diagPending = 0; |
1188 | spin_lock_init(&ioc->diagLock); | 1247 | spin_lock_init(&ioc->diagLock); |
1248 | spin_lock_init(&ioc->initializing_hba_lock); | ||
1189 | 1249 | ||
1190 | /* Initialize the event logging. | 1250 | /* Initialize the event logging. |
1191 | */ | 1251 | */ |
@@ -1408,8 +1468,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) | |||
1408 | */ | 1468 | */ |
1409 | mpt_detect_bound_ports(ioc, pdev); | 1469 | mpt_detect_bound_ports(ioc, pdev); |
1410 | 1470 | ||
1411 | if ((r = mpt_do_ioc_recovery(ioc, | 1471 | if ((r = mpt_bringup_adapter(ioc, CAN_SLEEP)) != 0){ |
1412 | MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0) { | ||
1413 | printk(KERN_WARNING MYNAM | 1472 | printk(KERN_WARNING MYNAM |
1414 | ": WARNING - %s did not initialize properly! (%d)\n", | 1473 | ": WARNING - %s did not initialize properly! (%d)\n", |
1415 | ioc->name, r); | 1474 | ioc->name, r); |
@@ -6298,6 +6357,7 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3); | |||
6298 | EXPORT_SYMBOL(mpt_alloc_fw_memory); | 6357 | EXPORT_SYMBOL(mpt_alloc_fw_memory); |
6299 | EXPORT_SYMBOL(mpt_free_fw_memory); | 6358 | EXPORT_SYMBOL(mpt_free_fw_memory); |
6300 | EXPORT_SYMBOL(mptbase_sas_persist_operation); | 6359 | EXPORT_SYMBOL(mptbase_sas_persist_operation); |
6360 | EXPORT_SYMBOL(mpt_alt_ioc_wait); | ||
6301 | 6361 | ||
6302 | 6362 | ||
6303 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ | 6363 | /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |
diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 5f5b3fb5b4d7..bac8eb4186d2 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h | |||
@@ -611,6 +611,8 @@ typedef struct _MPT_ADAPTER | |||
611 | int DoneCtx; | 611 | int DoneCtx; |
612 | int TaskCtx; | 612 | int TaskCtx; |
613 | int InternalCtx; | 613 | int InternalCtx; |
614 | spinlock_t initializing_hba_lock; | ||
615 | int initializing_hba_lock_flag; | ||
614 | struct list_head list; | 616 | struct list_head list; |
615 | struct net_device *netdev; | 617 | struct net_device *netdev; |
616 | struct list_head sas_topology; | 618 | struct list_head sas_topology; |
@@ -1001,6 +1003,7 @@ extern void mpt_free_fw_memory(MPT_ADAPTER *ioc); | |||
1001 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); | 1003 | extern int mpt_findImVolumes(MPT_ADAPTER *ioc); |
1002 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); | 1004 | extern int mpt_read_ioc_pg_3(MPT_ADAPTER *ioc); |
1003 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); | 1005 | extern int mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode); |
1006 | extern int mpt_alt_ioc_wait(MPT_ADAPTER *ioc); | ||
1004 | 1007 | ||
1005 | /* | 1008 | /* |
1006 | * Public data decl's... | 1009 | * Public data decl's... |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 4330ed0cedaa..b7b9846ff3fd 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -4162,6 +4162,12 @@ mptscsih_domainValidation(void *arg) | |||
4162 | } | 4162 | } |
4163 | } | 4163 | } |
4164 | 4164 | ||
4165 | if(mpt_alt_ioc_wait(hd->ioc)!=0) { | ||
4166 | ddvprintk((MYIOC_s_WARN_FMT "alt_ioc busy!\n", | ||
4167 | hd->ioc->name)); | ||
4168 | continue; | ||
4169 | } | ||
4170 | |||
4165 | if (mptscsih_doDv(hd, 0, id) == 1) { | 4171 | if (mptscsih_doDv(hd, 0, id) == 1) { |
4166 | /* Untagged device was busy, try again | 4172 | /* Untagged device was busy, try again |
4167 | */ | 4173 | */ |
@@ -4173,6 +4179,10 @@ mptscsih_domainValidation(void *arg) | |||
4173 | hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING); | 4179 | hd->ioc->spi_data.dvStatus[id] &= ~(MPT_SCSICFG_DV_NOT_DONE | MPT_SCSICFG_DV_PENDING); |
4174 | } | 4180 | } |
4175 | 4181 | ||
4182 | spin_lock(&hd->ioc->initializing_hba_lock); | ||
4183 | hd->ioc->initializing_hba_lock_flag=0; | ||
4184 | spin_unlock(&hd->ioc->initializing_hba_lock); | ||
4185 | |||
4176 | if (isPhysDisk) { | 4186 | if (isPhysDisk) { |
4177 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { | 4187 | for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { |
4178 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { | 4188 | if (hd->ioc->raid_data.isRaid & (1 << ii)) { |
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index c218b5c944a6..5e84c5aa7779 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c | |||
@@ -996,6 +996,20 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) | |||
996 | spin_lock_init(&adapter->fsf_req_list_lock); | 996 | spin_lock_init(&adapter->fsf_req_list_lock); |
997 | INIT_LIST_HEAD(&adapter->fsf_req_list_head); | 997 | INIT_LIST_HEAD(&adapter->fsf_req_list_head); |
998 | 998 | ||
999 | /* initialize debug locks */ | ||
1000 | |||
1001 | spin_lock_init(&adapter->erp_dbf_lock); | ||
1002 | spin_lock_init(&adapter->hba_dbf_lock); | ||
1003 | spin_lock_init(&adapter->san_dbf_lock); | ||
1004 | spin_lock_init(&adapter->scsi_dbf_lock); | ||
1005 | |||
1006 | /* initialize error recovery stuff */ | ||
1007 | |||
1008 | rwlock_init(&adapter->erp_lock); | ||
1009 | sema_init(&adapter->erp_ready_sem, 0); | ||
1010 | INIT_LIST_HEAD(&adapter->erp_ready_head); | ||
1011 | INIT_LIST_HEAD(&adapter->erp_running_head); | ||
1012 | |||
999 | /* initialize abort lock */ | 1013 | /* initialize abort lock */ |
1000 | rwlock_init(&adapter->abort_lock); | 1014 | rwlock_init(&adapter->abort_lock); |
1001 | 1015 | ||
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 826fb3b00605..95599719f8ab 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -926,7 +926,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
926 | char dbf_name[DEBUG_MAX_NAME_LEN]; | 926 | char dbf_name[DEBUG_MAX_NAME_LEN]; |
927 | 927 | ||
928 | /* debug feature area which records recovery activity */ | 928 | /* debug feature area which records recovery activity */ |
929 | spin_lock_init(&adapter->erp_dbf_lock); | ||
930 | sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter)); | 929 | sprintf(dbf_name, "zfcp_%s_erp", zfcp_get_busid_by_adapter(adapter)); |
931 | adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2, | 930 | adapter->erp_dbf = debug_register(dbf_name, dbfsize, 2, |
932 | sizeof(struct zfcp_erp_dbf_record)); | 931 | sizeof(struct zfcp_erp_dbf_record)); |
@@ -936,7 +935,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
936 | debug_set_level(adapter->erp_dbf, 3); | 935 | debug_set_level(adapter->erp_dbf, 3); |
937 | 936 | ||
938 | /* debug feature area which records HBA (FSF and QDIO) conditions */ | 937 | /* debug feature area which records HBA (FSF and QDIO) conditions */ |
939 | spin_lock_init(&adapter->hba_dbf_lock); | ||
940 | sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter)); | 938 | sprintf(dbf_name, "zfcp_%s_hba", zfcp_get_busid_by_adapter(adapter)); |
941 | adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, | 939 | adapter->hba_dbf = debug_register(dbf_name, dbfsize, 1, |
942 | sizeof(struct zfcp_hba_dbf_record)); | 940 | sizeof(struct zfcp_hba_dbf_record)); |
@@ -947,7 +945,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
947 | debug_set_level(adapter->hba_dbf, 3); | 945 | debug_set_level(adapter->hba_dbf, 3); |
948 | 946 | ||
949 | /* debug feature area which records SAN command failures and recovery */ | 947 | /* debug feature area which records SAN command failures and recovery */ |
950 | spin_lock_init(&adapter->san_dbf_lock); | ||
951 | sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter)); | 948 | sprintf(dbf_name, "zfcp_%s_san", zfcp_get_busid_by_adapter(adapter)); |
952 | adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, | 949 | adapter->san_dbf = debug_register(dbf_name, dbfsize, 1, |
953 | sizeof(struct zfcp_san_dbf_record)); | 950 | sizeof(struct zfcp_san_dbf_record)); |
@@ -958,7 +955,6 @@ int zfcp_adapter_debug_register(struct zfcp_adapter *adapter) | |||
958 | debug_set_level(adapter->san_dbf, 6); | 955 | debug_set_level(adapter->san_dbf, 6); |
959 | 956 | ||
960 | /* debug feature area which records SCSI command failures and recovery */ | 957 | /* debug feature area which records SCSI command failures and recovery */ |
961 | spin_lock_init(&adapter->scsi_dbf_lock); | ||
962 | sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter)); | 958 | sprintf(dbf_name, "zfcp_%s_scsi", zfcp_get_busid_by_adapter(adapter)); |
963 | adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, | 959 | adapter->scsi_dbf = debug_register(dbf_name, dbfsize, 1, |
964 | sizeof(struct zfcp_scsi_dbf_record)); | 960 | sizeof(struct zfcp_scsi_dbf_record)); |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 023f4e558ae4..ee7314d8c2da 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -1071,11 +1071,6 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter) | |||
1071 | 1071 | ||
1072 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); | 1072 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status); |
1073 | 1073 | ||
1074 | rwlock_init(&adapter->erp_lock); | ||
1075 | INIT_LIST_HEAD(&adapter->erp_ready_head); | ||
1076 | INIT_LIST_HEAD(&adapter->erp_running_head); | ||
1077 | sema_init(&adapter->erp_ready_sem, 0); | ||
1078 | |||
1079 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); | 1074 | retval = kernel_thread(zfcp_erp_thread, adapter, SIGCHLD); |
1080 | if (retval < 0) { | 1075 | if (retval < 0) { |
1081 | ZFCP_LOG_NORMAL("error: creation of erp thread failed for " | 1076 | ZFCP_LOG_NORMAL("error: creation of erp thread failed for " |
@@ -2248,29 +2243,26 @@ zfcp_erp_adapter_strategy_close_qdio(struct zfcp_erp_action *erp_action) | |||
2248 | return retval; | 2243 | return retval; |
2249 | } | 2244 | } |
2250 | 2245 | ||
2251 | /* | ||
2252 | * function: zfcp_fsf_init | ||
2253 | * | ||
2254 | * purpose: initializes FSF operation for the specified adapter | ||
2255 | * | ||
2256 | * returns: 0 - succesful initialization of FSF operation | ||
2257 | * !0 - failed to initialize FSF operation | ||
2258 | */ | ||
2259 | static int | 2246 | static int |
2260 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) | 2247 | zfcp_erp_adapter_strategy_open_fsf(struct zfcp_erp_action *erp_action) |
2261 | { | 2248 | { |
2262 | int xconfig, xport; | 2249 | int retval; |
2263 | 2250 | ||
2264 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2251 | if ((atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
2265 | &erp_action->adapter->status)) { | 2252 | &erp_action->adapter->status)) && |
2253 | (erp_action->adapter->adapter_features & | ||
2254 | FSF_FEATURE_HBAAPI_MANAGEMENT)) { | ||
2266 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 2255 | zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); |
2267 | atomic_set(&erp_action->adapter->erp_counter, 0); | 2256 | atomic_set(&erp_action->adapter->erp_counter, 0); |
2268 | return ZFCP_ERP_FAILED; | 2257 | return ZFCP_ERP_FAILED; |
2269 | } | 2258 | } |
2270 | 2259 | ||
2271 | xconfig = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); | 2260 | retval = zfcp_erp_adapter_strategy_open_fsf_xconfig(erp_action); |
2272 | xport = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | 2261 | if (retval == ZFCP_ERP_FAILED) |
2273 | if ((xconfig == ZFCP_ERP_FAILED) || (xport == ZFCP_ERP_FAILED)) | 2262 | return ZFCP_ERP_FAILED; |
2263 | |||
2264 | retval = zfcp_erp_adapter_strategy_open_fsf_xport(erp_action); | ||
2265 | if (retval == ZFCP_ERP_FAILED) | ||
2274 | return ZFCP_ERP_FAILED; | 2266 | return ZFCP_ERP_FAILED; |
2275 | 2267 | ||
2276 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); | 2268 | return zfcp_erp_adapter_strategy_open_fsf_statusread(erp_action); |
@@ -2359,41 +2351,29 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action) | |||
2359 | static int | 2351 | static int |
2360 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | 2352 | zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) |
2361 | { | 2353 | { |
2362 | int retval = ZFCP_ERP_SUCCEEDED; | 2354 | int ret; |
2363 | int retries; | 2355 | int retries; |
2364 | int sleep; | 2356 | int sleep; |
2365 | struct zfcp_adapter *adapter = erp_action->adapter; | 2357 | struct zfcp_adapter *adapter = erp_action->adapter; |
2366 | 2358 | ||
2367 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); | 2359 | atomic_clear_mask(ZFCP_STATUS_ADAPTER_XPORT_OK, &adapter->status); |
2368 | 2360 | ||
2369 | for (retries = 0; ; retries++) { | 2361 | retries = 0; |
2370 | ZFCP_LOG_DEBUG("Doing exchange port data\n"); | 2362 | do { |
2363 | write_lock(&adapter->erp_lock); | ||
2371 | zfcp_erp_action_to_running(erp_action); | 2364 | zfcp_erp_action_to_running(erp_action); |
2365 | write_unlock(&adapter->erp_lock); | ||
2372 | zfcp_erp_timeout_init(erp_action); | 2366 | zfcp_erp_timeout_init(erp_action); |
2373 | if (zfcp_fsf_exchange_port_data(erp_action, adapter, NULL)) { | 2367 | ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); |
2374 | retval = ZFCP_ERP_FAILED; | 2368 | if (ret == -EOPNOTSUPP) { |
2375 | debug_text_event(adapter->erp_dbf, 5, "a_fstx_xf"); | 2369 | debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); |
2376 | ZFCP_LOG_INFO("error: initiation of exchange of " | 2370 | return ZFCP_ERP_SUCCEEDED; |
2377 | "port data failed for adapter %s\n", | 2371 | } else if (ret) { |
2378 | zfcp_get_busid_by_adapter(adapter)); | 2372 | debug_text_event(adapter->erp_dbf, 3, "a_xport_failed"); |
2379 | break; | 2373 | return ZFCP_ERP_FAILED; |
2380 | } | 2374 | } |
2381 | debug_text_event(adapter->erp_dbf, 6, "a_fstx_xok"); | 2375 | debug_text_event(adapter->erp_dbf, 6, "a_xport_ok"); |
2382 | ZFCP_LOG_DEBUG("Xchange underway\n"); | ||
2383 | 2376 | ||
2384 | /* | ||
2385 | * Why this works: | ||
2386 | * Both the normal completion handler as well as the timeout | ||
2387 | * handler will do an 'up' when the 'exchange port data' | ||
2388 | * request completes or times out. Thus, the signal to go on | ||
2389 | * won't be lost utilizing this semaphore. | ||
2390 | * Furthermore, this 'adapter_reopen' action is | ||
2391 | * guaranteed to be the only action being there (highest action | ||
2392 | * which prevents other actions from being created). | ||
2393 | * Resulting from that, the wake signal recognized here | ||
2394 | * _must_ be the one belonging to the 'exchange port | ||
2395 | * data' request. | ||
2396 | */ | ||
2397 | down(&adapter->erp_ready_sem); | 2377 | down(&adapter->erp_ready_sem); |
2398 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { | 2378 | if (erp_action->status & ZFCP_STATUS_ERP_TIMEDOUT) { |
2399 | ZFCP_LOG_INFO("error: exchange of port data " | 2379 | ZFCP_LOG_INFO("error: exchange of port data " |
@@ -2401,29 +2381,19 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) | |||
2401 | zfcp_get_busid_by_adapter(adapter)); | 2381 | zfcp_get_busid_by_adapter(adapter)); |
2402 | break; | 2382 | break; |
2403 | } | 2383 | } |
2404 | |||
2405 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 2384 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, |
2406 | &adapter->status)) | 2385 | &adapter->status)) |
2407 | break; | 2386 | break; |
2408 | 2387 | ||
2409 | ZFCP_LOG_DEBUG("host connection still initialising... " | 2388 | if (retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES) { |
2410 | "waiting and retrying...\n"); | 2389 | sleep = ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP; |
2411 | /* sleep a little bit before retry */ | 2390 | retries++; |
2412 | sleep = retries < ZFCP_EXCHANGE_PORT_DATA_SHORT_RETRIES ? | 2391 | } else |
2413 | ZFCP_EXCHANGE_PORT_DATA_SHORT_SLEEP : | 2392 | sleep = ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; |
2414 | ZFCP_EXCHANGE_PORT_DATA_LONG_SLEEP; | 2393 | schedule_timeout(sleep); |
2415 | msleep(jiffies_to_msecs(sleep)); | 2394 | } while (1); |
2416 | } | ||
2417 | |||
2418 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
2419 | &adapter->status)) { | ||
2420 | ZFCP_LOG_INFO("error: exchange of port data for " | ||
2421 | "adapter %s failed\n", | ||
2422 | zfcp_get_busid_by_adapter(adapter)); | ||
2423 | retval = ZFCP_ERP_FAILED; | ||
2424 | } | ||
2425 | 2395 | ||
2426 | return retval; | 2396 | return ZFCP_ERP_SUCCEEDED; |
2427 | } | 2397 | } |
2428 | 2398 | ||
2429 | /* | 2399 | /* |
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 3b0fc1163f5f..59587951c847 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c | |||
@@ -554,6 +554,17 @@ static void | |||
554 | zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, | 554 | zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, |
555 | struct fsf_link_down_info *link_down) | 555 | struct fsf_link_down_info *link_down) |
556 | { | 556 | { |
557 | if (atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | ||
558 | &adapter->status)) | ||
559 | return; | ||
560 | |||
561 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status); | ||
562 | |||
563 | if (link_down == NULL) { | ||
564 | zfcp_erp_adapter_reopen(adapter, 0); | ||
565 | return; | ||
566 | } | ||
567 | |||
557 | switch (link_down->error_code) { | 568 | switch (link_down->error_code) { |
558 | case FSF_PSQ_LINK_NO_LIGHT: | 569 | case FSF_PSQ_LINK_NO_LIGHT: |
559 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " | 570 | ZFCP_LOG_NORMAL("The local link to adapter %s is down " |
@@ -634,20 +645,15 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, | |||
634 | link_down->explanation_code, | 645 | link_down->explanation_code, |
635 | link_down->vendor_specific_code); | 646 | link_down->vendor_specific_code); |
636 | 647 | ||
637 | if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 648 | switch (link_down->error_code) { |
638 | &adapter->status)) { | 649 | case FSF_PSQ_LINK_NO_LIGHT: |
639 | atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, | 650 | case FSF_PSQ_LINK_WRAP_PLUG: |
640 | &adapter->status); | 651 | case FSF_PSQ_LINK_NO_FCP: |
641 | switch (link_down->error_code) { | 652 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: |
642 | case FSF_PSQ_LINK_NO_LIGHT: | 653 | zfcp_erp_adapter_reopen(adapter, 0); |
643 | case FSF_PSQ_LINK_WRAP_PLUG: | 654 | break; |
644 | case FSF_PSQ_LINK_NO_FCP: | 655 | default: |
645 | case FSF_PSQ_LINK_FIRMWARE_UPDATE: | 656 | zfcp_erp_adapter_failed(adapter); |
646 | zfcp_erp_adapter_reopen(adapter, 0); | ||
647 | break; | ||
648 | default: | ||
649 | zfcp_erp_adapter_failed(adapter); | ||
650 | } | ||
651 | } | 657 | } |
652 | } | 658 | } |
653 | 659 | ||
@@ -919,30 +925,36 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) | |||
919 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: | 925 | case FSF_STATUS_READ_SUB_NO_PHYSICAL_LINK: |
920 | ZFCP_LOG_INFO("Physical link to adapter %s is down\n", | 926 | ZFCP_LOG_INFO("Physical link to adapter %s is down\n", |
921 | zfcp_get_busid_by_adapter(adapter)); | 927 | zfcp_get_busid_by_adapter(adapter)); |
928 | zfcp_fsf_link_down_info_eval(adapter, | ||
929 | (struct fsf_link_down_info *) | ||
930 | &status_buffer->payload); | ||
922 | break; | 931 | break; |
923 | case FSF_STATUS_READ_SUB_FDISC_FAILED: | 932 | case FSF_STATUS_READ_SUB_FDISC_FAILED: |
924 | ZFCP_LOG_INFO("Local link to adapter %s is down " | 933 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
925 | "due to failed FDISC login\n", | 934 | "due to failed FDISC login\n", |
926 | zfcp_get_busid_by_adapter(adapter)); | 935 | zfcp_get_busid_by_adapter(adapter)); |
936 | zfcp_fsf_link_down_info_eval(adapter, | ||
937 | (struct fsf_link_down_info *) | ||
938 | &status_buffer->payload); | ||
927 | break; | 939 | break; |
928 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: | 940 | case FSF_STATUS_READ_SUB_FIRMWARE_UPDATE: |
929 | ZFCP_LOG_INFO("Local link to adapter %s is down " | 941 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
930 | "due to firmware update on adapter\n", | 942 | "due to firmware update on adapter\n", |
931 | zfcp_get_busid_by_adapter(adapter)); | 943 | zfcp_get_busid_by_adapter(adapter)); |
944 | zfcp_fsf_link_down_info_eval(adapter, NULL); | ||
932 | break; | 945 | break; |
933 | default: | 946 | default: |
934 | ZFCP_LOG_INFO("Local link to adapter %s is down " | 947 | ZFCP_LOG_INFO("Local link to adapter %s is down " |
935 | "due to unknown reason\n", | 948 | "due to unknown reason\n", |
936 | zfcp_get_busid_by_adapter(adapter)); | 949 | zfcp_get_busid_by_adapter(adapter)); |
950 | zfcp_fsf_link_down_info_eval(adapter, NULL); | ||
937 | }; | 951 | }; |
938 | zfcp_fsf_link_down_info_eval(adapter, | ||
939 | (struct fsf_link_down_info *) &status_buffer->payload); | ||
940 | break; | 952 | break; |
941 | 953 | ||
942 | case FSF_STATUS_READ_LINK_UP: | 954 | case FSF_STATUS_READ_LINK_UP: |
943 | ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " | 955 | ZFCP_LOG_NORMAL("Local link to adapter %s was replugged. " |
944 | "Restarting operations on this adapter\n", | 956 | "Restarting operations on this adapter\n", |
945 | zfcp_get_busid_by_adapter(adapter)); | 957 | zfcp_get_busid_by_adapter(adapter)); |
946 | /* All ports should be marked as ready to run again */ | 958 | /* All ports should be marked as ready to run again */ |
947 | zfcp_erp_modify_adapter_status(adapter, | 959 | zfcp_erp_modify_adapter_status(adapter, |
948 | ZFCP_STATUS_COMMON_RUNNING, | 960 | ZFCP_STATUS_COMMON_RUNNING, |
@@ -2191,13 +2203,10 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
2191 | return -EOPNOTSUPP; | 2203 | return -EOPNOTSUPP; |
2192 | } | 2204 | } |
2193 | 2205 | ||
2194 | timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); | ||
2195 | if (!timer) | ||
2196 | return -ENOMEM; | ||
2197 | |||
2198 | /* setup new FSF request */ | 2206 | /* setup new FSF request */ |
2199 | retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, | 2207 | retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, |
2200 | 0, 0, &lock_flags, &fsf_req); | 2208 | erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0, |
2209 | 0, &lock_flags, &fsf_req); | ||
2201 | if (retval < 0) { | 2210 | if (retval < 0) { |
2202 | ZFCP_LOG_INFO("error: Out of resources. Could not create an " | 2211 | ZFCP_LOG_INFO("error: Out of resources. Could not create an " |
2203 | "exchange port data request for" | 2212 | "exchange port data request for" |
@@ -2205,25 +2214,33 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
2205 | zfcp_get_busid_by_adapter(adapter)); | 2214 | zfcp_get_busid_by_adapter(adapter)); |
2206 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2215 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
2207 | lock_flags); | 2216 | lock_flags); |
2208 | goto out; | 2217 | return retval; |
2209 | } | ||
2210 | |||
2211 | if (erp_action) { | ||
2212 | erp_action->fsf_req = fsf_req; | ||
2213 | fsf_req->erp_action = erp_action; | ||
2214 | } | 2218 | } |
2215 | 2219 | ||
2216 | if (data) | 2220 | if (data) |
2217 | fsf_req->data = (unsigned long) data; | 2221 | fsf_req->data = (unsigned long) data; |
2218 | 2222 | ||
2219 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); | 2223 | sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); |
2220 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; | 2224 | sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; |
2221 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; | 2225 | sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; |
2222 | 2226 | ||
2223 | init_timer(timer); | 2227 | if (erp_action) { |
2224 | timer->function = zfcp_fsf_request_timeout_handler; | 2228 | erp_action->fsf_req = fsf_req; |
2225 | timer->data = (unsigned long) adapter; | 2229 | fsf_req->erp_action = erp_action; |
2226 | timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; | 2230 | timer = &erp_action->timer; |
2231 | } else { | ||
2232 | timer = kmalloc(sizeof(struct timer_list), GFP_ATOMIC); | ||
2233 | if (!timer) { | ||
2234 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | ||
2235 | lock_flags); | ||
2236 | zfcp_fsf_req_free(fsf_req); | ||
2237 | return -ENOMEM; | ||
2238 | } | ||
2239 | init_timer(timer); | ||
2240 | timer->function = zfcp_fsf_request_timeout_handler; | ||
2241 | timer->data = (unsigned long) adapter; | ||
2242 | timer->expires = ZFCP_FSF_REQUEST_TIMEOUT; | ||
2243 | } | ||
2227 | 2244 | ||
2228 | retval = zfcp_fsf_req_send(fsf_req, timer); | 2245 | retval = zfcp_fsf_req_send(fsf_req, timer); |
2229 | if (retval) { | 2246 | if (retval) { |
@@ -2233,23 +2250,22 @@ zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, | |||
2233 | zfcp_fsf_req_free(fsf_req); | 2250 | zfcp_fsf_req_free(fsf_req); |
2234 | if (erp_action) | 2251 | if (erp_action) |
2235 | erp_action->fsf_req = NULL; | 2252 | erp_action->fsf_req = NULL; |
2253 | else | ||
2254 | kfree(timer); | ||
2236 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | 2255 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, |
2237 | lock_flags); | 2256 | lock_flags); |
2238 | goto out; | 2257 | return retval; |
2239 | } | 2258 | } |
2240 | 2259 | ||
2241 | ZFCP_LOG_DEBUG("Exchange Port Data request initiated (adapter %s)\n", | 2260 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); |
2242 | zfcp_get_busid_by_adapter(adapter)); | ||
2243 | |||
2244 | write_unlock_irqrestore(&adapter->request_queue.queue_lock, | ||
2245 | lock_flags); | ||
2246 | 2261 | ||
2247 | wait_event(fsf_req->completion_wq, | 2262 | if (!erp_action) { |
2248 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); | 2263 | wait_event(fsf_req->completion_wq, |
2249 | del_timer_sync(timer); | 2264 | fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); |
2250 | zfcp_fsf_req_free(fsf_req); | 2265 | del_timer_sync(timer); |
2251 | out: | 2266 | zfcp_fsf_req_free(fsf_req); |
2252 | kfree(timer); | 2267 | kfree(timer); |
2268 | } | ||
2253 | return retval; | 2269 | return retval; |
2254 | } | 2270 | } |
2255 | 2271 | ||
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index 3dcd1bfba3b4..66608d13a634 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c | |||
@@ -179,7 +179,7 @@ zfcp_scsi_slave_alloc(struct scsi_device *sdp) | |||
179 | struct zfcp_adapter *adapter; | 179 | struct zfcp_adapter *adapter; |
180 | struct zfcp_unit *unit; | 180 | struct zfcp_unit *unit; |
181 | unsigned long flags; | 181 | unsigned long flags; |
182 | int retval = -ENODEV; | 182 | int retval = -ENXIO; |
183 | 183 | ||
184 | adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; | 184 | adapter = (struct zfcp_adapter *) sdp->host->hostdata[0]; |
185 | if (!adapter) | 185 | if (!adapter) |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index ab383d1f59e2..3cb68af90456 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -325,6 +325,8 @@ static int aac_biosparm(struct scsi_device *sdev, struct block_device *bdev, | |||
325 | * translations ( 64/32, 128/32, 255/63 ). | 325 | * translations ( 64/32, 128/32, 255/63 ). |
326 | */ | 326 | */ |
327 | buf = scsi_bios_ptable(bdev); | 327 | buf = scsi_bios_ptable(bdev); |
328 | if (!buf) | ||
329 | return 0; | ||
328 | if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) { | 330 | if(*(__le16 *)(buf + 0x40) == cpu_to_le16(0xaa55)) { |
329 | struct partition *first = (struct partition * )buf; | 331 | struct partition *first = (struct partition * )buf; |
330 | struct partition *entry = first; | 332 | struct partition *entry = first; |
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 31e9f40e79a2..6aab9dacdeea 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c | |||
@@ -2105,7 +2105,7 @@ ahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
2105 | scmd_id(cmd), | 2105 | scmd_id(cmd), |
2106 | scmd_channel(cmd) + 'A', | 2106 | scmd_channel(cmd) + 'A', |
2107 | CAM_LUN_WILDCARD, | 2107 | CAM_LUN_WILDCARD, |
2108 | SCB_LIST_NULL, ROLE_INITIATOR) == 0) | 2108 | SCB_LIST_NULL, ROLE_INITIATOR)) |
2109 | break; | 2109 | break; |
2110 | } | 2110 | } |
2111 | } | 2111 | } |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 7fc6454068e4..d866213f42b8 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -2169,7 +2169,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) | |||
2169 | if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd), | 2169 | if (ahc_match_scb(ahc, pending_scb, scmd_id(cmd), |
2170 | scmd_channel(cmd) + 'A', | 2170 | scmd_channel(cmd) + 'A', |
2171 | CAM_LUN_WILDCARD, | 2171 | CAM_LUN_WILDCARD, |
2172 | SCB_LIST_NULL, ROLE_INITIATOR) == 0) | 2172 | SCB_LIST_NULL, ROLE_INITIATOR)) |
2173 | break; | 2173 | break; |
2174 | } | 2174 | } |
2175 | } | 2175 | } |
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index 3b4ca55a3332..379e87089764 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c | |||
@@ -2239,7 +2239,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) | |||
2239 | struct scsi_cmnd *cmd = qc->scsicmd; | 2239 | struct scsi_cmnd *cmd = qc->scsicmd; |
2240 | 2240 | ||
2241 | if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) | 2241 | if ((tf->protocol = ata_scsi_map_proto(scsicmd[1])) == ATA_PROT_UNKNOWN) |
2242 | return 1; | 2242 | goto invalid_fld; |
2243 | 2243 | ||
2244 | /* | 2244 | /* |
2245 | * 12 and 16 byte CDBs use different offsets to | 2245 | * 12 and 16 byte CDBs use different offsets to |
@@ -2301,7 +2301,7 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) | |||
2301 | */ | 2301 | */ |
2302 | if ((tf->command == ATA_CMD_SET_FEATURES) | 2302 | if ((tf->command == ATA_CMD_SET_FEATURES) |
2303 | && (tf->feature == SETFEATURES_XFER)) | 2303 | && (tf->feature == SETFEATURES_XFER)) |
2304 | return 1; | 2304 | goto invalid_fld; |
2305 | 2305 | ||
2306 | /* | 2306 | /* |
2307 | * Set flags so that all registers will be written, | 2307 | * Set flags so that all registers will be written, |
@@ -2322,6 +2322,11 @@ ata_scsi_pass_thru(struct ata_queued_cmd *qc, const u8 *scsicmd) | |||
2322 | qc->nsect = cmd->bufflen / ATA_SECT_SIZE; | 2322 | qc->nsect = cmd->bufflen / ATA_SECT_SIZE; |
2323 | 2323 | ||
2324 | return 0; | 2324 | return 0; |
2325 | |||
2326 | invalid_fld: | ||
2327 | ata_scsi_set_sense(qc->scsicmd, ILLEGAL_REQUEST, 0x24, 0x00); | ||
2328 | /* "Invalid field in cdb" */ | ||
2329 | return 1; | ||
2325 | } | 2330 | } |
2326 | 2331 | ||
2327 | /** | 2332 | /** |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index ce9d73a292e2..4afef5cdcb17 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -542,17 +542,10 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) | |||
542 | 542 | ||
543 | void scsi_next_command(struct scsi_cmnd *cmd) | 543 | void scsi_next_command(struct scsi_cmnd *cmd) |
544 | { | 544 | { |
545 | struct scsi_device *sdev = cmd->device; | 545 | struct request_queue *q = cmd->device->request_queue; |
546 | struct request_queue *q = sdev->request_queue; | ||
547 | |||
548 | /* need to hold a reference on the device before we let go of the cmd */ | ||
549 | get_device(&sdev->sdev_gendev); | ||
550 | 546 | ||
551 | scsi_put_command(cmd); | 547 | scsi_put_command(cmd); |
552 | scsi_run_queue(q); | 548 | scsi_run_queue(q); |
553 | |||
554 | /* ok to remove device now */ | ||
555 | put_device(&sdev->sdev_gendev); | ||
556 | } | 549 | } |
557 | 550 | ||
558 | void scsi_run_host_queues(struct Scsi_Host *shost) | 551 | void scsi_run_host_queues(struct Scsi_Host *shost) |
diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 718a2bc4ed5e..38a53b5f9e9a 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c | |||
@@ -812,12 +812,10 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) | |||
812 | if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev)) | 812 | if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev)) |
813 | return; | 813 | return; |
814 | 814 | ||
815 | /* see if the device has an echo buffer. If it does we can | 815 | /* len == -1 is the signal that we need to ascertain the |
816 | * do the SPI pattern write tests */ | 816 | * presence of an echo buffer before trying to use it. len == |
817 | 817 | * 0 means we don't have an echo buffer */ | |
818 | len = 0; | 818 | len = -1; |
819 | if (scsi_device_dt(sdev)) | ||
820 | len = spi_dv_device_get_echo_buffer(sdev, buffer); | ||
821 | 819 | ||
822 | retry: | 820 | retry: |
823 | 821 | ||
@@ -840,11 +838,23 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) | |||
840 | if (spi_min_period(starget) == 8) | 838 | if (spi_min_period(starget) == 8) |
841 | DV_SET(pcomp_en, 1); | 839 | DV_SET(pcomp_en, 1); |
842 | } | 840 | } |
841 | /* Do the read only INQUIRY tests */ | ||
842 | spi_dv_retrain(sdev, buffer, buffer + sdev->inquiry_len, | ||
843 | spi_dv_device_compare_inquiry); | ||
844 | /* See if we actually managed to negotiate and sustain DT */ | ||
845 | if (i->f->get_dt) | ||
846 | i->f->get_dt(starget); | ||
847 | |||
848 | /* see if the device has an echo buffer. If it does we can do | ||
849 | * the SPI pattern write tests. Because of some broken | ||
850 | * devices, we *only* try this on a device that has actually | ||
851 | * negotiated DT */ | ||
852 | |||
853 | if (len == -1 && spi_dt(starget)) | ||
854 | len = spi_dv_device_get_echo_buffer(sdev, buffer); | ||
843 | 855 | ||
844 | if (len == 0) { | 856 | if (len <= 0) { |
845 | starget_printk(KERN_INFO, starget, "Domain Validation skipping write tests\n"); | 857 | starget_printk(KERN_INFO, starget, "Domain Validation skipping write tests\n"); |
846 | spi_dv_retrain(sdev, buffer, buffer + len, | ||
847 | spi_dv_device_compare_inquiry); | ||
848 | return; | 858 | return; |
849 | } | 859 | } |
850 | 860 | ||
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 72ec59456e69..b55c2a8a547c 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1860,9 +1860,11 @@ st_map_user_pages(struct scatterlist *sgl, const unsigned int max_pages, | |||
1860 | unlock_page(pages[j]); */ | 1860 | unlock_page(pages[j]); */ |
1861 | res = 0; | 1861 | res = 0; |
1862 | out_unmap: | 1862 | out_unmap: |
1863 | if (res > 0) | 1863 | if (res > 0) { |
1864 | for (j=0; j < res; j++) | 1864 | for (j=0; j < res; j++) |
1865 | page_cache_release(pages[j]); | 1865 | page_cache_release(pages[j]); |
1866 | res = 0; | ||
1867 | } | ||
1866 | kfree(pages); | 1868 | kfree(pages); |
1867 | return res; | 1869 | return res; |
1868 | } | 1870 | } |
@@ -1878,8 +1880,6 @@ st_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_pages, | |||
1878 | for (i=0; i < nr_pages; i++) { | 1880 | for (i=0; i < nr_pages; i++) { |
1879 | struct page *page = sgl[i].page; | 1881 | struct page *page = sgl[i].page; |
1880 | 1882 | ||
1881 | /* XXX: just for debug. Remove when PageReserved is removed */ | ||
1882 | BUG_ON(PageReserved(page)); | ||
1883 | if (dirtied) | 1883 | if (dirtied) |
1884 | SetPageDirty(page); | 1884 | SetPageDirty(page); |
1885 | /* unlock_page(page); */ | 1885 | /* unlock_page(page); */ |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 770c4324f3d5..7ac6ea141fff 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -4509,6 +4509,7 @@ static int sgl_map_user_pages(struct scatterlist *sgl, const unsigned int max_pa | |||
4509 | if (res > 0) { | 4509 | if (res > 0) { |
4510 | for (j=0; j < res; j++) | 4510 | for (j=0; j < res; j++) |
4511 | page_cache_release(pages[j]); | 4511 | page_cache_release(pages[j]); |
4512 | res = 0; | ||
4512 | } | 4513 | } |
4513 | kfree(pages); | 4514 | kfree(pages); |
4514 | return res; | 4515 | return res; |
@@ -4524,8 +4525,6 @@ static int sgl_unmap_user_pages(struct scatterlist *sgl, const unsigned int nr_p | |||
4524 | for (i=0; i < nr_pages; i++) { | 4525 | for (i=0; i < nr_pages; i++) { |
4525 | struct page *page = sgl[i].page; | 4526 | struct page *page = sgl[i].page; |
4526 | 4527 | ||
4527 | /* XXX: just for debug. Remove when PageReserved is removed */ | ||
4528 | BUG_ON(PageReserved(page)); | ||
4529 | if (dirtied) | 4528 | if (dirtied) |
4530 | SetPageDirty(page); | 4529 | SetPageDirty(page); |
4531 | /* FIXME: cache flush missing for rw==READ | 4530 | /* FIXME: cache flush missing for rw==READ |
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index d76766c3ce16..7fc0b97173e1 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c | |||
@@ -2086,6 +2086,7 @@ static void sym2_set_dt(struct scsi_target *starget, int dt) | |||
2086 | tp->tgoal.check_nego = 1; | 2086 | tp->tgoal.check_nego = 1; |
2087 | } | 2087 | } |
2088 | 2088 | ||
2089 | #if 0 | ||
2089 | static void sym2_set_iu(struct scsi_target *starget, int iu) | 2090 | static void sym2_set_iu(struct scsi_target *starget, int iu) |
2090 | { | 2091 | { |
2091 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 2092 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
@@ -2111,7 +2112,7 @@ static void sym2_set_qas(struct scsi_target *starget, int qas) | |||
2111 | tp->tgoal.qas = 0; | 2112 | tp->tgoal.qas = 0; |
2112 | tp->tgoal.check_nego = 1; | 2113 | tp->tgoal.check_nego = 1; |
2113 | } | 2114 | } |
2114 | 2115 | #endif | |
2115 | 2116 | ||
2116 | static struct spi_function_template sym2_transport_functions = { | 2117 | static struct spi_function_template sym2_transport_functions = { |
2117 | .set_offset = sym2_set_offset, | 2118 | .set_offset = sym2_set_offset, |
@@ -2122,10 +2123,12 @@ static struct spi_function_template sym2_transport_functions = { | |||
2122 | .show_width = 1, | 2123 | .show_width = 1, |
2123 | .set_dt = sym2_set_dt, | 2124 | .set_dt = sym2_set_dt, |
2124 | .show_dt = 1, | 2125 | .show_dt = 1, |
2126 | #if 0 | ||
2125 | .set_iu = sym2_set_iu, | 2127 | .set_iu = sym2_set_iu, |
2126 | .show_iu = 1, | 2128 | .show_iu = 1, |
2127 | .set_qas = sym2_set_qas, | 2129 | .set_qas = sym2_set_qas, |
2128 | .show_qas = 1, | 2130 | .show_qas = 1, |
2131 | #endif | ||
2129 | .get_signalling = sym2_get_signalling, | 2132 | .get_signalling = sym2_get_signalling, |
2130 | }; | 2133 | }; |
2131 | 2134 | ||
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 7370583b61e5..c0d1a214572c 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -1287,6 +1287,7 @@ dentry->d_parent->d_name.name, dentry->d_name.name); | |||
1287 | nfs_begin_data_update(dentry->d_inode); | 1287 | nfs_begin_data_update(dentry->d_inode); |
1288 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1288 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
1289 | dir, &qsilly); | 1289 | dir, &qsilly); |
1290 | nfs_mark_for_revalidate(dentry->d_inode); | ||
1290 | nfs_end_data_update(dentry->d_inode); | 1291 | nfs_end_data_update(dentry->d_inode); |
1291 | } else | 1292 | } else |
1292 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, | 1293 | error = NFS_PROTO(dir)->rename(dir, &dentry->d_name, |
@@ -1334,6 +1335,7 @@ static int nfs_safe_remove(struct dentry *dentry) | |||
1334 | /* The VFS may want to delete this inode */ | 1335 | /* The VFS may want to delete this inode */ |
1335 | if (error == 0) | 1336 | if (error == 0) |
1336 | inode->i_nlink--; | 1337 | inode->i_nlink--; |
1338 | nfs_mark_for_revalidate(inode); | ||
1337 | nfs_end_data_update(inode); | 1339 | nfs_end_data_update(inode); |
1338 | } else | 1340 | } else |
1339 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); | 1341 | error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); |
@@ -1556,6 +1558,7 @@ go_ahead: | |||
1556 | nfs_begin_data_update(old_inode); | 1558 | nfs_begin_data_update(old_inode); |
1557 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, | 1559 | error = NFS_PROTO(old_dir)->rename(old_dir, &old_dentry->d_name, |
1558 | new_dir, &new_dentry->d_name); | 1560 | new_dir, &new_dentry->d_name); |
1561 | nfs_mark_for_revalidate(old_inode); | ||
1559 | nfs_end_data_update(old_inode); | 1562 | nfs_end_data_update(old_inode); |
1560 | nfs_end_data_update(new_dir); | 1563 | nfs_end_data_update(new_dir); |
1561 | nfs_end_data_update(old_dir); | 1564 | nfs_end_data_update(old_dir); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index aaab1a5ac461..afd75d0463fd 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -54,7 +54,7 @@ | |||
54 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) | 54 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) |
55 | 55 | ||
56 | static void nfs_invalidate_inode(struct inode *); | 56 | static void nfs_invalidate_inode(struct inode *); |
57 | static int nfs_update_inode(struct inode *, struct nfs_fattr *, unsigned long); | 57 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); |
58 | 58 | ||
59 | static struct inode *nfs_alloc_inode(struct super_block *sb); | 59 | static struct inode *nfs_alloc_inode(struct super_block *sb); |
60 | static void nfs_destroy_inode(struct inode *); | 60 | static void nfs_destroy_inode(struct inode *); |
@@ -1080,8 +1080,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1080 | int status = -ESTALE; | 1080 | int status = -ESTALE; |
1081 | struct nfs_fattr fattr; | 1081 | struct nfs_fattr fattr; |
1082 | struct nfs_inode *nfsi = NFS_I(inode); | 1082 | struct nfs_inode *nfsi = NFS_I(inode); |
1083 | unsigned long verifier; | ||
1084 | unsigned long cache_validity; | ||
1085 | 1083 | ||
1086 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 1084 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
1087 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 1085 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
@@ -1106,8 +1104,6 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1106 | } | 1104 | } |
1107 | } | 1105 | } |
1108 | 1106 | ||
1109 | /* Protect against RPC races by saving the change attribute */ | ||
1110 | verifier = nfs_save_change_attribute(inode); | ||
1111 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 1107 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
1112 | if (status != 0) { | 1108 | if (status != 0) { |
1113 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 1109 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
@@ -1122,7 +1118,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1122 | } | 1118 | } |
1123 | 1119 | ||
1124 | spin_lock(&inode->i_lock); | 1120 | spin_lock(&inode->i_lock); |
1125 | status = nfs_update_inode(inode, &fattr, verifier); | 1121 | status = nfs_update_inode(inode, &fattr); |
1126 | if (status) { | 1122 | if (status) { |
1127 | spin_unlock(&inode->i_lock); | 1123 | spin_unlock(&inode->i_lock); |
1128 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 1124 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
@@ -1130,20 +1126,11 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | |||
1130 | (long long)NFS_FILEID(inode), status); | 1126 | (long long)NFS_FILEID(inode), status); |
1131 | goto out; | 1127 | goto out; |
1132 | } | 1128 | } |
1133 | cache_validity = nfsi->cache_validity; | ||
1134 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | ||
1135 | |||
1136 | /* | ||
1137 | * We may need to keep the attributes marked as invalid if | ||
1138 | * we raced with nfs_end_attr_update(). | ||
1139 | */ | ||
1140 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) | ||
1141 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
1142 | spin_unlock(&inode->i_lock); | 1129 | spin_unlock(&inode->i_lock); |
1143 | 1130 | ||
1144 | nfs_revalidate_mapping(inode, inode->i_mapping); | 1131 | nfs_revalidate_mapping(inode, inode->i_mapping); |
1145 | 1132 | ||
1146 | if (cache_validity & NFS_INO_INVALID_ACL) | 1133 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
1147 | nfs_zap_acl_cache(inode); | 1134 | nfs_zap_acl_cache(inode); |
1148 | 1135 | ||
1149 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 1136 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", |
@@ -1346,10 +1333,8 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1346 | return 0; | 1333 | return 0; |
1347 | spin_lock(&inode->i_lock); | 1334 | spin_lock(&inode->i_lock); |
1348 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | 1335 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
1349 | if (nfs_verify_change_attribute(inode, fattr->time_start)) | ||
1350 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
1351 | if (time_after(fattr->time_start, nfsi->last_updated)) | 1336 | if (time_after(fattr->time_start, nfsi->last_updated)) |
1352 | status = nfs_update_inode(inode, fattr, fattr->time_start); | 1337 | status = nfs_update_inode(inode, fattr); |
1353 | else | 1338 | else |
1354 | status = nfs_check_inode_attributes(inode, fattr); | 1339 | status = nfs_check_inode_attributes(inode, fattr); |
1355 | 1340 | ||
@@ -1375,10 +1360,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1375 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; | 1360 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; |
1376 | goto out; | 1361 | goto out; |
1377 | } | 1362 | } |
1378 | status = nfs_update_inode(inode, fattr, fattr->time_start); | 1363 | status = nfs_update_inode(inode, fattr); |
1379 | if (time_after_eq(fattr->time_start, nfsi->cache_change_attribute)) | ||
1380 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
1381 | nfsi->cache_change_attribute = jiffies; | ||
1382 | out: | 1364 | out: |
1383 | spin_unlock(&inode->i_lock); | 1365 | spin_unlock(&inode->i_lock); |
1384 | return status; | 1366 | return status; |
@@ -1396,12 +1378,12 @@ out: | |||
1396 | * | 1378 | * |
1397 | * A very similar scenario holds for the dir cache. | 1379 | * A very similar scenario holds for the dir cache. |
1398 | */ | 1380 | */ |
1399 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsigned long verifier) | 1381 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
1400 | { | 1382 | { |
1401 | struct nfs_inode *nfsi = NFS_I(inode); | 1383 | struct nfs_inode *nfsi = NFS_I(inode); |
1402 | loff_t cur_isize, new_isize; | 1384 | loff_t cur_isize, new_isize; |
1403 | unsigned int invalid = 0; | 1385 | unsigned int invalid = 0; |
1404 | int data_unstable; | 1386 | int data_stable; |
1405 | 1387 | ||
1406 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 1388 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
1407 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, | 1389 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, |
@@ -1432,8 +1414,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1432 | nfsi->last_updated = jiffies; | 1414 | nfsi->last_updated = jiffies; |
1433 | 1415 | ||
1434 | /* Are we racing with known updates of the metadata on the server? */ | 1416 | /* Are we racing with known updates of the metadata on the server? */ |
1435 | data_unstable = ! (nfs_verify_change_attribute(inode, verifier) || | 1417 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); |
1436 | (nfsi->cache_validity & NFS_INO_REVAL_PAGECACHE)); | 1418 | if (data_stable) |
1419 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | ||
1437 | 1420 | ||
1438 | /* Check if our cached file size is stale */ | 1421 | /* Check if our cached file size is stale */ |
1439 | new_isize = nfs_size_to_loff_t(fattr->size); | 1422 | new_isize = nfs_size_to_loff_t(fattr->size); |
@@ -1442,7 +1425,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1442 | /* Do we perhaps have any outstanding writes? */ | 1425 | /* Do we perhaps have any outstanding writes? */ |
1443 | if (nfsi->npages == 0) { | 1426 | if (nfsi->npages == 0) { |
1444 | /* No, but did we race with nfs_end_data_update()? */ | 1427 | /* No, but did we race with nfs_end_data_update()? */ |
1445 | if (time_after_eq(verifier, nfsi->cache_change_attribute)) { | 1428 | if (data_stable) { |
1446 | inode->i_size = new_isize; | 1429 | inode->i_size = new_isize; |
1447 | invalid |= NFS_INO_INVALID_DATA; | 1430 | invalid |= NFS_INO_INVALID_DATA; |
1448 | } | 1431 | } |
@@ -1451,6 +1434,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1451 | inode->i_size = new_isize; | 1434 | inode->i_size = new_isize; |
1452 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1435 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1453 | } | 1436 | } |
1437 | nfsi->cache_change_attribute = jiffies; | ||
1454 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1438 | dprintk("NFS: isize change on server for file %s/%ld\n", |
1455 | inode->i_sb->s_id, inode->i_ino); | 1439 | inode->i_sb->s_id, inode->i_ino); |
1456 | } | 1440 | } |
@@ -1460,8 +1444,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1460 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1444 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
1461 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1445 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
1462 | inode->i_sb->s_id, inode->i_ino); | 1446 | inode->i_sb->s_id, inode->i_ino); |
1463 | if (!data_unstable) | 1447 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
1464 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1448 | nfsi->cache_change_attribute = jiffies; |
1465 | } | 1449 | } |
1466 | 1450 | ||
1467 | if ((fattr->valid & NFS_ATTR_FATTR_V4) | 1451 | if ((fattr->valid & NFS_ATTR_FATTR_V4) |
@@ -1469,15 +1453,15 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1469 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1453 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
1470 | inode->i_sb->s_id, inode->i_ino); | 1454 | inode->i_sb->s_id, inode->i_ino); |
1471 | nfsi->change_attr = fattr->change_attr; | 1455 | nfsi->change_attr = fattr->change_attr; |
1472 | if (!data_unstable) | 1456 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1473 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1457 | nfsi->cache_change_attribute = jiffies; |
1474 | } | 1458 | } |
1475 | 1459 | ||
1476 | /* If ctime has changed we should definitely clear access+acl caches */ | 1460 | /* If ctime has changed we should definitely clear access+acl caches */ |
1477 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1461 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
1478 | if (!data_unstable) | 1462 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
1479 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | ||
1480 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1463 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
1464 | nfsi->cache_change_attribute = jiffies; | ||
1481 | } | 1465 | } |
1482 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1466 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
1483 | 1467 | ||
@@ -1515,6 +1499,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign | |||
1515 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1499 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1516 | || S_ISLNK(inode->i_mode))) | 1500 | || S_ISLNK(inode->i_mode))) |
1517 | invalid &= ~NFS_INO_INVALID_DATA; | 1501 | invalid &= ~NFS_INO_INVALID_DATA; |
1502 | if (data_stable) | ||
1503 | invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | ||
1518 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1504 | if (!nfs_have_delegation(inode, FMODE_READ)) |
1519 | nfsi->cache_validity |= invalid; | 1505 | nfsi->cache_validity |= invalid; |
1520 | 1506 | ||
@@ -2066,6 +2052,7 @@ static struct inode *nfs_alloc_inode(struct super_block *sb) | |||
2066 | return NULL; | 2052 | return NULL; |
2067 | nfsi->flags = 0UL; | 2053 | nfsi->flags = 0UL; |
2068 | nfsi->cache_validity = 0UL; | 2054 | nfsi->cache_validity = 0UL; |
2055 | nfsi->cache_change_attribute = jiffies; | ||
2069 | #ifdef CONFIG_NFS_V3_ACL | 2056 | #ifdef CONFIG_NFS_V3_ACL |
2070 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 2057 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
2071 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 2058 | nfsi->acl_default = ERR_PTR(-EAGAIN); |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 60e0dd800cc3..f988a9417b13 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1506,10 +1506,15 @@ static int _nfs4_proc_write(struct nfs_write_data *wdata) | |||
1506 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, | 1506 | dprintk("NFS call write %d @ %Ld\n", wdata->args.count, |
1507 | (long long) wdata->args.offset); | 1507 | (long long) wdata->args.offset); |
1508 | 1508 | ||
1509 | wdata->args.bitmask = server->attr_bitmask; | ||
1510 | wdata->res.server = server; | ||
1509 | nfs_fattr_init(fattr); | 1511 | nfs_fattr_init(fattr); |
1510 | status = rpc_call_sync(server->client, &msg, rpcflags); | 1512 | status = rpc_call_sync(server->client, &msg, rpcflags); |
1511 | dprintk("NFS reply write: %d\n", status); | 1513 | dprintk("NFS reply write: %d\n", status); |
1512 | return status; | 1514 | if (status < 0) |
1515 | return status; | ||
1516 | nfs_post_op_update_inode(inode, fattr); | ||
1517 | return wdata->res.count; | ||
1513 | } | 1518 | } |
1514 | 1519 | ||
1515 | static int nfs4_proc_write(struct nfs_write_data *wdata) | 1520 | static int nfs4_proc_write(struct nfs_write_data *wdata) |
@@ -1540,9 +1545,13 @@ static int _nfs4_proc_commit(struct nfs_write_data *cdata) | |||
1540 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, | 1545 | dprintk("NFS call commit %d @ %Ld\n", cdata->args.count, |
1541 | (long long) cdata->args.offset); | 1546 | (long long) cdata->args.offset); |
1542 | 1547 | ||
1548 | cdata->args.bitmask = server->attr_bitmask; | ||
1549 | cdata->res.server = server; | ||
1543 | nfs_fattr_init(fattr); | 1550 | nfs_fattr_init(fattr); |
1544 | status = rpc_call_sync(server->client, &msg, 0); | 1551 | status = rpc_call_sync(server->client, &msg, 0); |
1545 | dprintk("NFS reply commit: %d\n", status); | 1552 | dprintk("NFS reply commit: %d\n", status); |
1553 | if (status >= 0) | ||
1554 | nfs_post_op_update_inode(inode, fattr); | ||
1546 | return status; | 1555 | return status; |
1547 | } | 1556 | } |
1548 | 1557 | ||
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index a48a003242c0..e1e3ca5d746b 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -375,6 +375,7 @@ nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) | |||
375 | 375 | ||
376 | dprintk("NFS call link %s\n", name->name); | 376 | dprintk("NFS call link %s\n", name->name); |
377 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); | 377 | status = rpc_call(NFS_CLIENT(inode), NFSPROC_LINK, &arg, NULL, 0); |
378 | nfs_mark_for_revalidate(inode); | ||
378 | nfs_mark_for_revalidate(dir); | 379 | nfs_mark_for_revalidate(dir); |
379 | dprintk("NFS reply link: %d\n", status); | 380 | dprintk("NFS reply link: %d\n", status); |
380 | return status; | 381 | return status; |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 8f71e766cc5d..3107908e5f3f 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -189,6 +189,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
189 | (long long)NFS_FILEID(inode), | 189 | (long long)NFS_FILEID(inode), |
190 | count, (long long)(page_offset(page) + offset)); | 190 | count, (long long)(page_offset(page) + offset)); |
191 | 191 | ||
192 | set_page_writeback(page); | ||
192 | nfs_begin_data_update(inode); | 193 | nfs_begin_data_update(inode); |
193 | do { | 194 | do { |
194 | if (count < wsize) | 195 | if (count < wsize) |
@@ -221,6 +222,7 @@ static int nfs_writepage_sync(struct nfs_open_context *ctx, struct inode *inode, | |||
221 | 222 | ||
222 | io_error: | 223 | io_error: |
223 | nfs_end_data_update(inode); | 224 | nfs_end_data_update(inode); |
225 | end_page_writeback(page); | ||
224 | nfs_writedata_free(wdata); | 226 | nfs_writedata_free(wdata); |
225 | return written ? written : result; | 227 | return written ? written : result; |
226 | } | 228 | } |
@@ -929,7 +931,7 @@ static int nfs_flush_multi(struct list_head *head, struct inode *inode, int how) | |||
929 | atomic_set(&req->wb_complete, requests); | 931 | atomic_set(&req->wb_complete, requests); |
930 | 932 | ||
931 | ClearPageError(page); | 933 | ClearPageError(page); |
932 | SetPageWriteback(page); | 934 | set_page_writeback(page); |
933 | offset = 0; | 935 | offset = 0; |
934 | nbytes = req->wb_bytes; | 936 | nbytes = req->wb_bytes; |
935 | do { | 937 | do { |
@@ -992,7 +994,7 @@ static int nfs_flush_one(struct list_head *head, struct inode *inode, int how) | |||
992 | nfs_list_remove_request(req); | 994 | nfs_list_remove_request(req); |
993 | nfs_list_add_request(req, &data->pages); | 995 | nfs_list_add_request(req, &data->pages); |
994 | ClearPageError(req->wb_page); | 996 | ClearPageError(req->wb_page); |
995 | SetPageWriteback(req->wb_page); | 997 | set_page_writeback(req->wb_page); |
996 | *pages++ = req->wb_page; | 998 | *pages++ = req->wb_page; |
997 | count += req->wb_bytes; | 999 | count += req->wb_bytes; |
998 | } | 1000 | } |
diff --git a/mm/memory.c b/mm/memory.c index 4b4fc3a7ea48..aa8af0e20269 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1223,7 +1223,7 @@ int vm_insert_page(struct vm_area_struct *vma, unsigned long addr, struct page * | |||
1223 | return -EINVAL; | 1223 | return -EINVAL; |
1224 | return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot); | 1224 | return insert_page(vma->vm_mm, addr, page, vma->vm_page_prot); |
1225 | } | 1225 | } |
1226 | EXPORT_SYMBOL_GPL(vm_insert_page); | 1226 | EXPORT_SYMBOL(vm_insert_page); |
1227 | 1227 | ||
1228 | /* | 1228 | /* |
1229 | * Somebody does a pfn remapping that doesn't actually work as a vma. | 1229 | * Somebody does a pfn remapping that doesn't actually work as a vma. |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index b257720edfc8..3b21a13d841c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1772,16 +1772,16 @@ static int __devinit zone_batchsize(struct zone *zone) | |||
1772 | batch = 1; | 1772 | batch = 1; |
1773 | 1773 | ||
1774 | /* | 1774 | /* |
1775 | * We will be trying to allcoate bigger chunks of contiguous | 1775 | * Clamp the batch to a 2^n - 1 value. Having a power |
1776 | * memory of the order of fls(batch). This should result in | 1776 | * of 2 value was found to be more likely to have |
1777 | * better cache coloring. | 1777 | * suboptimal cache aliasing properties in some cases. |
1778 | * | 1778 | * |
1779 | * A sanity check also to ensure that batch is still in limits. | 1779 | * For example if 2 tasks are alternately allocating |
1780 | * batches of pages, one task can end up with a lot | ||
1781 | * of pages of one half of the possible page colors | ||
1782 | * and the other with pages of the other colors. | ||
1780 | */ | 1783 | */ |
1781 | batch = (1 << fls(batch + batch/2)); | 1784 | batch = (1 << (fls(batch + batch/2)-1)) - 1; |
1782 | |||
1783 | if (fls(batch) >= (PAGE_SHIFT + MAX_ORDER - 2)) | ||
1784 | batch = PAGE_SHIFT + ((MAX_ORDER - 1 - PAGE_SHIFT)/2); | ||
1785 | 1785 | ||
1786 | return batch; | 1786 | return batch; |
1787 | } | 1787 | } |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index eaa150c33b04..d368cf249000 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -228,13 +228,14 @@ static int inet_create(struct socket *sock, int protocol) | |||
228 | unsigned char answer_flags; | 228 | unsigned char answer_flags; |
229 | char answer_no_check; | 229 | char answer_no_check; |
230 | int try_loading_module = 0; | 230 | int try_loading_module = 0; |
231 | int err = -ESOCKTNOSUPPORT; | 231 | int err; |
232 | 232 | ||
233 | sock->state = SS_UNCONNECTED; | 233 | sock->state = SS_UNCONNECTED; |
234 | 234 | ||
235 | /* Look for the requested type/protocol pair. */ | 235 | /* Look for the requested type/protocol pair. */ |
236 | answer = NULL; | 236 | answer = NULL; |
237 | lookup_protocol: | 237 | lookup_protocol: |
238 | err = -ESOCKTNOSUPPORT; | ||
238 | rcu_read_lock(); | 239 | rcu_read_lock(); |
239 | list_for_each_rcu(p, &inetsw[sock->type]) { | 240 | list_for_each_rcu(p, &inetsw[sock->type]) { |
240 | answer = list_entry(p, struct inet_protosw, list); | 241 | answer = list_entry(p, struct inet_protosw, list); |
@@ -252,6 +253,7 @@ lookup_protocol: | |||
252 | if (IPPROTO_IP == answer->protocol) | 253 | if (IPPROTO_IP == answer->protocol) |
253 | break; | 254 | break; |
254 | } | 255 | } |
256 | err = -EPROTONOSUPPORT; | ||
255 | answer = NULL; | 257 | answer = NULL; |
256 | } | 258 | } |
257 | 259 | ||
@@ -280,9 +282,6 @@ lookup_protocol: | |||
280 | err = -EPERM; | 282 | err = -EPERM; |
281 | if (answer->capability > 0 && !capable(answer->capability)) | 283 | if (answer->capability > 0 && !capable(answer->capability)) |
282 | goto out_rcu_unlock; | 284 | goto out_rcu_unlock; |
283 | err = -EPROTONOSUPPORT; | ||
284 | if (!protocol) | ||
285 | goto out_rcu_unlock; | ||
286 | 285 | ||
287 | sock->ops = answer->ops; | 286 | sock->ops = answer->ops; |
288 | answer_prot = answer->prot; | 287 | answer_prot = answer->prot; |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index c04607b49212..4a195c724f01 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -897,7 +897,10 @@ int igmp_rcv(struct sk_buff *skb) | |||
897 | /* Is it our report looped back? */ | 897 | /* Is it our report looped back? */ |
898 | if (((struct rtable*)skb->dst)->fl.iif == 0) | 898 | if (((struct rtable*)skb->dst)->fl.iif == 0) |
899 | break; | 899 | break; |
900 | igmp_heard_report(in_dev, ih->group); | 900 | /* don't rely on MC router hearing unicast reports */ |
901 | if (skb->pkt_type == PACKET_MULTICAST || | ||
902 | skb->pkt_type == PACKET_BROADCAST) | ||
903 | igmp_heard_report(in_dev, ih->group); | ||
901 | break; | 904 | break; |
902 | case IGMP_PIM: | 905 | case IGMP_PIM: |
903 | #ifdef CONFIG_IP_PIMSM_V1 | 906 | #ifdef CONFIG_IP_PIMSM_V1 |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index c63b8ce0e1b5..d9546380fa04 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -92,10 +92,13 @@ static int inet6_create(struct socket *sock, int protocol) | |||
92 | struct proto *answer_prot; | 92 | struct proto *answer_prot; |
93 | unsigned char answer_flags; | 93 | unsigned char answer_flags; |
94 | char answer_no_check; | 94 | char answer_no_check; |
95 | int rc; | 95 | int try_loading_module = 0; |
96 | int err; | ||
96 | 97 | ||
97 | /* Look for the requested type/protocol pair. */ | 98 | /* Look for the requested type/protocol pair. */ |
98 | answer = NULL; | 99 | answer = NULL; |
100 | lookup_protocol: | ||
101 | err = -ESOCKTNOSUPPORT; | ||
99 | rcu_read_lock(); | 102 | rcu_read_lock(); |
100 | list_for_each_rcu(p, &inetsw6[sock->type]) { | 103 | list_for_each_rcu(p, &inetsw6[sock->type]) { |
101 | answer = list_entry(p, struct inet_protosw, list); | 104 | answer = list_entry(p, struct inet_protosw, list); |
@@ -113,21 +116,37 @@ static int inet6_create(struct socket *sock, int protocol) | |||
113 | if (IPPROTO_IP == answer->protocol) | 116 | if (IPPROTO_IP == answer->protocol) |
114 | break; | 117 | break; |
115 | } | 118 | } |
119 | err = -EPROTONOSUPPORT; | ||
116 | answer = NULL; | 120 | answer = NULL; |
117 | } | 121 | } |
118 | 122 | ||
119 | rc = -ESOCKTNOSUPPORT; | 123 | if (!answer) { |
120 | if (!answer) | 124 | if (try_loading_module < 2) { |
121 | goto out_rcu_unlock; | 125 | rcu_read_unlock(); |
122 | rc = -EPERM; | 126 | /* |
127 | * Be more specific, e.g. net-pf-10-proto-132-type-1 | ||
128 | * (net-pf-PF_INET6-proto-IPPROTO_SCTP-type-SOCK_STREAM) | ||
129 | */ | ||
130 | if (++try_loading_module == 1) | ||
131 | request_module("net-pf-%d-proto-%d-type-%d", | ||
132 | PF_INET6, protocol, sock->type); | ||
133 | /* | ||
134 | * Fall back to generic, e.g. net-pf-10-proto-132 | ||
135 | * (net-pf-PF_INET6-proto-IPPROTO_SCTP) | ||
136 | */ | ||
137 | else | ||
138 | request_module("net-pf-%d-proto-%d", | ||
139 | PF_INET6, protocol); | ||
140 | goto lookup_protocol; | ||
141 | } else | ||
142 | goto out_rcu_unlock; | ||
143 | } | ||
144 | |||
145 | err = -EPERM; | ||
123 | if (answer->capability > 0 && !capable(answer->capability)) | 146 | if (answer->capability > 0 && !capable(answer->capability)) |
124 | goto out_rcu_unlock; | 147 | goto out_rcu_unlock; |
125 | rc = -EPROTONOSUPPORT; | ||
126 | if (!protocol) | ||
127 | goto out_rcu_unlock; | ||
128 | 148 | ||
129 | sock->ops = answer->ops; | 149 | sock->ops = answer->ops; |
130 | |||
131 | answer_prot = answer->prot; | 150 | answer_prot = answer->prot; |
132 | answer_no_check = answer->no_check; | 151 | answer_no_check = answer->no_check; |
133 | answer_flags = answer->flags; | 152 | answer_flags = answer->flags; |
@@ -135,14 +154,14 @@ static int inet6_create(struct socket *sock, int protocol) | |||
135 | 154 | ||
136 | BUG_TRAP(answer_prot->slab != NULL); | 155 | BUG_TRAP(answer_prot->slab != NULL); |
137 | 156 | ||
138 | rc = -ENOBUFS; | 157 | err = -ENOBUFS; |
139 | sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1); | 158 | sk = sk_alloc(PF_INET6, GFP_KERNEL, answer_prot, 1); |
140 | if (sk == NULL) | 159 | if (sk == NULL) |
141 | goto out; | 160 | goto out; |
142 | 161 | ||
143 | sock_init_data(sock, sk); | 162 | sock_init_data(sock, sk); |
144 | 163 | ||
145 | rc = 0; | 164 | err = 0; |
146 | sk->sk_no_check = answer_no_check; | 165 | sk->sk_no_check = answer_no_check; |
147 | if (INET_PROTOSW_REUSE & answer_flags) | 166 | if (INET_PROTOSW_REUSE & answer_flags) |
148 | sk->sk_reuse = 1; | 167 | sk->sk_reuse = 1; |
@@ -202,14 +221,14 @@ static int inet6_create(struct socket *sock, int protocol) | |||
202 | sk->sk_prot->hash(sk); | 221 | sk->sk_prot->hash(sk); |
203 | } | 222 | } |
204 | if (sk->sk_prot->init) { | 223 | if (sk->sk_prot->init) { |
205 | rc = sk->sk_prot->init(sk); | 224 | err = sk->sk_prot->init(sk); |
206 | if (rc) { | 225 | if (err) { |
207 | sk_common_release(sk); | 226 | sk_common_release(sk); |
208 | goto out; | 227 | goto out; |
209 | } | 228 | } |
210 | } | 229 | } |
211 | out: | 230 | out: |
212 | return rc; | 231 | return err; |
213 | out_rcu_unlock: | 232 | out_rcu_unlock: |
214 | rcu_read_unlock(); | 233 | rcu_read_unlock(); |
215 | goto out; | 234 | goto out; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index f15e04ad026e..fd939da090c4 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1231,6 +1231,11 @@ int igmp6_event_report(struct sk_buff *skb) | |||
1231 | if (skb->pkt_type == PACKET_LOOPBACK) | 1231 | if (skb->pkt_type == PACKET_LOOPBACK) |
1232 | return 0; | 1232 | return 0; |
1233 | 1233 | ||
1234 | /* send our report if the MC router may not have heard this report */ | ||
1235 | if (skb->pkt_type != PACKET_MULTICAST && | ||
1236 | skb->pkt_type != PACKET_BROADCAST) | ||
1237 | return 0; | ||
1238 | |||
1234 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) | 1239 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) |
1235 | return -EINVAL; | 1240 | return -EINVAL; |
1236 | 1241 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index abab81f3818f..d890dfa8818f 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -4743,11 +4743,6 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, | |||
4743 | struct sk_buff *skb; | 4743 | struct sk_buff *skb; |
4744 | long timeo; | 4744 | long timeo; |
4745 | 4745 | ||
4746 | /* Caller is allowed not to check sk->sk_err before calling. */ | ||
4747 | error = sock_error(sk); | ||
4748 | if (error) | ||
4749 | goto no_packet; | ||
4750 | |||
4751 | timeo = sock_rcvtimeo(sk, noblock); | 4746 | timeo = sock_rcvtimeo(sk, noblock); |
4752 | 4747 | ||
4753 | SCTP_DEBUG_PRINTK("Timeout: timeo: %ld, MAX: %ld.\n", | 4748 | SCTP_DEBUG_PRINTK("Timeout: timeo: %ld, MAX: %ld.\n", |
@@ -4774,6 +4769,11 @@ static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, | |||
4774 | if (skb) | 4769 | if (skb) |
4775 | return skb; | 4770 | return skb; |
4776 | 4771 | ||
4772 | /* Caller is allowed not to check sk->sk_err before calling. */ | ||
4773 | error = sock_error(sk); | ||
4774 | if (error) | ||
4775 | goto no_packet; | ||
4776 | |||
4777 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 4777 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
4778 | break; | 4778 | break; |
4779 | 4779 | ||
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 6bc27200e6ca..268ddaf2dc0f 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -261,7 +261,8 @@ void sctp_transport_route(struct sctp_transport *transport, | |||
261 | * association's active path for getsockname(). | 261 | * association's active path for getsockname(). |
262 | */ | 262 | */ |
263 | if (asoc && (transport == asoc->peer.active_path)) | 263 | if (asoc && (transport == asoc->peer.active_path)) |
264 | af->to_sk_saddr(&transport->saddr, asoc->base.sk); | 264 | opt->pf->af->to_sk_saddr(&transport->saddr, |
265 | asoc->base.sk); | ||
265 | } else | 266 | } else |
266 | transport->pmtu = SCTP_DEFAULT_MAXSEGMENT; | 267 | transport->pmtu = SCTP_DEFAULT_MAXSEGMENT; |
267 | } | 268 | } |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index e3b242daf53c..c76ea221798c 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -59,7 +59,6 @@ __rpc_purge_upcall(struct inode *inode, int err) | |||
59 | struct rpc_inode *rpci = RPC_I(inode); | 59 | struct rpc_inode *rpci = RPC_I(inode); |
60 | 60 | ||
61 | __rpc_purge_list(rpci, &rpci->pipe, err); | 61 | __rpc_purge_list(rpci, &rpci->pipe, err); |
62 | __rpc_purge_list(rpci, &rpci->in_upcall, err); | ||
63 | rpci->pipelen = 0; | 62 | rpci->pipelen = 0; |
64 | wake_up(&rpci->waitq); | 63 | wake_up(&rpci->waitq); |
65 | } | 64 | } |
@@ -119,6 +118,7 @@ rpc_close_pipes(struct inode *inode) | |||
119 | down(&inode->i_sem); | 118 | down(&inode->i_sem); |
120 | if (rpci->ops != NULL) { | 119 | if (rpci->ops != NULL) { |
121 | rpci->nreaders = 0; | 120 | rpci->nreaders = 0; |
121 | __rpc_purge_list(rpci, &rpci->in_upcall, -EPIPE); | ||
122 | __rpc_purge_upcall(inode, -EPIPE); | 122 | __rpc_purge_upcall(inode, -EPIPE); |
123 | rpci->nwriters = 0; | 123 | rpci->nwriters = 0; |
124 | if (rpci->ops->release_pipe) | 124 | if (rpci->ops->release_pipe) |