aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/sx8.c50
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
34MODULE_AUTHOR("Jeff Garzik");
35MODULE_LICENSE("GPL");
36MODULE_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
47MODULE_AUTHOR("Jeff Garzik");
48MODULE_LICENSE("GPL");
49MODULE_DESCRIPTION("Promise SATA SX8 block driver");
50MODULE_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 */
68static int max_queue = 1;
69module_param(max_queue, int, 0444);
70MODULE_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
204enum {
205 CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */
206};
207
184enum scatter_gather_types { 208enum 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
529static int carm_put_request(struct carm_host *host, struct carm_request *crq) 553static 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)) {