Manual merge for trivial #include changes
Unified · Split
| @@ -26,6 +26,8 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/slab.h> |
| 27 | 27 | #include <linux/swap.h> |
| 28 | 28 | #include <linux/writeback.h> |
| 29 | +#include <linux/interrupt.h> | |
| 30 | +#include <linux/cpu.h> | |
| 29 | 31 | |
| 30 | 32 | /* |
| 31 | 33 | * for max sense size |
| @@ -61,13 +63,15 @@ static wait_queue_head_t congestion_wqh[2] = { · 29 unmodified lines | ||
| 61 | 63 | /* |
| 62 | 64 | * Controlling structure to kblockd |
| 63 | 65 | */ |
| 64 | −static struct workqueue_struct *kblockd_workqueue; | |
| 66 | +static struct workqueue_struct *kblockd_workqueue; | |
| 65 | 67 | |
| 66 | 68 | unsigned long blk_max_low_pfn, blk_max_pfn; |
| 67 | 69 | |
| 68 | 70 | EXPORT_SYMBOL(blk_max_low_pfn); |
| 69 | 71 | EXPORT_SYMBOL(blk_max_pfn); |
| 70 | 72 | |
| 73 | +static DEFINE_PER_CPU(struct list_head, blk_cpu_done); | |
| 74 | + | |
| 71 | 75 | /* Amount of time in which a process may batch requests */ |
| 72 | 76 | #define BLK_BATCH_TIME (HZ/50UL) |
| 73 | 77 | |
| @@ -206,6 +210,13 @@ void blk_queue_merge_bvec(request_queue_t *q, merge_bvec_fn *mbfn) · 132 unmodified lines | ||
| 206 | 210 | |
| 207 | 211 | EXPORT_SYMBOL(blk_queue_merge_bvec); |
| 208 | 212 | |
| 213 | +void blk_queue_softirq_done(request_queue_t *q, softirq_done_fn *fn) | |
| 214 | +{ | |
| 215 | + q->softirq_done_fn = fn; | |
| 216 | +} | |
| 217 | + | |
| 218 | +EXPORT_SYMBOL(blk_queue_softirq_done); | |
| 219 | + | |
| 209 | 220 | /** |
| 210 | 221 | * blk_queue_make_request - define an alternate make_request function for a device |
| 211 | 222 | * @q: the request queue for the device to be affected |
| @@ -269,6 +280,7 @@ EXPORT_SYMBOL(blk_queue_make_request); · 57 unmodified lines | ||
| 269 | 280 | static inline void rq_init(request_queue_t *q, struct request *rq) |
| 270 | 281 | { |
| 271 | 282 | INIT_LIST_HEAD(&rq->queuelist); |
| 283 | + INIT_LIST_HEAD(&rq->donelist); | |
| 272 | 284 | |
| 273 | 285 | rq->errors = 0; |
| 274 | 286 | rq->rq_status = RQ_ACTIVE; |
| @@ -285,6 +297,7 @@ static inline void rq_init(request_queue_t *q, struct request *rq) · 10 unmodified lines | ||
| 285 | 297 | rq->sense = NULL; |
| 286 | 298 | rq->end_io = NULL; |
| 287 | 299 | rq->end_io_data = NULL; |
| 300 | + rq->completion_data = NULL; | |
| 288 | 301 | } |
| 289 | 302 | |
| 290 | 303 | /** |
| @@ -3261,6 +3274,87 @@ int end_that_request_chunk(struct request *req, int uptodate, int nr_bytes) · 2970 unmodified lines | ||
| 3261 | 3274 | |
| 3262 | 3275 | EXPORT_SYMBOL(end_that_request_chunk); |
| 3263 | 3276 | |
| 3277 | +/* | |
| 3278 | + * splice the completion data to a local structure and hand off to | |
| 3279 | + * process_completion_queue() to complete the requests | |
| 3280 | + */ | |
| 3281 | +static void blk_done_softirq(struct softirq_action *h) | |
| 3282 | +{ | |
| 3283 | + struct list_head *cpu_list; | |
| 3284 | + LIST_HEAD(local_list); | |
| 3285 | + | |
| 3286 | + local_irq_disable(); | |
| 3287 | + cpu_list = &__get_cpu_var(blk_cpu_done); | |
| 3288 | + list_splice_init(cpu_list, &local_list); | |
| 3289 | + local_irq_enable(); | |
| 3290 | + | |
| 3291 | + while (!list_empty(&local_list)) { | |
| 3292 | + struct request *rq = list_entry(local_list.next, struct request, donelist); | |
| 3293 | + | |
| 3294 | + list_del_init(&rq->donelist); | |
| 3295 | + rq->q->softirq_done_fn(rq); | |
| 3296 | + } | |
| 3297 | +} | |
| 3298 | + | |
| 3299 | +#ifdef CONFIG_HOTPLUG_CPU | |
| 3300 | + | |
| 3301 | +static int blk_cpu_notify(struct notifier_block *self, unsigned long action, | |
| 3302 | + void *hcpu) | |
| 3303 | +{ | |
| 3304 | + /* | |
| 3305 | + * If a CPU goes away, splice its entries to the current CPU | |
| 3306 | + * and trigger a run of the softirq | |
| 3307 | + */ | |
| 3308 | + if (action == CPU_DEAD) { | |
| 3309 | + int cpu = (unsigned long) hcpu; | |
| 3310 | + | |
| 3311 | + local_irq_disable(); | |
| 3312 | + list_splice_init(&per_cpu(blk_cpu_done, cpu), | |
| 3313 | + &__get_cpu_var(blk_cpu_done)); | |
| 3314 | + raise_softirq_irqoff(BLOCK_SOFTIRQ); | |
| 3315 | + local_irq_enable(); | |
| 3316 | + } | |
| 3317 | + | |
| 3318 | + return NOTIFY_OK; | |
| 3319 | +} | |
| 3320 | + | |
| 3321 | + | |
| 3322 | +static struct notifier_block __devinitdata blk_cpu_notifier = { | |
| 3323 | + .notifier_call = blk_cpu_notify, | |
| 3324 | +}; | |
| 3325 | + | |
| 3326 | +#endif /* CONFIG_HOTPLUG_CPU */ | |
| 3327 | + | |
| 3328 | +/** | |
| 3329 | + * blk_complete_request - end I/O on a request | |
| 3330 | + * @req: the request being processed | |
| 3331 | + * | |
| 3332 | + * Description: | |
| 3333 | + * Ends all I/O on a request. It does not handle partial completions, | |
| 3334 | + * unless the driver actually implements this in its completionc callback | |
| 3335 | + * through requeueing. Theh actual completion happens out-of-order, | |
| 3336 | + * through a softirq handler. The user must have registered a completion | |
| 3337 | + * callback through blk_queue_softirq_done(). | |
| 3338 | + **/ | |
| 3339 | + | |
| 3340 | +void blk_complete_request(struct request *req) | |
| 3341 | +{ | |
| 3342 | + struct list_head *cpu_list; | |
| 3343 | + unsigned long flags; | |
| 3344 | + | |
| 3345 | + BUG_ON(!req->q->softirq_done_fn); | |
| 3346 | + | |
| 3347 | + local_irq_save(flags); | |
| 3348 | + | |
| 3349 | + cpu_list = &__get_cpu_var(blk_cpu_done); | |
| 3350 | + list_add_tail(&req->donelist, cpu_list); | |
| 3351 | + raise_softirq_irqoff(BLOCK_SOFTIRQ); | |
| 3352 | + | |
| 3353 | + local_irq_restore(flags); | |
| 3354 | +} | |
| 3355 | + | |
| 3356 | +EXPORT_SYMBOL(blk_complete_request); | |
| 3357 | + | |
| 3264 | 3358 | /* |
| 3265 | 3359 | * queue lock must be held |
| 3266 | 3360 | */ |
| @@ -3339,6 +3433,8 @@ EXPORT_SYMBOL(kblockd_flush); · 72 unmodified lines | ||
| 3339 | 3433 | |
| 3340 | 3434 | int __init blk_dev_init(void) |
| 3341 | 3435 | { |
| 3436 | + int i; | |
| 3437 | + | |
| 3342 | 3438 | kblockd_workqueue = create_workqueue("kblockd"); |
| 3343 | 3439 | if (!kblockd_workqueue) |
| 3344 | 3440 | panic("Failed to create kblockd\n"); |
| @@ -3352,6 +3448,14 @@ int __init blk_dev_init(void) · 7 unmodified lines | ||
| 3352 | 3448 | iocontext_cachep = kmem_cache_create("blkdev_ioc", |
| 3353 | 3449 | sizeof(struct io_context), 0, SLAB_PANIC, NULL, NULL); |
| 3354 | 3450 | |
| 3451 | + for (i = 0; i < NR_CPUS; i++) | |
| 3452 | + INIT_LIST_HEAD(&per_cpu(blk_cpu_done, i)); | |
| 3453 | + | |
| 3454 | + open_softirq(BLOCK_SOFTIRQ, blk_done_softirq, NULL); | |
| 3455 | +#ifdef CONFIG_HOTPLUG_CPU | |
| 3456 | + register_cpu_notifier(&blk_cpu_notifier); | |
| 3457 | +#endif | |
| 3458 | + | |
| 3355 | 3459 | blk_max_low_pfn = max_low_pfn; |
| 3356 | 3460 | blk_max_pfn = max_pfn; |
| 3357 | 3461 | |
| @@ -2178,16 +2178,48 @@ static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c) · 2177 unmodified lines | ||
| 2178 | 2178 | |
| 2179 | 2179 | start_io(h); |
| 2180 | 2180 | } |
| 2181 | + | |
| 2182 | +static void cciss_softirq_done(struct request *rq) | |
| 2183 | +{ | |
| 2184 | + CommandList_struct *cmd = rq->completion_data; | |
| 2185 | + ctlr_info_t *h = hba[cmd->ctlr]; | |
| 2186 | + u64bit temp64; | |
| 2187 | + int i, ddir; | |
| 2188 | + | |
| 2189 | + if (cmd->Request.Type.Direction == XFER_READ) | |
| 2190 | + ddir = PCI_DMA_FROMDEVICE; | |
| 2191 | + else | |
| 2192 | + ddir = PCI_DMA_TODEVICE; | |
| 2193 | + | |
| 2194 | + /* command did not need to be retried */ | |
| 2195 | + /* unmap the DMA mapping for all the scatter gather elements */ | |
| 2196 | + for(i=0; i<cmd->Header.SGList; i++) { | |
| 2197 | + temp64.val32.lower = cmd->SG[i].Addr.lower; | |
| 2198 | + temp64.val32.upper = cmd->SG[i].Addr.upper; | |
| 2199 | + pci_unmap_page(h->pdev, temp64.val, cmd->SG[i].Len, ddir); | |
| 2200 | + } | |
| 2201 | + | |
| 2202 | + complete_buffers(rq->bio, rq->errors); | |
| 2203 | + | |
| 2204 | +#ifdef CCISS_DEBUG | |
| 2205 | + printk("Done with %p\n", rq); | |
| 2206 | +#endif /* CCISS_DEBUG */ | |
| 2207 | + | |
| 2208 | + spin_lock_irq(&h->lock); | |
| 2209 | + end_that_request_last(rq, rq->errors); | |
| 2210 | + cmd_free(h, cmd,1); | |
| 2211 | + spin_unlock_irq(&h->lock); | |
| 2212 | +} | |
| 2213 | + | |
| 2181 | 2214 | /* checks the status of the job and calls complete buffers to mark all |
| 2182 | − * buffers for the completed job. | |
| 2215 | + * buffers for the completed job. Note that this function does not need | |
| 2216 | + * to hold the hba/queue lock. | |
| 2183 | 2217 | */ |
| 2184 | 2218 | static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, |
| 2185 | 2219 | int timeout) |
| 2186 | 2220 | { |
| 2187 | 2221 | int status = 1; |
| 2188 | − int i; | |
| 2189 | 2222 | int retry_cmd = 0; |
| 2190 | − u64bit temp64; | |
| 2191 | 2223 | |
| 2192 | 2224 | if (timeout) |
| 2193 | 2225 | status = 0; |
| @@ -2295,24 +2327,10 @@ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd, · 101 unmodified lines | ||
| 2295 | 2327 | resend_cciss_cmd(h,cmd); |
| 2296 | 2328 | return; |
| 2297 | 2329 | } |
| 2298 | − /* command did not need to be retried */ | |
| 2299 | − /* unmap the DMA mapping for all the scatter gather elements */ | |
| 2300 | − for(i=0; i<cmd->Header.SGList; i++) { | |
| 2301 | − temp64.val32.lower = cmd->SG[i].Addr.lower; | |
| 2302 | − temp64.val32.upper = cmd->SG[i].Addr.upper; | |
| 2303 | − pci_unmap_page(hba[cmd->ctlr]->pdev, | |
| 2304 | − temp64.val, cmd->SG[i].Len, | |
| 2305 | − (cmd->Request.Type.Direction == XFER_READ) ? | |
| 2306 | − PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); | |
| 2307 | − } | |
| 2308 | − complete_buffers(cmd->rq->bio, status); | |
| 2309 | − | |
| 2310 | −#ifdef CCISS_DEBUG | |
| 2311 | − printk("Done with %p\n", cmd->rq); | |
| 2312 | −#endif /* CCISS_DEBUG */ | |
| 2313 | 2330 | |
| 2314 | − end_that_request_last(cmd->rq, status ? 1 : -EIO); | |
| 2315 | − cmd_free(h,cmd,1); | |
| 2331 | + cmd->rq->completion_data = cmd; | |
| 2332 | + cmd->rq->errors = status; | |
| 2333 | + blk_complete_request(cmd->rq); | |
| 2316 | 2334 | } |
| 2317 | 2335 | |
| 2318 | 2336 | /* |
| @@ -3199,15 +3217,17 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, · 880 unmodified lines | ||
| 3199 | 3217 | drv->queue = q; |
| 3200 | 3218 | |
| 3201 | 3219 | q->backing_dev_info.ra_pages = READ_AHEAD; |
| 3202 | − blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); | |
| 3220 | + blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask); | |
| 3221 | + | |
| 3222 | + /* This is a hardware imposed limit. */ | |
| 3223 | + blk_queue_max_hw_segments(q, MAXSGENTRIES); | |
| 3203 | 3224 | |
| 3204 | − /* This is a hardware imposed limit. */ | |
| 3205 | − blk_queue_max_hw_segments(q, MAXSGENTRIES); | |
| 3225 | + /* This is a limit in the driver and could be eliminated. */ | |
| 3226 | + blk_queue_max_phys_segments(q, MAXSGENTRIES); | |
| 3206 | 3227 | |
| 3207 | − /* This is a limit in the driver and could be eliminated. */ | |
| 3208 | − blk_queue_max_phys_segments(q, MAXSGENTRIES); | |
| 3228 | + blk_queue_max_sectors(q, 512); | |
| 3209 | 3229 | |
| 3210 | − blk_queue_max_sectors(q, 512); | |
| 3230 | + blk_queue_softirq_done(q, cciss_softirq_done); | |
| 3211 | 3231 | |
| 3212 | 3232 | q->queuedata = hba[i]; |
| 3213 | 3233 | sprintf(disk->disk_name, "cciss/c%dd%d", i, j); |
| @@ -55,9 +55,22 @@ · 54 unmodified lines | ||
| 55 | 55 | #include <asm/io.h> |
| 56 | 56 | #include <asm/bitops.h> |
| 57 | 57 | |
| 58 | +void ide_softirq_done(struct request *rq) | |
| 59 | +{ | |
| 60 | + request_queue_t *q = rq->q; | |
| 61 | + | |
| 62 | + add_disk_randomness(rq->rq_disk); | |
| 63 | + end_that_request_chunk(rq, rq->errors, rq->data_len); | |
| 64 | + | |
| 65 | + spin_lock_irq(q->queue_lock); | |
| 66 | + end_that_request_last(rq, rq->errors); | |
| 67 | + spin_unlock_irq(q->queue_lock); | |
| 68 | +} | |
| 69 | + | |
| 58 | 70 | int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, |
| 59 | 71 | int nr_sectors) |
| 60 | 72 | { |
| 73 | + unsigned int nbytes; | |
| 61 | 74 | int ret = 1; |
| 62 | 75 | |
| 63 | 76 | BUG_ON(!(rq->flags & REQ_STARTED)); |
| @@ -81,17 +94,28 @@ int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate, · 17 unmodified lines | ||
| 81 | 94 | HWGROUP(drive)->hwif->ide_dma_on(drive); |
| 82 | 95 | } |
| 83 | 96 | |
| 84 | − if (!end_that_request_first(rq, uptodate, nr_sectors)) { | |
| 85 | − add_disk_randomness(rq->rq_disk); | |
| 86 | − | |
| 87 | − if (blk_rq_tagged(rq)) | |
| 88 | − blk_queue_end_tag(drive->queue, rq); | |
| 89 | − | |
| 97 | + /* | |
| 98 | + * For partial completions (or non fs/pc requests), use the regular | |
| 99 | + * direct completion path. | |
| 100 | + */ | |
| 101 | + nbytes = nr_sectors << 9; | |
| 102 | + if (rq_all_done(rq, nbytes)) { | |
| 103 | + rq->errors = uptodate; | |
| 104 | + rq->data_len = nbytes; | |
| 90 | 105 | blkdev_dequeue_request(rq); |
| 91 | 106 | HWGROUP(drive)->rq = NULL; |
| 92 | − end_that_request_last(rq, uptodate); | |
| 107 | + blk_complete_request(rq); | |
| 93 | 108 | ret = 0; |
| 109 | + } else { | |
| 110 | + if (!end_that_request_first(rq, uptodate, nr_sectors)) { | |
| 111 | + add_disk_randomness(rq->rq_disk); | |
| 112 | + blkdev_dequeue_request(rq); | |
| 113 | + HWGROUP(drive)->rq = NULL; | |
| 114 | + end_that_request_last(rq, uptodate); | |
| 115 | + ret = 0; | |
| 116 | + } | |
| 94 | 117 | } |
| 118 | + | |
| 95 | 119 | return ret; |
| 96 | 120 | } |
| 97 | 121 | EXPORT_SYMBOL(__ide_end_request); |
| @@ -113,6 +137,10 @@ int ide_end_request (ide_drive_t *drive, int uptodate, int nr_sectors) · 15 unmodified lines | ||
| 113 | 137 | unsigned long flags; |
| 114 | 138 | int ret = 1; |
| 115 | 139 | |
| 140 | + /* | |
| 141 | + * room for locking improvements here, the calls below don't | |
| 142 | + * need the queue lock held at all | |
| 143 | + */ | |
| 116 | 144 | spin_lock_irqsave(&ide_lock, flags); |
| 117 | 145 | rq = HWGROUP(drive)->rq; |
| 118 | 146 | |
| @@ -1011,6 +1011,8 @@ static int ide_init_queue(ide_drive_t *drive) · 1010 unmodified lines | ||
| 1011 | 1011 | blk_queue_max_hw_segments(q, max_sg_entries); |
| 1012 | 1012 | blk_queue_max_phys_segments(q, max_sg_entries); |
| 1013 | 1013 | |
| 1014 | + blk_queue_softirq_done(q, ide_softirq_done); | |
| 1015 | + | |
| 1014 | 1016 | /* assign drive queue */ |
| 1015 | 1017 | drive->queue = q; |
| 1016 | 1018 | |
| @@ -69,7 +69,6 @@ · 68 unmodified lines | ||
| 69 | 69 | #include "scsi_logging.h" |
| 70 | 70 | |
| 71 | 71 | static void scsi_done(struct scsi_cmnd *cmd); |
| 72 | −static int scsi_retry_command(struct scsi_cmnd *cmd); | |
| 73 | 72 | |
| 74 | 73 | /* |
| 75 | 74 | * Definitions and constants. |
| @@ -752,7 +751,7 @@ static void scsi_done(struct scsi_cmnd *cmd) · 676 unmodified lines | ||
| 752 | 751 | * isn't running --- used by scsi_times_out */ |
| 753 | 752 | void __scsi_done(struct scsi_cmnd *cmd) |
| 754 | 753 | { |
| 755 | − unsigned long flags; | |
| 754 | + struct request *rq = cmd->request; | |
| 756 | 755 | |
| 757 | 756 | /* |
| 758 | 757 | * Set the serial numbers back to zero |
| @@ -763,71 +762,14 @@ void __scsi_done(struct scsi_cmnd *cmd) · 4 unmodified lines | ||
| 763 | 762 | if (cmd->result) |
| 764 | 763 | atomic_inc(&cmd->device->ioerr_cnt); |
| 765 | 764 | |
| 765 | + BUG_ON(!rq); | |
| 766 | + | |
| 766 | 767 | /* |
| 767 | − * Next, enqueue the command into the done queue. | |
| 768 | − * It is a per-CPU queue, so we just disable local interrupts | |
| 769 | − * and need no spinlock. | |
| 768 | + * The uptodate/nbytes values don't matter, as we allow partial | |
| 769 | + * completes and thus will check this in the softirq callback | |
| 770 | 770 | */ |
| 771 | − local_irq_save(flags); | |
| 772 | − list_add_tail(&cmd->eh_entry, &__get_cpu_var(scsi_done_q)); | |
| 773 | − raise_softirq_irqoff(SCSI_SOFTIRQ); | |
| 774 | − local_irq_restore(flags); | |
| 775 | −} | |
| 776 | − | |
| 777 | −/** | |
| 778 | − * scsi_softirq - Perform post-interrupt processing of finished SCSI commands. | |
| 779 | − * | |
| 780 | − * This is the consumer of the done queue. | |
| 781 | − * | |
| 782 | − * This is called with all interrupts enabled. This should reduce | |
| 783 | − * interrupt latency, stack depth, and reentrancy of the low-level | |
| 784 | − * drivers. | |
| 785 | − */ | |
| 786 | −static void scsi_softirq(struct softirq_action *h) | |
| 787 | −{ | |
| 788 | − int disposition; | |
| 789 | − LIST_HEAD(local_q); | |
| 790 | − | |
| 791 | − local_irq_disable(); | |
| 792 | − list_splice_init(&__get_cpu_var(scsi_done_q), &local_q); | |
| 793 | − local_irq_enable(); | |
| 794 | − | |
| 795 | − while (!list_empty(&local_q)) { | |
| 796 | − struct scsi_cmnd *cmd = list_entry(local_q.next, | |
| 797 | − struct scsi_cmnd, eh_entry); | |
| 798 | − /* The longest time any command should be outstanding is the | |
| 799 | − * per command timeout multiplied by the number of retries. | |
| 800 | − * | |
| 801 | − * For a typical command, this is 2.5 minutes */ | |
| 802 | − unsigned long wait_for | |
| 803 | − = cmd->allowed * cmd->timeout_per_command; | |
| 804 | − list_del_init(&cmd->eh_entry); | |
| 805 | − | |
| 806 | − disposition = scsi_decide_disposition(cmd); | |
| 807 | − if (disposition != SUCCESS && | |
| 808 | − time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { | |
| 809 | − sdev_printk(KERN_ERR, cmd->device, | |
| 810 | − "timing out command, waited %lus\n", | |
| 811 | − wait_for/HZ); | |
| 812 | − disposition = SUCCESS; | |
| 813 | − } | |
| 814 | − | |
| 815 | − scsi_log_completion(cmd, disposition); | |
| 816 | − switch (disposition) { | |
| 817 | − case SUCCESS: | |
| 818 | − scsi_finish_command(cmd); | |
| 819 | − break; | |
| 820 | − case NEEDS_RETRY: | |
| 821 | − scsi_retry_command(cmd); | |
| 822 | − break; | |
| 823 | − case ADD_TO_MLQUEUE: | |
| 824 | − scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); | |
| 825 | − break; | |
| 826 | − default: | |
| 827 | − if (!scsi_eh_scmd_add(cmd, 0)) | |
| 828 | − scsi_finish_command(cmd); | |
| 829 | − } | |
| 830 | − } | |
| 771 | + rq->completion_data = cmd; | |
| 772 | + blk_complete_request(rq); | |
| 831 | 773 | } |
| 832 | 774 | |
| 833 | 775 | /* |
| @@ -840,7 +782,7 @@ static void scsi_softirq(struct softirq_action *h) · 6 unmodified lines | ||
| 840 | 782 | * level drivers should not become re-entrant as a result of |
| 841 | 783 | * this. |
| 842 | 784 | */ |
| 843 | −static int scsi_retry_command(struct scsi_cmnd *cmd) | |
| 785 | +int scsi_retry_command(struct scsi_cmnd *cmd) | |
| 844 | 786 | { |
| 845 | 787 | /* |
| 846 | 788 | * Restore the SCSI command state. |
| @@ -1273,38 +1215,6 @@ int scsi_device_cancel(struct scsi_device *sdev, int recovery) · 426 unmodified lines | ||
| 1273 | 1215 | } |
| 1274 | 1216 | EXPORT_SYMBOL(scsi_device_cancel); |
| 1275 | 1217 | |
| 1276 | −#ifdef CONFIG_HOTPLUG_CPU | |
| 1277 | −static int scsi_cpu_notify(struct notifier_block *self, | |
| 1278 | − unsigned long action, void *hcpu) | |
| 1279 | −{ | |
| 1280 | − int cpu = (unsigned long)hcpu; | |
| 1281 | − | |
| 1282 | − switch(action) { | |
| 1283 | − case CPU_DEAD: | |
| 1284 | − /* Drain scsi_done_q. */ | |
| 1285 | − local_irq_disable(); | |
| 1286 | − list_splice_init(&per_cpu(scsi_done_q, cpu), | |
| 1287 | − &__get_cpu_var(scsi_done_q)); | |
| 1288 | − raise_softirq_irqoff(SCSI_SOFTIRQ); | |
| 1289 | − local_irq_enable(); | |
| 1290 | − break; | |
| 1291 | − default: | |
| 1292 | − break; | |
| 1293 | − } | |
| 1294 | − return NOTIFY_OK; | |
| 1295 | −} | |
| 1296 | − | |
| 1297 | −static struct notifier_block __devinitdata scsi_cpu_nb = { | |
| 1298 | − .notifier_call = scsi_cpu_notify, | |
| 1299 | −}; | |
| 1300 | − | |
| 1301 | −#define register_scsi_cpu() register_cpu_notifier(&scsi_cpu_nb) | |
| 1302 | −#define unregister_scsi_cpu() unregister_cpu_notifier(&scsi_cpu_nb) | |
| 1303 | −#else | |
| 1304 | −#define register_scsi_cpu() | |
| 1305 | −#define unregister_scsi_cpu() | |
| 1306 | −#endif /* CONFIG_HOTPLUG_CPU */ | |
| 1307 | − | |
| 1308 | 1218 | MODULE_DESCRIPTION("SCSI core"); |
| 1309 | 1219 | MODULE_LICENSE("GPL"); |
| 1310 | 1220 | |
| @@ -1338,8 +1248,6 @@ static int __init init_scsi(void) · 27 unmodified lines | ||
| 1338 | 1248 | INIT_LIST_HEAD(&per_cpu(scsi_done_q, i)); |
| 1339 | 1249 | |
| 1340 | 1250 | devfs_mk_dir("scsi"); |
| 1341 | − open_softirq(SCSI_SOFTIRQ, scsi_softirq, NULL); | |
| 1342 | − register_scsi_cpu(); | |
| 1343 | 1251 | printk(KERN_NOTICE "SCSI subsystem initialized\n"); |
| 1344 | 1252 | return 0; |
| 1345 | 1253 | |
| @@ -1367,7 +1275,6 @@ static void __exit exit_scsi(void) · 21 unmodified lines | ||
| 1367 | 1275 | devfs_remove("scsi"); |
| 1368 | 1276 | scsi_exit_procfs(); |
| 1369 | 1277 | scsi_exit_queue(); |
| 1370 | − unregister_scsi_cpu(); | |
| 1371 | 1278 | } |
| 1372 | 1279 | |
| 1373 | 1280 | subsys_initcall(init_scsi); |
| @@ -1493,6 +1493,41 @@ static void scsi_kill_request(struct request *req, request_queue_t *q) · 1492 unmodified lines | ||
| 1493 | 1493 | __scsi_done(cmd); |
| 1494 | 1494 | } |
| 1495 | 1495 | |
| 1496 | +static void scsi_softirq_done(struct request *rq) | |
| 1497 | +{ | |
| 1498 | + struct scsi_cmnd *cmd = rq->completion_data; | |
| 1499 | + unsigned long wait_for = cmd->allowed * cmd->timeout_per_command; | |
| 1500 | + int disposition; | |
| 1501 | + | |
| 1502 | + INIT_LIST_HEAD(&cmd->eh_entry); | |
| 1503 | + | |
| 1504 | + disposition = scsi_decide_disposition(cmd); | |
| 1505 | + if (disposition != SUCCESS && | |
| 1506 | + time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { | |
| 1507 | + sdev_printk(KERN_ERR, cmd->device, | |
| 1508 | + "timing out command, waited %lus\n", | |
| 1509 | + wait_for/HZ); | |
| 1510 | + disposition = SUCCESS; | |
| 1511 | + } | |
| 1512 | + | |
| 1513 | + scsi_log_completion(cmd, disposition); | |
| 1514 | + | |
| 1515 | + switch (disposition) { | |
| 1516 | + case SUCCESS: | |
| 1517 | + scsi_finish_command(cmd); | |
| 1518 | + break; | |
| 1519 | + case NEEDS_RETRY: | |
| 1520 | + scsi_retry_command(cmd); | |
| 1521 | + break; | |
| 1522 | + case ADD_TO_MLQUEUE: | |
| 1523 | + scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); | |
| 1524 | + break; | |
| 1525 | + default: | |
| 1526 | + if (!scsi_eh_scmd_add(cmd, 0)) | |
| 1527 | + scsi_finish_command(cmd); | |
| 1528 | + } | |
| 1529 | +} | |
| 1530 | + | |
| 1496 | 1531 | /* |
| 1497 | 1532 | * Function: scsi_request_fn() |
| 1498 | 1533 | * |
| @@ -1667,6 +1702,7 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) · 168 unmodified lines | ||
| 1667 | 1702 | blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost)); |
| 1668 | 1703 | blk_queue_segment_boundary(q, shost->dma_boundary); |
| 1669 | 1704 | blk_queue_issue_flush_fn(q, scsi_issue_flush_fn); |
| 1705 | + blk_queue_softirq_done(q, scsi_softirq_done); | |
| 1670 | 1706 | |
| 1671 | 1707 | if (!shost->use_clustering) |
| 1672 | 1708 | clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); |
| @@ -44,6 +44,7 @@ extern void scsi_init_cmd_from_req(struct scsi_cmnd *cmd, · 43 unmodified lines | ||
| 44 | 44 | struct scsi_request *sreq); |
| 45 | 45 | extern void __scsi_release_request(struct scsi_request *sreq); |
| 46 | 46 | extern void __scsi_done(struct scsi_cmnd *cmd); |
| 47 | +extern int scsi_retry_command(struct scsi_cmnd *cmd); | |
| 47 | 48 | #ifdef CONFIG_SCSI_LOGGING |
| 48 | 49 | void scsi_log_send(struct scsi_cmnd *cmd); |
| 49 | 50 | void scsi_log_completion(struct scsi_cmnd *cmd, int disposition); |
| @@ -118,9 +118,9 @@ struct request_list { · 117 unmodified lines | ||
| 118 | 118 | * try to put the fields that are referenced together in the same cacheline |
| 119 | 119 | */ |
| 120 | 120 | struct request { |
| 121 | − struct list_head queuelist; /* looking for ->queue? you must _not_ | |
| 122 | − * access it directly, use | |
| 123 | − * blkdev_dequeue_request! */ | |
| 121 | + struct list_head queuelist; | |
| 122 | + struct list_head donelist; | |
| 123 | + | |
| 124 | 124 | unsigned long flags; /* see REQ_ bits below */ |
| 125 | 125 | |
| 126 | 126 | /* Maintain bio traversal state for part by part I/O submission. |
| @@ -141,6 +141,7 @@ struct request { · 14 unmodified lines | ||
| 141 | 141 | struct bio *biotail; |
| 142 | 142 | |
| 143 | 143 | void *elevator_private; |
| 144 | + void *completion_data; | |
| 144 | 145 | |
| 145 | 146 | unsigned short ioprio; |
| 146 | 147 | |
| @@ -291,6 +292,7 @@ typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *); · 144 unmodified lines | ||
| 291 | 292 | typedef void (activity_fn) (void *data, int rw); |
| 292 | 293 | typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *); |
| 293 | 294 | typedef void (prepare_flush_fn) (request_queue_t *, struct request *); |
| 295 | +typedef void (softirq_done_fn)(struct request *); | |
| 294 | 296 | |
| 295 | 297 | enum blk_queue_state { |
| 296 | 298 | Queue_down, |
| @@ -332,6 +334,7 @@ struct request_queue · 35 unmodified lines | ||
| 332 | 334 | activity_fn *activity_fn; |
| 333 | 335 | issue_flush_fn *issue_flush_fn; |
| 334 | 336 | prepare_flush_fn *prepare_flush_fn; |
| 337 | + softirq_done_fn *softirq_done_fn; | |
| 335 | 338 | |
| 336 | 339 | /* |
| 337 | 340 | * Dispatch queue sorting |
| @@ -645,6 +648,17 @@ extern int end_that_request_first(struct request *, int, int); · 307 unmodified lines | ||
| 645 | 648 | extern int end_that_request_chunk(struct request *, int, int); |
| 646 | 649 | extern void end_that_request_last(struct request *, int); |
| 647 | 650 | extern void end_request(struct request *req, int uptodate); |
| 651 | +extern void blk_complete_request(struct request *); | |
| 652 | + | |
| 653 | +static inline int rq_all_done(struct request *rq, unsigned int nr_bytes) | |
| 654 | +{ | |
| 655 | + if (blk_fs_request(rq)) | |
| 656 | + return (nr_bytes >= (rq->hard_nr_sectors << 9)); | |
| 657 | + else if (blk_pc_request(rq)) | |
| 658 | + return nr_bytes >= rq->data_len; | |
| 659 | + | |
| 660 | + return 0; | |
| 661 | +} | |
| 648 | 662 | |
| 649 | 663 | /* |
| 650 | 664 | * end_that_request_first/chunk() takes an uptodate argument. we account |
| @@ -693,6 +707,7 @@ extern void blk_queue_segment_boundary(request_queue_t *, unsigned long); · 42 unmodified lines | ||
| 693 | 707 | extern void blk_queue_prep_rq(request_queue_t *, prep_rq_fn *pfn); |
| 694 | 708 | extern void blk_queue_merge_bvec(request_queue_t *, merge_bvec_fn *); |
| 695 | 709 | extern void blk_queue_dma_alignment(request_queue_t *, int); |
| 710 | +extern void blk_queue_softirq_done(request_queue_t *, softirq_done_fn *); | |
| 696 | 711 | extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); |
| 697 | 712 | extern int blk_queue_ordered(request_queue_t *, unsigned, prepare_flush_fn *); |
| 698 | 713 | extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *); |
| @@ -1001,6 +1001,7 @@ extern int noautodma; · 1000 unmodified lines | ||
| 1001 | 1001 | |
| 1002 | 1002 | extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); |
| 1003 | 1003 | extern int __ide_end_request (ide_drive_t *drive, struct request *rq, int uptodate, int nrsecs); |
| 1004 | +extern void ide_softirq_done(struct request *rq); | |
| 1004 | 1005 | |
| 1005 | 1006 | /* |
| 1006 | 1007 | * This is used on exit from the driver to designate the next irq handler |
| @@ -112,7 +112,7 @@ enum · 111 unmodified lines | ||
| 112 | 112 | TIMER_SOFTIRQ, |
| 113 | 113 | NET_TX_SOFTIRQ, |
| 114 | 114 | NET_RX_SOFTIRQ, |
| 115 | − SCSI_SOFTIRQ, | |
| 115 | + BLOCK_SOFTIRQ, | |
| 116 | 116 | TASKLET_SOFTIRQ |
| 117 | 117 | }; |
| 118 | 118 | |