diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/cciss.c | 153 | ||||
-rw-r--r-- | drivers/block/cciss_scsi.c | 10 |
2 files changed, 89 insertions, 74 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 70ad24f3604f..1dc95740b3bb 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -907,60 +907,73 @@ static void cciss_destroy_ld_sysfs_entry(struct ctlr_info *h, int drv_index, | |||
907 | /* | 907 | /* |
908 | * For operations that cannot sleep, a command block is allocated at init, | 908 | * For operations that cannot sleep, a command block is allocated at init, |
909 | * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track | 909 | * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track |
910 | * which ones are free or in use. For operations that can wait for kmalloc | 910 | * which ones are free or in use. |
911 | * to possible sleep, this routine can be called with get_from_pool set to 0. | ||
912 | * cmd_free() MUST be called with a got_from_pool set to 0 if cmd_alloc was. | ||
913 | */ | 911 | */ |
914 | static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) | 912 | static CommandList_struct *cmd_alloc(ctlr_info_t *h) |
915 | { | 913 | { |
916 | CommandList_struct *c; | 914 | CommandList_struct *c; |
917 | int i; | 915 | int i; |
918 | u64bit temp64; | 916 | u64bit temp64; |
919 | dma_addr_t cmd_dma_handle, err_dma_handle; | 917 | dma_addr_t cmd_dma_handle, err_dma_handle; |
920 | 918 | ||
921 | if (!get_from_pool) { | 919 | do { |
922 | c = (CommandList_struct *) pci_alloc_consistent(h->pdev, | 920 | i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); |
923 | sizeof(CommandList_struct), &cmd_dma_handle); | 921 | if (i == h->nr_cmds) |
924 | if (c == NULL) | ||
925 | return NULL; | 922 | return NULL; |
926 | memset(c, 0, sizeof(CommandList_struct)); | 923 | } while (test_and_set_bit(i & (BITS_PER_LONG - 1), |
924 | h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0); | ||
925 | #ifdef CCISS_DEBUG | ||
926 | printk(KERN_DEBUG "cciss: using command buffer %d\n", i); | ||
927 | #endif | ||
928 | c = h->cmd_pool + i; | ||
929 | memset(c, 0, sizeof(CommandList_struct)); | ||
930 | cmd_dma_handle = h->cmd_pool_dhandle + i * sizeof(CommandList_struct); | ||
931 | c->err_info = h->errinfo_pool + i; | ||
932 | memset(c->err_info, 0, sizeof(ErrorInfo_struct)); | ||
933 | err_dma_handle = h->errinfo_pool_dhandle | ||
934 | + i * sizeof(ErrorInfo_struct); | ||
935 | h->nr_allocs++; | ||
927 | 936 | ||
928 | c->cmdindex = -1; | 937 | c->cmdindex = i; |
929 | 938 | ||
930 | c->err_info = (ErrorInfo_struct *) | 939 | INIT_HLIST_NODE(&c->list); |
931 | pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct), | 940 | c->busaddr = (__u32) cmd_dma_handle; |
932 | &err_dma_handle); | 941 | temp64.val = (__u64) err_dma_handle; |
942 | c->ErrDesc.Addr.lower = temp64.val32.lower; | ||
943 | c->ErrDesc.Addr.upper = temp64.val32.upper; | ||
944 | c->ErrDesc.Len = sizeof(ErrorInfo_struct); | ||
933 | 945 | ||
934 | if (c->err_info == NULL) { | 946 | c->ctlr = h->ctlr; |
935 | pci_free_consistent(h->pdev, | 947 | return c; |
936 | sizeof(CommandList_struct), c, cmd_dma_handle); | 948 | } |
937 | return NULL; | 949 | |
938 | } | 950 | /* allocate a command using pci_alloc_consistent, used for ioctls, |
939 | memset(c->err_info, 0, sizeof(ErrorInfo_struct)); | 951 | * etc., not for the main i/o path. |
940 | } else { /* get it out of the controllers pool */ | 952 | */ |
941 | 953 | static CommandList_struct *cmd_special_alloc(ctlr_info_t *h) | |
942 | do { | 954 | { |
943 | i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds); | 955 | CommandList_struct *c; |
944 | if (i == h->nr_cmds) | 956 | u64bit temp64; |
945 | return NULL; | 957 | dma_addr_t cmd_dma_handle, err_dma_handle; |
946 | } while (test_and_set_bit | 958 | |
947 | (i & (BITS_PER_LONG - 1), | 959 | c = (CommandList_struct *) pci_alloc_consistent(h->pdev, |
948 | h->cmd_pool_bits + (i / BITS_PER_LONG)) != 0); | 960 | sizeof(CommandList_struct), &cmd_dma_handle); |
949 | #ifdef CCISS_DEBUG | 961 | if (c == NULL) |
950 | printk(KERN_DEBUG "cciss: using command buffer %d\n", i); | 962 | return NULL; |
951 | #endif | 963 | memset(c, 0, sizeof(CommandList_struct)); |
952 | c = h->cmd_pool + i; | 964 | |
953 | memset(c, 0, sizeof(CommandList_struct)); | 965 | c->cmdindex = -1; |
954 | cmd_dma_handle = h->cmd_pool_dhandle | 966 | |
955 | + i * sizeof(CommandList_struct); | 967 | c->err_info = (ErrorInfo_struct *) |
956 | c->err_info = h->errinfo_pool + i; | 968 | pci_alloc_consistent(h->pdev, sizeof(ErrorInfo_struct), |
957 | memset(c->err_info, 0, sizeof(ErrorInfo_struct)); | 969 | &err_dma_handle); |
958 | err_dma_handle = h->errinfo_pool_dhandle | ||
959 | + i * sizeof(ErrorInfo_struct); | ||
960 | h->nr_allocs++; | ||
961 | 970 | ||
962 | c->cmdindex = i; | 971 | if (c->err_info == NULL) { |
972 | pci_free_consistent(h->pdev, | ||
973 | sizeof(CommandList_struct), c, cmd_dma_handle); | ||
974 | return NULL; | ||
963 | } | 975 | } |
976 | memset(c->err_info, 0, sizeof(ErrorInfo_struct)); | ||
964 | 977 | ||
965 | INIT_HLIST_NODE(&c->list); | 978 | INIT_HLIST_NODE(&c->list); |
966 | c->busaddr = (__u32) cmd_dma_handle; | 979 | c->busaddr = (__u32) cmd_dma_handle; |
@@ -973,27 +986,26 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool) | |||
973 | return c; | 986 | return c; |
974 | } | 987 | } |
975 | 988 | ||
976 | /* | 989 | static void cmd_free(ctlr_info_t *h, CommandList_struct *c) |
977 | * Frees a command block that was previously allocated with cmd_alloc(). | ||
978 | */ | ||
979 | static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool) | ||
980 | { | 990 | { |
981 | int i; | 991 | int i; |
992 | |||
993 | i = c - h->cmd_pool; | ||
994 | clear_bit(i & (BITS_PER_LONG - 1), | ||
995 | h->cmd_pool_bits + (i / BITS_PER_LONG)); | ||
996 | h->nr_frees++; | ||
997 | } | ||
998 | |||
999 | static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c) | ||
1000 | { | ||
982 | u64bit temp64; | 1001 | u64bit temp64; |
983 | 1002 | ||
984 | if (!got_from_pool) { | 1003 | temp64.val32.lower = c->ErrDesc.Addr.lower; |
985 | temp64.val32.lower = c->ErrDesc.Addr.lower; | 1004 | temp64.val32.upper = c->ErrDesc.Addr.upper; |
986 | temp64.val32.upper = c->ErrDesc.Addr.upper; | 1005 | pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), |
987 | pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct), | 1006 | c->err_info, (dma_addr_t) temp64.val); |
988 | c->err_info, (dma_addr_t) temp64.val); | 1007 | pci_free_consistent(h->pdev, sizeof(CommandList_struct), |
989 | pci_free_consistent(h->pdev, sizeof(CommandList_struct), | 1008 | c, (dma_addr_t) c->busaddr); |
990 | c, (dma_addr_t) c->busaddr); | ||
991 | } else { | ||
992 | i = c - h->cmd_pool; | ||
993 | clear_bit(i & (BITS_PER_LONG - 1), | ||
994 | h->cmd_pool_bits + (i / BITS_PER_LONG)); | ||
995 | h->nr_frees++; | ||
996 | } | ||
997 | } | 1009 | } |
998 | 1010 | ||
999 | static inline ctlr_info_t *get_host(struct gendisk *disk) | 1011 | static inline ctlr_info_t *get_host(struct gendisk *disk) |
@@ -1470,7 +1482,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1470 | } else { | 1482 | } else { |
1471 | memset(buff, 0, iocommand.buf_size); | 1483 | memset(buff, 0, iocommand.buf_size); |
1472 | } | 1484 | } |
1473 | c = cmd_alloc(h, 0); | 1485 | c = cmd_special_alloc(h); |
1474 | if (!c) { | 1486 | if (!c) { |
1475 | kfree(buff); | 1487 | kfree(buff); |
1476 | return -ENOMEM; | 1488 | return -ENOMEM; |
@@ -1524,7 +1536,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1524 | if (copy_to_user | 1536 | if (copy_to_user |
1525 | (argp, &iocommand, sizeof(IOCTL_Command_struct))) { | 1537 | (argp, &iocommand, sizeof(IOCTL_Command_struct))) { |
1526 | kfree(buff); | 1538 | kfree(buff); |
1527 | cmd_free(h, c, 0); | 1539 | cmd_special_free(h, c); |
1528 | return -EFAULT; | 1540 | return -EFAULT; |
1529 | } | 1541 | } |
1530 | 1542 | ||
@@ -1533,12 +1545,12 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1533 | if (copy_to_user | 1545 | if (copy_to_user |
1534 | (iocommand.buf, buff, iocommand.buf_size)) { | 1546 | (iocommand.buf, buff, iocommand.buf_size)) { |
1535 | kfree(buff); | 1547 | kfree(buff); |
1536 | cmd_free(h, c, 0); | 1548 | cmd_special_free(h, c); |
1537 | return -EFAULT; | 1549 | return -EFAULT; |
1538 | } | 1550 | } |
1539 | } | 1551 | } |
1540 | kfree(buff); | 1552 | kfree(buff); |
1541 | cmd_free(h, c, 0); | 1553 | cmd_special_free(h, c); |
1542 | return 0; | 1554 | return 0; |
1543 | } | 1555 | } |
1544 | case CCISS_BIG_PASSTHRU:{ | 1556 | case CCISS_BIG_PASSTHRU:{ |
@@ -1620,7 +1632,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1620 | data_ptr += sz; | 1632 | data_ptr += sz; |
1621 | sg_used++; | 1633 | sg_used++; |
1622 | } | 1634 | } |
1623 | c = cmd_alloc(h, 0); | 1635 | c = cmd_special_alloc(h); |
1624 | if (!c) { | 1636 | if (!c) { |
1625 | status = -ENOMEM; | 1637 | status = -ENOMEM; |
1626 | goto cleanup1; | 1638 | goto cleanup1; |
@@ -1668,7 +1680,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1668 | /* Copy the error information out */ | 1680 | /* Copy the error information out */ |
1669 | ioc->error_info = *(c->err_info); | 1681 | ioc->error_info = *(c->err_info); |
1670 | if (copy_to_user(argp, ioc, sizeof(*ioc))) { | 1682 | if (copy_to_user(argp, ioc, sizeof(*ioc))) { |
1671 | cmd_free(h, c, 0); | 1683 | cmd_special_free(h, c); |
1672 | status = -EFAULT; | 1684 | status = -EFAULT; |
1673 | goto cleanup1; | 1685 | goto cleanup1; |
1674 | } | 1686 | } |
@@ -1678,14 +1690,14 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode, | |||
1678 | for (i = 0; i < sg_used; i++) { | 1690 | for (i = 0; i < sg_used; i++) { |
1679 | if (copy_to_user | 1691 | if (copy_to_user |
1680 | (ptr, buff[i], buff_size[i])) { | 1692 | (ptr, buff[i], buff_size[i])) { |
1681 | cmd_free(h, c, 0); | 1693 | cmd_special_free(h, c); |
1682 | status = -EFAULT; | 1694 | status = -EFAULT; |
1683 | goto cleanup1; | 1695 | goto cleanup1; |
1684 | } | 1696 | } |
1685 | ptr += buff_size[i]; | 1697 | ptr += buff_size[i]; |
1686 | } | 1698 | } |
1687 | } | 1699 | } |
1688 | cmd_free(h, c, 0); | 1700 | cmd_special_free(h, c); |
1689 | status = 0; | 1701 | status = 0; |
1690 | cleanup1: | 1702 | cleanup1: |
1691 | if (buff) { | 1703 | if (buff) { |
@@ -1813,7 +1825,7 @@ static void cciss_softirq_done(struct request *rq) | |||
1813 | blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO); | 1825 | blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO); |
1814 | 1826 | ||
1815 | spin_lock_irqsave(&h->lock, flags); | 1827 | spin_lock_irqsave(&h->lock, flags); |
1816 | cmd_free(h, c, 1); | 1828 | cmd_free(h, c); |
1817 | cciss_check_queues(h); | 1829 | cciss_check_queues(h); |
1818 | spin_unlock_irqrestore(&h->lock, flags); | 1830 | spin_unlock_irqrestore(&h->lock, flags); |
1819 | } | 1831 | } |
@@ -2765,7 +2777,7 @@ static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, | |||
2765 | CommandList_struct *c; | 2777 | CommandList_struct *c; |
2766 | int return_status; | 2778 | int return_status; |
2767 | 2779 | ||
2768 | c = cmd_alloc(h, 0); | 2780 | c = cmd_special_alloc(h); |
2769 | if (!c) | 2781 | if (!c) |
2770 | return -ENOMEM; | 2782 | return -ENOMEM; |
2771 | return_status = fill_cmd(h, c, cmd, buff, size, page_code, | 2783 | return_status = fill_cmd(h, c, cmd, buff, size, page_code, |
@@ -2773,7 +2785,7 @@ static int sendcmd_withirq(ctlr_info_t *h, __u8 cmd, void *buff, size_t size, | |||
2773 | if (return_status == IO_OK) | 2785 | if (return_status == IO_OK) |
2774 | return_status = sendcmd_withirq_core(h, c, 1); | 2786 | return_status = sendcmd_withirq_core(h, c, 1); |
2775 | 2787 | ||
2776 | cmd_free(h, c, 0); | 2788 | cmd_special_free(h, c); |
2777 | return return_status; | 2789 | return return_status; |
2778 | } | 2790 | } |
2779 | 2791 | ||
@@ -3240,7 +3252,8 @@ static void do_cciss_request(struct request_queue *q) | |||
3240 | 3252 | ||
3241 | BUG_ON(creq->nr_phys_segments > h->maxsgentries); | 3253 | BUG_ON(creq->nr_phys_segments > h->maxsgentries); |
3242 | 3254 | ||
3243 | if ((c = cmd_alloc(h, 1)) == NULL) | 3255 | c = cmd_alloc(h); |
3256 | if (!c) | ||
3244 | goto full; | 3257 | goto full; |
3245 | 3258 | ||
3246 | blk_start_request(creq); | 3259 | blk_start_request(creq); |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index 9133ad4c7b1b..9fe0d8ffc90d 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
@@ -49,8 +49,10 @@ static int fill_cmd(ctlr_info_t *h, CommandList_struct *c, __u8 cmd, void *buff, | |||
49 | __u8 page_code, unsigned char *scsi3addr, | 49 | __u8 page_code, unsigned char *scsi3addr, |
50 | int cmd_type); | 50 | int cmd_type); |
51 | 51 | ||
52 | static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool); | 52 | static CommandList_struct *cmd_alloc(ctlr_info_t *h); |
53 | static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool); | 53 | static CommandList_struct *cmd_special_alloc(ctlr_info_t *h); |
54 | static void cmd_free(ctlr_info_t *h, CommandList_struct *c); | ||
55 | static void cmd_special_free(ctlr_info_t *h, CommandList_struct *c); | ||
54 | 56 | ||
55 | static int cciss_scsi_proc_info( | 57 | static int cciss_scsi_proc_info( |
56 | struct Scsi_Host *sh, | 58 | struct Scsi_Host *sh, |
@@ -1582,7 +1584,7 @@ static int wait_for_device_to_become_ready(ctlr_info_t *h, | |||
1582 | int waittime = HZ; | 1584 | int waittime = HZ; |
1583 | CommandList_struct *c; | 1585 | CommandList_struct *c; |
1584 | 1586 | ||
1585 | c = cmd_alloc(h, 1); | 1587 | c = cmd_alloc(h); |
1586 | if (!c) { | 1588 | if (!c) { |
1587 | printk(KERN_WARNING "cciss%d: out of memory in " | 1589 | printk(KERN_WARNING "cciss%d: out of memory in " |
1588 | "wait_for_device_to_become_ready.\n", h->ctlr); | 1590 | "wait_for_device_to_become_ready.\n", h->ctlr); |
@@ -1640,7 +1642,7 @@ retry_tur: | |||
1640 | else | 1642 | else |
1641 | printk(KERN_WARNING "cciss%d: device is ready.\n", h->ctlr); | 1643 | printk(KERN_WARNING "cciss%d: device is ready.\n", h->ctlr); |
1642 | 1644 | ||
1643 | cmd_free(h, c, 1); | 1645 | cmd_free(h, c); |
1644 | return rc; | 1646 | return rc; |
1645 | } | 1647 | } |
1646 | 1648 | ||