diff options
| author | Boaz Harrosh <bharrosh@panasas.com> | 2007-10-02 17:18:03 -0400 |
|---|---|---|
| committer | James Bottomley <jejb@mulgrave.localdomain> | 2007-10-12 14:56:13 -0400 |
| commit | 3892d88ae6fb186ff6205f764213b556d70800b0 (patch) | |
| tree | 5435ca13a3d70569582887813a92f49a0ac7ca7c | |
| parent | f842b64e0ffbcc9ce48a3bf799d0b005094107c1 (diff) | |
[SCSI] gdth: !use_sg cleanup and use of scsi accessors
gdth_execute() will issue an internal, none scsi-standard commands
onto __gdth_queuecommand(). Since it is not recommended to set
struct scsi_cmnd IO members in llds, gdth now uses internal IO
members for IO. In the case of gdth_execute() these members will be
set properly. In case the command was issued from scsi-ml
(by gdth_queuecommand) they will be set from scsi IO accessors.
* define gdth IO accessors and use them throughout the driver.
* use an sg-of-one in gdth_execute() and fix gdth_special_cmd()
accordingly.
* Clean the not use_sg code path and company
Signed-off-by Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
| -rw-r--r-- | drivers/scsi/gdth.c | 228 | ||||
| -rw-r--r-- | drivers/scsi/gdth.h | 7 |
2 files changed, 109 insertions, 126 deletions
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index a68004b0d90b..0153d1d8b12e 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c | |||
| @@ -85,11 +85,11 @@ | |||
| 85 | 85 | ||
| 86 | /* The meaning of the Scsi_Pointer members in this driver is as follows: | 86 | /* The meaning of the Scsi_Pointer members in this driver is as follows: |
| 87 | * ptr: Chaining | 87 | * ptr: Chaining |
| 88 | * this_residual: unused | 88 | * this_residual: gdth_bufflen |
| 89 | * buffer: unused | 89 | * buffer: gdth_sglist |
| 90 | * dma_handle: will drop in !use_sg patch. | 90 | * dma_handle: unused |
| 91 | * buffers_residual: unused | 91 | * buffers_residual: gdth_sg_count |
| 92 | * Status: DMA mem. mappings (FIXME: drop in !use_sg patch.) | 92 | * Status: unused |
| 93 | * Message: unused | 93 | * Message: unused |
| 94 | * have_data_in: unused | 94 | * have_data_in: unused |
| 95 | * sent_command: unused | 95 | * sent_command: unused |
| @@ -132,6 +132,7 @@ | |||
| 132 | #include <asm/uaccess.h> | 132 | #include <asm/uaccess.h> |
| 133 | #include <linux/spinlock.h> | 133 | #include <linux/spinlock.h> |
| 134 | #include <linux/blkdev.h> | 134 | #include <linux/blkdev.h> |
| 135 | #include <linux/scatterlist.h> | ||
| 135 | 136 | ||
| 136 | #include "scsi.h" | 137 | #include "scsi.h" |
| 137 | #include <scsi/scsi_host.h> | 138 | #include <scsi/scsi_host.h> |
| @@ -159,7 +160,7 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application, | |||
| 159 | static void gdth_clear_events(void); | 160 | static void gdth_clear_events(void); |
| 160 | 161 | ||
| 161 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | 162 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, |
| 162 | char *buffer,ushort count); | 163 | char *buffer, ushort count, int to_buffer); |
| 163 | static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); | 164 | static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); |
| 164 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); | 165 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); |
| 165 | 166 | ||
| @@ -373,6 +374,47 @@ static const struct file_operations gdth_fops = { | |||
| 373 | .release = gdth_close, | 374 | .release = gdth_close, |
| 374 | }; | 375 | }; |
| 375 | 376 | ||
| 377 | /* | ||
| 378 | * gdth scsi_command access wrappers. | ||
| 379 | * below 6 functions are used throughout the driver to access scsi_command's | ||
| 380 | * io parameters. The reason we do not use the regular accessors from | ||
| 381 | * scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for | ||
| 382 | * llds to directly set scsi_cmnd's IO members. This driver will use SCp | ||
| 383 | * members for IO parameters, and will copy scsi_cmnd's members to Scp | ||
| 384 | * members in queuecommand. For internal commands through gdth_execute() | ||
| 385 | * SCp's members will be set directly. | ||
| 386 | */ | ||
| 387 | static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd) | ||
| 388 | { | ||
| 389 | return (unsigned)cmd->SCp.this_residual; | ||
| 390 | } | ||
| 391 | |||
| 392 | static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen) | ||
| 393 | { | ||
| 394 | cmd->SCp.this_residual = bufflen; | ||
| 395 | } | ||
| 396 | |||
| 397 | static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd) | ||
| 398 | { | ||
| 399 | return (unsigned)cmd->SCp.buffers_residual; | ||
| 400 | } | ||
| 401 | |||
| 402 | static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count) | ||
| 403 | { | ||
| 404 | cmd->SCp.buffers_residual = sg_count; | ||
| 405 | } | ||
| 406 | |||
| 407 | static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd) | ||
| 408 | { | ||
| 409 | return cmd->SCp.buffer; | ||
| 410 | } | ||
| 411 | |||
| 412 | static inline void gdth_set_sglist(struct scsi_cmnd *cmd, | ||
| 413 | struct scatterlist *sglist) | ||
| 414 | { | ||
| 415 | cmd->SCp.buffer = sglist; | ||
| 416 | } | ||
| 417 | |||
| 376 | #include "gdth_proc.h" | 418 | #include "gdth_proc.h" |
| 377 | #include "gdth_proc.c" | 419 | #include "gdth_proc.c" |
| 378 | 420 | ||
| @@ -452,6 +494,7 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, | |||
| 452 | gdth_ha_str *ha = shost_priv(sdev->host); | 494 | gdth_ha_str *ha = shost_priv(sdev->host); |
| 453 | Scsi_Cmnd *scp; | 495 | Scsi_Cmnd *scp; |
| 454 | struct gdth_cmndinfo cmndinfo; | 496 | struct gdth_cmndinfo cmndinfo; |
| 497 | struct scatterlist one_sg; | ||
| 455 | DECLARE_COMPLETION_ONSTACK(wait); | 498 | DECLARE_COMPLETION_ONSTACK(wait); |
| 456 | int rval; | 499 | int rval; |
| 457 | 500 | ||
| @@ -465,7 +508,10 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, | |||
| 465 | /* use request field to save the ptr. to completion struct. */ | 508 | /* use request field to save the ptr. to completion struct. */ |
| 466 | scp->request = (struct request *)&wait; | 509 | scp->request = (struct request *)&wait; |
| 467 | scp->timeout_per_command = timeout*HZ; | 510 | scp->timeout_per_command = timeout*HZ; |
| 468 | scp->request_buffer = gdtcmd; | 511 | sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd)); |
| 512 | gdth_set_sglist(scp, &one_sg); | ||
| 513 | gdth_set_sg_count(scp, 1); | ||
| 514 | gdth_set_bufflen(scp, sizeof(*gdtcmd)); | ||
| 469 | scp->cmd_len = 12; | 515 | scp->cmd_len = 12; |
| 470 | memcpy(scp->cmnd, cmnd, 12); | 516 | memcpy(scp->cmnd, cmnd, 12); |
| 471 | cmndinfo.priority = IOCTL_PRI; | 517 | cmndinfo.priority = IOCTL_PRI; |
| @@ -2303,24 +2349,28 @@ static void gdth_next(gdth_ha_str *ha) | |||
| 2303 | ha->hanum, cmd_index); | 2349 | ha->hanum, cmd_index); |
| 2304 | } | 2350 | } |
| 2305 | } | 2351 | } |
| 2306 | 2352 | ||
| 2353 | /* | ||
| 2354 | * gdth_copy_internal_data() - copy to/from a buffer onto a scsi_cmnd's | ||
| 2355 | * buffers, kmap_atomic() as needed. | ||
| 2356 | */ | ||
| 2307 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | 2357 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, |
| 2308 | char *buffer,ushort count) | 2358 | char *buffer, ushort count, int to_buffer) |
| 2309 | { | 2359 | { |
| 2310 | ushort cpcount,i; | 2360 | ushort cpcount,i, max_sg = gdth_sg_count(scp); |
| 2311 | ushort cpsum,cpnow; | 2361 | ushort cpsum,cpnow; |
| 2312 | struct scatterlist *sl; | 2362 | struct scatterlist *sl; |
| 2313 | char *address; | 2363 | char *address; |
| 2314 | 2364 | ||
| 2315 | cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen; | 2365 | cpcount = min_t(ushort, count, gdth_bufflen(scp)); |
| 2316 | 2366 | ||
| 2317 | if (scp->use_sg) { | 2367 | if (cpcount) { |
| 2318 | sl = (struct scatterlist *)scp->request_buffer; | 2368 | cpsum=0; |
| 2319 | for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) { | 2369 | scsi_for_each_sg(scp, sl, max_sg, i) { |
| 2320 | unsigned long flags; | 2370 | unsigned long flags; |
| 2321 | cpnow = (ushort)sl->length; | 2371 | cpnow = (ushort)sl->length; |
| 2322 | TRACE(("copy_internal() now %d sum %d count %d %d\n", | 2372 | TRACE(("copy_internal() now %d sum %d count %d %d\n", |
| 2323 | cpnow,cpsum,cpcount,(ushort)scp->bufflen)); | 2373 | cpnow, cpsum, cpcount, gdth_bufflen(scp))); |
| 2324 | if (cpsum+cpnow > cpcount) | 2374 | if (cpsum+cpnow > cpcount) |
| 2325 | cpnow = cpcount - cpsum; | 2375 | cpnow = cpcount - cpsum; |
| 2326 | cpsum += cpnow; | 2376 | cpsum += cpnow; |
| @@ -2331,7 +2381,10 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | |||
| 2331 | } | 2381 | } |
| 2332 | local_irq_save(flags); | 2382 | local_irq_save(flags); |
| 2333 | address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; | 2383 | address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; |
| 2334 | memcpy(address,buffer,cpnow); | 2384 | if (to_buffer) |
| 2385 | memcpy(buffer, address, cpnow); | ||
| 2386 | else | ||
| 2387 | memcpy(address, buffer, cpnow); | ||
| 2335 | flush_dcache_page(sl->page); | 2388 | flush_dcache_page(sl->page); |
| 2336 | kunmap_atomic(address, KM_BIO_SRC_IRQ); | 2389 | kunmap_atomic(address, KM_BIO_SRC_IRQ); |
| 2337 | local_irq_restore(flags); | 2390 | local_irq_restore(flags); |
| @@ -2339,9 +2392,10 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | |||
| 2339 | break; | 2392 | break; |
| 2340 | buffer += cpnow; | 2393 | buffer += cpnow; |
| 2341 | } | 2394 | } |
| 2342 | } else { | 2395 | } else if (count) { |
| 2343 | TRACE(("copy_internal() count %d\n",cpcount)); | 2396 | printk("GDT-HA %d: SCSI command with no buffers but data transfer expected!\n", |
| 2344 | memcpy((char*)scp->request_buffer,buffer,cpcount); | 2397 | ha->hanum); |
| 2398 | WARN_ON(1); | ||
| 2345 | } | 2399 | } |
| 2346 | } | 2400 | } |
| 2347 | 2401 | ||
| @@ -2384,7 +2438,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
| 2384 | strcpy(inq.vendor,ha->oem_name); | 2438 | strcpy(inq.vendor,ha->oem_name); |
| 2385 | sprintf(inq.product,"Host Drive #%02d",t); | 2439 | |
