diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-20 11:50:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-09-20 11:50:49 -0400 |
commit | 9600c11ba3602be161cd376f1460f3de561fc299 (patch) | |
tree | d071c2427a8f7ad601aec6d8ae76b0f61410becf /drivers/scsi | |
parent | 676d55ae30ea3b688f0386f70553489f25f24d55 (diff) | |
parent | 13e1e1f08c1c098c7574c1fa72bd8c67792dc89b (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-for-linus-2.6
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.c | 9 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm.h | 2 | ||||
-rw-r--r-- | drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 8 | ||||
-rw-r--r-- | drivers/scsi/atp870u.c | 6 | ||||
-rw-r--r-- | drivers/scsi/atp870u.h | 5 | ||||
-rw-r--r-- | drivers/scsi/fd_mcs.c | 2 | ||||
-rw-r--r-- | drivers/scsi/hosts.c | 35 | ||||
-rw-r--r-- | drivers/scsi/ibmmca.c | 2 | ||||
-rw-r--r-- | drivers/scsi/ibmvscsi/ibmvscsi.c | 10 | ||||
-rw-r--r-- | drivers/scsi/scsi.c | 5 | ||||
-rw-r--r-- | drivers/scsi/scsi_devinfo.c | 1 | ||||
-rw-r--r-- | drivers/scsi/scsi_error.c | 78 | ||||
-rw-r--r-- | drivers/scsi/scsi_ioctl.c | 2 | ||||
-rw-r--r-- | drivers/scsi/scsi_lib.c | 12 | ||||
-rw-r--r-- | drivers/scsi/scsi_scan.c | 20 | ||||
-rw-r--r-- | drivers/scsi/scsi_sysfs.c | 17 | ||||
-rw-r--r-- | drivers/scsi/sd.c | 1 | ||||
-rw-r--r-- | drivers/scsi/sg.c | 2 | ||||
-rw-r--r-- | drivers/scsi/sr.c | 1 | ||||
-rw-r--r-- | drivers/scsi/st.c | 1 |
20 files changed, 129 insertions, 90 deletions
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index c932b3b94490..876d1de8480d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c | |||
@@ -1109,15 +1109,6 @@ ahc_linux_register_host(struct ahc_softc *ahc, struct scsi_host_template *templa | |||
1109 | return (0); | 1109 | return (0); |
1110 | } | 1110 | } |
1111 | 1111 | ||
1112 | uint64_t | ||
1113 | ahc_linux_get_memsize(void) | ||
1114 | { | ||
1115 | struct sysinfo si; | ||
1116 | |||
1117 | si_meminfo(&si); | ||
1118 | return ((uint64_t)si.totalram << PAGE_SHIFT); | ||
1119 | } | ||
1120 | |||
1121 | /* | 1112 | /* |
1122 | * Place the SCSI bus into a known state by either resetting it, | 1113 | * Place the SCSI bus into a known state by either resetting it, |
1123 | * or forcing transfer negotiations on the next command to any | 1114 | * or forcing transfer negotiations on the next command to any |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index c52996269240..be9edbe26dbe 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h | |||
@@ -494,8 +494,6 @@ ahc_insb(struct ahc_softc * ahc, long port, uint8_t *array, int count) | |||
494 | int ahc_linux_register_host(struct ahc_softc *, | 494 | int ahc_linux_register_host(struct ahc_softc *, |
495 | struct scsi_host_template *); | 495 | struct scsi_host_template *); |
496 | 496 | ||
497 | uint64_t ahc_linux_get_memsize(void); | ||
498 | |||
499 | /*************************** Pretty Printing **********************************/ | 497 | /*************************** Pretty Printing **********************************/ |
500 | struct info_str { | 498 | struct info_str { |
501 | char *buffer; | 499 | char *buffer; |
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index 0d44a6907dd2..3ce77ddc889e 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | |||
@@ -180,6 +180,7 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
180 | struct ahc_pci_identity *entry; | 180 | struct ahc_pci_identity *entry; |
181 | char *name; | 181 | char *name; |
182 | int error; | 182 | int error; |
183 | struct device *dev = &pdev->dev; | ||
183 | 184 | ||
184 | pci = pdev; | 185 | pci = pdev; |
185 | entry = ahc_find_pci_device(pci); | 186 | entry = ahc_find_pci_device(pci); |
@@ -209,11 +210,12 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
209 | pci_set_master(pdev); | 210 | pci_set_master(pdev); |
210 | 211 | ||
211 | if (sizeof(dma_addr_t) > 4 | 212 | if (sizeof(dma_addr_t) > 4 |
212 | && ahc_linux_get_memsize() > 0x80000000 | 213 | && ahc->features & AHC_LARGE_SCBS |
213 | && pci_set_dma_mask(pdev, mask_39bit) == 0) { | 214 | && dma_set_mask(dev, mask_39bit) == 0 |
215 | && dma_get_required_mask(dev) > DMA_32BIT_MASK) { | ||
214 | ahc->flags |= AHC_39BIT_ADDRESSING; | 216 | ahc->flags |= AHC_39BIT_ADDRESSING; |
215 | } else { | 217 | } else { |
216 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 218 | if (dma_set_mask(dev, DMA_32BIT_MASK)) { |
217 | printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); | 219 | printk(KERN_WARNING "aic7xxx: No suitable DMA available.\n"); |
218 | return (-ENODEV); | 220 | return (-ENODEV); |
219 | } | 221 | } |
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index e6153fe5842a..a8cfbef304b5 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c | |||
@@ -996,6 +996,7 @@ oktosend: | |||
996 | #ifdef ED_DBGP | 996 | #ifdef ED_DBGP |
997 | printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id); | 997 | printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id); |
998 | #endif | 998 | #endif |
999 | dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus; | ||
999 | outl(dev->id[c][target_id].prdaddr, tmpcip); | 1000 | outl(dev->id[c][target_id].prdaddr, tmpcip); |
1000 | tmpcip = tmpcip - 2; | 1001 | tmpcip = tmpcip - 2; |
1001 | outb(0x06, tmpcip); | 1002 | outb(0x06, tmpcip); |
@@ -2572,7 +2573,7 @@ static void atp870u_free_tables(struct Scsi_Host *host) | |||
2572 | for (k = 0; k < 16; k++) { | 2573 | for (k = 0; k < 16; k++) { |
2573 | if (!atp_dev->id[j][k].prd_table) | 2574 | if (!atp_dev->id[j][k].prd_table) |
2574 | continue; | 2575 | continue; |
2575 | pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr); | 2576 | pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prd_bus); |
2576 | atp_dev->id[j][k].prd_table = NULL; | 2577 | atp_dev->id[j][k].prd_table = NULL; |
2577 | } | 2578 | } |
2578 | } | 2579 | } |
@@ -2584,12 +2585,13 @@ static int atp870u_init_tables(struct Scsi_Host *host) | |||
2584 | int c,k; | 2585 | int c,k; |
2585 | for(c=0;c < 2;c++) { | 2586 | for(c=0;c < 2;c++) { |
2586 | for(k=0;k<16;k++) { | 2587 | for(k=0;k<16;k++) { |
2587 | atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr)); | 2588 | atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prd_bus)); |
2588 | if (!atp_dev->id[c][k].prd_table) { | 2589 | if (!atp_dev->id[c][k].prd_table) { |
2589 | printk("atp870u_init_tables fail\n"); | 2590 | printk("atp870u_init_tables fail\n"); |
2590 | atp870u_free_tables(host); | 2591 | atp870u_free_tables(host); |
2591 | return -ENOMEM; | 2592 | return -ENOMEM; |
2592 | } | 2593 | } |
2594 | atp_dev->id[c][k].prdaddr = atp_dev->id[c][k].prd_bus; | ||
2593 | atp_dev->id[c][k].devsp=0x20; | 2595 | atp_dev->id[c][k].devsp=0x20; |
2594 | atp_dev->id[c][k].devtype = 0x7f; | 2596 | atp_dev->id[c][k].devtype = 0x7f; |
2595 | atp_dev->id[c][k].curr_req = NULL; | 2597 | atp_dev->id[c][k].curr_req = NULL; |
diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h index 89f43af39cf2..62bae64a01c1 100644 --- a/drivers/scsi/atp870u.h +++ b/drivers/scsi/atp870u.h | |||
@@ -54,8 +54,9 @@ struct atp_unit | |||
54 | unsigned long tran_len; | 54 | unsigned long tran_len; |
55 | unsigned long last_len; | 55 | unsigned long last_len; |
56 | unsigned char *prd_pos; | 56 | unsigned char *prd_pos; |
57 | unsigned char *prd_table; | 57 | unsigned char *prd_table; /* Kernel address of PRD table */ |
58 | dma_addr_t prdaddr; | 58 | dma_addr_t prd_bus; /* Bus address of PRD */ |
59 | dma_addr_t prdaddr; /* Dynamically updated in driver */ | ||
59 | struct scsi_cmnd *curr_req; | 60 | struct scsi_cmnd *curr_req; |
60 | } id[2][16]; | 61 | } id[2][16]; |
61 | struct Scsi_Host *host; | 62 | struct Scsi_Host *host; |
diff --git a/drivers/scsi/fd_mcs.c b/drivers/scsi/fd_mcs.c index fa652f8aa643..d59d449a9e4d 100644 --- a/drivers/scsi/fd_mcs.c +++ b/drivers/scsi/fd_mcs.c | |||
@@ -1360,3 +1360,5 @@ static Scsi_Host_Template driver_template = { | |||
1360 | .use_clustering = DISABLE_CLUSTERING, | 1360 | .use_clustering = DISABLE_CLUSTERING, |
1361 | }; | 1361 | }; |
1362 | #include "scsi_module.c" | 1362 | #include "scsi_module.c" |
1363 | |||
1364 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 85503fad789a..f2a72d33132c 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c | |||
@@ -98,6 +98,7 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) | |||
98 | switch (oldstate) { | 98 | switch (oldstate) { |
99 | case SHOST_CREATED: | 99 | case SHOST_CREATED: |
100 | case SHOST_RUNNING: | 100 | case SHOST_RUNNING: |
101 | case SHOST_CANCEL_RECOVERY: | ||
101 | break; | 102 | break; |
102 | default: | 103 | default: |
103 | goto illegal; | 104 | goto illegal; |
@@ -107,12 +108,31 @@ int scsi_host_set_state(struct Scsi_Host *shost, enum scsi_host_state state) | |||
107 | case SHOST_DEL: | 108 | case SHOST_DEL: |
108 | switch (oldstate) { | 109 | switch (oldstate) { |
109 | case SHOST_CANCEL: | 110 | case SHOST_CANCEL: |
111 | case SHOST_DEL_RECOVERY: | ||
110 | break; | 112 | break; |
111 | default: | 113 | default: |
112 | goto illegal; | 114 | goto illegal; |
113 | } | 115 | } |
114 | break; | 116 | break; |
115 | 117 | ||
118 | case SHOST_CANCEL_RECOVERY: | ||
119 | switch (oldstate) { | ||
120 | case SHOST_CANCEL: | ||
121 | case SHOST_RECOVERY: | ||
122 | break; | ||
123 | default: | ||
124 | goto illegal; | ||
125 | } | ||
126 | break; | ||
127 | |||
128 | case SHOST_DEL_RECOVERY: | ||
129 | switch (oldstate) { | ||
130 | case SHOST_CANCEL_RECOVERY: | ||
131 | break; | ||
132 | default: | ||
133 | goto illegal; | ||
134 | } | ||
135 | break; | ||
116 | } | 136 | } |
117 | shost->shost_state = state; | 137 | shost->shost_state = state; |
118 | return 0; | 138 | return 0; |
@@ -134,13 +154,24 @@ EXPORT_SYMBOL(scsi_host_set_state); | |||
134 | **/ | 154 | **/ |
135 | void scsi_remove_host(struct Scsi_Host *shost) | 155 | void scsi_remove_host(struct Scsi_Host *shost) |
136 | { | 156 | { |
157 | unsigned long flags; | ||
137 | down(&shost->scan_mutex); | 158 | down(&shost->scan_mutex); |
138 | scsi_host_set_state(shost, SHOST_CANCEL); | 159 | spin_lock_irqsave(shost->host_lock, flags); |
160 | if (scsi_host_set_state(shost, SHOST_CANCEL)) | ||
161 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) { | ||
162 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
163 | up(&shost->scan_mutex); | ||
164 | return; | ||
165 | } | ||
166 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
139 | up(&shost->scan_mutex); | 167 | up(&shost->scan_mutex); |
140 | scsi_forget_host(shost); | 168 | scsi_forget_host(shost); |
141 | scsi_proc_host_rm(shost); | 169 | scsi_proc_host_rm(shost); |
142 | 170 | ||
143 | scsi_host_set_state(shost, SHOST_DEL); | 171 | spin_lock_irqsave(shost->host_lock, flags); |
172 | if (scsi_host_set_state(shost, SHOST_DEL)) | ||
173 | BUG_ON(scsi_host_set_state(shost, SHOST_DEL_RECOVERY)); | ||
174 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
144 | 175 | ||
145 | transport_unregister_device(&shost->shost_gendev); | 176 | transport_unregister_device(&shost->shost_gendev); |
146 | class_device_unregister(&shost->shost_classdev); | 177 | class_device_unregister(&shost->shost_classdev); |
diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 6e54c7d9b33c..19392f651272 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c | |||
@@ -460,6 +460,8 @@ MODULE_PARM(adisplay, "1i"); | |||
460 | MODULE_PARM(normal, "1i"); | 460 | MODULE_PARM(normal, "1i"); |
461 | MODULE_PARM(ansi, "1i"); | 461 | MODULE_PARM(ansi, "1i"); |
462 | #endif | 462 | #endif |
463 | |||
464 | MODULE_LICENSE("GPL"); | ||
463 | #endif | 465 | #endif |
464 | /*counter of concurrent disk read/writes, to turn on/off disk led */ | 466 | /*counter of concurrent disk read/writes, to turn on/off disk led */ |
465 | static int disk_rw_in_progress = 0; | 467 | static int disk_rw_in_progress = 0; |
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5b14934ba861..ff25210b00ba 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c | |||
@@ -727,6 +727,16 @@ static void adapter_info_rsp(struct srp_event_struct *evt_struct) | |||
727 | if (hostdata->madapter_info.port_max_txu[0]) | 727 | if (hostdata->madapter_info.port_max_txu[0]) |
728 | hostdata->host->max_sectors = | 728 | hostdata->host->max_sectors = |
729 | hostdata->madapter_info.port_max_txu[0] >> 9; | 729 | hostdata->madapter_info.port_max_txu[0] >> 9; |
730 | |||
731 | if (hostdata->madapter_info.os_type == 3 && | ||
732 | strcmp(hostdata->madapter_info.srp_version, "1.6a") <= 0) { | ||
733 | printk("ibmvscsi: host (Ver. %s) doesn't support large" | ||
734 | "transfers\n", | ||
735 | hostdata->madapter_info.srp_version); | ||
736 | printk("ibmvscsi: limiting scatterlists to %d\n", | ||
737 | MAX_INDIRECT_BUFS); | ||
738 | hostdata->host->sg_tablesize = MAX_INDIRECT_BUFS; | ||
739 | } | ||
730 | } | 740 | } |
731 | } | 741 | } |
732 | 742 | ||
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a780546eda9c..1f0ebabf6d47 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -1265,9 +1265,8 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) | |||
1265 | list_for_each_safe(lh, lh_sf, &active_list) { | 1265 | list_for_each_safe(lh, lh_sf, &active_list) { |
1266 | scmd = list_entry(lh, struct scsi_cmnd, eh_entry); | 1266 | scmd = list_entry(lh, struct scsi_cmnd, eh_entry); |
1267 | list_del_init(lh); | 1267 | list_del_init(lh); |
1268 | if (recovery) { | 1268 | if (recovery && |
1269 | scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD); | 1269 | !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD)) { |
1270 | } else { | ||
1271 | scmd->result = (DID_ABORT << 16); | 1270 | scmd->result = (DID_ABORT << 16); |
1272 | scsi_finish_command(scmd); | 1271 | scsi_finish_command(scmd); |
1273 | } | 1272 | } |
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 07b554affcf2..64fc9e21f35b 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c | |||
@@ -110,6 +110,7 @@ static struct { | |||
110 | {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ | 110 | {"RELISYS", "Scorpio", NULL, BLIST_NOLUN}, /* responds to all lun */ |
111 | {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ | 111 | {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */ |
112 | {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, | 112 | {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, |
113 | {"transtec", "T5008", "0001", BLIST_NOREPORTLUN }, | ||
113 | {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ | 114 | {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* locks up */ |
114 | {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ | 115 | {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* locks up */ |
115 | {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ | 116 | {"YAMAHA", "CRW8424S", "1.0", BLIST_NOLUN}, /* locks up */ |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 895c9452be4c..ad5342165079 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
@@ -50,7 +50,7 @@ | |||
50 | void scsi_eh_wakeup(struct Scsi_Host *shost) | 50 | void scsi_eh_wakeup(struct Scsi_Host *shost) |
51 | { | 51 | { |
52 | if (shost->host_busy == shost->host_failed) { | 52 | if (shost->host_busy == shost->host_failed) { |
53 | up(shost->eh_wait); | 53 | wake_up_process(shost->ehandler); |
54 | SCSI_LOG_ERROR_RECOVERY(5, | 54 | SCSI_LOG_ERROR_RECOVERY(5, |
55 | printk("Waking error handler thread\n")); | 55 | printk("Waking error handler thread\n")); |
56 | } | 56 | } |
@@ -68,19 +68,24 @@ int scsi_eh_scmd_add(struct scsi_cmnd *scmd, int eh_flag) | |||
68 | { | 68 | { |
69 | struct Scsi_Host *shost = scmd->device->host; | 69 | struct Scsi_Host *shost = scmd->device->host; |
70 | unsigned long flags; | 70 | unsigned long flags; |
71 | int ret = 0; | ||
71 | 72 | ||
72 | if (shost->eh_wait == NULL) | 73 | if (!shost->ehandler) |
73 | return 0; | 74 | return 0; |
74 | 75 | ||
75 | spin_lock_irqsave(shost->host_lock, flags); | 76 | spin_lock_irqsave(shost->host_lock, flags); |
77 | if (scsi_host_set_state(shost, SHOST_RECOVERY)) | ||
78 | if (scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)) | ||
79 | goto out_unlock; | ||
76 | 80 | ||
81 | ret = 1; | ||
77 | scmd->eh_eflags |= eh_flag; | 82 | scmd->eh_eflags |= eh_flag; |
78 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); | 83 | list_add_tail(&scmd->eh_entry, &shost->eh_cmd_q); |
79 | scsi_host_set_state(shost, SHOST_RECOVERY); | ||
80 | shost->host_failed++; | 84 | shost->host_failed++; |
81 | scsi_eh_wakeup(shost); | 85 | scsi_eh_wakeup(shost); |
86 | out_unlock: | ||
82 | spin_unlock_irqrestore(shost->host_lock, flags); | 87 | spin_unlock_irqrestore(shost->host_lock, flags); |
83 | return 1; | 88 | return ret; |
84 | } | 89 | } |
85 | 90 | ||
86 | /** | 91 | /** |
@@ -176,8 +181,8 @@ void scsi_times_out(struct scsi_cmnd *scmd) | |||
176 | } | 181 | } |
177 | 182 | ||
178 | if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { | 183 | if (unlikely(!scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) { |
179 | panic("Error handler thread not present at %p %p %s %d", | 184 | scmd->result |= DID_TIME_OUT << 16; |
180 | scmd, scmd->device->host, __FILE__, __LINE__); | 185 | __scsi_done(scmd); |
181 | } | 186 | } |
182 | } | 187 | } |
183 | 188 | ||
@@ -196,8 +201,7 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) | |||
196 | { | 201 | { |
197 | int online; | 202 | int online; |
198 | 203 | ||
199 | wait_event(sdev->host->host_wait, (sdev->host->shost_state != | 204 | wait_event(sdev->host->host_wait, !scsi_host_in_recovery(sdev->host)); |
200 | SHOST_RECOVERY)); | ||
201 | 205 | ||
202 | online = scsi_device_online(sdev); | 206 | online = scsi_device_online(sdev); |
203 | 207 | ||
@@ -1441,6 +1445,7 @@ static void scsi_eh_lock_door(struct scsi_device *sdev) | |||
1441 | static void scsi_restart_operations(struct Scsi_Host *shost) | 1445 | static void scsi_restart_operations(struct Scsi_Host *shost) |
1442 | { | 1446 | { |
1443 | struct scsi_device *sdev; | 1447 | struct scsi_device *sdev; |
1448 | unsigned long flags; | ||
1444 | 1449 | ||
1445 | /* | 1450 | /* |
1446 | * If the door was locked, we need to insert a door lock request | 1451 | * If the door was locked, we need to insert a door lock request |
@@ -1460,7 +1465,11 @@ static void scsi_restart_operations(struct Scsi_Host *shost) | |||
1460 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", | 1465 | SCSI_LOG_ERROR_RECOVERY(3, printk("%s: waking up host to restart\n", |
1461 | __FUNCTION__)); | 1466 | __FUNCTION__)); |
1462 | 1467 | ||
1463 | scsi_host_set_state(shost, SHOST_RUNNING); | 1468 | spin_lock_irqsave(shost->host_lock, flags); |
1469 | if (scsi_host_set_state(shost, SHOST_RUNNING)) | ||
1470 | if (scsi_host_set_state(shost, SHOST_CANCEL)) | ||
1471 | BUG_ON(scsi_host_set_state(shost, SHOST_DEL)); | ||
1472 | spin_unlock_irqrestore(shost->host_lock, flags); | ||
1464 | 1473 | ||
1465 | wake_up(&shost->host_wait); | 1474 | wake_up(&shost->host_wait); |
1466 | 1475 | ||
@@ -1582,40 +1591,31 @@ int scsi_error_handler(void *data) | |||
1582 | { | 1591 | { |
1583 | struct Scsi_Host *shost = (struct Scsi_Host *) data; | 1592 | struct Scsi_Host *shost = (struct Scsi_Host *) data; |
1584 | int rtn; | 1593 | int rtn; |
1585 | DECLARE_MUTEX_LOCKED(sem); | ||
1586 | 1594 | ||
1587 | current->flags |= PF_NOFREEZE; | 1595 | current->flags |= PF_NOFREEZE; |
1588 | shost->eh_wait = &sem; | ||
1589 | 1596 | ||
1597 | |||
1590 | /* | 1598 | /* |
1591 | * Wake up the thread that created us. | 1599 | * Note - we always use TASK_INTERRUPTIBLE even if the module |
1600 | * was loaded as part of the kernel. The reason is that | ||
1601 | * UNINTERRUPTIBLE would cause this thread to be counted in | ||
1602 | * the load average as a running process, and an interruptible | ||
1603 | * wait doesn't. | ||
1592 | */ | 1604 | */ |
1593 | SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent of" | 1605 | set_current_state(TASK_INTERRUPTIBLE); |
1594 | " scsi_eh_%d\n",shost->host_no)); | 1606 | while (!kthread_should_stop()) { |
1595 | 1607 | if (shost->host_failed == 0 || | |
1596 | while (1) { | 1608 | shost->host_failed != shost->host_busy) { |
1597 | /* | 1609 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
1598 | * If we get a signal, it means we are supposed to go | 1610 | " scsi_eh_%d" |
1599 | * away and die. This typically happens if the user is | 1611 | " sleeping\n", |
1600 | * trying to unload a module. | 1612 | shost->host_no)); |
1601 | */ | 1613 | schedule(); |
1602 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1614 | set_current_state(TASK_INTERRUPTIBLE); |
1603 | " scsi_eh_%d" | 1615 | continue; |
1604 | " sleeping\n",shost->host_no)); | 1616 | } |
1605 | |||
1606 | /* | ||
1607 | * Note - we always use down_interruptible with the semaphore | ||
1608 | * even if the module was loaded as part of the kernel. The | ||
1609 | * reason is that down() will cause this thread to be counted | ||
1610 | * in the load average as a running process, and down | ||
1611 | * interruptible doesn't. Given that we need to allow this | ||
1612 | * thread to die if the driver was loaded as a module, using | ||
1613 | * semaphores isn't unreasonable. | ||
1614 | */ | ||
1615 | down_interruptible(&sem); | ||
1616 | if (kthread_should_stop()) | ||
1617 | break; | ||
1618 | 1617 | ||
1618 | __set_current_state(TASK_RUNNING); | ||
1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" | 1619 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler" |
1620 | " scsi_eh_%d waking" | 1620 | " scsi_eh_%d waking" |
1621 | " up\n",shost->host_no)); | 1621 | " up\n",shost->host_no)); |
@@ -1642,7 +1642,7 @@ int scsi_error_handler(void *data) | |||
1642 | * which are still online. | 1642 | * which are still online. |
1643 | */ | 1643 | */ |
1644 | scsi_restart_operations(shost); | 1644 | scsi_restart_operations(shost); |
1645 | 1645 | set_current_state(TASK_INTERRUPTIBLE); | |
1646 | } | 1646 | } |
1647 | 1647 | ||
1648 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" | 1648 | SCSI_LOG_ERROR_RECOVERY(1, printk("Error handler scsi_eh_%d" |
@@ -1651,7 +1651,7 @@ int scsi_error_handler(void *data) | |||
1651 | /* | 1651 | /* |
1652 | * Make sure that nobody tries to wake us up again. | 1652 | * Make sure that nobody tries to wake us up again. |
1653 | */ | 1653 | */ |
1654 | shost->eh_wait = NULL; | 1654 | shost->ehandler = NULL; |
1655 | return 0; | 1655 | return 0; |
1656 | } | 1656 | } |
1657 | 1657 | ||
diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index b7fddac81347..de7f98cc38fe 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c | |||
@@ -458,7 +458,7 @@ int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd, | |||
458 | * error processing, as long as the device was opened | 458 | * error processing, as long as the device was opened |
459 | * non-blocking */ | 459 | * non-blocking */ |
460 | if (filp && filp->f_flags & O_NONBLOCK) { | 460 | if (filp && filp->f_flags & O_NONBLOCK) { |
461 | if (sdev->host->shost_state == SHOST_RECOVERY) | 461 | if (scsi_host_in_recovery(sdev->host)) |
462 | return -ENODEV; | 462 | return -ENODEV; |
463 | } else if (!scsi_block_when_processing_errors(sdev)) | 463 | } else if (!scsi_block_when_processing_errors(sdev)) |
464 | return -ENODEV; | 464 | return -ENODEV; |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 863bb6495daa..dc9c772bc874 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -118,7 +118,6 @@ static void scsi_unprep_request(struct request *req) | |||
118 | req->flags &= ~REQ_DONTPREP; | 118 | req->flags &= ~REQ_DONTPREP; |
119 | req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; | 119 | req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL; |
120 | 120 | ||
121 | scsi_release_buffers(cmd); | ||
122 | scsi_put_command(cmd); | 121 | scsi_put_command(cmd); |
123 | } | 122 | } |
124 | 123 | ||
@@ -140,14 +139,12 @@ static void scsi_unprep_request(struct request *req) | |||
140 | * commands. | 139 | * commands. |
141 | * Notes: This could be called either from an interrupt context or a | 140 | * Notes: This could be called either from an interrupt context or a |
142 | * normal process context. | 141 | * normal process context. |
143 | * Notes: Upon return, cmd is a stale pointer. | ||
144 | */ | 142 | */ |
145 | int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | 143 | int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) |
146 | { | 144 | { |
147 | struct Scsi_Host *host = cmd->device->host; | 145 | struct Scsi_Host *host = cmd->device->host; |
148 | struct scsi_device *device = cmd->device; | 146 | struct scsi_device *device = cmd->device; |
149 | struct request_queue *q = device->request_queue; | 147 | struct request_queue *q = device->request_queue; |
150 | struct request *req = cmd->request; | ||
151 | unsigned long flags; | 148 | unsigned long flags; |
152 | 149 | ||
153 | SCSI_LOG_MLQUEUE(1, | 150 | SCSI_LOG_MLQUEUE(1, |
@@ -188,9 +185,8 @@ int scsi_queue_insert(struct scsi_cmnd *cmd, int reason) | |||
188 | * function. The SCSI request function detects the blocked condition | 185 | * function. The SCSI request function detects the blocked condition |
189 | * and plugs the queue appropriately. | 186 | * and plugs the queue appropriately. |
190 | */ | 187 | */ |
191 | scsi_unprep_request(req); | ||
192 | spin_lock_irqsave(q->queue_lock, flags); | 188 | spin_lock_irqsave(q->queue_lock, flags); |
193 | blk_requeue_request(q, req); | 189 | blk_requeue_request(q, cmd->request); |
194 | spin_unlock_irqrestore(q->queue_lock, flags); | 190 | spin_unlock_irqrestore(q->queue_lock, flags); |
195 | 191 | ||
196 | scsi_run_queue(q); | 192 | scsi_run_queue(q); |
@@ -451,7 +447,7 @@ void scsi_device_unbusy(struct scsi_device *sdev) | |||
451 | 447 | ||
452 | spin_lock_irqsave(shost->host_lock, flags); | 448 | spin_lock_irqsave(shost->host_lock, flags); |
453 | shost->host_busy--; | 449 | shost->host_busy--; |
454 | if (unlikely((shost->shost_state == SHOST_RECOVERY) && | 450 | if (unlikely(scsi_host_in_recovery(shost) && |
455 | shost->host_failed)) | 451 | shost->host_failed)) |
456 | scsi_eh_wakeup(shost); | 452 | scsi_eh_wakeup(shost); |
457 | spin_unlock(shost->host_lock); | 453 | spin_unlock(shost->host_lock); |
@@ -1268,6 +1264,7 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) | |||
1268 | } | 1264 | } |
1269 | } else { | 1265 | } else { |
1270 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); | 1266 | memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd)); |
1267 | cmd->cmd_len = req->cmd_len; | ||
1271 | if (rq_data_dir(req) == WRITE) | 1268 | if (rq_data_dir(req) == WRITE) |
1272 | cmd->sc_data_direction = DMA_TO_DEVICE; | 1269 | cmd->sc_data_direction = DMA_TO_DEVICE; |
1273 | else if (req->data_len) | 1270 | else if (req->data_len) |
@@ -1342,7 +1339,7 @@ static inline int scsi_host_queue_ready(struct request_queue *q, | |||
1342 | struct Scsi_Host *shost, | 1339 | struct Scsi_Host *shost, |
1343 | struct scsi_device *sdev) | 1340 | struct scsi_device *sdev) |
1344 | { | 1341 | { |
1345 | if (shost->shost_state == SHOST_RECOVERY) | 1342 | if (scsi_host_in_recovery(shost)) |
1346 | return 0; | 1343 | return 0; |
1347 | if (shost->host_busy == 0 && shost->host_blocked) { | 1344 | if (shost->host_busy == 0 && shost->host_blocked) { |
1348 | /* | 1345 | /* |
@@ -1514,7 +1511,6 @@ static void scsi_request_fn(struct request_queue *q) | |||
1514 | * cases (host limits or settings) should run the queue at some | 1511 | * cases (host limits or settings) should run the queue at some |
1515 | * later time. | 1512 | * later time. |
1516 | */ | 1513 | */ |
1517 | scsi_unprep_request(req); | ||
1518 | spin_lock_irq(q->queue_lock); | 1514 | spin_lock_irq(q->queue_lock); |
1519 | blk_requeue_request(q, req); | 1515 | blk_requeue_request(q, req); |
1520 | sdev->device_busy--; | 1516 | sdev->device_busy--; |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index b86f170fa8ed..fcf9f6cbb142 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -1466,23 +1466,17 @@ EXPORT_SYMBOL(scsi_scan_single_target); | |||
1466 | 1466 | ||
1467 | void scsi_forget_host(struct Scsi_Host *shost) | 1467 | void scsi_forget_host(struct Scsi_Host *shost) |
1468 | { | 1468 | { |
1469 | struct scsi_target *starget, *tmp; | 1469 | struct scsi_device *sdev; |
1470 | unsigned long flags; | 1470 | unsigned long flags; |
1471 | 1471 | ||
1472 | /* | 1472 | restart: |
1473 | * Ok, this look a bit strange. We always look for the first device | ||
1474 | * on the list as scsi_remove_device removes them from it - thus we | ||
1475 | * also have to release the lock. | ||
1476 | * We don't need to get another reference to the device before | ||
1477 | * releasing the lock as we already own the reference from | ||
1478 | * scsi_register_device that's release in scsi_remove_device. And | ||
1479 | * after that we don't look at sdev anymore. | ||
1480 | */ | ||
1481 | spin_lock_irqsave(shost->host_lock, flags); | 1473 | spin_lock_irqsave(shost->host_lock, flags); |
1482 | list_for_each_entry_safe(starget, tmp, &shost->__targets, siblings) { | 1474 | list_for_each_entry(sdev, &shost->__devices, siblings) { |
1475 | if (sdev->sdev_state == SDEV_DEL) | ||
1476 | continue; | ||
1483 | spin_unlock_irqrestore(shost->host_lock, flags); | 1477 | spin_unlock_irqrestore(shost->host_lock, flags); |
1484 | scsi_remove_target(&starget->dev); | 1478 | __scsi_remove_device(sdev); |
1485 | spin_lock_irqsave(shost->host_lock, flags); | 1479 | goto restart; |
1486 | } | 1480 | } |
1487 | spin_unlock_irqrestore(shost->host_lock, flags); | 1481 | spin_unlock_irqrestore(shost->host_lock, flags); |
1488 | } | 1482 | } |
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index b8052d5206cc..72a6550a056c 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c | |||
@@ -57,6 +57,8 @@ static struct { | |||
57 | { SHOST_CANCEL, "cancel" }, | 57 | { SHOST_CANCEL, "cancel" }, |
58 | { SHOST_DEL, "deleted" }, | 58 | { SHOST_DEL, "deleted" }, |
59 | { SHOST_RECOVERY, "recovery" }, | 59 | { SHOST_RECOVERY, "recovery" }, |
60 | { SHOST_CANCEL_RECOVERY, "cancel/recovery" }, | ||
61 | { SHOST_DEL_RECOVERY, "deleted/recovery", }, | ||
60 | }; | 62 | }; |
61 | const char *scsi_host_state_name(enum scsi_host_state state) | 63 | const char *scsi_host_state_name(enum scsi_host_state state) |
62 | { | 64 | { |
@@ -707,9 +709,11 @@ void __scsi_remove_device(struct scsi_device *sdev) | |||
707 | **/ | 709 | **/ |
708 | void scsi_remove_device(struct scsi_device *sdev) | 710 | void scsi_remove_device(struct scsi_device *sdev) |
709 | { | 711 | { |
710 | down(&sdev->host->scan_mutex); | 712 | struct Scsi_Host *shost = sdev->host; |
713 | |||
714 | down(&shost->scan_mutex); | ||
711 | __scsi_remove_device(sdev); | 715 | __scsi_remove_device(sdev); |
712 | up(&sdev->host->scan_mutex); | 716 | up(&shost->scan_mutex); |
713 | } | 717 | } |
714 | EXPORT_SYMBOL(scsi_remove_device); | 718 | EXPORT_SYMBOL(scsi_remove_device); |
715 | 719 | ||
@@ -717,17 +721,20 @@ void __scsi_remove_target(struct scsi_target *starget) | |||
717 | { | 721 | { |
718 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 722 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
719 | unsigned long flags; | 723 | unsigned long flags; |
720 | struct scsi_device *sdev, *tmp; | 724 | struct scsi_device *sdev; |
721 | 725 | ||
722 | spin_lock_irqsave(shost->host_lock, flags); | 726 | spin_lock_irqsave(shost->host_lock, flags); |
723 | starget->reap_ref++; | 727 | starget->reap_ref++; |
724 | list_for_each_entry_safe(sdev, tmp, &shost->__devices, siblings) { | 728 | restart: |
729 | list_for_each_entry(sdev, &shost->__devices, siblings) { | ||
725 | if (sdev->channel != starget->channel || | 730 | if (sdev->channel != starget->channel || |
726 | sdev->id != starget->id) | 731 | sdev->id != starget->id || |
732 | sdev->sdev_state == SDEV_DEL) | ||
727 | continue; | 733 | continue; |
728 | spin_unlock_irqrestore(shost->host_lock, flags); | 734 | spin_unlock_irqrestore(shost->host_lock, flags); |
729 | scsi_remove_device(sdev); | 735 | scsi_remove_device(sdev); |
730 | spin_lock_irqsave(shost->host_lock, flags); | 736 | spin_lock_irqsave(shost->host_lock, flags); |
737 | goto restart; | ||
731 | } | 738 | } |
732 | spin_unlock_irqrestore(shost->host_lock, flags); | 739 | spin_unlock_irqrestore(shost->host_lock, flags); |
733 | scsi_target_reap(starget); | 740 | scsi_target_reap(starget); |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index de564b386052..9a1dc0cea03c 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -235,6 +235,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) | |||
235 | return 0; | 235 | return 0; |
236 | 236 | ||
237 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); | 237 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); |
238 | SCpnt->cmd_len = rq->cmd_len; | ||
238 | if (rq_data_dir(rq) == WRITE) | 239 | if (rq_data_dir(rq) == WRITE) |
239 | SCpnt->sc_data_direction = DMA_TO_DEVICE; | 240 | SCpnt->sc_data_direction = DMA_TO_DEVICE; |
240 | else if (rq->data_len) | 241 | else if (rq->data_len) |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9ea4765d1d12..4d09a6e4dd2e 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1027,7 +1027,7 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
1027 | if (sdp->detached) | 1027 | if (sdp->detached) |
1028 | return -ENODEV; | 1028 | return -ENODEV; |
1029 | if (filp->f_flags & O_NONBLOCK) { | 1029 | if (filp->f_flags & O_NONBLOCK) { |
1030 | if (sdp->device->host->shost_state == SHOST_RECOVERY) | 1030 | if (scsi_host_in_recovery(sdp->device->host)) |
1031 | return -EBUSY; | 1031 | return -EBUSY; |
1032 | } else if (!scsi_block_when_processing_errors(sdp->device)) | 1032 | } else if (!scsi_block_when_processing_errors(sdp->device)) |
1033 | return -EBUSY; | 1033 | return -EBUSY; |
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index ce63fc8312dc..561901b1cf11 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
@@ -326,6 +326,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) | |||
326 | return 0; | 326 | return 0; |
327 | 327 | ||
328 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); | 328 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); |
329 | SCpnt->cmd_len = rq->cmd_len; | ||
329 | if (!rq->data_len) | 330 | if (!rq->data_len) |
330 | SCpnt->sc_data_direction = DMA_NONE; | 331 | SCpnt->sc_data_direction = DMA_NONE; |
331 | else if (rq_data_dir(rq) == WRITE) | 332 | else if (rq_data_dir(rq) == WRITE) |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a93308ae9736..d001c046551b 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -4206,6 +4206,7 @@ static int st_init_command(struct scsi_cmnd *SCpnt) | |||
4206 | return 0; | 4206 | return 0; |
4207 | 4207 | ||
4208 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); | 4208 | memcpy(SCpnt->cmnd, rq->cmd, sizeof(SCpnt->cmnd)); |
4209 | SCpnt->cmd_len = rq->cmd_len; | ||
4209 | 4210 | ||
4210 | if (rq_data_dir(rq) == WRITE) | 4211 | if (rq_data_dir(rq) == WRITE) |
4211 | SCpnt->sc_data_direction = DMA_TO_DEVICE; | 4212 | SCpnt->sc_data_direction = DMA_TO_DEVICE; |