diff options
Diffstat (limited to 'drivers/scsi/ps3rom.c')
| -rw-r--r-- | drivers/scsi/ps3rom.c | 125 |
1 files changed, 26 insertions, 99 deletions
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index fad6cb5cba2..e6e2a30493e 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c @@ -20,12 +20,15 @@ #include <linux/cdrom.h> #include <linux/highmem.h> +#include <linux/module.h> +#include <linux/slab.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_dbg.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> +#include <scsi/scsi_eh.h> #include <asm/lv1call.h> #include <asm/ps3stor.h> @@ -90,78 +93,6 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev) return 0; } -/* - * copy data from device into scatter/gather buffer - */ -static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) -{ - int k, req_len, act_len, len, active; - void *kaddr; - struct scatterlist *sgpnt; - unsigned int buflen; - - buflen = scsi_bufflen(cmd); - if (!buflen) - return 0; - - if (!scsi_sglist(cmd)) - return -1; - - active = 1; - req_len = act_len = 0; - scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { - if (active) { - kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0); - len = sgpnt->length; - if ((req_len + len) > buflen) { - active = 0; - len = buflen - req_len; - } - memcpy(kaddr + sgpnt->offset, buf + req_len, len); - flush_kernel_dcache_page(sg_page(sgpnt)); - kunmap_atomic(kaddr, KM_IRQ0); - act_len += len; - } - req_len += sgpnt->length; - } - scsi_set_resid(cmd, buflen - act_len); - return 0; -} - -/* - * copy data from scatter/gather into device's buffer - */ -static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf) -{ - int k, req_len, len, fin; - void *kaddr; - struct scatterlist *sgpnt; - unsigned int buflen; - - buflen = scsi_bufflen(cmd); - if (!buflen) - return 0; - - if (!scsi_sglist(cmd)) - return -1; - - req_len = fin = 0; - scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { - kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0); - len = sgpnt->length; - if ((req_len + len) > buflen) { - len = buflen - req_len; - fin = 1; - } - memcpy(buf + req_len, kaddr + sgpnt->offset, len); - kunmap_atomic(kaddr, KM_IRQ0); - if (fin) - return req_len + len; - req_len += sgpnt->length; - } - return req_len; -} - static int ps3rom_atapi_request(struct ps3_storage_device *dev, struct scsi_cmnd *cmd) { @@ -195,9 +126,7 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev, else atapi_cmnd.proto = PIO_DATA_OUT_PROTO; atapi_cmnd.in_out = DIR_WRITE; - res = fetch_to_dev_buffer(cmd, dev->bounce_buf); - if (res < 0) - return DID_ERROR << 16; + scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size); break; default: @@ -269,9 +198,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev, dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n", __func__, __LINE__, sectors, start_sector); - res = fetch_to_dev_buffer(cmd, dev->bounce_buf); - if (res < 0) - return DID_ERROR << 16; + scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size); res = lv1_storage_write(dev->sbd.dev_id, dev->regions[dev->region_idx].id, start_sector, @@ -285,7 +212,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev, return 0; } -static int ps3rom_queuecommand(struct scsi_cmnd *cmd, +static int ps3rom_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { struct ps3rom_private *priv = shost_priv(cmd->device->host); @@ -334,6 +261,8 @@ static int ps3rom_queuecommand(struct scsi_cmnd *cmd, return 0; } +static DEF_SCSI_QCMD(ps3rom_queuecommand) + static int decode_lv1_status(u64 status, unsigned char *sense_key, unsigned char *asc, unsigned char *ascq) { @@ -365,27 +294,29 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data) if (tag != dev->tag) dev_err(&dev->sbd.core, - "%s:%u: tag mismatch, got %lx, expected %lx\n", + "%s:%u: tag mismatch, got %llx, expected %llx\n", __func__, __LINE__, tag, dev->tag); if (res) { - dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n", + dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n", __func__, __LINE__, res, status); return IRQ_HANDLED; } - host = dev->sbd.core.driver_data; + host = ps3_system_bus_get_drvdata(&dev->sbd); priv = shost_priv(host); cmd = priv->curr_cmd; if (!status) { /* OK, completed */ if (cmd->sc_data_direction == DMA_FROM_DEVICE) { - res = fill_from_dev_buffer(cmd, dev->bounce_buf); - if (res) { - cmd->result = DID_ERROR << 16; - goto done; - } + int len; + + len = scsi_sg_copy_from_buffer(cmd, + dev->bounce_buf, + dev->bounce_size); + + scsi_set_resid(cmd, scsi_bufflen(cmd) - len); } cmd->result = DID_OK << 16; goto done; @@ -404,11 +335,7 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data) goto done; } - cmd->sense_buffer[0] = 0x70; - cmd->sense_buffer[2] = sense_key; - cmd->sense_buffer[7] = 16 - 6; - cmd->sense_buffer[12] = asc; - cmd->sense_buffer[13] = ascq; + scsi_build_sense_buffer(0, cmd->sense_buffer, sense_key, asc, ascq); cmd->result = SAM_STAT_CHECK_CONDITION; done: @@ -427,12 +354,12 @@ static struct scsi_host_template ps3rom_host_template = { .cmd_per_lun = 1, .emulated = 1, /* only sg driver uses this */ .max_sectors = PS3ROM_MAX_SECTORS, - .use_clustering = DISABLE_CLUSTERING, + .use_clustering = ENABLE_CLUSTERING, .module = THIS_MODULE, }; -static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev) +static int ps3rom_probe(struct ps3_system_bus_device *_dev) { struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); int error; @@ -441,7 +368,7 @@ static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev) if (dev->blk_size != CD_FRAMESIZE) { dev_err(&dev->sbd.core, - "%s:%u: cannot handle block size %lu\n", __func__, + "%s:%u: cannot handle block size %llu\n", __func__, __LINE__, dev->blk_size); return -EINVAL; } @@ -464,7 +391,7 @@ static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev) } priv = shost_priv(host); - dev->sbd.core.driver_data = host; + ps3_system_bus_set_drvdata(&dev->sbd, host); priv->dev = dev; /* One device/LUN per SCSI bus */ @@ -484,7 +411,7 @@ static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev) fail_host_put: scsi_host_put(host); - dev->sbd.core.driver_data = NULL; + ps3_system_bus_set_drvdata(&dev->sbd, NULL); fail_teardown: ps3stor_teardown(dev); fail_free_bounce: @@ -495,12 +422,12 @@ fail_free_bounce: static int ps3rom_remove(struct ps3_system_bus_device *_dev) { struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); - struct Scsi_Host *host = dev->sbd.core.driver_data; + struct Scsi_Host *host = ps3_system_bus_get_drvdata(&dev->sbd); scsi_remove_host(host); ps3stor_teardown(dev); scsi_host_put(host); - dev->sbd.core.driver_data = NULL; + ps3_system_bus_set_drvdata(&dev->sbd, NULL); kfree(dev->bounce_buf); return 0; } |
