diff options
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 402 |
1 files changed, 238 insertions, 164 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index d789e61bdc49..1e82c69b36b0 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * based on the old aacraid driver that is.. | 5 | * based on the old aacraid driver that is.. |
6 | * Adaptec aacraid device driver for Linux. | 6 | * Adaptec aacraid device driver for Linux. |
7 | * | 7 | * |
8 | * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com) | 8 | * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com) |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
@@ -172,6 +172,30 @@ MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. | |||
172 | int expose_physicals = -1; | 172 | int expose_physicals = -1; |
173 | module_param(expose_physicals, int, S_IRUGO|S_IWUSR); | 173 | module_param(expose_physicals, int, S_IRUGO|S_IWUSR); |
174 | MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); | 174 | MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. -1=protect 0=off, 1=on"); |
175 | |||
176 | |||
177 | static inline int aac_valid_context(struct scsi_cmnd *scsicmd, | ||
178 | struct fib *fibptr) { | ||
179 | struct scsi_device *device; | ||
180 | |||
181 | if (unlikely(!scsicmd || !scsicmd->scsi_done )) { | ||
182 | dprintk((KERN_WARNING "aac_valid_context: scsi command corrupt\n")) | ||
183 | ; | ||
184 | aac_fib_complete(fibptr); | ||
185 | aac_fib_free(fibptr); | ||
186 | return 0; | ||
187 | } | ||
188 | scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; | ||
189 | device = scsicmd->device; | ||
190 | if (unlikely(!device || !scsi_device_online(device))) { | ||
191 | dprintk((KERN_WARNING "aac_valid_context: scsi device corrupt\n")); | ||
192 | aac_fib_complete(fibptr); | ||
193 | aac_fib_free(fibptr); | ||
194 | return 0; | ||
195 | } | ||
196 | return 1; | ||
197 | } | ||
198 | |||
175 | /** | 199 | /** |
176 | * aac_get_config_status - check the adapter configuration | 200 | * aac_get_config_status - check the adapter configuration |
177 | * @common: adapter to query | 201 | * @common: adapter to query |
@@ -258,13 +282,10 @@ int aac_get_containers(struct aac_dev *dev) | |||
258 | u32 index; | 282 | u32 index; |
259 | int status = 0; | 283 | int status = 0; |
260 | struct fib * fibptr; | 284 | struct fib * fibptr; |
261 | unsigned instance; | ||
262 | struct aac_get_container_count *dinfo; | 285 | struct aac_get_container_count *dinfo; |
263 | struct aac_get_container_count_resp *dresp; | 286 | struct aac_get_container_count_resp *dresp; |
264 | int maximum_num_containers = MAXIMUM_NUM_CONTAINERS; | 287 | int maximum_num_containers = MAXIMUM_NUM_CONTAINERS; |
265 | 288 | ||
266 | instance = dev->scsi_host_ptr->unique_id; | ||
267 | |||
268 | if (!(fibptr = aac_fib_alloc(dev))) | 289 | if (!(fibptr = aac_fib_alloc(dev))) |
269 | return -ENOMEM; | 290 | return -ENOMEM; |
270 | 291 | ||
@@ -284,88 +305,35 @@ int aac_get_containers(struct aac_dev *dev) | |||
284 | maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); | 305 | maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries); |
285 | aac_fib_complete(fibptr); | 306 | aac_fib_complete(fibptr); |
286 | } | 307 | } |
308 | aac_fib_free(fibptr); | ||
287 | 309 | ||
288 | if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) | 310 | if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS) |
289 | maximum_num_containers = MAXIMUM_NUM_CONTAINERS; | 311 | maximum_num_containers = MAXIMUM_NUM_CONTAINERS; |
290 | fsa_dev_ptr = kmalloc( | 312 | fsa_dev_ptr = kmalloc(sizeof(*fsa_dev_ptr) * maximum_num_containers, |
291 | sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL); | 313 | GFP_KERNEL); |
292 | if (!fsa_dev_ptr) { | 314 | if (!fsa_dev_ptr) |
293 | aac_fib_free(fibptr); | ||
294 | return -ENOMEM; | 315 | return -ENOMEM; |
295 | } | ||
296 | memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); | 316 | memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers); |
297 | 317 | ||
298 | dev->fsa_dev = fsa_dev_ptr; | 318 | dev->fsa_dev = fsa_dev_ptr; |
299 | dev->maximum_num_containers = maximum_num_containers; | 319 | dev->maximum_num_containers = maximum_num_containers; |
300 | 320 | ||
301 | for (index = 0; index < dev->maximum_num_containers; index++) { | 321 | for (index = 0; index < dev->maximum_num_containers; ) { |
302 | struct aac_query_mount *dinfo; | ||
303 | struct aac_mount *dresp; | ||
304 | |||
305 | fsa_dev_ptr[index].devname[0] = '\0'; | 322 | fsa_dev_ptr[index].devname[0] = '\0'; |
306 | 323 | ||
307 | aac_fib_init(fibptr); | 324 | status = aac_probe_container(dev, index); |
308 | dinfo = (struct aac_query_mount *) fib_data(fibptr); | ||
309 | |||
310 | dinfo->command = cpu_to_le32(VM_NameServe); | ||
311 | dinfo->count = cpu_to_le32(index); | ||
312 | dinfo->type = cpu_to_le32(FT_FILESYS); | ||
313 | 325 | ||
314 | status = aac_fib_send(ContainerCommand, | 326 | if (status < 0) { |
315 | fibptr, | ||
316 | sizeof (struct aac_query_mount), | ||
317 | FsaNormal, | ||
318 | 1, 1, | ||
319 | NULL, NULL); | ||
320 | if (status < 0 ) { | ||
321 | printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); | 327 | printk(KERN_WARNING "aac_get_containers: SendFIB failed.\n"); |
322 | break; | 328 | break; |
323 | } | 329 | } |
324 | dresp = (struct aac_mount *)fib_data(fibptr); | ||
325 | 330 | ||
326 | if ((le32_to_cpu(dresp->status) == ST_OK) && | ||
327 | (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { | ||
328 | dinfo->command = cpu_to_le32(VM_NameServe64); | ||
329 | dinfo->count = cpu_to_le32(index); | ||
330 | dinfo->type = cpu_to_le32(FT_FILESYS); | ||
331 | |||
332 | if (aac_fib_send(ContainerCommand, | ||
333 | fibptr, | ||
334 | sizeof(struct aac_query_mount), | ||
335 | FsaNormal, | ||
336 | 1, 1, | ||
337 | NULL, NULL) < 0) | ||
338 | continue; | ||
339 | } else | ||
340 | dresp->mnt[0].capacityhigh = 0; | ||
341 | |||
342 | dprintk ((KERN_DEBUG | ||
343 | "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n", | ||
344 | (int)index, (int)le32_to_cpu(dresp->status), | ||
345 | (int)le32_to_cpu(dresp->mnt[0].vol), | ||
346 | (int)le32_to_cpu(dresp->mnt[0].state), | ||
347 | ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + | ||
348 | (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32))); | ||
349 | if ((le32_to_cpu(dresp->status) == ST_OK) && | ||
350 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && | ||
351 | (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { | ||
352 | fsa_dev_ptr[index].valid = 1; | ||
353 | fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol); | ||
354 | fsa_dev_ptr[index].size | ||
355 | = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + | ||
356 | (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); | ||
357 | if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) | ||
358 | fsa_dev_ptr[index].ro = 1; | ||
359 | } | ||
360 | aac_fib_complete(fibptr); | ||
361 | /* | 331 | /* |
362 | * If there are no more containers, then stop asking. | 332 | * If there are no more containers, then stop asking. |
363 | */ | 333 | */ |
364 | if ((index + 1) >= le32_to_cpu(dresp->count)){ | 334 | if (++index >= status) |
365 | break; | 335 | break; |
366 | } | ||
367 | } | 336 | } |
368 | aac_fib_free(fibptr); | ||
369 | return status; | 337 | return status; |
370 | } | 338 | } |
371 | 339 | ||
@@ -382,8 +350,9 @@ static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigne | |||
382 | buf = scsicmd->request_buffer; | 350 | buf = scsicmd->request_buffer; |
383 | transfer_len = min(scsicmd->request_bufflen, len + offset); | 351 | transfer_len = min(scsicmd->request_bufflen, len + offset); |
384 | } | 352 | } |
385 | 353 | transfer_len -= offset; | |
386 | memcpy(buf + offset, data, transfer_len - offset); | 354 | if (buf && transfer_len) |
355 | memcpy(buf + offset, data, transfer_len); | ||
387 | 356 | ||
388 | if (scsicmd->use_sg) | 357 | if (scsicmd->use_sg) |
389 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | 358 | kunmap_atomic(buf - sg->offset, KM_IRQ0); |
@@ -396,7 +365,9 @@ static void get_container_name_callback(void *context, struct fib * fibptr) | |||
396 | struct scsi_cmnd * scsicmd; | 365 | struct scsi_cmnd * scsicmd; |
397 | 366 | ||
398 | scsicmd = (struct scsi_cmnd *) context; | 367 | scsicmd = (struct scsi_cmnd *) context; |
399 | scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; | 368 | |
369 | if (!aac_valid_context(scsicmd, fibptr)) | ||
370 | return; | ||
400 | 371 | ||
401 | dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); | 372 | dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies)); |
402 | BUG_ON(fibptr == NULL); | 373 | BUG_ON(fibptr == NULL); |
@@ -431,7 +402,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) | |||
431 | /** | 402 | /** |
432 | * aac_get_container_name - get container name, none blocking. | 403 | * aac_get_container_name - get container name, none blocking. |
433 | */ | 404 | */ |
434 | static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) | 405 | static int aac_get_container_name(struct scsi_cmnd * scsicmd) |
435 | { | 406 | { |
436 | int status; | 407 | int status; |
437 | struct aac_get_name *dinfo; | 408 | struct aac_get_name *dinfo; |
@@ -448,7 +419,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) | |||
448 | 419 | ||
449 | dinfo->command = cpu_to_le32(VM_ContainerConfig); | 420 | dinfo->command = cpu_to_le32(VM_ContainerConfig); |
450 | dinfo->type = cpu_to_le32(CT_READ_NAME); | 421 | dinfo->type = cpu_to_le32(CT_READ_NAME); |
451 | dinfo->cid = cpu_to_le32(cid); | 422 | dinfo->cid = cpu_to_le32(scmd_id(scsicmd)); |
452 | dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data)); | 423 | dinfo->count = cpu_to_le32(sizeof(((struct aac_get_name_resp *)NULL)->data)); |
453 | 424 | ||
454 | status = aac_fib_send(ContainerCommand, | 425 | status = aac_fib_send(ContainerCommand, |
@@ -473,85 +444,192 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid) | |||
473 | return -1; | 444 | return -1; |
474 | } | 445 | } |
475 | 446 | ||
476 | /** | 447 | static int aac_probe_container_callback2(struct scsi_cmnd * scsicmd) |
477 | * aac_probe_container - query a logical volume | 448 | { |
478 | * @dev: device to query | 449 | struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; |
479 | * @cid: container identifier | 450 | |
480 | * | 451 | if (fsa_dev_ptr[scmd_id(scsicmd)].valid) |
481 | * Queries the controller about the given volume. The volume information | 452 | return aac_scsi_cmd(scsicmd); |
482 | * is updated in the struct fsa_dev_info structure rather than returned. | 453 | |
483 | */ | 454 | scsicmd->result = DID_NO_CONNECT << 16; |
484 | 455 | scsicmd->scsi_done(scsicmd); | |
485 | int aac_probe_container(struct aac_dev *dev, int cid) | 456 | return 0; |
457 | } | ||
458 | |||
459 | static int _aac_probe_container2(void * context, struct fib * fibptr) | ||
486 | { | 460 | { |
487 | struct fsa_dev_info *fsa_dev_ptr; | 461 | struct fsa_dev_info *fsa_dev_ptr; |
488 | int status; | 462 | int (*callback)(struct scsi_cmnd *); |
463 | struct scsi_cmnd * scsicmd = (struct scsi_cmnd *)context; | ||
464 | |||
465 | if (!aac_valid_context(scsicmd, fibptr)) | ||
466 | return 0; | ||
467 | |||
468 | fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; | ||
469 | |||
470 | scsicmd->SCp.Status = 0; | ||
471 | if (fsa_dev_ptr) { | ||
472 | struct aac_mount * dresp = (struct aac_mount *) fib_data(fibptr); | ||
473 | fsa_dev_ptr += scmd_id(scsicmd); | ||
474 | |||
475 | if ((le32_to_cpu(dresp->status) == ST_OK) && | ||
476 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && | ||
477 | (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { | ||
478 | fsa_dev_ptr->valid = 1; | ||
479 | fsa_dev_ptr->type = le32_to_cpu(dresp->mnt[0].vol); | ||
480 | fsa_dev_ptr->size | ||
481 | = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + | ||
482 | (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); | ||
483 | fsa_dev_ptr->ro = ((le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) != 0); | ||
484 | } | ||
485 | if ((fsa_dev_ptr->valid & 1) == 0) | ||
486 | fsa_dev_ptr->valid = 0; | ||
487 | scsicmd->SCp.Status = le32_to_cpu(dresp->count); | ||
488 | } | ||
489 | aac_fib_complete(fibptr); | ||
490 | aac_fib_free(fibptr); | ||
491 | callback = (int (*)(struct scsi_cmnd *))(scsicmd->SCp.ptr); | ||
492 | scsicmd->SCp.ptr = NULL; | ||
493 | return (*callback)(scsicmd); | ||
494 | } | ||
495 | |||
496 | static int _aac_probe_container1(void * context, struct fib * fibptr) | ||
497 | { | ||
498 | struct scsi_cmnd * scsicmd; | ||
499 | struct aac_mount * dresp; | ||
489 | struct aac_query_mount *dinfo; | 500 | struct aac_query_mount *dinfo; |
490 | struct aac_mount *dresp; | 501 | int status; |
491 | struct fib * fibptr; | ||
492 | unsigned instance; | ||
493 | 502 | ||
494 | fsa_dev_ptr = dev->fsa_dev; | 503 | dresp = (struct aac_mount *) fib_data(fibptr); |
495 | if (!fsa_dev_ptr) | 504 | dresp->mnt[0].capacityhigh = 0; |
496 | return -ENOMEM; | 505 | if ((le32_to_cpu(dresp->status) != ST_OK) || |
497 | instance = dev->scsi_host_ptr->unique_id; | 506 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) |
507 | return _aac_probe_container2(context, fibptr); | ||
508 | scsicmd = (struct scsi_cmnd *) context; | ||
509 | scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; | ||
498 | 510 | ||
499 | if (!(fibptr = aac_fib_alloc(dev))) | 511 | if (!aac_valid_context(scsicmd, fibptr)) |
500 | return -ENOMEM; | 512 | return 0; |
501 | 513 | ||
502 | aac_fib_init(fibptr); | 514 | aac_fib_init(fibptr); |
503 | 515 | ||
504 | dinfo = (struct aac_query_mount *)fib_data(fibptr); | 516 | dinfo = (struct aac_query_mount *)fib_data(fibptr); |
505 | 517 | ||
506 | dinfo->command = cpu_to_le32(VM_NameServe); | 518 | dinfo->command = cpu_to_le32(VM_NameServe64); |
507 | dinfo->count = cpu_to_le32(cid); | 519 | dinfo->count = cpu_to_le32(scmd_id(scsicmd)); |
508 | dinfo->type = cpu_to_le32(FT_FILESYS); | 520 | dinfo->type = cpu_to_le32(FT_FILESYS); |
509 | 521 | ||
510 | status = aac_fib_send(ContainerCommand, | 522 | status = aac_fib_send(ContainerCommand, |
511 | fibptr, | 523 | fibptr, |
512 | sizeof(struct aac_query_mount), | 524 | sizeof(struct aac_query_mount), |
513 | FsaNormal, | 525 | FsaNormal, |
514 | 1, 1, | 526 | 0, 1, |
515 | NULL, NULL); | 527 | (fib_callback) _aac_probe_container2, |
528 | (void *) scsicmd); | ||
529 | /* | ||
530 | * Check that the command queued to the controller | ||
531 | */ | ||
532 | if (status == -EINPROGRESS) { | ||
533 | scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; | ||
534 | return 0; | ||
535 | } | ||
516 | if (status < 0) { | 536 | if (status < 0) { |
517 | printk(KERN_WARNING "aacraid: aac_probe_container query failed.\n"); | 537 | /* Inherit results from VM_NameServe, if any */ |
518 | goto error; | 538 | dresp->status = cpu_to_le32(ST_OK); |
539 | return _aac_probe_container2(context, fibptr); | ||
519 | } | 540 | } |
541 | return 0; | ||
542 | } | ||
520 | 543 | ||
521 | dresp = (struct aac_mount *) fib_data(fibptr); | 544 | static int _aac_probe_container(struct scsi_cmnd * scsicmd, int (*callback)(struct scsi_cmnd *)) |
545 | { | ||
546 | struct fib * fibptr; | ||
547 | int status = -ENOMEM; | ||
522 | 548 | ||
523 | if ((le32_to_cpu(dresp->status) == ST_OK) && | 549 | if ((fibptr = aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) { |
524 | (le32_to_cpu(dresp->mnt[0].vol) == CT_NONE)) { | 550 | struct aac_query_mount *dinfo; |
525 | dinfo->command = cpu_to_le32(VM_NameServe64); | ||
526 | dinfo->count = cpu_to_le32(cid); | ||
527 | dinfo->type = cpu_to_le32(FT_FILESYS); | ||
528 | 551 | ||
529 | if (aac_fib_send(ContainerCommand, | 552 | aac_fib_init(fibptr); |
530 | fibptr, | 553 | |
531 | sizeof(struct aac_query_mount), | 554 | dinfo = (struct aac_query_mount *)fib_data(fibptr); |
532 | FsaNormal, | 555 | |
533 | 1, 1, | 556 | dinfo->command = cpu_to_le32(VM_NameServe); |
534 | NULL, NULL) < 0) | 557 | dinfo->count = cpu_to_le32(scmd_id(scsicmd)); |
535 | goto error; | 558 | dinfo->type = cpu_to_le32(FT_FILESYS); |
536 | } else | 559 | scsicmd->SCp.ptr = (char *)callback; |
537 | dresp->mnt[0].capacityhigh = 0; | ||
538 | 560 | ||
539 | if ((le32_to_cpu(dresp->status) == ST_OK) && | 561 | status = aac_fib_send(ContainerCommand, |
540 | (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) && | 562 | fibptr, |
541 | (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) { | 563 | sizeof(struct aac_query_mount), |
542 | fsa_dev_ptr[cid].valid = 1; | 564 | FsaNormal, |
543 | fsa_dev_ptr[cid].type = le32_to_cpu(dresp->mnt[0].vol); | 565 | 0, 1, |
544 | fsa_dev_ptr[cid].size | 566 | (fib_callback) _aac_probe_container1, |
545 | = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) + | 567 | (void *) scsicmd); |
546 | (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32); | 568 | /* |
547 | if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY) | 569 | * Check that the command queued to the controller |
548 | fsa_dev_ptr[cid].ro = 1; | 570 | */ |
571 | if (status == -EINPROGRESS) { | ||
572 | scsicmd->SCp.phase = AAC_OWNER_FIRMWARE; | ||
573 | return 0; | ||
574 | } | ||
575 | if (status < 0) { | ||
576 | scsicmd->SCp.ptr = NULL; | ||
577 | aac_fib_complete(fibptr); | ||
578 | aac_fib_free(fibptr); | ||
579 | } | ||
549 | } | 580 | } |
581 | if (status < 0) { | ||
582 | struct fsa_dev_info *fsa_dev_ptr = ((struct aac_dev *)(scsicmd->device->host->hostdata))->fsa_dev; | ||
583 | if (fsa_dev_ptr) { | ||
584 | fsa_dev_ptr += scmd_id(scsicmd); | ||
585 | if ((fsa_dev_ptr->valid & 1) == 0) { | ||
586 | fsa_dev_ptr->valid = 0; | ||
587 | return (*callback)(scsicmd); | ||
588 | } | ||
589 | } | ||
590 | } | ||
591 | return status; | ||
592 | } | ||
550 | 593 | ||
551 | error: | 594 | /** |
552 | aac_fib_complete(fibptr); | 595 | * aac_probe_container - query a logical volume |
553 | aac_fib_free(fibptr); | 596 | * @dev: device to query |
597 | * @cid: container identifier | ||
598 | * | ||
599 | * Queries the controller about the given volume. The volume information | ||
600 | * is updated in the struct fsa_dev_info structure rather than returned. | ||
601 | */ | ||
602 | static int aac_probe_container_callback1(struct scsi_cmnd * scsicmd) | ||
603 | { | ||
604 | scsicmd->device = NULL; | ||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | int aac_probe_container(struct aac_dev *dev, int cid) | ||
609 | { | ||
610 | struct scsi_cmnd *scsicmd = kmalloc(sizeof(*scsicmd), GFP_KERNEL); | ||
611 | struct scsi_device *scsidev = kmalloc(sizeof(*scsidev), GFP_KERNEL); | ||
612 | int status; | ||
554 | 613 | ||
614 | if (!scsicmd || !scsidev) { | ||
615 | kfree(scsicmd); | ||
616 | kfree(scsidev); | ||
617 | return -ENOMEM; | ||
618 | } | ||
619 | scsicmd->list.next = NULL; | ||
620 | scsicmd->scsi_done = (void (*)(struct scsi_cmnd*))_aac_probe_container1; | ||
621 | |||
622 | scsicmd->device = scsidev; | ||
623 | scsidev->sdev_state = 0; | ||
624 | scsidev->id = cid; | ||
625 | scsidev->host = dev->scsi_host_ptr; | ||
626 | |||
627 | if (_aac_probe_container(scsicmd, aac_probe_container_callback1) == 0) | ||
628 | while (scsicmd->device == scsidev) | ||
629 | schedule(); | ||
630 | kfree(scsidev); | ||
631 | status = scsicmd->SCp.Status; | ||
632 | kfree(scsicmd); | ||
555 | return status; | 633 | return status; |
556 | } | 634 | } |
557 | 635 | ||
@@ -1115,6 +1193,12 @@ int aac_get_adapter_info(struct aac_dev* dev) | |||
1115 | printk(KERN_INFO "%s%d: serial %x\n", | 1193 | printk(KERN_INFO "%s%d: serial %x\n", |
1116 | dev->name, dev->id, | 1194 | dev->name, dev->id, |
1117 | le32_to_cpu(dev->adapter_info.serial[0])); | 1195 | le32_to_cpu(dev->adapter_info.serial[0])); |
1196 | if (dev->supplement_adapter_info.VpdInfo.Tsid[0]) { | ||
1197 | printk(KERN_INFO "%s%d: TSID %.*s\n", | ||
1198 | dev->name, dev->id, | ||
1199 | (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid), | ||
1200 | dev->supplement_adapter_info.VpdInfo.Tsid); | ||
1201 | } | ||
1118 | } | 1202 | } |
1119 | 1203 | ||
1120 | dev->nondasd_support = 0; | 1204 | dev->nondasd_support = 0; |
@@ -1241,7 +1325,9 @@ static void io_callback(void *context, struct fib * fibptr) | |||
1241 | u32 cid; | 1325 | u32 cid; |
1242 | 1326 | ||
1243 | scsicmd = (struct scsi_cmnd *) context; | 1327 | scsicmd = (struct scsi_cmnd *) context; |
1244 | scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; | 1328 | |
1329 | if (!aac_valid_context(scsicmd, fibptr)) | ||
1330 | return; | ||
1245 | 1331 | ||
1246 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | 1332 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; |
1247 | cid = scmd_id(scsicmd); | 1333 | cid = scmd_id(scsicmd); |
@@ -1317,7 +1403,7 @@ static void io_callback(void *context, struct fib * fibptr) | |||
1317 | scsicmd->scsi_done(scsicmd); | 1403 | scsicmd->scsi_done(scsicmd); |
1318 | } | 1404 | } |
1319 | 1405 | ||
1320 | static int aac_read(struct scsi_cmnd * scsicmd, int cid) | 1406 | static int aac_read(struct scsi_cmnd * scsicmd) |
1321 | { | 1407 | { |
1322 | u64 lba; | 1408 | u64 lba; |
1323 | u32 count; | 1409 | u32 count; |
@@ -1331,7 +1417,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
1331 | */ | 1417 | */ |
1332 | switch (scsicmd->cmnd[0]) { | 1418 | switch (scsicmd->cmnd[0]) { |
1333 | case READ_6: | 1419 | case READ_6: |
1334 | dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", cid)); | 1420 | dprintk((KERN_DEBUG "aachba: received a read(6) command on id %d.\n", scmd_id(scsicmd))); |
1335 | 1421 | ||
1336 | lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | | 1422 | lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | |
1337 | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; | 1423 | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3]; |
@@ -1341,7 +1427,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
1341 | count = 256; | 1427 | count = 256; |
1342 | break; | 1428 | break; |
1343 | case READ_16: | 1429 | case READ_16: |
1344 | dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", cid)); | 1430 | dprintk((KERN_DEBUG "aachba: received a read(16) command on id %d.\n", scmd_id(scsicmd))); |
1345 | 1431 | ||
1346 | lba = ((u64)scsicmd->cmnd[2] << 56) | | 1432 | lba = ((u64)scsicmd->cmnd[2] << 56) | |
1347 | ((u64)scsicmd->cmnd[3] << 48) | | 1433 | ((u64)scsicmd->cmnd[3] << 48) | |
@@ -1355,7 +1441,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
1355 | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; | 1441 | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; |
1356 | break; | 1442 | break; |
1357 | case READ_12: | 1443 | case READ_12: |
1358 | dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", cid)); | 1444 | dprintk((KERN_DEBUG "aachba: received a read(12) command on id %d.\n", scmd_id(scsicmd))); |
1359 | 1445 | ||
1360 | lba = ((u64)scsicmd->cmnd[2] << 24) | | 1446 | lba = ((u64)scsicmd->cmnd[2] << 24) | |
1361 | (scsicmd->cmnd[3] << 16) | | 1447 | (scsicmd->cmnd[3] << 16) | |
@@ -1365,7 +1451,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
1365 | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; | 1451 | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; |
1366 | break; | 1452 | break; |
1367 | default: | 1453 | default: |
1368 | dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", cid)); | 1454 | dprintk((KERN_DEBUG "aachba: received a read(10) command on id %d.\n", scmd_id(scsicmd))); |
1369 | 1455 | ||
1370 | lba = ((u64)scsicmd->cmnd[2] << 24) | | 1456 | lba = ((u64)scsicmd->cmnd[2] << 24) | |
1371 | (scsicmd->cmnd[3] << 16) | | 1457 | (scsicmd->cmnd[3] << 16) | |
@@ -1405,7 +1491,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid) | |||
1405 | return 0; | 1491 | return 0; |
1406 | } | 1492 | } |
1407 | 1493 | ||
1408 | static int aac_write(struct scsi_cmnd * scsicmd, int cid) | 1494 | static int aac_write(struct scsi_cmnd * scsicmd) |
1409 | { | 1495 | { |
1410 | u64 lba; | 1496 | u64 lba; |
1411 | u32 count; | 1497 | u32 count; |
@@ -1424,7 +1510,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) | |||
1424 | if (count == 0) | 1510 | if (count == 0) |
1425 | count = 256; | 1511 | count = 256; |
1426 | } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ | 1512 | } else if (scsicmd->cmnd[0] == WRITE_16) { /* 16 byte command */ |
1427 | dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", cid)); | 1513 | dprintk((KERN_DEBUG "aachba: received a write(16) command on id %d.\n", scmd_id(scsicmd))); |
1428 | 1514 | ||
1429 | lba = ((u64)scsicmd->cmnd[2] << 56) | | 1515 | lba = ((u64)scsicmd->cmnd[2] << 56) | |
1430 | ((u64)scsicmd->cmnd[3] << 48) | | 1516 | ((u64)scsicmd->cmnd[3] << 48) | |
@@ -1436,14 +1522,14 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) | |||
1436 | count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | | 1522 | count = (scsicmd->cmnd[10] << 24) | (scsicmd->cmnd[11] << 16) | |
1437 | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; | 1523 | (scsicmd->cmnd[12] << 8) | scsicmd->cmnd[13]; |
1438 | } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ | 1524 | } else if (scsicmd->cmnd[0] == WRITE_12) { /* 12 byte command */ |
1439 | dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", cid)); | 1525 | dprintk((KERN_DEBUG "aachba: received a write(12) command on id %d.\n", scmd_id(scsicmd))); |
1440 | 1526 | ||
1441 | lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | 1527 | lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) |
1442 | | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; | 1528 | | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; |
1443 | count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) | 1529 | count = (scsicmd->cmnd[6] << 24) | (scsicmd->cmnd[7] << 16) |
1444 | | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; | 1530 | | (scsicmd->cmnd[8] << 8) | scsicmd->cmnd[9]; |
1445 | } else { | 1531 | } else { |
1446 | dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", cid)); | 1532 | dprintk((KERN_DEBUG "aachba: received a write(10) command on id %d.\n", scmd_id(scsicmd))); |
1447 | lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; | 1533 | lba = ((u64)scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5]; |
1448 | count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; | 1534 | count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8]; |
1449 | } | 1535 | } |
@@ -1488,7 +1574,9 @@ static void synchronize_callback(void *context, struct fib *fibptr) | |||
1488 | struct scsi_cmnd *cmd; | 1574 | struct scsi_cmnd *cmd; |
1489 | 1575 | ||
1490 | cmd = context; | 1576 | cmd = context; |
1491 | cmd->SCp.phase = AAC_OWNER_MIDLEVEL; | 1577 | |
1578 | if (!aac_valid_context(cmd, fibptr)) | ||
1579 | return; | ||
1492 | 1580 | ||
1493 | dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", | 1581 | dprintk((KERN_DEBUG "synchronize_callback[cpu %d]: t = %ld.\n", |
1494 | smp_processor_id(), jiffies)); | 1582 | smp_processor_id(), jiffies)); |
@@ -1523,7 +1611,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) | |||
1523 | cmd->scsi_done(cmd); | 1611 | cmd->scsi_done(cmd); |
1524 | } | 1612 | } |
1525 | 1613 | ||
1526 | static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) | 1614 | static int aac_synchronize(struct scsi_cmnd *scsicmd) |
1527 | { | 1615 | { |
1528 | int status; | 1616 | int status; |
1529 | struct fib *cmd_fibcontext; | 1617 | struct fib *cmd_fibcontext; |
@@ -1568,7 +1656,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) | |||
1568 | synchronizecmd = fib_data(cmd_fibcontext); | 1656 | synchronizecmd = fib_data(cmd_fibcontext); |
1569 | synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); | 1657 | synchronizecmd->command = cpu_to_le32(VM_ContainerConfig); |
1570 | synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); | 1658 | synchronizecmd->type = cpu_to_le32(CT_FLUSH_CACHE); |
1571 | synchronizecmd->cid = cpu_to_le32(cid); | 1659 | synchronizecmd->cid = cpu_to_le32(scmd_id(scsicmd)); |
1572 | synchronizecmd->count = | 1660 | synchronizecmd->count = |
1573 | cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); | 1661 | cpu_to_le32(sizeof(((struct aac_synchronize_reply *)NULL)->data)); |
1574 | 1662 | ||
@@ -1646,29 +1734,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1646 | case TEST_UNIT_READY: | 1734 | case TEST_UNIT_READY: |
1647 | if (dev->in_reset) | 1735 | if (dev->in_reset) |
1648 | return -1; | 1736 | return -1; |
1649 | spin_unlock_irq(host->host_lock); | 1737 | return _aac_probe_container(scsicmd, |
1650 | aac_probe_container(dev, cid); | 1738 | aac_probe_container_callback2); |
1651 | if ((fsa_dev_ptr[cid].valid & 1) == 0) | ||
1652 | fsa_dev_ptr[cid].valid = 0; | ||
1653 | spin_lock_irq(host->host_lock); | ||
1654 | if (fsa_dev_ptr[cid].valid == 0) { | ||
1655 | scsicmd->result = DID_NO_CONNECT << 16; | ||
1656 | scsicmd->scsi_done(scsicmd); | ||
1657 | return 0; | ||
1658 | } | ||
1659 | default: | 1739 | default: |
1660 | break; | 1740 | break; |
1661 | } | 1741 | } |
1662 | } | 1742 | } |
1663 | /* | ||
1664 | * If the target container still doesn't exist, | ||
1665 | * return failure | ||
1666 | */ | ||
1667 | if (fsa_dev_ptr[cid].valid == 0) { | ||
1668 | scsicmd->result = DID_BAD_TARGET << 16; | ||
1669 | scsicmd->scsi_done(scsicmd); | ||
1670 | return 0; | ||
1671 | } | ||
1672 | } else { /* check for physical non-dasd devices */ | 1743 | } else { /* check for physical non-dasd devices */ |
1673 | if ((dev->nondasd_support == 1) || expose_physicals) { | 1744 | if ((dev->nondasd_support == 1) || expose_physicals) { |
1674 | if (dev->in_reset) | 1745 | if (dev->in_reset) |
@@ -1733,7 +1804,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1733 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); | 1804 | setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); |
1734 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ | 1805 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ |
1735 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | 1806 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); |
1736 | return aac_get_container_name(scsicmd, cid); | 1807 | return aac_get_container_name(scsicmd); |
1737 | } | 1808 | } |
1738 | case SERVICE_ACTION_IN: | 1809 | case SERVICE_ACTION_IN: |
1739 | if (!(dev->raw_io_interface) || | 1810 | if (!(dev->raw_io_interface) || |
@@ -1899,7 +1970,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1899 | min(sizeof(fsa_dev_ptr[cid].devname), | 1970 | min(sizeof(fsa_dev_ptr[cid].devname), |
1900 | sizeof(scsicmd->request->rq_disk->disk_name) + 1)); | 1971 | sizeof(scsicmd->request->rq_disk->disk_name) + 1)); |
1901 | 1972 | ||
1902 | return aac_read(scsicmd, cid); | 1973 | return aac_read(scsicmd); |
1903 | 1974 | ||
1904 | case WRITE_6: | 1975 | case WRITE_6: |
1905 | case WRITE_10: | 1976 | case WRITE_10: |
@@ -1907,11 +1978,11 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1907 | case WRITE_16: | 1978 | case WRITE_16: |
1908 | if (dev->in_reset) | 1979 | if (dev->in_reset) |
1909 | return -1; | 1980 | return -1; |
1910 | return aac_write(scsicmd, cid); | 1981 | return aac_write(scsicmd); |
1911 | 1982 | ||
1912 | case SYNCHRONIZE_CACHE: | 1983 | case SYNCHRONIZE_CACHE: |
1913 | /* Issue FIB to tell Firmware to flush it's cache */ | 1984 | /* Issue FIB to tell Firmware to flush it's cache */ |
1914 | return aac_synchronize(scsicmd, cid); | 1985 | return aac_synchronize(scsicmd); |
1915 | 1986 | ||
1916 | default: | 1987 | default: |
1917 | /* | 1988 | /* |
@@ -2058,7 +2129,10 @@ static void aac_srb_callback(void *context, struct fib * fibptr) | |||
2058 | struct scsi_cmnd *scsicmd; | 2129 | struct scsi_cmnd *scsicmd; |
2059 | 2130 | ||
2060 | scsicmd = (struct scsi_cmnd *) context; | 2131 | scsicmd = (struct scsi_cmnd *) context; |
2061 | scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL; | 2132 | |
2133 | if (!aac_valid_context(scsicmd, fibptr)) | ||
2134 | return; | ||
2135 | |||
2062 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; | 2136 | dev = (struct aac_dev *)scsicmd->device->host->hostdata; |
2063 | 2137 | ||
2064 | BUG_ON(fibptr == NULL); | 2138 | BUG_ON(fibptr == NULL); |