Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 188308
b: refs/heads/master
c: 33a2ffc
h: refs/heads/master
v: v3
  • Loading branch information
Stephen M. Cameron authored and James Bottomley committed Mar 3, 2010
1 parent 6610e72 commit 49e8b50
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 15 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: db61bfcfe2a68dc71402c270686cd73b80971efc
refs/heads/master: 33a2ffce51d9598380d73c515a27fc6cff3bd9c4
134 changes: 123 additions & 11 deletions trunk/drivers/scsi/hpsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ static struct scsi_host_template hpsa_driver_template = {
.scan_finished = hpsa_scan_finished,
.change_queue_depth = hpsa_change_queue_depth,
.this_id = -1,
.sg_tablesize = MAXSGENTRIES,
.use_clustering = ENABLE_CLUSTERING,
.eh_device_reset_handler = hpsa_eh_device_reset_handler,
.ioctl = hpsa_ioctl,
Expand Down Expand Up @@ -844,6 +843,76 @@ static void hpsa_scsi_setup(struct ctlr_info *h)
spin_lock_init(&h->devlock);
}

static void hpsa_free_sg_chain_blocks(struct ctlr_info *h)
{
int i;

if (!h->cmd_sg_list)
return;
for (i = 0; i < h->nr_cmds; i++) {
kfree(h->cmd_sg_list[i]);
h->cmd_sg_list[i] = NULL;
}
kfree(h->cmd_sg_list);
h->cmd_sg_list = NULL;
}

static int hpsa_allocate_sg_chain_blocks(struct ctlr_info *h)
{
int i;

if (h->chainsize <= 0)
return 0;

h->cmd_sg_list = kzalloc(sizeof(*h->cmd_sg_list) * h->nr_cmds,
GFP_KERNEL);
if (!h->cmd_sg_list)
return -ENOMEM;
for (i = 0; i < h->nr_cmds; i++) {
h->cmd_sg_list[i] = kmalloc(sizeof(*h->cmd_sg_list[i]) *
h->chainsize, GFP_KERNEL);
if (!h->cmd_sg_list[i])
goto clean;
}
return 0;

clean:
hpsa_free_sg_chain_blocks(h);
return -ENOMEM;
}

static void hpsa_map_sg_chain_block(struct ctlr_info *h,
struct CommandList *c)
{
struct SGDescriptor *chain_sg, *chain_block;
u64 temp64;

chain_sg = &c->SG[h->max_cmd_sg_entries - 1];
chain_block = h->cmd_sg_list[c->cmdindex];
chain_sg->Ext = HPSA_SG_CHAIN;
chain_sg->Len = sizeof(*chain_sg) *
(c->Header.SGTotal - h->max_cmd_sg_entries);
temp64 = pci_map_single(h->pdev, chain_block, chain_sg->Len,
PCI_DMA_TODEVICE);
chain_sg->Addr.lower = (u32) (temp64 & 0x0FFFFFFFFULL);
chain_sg->Addr.upper = (u32) ((temp64 >> 32) & 0x0FFFFFFFFULL);
}

static void hpsa_unmap_sg_chain_block(struct ctlr_info *h,
struct CommandList *c)
{
struct SGDescriptor *chain_sg;
union u64bit temp64;

if (c->Header.SGTotal <= h->max_cmd_sg_entries)
return;

chain_sg = &c->SG[h->max_cmd_sg_entries - 1];
temp64.val32.lower = chain_sg->Addr.lower;
temp64.val32.upper = chain_sg->Addr.upper;
pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
}

static void complete_scsi_command(struct CommandList *cp,
int timeout, u32 tag)
{
Expand All @@ -860,6 +929,8 @@ static void complete_scsi_command(struct CommandList *cp,
h = cp->h;

scsi_dma_unmap(cmd); /* undo the DMA mappings */
if (cp->Header.SGTotal > h->max_cmd_sg_entries)
hpsa_unmap_sg_chain_block(h, cp);

cmd->result = (DID_OK << 16); /* host byte */
cmd->result |= (COMMAND_COMPLETE << 8); /* msg byte */
Expand Down Expand Up @@ -1064,6 +1135,7 @@ static int hpsa_scsi_detect(struct ctlr_info *h)
sh->max_id = HPSA_MAX_LUN;
sh->can_queue = h->nr_cmds;
sh->cmd_per_lun = h->nr_cmds;
sh->sg_tablesize = h->maxsgentries;
h->scsi_host = sh;
sh->hostdata[0] = (unsigned long) h;
sh->irq = h->intr[PERF_MODE_INT];
Expand Down Expand Up @@ -1765,16 +1837,17 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno)
* dma mapping and fills in the scatter gather entries of the
* hpsa command, cp.
*/
static int hpsa_scatter_gather(struct pci_dev *pdev,
static int hpsa_scatter_gather(struct ctlr_info *h,
struct CommandList *cp,
struct scsi_cmnd *cmd)
{
unsigned int len;
struct scatterlist *sg;
u64 addr64;
int use_sg, i;
int use_sg, i, sg_index, chained;
struct SGDescriptor *curr_sg;

BUG_ON(scsi_sg_count(cmd) > MAXSGENTRIES);
BUG_ON(scsi_sg_count(cmd) > h->maxsgentries);

use_sg = scsi_dma_map(cmd);
if (use_sg < 0)
Expand All @@ -1783,15 +1856,33 @@ static int hpsa_scatter_gather(struct pci_dev *pdev,
if (!use_sg)
goto sglist_finished;

curr_sg = cp->SG;
chained = 0;
sg_index = 0;
scsi_for_each_sg(cmd, sg, use_sg, i) {
if (i == h->max_cmd_sg_entries - 1 &&
use_sg > h->max_cmd_sg_entries) {
chained = 1;
curr_sg = h->cmd_sg_list[cp->cmdindex];
sg_index = 0;
}
addr64 = (u64) sg_dma_address(sg);
len = sg_dma_len(sg);
cp->SG[i].Addr.lower =
(u32) (addr64 & (u64) 0x00000000FFFFFFFF);
cp->SG[i].Addr.upper =
(u32) ((addr64 >> 32) & (u64) 0x00000000FFFFFFFF);
cp->SG[i].Len = len;
cp->SG[i].Ext = 0; /* we are not chaining */
curr_sg->Addr.lower = (u32) (addr64 & 0x0FFFFFFFFULL);
curr_sg->Addr.upper = (u32) ((addr64 >> 32) & 0x0FFFFFFFFULL);
curr_sg->Len = len;
curr_sg->Ext = 0; /* we are not chaining */
curr_sg++;
}

if (use_sg + chained > h->maxSG)
h->maxSG = use_sg + chained;

if (chained) {
cp->Header.SGList = h->max_cmd_sg_entries;
cp->Header.SGTotal = (u16) (use_sg + 1);
hpsa_map_sg_chain_block(h, cp);
return 0;
}

sglist_finished:
Expand Down Expand Up @@ -1887,7 +1978,7 @@ static int hpsa_scsi_queue_command(struct scsi_cmnd *cmd,
break;
}

if (hpsa_scatter_gather(h->pdev, c, cmd) < 0) { /* Fill SG list */
if (hpsa_scatter_gather(h, c, cmd) < 0) { /* Fill SG list */
cmd_free(h, c);
return SCSI_MLQUEUE_HOST_BUSY;
}
Expand Down Expand Up @@ -3283,6 +3374,23 @@ static int __devinit hpsa_pci_init(struct ctlr_info *h, struct pci_dev *pdev)

h->board_id = board_id;
h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
h->maxsgentries = readl(&(h->cfgtable->MaxScatterGatherElements));

/*
* Limit in-command s/g elements to 32 save dma'able memory.
* Howvever spec says if 0, use 31
*/

h->max_cmd_sg_entries = 31;
if (h->maxsgentries > 512) {
h->max_cmd_sg_entries = 32;
h->chainsize = h->maxsgentries - h->max_cmd_sg_entries + 1;
h->maxsgentries--; /* save one for chain pointer */
} else {
h->maxsgentries = 31; /* default to traditional values */
h->chainsize = 0;
}

h->product_name = products[prod_index].product_name;
h->access = *(products[prod_index].access);
/* Allow room for some ioctls */
Expand Down Expand Up @@ -3463,6 +3571,8 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
rc = -ENOMEM;
goto clean4;
}
if (hpsa_allocate_sg_chain_blocks(h))
goto clean4;
spin_lock_init(&h->lock);
spin_lock_init(&h->scan_lock);
init_waitqueue_head(&h->scan_wait_queue);
Expand All @@ -3485,6 +3595,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev,
return 1;

clean4:
hpsa_free_sg_chain_blocks(h);
kfree(h->cmd_pool_bits);
if (h->cmd_pool)
pci_free_consistent(h->pdev,
Expand Down Expand Up @@ -3560,6 +3671,7 @@ static void __devexit hpsa_remove_one(struct pci_dev *pdev)
hpsa_unregister_scsi(h); /* unhook from SCSI subsystem */
hpsa_shutdown(pdev);
iounmap(h->vaddr);
hpsa_free_sg_chain_blocks(h);
pci_free_consistent(h->pdev,
h->nr_cmds * sizeof(struct CommandList),
h->cmd_pool, h->cmd_pool_dhandle);
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/scsi/hpsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ struct ctlr_info {
unsigned int maxQsinceinit;
unsigned int maxSG;
spinlock_t lock;
int maxsgentries;
u8 max_cmd_sg_entries;
int chainsize;
struct SGDescriptor **cmd_sg_list;

/* pointers to command and error info pool */
struct CommandList *cmd_pool;
Expand Down
7 changes: 4 additions & 3 deletions trunk/drivers/scsi/hpsa_cmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@

/* general boundary defintions */
#define SENSEINFOBYTES 32 /* may vary between hbas */
#define MAXSGENTRIES 31
#define MAXSGENTRIES 32
#define HPSA_SG_CHAIN 0x80000000
#define MAXREPLYQS 256

/* Command Status value */
Expand Down Expand Up @@ -321,8 +322,8 @@ struct CommandList {
*/
#define IS_32_BIT ((8 - sizeof(long))/4)
#define IS_64_BIT (!IS_32_BIT)
#define PAD_32 (8)
#define PAD_64 (0)
#define PAD_32 (24)
#define PAD_64 (16)
#define COMMANDLIST_PAD (IS_32_BIT * PAD_32 + IS_64_BIT * PAD_64)
u8 pad[COMMANDLIST_PAD];
};
Expand Down

0 comments on commit 49e8b50

Please sign in to comment.