diff options
| author | Jeff Garzik <jgarzik@pobox.com> | 2005-10-22 00:14:31 -0400 | 
|---|---|---|
| committer | Jeff Garzik <jgarzik@pobox.com> | 2005-10-22 00:14:31 -0400 | 
| commit | 2d5a2ae52d8863275e2d26398bc010249ea709d1 (patch) | |
| tree | d616b75e3ca5b317db905984aea16ebe777e4a2d | |
| parent | 63172cb3d5ef762dcb60a292bc7f016b85cf6e1f (diff) | |
drivers/block/sx8: several minor changes
* Newer hardware doesn't corrupt data when the queue depth
  is greater than one.  Rather than force the user to recompile
  with a greater queue depth, make it a module parameter.
* update copyright date
* add MODULE_VERSION()
* trim trailing whitespace
* move CARM_SG_BOUNDARY to a separate enum, since its unsigned long
* bump to version 1.0
| -rw-r--r-- | drivers/block/sx8.c | 50 | 
1 files changed, 37 insertions, 13 deletions
| diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index d57007b92f77..b5f612679a31 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* | 
| 2 | * sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware | 2 | * sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware | 
| 3 | * | 3 | * | 
| 4 | * Copyright 2004 Red Hat, Inc. | 4 | * Copyright 2004-2005 Red Hat, Inc. | 
| 5 | * | 5 | * | 
| 6 | * Author/maintainer: Jeff Garzik <jgarzik@pobox.com> | 6 | * Author/maintainer: Jeff Garzik <jgarzik@pobox.com> | 
| 7 | * | 7 | * | 
| @@ -31,10 +31,6 @@ | |||
| 31 | #include <asm/semaphore.h> | 31 | #include <asm/semaphore.h> | 
| 32 | #include <asm/uaccess.h> | 32 | #include <asm/uaccess.h> | 
| 33 | 33 | ||
| 34 | MODULE_AUTHOR("Jeff Garzik"); | ||
| 35 | MODULE_LICENSE("GPL"); | ||
| 36 | MODULE_DESCRIPTION("Promise SATA SX8 block driver"); | ||
| 37 | |||
| 38 | #if 0 | 34 | #if 0 | 
| 39 | #define CARM_DEBUG | 35 | #define CARM_DEBUG | 
| 40 | #define CARM_VERBOSE_DEBUG | 36 | #define CARM_VERBOSE_DEBUG | 
| @@ -45,9 +41,35 @@ MODULE_DESCRIPTION("Promise SATA SX8 block driver"); | |||
| 45 | #undef CARM_NDEBUG | 41 | #undef CARM_NDEBUG | 
| 46 | 42 | ||
| 47 | #define DRV_NAME "sx8" | 43 | #define DRV_NAME "sx8" | 
| 48 | #define DRV_VERSION "0.8" | 44 | #define DRV_VERSION "1.0" | 
| 49 | #define PFX DRV_NAME ": " | 45 | #define PFX DRV_NAME ": " | 
| 50 | 46 | ||
| 47 | MODULE_AUTHOR("Jeff Garzik"); | ||
| 48 | MODULE_LICENSE("GPL"); | ||
| 49 | MODULE_DESCRIPTION("Promise SATA SX8 block driver"); | ||
| 50 | MODULE_VERSION(DRV_VERSION); | ||
| 51 | |||
| 52 | /* | ||
| 53 | * SX8 hardware has a single message queue for all ATA ports. | ||
| 54 | * When this driver was written, the hardware (firmware?) would | ||
| 55 | * corrupt data eventually, if more than one request was outstanding. | ||
| 56 | * As one can imagine, having 8 ports bottlenecking on a single | ||
| 57 | * command hurts performance. | ||
| 58 | * | ||
| 59 | * Based on user reports, later versions of the hardware (firmware?) | ||
| 60 | * seem to be able to survive with more than one command queued. | ||
| 61 | * | ||
| 62 | * Therefore, we default to the safe option -- 1 command -- but | ||
| 63 | * allow the user to increase this. | ||
| 64 | * | ||
| 65 | * SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ), | ||
| 66 | * but problems seem to occur when you exceed ~30, even on newer hardware. | ||
| 67 | */ | ||
| 68 | static int max_queue = 1; | ||
| 69 | module_param(max_queue, int, 0444); | ||
| 70 | MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)"); | ||
| 71 | |||
| 72 | |||
| 51 | #define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN) | 73 | #define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN) | 
| 52 | 74 | ||
| 53 | /* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */ | 75 | /* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */ | 
| @@ -90,12 +112,10 @@ enum { | |||
| 90 | 112 | ||
| 91 | /* command message queue limits */ | 113 | /* command message queue limits */ | 
| 92 | CARM_MAX_REQ = 64, /* max command msgs per host */ | 114 | CARM_MAX_REQ = 64, /* max command msgs per host */ | 
| 93 | CARM_MAX_Q = 1, /* one command at a time */ | ||
| 94 | CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */ | 115 | CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */ | 
| 95 | 116 | ||
| 96 | /* S/G limits, host-wide and per-request */ | 117 | /* S/G limits, host-wide and per-request */ | 
| 97 | CARM_MAX_REQ_SG = 32, /* max s/g entries per request */ | 118 | CARM_MAX_REQ_SG = 32, /* max s/g entries per request */ | 
| 98 | CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */ | ||
| 99 | CARM_MAX_HOST_SG = 600, /* max s/g entries per host */ | 119 | CARM_MAX_HOST_SG = 600, /* max s/g entries per host */ | 
| 100 | CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */ | 120 | CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */ | 
| 101 | 121 | ||
| @@ -181,6 +201,10 @@ enum { | |||
| 181 | FL_DYN_MAJOR = (1 << 17), | 201 | FL_DYN_MAJOR = (1 << 17), | 
| 182 | }; | 202 | }; | 
| 183 | 203 | ||
| 204 | enum { | ||
| 205 | CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */ | ||
| 206 | }; | ||
| 207 | |||
| 184 | enum scatter_gather_types { | 208 | enum scatter_gather_types { | 
| 185 | SGT_32BIT = 0, | 209 | SGT_32BIT = 0, | 
| 186 | SGT_64BIT = 1, | 210 | SGT_64BIT = 1, | 
| @@ -448,7 +472,7 @@ static inline int carm_lookup_bucket(u32 msg_size) | |||
| 448 | for (i = 0; i < ARRAY_SIZE(msg_sizes); i++) | 472 | for (i = 0; i < ARRAY_SIZE(msg_sizes); i++) | 
| 449 | if (msg_size <= msg_sizes[i]) | 473 | if (msg_size <= msg_sizes[i]) | 
| 450 | return i; | 474 | return i; | 
| 451 | 475 | ||
| 452 | return -ENOENT; | 476 | return -ENOENT; | 
| 453 | } | 477 | } | 
| 454 | 478 | ||
| @@ -509,7 +533,7 @@ static struct carm_request *carm_get_request(struct carm_host *host) | |||
| 509 | if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG)) | 533 | if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG)) | 
| 510 | return NULL; | 534 | return NULL; | 
| 511 | 535 | ||
| 512 | for (i = 0; i < CARM_MAX_Q; i++) | 536 | for (i = 0; i < max_queue; i++) | 
| 513 | if ((host->msg_alloc & (1ULL << i)) == 0) { | 537 | if ((host->msg_alloc & (1ULL << i)) == 0) { | 
| 514 | struct carm_request *crq = &host->req[i]; | 538 | struct carm_request *crq = &host->req[i]; | 
| 515 | crq->port = NULL; | 539 | crq->port = NULL; | 
| @@ -521,14 +545,14 @@ static struct carm_request *carm_get_request(struct carm_host *host) | |||
| 521 | assert(host->n_msgs <= CARM_MAX_REQ); | 545 | assert(host->n_msgs <= CARM_MAX_REQ); | 
| 522 | return crq; | 546 | return crq; | 
| 523 | } | 547 | } | 
| 524 | 548 | ||
| 525 | DPRINTK("no request available, returning NULL\n"); | 549 | DPRINTK("no request available, returning NULL\n"); | 
| 526 | return NULL; | 550 | return NULL; | 
| 527 | } | 551 | } | 
| 528 | 552 | ||
| 529 | static int carm_put_request(struct carm_host *host, struct carm_request *crq) | 553 | static int carm_put_request(struct carm_host *host, struct carm_request *crq) | 
| 530 | { | 554 | { | 
| 531 | assert(crq->tag < CARM_MAX_Q); | 555 | assert(crq->tag < max_queue); | 
| 532 | 556 | ||
| 533 | if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0)) | 557 | if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0)) | 
| 534 | return -EINVAL; /* tried to clear a tag that was not active */ | 558 | return -EINVAL; /* tried to clear a tag that was not active */ | 
| @@ -791,7 +815,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq, | |||
| 791 | int is_ok) | 815 | int is_ok) | 
| 792 | { | 816 | { | 
| 793 | carm_end_request_queued(host, crq, is_ok); | 817 | carm_end_request_queued(host, crq, is_ok); | 
| 794 | if (CARM_MAX_Q == 1) | 818 | if (max_queue == 1) | 
| 795 | carm_round_robin(host); | 819 | carm_round_robin(host); | 
| 796 | else if ((host->n_msgs <= CARM_MSG_LOW_WATER) && | 820 | else if ((host->n_msgs <= CARM_MSG_LOW_WATER) && | 
| 797 | (host->hw_sg_used <= CARM_SG_LOW_WATER)) { | 821 | (host->hw_sg_used <= CARM_SG_LOW_WATER)) { | 
