forked from mirrors/linux
		
	ide: convert to blk-mq
ide-disk and ide-cd tested as working just fine, ide-tape and ide-floppy haven't. But the latter don't require changes, so they should work without issue. Add helper function to insert a request from a work queue, since we cannot invoke the blk-mq request insertion from IRQ context. Cc: David Miller <davem@davemloft.net> Reviewed-by: Hannes Reinecke <hare@suse.com> Tested-by: Ming Lei <ming.lei@redhat.com> Reviewed-by: Omar Sandoval <osandov@fb.com> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
		
							parent
							
								
									d0be12274d
								
							
						
					
					
						commit
						600335205b
					
				
					 8 changed files with 239 additions and 179 deletions
				
			
		|  | @ -172,8 +172,8 @@ EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd); | ||||||
| void ide_prep_sense(ide_drive_t *drive, struct request *rq) | void ide_prep_sense(ide_drive_t *drive, struct request *rq) | ||||||
| { | { | ||||||
| 	struct request_sense *sense = &drive->sense_data; | 	struct request_sense *sense = &drive->sense_data; | ||||||
| 	struct request *sense_rq = drive->sense_rq; | 	struct request *sense_rq; | ||||||
| 	struct scsi_request *req = scsi_req(sense_rq); | 	struct scsi_request *req; | ||||||
| 	unsigned int cmd_len, sense_len; | 	unsigned int cmd_len, sense_len; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
|  | @ -196,9 +196,16 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) | ||||||
| 	if (ata_sense_request(rq) || drive->sense_rq_armed) | 	if (ata_sense_request(rq) || drive->sense_rq_armed) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | 	sense_rq = drive->sense_rq; | ||||||
|  | 	if (!sense_rq) { | ||||||
|  | 		sense_rq = blk_mq_alloc_request(drive->queue, REQ_OP_DRV_IN, | ||||||
|  | 					BLK_MQ_REQ_RESERVED | BLK_MQ_REQ_NOWAIT); | ||||||
|  | 		drive->sense_rq = sense_rq; | ||||||
|  | 	} | ||||||
|  | 	req = scsi_req(sense_rq); | ||||||
|  | 
 | ||||||
| 	memset(sense, 0, sizeof(*sense)); | 	memset(sense, 0, sizeof(*sense)); | ||||||
| 
 | 
 | ||||||
| 	blk_rq_init(rq->q, sense_rq); |  | ||||||
| 	scsi_req_init(req); | 	scsi_req_init(req); | ||||||
| 
 | 
 | ||||||
| 	err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len, | 	err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len, | ||||||
|  | @ -207,6 +214,8 @@ void ide_prep_sense(ide_drive_t *drive, struct request *rq) | ||||||
| 		if (printk_ratelimit()) | 		if (printk_ratelimit()) | ||||||
| 			printk(KERN_WARNING PFX "%s: failed to map sense " | 			printk(KERN_WARNING PFX "%s: failed to map sense " | ||||||
| 					    "buffer\n", drive->name); | 					    "buffer\n", drive->name); | ||||||
|  | 		blk_mq_free_request(sense_rq); | ||||||
|  | 		drive->sense_rq = NULL; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -226,6 +235,8 @@ EXPORT_SYMBOL_GPL(ide_prep_sense); | ||||||
| 
 | 
 | ||||||
| int ide_queue_sense_rq(ide_drive_t *drive, void *special) | int ide_queue_sense_rq(ide_drive_t *drive, void *special) | ||||||
| { | { | ||||||
|  | 	struct request *sense_rq = drive->sense_rq; | ||||||
|  | 
 | ||||||
| 	/* deferred failure from ide_prep_sense() */ | 	/* deferred failure from ide_prep_sense() */ | ||||||
| 	if (!drive->sense_rq_armed) { | 	if (!drive->sense_rq_armed) { | ||||||
| 		printk(KERN_WARNING PFX "%s: error queuing a sense request\n", | 		printk(KERN_WARNING PFX "%s: error queuing a sense request\n", | ||||||
|  | @ -233,12 +244,12 @@ int ide_queue_sense_rq(ide_drive_t *drive, void *special) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	drive->sense_rq->special = special; | 	sense_rq->special = special; | ||||||
| 	drive->sense_rq_armed = false; | 	drive->sense_rq_armed = false; | ||||||
| 
 | 
 | ||||||
| 	drive->hwif->rq = NULL; | 	drive->hwif->rq = NULL; | ||||||
| 
 | 
 | ||||||
| 	elv_add_request(drive->queue, drive->sense_rq, ELEVATOR_INSERT_FRONT); | 	ide_insert_request_head(drive, sense_rq); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(ide_queue_sense_rq); | EXPORT_SYMBOL_GPL(ide_queue_sense_rq); | ||||||
|  | @ -270,10 +281,8 @@ void ide_retry_pc(ide_drive_t *drive) | ||||||
| 	 */ | 	 */ | ||||||
| 	drive->hwif->rq = NULL; | 	drive->hwif->rq = NULL; | ||||||
| 	ide_requeue_and_plug(drive, failed_rq); | 	ide_requeue_and_plug(drive, failed_rq); | ||||||
| 	if (ide_queue_sense_rq(drive, pc)) { | 	if (ide_queue_sense_rq(drive, pc)) | ||||||
| 		blk_start_request(failed_rq); |  | ||||||
| 		ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(failed_rq)); | 		ide_complete_rq(drive, BLK_STS_IOERR, blk_rq_bytes(failed_rq)); | ||||||
| 	} |  | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(ide_retry_pc); | EXPORT_SYMBOL_GPL(ide_retry_pc); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -258,11 +258,22 @@ static int ide_cd_breathe(ide_drive_t *drive, struct request *rq) | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * take a breather | 		 * take a breather | ||||||
| 		 */ | 		 */ | ||||||
| 		blk_delay_queue(drive->queue, 1); | 		blk_mq_requeue_request(rq, false); | ||||||
|  | 		blk_mq_delay_kick_requeue_list(drive->queue, 1); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void ide_cd_free_sense(ide_drive_t *drive) | ||||||
|  | { | ||||||
|  | 	if (!drive->sense_rq) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	blk_mq_free_request(drive->sense_rq); | ||||||
|  | 	drive->sense_rq = NULL; | ||||||
|  | 	drive->sense_rq_armed = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Returns: |  * Returns: | ||||||
|  * 0: if the request should be continued. |  * 0: if the request should be continued. | ||||||
|  | @ -516,6 +527,82 @@ static bool ide_cd_error_cmd(ide_drive_t *drive, struct ide_cmd *cmd) | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* standard prep_rq_fn that builds 10 byte cmds */ | ||||||
|  | static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) | ||||||
|  | { | ||||||
|  | 	int hard_sect = queue_logical_block_size(q); | ||||||
|  | 	long block = (long)blk_rq_pos(rq) / (hard_sect >> 9); | ||||||
|  | 	unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9); | ||||||
|  | 	struct scsi_request *req = scsi_req(rq); | ||||||
|  | 
 | ||||||
|  | 	if (rq_data_dir(rq) == READ) | ||||||
|  | 		req->cmd[0] = GPCMD_READ_10; | ||||||
|  | 	else | ||||||
|  | 		req->cmd[0] = GPCMD_WRITE_10; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * fill in lba | ||||||
|  | 	 */ | ||||||
|  | 	req->cmd[2] = (block >> 24) & 0xff; | ||||||
|  | 	req->cmd[3] = (block >> 16) & 0xff; | ||||||
|  | 	req->cmd[4] = (block >>  8) & 0xff; | ||||||
|  | 	req->cmd[5] = block & 0xff; | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * and transfer length | ||||||
|  | 	 */ | ||||||
|  | 	req->cmd[7] = (blocks >> 8) & 0xff; | ||||||
|  | 	req->cmd[8] = blocks & 0xff; | ||||||
|  | 	req->cmd_len = 10; | ||||||
|  | 	return BLKPREP_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*
 | ||||||
|  |  * Most of the SCSI commands are supported directly by ATAPI devices. | ||||||
|  |  * This transform handles the few exceptions. | ||||||
|  |  */ | ||||||
|  | static int ide_cdrom_prep_pc(struct request *rq) | ||||||
|  | { | ||||||
|  | 	u8 *c = scsi_req(rq)->cmd; | ||||||
|  | 
 | ||||||
|  | 	/* transform 6-byte read/write commands to the 10-byte version */ | ||||||
|  | 	if (c[0] == READ_6 || c[0] == WRITE_6) { | ||||||
|  | 		c[8] = c[4]; | ||||||
|  | 		c[5] = c[3]; | ||||||
|  | 		c[4] = c[2]; | ||||||
|  | 		c[3] = c[1] & 0x1f; | ||||||
|  | 		c[2] = 0; | ||||||
|  | 		c[1] &= 0xe0; | ||||||
|  | 		c[0] += (READ_10 - READ_6); | ||||||
|  | 		scsi_req(rq)->cmd_len = 10; | ||||||
|  | 		return BLKPREP_OK; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/*
 | ||||||
|  | 	 * it's silly to pretend we understand 6-byte sense commands, just | ||||||
|  | 	 * reject with ILLEGAL_REQUEST and the caller should take the | ||||||
|  | 	 * appropriate action | ||||||
|  | 	 */ | ||||||
|  | 	if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { | ||||||
|  | 		scsi_req(rq)->result = ILLEGAL_REQUEST; | ||||||
|  | 		return BLKPREP_KILL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return BLKPREP_OK; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static int ide_cdrom_prep_fn(ide_drive_t *drive, struct request *rq) | ||||||
|  | { | ||||||
|  | 	if (!blk_rq_is_passthrough(rq)) { | ||||||
|  | 		scsi_req_init(scsi_req(rq)); | ||||||
|  | 
 | ||||||
|  | 		return ide_cdrom_prep_fs(drive->queue, rq); | ||||||
|  | 	} else if (blk_rq_is_scsi(rq)) | ||||||
|  | 		return ide_cdrom_prep_pc(rq); | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | ||||||
| { | { | ||||||
| 	ide_hwif_t *hwif = drive->hwif; | 	ide_hwif_t *hwif = drive->hwif; | ||||||
|  | @ -675,7 +762,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | ||||||
| out_end: | out_end: | ||||||
| 	if (blk_rq_is_scsi(rq) && rc == 0) { | 	if (blk_rq_is_scsi(rq) && rc == 0) { | ||||||
| 		scsi_req(rq)->resid_len = 0; | 		scsi_req(rq)->resid_len = 0; | ||||||
| 		blk_end_request_all(rq, BLK_STS_OK); | 		blk_mq_end_request(rq, BLK_STS_OK); | ||||||
| 		hwif->rq = NULL; | 		hwif->rq = NULL; | ||||||
| 	} else { | 	} else { | ||||||
| 		if (sense && uptodate) | 		if (sense && uptodate) | ||||||
|  | @ -705,6 +792,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | ||||||
| 		if (sense && rc == 2) | 		if (sense && rc == 2) | ||||||
| 			ide_error(drive, "request sense failure", stat); | 			ide_error(drive, "request sense failure", stat); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	ide_cd_free_sense(drive); | ||||||
| 	return ide_stopped; | 	return ide_stopped; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -729,7 +818,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | ||||||
| 		 * We may be retrying this request after an error.  Fix up any | 		 * We may be retrying this request after an error.  Fix up any | ||||||
| 		 * weirdness which might be present in the request packet. | 		 * weirdness which might be present in the request packet. | ||||||
| 		 */ | 		 */ | ||||||
| 		q->prep_rq_fn(q, rq); | 		ide_cdrom_prep_fn(drive, rq); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* fs requests *must* be hardware frame aligned */ | 	/* fs requests *must* be hardware frame aligned */ | ||||||
|  | @ -1323,82 +1412,6 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive) | ||||||
| 	return nslots; | 	return nslots; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* standard prep_rq_fn that builds 10 byte cmds */ |  | ||||||
| static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) |  | ||||||
| { |  | ||||||
| 	int hard_sect = queue_logical_block_size(q); |  | ||||||
| 	long block = (long)blk_rq_pos(rq) / (hard_sect >> 9); |  | ||||||
| 	unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9); |  | ||||||
| 	struct scsi_request *req = scsi_req(rq); |  | ||||||
| 
 |  | ||||||
| 	q->initialize_rq_fn(rq); |  | ||||||
| 
 |  | ||||||
| 	if (rq_data_dir(rq) == READ) |  | ||||||
| 		req->cmd[0] = GPCMD_READ_10; |  | ||||||
| 	else |  | ||||||
| 		req->cmd[0] = GPCMD_WRITE_10; |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * fill in lba |  | ||||||
| 	 */ |  | ||||||
| 	req->cmd[2] = (block >> 24) & 0xff; |  | ||||||
| 	req->cmd[3] = (block >> 16) & 0xff; |  | ||||||
| 	req->cmd[4] = (block >>  8) & 0xff; |  | ||||||
| 	req->cmd[5] = block & 0xff; |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * and transfer length |  | ||||||
| 	 */ |  | ||||||
| 	req->cmd[7] = (blocks >> 8) & 0xff; |  | ||||||
| 	req->cmd[8] = blocks & 0xff; |  | ||||||
| 	req->cmd_len = 10; |  | ||||||
| 	return BLKPREP_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Most of the SCSI commands are supported directly by ATAPI devices. |  | ||||||
|  * This transform handles the few exceptions. |  | ||||||
|  */ |  | ||||||
| static int ide_cdrom_prep_pc(struct request *rq) |  | ||||||
| { |  | ||||||
| 	u8 *c = scsi_req(rq)->cmd; |  | ||||||
| 
 |  | ||||||
| 	/* transform 6-byte read/write commands to the 10-byte version */ |  | ||||||
| 	if (c[0] == READ_6 || c[0] == WRITE_6) { |  | ||||||
| 		c[8] = c[4]; |  | ||||||
| 		c[5] = c[3]; |  | ||||||
| 		c[4] = c[2]; |  | ||||||
| 		c[3] = c[1] & 0x1f; |  | ||||||
| 		c[2] = 0; |  | ||||||
| 		c[1] &= 0xe0; |  | ||||||
| 		c[0] += (READ_10 - READ_6); |  | ||||||
| 		scsi_req(rq)->cmd_len = 10; |  | ||||||
| 		return BLKPREP_OK; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/*
 |  | ||||||
| 	 * it's silly to pretend we understand 6-byte sense commands, just |  | ||||||
| 	 * reject with ILLEGAL_REQUEST and the caller should take the |  | ||||||
| 	 * appropriate action |  | ||||||
| 	 */ |  | ||||||
| 	if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { |  | ||||||
| 		scsi_req(rq)->result = ILLEGAL_REQUEST; |  | ||||||
| 		return BLKPREP_KILL; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return BLKPREP_OK; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int ide_cdrom_prep_fn(struct request_queue *q, struct request *rq) |  | ||||||
| { |  | ||||||
| 	if (!blk_rq_is_passthrough(rq)) |  | ||||||
| 		return ide_cdrom_prep_fs(q, rq); |  | ||||||
| 	else if (blk_rq_is_scsi(rq)) |  | ||||||
| 		return ide_cdrom_prep_pc(rq); |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct cd_list_entry { | struct cd_list_entry { | ||||||
| 	const char	*id_model; | 	const char	*id_model; | ||||||
| 	const char	*id_firmware; | 	const char	*id_firmware; | ||||||
|  | @ -1508,7 +1521,7 @@ static int ide_cdrom_setup(ide_drive_t *drive) | ||||||
| 
 | 
 | ||||||
| 	ide_debug_log(IDE_DBG_PROBE, "enter"); | 	ide_debug_log(IDE_DBG_PROBE, "enter"); | ||||||
| 
 | 
 | ||||||
| 	blk_queue_prep_rq(q, ide_cdrom_prep_fn); | 	drive->prep_rq = ide_cdrom_prep_fn; | ||||||
| 	blk_queue_dma_alignment(q, 31); | 	blk_queue_dma_alignment(q, 31); | ||||||
| 	blk_queue_update_dma_pad(q, 15); | 	blk_queue_update_dma_pad(q, 15); | ||||||
| 
 | 
 | ||||||
|  | @ -1569,7 +1582,7 @@ static void ide_cd_release(struct device *dev) | ||||||
| 	if (devinfo->handle == drive) | 	if (devinfo->handle == drive) | ||||||
| 		unregister_cdrom(devinfo); | 		unregister_cdrom(devinfo); | ||||||
| 	drive->driver_data = NULL; | 	drive->driver_data = NULL; | ||||||
| 	blk_queue_prep_rq(drive->queue, NULL); | 	drive->prep_rq = NULL; | ||||||
| 	g->private_data = NULL; | 	g->private_data = NULL; | ||||||
| 	put_disk(g); | 	put_disk(g); | ||||||
| 	kfree(info); | 	kfree(info); | ||||||
|  |  | ||||||
|  | @ -427,9 +427,8 @@ static void ide_disk_unlock_native_capacity(ide_drive_t *drive) | ||||||
| 		drive->dev_flags |= IDE_DFLAG_NOHPA; /* disable HPA on resume */ | 		drive->dev_flags |= IDE_DFLAG_NOHPA; /* disable HPA on resume */ | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int idedisk_prep_fn(struct request_queue *q, struct request *rq) | static int idedisk_prep_fn(ide_drive_t *drive, struct request *rq) | ||||||
| { | { | ||||||
| 	ide_drive_t *drive = q->queuedata; |  | ||||||
| 	struct ide_cmd *cmd; | 	struct ide_cmd *cmd; | ||||||
| 
 | 
 | ||||||
| 	if (req_op(rq) != REQ_OP_FLUSH) | 	if (req_op(rq) != REQ_OP_FLUSH) | ||||||
|  | @ -548,7 +547,7 @@ static void update_flush(ide_drive_t *drive) | ||||||
| 
 | 
 | ||||||
| 		if (barrier) { | 		if (barrier) { | ||||||
| 			wc = true; | 			wc = true; | ||||||
| 			blk_queue_prep_rq(drive->queue, idedisk_prep_fn); | 			drive->prep_rq = idedisk_prep_fn; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -67,7 +67,15 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error, | ||||||
| 		ide_dma_on(drive); | 		ide_dma_on(drive); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return blk_end_request(rq, error, nr_bytes); | 	if (!blk_update_request(rq, error, nr_bytes)) { | ||||||
|  | 		if (rq == drive->sense_rq) | ||||||
|  | 			drive->sense_rq = NULL; | ||||||
|  | 
 | ||||||
|  | 		__blk_mq_end_request(rq, error); | ||||||
|  | 		return 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 1; | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(ide_end_rq); | EXPORT_SYMBOL_GPL(ide_end_rq); | ||||||
| 
 | 
 | ||||||
|  | @ -307,8 +315,6 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | ||||||
| { | { | ||||||
| 	ide_startstop_t startstop; | 	ide_startstop_t startstop; | ||||||
| 
 | 
 | ||||||
| 	BUG_ON(!(rq->rq_flags & RQF_STARTED)); |  | ||||||
| 
 |  | ||||||
| #ifdef DEBUG | #ifdef DEBUG | ||||||
| 	printk("%s: start_request: current=0x%08lx\n", | 	printk("%s: start_request: current=0x%08lx\n", | ||||||
| 		drive->hwif->name, (unsigned long) rq); | 		drive->hwif->name, (unsigned long) rq); | ||||||
|  | @ -320,6 +326,9 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | ||||||
| 		goto kill_rq; | 		goto kill_rq; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	if (drive->prep_rq && drive->prep_rq(drive, rq)) | ||||||
|  | 		return ide_stopped; | ||||||
|  | 
 | ||||||
| 	if (ata_pm_request(rq)) | 	if (ata_pm_request(rq)) | ||||||
| 		ide_check_pm_state(drive, rq); | 		ide_check_pm_state(drive, rq); | ||||||
| 
 | 
 | ||||||
|  | @ -430,44 +439,38 @@ static inline void ide_unlock_host(struct ide_host *host) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq) |  | ||||||
| { |  | ||||||
| 	if (rq) |  | ||||||
| 		blk_requeue_request(q, rq); |  | ||||||
| 	if (rq || blk_peek_request(q)) { |  | ||||||
| 		/* Use 3ms as that was the old plug delay */ |  | ||||||
| 		blk_delay_queue(q, 3); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) | void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) | ||||||
| { | { | ||||||
| 	struct request_queue *q = drive->queue; | 	struct request_queue *q = drive->queue; | ||||||
| 	unsigned long flags; |  | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(q->queue_lock, flags); | 	/* Use 3ms as that was the old plug delay */ | ||||||
| 	__ide_requeue_and_plug(q, rq); | 	if (rq) { | ||||||
| 	spin_unlock_irqrestore(q->queue_lock, flags); | 		blk_mq_requeue_request(rq, false); | ||||||
|  | 		blk_mq_delay_kick_requeue_list(q, 3); | ||||||
|  | 	} else | ||||||
|  | 		blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  * Issue a new request to a device. |  * Issue a new request to a device. | ||||||
|  */ |  */ | ||||||
| void do_ide_request(struct request_queue *q) | blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx, | ||||||
|  | 			  const struct blk_mq_queue_data *bd) | ||||||
| { | { | ||||||
| 	ide_drive_t	*drive = q->queuedata; | 	ide_drive_t	*drive = hctx->queue->queuedata; | ||||||
| 	ide_hwif_t	*hwif = drive->hwif; | 	ide_hwif_t	*hwif = drive->hwif; | ||||||
| 	struct ide_host *host = hwif->host; | 	struct ide_host *host = hwif->host; | ||||||
| 	struct request	*rq = NULL; | 	struct request	*rq = NULL; | ||||||
| 	ide_startstop_t	startstop; | 	ide_startstop_t	startstop; | ||||||
| 
 | 
 | ||||||
| 	spin_unlock_irq(q->queue_lock); |  | ||||||
| 
 |  | ||||||
| 	/* HLD do_request() callback might sleep, make sure it's okay */ | 	/* HLD do_request() callback might sleep, make sure it's okay */ | ||||||
| 	might_sleep(); | 	might_sleep(); | ||||||
| 
 | 
 | ||||||
| 	if (ide_lock_host(host, hwif)) | 	if (ide_lock_host(host, hwif)) | ||||||
| 		goto plug_device_2; | 		return BLK_STS_DEV_RESOURCE; | ||||||
|  | 
 | ||||||
|  | 	rq = bd->rq; | ||||||
|  | 	blk_mq_start_request(rq); | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irq(&hwif->lock); | 	spin_lock_irq(&hwif->lock); | ||||||
| 
 | 
 | ||||||
|  | @ -503,22 +506,17 @@ void do_ide_request(struct request_queue *q) | ||||||
| 		hwif->cur_dev = drive; | 		hwif->cur_dev = drive; | ||||||
| 		drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); | 		drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED); | ||||||
| 
 | 
 | ||||||
| 		spin_unlock_irq(&hwif->lock); |  | ||||||
| 		spin_lock_irq(q->queue_lock); |  | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * we know that the queue isn't empty, but this can happen | 		 * we know that the queue isn't empty, but this can happen | ||||||
| 		 * if the q->prep_rq_fn() decides to kill a request | 		 * if the q->prep_rq_fn() decides to kill a request | ||||||
| 		 */ | 		 */ | ||||||
| 		if (!rq) | 		if (!rq) { | ||||||
| 			rq = blk_fetch_request(drive->queue); | 			rq = bd->rq; | ||||||
| 
 |  | ||||||
| 		spin_unlock_irq(q->queue_lock); |  | ||||||
| 		spin_lock_irq(&hwif->lock); |  | ||||||
| 
 |  | ||||||
| 			if (!rq) { | 			if (!rq) { | ||||||
| 				ide_unlock_port(hwif); | 				ide_unlock_port(hwif); | ||||||
| 				goto out; | 				goto out; | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * Sanity: don't accept a request that isn't a PM request | 		 * Sanity: don't accept a request that isn't a PM request | ||||||
|  | @ -551,23 +549,24 @@ void do_ide_request(struct request_queue *q) | ||||||
| 		if (startstop == ide_stopped) { | 		if (startstop == ide_stopped) { | ||||||
| 			rq = hwif->rq; | 			rq = hwif->rq; | ||||||
| 			hwif->rq = NULL; | 			hwif->rq = NULL; | ||||||
|  | 			if (rq) | ||||||
| 				goto repeat; | 				goto repeat; | ||||||
|  | 			ide_unlock_port(hwif); | ||||||
|  | 			goto out; | ||||||
| 		} | 		} | ||||||
| 	} else | 	} else { | ||||||
| 		goto plug_device; | plug_device: | ||||||
|  | 		spin_unlock_irq(&hwif->lock); | ||||||
|  | 		ide_unlock_host(host); | ||||||
|  | 		ide_requeue_and_plug(drive, rq); | ||||||
|  | 		return BLK_STS_OK; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| out: | out: | ||||||
| 	spin_unlock_irq(&hwif->lock); | 	spin_unlock_irq(&hwif->lock); | ||||||
| 	if (rq == NULL) | 	if (rq == NULL) | ||||||
| 		ide_unlock_host(host); | 		ide_unlock_host(host); | ||||||
| 	spin_lock_irq(q->queue_lock); | 	return BLK_STS_OK; | ||||||
| 	return; |  | ||||||
| 
 |  | ||||||
| plug_device: |  | ||||||
| 	spin_unlock_irq(&hwif->lock); |  | ||||||
| 	ide_unlock_host(host); |  | ||||||
| plug_device_2: |  | ||||||
| 	spin_lock_irq(q->queue_lock); |  | ||||||
| 	__ide_requeue_and_plug(q, rq); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int drive_is_ready(ide_drive_t *drive) | static int drive_is_ready(ide_drive_t *drive) | ||||||
|  | @ -887,3 +886,16 @@ void ide_pad_transfer(ide_drive_t *drive, int write, int len) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(ide_pad_transfer); | EXPORT_SYMBOL_GPL(ide_pad_transfer); | ||||||
|  | 
 | ||||||
|  | void ide_insert_request_head(ide_drive_t *drive, struct request *rq) | ||||||
|  | { | ||||||
|  | 	ide_hwif_t *hwif = drive->hwif; | ||||||
|  | 	unsigned long flags; | ||||||
|  | 
 | ||||||
|  | 	spin_lock_irqsave(&hwif->lock, flags); | ||||||
|  | 	list_add_tail(&rq->queuelist, &drive->rq_list); | ||||||
|  | 	spin_unlock_irqrestore(&hwif->lock, flags); | ||||||
|  | 
 | ||||||
|  | 	kblockd_schedule_work(&drive->rq_work); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(ide_insert_request_head); | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) | ||||||
| 		spin_unlock_irq(&hwif->lock); | 		spin_unlock_irq(&hwif->lock); | ||||||
| 
 | 
 | ||||||
| 		if (start_queue) | 		if (start_queue) | ||||||
| 			blk_run_queue(q); | 			blk_mq_run_hw_queues(q, true); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	spin_unlock_irq(&hwif->lock); | 	spin_unlock_irq(&hwif->lock); | ||||||
|  | @ -54,7 +54,7 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) | ||||||
| 	scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS; | 	scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS; | ||||||
| 	scsi_req(rq)->cmd_len = 1; | 	scsi_req(rq)->cmd_len = 1; | ||||||
| 	ide_req(rq)->type = ATA_PRIV_MISC; | 	ide_req(rq)->type = ATA_PRIV_MISC; | ||||||
| 	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT); | 	ide_insert_request_head(drive, rq); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	return; | 	return; | ||||||
|  |  | ||||||
|  | @ -40,32 +40,20 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void ide_end_sync_rq(struct request *rq, blk_status_t error) |  | ||||||
| { |  | ||||||
| 	complete(rq->end_io_data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int ide_pm_execute_rq(struct request *rq) | static int ide_pm_execute_rq(struct request *rq) | ||||||
| { | { | ||||||
| 	struct request_queue *q = rq->q; | 	struct request_queue *q = rq->q; | ||||||
| 	DECLARE_COMPLETION_ONSTACK(wait); |  | ||||||
| 
 |  | ||||||
| 	rq->end_io_data = &wait; |  | ||||||
| 	rq->end_io = ide_end_sync_rq; |  | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irq(q->queue_lock); | 	spin_lock_irq(q->queue_lock); | ||||||
| 	if (unlikely(blk_queue_dying(q))) { | 	if (unlikely(blk_queue_dying(q))) { | ||||||
| 		rq->rq_flags |= RQF_QUIET; | 		rq->rq_flags |= RQF_QUIET; | ||||||
| 		scsi_req(rq)->result = -ENXIO; | 		scsi_req(rq)->result = -ENXIO; | ||||||
| 		__blk_end_request_all(rq, BLK_STS_OK); |  | ||||||
| 		spin_unlock_irq(q->queue_lock); | 		spin_unlock_irq(q->queue_lock); | ||||||
|  | 		blk_mq_end_request(rq, BLK_STS_OK); | ||||||
| 		return -ENXIO; | 		return -ENXIO; | ||||||
| 	} | 	} | ||||||
| 	__elv_add_request(q, rq, ELEVATOR_INSERT_FRONT); |  | ||||||
| 	__blk_run_queue_uncond(q); |  | ||||||
| 	spin_unlock_irq(q->queue_lock); | 	spin_unlock_irq(q->queue_lock); | ||||||
| 
 | 	blk_execute_rq(q, NULL, rq, true); | ||||||
| 	wait_for_completion_io(&wait); |  | ||||||
| 
 | 
 | ||||||
| 	return scsi_req(rq)->result ? -EIO : 0; | 	return scsi_req(rq)->result ? -EIO : 0; | ||||||
| } | } | ||||||
|  | @ -79,6 +67,8 @@ int generic_ide_resume(struct device *dev) | ||||||
| 	struct ide_pm_state rqpm; | 	struct ide_pm_state rqpm; | ||||||
| 	int err; | 	int err; | ||||||
| 
 | 
 | ||||||
|  | 	blk_mq_start_stopped_hw_queues(drive->queue, true); | ||||||
|  | 
 | ||||||
| 	if (ide_port_acpi(hwif)) { | 	if (ide_port_acpi(hwif)) { | ||||||
| 		/* call ACPI _PS0 / _STM only once */ | 		/* call ACPI _PS0 / _STM only once */ | ||||||
| 		if ((drive->dn & 1) == 0 || pair == NULL) { | 		if ((drive->dn & 1) == 0 || pair == NULL) { | ||||||
|  | @ -226,15 +216,14 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) | ||||||
| #endif | #endif | ||||||
| 	spin_lock_irqsave(q->queue_lock, flags); | 	spin_lock_irqsave(q->queue_lock, flags); | ||||||
| 	if (ide_req(rq)->type == ATA_PRIV_PM_SUSPEND) | 	if (ide_req(rq)->type == ATA_PRIV_PM_SUSPEND) | ||||||
| 		blk_stop_queue(q); | 		blk_mq_stop_hw_queues(q); | ||||||
| 	else | 	else | ||||||
| 		drive->dev_flags &= ~IDE_DFLAG_BLOCKED; | 		drive->dev_flags &= ~IDE_DFLAG_BLOCKED; | ||||||
| 	spin_unlock_irqrestore(q->queue_lock, flags); | 	spin_unlock_irqrestore(q->queue_lock, flags); | ||||||
| 
 | 
 | ||||||
| 	drive->hwif->rq = NULL; | 	drive->hwif->rq = NULL; | ||||||
| 
 | 
 | ||||||
| 	if (blk_end_request(rq, BLK_STS_OK, 0)) | 	blk_mq_end_request(rq, BLK_STS_OK); | ||||||
| 		BUG(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | ||||||
|  | @ -260,7 +249,6 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | ||||||
| 		ide_hwif_t *hwif = drive->hwif; | 		ide_hwif_t *hwif = drive->hwif; | ||||||
| 		const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 		const struct ide_tp_ops *tp_ops = hwif->tp_ops; | ||||||
| 		struct request_queue *q = drive->queue; | 		struct request_queue *q = drive->queue; | ||||||
| 		unsigned long flags; |  | ||||||
| 		int rc; | 		int rc; | ||||||
| #ifdef DEBUG_PM | #ifdef DEBUG_PM | ||||||
| 		printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); | 		printk("%s: Wakeup request inited, waiting for !BSY...\n", drive->name); | ||||||
|  | @ -274,8 +262,6 @@ void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | ||||||
| 		if (rc) | 		if (rc) | ||||||
| 			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); | 			printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name); | ||||||
| 
 | 
 | ||||||
| 		spin_lock_irqsave(q->queue_lock, flags); | 		blk_mq_start_hw_queues(q); | ||||||
| 		blk_start_queue(q); |  | ||||||
| 		spin_unlock_irqrestore(q->queue_lock, flags); |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -750,6 +750,11 @@ static void ide_initialize_rq(struct request *rq) | ||||||
| 	req->sreq.sense = req->sense; | 	req->sreq.sense = req->sense; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const struct blk_mq_ops ide_mq_ops = { | ||||||
|  | 	.queue_rq		= ide_queue_rq, | ||||||
|  | 	.initialize_rq_fn	= ide_initialize_rq, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| /*
 | /*
 | ||||||
|  * init request queue |  * init request queue | ||||||
|  */ |  */ | ||||||
|  | @ -759,6 +764,7 @@ static int ide_init_queue(ide_drive_t *drive) | ||||||
| 	ide_hwif_t *hwif = drive->hwif; | 	ide_hwif_t *hwif = drive->hwif; | ||||||
| 	int max_sectors = 256; | 	int max_sectors = 256; | ||||||
| 	int max_sg_entries = PRD_ENTRIES; | 	int max_sg_entries = PRD_ENTRIES; | ||||||
|  | 	struct blk_mq_tag_set *set; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 *	Our default set up assumes the normal IDE case, | 	 *	Our default set up assumes the normal IDE case, | ||||||
|  | @ -767,19 +773,26 @@ static int ide_init_queue(ide_drive_t *drive) | ||||||
| 	 *	limits and LBA48 we could raise it but as yet | 	 *	limits and LBA48 we could raise it but as yet | ||||||
| 	 *	do not. | 	 *	do not. | ||||||
| 	 */ | 	 */ | ||||||
| 	q = blk_alloc_queue_node(GFP_KERNEL, hwif_to_node(hwif), NULL); | 
 | ||||||
| 	if (!q) | 	set = &drive->tag_set; | ||||||
|  | 	set->ops = &ide_mq_ops; | ||||||
|  | 	set->nr_hw_queues = 1; | ||||||
|  | 	set->queue_depth = 32; | ||||||
|  | 	set->reserved_tags = 1; | ||||||
|  | 	set->cmd_size = sizeof(struct ide_request); | ||||||
|  | 	set->numa_node = hwif_to_node(hwif); | ||||||
|  | 	set->flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; | ||||||
|  | 	if (blk_mq_alloc_tag_set(set)) | ||||||
| 		return 1; | 		return 1; | ||||||
| 
 | 
 | ||||||
| 	q->request_fn = do_ide_request; | 	q = blk_mq_init_queue(set); | ||||||
| 	q->initialize_rq_fn = ide_initialize_rq; | 	if (IS_ERR(q)) { | ||||||
| 	q->cmd_size = sizeof(struct ide_request); | 		blk_mq_free_tag_set(set); | ||||||
| 	blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, q); |  | ||||||
| 	if (blk_init_allocated_queue(q) < 0) { |  | ||||||
| 		blk_cleanup_queue(q); |  | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	blk_queue_flag_set(QUEUE_FLAG_SCSI_PASSTHROUGH, q); | ||||||
|  | 
 | ||||||
| 	q->queuedata = drive; | 	q->queuedata = drive; | ||||||
| 	blk_queue_segment_boundary(q, 0xffff); | 	blk_queue_segment_boundary(q, 0xffff); | ||||||
| 
 | 
 | ||||||
|  | @ -965,8 +978,12 @@ static void drive_release_dev (struct device *dev) | ||||||
| 
 | 
 | ||||||
| 	ide_proc_unregister_device(drive); | 	ide_proc_unregister_device(drive); | ||||||
| 
 | 
 | ||||||
|  | 	if (drive->sense_rq) | ||||||
|  | 		blk_mq_free_request(drive->sense_rq); | ||||||
|  | 
 | ||||||
| 	blk_cleanup_queue(drive->queue); | 	blk_cleanup_queue(drive->queue); | ||||||
| 	drive->queue = NULL; | 	drive->queue = NULL; | ||||||
|  | 	blk_mq_free_tag_set(&drive->tag_set); | ||||||
| 
 | 
 | ||||||
| 	drive->dev_flags &= ~IDE_DFLAG_PRESENT; | 	drive->dev_flags &= ~IDE_DFLAG_PRESENT; | ||||||
| 
 | 
 | ||||||
|  | @ -1133,6 +1150,28 @@ static void ide_port_cable_detect(ide_hwif_t *hwif) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /*
 | ||||||
|  |  * Deferred request list insertion handler | ||||||
|  |  */ | ||||||
|  | static void drive_rq_insert_work(struct work_struct *work) | ||||||
|  | { | ||||||
|  | 	ide_drive_t *drive = container_of(work, ide_drive_t, rq_work); | ||||||
|  | 	ide_hwif_t *hwif = drive->hwif; | ||||||
|  | 	struct request *rq; | ||||||
|  | 	LIST_HEAD(list); | ||||||
|  | 
 | ||||||
|  | 	spin_lock_irq(&hwif->lock); | ||||||
|  | 	if (!list_empty(&drive->rq_list)) | ||||||
|  | 		list_splice_init(&drive->rq_list, &list); | ||||||
|  | 	spin_unlock_irq(&hwif->lock); | ||||||
|  | 
 | ||||||
|  | 	while (!list_empty(&list)) { | ||||||
|  | 		rq = list_first_entry(&list, struct request, queuelist); | ||||||
|  | 		list_del_init(&rq->queuelist); | ||||||
|  | 		blk_execute_rq_nowait(drive->queue, rq->rq_disk, rq, true, NULL); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static const u8 ide_hwif_to_major[] = | static const u8 ide_hwif_to_major[] = | ||||||
| 	{ IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, | 	{ IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, | ||||||
| 	  IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; | 	  IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR, IDE8_MAJOR, IDE9_MAJOR }; | ||||||
|  | @ -1145,12 +1184,10 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) | ||||||
| 	ide_port_for_each_dev(i, drive, hwif) { | 	ide_port_for_each_dev(i, drive, hwif) { | ||||||
| 		u8 j = (hwif->index * MAX_DRIVES) + i; | 		u8 j = (hwif->index * MAX_DRIVES) + i; | ||||||
| 		u16 *saved_id = drive->id; | 		u16 *saved_id = drive->id; | ||||||
| 		struct request *saved_sense_rq = drive->sense_rq; |  | ||||||
| 
 | 
 | ||||||
| 		memset(drive, 0, sizeof(*drive)); | 		memset(drive, 0, sizeof(*drive)); | ||||||
| 		memset(saved_id, 0, SECTOR_SIZE); | 		memset(saved_id, 0, SECTOR_SIZE); | ||||||
| 		drive->id = saved_id; | 		drive->id = saved_id; | ||||||
| 		drive->sense_rq = saved_sense_rq; |  | ||||||
| 
 | 
 | ||||||
| 		drive->media			= ide_disk; | 		drive->media			= ide_disk; | ||||||
| 		drive->select			= (i << 4) | ATA_DEVICE_OBS; | 		drive->select			= (i << 4) | ATA_DEVICE_OBS; | ||||||
|  | @ -1166,6 +1203,9 @@ static void ide_port_init_devices_data(ide_hwif_t *hwif) | ||||||
| 
 | 
 | ||||||
| 		INIT_LIST_HEAD(&drive->list); | 		INIT_LIST_HEAD(&drive->list); | ||||||
| 		init_completion(&drive->gendev_rel_comp); | 		init_completion(&drive->gendev_rel_comp); | ||||||
|  | 
 | ||||||
|  | 		INIT_WORK(&drive->rq_work, drive_rq_insert_work); | ||||||
|  | 		INIT_LIST_HEAD(&drive->rq_list); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1255,7 +1295,6 @@ static void ide_port_free_devices(ide_hwif_t *hwif) | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	ide_port_for_each_dev(i, drive, hwif) { | 	ide_port_for_each_dev(i, drive, hwif) { | ||||||
| 		kfree(drive->sense_rq); |  | ||||||
| 		kfree(drive->id); | 		kfree(drive->id); | ||||||
| 		kfree(drive); | 		kfree(drive); | ||||||
| 	} | 	} | ||||||
|  | @ -1283,17 +1322,10 @@ static int ide_port_alloc_devices(ide_hwif_t *hwif, int node) | ||||||
| 		if (drive->id == NULL) | 		if (drive->id == NULL) | ||||||
| 			goto out_free_drive; | 			goto out_free_drive; | ||||||
| 
 | 
 | ||||||
| 		drive->sense_rq = kmalloc(sizeof(struct request) + |  | ||||||
| 				sizeof(struct ide_request), GFP_KERNEL); |  | ||||||
| 		if (!drive->sense_rq) |  | ||||||
| 			goto out_free_id; |  | ||||||
| 
 |  | ||||||
| 		hwif->devices[i] = drive; | 		hwif->devices[i] = drive; | ||||||
| 	} | 	} | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| out_free_id: |  | ||||||
| 	kfree(drive->id); |  | ||||||
| out_free_drive: | out_free_drive: | ||||||
| 	kfree(drive); | 	kfree(drive); | ||||||
| out_nomem: | out_nomem: | ||||||
|  |  | ||||||
|  | @ -10,7 +10,7 @@ | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| #include <linux/ioport.h> | #include <linux/ioport.h> | ||||||
| #include <linux/ata.h> | #include <linux/ata.h> | ||||||
| #include <linux/blkdev.h> | #include <linux/blk-mq.h> | ||||||
| #include <linux/proc_fs.h> | #include <linux/proc_fs.h> | ||||||
| #include <linux/interrupt.h> | #include <linux/interrupt.h> | ||||||
| #include <linux/bitops.h> | #include <linux/bitops.h> | ||||||
|  | @ -529,6 +529,10 @@ struct ide_drive_s { | ||||||
| 
 | 
 | ||||||
| 	struct request_queue	*queue;	/* request queue */ | 	struct request_queue	*queue;	/* request queue */ | ||||||
| 
 | 
 | ||||||
|  | 	int (*prep_rq)(struct ide_drive_s *, struct request *); | ||||||
|  | 
 | ||||||
|  | 	struct blk_mq_tag_set	tag_set; | ||||||
|  | 
 | ||||||
| 	struct request		*rq;	/* current request */ | 	struct request		*rq;	/* current request */ | ||||||
| 	void		*driver_data;	/* extra driver data */ | 	void		*driver_data;	/* extra driver data */ | ||||||
| 	u16			*id;	/* identification info */ | 	u16			*id;	/* identification info */ | ||||||
|  | @ -612,6 +616,10 @@ struct ide_drive_s { | ||||||
| 	bool sense_rq_armed; | 	bool sense_rq_armed; | ||||||
| 	struct request *sense_rq; | 	struct request *sense_rq; | ||||||
| 	struct request_sense sense_data; | 	struct request_sense sense_data; | ||||||
|  | 
 | ||||||
|  | 	/* async sense insertion */ | ||||||
|  | 	struct work_struct rq_work; | ||||||
|  | 	struct list_head rq_list; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| typedef struct ide_drive_s ide_drive_t; | typedef struct ide_drive_s ide_drive_t; | ||||||
|  | @ -1089,6 +1097,7 @@ extern int ide_pci_clk; | ||||||
| 
 | 
 | ||||||
| int ide_end_rq(ide_drive_t *, struct request *, blk_status_t, unsigned int); | int ide_end_rq(ide_drive_t *, struct request *, blk_status_t, unsigned int); | ||||||
| void ide_kill_rq(ide_drive_t *, struct request *); | void ide_kill_rq(ide_drive_t *, struct request *); | ||||||
|  | void ide_insert_request_head(ide_drive_t *, struct request *); | ||||||
| 
 | 
 | ||||||
| void __ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int); | void __ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int); | ||||||
| void ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int); | void ide_set_handler(ide_drive_t *, ide_handler_t *, unsigned int); | ||||||
|  | @ -1208,7 +1217,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout); | ||||||
| 
 | 
 | ||||||
| extern void ide_timer_expiry(struct timer_list *t); | extern void ide_timer_expiry(struct timer_list *t); | ||||||
| extern irqreturn_t ide_intr(int irq, void *dev_id); | extern irqreturn_t ide_intr(int irq, void *dev_id); | ||||||
| extern void do_ide_request(struct request_queue *); | extern blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *); | ||||||
| extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq); | extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq); | ||||||
| 
 | 
 | ||||||
| void ide_init_disk(struct gendisk *, ide_drive_t *); | void ide_init_disk(struct gendisk *, ide_drive_t *); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Jens Axboe
						Jens Axboe