diff options
Diffstat (limited to 'drivers/scsi/aacraid/commctrl.c')
-rw-r--r-- | drivers/scsi/aacraid/commctrl.c | 93 |
1 files changed, 50 insertions, 43 deletions
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index d9a93f8a728d..e6da87d17832 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
@@ -86,7 +86,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) | |||
86 | return -EFAULT; | 86 | return -EFAULT; |
87 | } | 87 | } |
88 | 88 | ||
89 | if (kfib->header.Command == cpu_to_le32(TakeABreakPt)) { | 89 | if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) { |
90 | aac_adapter_interrupt(dev); | 90 | aac_adapter_interrupt(dev); |
91 | /* | 91 | /* |
92 | * Since we didn't really send a fib, zero out the state to allow | 92 | * Since we didn't really send a fib, zero out the state to allow |
@@ -94,7 +94,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) | |||
94 | */ | 94 | */ |
95 | kfib->header.XferState = 0; | 95 | kfib->header.XferState = 0; |
96 | } else { | 96 | } else { |
97 | int retval = fib_send(kfib->header.Command, fibptr, | 97 | int retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr, |
98 | le16_to_cpu(kfib->header.Size) , FsaNormal, | 98 | le16_to_cpu(kfib->header.Size) , FsaNormal, |
99 | 1, 1, NULL, NULL); | 99 | 1, 1, NULL, NULL); |
100 | if (retval) { | 100 | if (retval) { |
@@ -114,7 +114,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg) | |||
114 | * was already included by the adapter.) | 114 | * was already included by the adapter.) |
115 | */ | 115 | */ |
116 | 116 | ||
117 | if (copy_to_user(arg, (void *)kfib, kfib->header.Size)) { | 117 | if (copy_to_user(arg, (void *)kfib, le16_to_cpu(kfib->header.Size))) { |
118 | fib_free(fibptr); | 118 | fib_free(fibptr); |
119 | return -EFAULT; | 119 | return -EFAULT; |
120 | } | 120 | } |
@@ -391,8 +391,8 @@ static int check_revision(struct aac_dev *dev, void __user *arg) | |||
391 | struct revision response; | 391 | struct revision response; |
392 | 392 | ||
393 | response.compat = 1; | 393 | response.compat = 1; |
394 | response.version = dev->adapter_info.kernelrev; | 394 | response.version = le32_to_cpu(dev->adapter_info.kernelrev); |
395 | response.build = dev->adapter_info.kernelbuild; | 395 | response.build = le32_to_cpu(dev->adapter_info.kernelbuild); |
396 | 396 | ||
397 | if (copy_to_user(arg, &response, sizeof(response))) | 397 | if (copy_to_user(arg, &response, sizeof(response))) |
398 | return -EFAULT; | 398 | return -EFAULT; |
@@ -409,8 +409,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
409 | { | 409 | { |
410 | struct fib* srbfib; | 410 | struct fib* srbfib; |
411 | int status; | 411 | int status; |
412 | struct aac_srb *srbcmd; | 412 | struct aac_srb *srbcmd = NULL; |
413 | struct aac_srb __user *user_srb = arg; | 413 | struct user_aac_srb *user_srbcmd = NULL; |
414 | struct user_aac_srb __user *user_srb = arg; | ||
414 | struct aac_srb_reply __user *user_reply; | 415 | struct aac_srb_reply __user *user_reply; |
415 | struct aac_srb_reply* reply; | 416 | struct aac_srb_reply* reply; |
416 | u32 fibsize = 0; | 417 | u32 fibsize = 0; |
@@ -450,7 +451,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
450 | goto cleanup; | 451 | goto cleanup; |
451 | } | 452 | } |
452 | 453 | ||
453 | if(copy_from_user(srbcmd, user_srb,fibsize)){ | 454 | user_srbcmd = kmalloc(GFP_KERNEL, fibsize); |
455 | if(copy_from_user(user_srbcmd, user_srb,fibsize)){ | ||
454 | printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); | 456 | printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); |
455 | rcode = -EFAULT; | 457 | rcode = -EFAULT; |
456 | goto cleanup; | 458 | goto cleanup; |
@@ -458,18 +460,19 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
458 | 460 | ||
459 | user_reply = arg+fibsize; | 461 | user_reply = arg+fibsize; |
460 | 462 | ||
461 | flags = srbcmd->flags; | 463 | flags = user_srbcmd->flags; /* from user in cpu order */ |
462 | // Fix up srb for endian and force some values | 464 | // Fix up srb for endian and force some values |
465 | |||
463 | srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this | 466 | srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this |
464 | srbcmd->channel = cpu_to_le32(srbcmd->channel); | 467 | srbcmd->channel = cpu_to_le32(user_srbcmd->channel); |
465 | srbcmd->id = cpu_to_le32(srbcmd->id); | 468 | srbcmd->id = cpu_to_le32(user_srbcmd->id); |
466 | srbcmd->lun = cpu_to_le32(srbcmd->lun); | 469 | srbcmd->lun = cpu_to_le32(user_srbcmd->lun); |
467 | srbcmd->flags = cpu_to_le32(srbcmd->flags); | 470 | srbcmd->flags = cpu_to_le32(user_srbcmd->flags); |
468 | srbcmd->timeout = cpu_to_le32(srbcmd->timeout); | 471 | srbcmd->timeout = cpu_to_le32(user_srbcmd->timeout); |
469 | srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter | 472 | srbcmd->retry_limit = 0; |
470 | srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size); | 473 | srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size); |
471 | 474 | ||
472 | switch (srbcmd->flags & (SRB_DataIn | SRB_DataOut)) { | 475 | switch (flags & (SRB_DataIn | SRB_DataOut)) { |
473 | case SRB_DataOut: | 476 | case SRB_DataOut: |
474 | data_dir = DMA_TO_DEVICE; | 477 | data_dir = DMA_TO_DEVICE; |
475 | break; | 478 | break; |
@@ -483,60 +486,61 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
483 | data_dir = DMA_NONE; | 486 | data_dir = DMA_NONE; |
484 | } | 487 | } |
485 | if (dev->dac_support == 1) { | 488 | if (dev->dac_support == 1) { |
486 | struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; | 489 | struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg; |
490 | struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg; | ||
487 | byte_count = 0; | 491 | byte_count = 0; |
488 | 492 | ||
489 | /* | 493 | /* |
490 | * This should also catch if user used the 32 bit sgmap | 494 | * This should also catch if user used the 32 bit sgmap |
491 | */ | 495 | */ |
492 | actual_fibsize = sizeof(struct aac_srb) - | 496 | actual_fibsize = sizeof(struct aac_srb) - |
493 | sizeof(struct sgentry) + ((srbcmd->sg.count & 0xff) * | 497 | sizeof(struct sgentry) + |
494 | sizeof(struct sgentry64)); | 498 | ((user_srbcmd->sg.count & 0xff) * |
499 | sizeof(struct sgentry64)); | ||
495 | if(actual_fibsize != fibsize){ // User made a mistake - should not continue | 500 | if(actual_fibsize != fibsize){ // User made a mistake - should not continue |
496 | printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"); | 501 | printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"); |
497 | rcode = -EINVAL; | 502 | rcode = -EINVAL; |
498 | goto cleanup; | 503 | goto cleanup; |
499 | } | 504 | } |
500 | if ((data_dir == DMA_NONE) && psg->count) { | 505 | if ((data_dir == DMA_NONE) && upsg->count) { |
501 | printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); | 506 | printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); |
502 | rcode = -EINVAL; | 507 | rcode = -EINVAL; |
503 | goto cleanup; | 508 | goto cleanup; |
504 | } | 509 | } |
505 | 510 | ||
506 | for (i = 0; i < psg->count; i++) { | 511 | for (i = 0; i < upsg->count; i++) { |
507 | dma_addr_t addr; | 512 | u64 addr; |
508 | u64 le_addr; | ||
509 | void* p; | 513 | void* p; |
510 | p = kmalloc(psg->sg[i].count,GFP_KERNEL|__GFP_DMA); | 514 | p = kmalloc(upsg->sg[i].count, GFP_KERNEL|__GFP_DMA); |
511 | if(p == 0) { | 515 | if(p == 0) { |
512 | printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 516 | printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
513 | psg->sg[i].count,i,psg->count); | 517 | upsg->sg[i].count,i,upsg->count); |
514 | rcode = -ENOMEM; | 518 | rcode = -ENOMEM; |
515 | goto cleanup; | 519 | goto cleanup; |
516 | } | 520 | } |
517 | sg_user[i] = (void __user *)psg->sg[i].addr; | 521 | sg_user[i] = (void __user *)upsg->sg[i].addr; |
518 | sg_list[i] = p; // save so we can clean up later | 522 | sg_list[i] = p; // save so we can clean up later |
519 | sg_indx = i; | 523 | sg_indx = i; |
520 | 524 | ||
521 | if( flags & SRB_DataOut ){ | 525 | if( flags & SRB_DataOut ){ |
522 | if(copy_from_user(p,sg_user[i],psg->sg[i].count)){ | 526 | if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){ |
523 | printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); | 527 | printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); |
524 | rcode = -EFAULT; | 528 | rcode = -EFAULT; |
525 | goto cleanup; | 529 | goto cleanup; |
526 | } | 530 | } |
527 | } | 531 | } |
528 | addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir); | 532 | addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir); |
529 | 533 | ||
530 | le_addr = cpu_to_le64(addr); | 534 | psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff); |
531 | psg->sg[i].addr[1] = (u32)(le_addr>>32); | 535 | psg->sg[i].addr[1] = cpu_to_le32(addr >> 32); |
532 | psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff); | 536 | psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); |
533 | psg->sg[i].count = cpu_to_le32(psg->sg[i].count); | 537 | byte_count += upsg->sg[i].count; |
534 | byte_count += psg->sg[i].count; | ||
535 | } | 538 | } |
536 | 539 | ||
537 | srbcmd->count = cpu_to_le32(byte_count); | 540 | srbcmd->count = cpu_to_le32(byte_count); |
538 | status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); | 541 | status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL); |
539 | } else { | 542 | } else { |
543 | struct user_sgmap* upsg = &user_srbcmd->sg; | ||
540 | struct sgmap* psg = &srbcmd->sg; | 544 | struct sgmap* psg = &srbcmd->sg; |
541 | byte_count = 0; | 545 | byte_count = 0; |
542 | 546 | ||
@@ -548,37 +552,39 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
548 | rcode = -EINVAL; | 552 | rcode = -EINVAL; |
549 | goto cleanup; | 553 | goto cleanup; |
550 | } | 554 | } |
551 | if ((data_dir == DMA_NONE) && psg->count) { | 555 | if ((data_dir == DMA_NONE) && upsg->count) { |
552 | printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); | 556 | printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"); |
553 | rcode = -EINVAL; | 557 | rcode = -EINVAL; |
554 | goto cleanup; | 558 | goto cleanup; |
555 | } | 559 | } |
556 | for (i = 0; i < psg->count; i++) { | 560 | for (i = 0; i < upsg->count; i++) { |
557 | dma_addr_t addr; | 561 | dma_addr_t addr; |
558 | void* p; | 562 | void* p; |
559 | p = kmalloc(psg->sg[i].count,GFP_KERNEL); | 563 | p = kmalloc(upsg->sg[i].count, GFP_KERNEL); |
560 | if(p == 0) { | 564 | if(p == 0) { |
561 | printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | 565 | printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
562 | psg->sg[i].count,i,psg->count); | 566 | upsg->sg[i].count, i, upsg->count); |
563 | rcode = -ENOMEM; | 567 | rcode = -ENOMEM; |
564 | goto cleanup; | 568 | goto cleanup; |
565 | } | 569 | } |
566 | sg_user[i] = (void __user *)(psg->sg[i].addr); | 570 | sg_user[i] = (void __user *)upsg->sg[i].addr; |
567 | sg_list[i] = p; // save so we can clean up later | 571 | sg_list[i] = p; // save so we can clean up later |
568 | sg_indx = i; | 572 | sg_indx = i; |
569 | 573 | ||
570 | if( flags & SRB_DataOut ){ | 574 | if( flags & SRB_DataOut ){ |
571 | if(copy_from_user(p,sg_user[i],psg->sg[i].count)){ | 575 | if(copy_from_user(p, sg_user[i], |
576 | upsg->sg[i].count)) { | ||
572 | printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); | 577 | printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); |
573 | rcode = -EFAULT; | 578 | rcode = -EFAULT; |
574 | goto cleanup; | 579 | goto cleanup; |
575 | } | 580 | } |
576 | } | 581 | } |
577 | addr = pci_map_single(dev->pdev, p, psg->sg[i].count, data_dir); | 582 | addr = pci_map_single(dev->pdev, p, |
583 | upsg->sg[i].count, data_dir); | ||
578 | 584 | ||
579 | psg->sg[i].addr = cpu_to_le32(addr); | 585 | psg->sg[i].addr = cpu_to_le32(addr); |
580 | psg->sg[i].count = cpu_to_le32(psg->sg[i].count); | 586 | psg->sg[i].count = cpu_to_le32(upsg->sg[i].count); |
581 | byte_count += psg->sg[i].count; | 587 | byte_count += upsg->sg[i].count; |
582 | } | 588 | } |
583 | srbcmd->count = cpu_to_le32(byte_count); | 589 | srbcmd->count = cpu_to_le32(byte_count); |
584 | status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); | 590 | status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL); |
@@ -609,6 +615,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
609 | } | 615 | } |
610 | 616 | ||
611 | cleanup: | 617 | cleanup: |
618 | kfree(user_srbcmd); | ||
612 | for(i=0; i <= sg_indx; i++){ | 619 | for(i=0; i <= sg_indx; i++){ |
613 | kfree(sg_list[i]); | 620 | kfree(sg_list[i]); |
614 | } | 621 | } |