diff options
Diffstat (limited to 'drivers/scsi/aacraid/comminit.c')
-rw-r--r-- | drivers/scsi/aacraid/comminit.c | 92 |
1 files changed, 87 insertions, 5 deletions
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 6832a55ca907..43557bf661f6 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/blkdev.h> | 39 | #include <linux/blkdev.h> |
40 | #include <linux/completion.h> | 40 | #include <linux/completion.h> |
41 | #include <linux/mm.h> | 41 | #include <linux/mm.h> |
42 | #include <scsi/scsi_host.h> | ||
42 | #include <asm/semaphore.h> | 43 | #include <asm/semaphore.h> |
43 | 44 | ||
44 | #include "aacraid.h" | 45 | #include "aacraid.h" |
@@ -49,8 +50,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
49 | { | 50 | { |
50 | unsigned char *base; | 51 | unsigned char *base; |
51 | unsigned long size, align; | 52 | unsigned long size, align; |
52 | unsigned long fibsize = 4096; | 53 | const unsigned long fibsize = 4096; |
53 | unsigned long printfbufsiz = 256; | 54 | const unsigned long printfbufsiz = 256; |
54 | struct aac_init *init; | 55 | struct aac_init *init; |
55 | dma_addr_t phys; | 56 | dma_addr_t phys; |
56 | 57 | ||
@@ -74,6 +75,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
74 | init = dev->init; | 75 | init = dev->init; |
75 | 76 | ||
76 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); | 77 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); |
78 | if (dev->max_fib_size != sizeof(struct hw_fib)) | ||
79 | init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4); | ||
77 | init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION); | 80 | init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION); |
78 | init->fsrev = cpu_to_le32(dev->fsrev); | 81 | init->fsrev = cpu_to_le32(dev->fsrev); |
79 | 82 | ||
@@ -110,6 +113,10 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co | |||
110 | init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); | 113 | init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES); |
111 | } | 114 | } |
112 | 115 | ||
116 | init->InitFlags = 0; | ||
117 | init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); | ||
118 | init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9); | ||
119 | init->MaxFibSize = cpu_to_le32(dev->max_fib_size); | ||
113 | 120 | ||
114 | /* | 121 | /* |
115 | * Increment the base address by the amount already used | 122 | * Increment the base address by the amount already used |
@@ -152,8 +159,8 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, | |||
152 | init_waitqueue_head(&q->qfull); | 159 | init_waitqueue_head(&q->qfull); |
153 | spin_lock_init(&q->lockdata); | 160 | spin_lock_init(&q->lockdata); |
154 | q->lock = &q->lockdata; | 161 | q->lock = &q->lockdata; |
155 | q->headers.producer = mem; | 162 | q->headers.producer = (__le32 *)mem; |
156 | q->headers.consumer = mem+1; | 163 | q->headers.consumer = (__le32 *)(mem+1); |
157 | *(q->headers.producer) = cpu_to_le32(qsize); | 164 | *(q->headers.producer) = cpu_to_le32(qsize); |
158 | *(q->headers.consumer) = cpu_to_le32(qsize); | 165 | *(q->headers.consumer) = cpu_to_le32(qsize); |
159 | q->entries = qsize; | 166 | q->entries = qsize; |
@@ -173,6 +180,8 @@ int aac_send_shutdown(struct aac_dev * dev) | |||
173 | int status; | 180 | int status; |
174 | 181 | ||
175 | fibctx = fib_alloc(dev); | 182 | fibctx = fib_alloc(dev); |
183 | if (!fibctx) | ||
184 | return -ENOMEM; | ||
176 | fib_init(fibctx); | 185 | fib_init(fibctx); |
177 | 186 | ||
178 | cmd = (struct aac_close *) fib_data(fibctx); | 187 | cmd = (struct aac_close *) fib_data(fibctx); |
@@ -204,7 +213,7 @@ int aac_send_shutdown(struct aac_dev * dev) | |||
204 | * 0 - If there were errors initing. This is a fatal error. | 213 | * 0 - If there were errors initing. This is a fatal error. |
205 | */ | 214 | */ |
206 | 215 | ||
207 | int aac_comm_init(struct aac_dev * dev) | 216 | static int aac_comm_init(struct aac_dev * dev) |
208 | { | 217 | { |
209 | unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2; | 218 | unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2; |
210 | unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES; | 219 | unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES; |
@@ -293,6 +302,79 @@ int aac_comm_init(struct aac_dev * dev) | |||
293 | 302 | ||
294 | struct aac_dev *aac_init_adapter(struct aac_dev *dev) | 303 | struct aac_dev *aac_init_adapter(struct aac_dev *dev) |
295 | { | 304 | { |
305 | u32 status[5]; | ||
306 | struct Scsi_Host * host = dev->scsi_host_ptr; | ||
307 | |||
308 | /* | ||
309 | * Check the preferred comm settings, defaults from template. | ||
310 | */ | ||
311 | dev->max_fib_size = sizeof(struct hw_fib); | ||
312 | dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size | ||
313 | - sizeof(struct aac_fibhdr) | ||
314 | - sizeof(struct aac_write) + sizeof(struct sgmap)) | ||
315 | / sizeof(struct sgmap); | ||
316 | if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS, | ||
317 | 0, 0, 0, 0, 0, 0, | ||
318 | status+0, status+1, status+2, status+3, status+4)) | ||
319 | && (status[0] == 0x00000001)) { | ||
320 | /* | ||
321 | * status[1] >> 16 maximum command size in KB | ||
322 | * status[1] & 0xFFFF maximum FIB size | ||
323 | * status[2] >> 16 maximum SG elements to driver | ||
324 | * status[2] & 0xFFFF maximum SG elements from driver | ||
325 | * status[3] & 0xFFFF maximum number FIBs outstanding | ||
326 | */ | ||
327 | host->max_sectors = (status[1] >> 16) << 1; | ||
328 | dev->max_fib_size = status[1] & 0xFFFF; | ||
329 | host->sg_tablesize = status[2] >> 16; | ||
330 | dev->sg_tablesize = status[2] & 0xFFFF; | ||
331 | host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB; | ||
332 | /* | ||
333 | * NOTE: | ||
334 | * All these overrides are based on a fixed internal | ||
335 | * knowledge and understanding of existing adapters, | ||
336 | * acbsize should be set with caution. | ||
337 | */ | ||
338 | if (acbsize == 512) { | ||
339 | host->max_sectors = AAC_MAX_32BIT_SGBCOUNT; | ||
340 | dev->max_fib_size = 512; | ||
341 | dev->sg_tablesize = host->sg_tablesize | ||
342 | = (512 - sizeof(struct aac_fibhdr) | ||
343 | - sizeof(struct aac_write) + sizeof(struct sgmap)) | ||
344 | / sizeof(struct sgmap); | ||
345 | host->can_queue = AAC_NUM_IO_FIB; | ||
346 | } else if (acbsize == 2048) { | ||
347 | host->max_sectors = 512; | ||
348 | dev->max_fib_size = 2048; | ||
349 | host->sg_tablesize = 65; | ||
350 | dev->sg_tablesize = 81; | ||
351 | host->can_queue = 512 - AAC_NUM_MGT_FIB; | ||
352 | } else if (acbsize == 4096) { | ||
353 | host->max_sectors = 1024; | ||
354 | dev->max_fib_size = 4096; | ||
355 | host->sg_tablesize = 129; | ||
356 | dev->sg_tablesize = 166; | ||
357 | host->can_queue = 256 - AAC_NUM_MGT_FIB; | ||
358 | } else if (acbsize == 8192) { | ||
359 | host->max_sectors = 2048; | ||
360 | dev->max_fib_size = 8192; | ||
361 | host->sg_tablesize = 257; | ||
362 | dev->sg_tablesize = 337; | ||
363 | host->can_queue = 128 - AAC_NUM_MGT_FIB; | ||
364 | } else if (acbsize > 0) { | ||
365 | printk("Illegal acbsize=%d ignored\n", acbsize); | ||
366 | } | ||
367 | } | ||
368 | { | ||
369 | |||
370 | if (numacb > 0) { | ||
371 | if (numacb < host->can_queue) | ||
372 | host->can_queue = numacb; | ||
373 | else | ||
374 | printk("numacb=%d ignored\n", numacb); | ||
375 | } | ||
376 | } | ||
377 | |||
296 | /* | 378 | /* |
297 | * Ok now init the communication subsystem | 379 | * Ok now init the communication subsystem |
298 | */ | 380 | */ |