The biggest changes are:
1) Adding support for Storageworks 1210m. This RAID controller,
unlike previous Smart Arrays, responds to SCSI_REPORT_LUNs and
consequently the code for device discovery and mapping devices to
bus/target/lun had to change significantly.
2) The 1210m requires the use of so-called "performant mode", which
allow multiple commands to be completed with a single interrupt. All
Smart Arrays support this mode.
3) Fixed bug in device updating code in which multiple changes at once
caused bad things to happen.
The remaining changes are mostly just cleaning things up.
Don Brace (1):
hpsa: Allow multiple command completions per interrupt.
Matt Gates (3):
hpsa: Return DID_RESET for commands which complete with status of UNSOLICITED ABORT
hpsa: Retry commands completing with a sense key of ABORTED_COMMAND
hpsa: Don't return DID_NO_CONNECT when a device is merely not ready
Mike Miller (2):
hpsa: add pci ids for storageworks 1210m, remove p400, p800, p700m
hpsa: print all the bytes of the CDB, not just the first one.
Stephen M. Cameron (24):
hpsa: fix typo in comments
hpsa: Use kernel integer types, not userland ones
hpsa: avoid unwanted promotion from unsigned to signed for raid level index
hpsa: Use BUG_ON instead of an if statement.
hpsa: make adjust_hpsa_scsi_table return void.
hpsa: remove superfluous returns from void functions.
hpsa: return proper error codes not minus one.
hpsa: use sizeof() not an inline constant in memset.
hpsa: use kzalloc not kmalloc plus memset
hpsa: remove unwanted debug code
hpsa: eliminate unnecessary memcpys
hpsa: make tag macros into functions
hpsa: fix some debug printks to use dev_dbg instead
hpsa: interrupt pending function should return bool not unsigned long
hpsa: Fix p1210m LUN assignment.
hpsa: Add an shost_to_hba helper function.
hpsa: use scan_start and scan_finished entry points for scanning
hpsa: when resetting devices, print out which device
hpsa: clarify obscure comment in adjust_hpsa_scsi_table
hpsa: Fix hpsa_find_scsi_entry so that it doesn't try to dereference NULL pointers
hpsa: fix bug in adjust_hpsa_scsi_table
hpsa: eliminate lock_kernel in compat_ioctl
hpsa: Reorder compat ioctl functions to eliminate some forward declarations.
hpsa: `update driver version to 2.0.1-3
drivers/scsi/hpsa.c | 793 ++++++++++++++++++++++++++++++++++-------------
drivers/scsi/hpsa.h | 136 +++++++-
drivers/scsi/hpsa_cmd.h | 204 +++++++-----
3 files changed, 809 insertions(+), 324 deletions(-)
--
steve
From: Stephen M. Cameron <[email protected]>
hpsa: return proper error codes not minus one.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 37 ++++++++++++++++++++++---------------
1 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 9017e64..8389cce 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1130,11 +1130,11 @@ static int hpsa_scsi_detect(struct ctlr_info *h)
dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_add_host"
" failed for controller %d\n", h->ctlr);
scsi_host_put(sh);
- return -1;
+ return error;
fail:
dev_err(&h->pdev->dev, "hpsa_scsi_detect: scsi_host_alloc"
" failed for controller %d\n", h->ctlr);
- return -1;
+ return -ENOMEM;
}
static void hpsa_pci_unmap(struct pci_dev *pdev,
@@ -1271,7 +1271,7 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr,
if (c == NULL) { /* trouble... */
dev_warn(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
- return -1;
+ return -ENOMEM;
}
fill_cmd(c, HPSA_INQUIRY, h, buf, bufsize, page, scsi3addr, TYPE_CMD);
@@ -3284,7 +3284,7 @@ err_out_free_res:
static int __devinit hpsa_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- int i;
+ int i, rc;
int dac;
struct ctlr_info *h;
@@ -3312,14 +3312,15 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
BUILD_BUG_ON(sizeof(struct CommandList) % 8);
h = kzalloc(sizeof(*h), GFP_KERNEL);
if (!h)
- return -1;
+ return -ENOMEM;
h->busy_initializing = 1;
INIT_HLIST_HEAD(&h->cmpQ);
INIT_HLIST_HEAD(&h->reqQ);
mutex_init(&h->busy_shutting_down);
init_completion(&h->scan_wait);
- if (hpsa_pci_init(h, pdev) != 0)
+ rc = hpsa_pci_init(h, pdev);
+ if (rc != 0)
goto clean1;
sprintf(h->devname, "hpsa%d", number_of_controllers);
@@ -3328,19 +3329,24 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
h->pdev = pdev;
/* configure PCI DMA stuff */
- if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+ if (rc == 0) {
dac = 1;
- else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))
- dac = 0;
- else {
- dev_err(&pdev->dev, "no suitable DMA available\n");
- goto clean1;
+ } else {
+ rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+ if (rc == 0) {
+ dac = 0;
+ } else {
+ dev_err(&pdev->dev, "no suitable DMA available\n");
+ goto clean1;
+ }
}
/* make sure the board interrupts are off */
h->access.set_intr_mask(h, HPSA_INTR_OFF);
- if (request_irq(h->intr[SIMPLE_MODE_INT], do_hpsa_intr,
- IRQF_DISABLED | IRQF_SHARED, h->devname, h)) {
+ rc = request_irq(h->intr[SIMPLE_MODE_INT], do_hpsa_intr,
+ IRQF_DISABLED | IRQF_SHARED, h->devname, h);
+ if (rc) {
dev_err(&pdev->dev, "unable to get irq %d for %s\n",
h->intr[SIMPLE_MODE_INT], h->devname);
goto clean2;
@@ -3363,6 +3369,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
|| (h->cmd_pool == NULL)
|| (h->errinfo_pool == NULL)) {
dev_err(&pdev->dev, "out of memory");
+ rc = -ENOMEM;
goto clean4;
}
spin_lock_init(&h->lock);
@@ -3397,7 +3404,7 @@ clean2:
clean1:
h->busy_initializing = 0;
kfree(h);
- return -1;
+ return rc;
}
static void hpsa_flush_cache(struct ctlr_info *h)
From: Stephen M. Cameron <[email protected]>
hpsa: make adjust_hpsa_scsi_table return void.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 2c256e3..6fe5142 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -733,7 +733,7 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
return DEVICE_NOT_FOUND;
}
-static int adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
+static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
struct hpsa_scsi_dev_t *sd[], int nsds)
{
/* sd contains scsi3 addresses and devtypes, and inquiry
@@ -859,7 +859,6 @@ static int adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
free_and_out:
kfree(added);
kfree(removed);
- return 0;
}
/*
From: Stephen M. Cameron <[email protected]>
hpsa: interrupt pending function should return bool not unsigned long
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 2 +-
drivers/scsi/hpsa.h | 8 +++-----
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 82987e1..314854b 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2693,7 +2693,7 @@ static inline unsigned long get_next_completion(struct ctlr_info *h)
return h->access.command_completed(h);
}
-static inline int interrupt_pending(struct ctlr_info *h)
+static inline bool interrupt_pending(struct ctlr_info *h)
{
return h->access.intr_pending(h);
}
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index cdac95b..0eab386 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -33,7 +33,7 @@ struct access_method {
struct CommandList *c);
void (*set_intr_mask)(struct ctlr_info *h, unsigned long val);
unsigned long (*fifo_full)(struct ctlr_info *h);
- unsigned long (*intr_pending)(struct ctlr_info *h);
+ bool (*intr_pending)(struct ctlr_info *h);
unsigned long (*command_completed)(struct ctlr_info *h);
};
@@ -233,14 +233,12 @@ static unsigned long SA5_completed(struct ctlr_info *h)
/*
* Returns true if an interrupt is pending..
*/
-static unsigned long SA5_intr_pending(struct ctlr_info *h)
+static bool SA5_intr_pending(struct ctlr_info *h)
{
unsigned long register_value =
readl(h->vaddr + SA5_INTR_STATUS);
dev_dbg(&h->pdev->dev, "intr_pending %lx\n", register_value);
- if (register_value & SA5_INTR_PENDING)
- return 1;
- return 0 ;
+ return register_value & SA5_INTR_PENDING;
}
From: Matt Gates <[email protected]>
hpsa: Return DID_RESET for commands which complete with status of UNSOLICITED ABORT.
The commands should be retried, and this will make that happen, instead of resulting
in an i/o error.
Signed-off-by: Matt Gates <[email protected]>
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index cc9e92a..bcc51f9 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1128,7 +1128,7 @@ static void complete_scsi_command(struct CommandList *cp,
dev_warn(&h->pdev->dev, "cp %p reports abort failed\n", cp);
break;
case CMD_UNSOLICITED_ABORT:
- cmd->result = DID_ABORT << 16;
+ cmd->result = DID_RESET << 16;
dev_warn(&h->pdev->dev, "cp %p aborted do to an unsolicited "
"abort\n", cp);
break;
From: Stephen M. Cameron <[email protected]>
hpsa: Fix hpsa_find_scsi_entry so that it doesn't try to dereference NULL pointers
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 42295c4..2764cb6 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -776,6 +776,8 @@ static int hpsa_scsi_find_entry(struct hpsa_scsi_dev_t *needle,
#define DEVICE_CHANGED 1
#define DEVICE_SAME 2
for (i = 0; i < haystack_size; i++) {
+ if (haystack[i] == NULL) /* previously removed. */
+ continue;
if (SCSI3ADDR_EQ(needle->scsi3addr, haystack[i]->scsi3addr)) {
*index = i;
if (device_is_the_same(needle, haystack[i]))
From: Stephen M. Cameron <[email protected]>
hpsa: when resetting devices, print out which device
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index f889ec8..db12bc2 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2141,14 +2141,14 @@ static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd)
h = sdev_to_hba(scsicmd->device);
if (h == NULL) /* paranoia */
return FAILED;
- dev_warn(&h->pdev->dev, "resetting drive\n");
-
dev = scsicmd->device->hostdata;
if (!dev) {
dev_err(&h->pdev->dev, "hpsa_eh_device_reset_handler: "
"device lookup failed.\n");
return FAILED;
}
+ dev_warn(&h->pdev->dev, "resetting device %d:%d:%d:%d\n",
+ h->scsi_host->host_no, dev->bus, dev->target, dev->lun);
/* send a reset to the SCSI LUN which the command was sent to */
rc = hpsa_send_reset(h, dev->scsi3addr);
if (rc == 0 && wait_for_device_to_become_ready(h, dev->scsi3addr) == 0)
From: Matt Gates <[email protected]>
hpsa: Don't return DID_NO_CONNECT when a device is merely not ready
Signed-off-by: Matt Gates <[email protected]>
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index d07b3d3..320d686 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1029,7 +1029,6 @@ static void complete_scsi_command(struct CommandList *cp,
* required
*/
if ((asc == 0x04) && (ascq == 0x03)) {
- cmd->result = DID_NO_CONNECT << 16;
dev_warn(&h->pdev->dev, "cp %p "
"has check condition: unit "
"not ready, manual "
From: Matt Gates <[email protected]>
hpsa: Retry commands completing with a sense key of ABORTED_COMMAND
Signed-off-by: Matt Gates <[email protected]>
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 11 +++++++++--
1 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index bcc51f9..d07b3d3 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1037,8 +1037,15 @@ static void complete_scsi_command(struct CommandList *cp,
break;
}
}
-
-
+ if (sense_key == ABORTED_COMMAND) {
+ /* Aborted command is retryable */
+ dev_warn(&h->pdev->dev, "cp %p "
+ "has check condition: aborted command: "
+ "ASC: 0x%x, ASCQ: 0x%x\n",
+ cp, asc, ascq);
+ cmd->result = DID_SOFT_ERROR << 16;
+ break;
+ }
/* Must be some other type of check condition */
dev_warn(&h->pdev->dev, "cp %p has check condition: "
"unknown type: "
From: Stephen M. Cameron <[email protected]>
hpsa: use scan_start and scan_finished entry points for scanning and
route the CCISS_REGNEWD ioctl and sysfs triggering of same functionality
through hpsa_scan_start.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++---
drivers/scsi/hpsa.h | 3 +++
2 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index e81df76..f889ec8 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -131,6 +131,9 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
void (*done)(struct scsi_cmnd *));
+static void hpsa_scan_start(struct Scsi_Host *);
+static int hpsa_scan_finished(struct Scsi_Host *sh,
+ unsigned long elapsed_time);
static int hpsa_eh_device_reset_handler(struct scsi_cmnd *scsicmd);
static int hpsa_slave_alloc(struct scsi_device *sdev);
@@ -177,6 +180,8 @@ static struct scsi_host_template hpsa_driver_template = {
.name = "hpsa",
.proc_name = "hpsa",
.queuecommand = hpsa_scsi_queue_command,
+ .scan_start = hpsa_scan_start,
+ .scan_finished = hpsa_scan_finished,
.this_id = -1,
.sg_tablesize = MAXSGENTRIES,
.use_clustering = ENABLE_CLUSTERING,
@@ -320,7 +325,7 @@ static int hpsa_scan_func(__attribute__((unused)) void *data)
h->busy_scanning = 1;
mutex_unlock(&hpsa_scan_mutex);
host_no = h->scsi_host ? h->scsi_host->host_no : -1;
- hpsa_update_scsi_devices(h, host_no);
+ hpsa_scan_start(h->scsi_host);
complete_all(&h->scan_wait);
mutex_lock(&hpsa_scan_mutex);
h->busy_scanning = 0;
@@ -2006,6 +2011,48 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
return 0;
}
+static void hpsa_scan_start(struct Scsi_Host *sh)
+{
+ struct ctlr_info *h = shost_to_hba(sh);
+ unsigned long flags;
+
+ /* wait until any scan already in progress is finished. */
+ while (1) {
+ spin_lock_irqsave(&h->scan_lock, flags);
+ if (h->scan_finished)
+ break;
+ spin_unlock_irqrestore(&h->scan_lock, flags);
+ wait_event(h->scan_wait_queue, h->scan_finished);
+ /* Note: We don't need to worry about a race between this
+ * thread and driver unload because the midlayer will
+ * have incremented the reference count, so unload won't
+ * happen if we're in here.
+ */
+ }
+ h->scan_finished = 0; /* mark scan as in progress */
+ spin_unlock_irqrestore(&h->scan_lock, flags);
+
+ hpsa_update_scsi_devices(h, h->scsi_host->host_no);
+
+ spin_lock_irqsave(&h->scan_lock, flags);
+ h->scan_finished = 1; /* mark scan as finished. */
+ wake_up_all(&h->scan_wait_queue);
+ spin_unlock_irqrestore(&h->scan_lock, flags);
+}
+
+static int hpsa_scan_finished(struct Scsi_Host *sh,
+ unsigned long elapsed_time)
+{
+ struct ctlr_info *h = shost_to_hba(sh);
+ unsigned long flags;
+ int finished;
+
+ spin_lock_irqsave(&h->scan_lock, flags);
+ finished = h->scan_finished;
+ spin_unlock_irqrestore(&h->scan_lock, flags);
+ return finished;
+}
+
static void hpsa_unregister_scsi(struct ctlr_info *h)
{
/* we are being forcibly unloaded, and may not refuse. */
@@ -2018,7 +2065,6 @@ static int hpsa_register_scsi(struct ctlr_info *h)
{
int rc;
- hpsa_update_scsi_devices(h, -1);
rc = hpsa_scsi_detect(h);
if (rc != 0)
dev_err(&h->pdev->dev, "hpsa_register_scsi: failed"
@@ -2619,7 +2665,7 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
case CCISS_DEREGDISK:
case CCISS_REGNEWDISK:
case CCISS_REGNEWD:
- hpsa_update_scsi_devices(h, dev->host->host_no);
+ hpsa_scan_start(h->scsi_host);
return 0;
case CCISS_GETPCIINFO:
return hpsa_getpciinfo_ioctl(h, argp);
@@ -3532,6 +3578,9 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
goto clean4;
}
spin_lock_init(&h->lock);
+ spin_lock_init(&h->scan_lock);
+ init_waitqueue_head(&h->scan_wait_queue);
+ h->scan_finished = 1; /* no scan currently in progress */
pci_set_drvdata(pdev, h);
memset(h->cmd_pool_bits, 0,
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 1ab0c1b..a0502b3 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -94,6 +94,9 @@ struct ctlr_info {
int nr_frees;
int busy_initializing;
int busy_scanning;
+ int scan_finished;
+ spinlock_t scan_lock;
+ wait_queue_head_t scan_wait_queue;
struct mutex busy_shutting_down;
struct list_head scan_list;
struct completion scan_wait;
From: Mike Miller <[email protected]>
hpsa: print all the bytes of the CDB, not just the first one.
Signed-off-by: Mike Miller <[email protected]>
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index db12bc2..b91ccd4 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1061,6 +1061,7 @@ static void complete_scsi_command(struct CommandList *cp,
"Sense: 0x%x, ASC: 0x%x, ASCQ: 0x%x, "
"Returning result: 0x%x, "
"cmd=[%02x %02x %02x %02x %02x "
+ "%02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x]\n",
cp, sense_key, asc, ascq,
cmd->result,
@@ -1068,7 +1069,10 @@ static void complete_scsi_command(struct CommandList *cp,
cmd->cmnd[2], cmd->cmnd[3],
cmd->cmnd[4], cmd->cmnd[5],
cmd->cmnd[6], cmd->cmnd[7],
- cmd->cmnd[8], cmd->cmnd[9]);
+ cmd->cmnd[8], cmd->cmnd[9],
+ cmd->cmnd[10], cmd->cmnd[11],
+ cmd->cmnd[12], cmd->cmnd[13],
+ cmd->cmnd[14], cmd->cmnd[15]);
break;
}
From: Stephen M. Cameron <[email protected]>
hpsa: fix bug in adjust_hpsa_scsi_table which caused devices
which have changed size, etc. to do the wrong thing.
The problem was as follows:
The driver maintains its current idea of what devices are present
in the h->dev[] array. When it updates this array, it scans the
hardware, and produces a new list of devices, call it sd[], for
scsi devices.
Then, it compares each item in h->dev[] vs. sd[], and any items which
are not present sd it removes from h->dev[], and any items present
in sd[], but different, it modifies in h->dev[].
Then, it looks for items in sd[] which are not present in h->dev[],
and adds those items into h->dev[]. All the while, it keeps track
of what items were added and removed to/from h->dev[].
Finally, it updates the SCSI mid-layer by removing and adding
the same devices it removed and added to/from h->dev[]. (modified
devices count as a remove then add.)
originally, when a "changed" device was discovered, it was
removed then added to h->dev[]. The item was added to the *end*
of h->dev[]. And, the item was removed from sd[] as well
(nulled out). As it processed h->dev[], these newly added items
at the end of the list were encountered, and sd[] was searched,
but those items were nulled out. So they ended up getting removed
immediately after they were added.
The solution is to have a way to replace items in the h->dev[]
array instead of doing a remove + add. Then the "changed" items.
are not encountered a second time, and removed.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 26 ++++++++++++++++++++------
1 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 2764cb6..6b40221 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -675,6 +675,24 @@ lun_assigned:
return 0;
}
+/* Replace an entry from h->dev[] array. */
+static void hpsa_scsi_replace_entry(struct ctlr_info *h, int hostno,
+ int entry, struct hpsa_scsi_dev_t *new_entry,
+ struct hpsa_scsi_dev_t *added[], int *nadded,
+ struct hpsa_scsi_dev_t *removed[], int *nremoved)
+{
+ /* assumes h->devlock is held */
+ BUG_ON(entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA);
+ removed[*nremoved] = h->dev[entry];
+ (*nremoved)++;
+ h->dev[entry] = new_entry;
+ added[*nadded] = new_entry;
+ (*nadded)++;
+ dev_info(&h->pdev->dev, "%s device c%db%dt%dl%d changed.\n",
+ scsi_device_type(new_entry->devtype), hostno, new_entry->bus,
+ new_entry->target, new_entry->lun);
+}
+
/* Remove an entry from h->dev[] array. */
static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,
struct hpsa_scsi_dev_t *removed[], int *nremoved)
@@ -835,12 +853,8 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
continue; /* remove ^^^, hence i not incremented */
} else if (device_change == DEVICE_CHANGED) {
changes++;
- hpsa_scsi_remove_entry(h, hostno, i,
- removed, &nremoved);
- (void) hpsa_scsi_add_entry(h, hostno, sd[entry],
- added, &nadded);
- /* add can't fail, we just removed one. */
-
+ hpsa_scsi_replace_entry(h, hostno, i, sd[entry],
+ added, &nadded, removed, &nremoved);
/* Set it to NULL to prevent it from being freed
* at the bottom of hpsa_update_scsi_devices()
*/
From: Stephen M. Cameron <[email protected]>
hpsa: Reorder compat ioctl functions to eliminate some forward declarations.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 64 ++++++++++++++++++++++++---------------------------
1 files changed, 30 insertions(+), 34 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 225a787..af20dbd 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2287,40 +2287,6 @@ static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
#ifdef CONFIG_COMPAT
-static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg);
-static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
- int cmd, void *arg);
-
-static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg)
-{
- switch (cmd) {
- case CCISS_GETPCIINFO:
- case CCISS_GETINTINFO:
- case CCISS_SETINTINFO:
- case CCISS_GETNODENAME:
- case CCISS_SETNODENAME:
- case CCISS_GETHEARTBEAT:
- case CCISS_GETBUSTYPES:
- case CCISS_GETFIRMVER:
- case CCISS_GETDRIVVER:
- case CCISS_REVALIDVOLS:
- case CCISS_DEREGDISK:
- case CCISS_REGNEWDISK:
- case CCISS_REGNEWD:
- case CCISS_RESCANDISK:
- case CCISS_GETLUNINFO:
- return hpsa_ioctl(dev, cmd, arg);
-
- case CCISS_PASSTHRU32:
- return hpsa_ioctl32_passthru(dev, cmd, arg);
- case CCISS_BIG_PASSTHRU32:
- return hpsa_ioctl32_big_passthru(dev, cmd, arg);
-
- default:
- return -ENOIOCTLCMD;
- }
-}
-
static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
{
IOCTL32_Command_struct __user *arg32 =
@@ -2391,6 +2357,36 @@ static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
return -EFAULT;
return err;
}
+
+static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg)
+{
+ switch (cmd) {
+ case CCISS_GETPCIINFO:
+ case CCISS_GETINTINFO:
+ case CCISS_SETINTINFO:
+ case CCISS_GETNODENAME:
+ case CCISS_SETNODENAME:
+ case CCISS_GETHEARTBEAT:
+ case CCISS_GETBUSTYPES:
+ case CCISS_GETFIRMVER:
+ case CCISS_GETDRIVVER:
+ case CCISS_REVALIDVOLS:
+ case CCISS_DEREGDISK:
+ case CCISS_REGNEWDISK:
+ case CCISS_REGNEWD:
+ case CCISS_RESCANDISK:
+ case CCISS_GETLUNINFO:
+ return hpsa_ioctl(dev, cmd, arg);
+
+ case CCISS_PASSTHRU32:
+ return hpsa_ioctl32_passthru(dev, cmd, arg);
+ case CCISS_BIG_PASSTHRU32:
+ return hpsa_ioctl32_big_passthru(dev, cmd, arg);
+
+ default:
+ return -ENOIOCTLCMD;
+ }
+}
#endif
static int hpsa_getpciinfo_ioctl(struct ctlr_info *h, void __user *argp)
From: Stephen M. Cameron <[email protected]>
hpsa: eliminate lock_kernel in compat_ioctl
The use of the big kernel lock here appears
to be ancient cruft that is no longer needed.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 16 +++-------------
1 files changed, 3 insertions(+), 13 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 6b40221..225a787 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2287,16 +2287,6 @@ static void cmd_special_free(struct ctlr_info *h, struct CommandList *c)
#ifdef CONFIG_COMPAT
-static int do_ioctl(struct scsi_device *dev, int cmd, void *arg)
-{
- int ret;
-
- lock_kernel();
- ret = hpsa_ioctl(dev, cmd, arg);
- unlock_kernel();
- return ret;
-}
-
static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg);
static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
int cmd, void *arg);
@@ -2319,7 +2309,7 @@ static int hpsa_compat_ioctl(struct scsi_device *dev, int cmd, void *arg)
case CCISS_REGNEWD:
case CCISS_RESCANDISK:
case CCISS_GETLUNINFO:
- return do_ioctl(dev, cmd, arg);
+ return hpsa_ioctl(dev, cmd, arg);
case CCISS_PASSTHRU32:
return hpsa_ioctl32_passthru(dev, cmd, arg);
@@ -2355,7 +2345,7 @@ static int hpsa_ioctl32_passthru(struct scsi_device *dev, int cmd, void *arg)
if (err)
return -EFAULT;
- err = do_ioctl(dev, CCISS_PASSTHRU, (void *)p);
+ err = hpsa_ioctl(dev, CCISS_PASSTHRU, (void *)p);
if (err)
return err;
err |= copy_in_user(&arg32->error_info, &p->error_info,
@@ -2392,7 +2382,7 @@ static int hpsa_ioctl32_big_passthru(struct scsi_device *dev,
if (err)
return -EFAULT;
- err = do_ioctl(dev, CCISS_BIG_PASSTHRU, (void *)p);
+ err = hpsa_ioctl(dev, CCISS_BIG_PASSTHRU, (void *)p);
if (err)
return err;
err |= copy_in_user(&arg32->error_info, &p->error_info,
From: Stephen M. Cameron <[email protected]>
hpsa: clarify obscure comment in adjust_hpsa_scsi_table
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 6 +++++-
1 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index b91ccd4..42295c4 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -838,7 +838,11 @@ static void adjust_hpsa_scsi_table(struct ctlr_info *h, int hostno,
(void) hpsa_scsi_add_entry(h, hostno, sd[entry],
added, &nadded);
/* add can't fail, we just removed one. */
- sd[entry] = NULL; /* prevent it from being freed */
+
+ /* Set it to NULL to prevent it from being freed
+ * at the bottom of hpsa_update_scsi_devices()
+ */
+ sd[entry] = NULL;
}
i++;
}
From: Stephen M. Cameron <[email protected]>
hpsa: `update driver version to 2.0.1-3
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index af20dbd..03697ba 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -52,7 +52,7 @@
#include "hpsa.h"
/* HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' */
-#define HPSA_DRIVER_VERSION "1.0.0"
+#define HPSA_DRIVER_VERSION "2.0.1-3"
#define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")"
/* How long to wait (in milliseconds) for board to go into simple mode */
From: Stephen M. Cameron <[email protected]>
hpsa: Add an shost_to_hba helper function.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 320d686..e81df76 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -197,6 +197,12 @@ static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
return (struct ctlr_info *) *priv;
}
+static inline struct ctlr_info *shost_to_hba(struct Scsi_Host *sh)
+{
+ unsigned long *priv = shost_priv(sh);
+ return (struct ctlr_info *) *priv;
+}
+
static struct task_struct *hpsa_scan_thread;
static DEFINE_MUTEX(hpsa_scan_mutex);
static LIST_HEAD(hpsa_scan_q);
@@ -381,8 +387,7 @@ static ssize_t host_store_rescan(struct device *dev,
{
struct ctlr_info *h;
struct Scsi_Host *shost = class_to_shost(dev);
- unsigned long *priv = shost_priv(shost);
- h = (struct ctlr_info *) *priv;
+ h = shost_to_hba(shost);
if (add_to_scan_list(h)) {
wake_up_process(hpsa_scan_thread);
wait_for_completion_interruptible(&h->scan_wait);
From: Stephen M. Cameron <[email protected]>
hpsa: Fix p1210m LUN assignment. The p1210m responsds to SCSI report
LUNs, unlike traditional Smart Array controllers. This means that the
bus, target, and lun assignments done by the driver cannot be arbitrary,
but must match what SCSI REPORT LUNS returns.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 117 ++++++++++++++++++++++++++++++++++++++++++---------
drivers/scsi/hpsa.h | 1
2 files changed, 98 insertions(+), 20 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 46055e2..cc9e92a 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -458,6 +458,15 @@ static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
return (scsi3addr[3] & 0xC0) == 0x40;
}
+static inline int is_scsi_rev_5(struct ctlr_info *h)
+{
+ if (!h->hba_inquiry_data)
+ return 0;
+ if ((h->hba_inquiry_data[2] & 0x07) == 5)
+ return 1;
+ return 0;
+}
+
static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
"UNKNOWN"
};
@@ -1525,22 +1534,44 @@ static void figure_bus_target_lun(struct ctlr_info *h,
if (is_logical_dev_addr_mode(lunaddrbytes)) {
/* logical device */
- lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
- if (is_msa2xxx(h, device)) {
- *bus = 1;
- *target = (lunid >> 16) & 0x3fff;
- *lun = lunid & 0x00ff;
- } else {
+ if (unlikely(is_scsi_rev_5(h))) {
+ /* p1210m, logical drives lun assignments
+ * match SCSI REPORT LUNS data.
+ */
+ lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
*bus = 0;
- *lun = 0;
- *target = lunid & 0x3fff;
+ *target = 0;
+ *lun = (lunid & 0x3fff) + 1;
+ } else {
+ /* not p1210m... */
+ lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
+ if (is_msa2xxx(h, device)) {
+ /* msa2xxx way, put logicals on bus 1
+ * and match target/lun numbers box
+ * reports.
+ */
+ *bus = 1;
+ *target = (lunid >> 16) & 0x3fff;
+ *lun = lunid & 0x00ff;
+ } else {
+ /* Traditional smart array way. */
+ *bus = 0;
+ *lun = 0;
+ *target = lunid & 0x3fff;
+ }
}
} else {
/* physical device */
if (is_hba_lunid(lunaddrbytes))
- *bus = 3;
+ if (unlikely(is_scsi_rev_5(h))) {
+ *bus = 0; /* put p1210m ctlr at 0,0,0 */
+ *target = 0;
+ *lun = 0;
+ return;
+ } else
+ *bus = 3; /* traditional smartarray */
else
- *bus = 2;
+ *bus = 2; /* physical disk */
*target = -1;
*lun = -1; /* we will fill these in later. */
}
@@ -1580,6 +1611,9 @@ static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
if (is_hba_lunid(scsi3addr))
return 0; /* Don't add the RAID controller here. */
+ if (is_scsi_rev_5(h))
+ return 0; /* p1210m doesn't need to do this. */
+
#define MAX_MSA2XXX_ENCLOSURES 32
if (*nmsa2xxx_enclosures >= MAX_MSA2XXX_ENCLOSURES) {
dev_warn(&h->pdev->dev, "Maximum number of MSA2XXX "
@@ -1643,6 +1677,31 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
return 0;
}
+u8 *figure_lunaddrbytes(struct ctlr_info *h, int raid_ctlr_position, int i,
+ int nphysicals, int nlogicals, struct ReportLUNdata *physdev_list,
+ struct ReportLUNdata *logdev_list)
+{
+ /* Helper function, figure out where the LUN ID info is coming from
+ * given index i, lists of physical and logical devices, where in
+ * the list the raid controller is supposed to appear (first or last)
+ */
+
+ int logicals_start = nphysicals + (raid_ctlr_position == 0);
+ int last_device = nphysicals + nlogicals + (raid_ctlr_position == 0);
+
+ if (i == raid_ctlr_position)
+ return RAID_CTLR_LUNID;
+
+ if (i < logicals_start)
+ return &physdev_list->LUN[i - (raid_ctlr_position == 0)][0];
+
+ if (i < last_device)
+ return &logdev_list->LUN[i - nphysicals -
+ (raid_ctlr_position == 0)][0];
+ BUG();
+ return NULL;
+}
+
static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
{
/* the idea here is we could get notified
@@ -1666,6 +1725,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 8;
int i, nmsa2xxx_enclosures, ndevs_to_allocate;
int bus, target, lun;
+ int raid_ctlr_position;
DECLARE_BITMAP(lunzerobits, HPSA_MAX_TARGETS_PER_CTLR);
currentsd = kzalloc(sizeof(*currentsd) * HPSA_MAX_SCSI_DEVS_PER_HBA,
@@ -1703,23 +1763,22 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
ndev_allocated++;
}
+ if (unlikely(is_scsi_rev_5(h)))
+ raid_ctlr_position = 0;
+ else
+ raid_ctlr_position = nphysicals + nlogicals;
+
/* adjust our table of devices */
nmsa2xxx_enclosures = 0;
for (i = 0; i < nphysicals + nlogicals + 1; i++) {
u8 *lunaddrbytes;
/* Figure out where the LUN ID info is coming from */
- if (i < nphysicals)
- lunaddrbytes = &physdev_list->LUN[i][0];
- else
- if (i < nphysicals + nlogicals)
- lunaddrbytes =
- &logdev_list->LUN[i-nphysicals][0];
- else /* jam in the RAID controller at the end */
- lunaddrbytes = RAID_CTLR_LUNID;
-
+ lunaddrbytes = figure_lunaddrbytes(h, raid_ctlr_position,
+ i, nphysicals, nlogicals, physdev_list, logdev_list);
/* skip masked physical devices. */
- if (lunaddrbytes[3] & 0xC0 && i < nphysicals)
+ if (lunaddrbytes[3] & 0xC0 &&
+ i < nphysicals + (raid_ctlr_position == 0))
continue;
/* Get device type, vendor, model, device id */
@@ -3349,6 +3408,22 @@ err_out_free_res:
return err;
}
+static void __devinit hpsa_hba_inquiry(struct ctlr_info *h)
+{
+ int rc;
+
+#define HBA_INQUIRY_BYTE_COUNT 64
+ h->hba_inquiry_data = kmalloc(HBA_INQUIRY_BYTE_COUNT, GFP_KERNEL);
+ if (!h->hba_inquiry_data)
+ return;
+ rc = hpsa_scsi_do_inquiry(h, RAID_CTLR_LUNID, 0,
+ h->hba_inquiry_data, HBA_INQUIRY_BYTE_COUNT);
+ if (rc != 0) {
+ kfree(h->hba_inquiry_data);
+ h->hba_inquiry_data = NULL;
+ }
+}
+
static int __devinit hpsa_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -3458,6 +3533,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
h->access.set_intr_mask(h, HPSA_INTR_ON);
hpsa_put_ctlr_into_performant_mode(h);
+ hpsa_hba_inquiry(h);
hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */
h->busy_initializing = 0;
return 1;
@@ -3550,6 +3626,7 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev)
h->reply_pool, h->reply_pool_dhandle);
kfree(h->cmd_pool_bits);
kfree(h->blockFetchTable);
+ kfree(h->hba_inquiry_data);
/*
* Deliberately omit pci_disable_device(): it does something nasty to
* Smart Array controllers that pci_enable_device does not undo
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 0ba1aa3..1ab0c1b 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -120,6 +120,7 @@ struct ctlr_info {
size_t reply_pool_size;
unsigned char reply_pool_wraparound;
u32 *blockFetchTable;
+ unsigned char *hba_inquiry_data;
};
#define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1
From: Mike Miller <[email protected]>
hpsa: add pci ids for StorageWorks 1210m, remove p400, p800, p700m
and update pci_ids.h to include new PCI ID for StorageWorks 1210m variant.
Signed-off-by: Mike Miller <[email protected]>
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 11 +++++------
1 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index e518766..46055e2 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -77,9 +77,6 @@ MODULE_PARM_DESC(hpsa_allow_any,
/* define the PCI info for the cards we can control */
static const struct pci_device_id hpsa_pci_device_id[] = {
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3223},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3234},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x323D},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3241},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3243},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3245},
@@ -87,6 +84,9 @@ static const struct pci_device_id hpsa_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3249},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324a},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x324b},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSE, 0x103C, 0x3233},
+#define PCI_DEVICE_ID_HP_CISSF 0x333f
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSF, 0x103C, 0x333F},
{PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
{0,}
@@ -99,9 +99,6 @@ MODULE_DEVICE_TABLE(pci, hpsa_pci_device_id);
* access = Address of the struct of function pointers
*/
static struct board_type products[] = {
- {0x3223103C, "Smart Array P800", &SA5_access},
- {0x3234103C, "Smart Array P400", &SA5_access},
- {0x323d103c, "Smart Array P700M", &SA5_access},
{0x3241103C, "Smart Array P212", &SA5_access},
{0x3243103C, "Smart Array P410", &SA5_access},
{0x3245103C, "Smart Array P410i", &SA5_access},
@@ -109,6 +106,8 @@ static struct board_type products[] = {
{0x3249103C, "Smart Array P812", &SA5_access},
{0x324a103C, "Smart Array P712m", &SA5_access},
{0x324b103C, "Smart Array P711m", &SA5_access},
+ {0x3233103C, "StorageWorks P1210m", &SA5_access},
+ {0x333F103C, "StorageWorks P1210m", &SA5_access},
{0xFFFF103C, "Unknown Smart Array", &SA5_access},
};
From: Don Brace <[email protected]>
hpsa: Allow multiple command completions per interrupt.
This is done by adding support for the so-called "performant mode"
(that's really what they called it). Smart Array controllers
have a mode which enables multiple command completions to be
delivered with a single interrupt, "performant" mode. We want to use
that mode, as some newer controllers will be requiring this mode.
Signed-off-by: Don Brace <[email protected]>
Signed-off-by: Stephen M. Cameron <[email protected]>
Signed-off-by: Mike Miller <[email protected]>
---
drivers/scsi/hpsa.c | 286 ++++++++++++++++++++++++++++++++++++++++-------
drivers/scsi/hpsa.h | 106 ++++++++++++++++-
drivers/scsi/hpsa_cmd.h | 78 ++++++++++---
3 files changed, 404 insertions(+), 66 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 314854b..e518766 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -150,6 +150,11 @@ static int check_for_unit_attention(struct ctlr_info *h,
struct CommandList *c);
static void check_ioctl_unit_attention(struct ctlr_info *h,
struct CommandList *c);
+/* performant mode helper functions */
+static void calc_bucket_map(int *bucket, int num_buckets,
+ int nsgs, int *bucket_map);
+static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h);
+static inline u32 next_command(struct ctlr_info *h);
static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
@@ -173,10 +178,8 @@ static struct scsi_host_template hpsa_driver_template = {
.name = "hpsa",
.proc_name = "hpsa",
.queuecommand = hpsa_scsi_queue_command,
- .can_queue = 512,
.this_id = -1,
.sg_tablesize = MAXSGENTRIES,
- .cmd_per_lun = 512,
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = hpsa_eh_device_reset_handler,
.ioctl = hpsa_ioctl,
@@ -394,10 +397,44 @@ static inline void addQ(struct hlist_head *list, struct CommandList *c)
hlist_add_head(&c->list, list);
}
+static inline u32 next_command(struct ctlr_info *h)
+{
+ u32 a;
+
+ if (unlikely(h->transMethod != CFGTBL_Trans_Performant))
+ return h->access.command_completed(h);
+
+ if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
+ a = *(h->reply_pool_head); /* Next cmd in ring buffer */
+ (h->reply_pool_head)++;
+ h->commands_outstanding--;
+ } else {
+ a = FIFO_EMPTY;
+ }
+ /* Check for wraparound */
+ if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
+ h->reply_pool_head = h->reply_pool;
+ h->reply_pool_wraparound ^= 1;
+ }
+ return a;
+}
+
+/* set_performant_mode: Modify the tag for cciss performant
+ * set bit 0 for pull model, bits 3-1 for block fetch
+ * register number
+ */
+static void set_performant_mode(struct ctlr_info *h, struct CommandList *c)
+{
+ if (likely(h->transMethod == CFGTBL_Trans_Performant))
+ c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
+}
+
static void enqueue_cmd_and_start_io(struct ctlr_info *h,
struct CommandList *c)
{
unsigned long flags;
+
+ set_performant_mode(h, c);
spin_lock_irqsave(&h->lock, flags);
addQ(&h->reqQ, c);
h->Qdepth++;
@@ -1116,9 +1153,11 @@ static int hpsa_scsi_detect(struct ctlr_info *h)
sh->max_cmd_len = MAX_COMMAND_SIZE;
sh->max_lun = HPSA_MAX_LUN;
sh->max_id = HPSA_MAX_LUN;
+ sh->can_queue = h->nr_cmds;
+ sh->cmd_per_lun = h->nr_cmds;
h->scsi_host = sh;
sh->hostdata[0] = (unsigned long) h;
- sh->irq = h->intr[SIMPLE_MODE_INT];
+ sh->irq = h->intr[PERF_MODE_INT];
sh->unique_id = sh->irq;
error = scsi_add_host(sh, &h->pdev->dev);
if (error)
@@ -1843,7 +1882,8 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
c->scsi_cmd = cmd;
c->Header.ReplyQueue = 0; /* unused in simple mode */
memcpy(&c->Header.LUN.LunAddrBytes[0], &scsi3addr[0], 8);
- c->Header.Tag.lower = c->busaddr; /* Use k. address of cmd as tag */
+ c->Header.Tag.lower = (c->cmdindex << DIRECT_LOOKUP_SHIFT);
+ c->Header.Tag.lower |= DIRECT_LOOKUP_BIT;
/* Fill in the request block... */
@@ -2700,8 +2740,9 @@ static inline bool interrupt_pending(struct ctlr_info *h)
static inline long interrupt_not_for_us(struct ctlr_info *h)
{
- return ((h->access.intr_pending(h) == 0) ||
- (h->interrupts_enabled == 0));
+ return !(h->msi_vector || h->msix_vector) &&
+ ((h->access.intr_pending(h) == 0) ||
+ (h->interrupts_enabled == 0));
}
static inline int bad_tag(struct ctlr_info *h, u32 tag_index,
@@ -2725,13 +2766,13 @@ static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
static inline u32 hpsa_tag_contains_index(u32 tag)
{
-#define DIRECT_LOOKUP_BIT 0x04
+#define DIRECT_LOOKUP_BIT 0x10
return tag & DIRECT_LOOKUP_BIT;
}
static inline u32 hpsa_tag_to_index(u32 tag)
{
-#define DIRECT_LOOKUP_SHIFT 3
+#define DIRECT_LOOKUP_SHIFT 5
return tag >> DIRECT_LOOKUP_SHIFT;
}
@@ -2741,42 +2782,61 @@ static inline u32 hpsa_tag_discard_error_bits(u32 tag)
return tag & ~HPSA_ERROR_BITS;
}
+/* process completion of an indexed ("direct lookup") command */
+static inline u32 process_indexed_cmd(struct ctlr_info *h,
+ u32 raw_tag)
+{
+ u32 tag_index;
+ struct CommandList *c;
+
+ tag_index = hpsa_tag_to_index(raw_tag);
+ if (bad_tag(h, tag_index, raw_tag))
+ return next_command(h);
+ c = h->cmd_pool + tag_index;
+ finish_cmd(c, raw_tag);
+ return next_command(h);
+}
+
+/* process completion of a non-indexed command */
+static inline u32 process_nonindexed_cmd(struct ctlr_info *h,
+ u32 raw_tag)
+{
+ u32 tag;
+ struct CommandList *c = NULL;
+ struct hlist_node *tmp;
+
+ tag = hpsa_tag_discard_error_bits(raw_tag);
+ hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
+ if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) {
+ finish_cmd(c, raw_tag);
+ return next_command(h);
+ }
+ }
+ bad_tag(h, h->nr_cmds + 1, raw_tag);
+ return next_command(h);
+}
+
static irqreturn_t do_hpsa_intr(int irq, void *dev_id)
{
struct ctlr_info *h = dev_id;
- struct CommandList *c;
unsigned long flags;
- u32 raw_tag, tag, tag_index;
- struct hlist_node *tmp;
+ u32 raw_tag;
if (interrupt_not_for_us(h))
return IRQ_NONE;
spin_lock_irqsave(&h->lock, flags);
- while (interrupt_pending(h)) {
- while ((raw_tag = get_next_completion(h)) != FIFO_EMPTY) {
- if (likely(hpsa_tag_contains_index(raw_tag))) {
- tag_index = hpsa_tag_to_index(raw_tag);
- if (bad_tag(h, tag_index, raw_tag))
- return IRQ_HANDLED;
- c = h->cmd_pool + tag_index;
- finish_cmd(c, raw_tag);
- continue;
- }
- tag = hpsa_tag_discard_error_bits(raw_tag);
- c = NULL;
- hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
- if (c->busaddr == tag) {
- finish_cmd(c, raw_tag);
- break;
- }
- }
- }
+ raw_tag = get_next_completion(h);
+ while (raw_tag != FIFO_EMPTY) {
+ if (hpsa_tag_contains_index(raw_tag))
+ raw_tag = process_indexed_cmd(h, raw_tag);
+ else
+ raw_tag = process_nonindexed_cmd(h, raw_tag);
}
spin_unlock_irqrestore(&h->lock, flags);
return IRQ_HANDLED;
}
-/* Send a message CDB to the firmware. */
+/* Send a message CDB to the firmwart. */
static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
unsigned char type)
{
@@ -3108,7 +3168,7 @@ static void __devinit hpsa_interrupt_mode(struct ctlr_info *h,
default_int_mode:
#endif /* CONFIG_PCI_MSI */
/* if we get here we're going to use the default interrupt mode */
- h->intr[SIMPLE_MODE_INT] = pdev->irq;
+ h->intr[PERF_MODE_INT] = pdev->irq;
}
static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
@@ -3118,6 +3178,7 @@ static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
u64 cfg_offset;
u32 cfg_base_addr;
u64 cfg_base_addr_index;
+ u32 trans_offset;
int i, prod_index, err;
subsystem_vendor_id = pdev->subsystem_vendor;
@@ -3211,11 +3272,14 @@ static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
h->cfgtable = remap_pci_mem(pci_resource_start(pdev,
cfg_base_addr_index) + cfg_offset,
sizeof(h->cfgtable));
- h->board_id = board_id;
-
- /* Query controller for max supported commands: */
- h->max_commands = readl(&(h->cfgtable->CmdsOutMax));
+ /* Find performant mode table. */
+ trans_offset = readl(&(h->cfgtable->TransMethodOffset));
+ h->transtable = remap_pci_mem(pci_resource_start(pdev,
+ cfg_base_addr_index)+cfg_offset+trans_offset,
+ sizeof(*h->transtable));
+ h->board_id = board_id;
+ h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
h->product_name = products[prod_index].product_name;
h->access = *(products[prod_index].access);
/* Allow room for some ioctls */
@@ -3314,7 +3378,12 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
}
}
- BUILD_BUG_ON(sizeof(struct CommandList) % 8);
+ /* Command structures must be aligned on a 32-byte boundary because
+ * the 5 lower bits of the address are used by the hardware. and by
+ * the driver. See comments in hpsa.h for more info.
+ */
+#define COMMANDLIST_ALIGNMENT 32
+ BUILD_BUG_ON(sizeof(struct CommandList) % COMMANDLIST_ALIGNMENT);
h = kzalloc(sizeof(*h), GFP_KERNEL);
if (!h)
return -ENOMEM;
@@ -3349,17 +3418,17 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
/* make sure the board interrupts are off */
h->access.set_intr_mask(h, HPSA_INTR_OFF);
- rc = request_irq(h->intr[SIMPLE_MODE_INT], do_hpsa_intr,
- IRQF_DISABLED | IRQF_SHARED, h->devname, h);
+ rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr,
+ IRQF_DISABLED, h->devname, h);
if (rc) {
dev_err(&pdev->dev, "unable to get irq %d for %s\n",
- h->intr[SIMPLE_MODE_INT], h->devname);
+ h->intr[PERF_MODE_INT], h->devname);
goto clean2;
}
- dev_info(&pdev->dev, "%s: <0x%x> at PCI %s IRQ %d%s using DAC\n",
- h->devname, pdev->device, pci_name(pdev),
- h->intr[SIMPLE_MODE_INT], dac ? "" : " not");
+ dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n",
+ h->devname, pdev->device,
+ h->intr[PERF_MODE_INT], dac ? "" : " not");
h->cmd_pool_bits =
kmalloc(((h->nr_cmds + BITS_PER_LONG -
@@ -3389,6 +3458,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
/* Turn the interrupts on so we can service requests */
h->access.set_intr_mask(h, HPSA_INTR_ON);
+ hpsa_put_ctlr_into_performant_mode(h);
hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */
h->busy_initializing = 0;
return 1;
@@ -3404,7 +3474,7 @@ clean4:
h->nr_cmds * sizeof(struct ErrorInfo),
h->errinfo_pool,
h->errinfo_pool_dhandle);
- free_irq(h->intr[SIMPLE_MODE_INT], h);
+ free_irq(h->intr[PERF_MODE_INT], h);
clean2:
clean1:
h->busy_initializing = 0;
@@ -3448,7 +3518,7 @@ static void hpsa_shutdown(struct pci_dev *pdev)
*/
hpsa_flush_cache(h);
h->access.set_intr_mask(h, HPSA_INTR_OFF);
- free_irq(h->intr[2], h);
+ free_irq(h->intr[PERF_MODE_INT], h);
#ifdef CONFIG_PCI_MSI
if (h->msix_vector)
pci_disable_msix(h->pdev);
@@ -3477,7 +3547,10 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev)
pci_free_consistent(h->pdev,
h->nr_cmds * sizeof(struct ErrorInfo),
h->errinfo_pool, h->errinfo_pool_dhandle);
+ pci_free_consistent(h->pdev, h->reply_pool_size,
+ h->reply_pool, h->reply_pool_dhandle);
kfree(h->cmd_pool_bits);
+ kfree(h->blockFetchTable);
/*
* Deliberately omit pci_disable_device(): it does something nasty to
* Smart Array controllers that pci_enable_device does not undo
@@ -3509,6 +3582,129 @@ static struct pci_driver hpsa_pci_driver = {
.resume = hpsa_resume,
};
+/* Fill in bucket_map[], given nsgs (the max number of
+ * scatter gather elements supported) and bucket[],
+ * which is an array of 8 integers. The bucket[] array
+ * contains 8 different DMA transfer sizes (in 16
+ * byte increments) which the controller uses to fetch
+ * commands. This function fills in bucket_map[], which
+ * maps a given number of scatter gather elements to one of
+ * the 8 DMA transfer sizes. The point of it is to allow the
+ * controller to only do as much DMA as needed to fetch the
+ * command, with the DMA transfer size encoded in the lower
+ * bits of the command address.
+ */
+static void calc_bucket_map(int bucket[], int num_buckets,
+ int nsgs, int *bucket_map)
+{
+ int i, j, b, size;
+
+ /* even a command with 0 SGs requires 4 blocks */
+#define MINIMUM_TRANSFER_BLOCKS 4
+#define NUM_BUCKETS 8
+ /* Note, bucket_map must have nsgs+1 entries. */
+ for (i = 0; i <= nsgs; i++) {
+ /* Compute size of a command with i SG entries */
+ size = i + MINIMUM_TRANSFER_BLOCKS;
+ b = num_buckets; /* Assume the biggest bucket */
+ /* Find the bucket that is just big enough */
+ for (j = 0; j < 8; j++) {
+ if (bucket[j] >= size) {
+ b = j;
+ break;
+ }
+ }
+ /* for a command with i SG entries, use bucket b. */
+ bucket_map[i] = b;
+ }
+}
+
+static void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
+{
+ u32 trans_support;
+ u64 trans_offset;
+ /* 5 = 1 s/g entry or 4k
+ * 6 = 2 s/g entry or 8k
+ * 8 = 4 s/g entry or 16k
+ * 10 = 6 s/g entry or 24k
+ */
+ int bft[8] = {5, 6, 8, 10, 12, 20, 28, 35}; /* for scatter/gathers */
+ int i = 0;
+ int l = 0;
+ unsigned long register_value;
+
+ trans_support = readl(&(h->cfgtable->TransportSupport));
+ if (!(trans_support & PERFORMANT_MODE))
+ return;
+
+ h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
+ h->max_sg_entries = 32;
+ /* Performant mode ring buffer and supporting data structures */
+ h->reply_pool_size = h->max_commands * sizeof(u64);
+ h->reply_pool = pci_alloc_consistent(h->pdev, h->reply_pool_size,
+ &(h->reply_pool_dhandle));
+
+ /* Need a block fetch table for performant mode */
+ h->blockFetchTable = kmalloc(((h->max_sg_entries+1) *
+ sizeof(u32)), GFP_KERNEL);
+
+ if ((h->reply_pool == NULL)
+ || (h->blockFetchTable == NULL))
+ goto clean_up;
+
+ h->reply_pool_wraparound = 1; /* spec: init to 1 */
+
+ /* Controller spec: zero out this buffer. */
+ memset(h->reply_pool, 0, h->reply_pool_size);
+ h->reply_pool_head = h->reply_pool;
+
+ trans_offset = readl(&(h->cfgtable->TransMethodOffset));
+ bft[7] = h->max_sg_entries + 4;
+ calc_bucket_map(bft, ARRAY_SIZE(bft), 32, h->blockFetchTable);
+ for (i = 0; i < 8; i++)
+ writel(bft[i], &h->transtable->BlockFetch[i]);
+
+ /* size of controller ring buffer */
+ writel(h->max_commands, &h->transtable->RepQSize);
+ writel(1, &h->transtable->RepQCount);
+ writel(0, &h->transtable->RepQCtrAddrLow32);
+ writel(0, &h->transtable->RepQCtrAddrHigh32);
+ writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32);
+ writel(0, &h->transtable->RepQAddr0High32);
+ writel(CFGTBL_Trans_Performant,
+ &(h->cfgtable->HostWrite.TransportRequest));
+ writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
+ /* under certain very rare conditions, this can take awhile.
+ * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
+ * as we enter this code.) */
+ for (l = 0; l < MAX_CONFIG_WAIT; l++) {
+ register_value = readl(h->vaddr + SA5_DOORBELL);
+ if (!(register_value & CFGTBL_ChangeReq))
+ break;
+ /* delay and try again */
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(10);
+ }
+ register_value = readl(&(h->cfgtable->TransportActive));
+ if (!(register_value & CFGTBL_Trans_Performant)) {
+ dev_warn(&h->pdev->dev, "unable to get board into"
+ " performant mode\n");
+ return;
+ }
+
+ /* Change the access methods to the performant access methods */
+ h->access = SA5_performant_access;
+ h->transMethod = CFGTBL_Trans_Performant;
+
+ return;
+
+clean_up:
+ if (h->reply_pool)
+ pci_free_consistent(h->pdev, h->reply_pool_size,
+ h->reply_pool, h->reply_pool_dhandle);
+ kfree(h->blockFetchTable);
+}
+
/*
* This is it. Register the PCI driver information for the cards we control
* the OS will call our registered routines when it finds one of our cards.
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 0eab386..0ba1aa3 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -60,14 +60,15 @@ struct ctlr_info {
unsigned long paddr;
int nr_cmds; /* Number of commands allowed on this controller */
struct CfgTable __iomem *cfgtable;
+ int max_sg_entries;
int interrupts_enabled;
int major;
int max_commands;
int commands_outstanding;
int max_outstanding; /* Debug */
int usage_count; /* number of opens all all minor devices */
-# define DOORBELL_INT 0
-# define PERF_MODE_INT 1
+# define PERF_MODE_INT 0
+# define DOORBELL_INT 1
# define SIMPLE_MODE_INT 2
# define MEMQ_MODE_INT 3
unsigned int intr[4];
@@ -102,6 +103,23 @@ struct ctlr_info {
int ndevices; /* number of used elements in .dev[] array. */
#define HPSA_MAX_SCSI_DEVS_PER_HBA 256
struct hpsa_scsi_dev_t *dev[HPSA_MAX_SCSI_DEVS_PER_HBA];
+ /*
+ * Performant mode tables.
+ */
+ u32 trans_support;
+ u32 trans_offset;
+ struct TransTable_struct *transtable;
+ unsigned long transMethod;
+
+ /*
+ * Performant mode completion buffer
+ */
+ u64 *reply_pool;
+ dma_addr_t reply_pool_dhandle;
+ u64 *reply_pool_head;
+ size_t reply_pool_size;
+ unsigned char reply_pool_wraparound;
+ u32 *blockFetchTable;
};
#define HPSA_ABORT_MSG 0
#define HPSA_DEVICE_RESET_MSG 1
@@ -165,6 +183,16 @@ struct ctlr_info {
#define HPSA_ERROR_BIT 0x02
+/* Performant mode flags */
+#define SA5_PERF_INTR_PENDING 0x04
+#define SA5_PERF_INTR_OFF 0x05
+#define SA5_OUTDB_STATUS_PERF_BIT 0x01
+#define SA5_OUTDB_CLEAR_PERF_BIT 0x01
+#define SA5_OUTDB_CLEAR 0xA0
+#define SA5_OUTDB_CLEAR_PERF_BIT 0x01
+#define SA5_OUTDB_STATUS 0x9C
+
+
#define HPSA_INTR_ON 1
#define HPSA_INTR_OFF 0
/*
@@ -173,7 +201,8 @@ struct ctlr_info {
static void SA5_submit_command(struct ctlr_info *h,
struct CommandList *c)
{
- dev_dbg(&h->pdev->dev, "Sending %x\n", c->busaddr);
+ dev_dbg(&h->pdev->dev, "Sending %x, tag = %x\n", c->busaddr,
+ c->Header.Tag.lower);
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
h->commands_outstanding++;
if (h->commands_outstanding > h->max_outstanding)
@@ -196,6 +225,52 @@ static void SA5_intr_mask(struct ctlr_info *h, unsigned long val)
h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
}
}
+
+static void SA5_performant_intr_mask(struct ctlr_info *h, unsigned long val)
+{
+ if (val) { /* turn on interrupts */
+ h->interrupts_enabled = 1;
+ writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+ } else {
+ h->interrupts_enabled = 0;
+ writel(SA5_PERF_INTR_OFF,
+ h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+ }
+}
+
+static unsigned long SA5_performant_completed(struct ctlr_info *h)
+{
+ unsigned long register_value = FIFO_EMPTY;
+
+ /* flush the controller write of the reply queue by reading
+ * outbound doorbell status register.
+ */
+ register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
+ /* msi auto clears the interrupt pending bit. */
+ if (!(h->msi_vector || h->msix_vector)) {
+ writel(SA5_OUTDB_CLEAR_PERF_BIT, h->vaddr + SA5_OUTDB_CLEAR);
+ /* Do a read in order to flush the write to the controller
+ * (as per spec.)
+ */
+ register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
+ }
+
+ if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
+ register_value = *(h->reply_pool_head);
+ (h->reply_pool_head)++;
+ h->commands_outstanding--;
+ } else {
+ register_value = FIFO_EMPTY;
+ }
+ /* Check for wraparound */
+ if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
+ h->reply_pool_head = h->reply_pool;
+ h->reply_pool_wraparound ^= 1;
+ }
+
+ return register_value;
+}
+
/*
* Returns true if fifo is full.
*
@@ -241,6 +316,20 @@ static bool SA5_intr_pending(struct ctlr_info *h)
return register_value & SA5_INTR_PENDING;
}
+static bool SA5_performant_intr_pending(struct ctlr_info *h)
+{
+ unsigned long register_value = readl(h->vaddr + SA5_INTR_STATUS);
+
+ if (!register_value)
+ return false;
+
+ if (h->msi_vector || h->msix_vector)
+ return true;
+
+ /* Read outbound doorbell to flush */
+ register_value = readl(h->vaddr + SA5_OUTDB_STATUS);
+ return register_value & SA5_OUTDB_STATUS_PERF_BIT;
+}
static struct access_method SA5_access = {
SA5_submit_command,
@@ -250,14 +339,19 @@ static struct access_method SA5_access = {
SA5_completed,
};
+static struct access_method SA5_performant_access = {
+ SA5_submit_command,
+ SA5_performant_intr_mask,
+ SA5_fifo_full,
+ SA5_performant_intr_pending,
+ SA5_performant_completed,
+};
+
struct board_type {
u32 board_id;
char *product_name;
struct access_method *access;
};
-
-/* end of old hpsa_scsi.h file */
-
#endif /* HPSA_H */
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 88bb3b0..3e0abdf 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -101,6 +101,7 @@
#define CFGTBL_AccCmds 0x00000001l
#define CFGTBL_Trans_Simple 0x00000002l
+#define CFGTBL_Trans_Performant 0x00000004l
#define CFGTBL_BusType_Ultra2 0x00000001l
#define CFGTBL_BusType_Ultra3 0x00000002l
@@ -267,12 +268,31 @@ struct ErrorInfo {
#define CMD_IOCTL_PEND 0x01
#define CMD_SCSI 0x03
+/* This structure needs to be divisible by 32 for new
+ * indexing method and performant mode.
+ */
+#define PAD32 32
+#define PAD64DIFF 0
+#define USEEXTRA ((sizeof(void *) - 4)/4)
+#define PADSIZE (PAD32 + PAD64DIFF * USEEXTRA)
+
+#define DIRECT_LOOKUP_SHIFT 5
+#define DIRECT_LOOKUP_BIT 0x10
+
+#define HPSA_ERROR_BIT 0x02
struct ctlr_info; /* defined in hpsa.h */
-/* The size of this structure needs to be divisible by 8
- * on all architectures, because the controller uses 2
- * lower bits of the address, and the driver uses 1 lower
- * bit (3 bits total.)
+/* The size of this structure needs to be divisible by 32
+ * on all architectures because low 5 bits of the addresses
+ * are used as follows:
+ *
+ * bit 0: to device, used to indicate "performant mode" command
+ * from device, indidcates error status.
+ * bit 1-3: to device, indicates block fetch table entry for
+ * reducing DMA in fetching commands from host memory.
+ * bit 4: used to indicate whether tag is "direct lookup" (index),
+ * or a bus address.
*/
+
struct CommandList {
struct CommandListHeader Header;
struct RequestBlock Request;
@@ -291,6 +311,14 @@ struct CommandList {
struct completion *waiting;
int retry_count;
void *scsi_cmd;
+
+/* on 64 bit architectures, to get this to be 32-byte-aligned
+ * it so happens we need no padding, on 32 bit systems,
+ * we need 8 bytes of padding. This does that.
+ */
+#define COMMANDLIST_PAD ((8 - sizeof(long))/4 * 8)
+ u8 pad[COMMANDLIST_PAD];
+
};
/* Configuration Table Structure */
@@ -301,18 +329,38 @@ struct HostWrite {
u32 CoalIntCount;
};
+#define SIMPLE_MODE 0x02
+#define PERFORMANT_MODE 0x04
+#define MEMQ_MODE 0x08
+
struct CfgTable {
- u8 Signature[4];
- u32 SpecValence;
- u32 TransportSupport;
- u32 TransportActive;
- struct HostWrite HostWrite;
- u32 CmdsOutMax;
- u32 BusTypes;
- u32 Reserved;
- u8 ServerName[16];
- u32 HeartBeat;
- u32 SCSI_Prefetch;
+ u8 Signature[4];
+ u32 SpecValence;
+ u32 TransportSupport;
+ u32 TransportActive;
+ struct HostWrite HostWrite;
+ u32 CmdsOutMax;
+ u32 BusTypes;
+ u32 TransMethodOffset;
+ u8 ServerName[16];
+ u32 HeartBeat;
+ u32 SCSI_Prefetch;
+ u32 MaxScatterGatherElements;
+ u32 MaxLogicalUnits;
+ u32 MaxPhysicalDevices;
+ u32 MaxPhysicalDrivesPerLogicalUnit;
+ u32 MaxPerformantModeCommands;
+};
+
+#define NUM_BLOCKFETCH_ENTRIES 8
+struct TransTable_struct {
+ u32 BlockFetch[NUM_BLOCKFETCH_ENTRIES];
+ u32 RepQSize;
+ u32 RepQCount;
+ u32 RepQCtrAddrLow32;
+ u32 RepQCtrAddrHigh32;
+ u32 RepQAddr0Low32;
+ u32 RepQAddr0High32;
};
struct hpsa_pci_info {
From: Stephen M. Cameron <[email protected]>
hpsa: remove superfluous returns from void functions.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 6fe5142..9017e64 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -898,7 +898,7 @@ static int hpsa_slave_alloc(struct scsi_device *sdev)
static void hpsa_slave_destroy(struct scsi_device *sdev)
{
- return; /* nothing to do. */
+ /* nothing to do. */
}
static void hpsa_scsi_setup(struct ctlr_info *h)
@@ -906,7 +906,6 @@ static void hpsa_scsi_setup(struct ctlr_info *h)
h->ndevices = 0;
h->scsi_host = NULL;
spin_lock_init(&h->devlock);
- return;
}
static void complete_scsi_command(struct CommandList *cp,
@@ -1775,7 +1774,6 @@ out:
kfree(inq_buff);
kfree(physdev_list);
kfree(logdev_list);
- return;
}
/* hpsa_scatter_gather takes a struct scsi_cmnd, (cmd), and does the pci
@@ -3106,7 +3104,6 @@ default_int_mode:
#endif /* CONFIG_PCI_MSI */
/* if we get here we're going to use the default interrupt mode */
h->intr[SIMPLE_MODE_INT] = pdev->irq;
- return;
}
static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
From: Stephen M. Cameron <[email protected]>
hpsa: eliminate unnecessary memcpys
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 11 +++--------
1 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 4594200..ba3dead 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1483,14 +1483,11 @@ static void figure_bus_target_lun(struct ctlr_info *h,
u8 *lunaddrbytes, int *bus, int *target, int *lun,
struct hpsa_scsi_dev_t *device)
{
-
u32 lunid;
if (is_logical_dev_addr_mode(lunaddrbytes)) {
/* logical device */
- memcpy(&lunid, lunaddrbytes, sizeof(lunid));
- lunid = le32_to_cpu(lunid);
-
+ lunid = le32_to_cpu(*((__le32 *) lunaddrbytes));
if (is_msa2xxx(h, device)) {
*bus = 1;
*target = (lunid >> 16) & 0x3fff;
@@ -1578,8 +1575,7 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
return -1;
}
- memcpy(nphysicals, &physdev->LUNListLength[0], sizeof(*nphysicals));
- *nphysicals = be32_to_cpu(*nphysicals) / 8;
+ *nphysicals = be32_to_cpu(*((__be32 *)physdev->LUNListLength)) / 8;
if (*nphysicals > HPSA_MAX_PHYS_LUN) {
dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded."
" %d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
@@ -1590,8 +1586,7 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
dev_err(&h->pdev->dev, "report logical LUNs failed.\n");
return -1;
}
- memcpy(nlogicals, &logdev->LUNListLength[0], sizeof(*nlogicals));
- *nlogicals = be32_to_cpu(*nlogicals) / 8;
+ *nlogicals = be32_to_cpu(*((__be32 *) logdev->LUNListLength)) / 8;
/* Reject Logicals in excess of our max capability. */
if (*nlogicals > HPSA_MAX_LUN) {
dev_warn(&h->pdev->dev,
From: Stephen M. Cameron <[email protected]>
hpsa: fix some debug printks to use dev_dbg instead
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.h | 13 ++++---------
1 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index da8dd3e..cdac95b 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -173,10 +173,7 @@ struct ctlr_info {
static void SA5_submit_command(struct ctlr_info *h,
struct CommandList *c)
{
-#ifdef HPSA_DEBUG
- printk(KERN_WARNING "hpsa: Sending %x - down to controller\n",
- c->busaddr);
-#endif /* HPSA_DEBUG */
+ dev_dbg(&h->pdev->dev, "Sending %x\n", c->busaddr);
writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
h->commands_outstanding++;
if (h->commands_outstanding > h->max_outstanding)
@@ -225,10 +222,10 @@ static unsigned long SA5_completed(struct ctlr_info *h)
#ifdef HPSA_DEBUG
if (register_value != FIFO_EMPTY)
- printk(KERN_INFO "hpsa: Read %lx back from board\n",
+ dev_dbg(&h->pdev->dev, "Read %lx back from board\n",
register_value);
else
- printk(KERN_INFO "hpsa: FIFO Empty read\n");
+ dev_dbg(&h->pdev->dev, "hpsa: FIFO Empty read\n");
#endif
return register_value;
@@ -240,9 +237,7 @@ static unsigned long SA5_intr_pending(struct ctlr_info *h)
{
unsigned long register_value =
readl(h->vaddr + SA5_INTR_STATUS);
-#ifdef HPSA_DEBUG
- printk(KERN_INFO "hpsa: intr_pending %lx\n", register_value);
-#endif /* HPSA_DEBUG */
+ dev_dbg(&h->pdev->dev, "intr_pending %lx\n", register_value);
if (register_value & SA5_INTR_PENDING)
return 1;
return 0 ;
From: Stephen M. Cameron <[email protected]>
hpsa: make tag macros into functions
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 26 ++++++++++++++++++++++----
drivers/scsi/hpsa.h | 3 ---
2 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index ba3dead..82987e1 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -2723,6 +2723,24 @@ static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
complete(c->waiting);
}
+static inline u32 hpsa_tag_contains_index(u32 tag)
+{
+#define DIRECT_LOOKUP_BIT 0x04
+ return tag & DIRECT_LOOKUP_BIT;
+}
+
+static inline u32 hpsa_tag_to_index(u32 tag)
+{
+#define DIRECT_LOOKUP_SHIFT 3
+ return tag >> DIRECT_LOOKUP_SHIFT;
+}
+
+static inline u32 hpsa_tag_discard_error_bits(u32 tag)
+{
+#define HPSA_ERROR_BITS 0x03
+ return tag & ~HPSA_ERROR_BITS;
+}
+
static irqreturn_t do_hpsa_intr(int irq, void *dev_id)
{
struct ctlr_info *h = dev_id;
@@ -2736,15 +2754,15 @@ static irqreturn_t do_hpsa_intr(int irq, void *dev_id)
spin_lock_irqsave(&h->lock, flags);
while (interrupt_pending(h)) {
while ((raw_tag = get_next_completion(h)) != FIFO_EMPTY) {
- if (likely(HPSA_TAG_CONTAINS_INDEX(raw_tag))) {
- tag_index = HPSA_TAG_TO_INDEX(raw_tag);
+ if (likely(hpsa_tag_contains_index(raw_tag))) {
+ tag_index = hpsa_tag_to_index(raw_tag);
if (bad_tag(h, tag_index, raw_tag))
return IRQ_HANDLED;
c = h->cmd_pool + tag_index;
finish_cmd(c, raw_tag);
continue;
}
- tag = HPSA_TAG_DISCARD_ERROR_BITS(raw_tag);
+ tag = hpsa_tag_discard_error_bits(raw_tag);
c = NULL;
hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
if (c->busaddr == tag) {
@@ -2824,7 +2842,7 @@ static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) {
tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
- if (HPSA_TAG_DISCARD_ERROR_BITS(tag) == paddr32)
+ if (hpsa_tag_discard_error_bits(tag) == paddr32)
break;
msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS);
}
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 194968e..da8dd3e 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -164,9 +164,6 @@ struct ctlr_info {
#define HPSA_FIRMWARE_READY 0xffff0000 /* value in scratchpad register */
#define HPSA_ERROR_BIT 0x02
-#define HPSA_TAG_CONTAINS_INDEX(tag) ((tag) & 0x04)
-#define HPSA_TAG_TO_INDEX(tag) ((tag) >> 3)
-#define HPSA_TAG_DISCARD_ERROR_BITS(tag) ((tag) & ~3)
#define HPSA_INTR_ON 1
#define HPSA_INTR_OFF 0
From: Stephen M. Cameron <[email protected]>
hpsa: Use BUG_ON instead of an if statement.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index ee9db5e..2c256e3 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -628,8 +628,7 @@ static void hpsa_scsi_remove_entry(struct ctlr_info *h, int hostno, int entry,
int i;
struct hpsa_scsi_dev_t *sd;
- if (entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA)
- BUG();
+ BUG_ON(entry < 0 || entry >= HPSA_MAX_SCSI_DEVS_PER_HBA);
sd = h->dev[entry];
removed[*nremoved] = h->dev[entry];
From: Stephen M. Cameron <[email protected]>
hpsa: avoid unwanted promotion from unsigned to signed for raid level index
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 0f4a1f3..ee9db5e 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -431,7 +431,7 @@ static ssize_t raid_level_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
ssize_t l = 0;
- int rlevel;
+ unsigned char rlevel;
struct ctlr_info *h;
struct scsi_device *sdev;
struct hpsa_scsi_dev_t *hdev;
@@ -455,7 +455,7 @@ static ssize_t raid_level_show(struct device *dev,
rlevel = hdev->raid_level;
spin_unlock_irqrestore(&h->lock, flags);
- if (rlevel < 0 || rlevel > RAID_UNKNOWN)
+ if (rlevel > RAID_UNKNOWN)
rlevel = RAID_UNKNOWN;
l = snprintf(buf, PAGE_SIZE, "RAID %s\n", raid_label[rlevel]);
return l;
From: Stephen M. Cameron <[email protected]>
hpsa: fix typo in comments
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa_cmd.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 12d7138..2df1c66 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -269,7 +269,7 @@ struct ErrorInfo {
struct ctlr_info; /* defined in hpsa.h */
/* The size of this structure needs to be divisible by 8
- * od on all architectures, because the controller uses 2
+ * on all architectures, because the controller uses 2
* lower bits of the address, and the driver uses 1 lower
* bit (3 bits total.)
*/
From: Stephen M. Cameron <[email protected]>
hpsa: Use kernel integer types, not userland ones
That is, use u64, u32, u16 and u8 rather than __u64, __u32, __u16 and __u8.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 90 ++++++++++++++---------------
drivers/scsi/hpsa.h | 4 +
drivers/scsi/hpsa_cmd.h | 146 ++++++++++++++++++++++++-----------------------
3 files changed, 120 insertions(+), 120 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index bb96fdd..0f4a1f3 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -126,8 +126,8 @@ static void cmd_free(struct ctlr_info *h, struct CommandList *c);
static void cmd_special_free(struct ctlr_info *h, struct CommandList *c);
static struct CommandList *cmd_alloc(struct ctlr_info *h);
static struct CommandList *cmd_special_alloc(struct ctlr_info *h);
-static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h,
- void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr,
+static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
+ void *buff, size_t size, u8 page_code, unsigned char *scsi3addr,
int cmd_type);
static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
@@ -912,7 +912,7 @@ static void hpsa_scsi_setup(struct ctlr_info *h)
}
static void complete_scsi_command(struct CommandList *cp,
- int timeout, __u32 tag)
+ int timeout, u32 tag)
{
struct scsi_cmnd *cmd;
struct ctlr_info *h;
@@ -1160,7 +1160,7 @@ static void hpsa_map_one(struct pci_dev *pdev,
size_t buflen,
int data_direction)
{
- __u64 addr64;
+ u64 addr64;
if (buflen == 0 || data_direction == PCI_DMA_NONE) {
cp->Header.SGList = 0;
@@ -1168,14 +1168,14 @@ static void hpsa_map_one(struct pci_dev *pdev,
return;
}
- addr64 = (__u64) pci_map_single(pdev, buf, buflen, data_direction);
+ addr64 = (u64) pci_map_single(pdev, buf, buflen, data_direction);
cp->SG[0].Addr.lower =
- (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+ (u32) (addr64 & (u64) 0x00000000FFFFFFFF);
cp->SG[0].Addr.upper =
- (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+ (u32) ((addr64 >> 32) & (u64) 0x00000000FFFFFFFF);
cp->SG[0].Len = buflen;
- cp->Header.SGList = (__u8) 1; /* no. SGs contig in this cmd */
- cp->Header.SGTotal = (__u16) 1; /* total sgs in this cmd list */
+ cp->Header.SGList = (u8) 1; /* no. SGs contig in this cmd */
+ cp->Header.SGTotal = (u16) 1; /* total sgs in this cmd list */
}
static inline void hpsa_scsi_do_simple_cmd_core(struct ctlr_info *h,
@@ -1485,11 +1485,11 @@ static int is_msa2xxx(struct ctlr_info *h, struct hpsa_scsi_dev_t *device)
* in hpsa_find_target_lun, called by hpsa_scsi_add_entry.)
*/
static void figure_bus_target_lun(struct ctlr_info *h,
- __u8 *lunaddrbytes, int *bus, int *target, int *lun,
+ u8 *lunaddrbytes, int *bus, int *target, int *lun,
struct hpsa_scsi_dev_t *device)
{
- __u32 lunid;
+ u32 lunid;
if (is_logical_dev_addr_mode(lunaddrbytes)) {
/* logical device */
@@ -1529,7 +1529,7 @@ static void figure_bus_target_lun(struct ctlr_info *h,
*/
static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
struct hpsa_scsi_dev_t *tmpdevice,
- struct hpsa_scsi_dev_t *this_device, __u8 *lunaddrbytes,
+ struct hpsa_scsi_dev_t *this_device, u8 *lunaddrbytes,
int bus, int target, int lun, unsigned long lunzerobits[],
int *nmsa2xxx_enclosures)
{
@@ -1576,8 +1576,8 @@ static int add_msa2xxx_enclosure_device(struct ctlr_info *h,
*/
static int hpsa_gather_lun_info(struct ctlr_info *h,
int reportlunsize,
- struct ReportLUNdata *physdev, __u32 *nphysicals,
- struct ReportLUNdata *logdev, __u32 *nlogicals)
+ struct ReportLUNdata *physdev, u32 *nphysicals,
+ struct ReportLUNdata *logdev, u32 *nlogicals)
{
if (hpsa_scsi_do_report_phys_luns(h, physdev, reportlunsize, 0)) {
dev_err(&h->pdev->dev, "report physical LUNs failed.\n");
@@ -1636,9 +1636,9 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
struct ReportLUNdata *physdev_list = NULL;
struct ReportLUNdata *logdev_list = NULL;
unsigned char *inq_buff = NULL;
- __u32 nphysicals = 0;
- __u32 nlogicals = 0;
- __u32 ndev_allocated = 0;
+ u32 nphysicals = 0;
+ u32 nlogicals = 0;
+ u32 ndev_allocated = 0;
struct hpsa_scsi_dev_t **currentsd, *this_device, *tmpdevice;
int ncurrent = 0;
int reportlunsize = sizeof(*physdev_list) + HPSA_MAX_PHYS_LUN * 8;
@@ -1684,7 +1684,7 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
/* adjust our table of devices */
nmsa2xxx_enclosures = 0;
for (i = 0; i < nphysicals + nlogicals + 1; i++) {
- __u8 *lunaddrbytes;
+ u8 *lunaddrbytes;
/* Figure out where the LUN ID info is coming from */
if (i < nphysicals)
@@ -1790,7 +1790,7 @@ static int hpsa_scatter_gather(struct pci_dev *pdev,
{
unsigned int len;
struct scatterlist *sg;
- __u64 addr64;
+ u64 addr64;
int use_sg, i;
BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
@@ -1803,20 +1803,20 @@ static int hpsa_scatter_gather(struct pci_dev *pdev,
goto sglist_finished;
scsi_for_each_sg(cmd, sg, use_sg, i) {
- addr64 = (__u64) sg_dma_address(sg);
+ addr64 = (u64) sg_dma_address(sg);
len = sg_dma_len(sg);
cp->SG[i].Addr.lower =
- (__u32) (addr64 & (__u64) 0x00000000FFFFFFFF);
+ (u32) (addr64 & (u64) 0x00000000FFFFFFFF);
cp->SG[i].Addr.upper =
- (__u32) ((addr64 >> 32) & (__u64) 0x00000000FFFFFFFF);
+ (u32) ((addr64 >> 32) & (u64) 0x00000000FFFFFFFF);
cp->SG[i].Len = len;
cp->SG[i].Ext = 0; /* we are not chaining */
}
sglist_finished:
- cp->Header.SGList = (__u8) use_sg; /* no. SGs contig in this cmd */
- cp->Header.SGTotal = (__u16) use_sg; /* total sgs in this cmd list */
+ cp->Header.SGList = (u8) use_sg; /* no. SGs contig in this cmd */
+ cp->Header.SGTotal = (u16) use_sg; /* total sgs in this cmd list */
return 0;
}
@@ -2053,8 +2053,8 @@ static struct CommandList *cmd_alloc(struct ctlr_info *h)
c->cmdindex = i;
INIT_HLIST_NODE(&c->list);
- c->busaddr = (__u32) cmd_dma_handle;
- temp64.val = (__u64) err_dma_handle;
+ c->busaddr = (u32) cmd_dma_handle;
+ temp64.val = (u64) err_dma_handle;
c->ErrDesc.Addr.lower = temp64.val32.lower;
c->ErrDesc.Addr.upper = temp64.val32.upper;
c->ErrDesc.Len = sizeof(*c->err_info);
@@ -2091,8 +2091,8 @@ static struct CommandList *cmd_special_alloc(struct ctlr_info *h)
memset(c->err_info, 0, sizeof(*c->err_info));
INIT_HLIST_NODE(&c->list);
- c->busaddr = (__u32) cmd_dma_handle;
- temp64.val = (__u64) err_dma_handle;
+ c->busaddr = (u32) cmd_dma_handle;
+ temp64.val = (u64) err_dma_handle;
c->ErrDesc.Addr.lower = temp64.val32.lower;
c->ErrDesc.Addr.upper = temp64.val32.upper;
c->ErrDesc.Len = sizeof(*c->err_info);
@@ -2378,8 +2378,8 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp)
BYTE sg_used = 0;
int status = 0;
int i;
- __u32 left;
- __u32 sz;
+ u32 left;
+ u32 sz;
BYTE __user *data_ptr;
if (!argp)
@@ -2542,8 +2542,8 @@ static int hpsa_ioctl(struct scsi_device *dev, int cmd, void *arg)
}
}
-static void fill_cmd(struct CommandList *c, __u8 cmd, struct ctlr_info *h,
- void *buff, size_t size, __u8 page_code, unsigned char *scsi3addr,
+static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h,
+ void *buff, size_t size, u8 page_code, unsigned char *scsi3addr,
int cmd_type)
{
int pci_dir = XFER_NONE;
@@ -2721,8 +2721,8 @@ static inline long interrupt_not_for_us(struct ctlr_info *h)
(h->interrupts_enabled == 0));
}
-static inline int bad_tag(struct ctlr_info *h, __u32 tag_index,
- __u32 raw_tag)
+static inline int bad_tag(struct ctlr_info *h, u32 tag_index,
+ u32 raw_tag)
{
if (unlikely(tag_index >= h->nr_cmds)) {
dev_warn(&h->pdev->dev, "bad tag 0x%08x ignored.\n", raw_tag);
@@ -2731,7 +2731,7 @@ static inline int bad_tag(struct ctlr_info *h, __u32 tag_index,
return 0;
}
-static inline void finish_cmd(struct CommandList *c, __u32 raw_tag)
+static inline void finish_cmd(struct CommandList *c, u32 raw_tag)
{
removeQ(c);
if (likely(c->cmd_type == CMD_SCSI))
@@ -2745,7 +2745,7 @@ static irqreturn_t do_hpsa_intr(int irq, void *dev_id)
struct ctlr_info *h = dev_id;
struct CommandList *c;
unsigned long flags;
- __u32 raw_tag, tag, tag_index;
+ u32 raw_tag, tag, tag_index;
struct hlist_node *tmp;
if (interrupt_not_for_us(h))
@@ -3063,7 +3063,7 @@ static int find_PCI_BAR_index(struct pci_dev *pdev, unsigned long pci_bar_addr)
*/
static void __devinit hpsa_interrupt_mode(struct ctlr_info *h,
- struct pci_dev *pdev, __u32 board_id)
+ struct pci_dev *pdev, u32 board_id)
{
#ifdef CONFIG_PCI_MSI
int err;
@@ -3114,15 +3114,15 @@ default_int_mode:
static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
{
ushort subsystem_vendor_id, subsystem_device_id, command;
- __u32 board_id, scratchpad = 0;
- __u64 cfg_offset;
- __u32 cfg_base_addr;
- __u64 cfg_base_addr_index;
+ u32 board_id, scratchpad = 0;
+ u64 cfg_offset;
+ u32 cfg_base_addr;
+ u64 cfg_base_addr_index;
int i, prod_index, err;
subsystem_vendor_id = pdev->subsystem_vendor;
subsystem_device_id = pdev->subsystem_device;
- board_id = (((__u32) (subsystem_device_id << 16) & 0xffff0000) |
+ board_id = (((u32) (subsystem_device_id << 16) & 0xffff0000) |
subsystem_vendor_id);
for (i = 0; i < ARRAY_SIZE(products); i++)
@@ -3199,7 +3199,7 @@ static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
/* get the address index number */
cfg_base_addr = readl(h->vaddr + SA5_CTCFG_OFFSET);
- cfg_base_addr &= (__u32) 0x0000ffff;
+ cfg_base_addr &= (u32) 0x0000ffff;
cfg_base_addr_index = find_PCI_BAR_index(pdev, cfg_base_addr);
if (cfg_base_addr_index == -1) {
dev_warn(&pdev->dev, "cannot find cfg_base_addr_index\n");
@@ -3232,7 +3232,7 @@ static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
#ifdef CONFIG_X86
{
/* Need to enable prefetch in the SCSI core for 6400 in x86 */
- __u32 prefetch;
+ u32 prefetch;
prefetch = readl(&(h->cfgtable->SCSI_Prefetch));
prefetch |= 0x100;
writel(prefetch, &(h->cfgtable->SCSI_Prefetch));
@@ -3244,7 +3244,7 @@ static int hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)
* physical memory.
*/
if (board_id == 0x3225103C) {
- __u32 dma_prefetch;
+ u32 dma_prefetch;
dma_prefetch = readl(h->vaddr + I2O_DMA1_CFG);
dma_prefetch |= 0x8000;
writel(dma_prefetch, h->vaddr + I2O_DMA1_CFG);
diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h
index 6bd1949..194968e 100644
--- a/drivers/scsi/hpsa.h
+++ b/drivers/scsi/hpsa.h
@@ -55,7 +55,7 @@ struct ctlr_info {
char *product_name;
char firm_ver[4]; /* Firmware version */
struct pci_dev *pdev;
- __u32 board_id;
+ u32 board_id;
void __iomem *vaddr;
unsigned long paddr;
int nr_cmds; /* Number of commands allowed on this controller */
@@ -261,7 +261,7 @@ static struct access_method SA5_access = {
};
struct board_type {
- __u32 board_id;
+ u32 board_id;
char *product_name;
struct access_method *access;
};
diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h
index 2df1c66..88bb3b0 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -107,13 +107,13 @@
#define CFGTBL_BusType_Fibre1G 0x00000100l
#define CFGTBL_BusType_Fibre2G 0x00000200l
struct vals32 {
- __u32 lower;
- __u32 upper;
+ u32 lower;
+ u32 upper;
};
union u64bit {
struct vals32 val32;
- __u64 val;
+ u64 val;
};
/* FIXME this is a per controller value (barf!) */
@@ -126,34 +126,34 @@ union u64bit {
#define HPSA_INQUIRY 0x12
struct InquiryData {
- __u8 data_byte[36];
+ u8 data_byte[36];
};
#define HPSA_REPORT_LOG 0xc2 /* Report Logical LUNs */
#define HPSA_REPORT_PHYS 0xc3 /* Report Physical LUNs */
struct ReportLUNdata {
- __u8 LUNListLength[4];
- __u32 reserved;
- __u8 LUN[HPSA_MAX_LUN][8];
+ u8 LUNListLength[4];
+ u32 reserved;
+ u8 LUN[HPSA_MAX_LUN][8];
};
struct ReportExtendedLUNdata {
- __u8 LUNListLength[4];
- __u8 extended_response_flag;
- __u8 reserved[3];
- __u8 LUN[HPSA_MAX_LUN][24];
+ u8 LUNListLength[4];
+ u8 extended_response_flag;
+ u8 reserved[3];
+ u8 LUN[HPSA_MAX_LUN][24];
};
struct SenseSubsystem_info {
- __u8 reserved[36];
- __u8 portname[8];
- __u8 reserved1[1108];
+ u8 reserved[36];
+ u8 portname[8];
+ u8 reserved1[1108];
};
#define HPSA_READ_CAPACITY 0x25 /* Read Capacity */
struct ReadCapdata {
- __u8 total_size[4]; /* Total size in blocks */
- __u8 block_size[4]; /* Size of blocks in bytes */
+ u8 total_size[4]; /* Total size in blocks */
+ u8 block_size[4]; /* Size of blocks in bytes */
};
#if 0
@@ -174,94 +174,94 @@ struct ReadCapdata {
/* Command List Structure */
union SCSI3Addr {
struct {
- __u8 Dev;
- __u8 Bus:6;
- __u8 Mode:2; /* b00 */
+ u8 Dev;
+ u8 Bus:6;
+ u8 Mode:2; /* b00 */
} PeripDev;
struct {
- __u8 DevLSB;
- __u8 DevMSB:6;
- __u8 Mode:2; /* b01 */
+ u8 DevLSB;
+ u8 DevMSB:6;
+ u8 Mode:2; /* b01 */
} LogDev;
struct {
- __u8 Dev:5;
- __u8 Bus:3;
- __u8 Targ:6;
- __u8 Mode:2; /* b10 */
+ u8 Dev:5;
+ u8 Bus:3;
+ u8 Targ:6;
+ u8 Mode:2; /* b10 */
} LogUnit;
};
struct PhysDevAddr {
- __u32 TargetId:24;
- __u32 Bus:6;
- __u32 Mode:2;
+ u32 TargetId:24;
+ u32 Bus:6;
+ u32 Mode:2;
/* 2 level target device addr */
union SCSI3Addr Target[2];
};
struct LogDevAddr {
- __u32 VolId:30;
- __u32 Mode:2;
- __u8 reserved[4];
+ u32 VolId:30;
+ u32 Mode:2;
+ u8 reserved[4];
};
union LUNAddr {
- __u8 LunAddrBytes[8];
+ u8 LunAddrBytes[8];
union SCSI3Addr SCSI3Lun[4];
struct PhysDevAddr PhysDev;
struct LogDevAddr LogDev;
};
struct CommandListHeader {
- __u8 ReplyQueue;
- __u8 SGList;
- __u16 SGTotal;
+ u8 ReplyQueue;
+ u8 SGList;
+ u16 SGTotal;
struct vals32 Tag;
union LUNAddr LUN;
};
struct RequestBlock {
- __u8 CDBLen;
+ u8 CDBLen;
struct {
- __u8 Type:3;
- __u8 Attribute:3;
- __u8 Direction:2;
+ u8 Type:3;
+ u8 Attribute:3;
+ u8 Direction:2;
} Type;
- __u16 Timeout;
- __u8 CDB[16];
+ u16 Timeout;
+ u8 CDB[16];
};
struct ErrDescriptor {
struct vals32 Addr;
- __u32 Len;
+ u32 Len;
};
struct SGDescriptor {
struct vals32 Addr;
- __u32 Len;
- __u32 Ext;
+ u32 Len;
+ u32 Ext;
};
union MoreErrInfo {
struct {
- __u8 Reserved[3];
- __u8 Type;
- __u32 ErrorInfo;
+ u8 Reserved[3];
+ u8 Type;
+ u32 ErrorInfo;
} Common_Info;
struct {
- __u8 Reserved[2];
- __u8 offense_size; /* size of offending entry */
- __u8 offense_num; /* byte # of offense 0-base */
- __u32 offense_value;
+ u8 Reserved[2];
+ u8 offense_size; /* size of offending entry */
+ u8 offense_num; /* byte # of offense 0-base */
+ u32 offense_value;
} Invalid_Cmd;
};
struct ErrorInfo {
- __u8 ScsiStatus;
- __u8 SenseLen;
- __u16 CommandStatus;
- __u32 ResidualCnt;
+ u8 ScsiStatus;
+ u8 SenseLen;
+ u16 CommandStatus;
+ u32 ResidualCnt;
union MoreErrInfo MoreErrInfo;
- __u8 SenseInfo[SENSEINFOBYTES];
+ u8 SenseInfo[SENSEINFOBYTES];
};
/* Command types */
#define CMD_IOCTL_PEND 0x01
@@ -279,7 +279,7 @@ struct CommandList {
struct ErrDescriptor ErrDesc;
struct SGDescriptor SG[MAXSGENTRIES];
/* information associated with the command */
- __u32 busaddr; /* physical addr of this record */
+ u32 busaddr; /* physical addr of this record */
struct ErrorInfo *err_info; /* pointer to the allocated mem */
struct ctlr_info *h;
int cmd_type;
@@ -295,31 +295,31 @@ struct CommandList {
/* Configuration Table Structure */
struct HostWrite {
- __u32 TransportRequest;
- __u32 Reserved;
- __u32 CoalIntDelay;
- __u32 CoalIntCount;
+ u32 TransportRequest;
+ u32 Reserved;
+ u32 CoalIntDelay;
+ u32 CoalIntCount;
};
struct CfgTable {
- __u8 Signature[4];
- __u32 SpecValence;
- __u32 TransportSupport;
- __u32 TransportActive;
+ u8 Signature[4];
+ u32 SpecValence;
+ u32 TransportSupport;
+ u32 TransportActive;
struct HostWrite HostWrite;
- __u32 CmdsOutMax;
- __u32 BusTypes;
- __u32 Reserved;
- __u8 ServerName[16];
- __u32 HeartBeat;
- __u32 SCSI_Prefetch;
+ u32 CmdsOutMax;
+ u32 BusTypes;
+ u32 Reserved;
+ u8 ServerName[16];
+ u32 HeartBeat;
+ u32 SCSI_Prefetch;
};
struct hpsa_pci_info {
unsigned char bus;
unsigned char dev_fn;
unsigned short domain;
- __u32 board_id;
+ u32 board_id;
};
#pragma pack()
From: Stephen M. Cameron <[email protected]>
hpsa: remove unwanted debug code
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 6 ------
1 files changed, 0 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index bd081fe..4594200 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1580,9 +1580,6 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
}
memcpy(nphysicals, &physdev->LUNListLength[0], sizeof(*nphysicals));
*nphysicals = be32_to_cpu(*nphysicals) / 8;
-#ifdef DEBUG
- dev_info(&h->pdev->dev, "number of physical luns is %d\n", *nphysicals);
-#endif
if (*nphysicals > HPSA_MAX_PHYS_LUN) {
dev_warn(&h->pdev->dev, "maximum physical LUNs (%d) exceeded."
" %d LUNs ignored.\n", HPSA_MAX_PHYS_LUN,
@@ -1595,9 +1592,6 @@ static int hpsa_gather_lun_info(struct ctlr_info *h,
}
memcpy(nlogicals, &logdev->LUNListLength[0], sizeof(*nlogicals));
*nlogicals = be32_to_cpu(*nlogicals) / 8;
-#ifdef DEBUG
- dev_info(&h->pdev->dev, "number of logical luns is %d\n", *nlogicals);
-#endif
/* Reject Logicals in excess of our max capability. */
if (*nlogicals > HPSA_MAX_LUN) {
dev_warn(&h->pdev->dev,
From: Stephen M. Cameron <[email protected]>
hpsa: use kzalloc not kmalloc plus memset
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index add2ed5..bd081fe 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1405,13 +1405,12 @@ static int hpsa_update_device_info(struct ctlr_info *h,
unsigned char scsi3addr[], struct hpsa_scsi_dev_t *this_device)
{
#define OBDR_TAPE_INQ_SIZE 49
- unsigned char *inq_buff = NULL;
+ unsigned char *inq_buff;
- inq_buff = kmalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
+ inq_buff = kzalloc(OBDR_TAPE_INQ_SIZE, GFP_KERNEL);
if (!inq_buff)
goto bail_out;
- memset(inq_buff, 0, OBDR_TAPE_INQ_SIZE);
/* Do an inquiry to the device to see what it is. */
if (hpsa_scsi_do_inquiry(h, scsi3addr, 0, inq_buff,
(unsigned char) OBDR_TAPE_INQ_SIZE) != 0) {
From: Stephen M. Cameron <[email protected]>
hpsa: use sizeof() not an inline constant in memset.
Signed-off-by: Stephen M. Cameron <[email protected]>
---
drivers/scsi/hpsa.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c
index 8389cce..add2ed5 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -1363,9 +1363,8 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical,
dev_err(&h->pdev->dev, "cmd_special_alloc returned NULL!\n");
return -1;
}
-
- memset(&scsi3addr[0], 0, 8); /* address the controller */
-
+ /* address the controller */
+ memset(scsi3addr, 0, sizeof(scsi3addr));
fill_cmd(c, logical ? HPSA_REPORT_LOG : HPSA_REPORT_PHYS, h,
buf, bufsize, 0, scsi3addr, TYPE_CMD);
if (extended_response)