diff options
Diffstat (limited to 'drivers/scsi/ps3rom.c')
-rw-r--r-- | drivers/scsi/ps3rom.c | 101 |
1 files changed, 12 insertions, 89 deletions
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index fad6cb5cba28..ce48e2d0193c 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <scsi/scsi_dbg.h> | 26 | #include <scsi/scsi_dbg.h> |
27 | #include <scsi/scsi_device.h> | 27 | #include <scsi/scsi_device.h> |
28 | #include <scsi/scsi_host.h> | 28 | #include <scsi/scsi_host.h> |
29 | #include <scsi/scsi_eh.h> | ||
29 | 30 | ||
30 | #include <asm/lv1call.h> | 31 | #include <asm/lv1call.h> |
31 | #include <asm/ps3stor.h> | 32 | #include <asm/ps3stor.h> |
@@ -90,78 +91,6 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev) | |||
90 | return 0; | 91 | return 0; |
91 | } | 92 | } |
92 | 93 | ||
93 | /* | ||
94 | * copy data from device into scatter/gather buffer | ||
95 | */ | ||
96 | static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) | ||
97 | { | ||
98 | int k, req_len, act_len, len, active; | ||
99 | void *kaddr; | ||
100 | struct scatterlist *sgpnt; | ||
101 | unsigned int buflen; | ||
102 | |||
103 | buflen = scsi_bufflen(cmd); | ||
104 | if (!buflen) | ||
105 | return 0; | ||
106 | |||
107 | if (!scsi_sglist(cmd)) | ||
108 | return -1; | ||
109 | |||
110 | active = 1; | ||
111 | req_len = act_len = 0; | ||
112 | scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { | ||
113 | if (active) { | ||
114 | kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0); | ||
115 | len = sgpnt->length; | ||
116 | if ((req_len + len) > buflen) { | ||
117 | active = 0; | ||
118 | len = buflen - req_len; | ||
119 | } | ||
120 | memcpy(kaddr + sgpnt->offset, buf + req_len, len); | ||
121 | flush_kernel_dcache_page(sg_page(sgpnt)); | ||
122 | kunmap_atomic(kaddr, KM_IRQ0); | ||
123 | act_len += len; | ||
124 | } | ||
125 | req_len += sgpnt->length; | ||
126 | } | ||
127 | scsi_set_resid(cmd, buflen - act_len); | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * copy data from scatter/gather into device's buffer | ||
133 | */ | ||
134 | static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf) | ||
135 | { | ||
136 | int k, req_len, len, fin; | ||
137 | void *kaddr; | ||
138 | struct scatterlist *sgpnt; | ||
139 | unsigned int buflen; | ||
140 | |||
141 | buflen = scsi_bufflen(cmd); | ||
142 | if (!buflen) | ||
143 | return 0; | ||
144 | |||
145 | if (!scsi_sglist(cmd)) | ||
146 | return -1; | ||
147 | |||
148 | req_len = fin = 0; | ||
149 | scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { | ||
150 | kaddr = kmap_atomic(sg_page(sgpnt), KM_IRQ0); | ||
151 | len = sgpnt->length; | ||
152 | if ((req_len + len) > buflen) { | ||
153 | len = buflen - req_len; | ||
154 | fin = 1; | ||
155 | } | ||
156 | memcpy(buf + req_len, kaddr + sgpnt->offset, len); | ||
157 | kunmap_atomic(kaddr, KM_IRQ0); | ||
158 | if (fin) | ||
159 | return req_len + len; | ||
160 | req_len += sgpnt->length; | ||
161 | } | ||
162 | return req_len; | ||
163 | } | ||
164 | |||
165 | static int ps3rom_atapi_request(struct ps3_storage_device *dev, | 94 | static int ps3rom_atapi_request(struct ps3_storage_device *dev, |
166 | struct scsi_cmnd *cmd) | 95 | struct scsi_cmnd *cmd) |
167 | { | 96 | { |
@@ -195,9 +124,7 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev, | |||
195 | else | 124 | else |
196 | atapi_cmnd.proto = PIO_DATA_OUT_PROTO; | 125 | atapi_cmnd.proto = PIO_DATA_OUT_PROTO; |
197 | atapi_cmnd.in_out = DIR_WRITE; | 126 | atapi_cmnd.in_out = DIR_WRITE; |
198 | res = fetch_to_dev_buffer(cmd, dev->bounce_buf); | 127 | scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size); |
199 | if (res < 0) | ||
200 | return DID_ERROR << 16; | ||
201 | break; | 128 | break; |
202 | 129 | ||
203 | default: | 130 | default: |
@@ -269,9 +196,7 @@ static int ps3rom_write_request(struct ps3_storage_device *dev, | |||
269 | dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n", | 196 | dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n", |
270 | __func__, __LINE__, sectors, start_sector); | 197 | __func__, __LINE__, sectors, start_sector); |
271 | 198 | ||
272 | res = fetch_to_dev_buffer(cmd, dev->bounce_buf); | 199 | scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size); |
273 | if (res < 0) | ||
274 | return DID_ERROR << 16; | ||
275 | 200 | ||
276 | res = lv1_storage_write(dev->sbd.dev_id, | 201 | res = lv1_storage_write(dev->sbd.dev_id, |
277 | dev->regions[dev->region_idx].id, start_sector, | 202 | dev->regions[dev->region_idx].id, start_sector, |
@@ -381,11 +306,13 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data) | |||
381 | if (!status) { | 306 | if (!status) { |
382 | /* OK, completed */ | 307 | /* OK, completed */ |
383 | if (cmd->sc_data_direction == DMA_FROM_DEVICE) { | 308 | if (cmd->sc_data_direction == DMA_FROM_DEVICE) { |
384 | res = fill_from_dev_buffer(cmd, dev->bounce_buf); | 309 | int len; |
385 | if (res) { | 310 | |
386 | cmd->result = DID_ERROR << 16; | 311 | len = scsi_sg_copy_from_buffer(cmd, |
387 | goto done; | 312 | dev->bounce_buf, |
388 | } | 313 | dev->bounce_size); |
314 | |||
315 | scsi_set_resid(cmd, scsi_bufflen(cmd) - len); | ||
389 | } | 316 | } |
390 | cmd->result = DID_OK << 16; | 317 | cmd->result = DID_OK << 16; |
391 | goto done; | 318 | goto done; |
@@ -404,11 +331,7 @@ static irqreturn_t ps3rom_interrupt(int irq, void *data) | |||
404 | goto done; | 331 | goto done; |
405 | } | 332 | } |
406 | 333 | ||
407 | cmd->sense_buffer[0] = 0x70; | 334 | scsi_build_sense_buffer(0, cmd->sense_buffer, sense_key, asc, ascq); |
408 | cmd->sense_buffer[2] = sense_key; | ||
409 | cmd->sense_buffer[7] = 16 - 6; | ||
410 | cmd->sense_buffer[12] = asc; | ||
411 | cmd->sense_buffer[13] = ascq; | ||
412 | cmd->result = SAM_STAT_CHECK_CONDITION; | 335 | cmd->result = SAM_STAT_CHECK_CONDITION; |
413 | 336 | ||
414 | done: | 337 | done: |
@@ -427,7 +350,7 @@ static struct scsi_host_template ps3rom_host_template = { | |||
427 | .cmd_per_lun = 1, | 350 | .cmd_per_lun = 1, |
428 | .emulated = 1, /* only sg driver uses this */ | 351 | .emulated = 1, /* only sg driver uses this */ |
429 | .max_sectors = PS3ROM_MAX_SECTORS, | 352 | .max_sectors = PS3ROM_MAX_SECTORS, |
430 | .use_clustering = DISABLE_CLUSTERING, | 353 | .use_clustering = ENABLE_CLUSTERING, |
431 | .module = THIS_MODULE, | 354 | .module = THIS_MODULE, |
432 | }; | 355 | }; |
433 | 356 | ||