diff options
author | Randy Dunlap <rdunlap@xenotime.net> | 2006-06-28 01:01:28 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-28 12:43:20 -0400 |
commit | dc6a78f1af10d28fb8c395034ae1e099b85c05b0 (patch) | |
tree | 531357a95f9dfa3df48d87073d52e7a3d8e25668 /drivers/scsi/atp870u.c | |
parent | 87cf89866790a373edcf88c12b64d6d38560acdd (diff) |
[SCSI] atp870u: reduce huge stack usage
The atp870u driver is the largest stack eater reported by checkstack
(on x86_864, allmodconfig). This converts the offending function
to kmalloc+kfree struct atp_unit instead of allocating it on the stack.
Was:
0x0000164c atp870u_probe [atp870u]: 3176
Now:
0x0000164c atp870u_probe [atp870u]: 408
Signed-off-by: Randy Dunlap <rdunlap@xenotime.net>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/atp870u.c')
-rw-r--r-- | drivers/scsi/atp870u.c | 157 |
1 files changed, 83 insertions, 74 deletions
diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 3ee4d4d3f44..69e6e9821c9 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c | |||
@@ -2625,29 +2625,32 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2625 | unsigned int base_io, tmport, error,n; | 2625 | unsigned int base_io, tmport, error,n; |
2626 | unsigned char host_id; | 2626 | unsigned char host_id; |
2627 | struct Scsi_Host *shpnt = NULL; | 2627 | struct Scsi_Host *shpnt = NULL; |
2628 | struct atp_unit atp_dev, *p; | 2628 | struct atp_unit *atpdev, *p; |
2629 | unsigned char setupdata[2][16]; | 2629 | unsigned char setupdata[2][16]; |
2630 | int count = 0; | 2630 | int count = 0; |
2631 | 2631 | ||
2632 | atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL); | ||
2633 | if (!atpdev) | ||
2634 | return -ENOMEM; | ||
2635 | |||
2632 | if (pci_enable_device(pdev)) | 2636 | if (pci_enable_device(pdev)) |
2633 | return -EIO; | 2637 | goto err_eio; |
2634 | 2638 | ||
2635 | if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 2639 | if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { |
2636 | printk(KERN_INFO "atp870u: use 32bit DMA mask.\n"); | 2640 | printk(KERN_INFO "atp870u: use 32bit DMA mask.\n"); |
2637 | } else { | 2641 | } else { |
2638 | printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); | 2642 | printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); |
2639 | return -EIO; | 2643 | goto err_eio; |
2640 | } | 2644 | } |
2641 | 2645 | ||
2642 | memset(&atp_dev, 0, sizeof atp_dev); | ||
2643 | /* | 2646 | /* |
2644 | * It's probably easier to weed out some revisions like | 2647 | * It's probably easier to weed out some revisions like |
2645 | * this than via the PCI device table | 2648 | * this than via the PCI device table |
2646 | */ | 2649 | */ |
2647 | if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) { | 2650 | if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) { |
2648 | error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver); | 2651 | error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver); |
2649 | if (atp_dev.chip_ver < 2) | 2652 | if (atpdev->chip_ver < 2) |
2650 | return -EIO; | 2653 | goto err_eio; |
2651 | } | 2654 | } |
2652 | 2655 | ||
2653 | switch (ent->device) { | 2656 | switch (ent->device) { |
@@ -2656,15 +2659,15 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2656 | case ATP880_DEVID1: | 2659 | case ATP880_DEVID1: |
2657 | case ATP880_DEVID2: | 2660 | case ATP880_DEVID2: |
2658 | case ATP885_DEVID: | 2661 | case ATP885_DEVID: |
2659 | atp_dev.chip_ver = 0x04; | 2662 | atpdev->chip_ver = 0x04; |
2660 | default: | 2663 | default: |
2661 | break; | 2664 | break; |
2662 | } | 2665 | } |
2663 | base_io = pci_resource_start(pdev, 0); | 2666 | base_io = pci_resource_start(pdev, 0); |
2664 | base_io &= 0xfffffff8; | 2667 | base_io &= 0xfffffff8; |
2665 | 2668 | ||
2666 | if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) { | 2669 | if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) { |
2667 | error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver); | 2670 | error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver); |
2668 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803 | 2671 | pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803 |
2669 | 2672 | ||
2670 | host_id = inb(base_io + 0x39); | 2673 | host_id = inb(base_io + 0x39); |
@@ -2672,17 +2675,17 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2672 | 2675 | ||
2673 | printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d" | 2676 | printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d" |
2674 | " IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); | 2677 | " IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); |
2675 | atp_dev.ioport[0] = base_io + 0x40; | 2678 | atpdev->ioport[0] = base_io + 0x40; |
2676 | atp_dev.pciport[0] = base_io + 0x28; | 2679 | atpdev->pciport[0] = base_io + 0x28; |
2677 | atp_dev.dev_id = ent->device; | 2680 | atpdev->dev_id = ent->device; |
2678 | atp_dev.host_id[0] = host_id; | 2681 | atpdev->host_id[0] = host_id; |
2679 | 2682 | ||
2680 | tmport = base_io + 0x22; | 2683 | tmport = base_io + 0x22; |
2681 | atp_dev.scam_on = inb(tmport); | 2684 | atpdev->scam_on = inb(tmport); |
2682 | tmport += 0x13; | 2685 | tmport += 0x13; |
2683 | atp_dev.global_map[0] = inb(tmport); | 2686 | atpdev->global_map[0] = inb(tmport); |
2684 | tmport += 0x07; | 2687 | tmport += 0x07; |
2685 | atp_dev.ultra_map[0] = inw(tmport); | 2688 | atpdev->ultra_map[0] = inw(tmport); |
2686 | 2689 | ||
2687 | n = 0x3f09; | 2690 | n = 0x3f09; |
2688 | next_fblk_880: | 2691 | next_fblk_880: |
@@ -2695,57 +2698,57 @@ next_fblk_880: | |||
2695 | if (inb(base_io + 0x30) == 0xff) | 2698 | if (inb(base_io + 0x30) == 0xff) |
2696 | goto flash_ok_880; | 2699 | goto flash_ok_880; |
2697 | 2700 | ||
2698 | atp_dev.sp[0][m++] = inb(base_io + 0x30); | 2701 | atpdev->sp[0][m++] = inb(base_io + 0x30); |
2699 | atp_dev.sp[0][m++] = inb(base_io + 0x31); | 2702 | atpdev->sp[0][m++] = inb(base_io + 0x31); |
2700 | atp_dev.sp[0][m++] = inb(base_io + 0x32); | 2703 | atpdev->sp[0][m++] = inb(base_io + 0x32); |
2701 | atp_dev.sp[0][m++] = inb(base_io + 0x33); | 2704 | atpdev->sp[0][m++] = inb(base_io + 0x33); |
2702 | outw(n, base_io + 0x34); | 2705 | outw(n, base_io + 0x34); |
2703 | n += 0x0002; | 2706 | n += 0x0002; |
2704 | atp_dev.sp[0][m++] = inb(base_io + 0x30); | 2707 | atpdev->sp[0][m++] = inb(base_io + 0x30); |
2705 | atp_dev.sp[0][m++] = inb(base_io + 0x31); | 2708 | atpdev->sp[0][m++] = inb(base_io + 0x31); |
2706 | atp_dev.sp[0][m++] = inb(base_io + 0x32); | 2709 | atpdev->sp[0][m++] = inb(base_io + 0x32); |
2707 | atp_dev.sp[0][m++] = inb(base_io + 0x33); | 2710 | atpdev->sp[0][m++] = inb(base_io + 0x33); |
2708 | outw(n, base_io + 0x34); | 2711 | outw(n, base_io + 0x34); |
2709 | n += 0x0002; | 2712 | n += 0x0002; |
2710 | atp_dev.sp[0][m++] = inb(base_io + 0x30); | 2713 | atpdev->sp[0][m++] = inb(base_io + 0x30); |
2711 | atp_dev.sp[0][m++] = inb(base_io + 0x31); | 2714 | atpdev->sp[0][m++] = inb(base_io + 0x31); |
2712 | atp_dev.sp[0][m++] = inb(base_io + 0x32); | 2715 | atpdev->sp[0][m++] = inb(base_io + 0x32); |
2713 | atp_dev.sp[0][m++] = inb(base_io + 0x33); | 2716 | atpdev->sp[0][m++] = inb(base_io + 0x33); |
2714 | outw(n, base_io + 0x34); | 2717 | outw(n, base_io + 0x34); |
2715 | n += 0x0002; | 2718 | n += 0x0002; |
2716 | atp_dev.sp[0][m++] = inb(base_io + 0x30); | 2719 | atpdev->sp[0][m++] = inb(base_io + 0x30); |
2717 | atp_dev.sp[0][m++] = inb(base_io + 0x31); | 2720 | atpdev->sp[0][m++] = inb(base_io + 0x31); |
2718 | atp_dev.sp[0][m++] = inb(base_io + 0x32); | 2721 | atpdev->sp[0][m++] = inb(base_io + 0x32); |
2719 | atp_dev.sp[0][m++] = inb(base_io + 0x33); | 2722 | atpdev->sp[0][m++] = inb(base_io + 0x33); |
2720 | n += 0x0018; | 2723 | n += 0x0018; |
2721 | goto next_fblk_880; | 2724 | goto next_fblk_880; |
2722 | flash_ok_880: | 2725 | flash_ok_880: |
2723 | outw(0, base_io + 0x34); | 2726 | outw(0, base_io + 0x34); |
2724 | atp_dev.ultra_map[0] = 0; | 2727 | atpdev->ultra_map[0] = 0; |
2725 | atp_dev.async[0] = 0; | 2728 | atpdev->async[0] = 0; |
2726 | for (k = 0; k < 16; k++) { | 2729 | for (k = 0; k < 16; k++) { |
2727 | n = 1; | 2730 | n = 1; |
2728 | n = n << k; | 2731 | n = n << k; |
2729 | if (atp_dev.sp[0][k] > 1) { | 2732 | if (atpdev->sp[0][k] > 1) { |
2730 | atp_dev.ultra_map[0] |= n; | 2733 | atpdev->ultra_map[0] |= n; |
2731 | } else { | 2734 | } else { |
2732 | if (atp_dev.sp[0][k] == 0) | 2735 | if (atpdev->sp[0][k] == 0) |
2733 | atp_dev.async[0] |= n; | 2736 | atpdev->async[0] |= n; |
2734 | } | 2737 | } |
2735 | } | 2738 | } |
2736 | atp_dev.async[0] = ~(atp_dev.async[0]); | 2739 | atpdev->async[0] = ~(atpdev->async[0]); |
2737 | outb(atp_dev.global_map[0], base_io + 0x35); | 2740 | outb(atpdev->global_map[0], base_io + 0x35); |
2738 | 2741 | ||
2739 | shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); | 2742 | shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); |
2740 | if (!shpnt) | 2743 | if (!shpnt) |
2741 | return -ENOMEM; | 2744 | goto err_nomem; |
2742 | 2745 | ||
2743 | p = (struct atp_unit *)&shpnt->hostdata; | 2746 | p = (struct atp_unit *)&shpnt->hostdata; |
2744 | 2747 | ||
2745 | atp_dev.host = shpnt; | 2748 | atpdev->host = shpnt; |
2746 | atp_dev.pdev = pdev; | 2749 | atpdev->pdev = pdev; |
2747 | pci_set_drvdata(pdev, p); | 2750 | pci_set_drvdata(pdev, p); |
2748 | memcpy(p, &atp_dev, sizeof atp_dev); | 2751 | memcpy(p, atpdev, sizeof(*atpdev)); |
2749 | if (atp870u_init_tables(shpnt) < 0) { | 2752 | if (atp870u_init_tables(shpnt) < 0) { |
2750 | printk(KERN_ERR "Unable to allocate tables for Acard controller\n"); | 2753 | printk(KERN_ERR "Unable to allocate tables for Acard controller\n"); |
2751 | goto unregister; | 2754 | goto unregister; |
@@ -2798,24 +2801,24 @@ flash_ok_880: | |||
2798 | printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n" | 2801 | printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n" |
2799 | , base_io, pdev->irq); | 2802 | , base_io, pdev->irq); |
2800 | 2803 | ||
2801 | atp_dev.pdev = pdev; | 2804 | atpdev->pdev = pdev; |
2802 | atp_dev.dev_id = ent->device; | 2805 | atpdev->dev_id = ent->device; |
2803 | atp_dev.baseport = base_io; | 2806 | atpdev->baseport = base_io; |
2804 | atp_dev.ioport[0] = base_io + 0x80; | 2807 | atpdev->ioport[0] = base_io + 0x80; |
2805 | atp_dev.ioport[1] = base_io + 0xc0; | 2808 | atpdev->ioport[1] = base_io + 0xc0; |
2806 | atp_dev.pciport[0] = base_io + 0x40; | 2809 | atpdev->pciport[0] = base_io + 0x40; |
2807 | atp_dev.pciport[1] = base_io + 0x50; | 2810 | atpdev->pciport[1] = base_io + 0x50; |
2808 | 2811 | ||
2809 | shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); | 2812 | shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); |
2810 | if (!shpnt) | 2813 | if (!shpnt) |
2811 | return -ENOMEM; | 2814 | goto err_nomem; |
2812 | 2815 | ||
2813 | p = (struct atp_unit *)&shpnt->hostdata; | 2816 | p = (struct atp_unit *)&shpnt->hostdata; |
2814 | 2817 | ||
2815 | atp_dev.host = shpnt; | 2818 | atpdev->host = shpnt; |
2816 | atp_dev.pdev = pdev; | 2819 | atpdev->pdev = pdev; |
2817 | pci_set_drvdata(pdev, p); | 2820 | pci_set_drvdata(pdev, p); |
2818 | memcpy(p, &atp_dev, sizeof(struct atp_unit)); | 2821 | memcpy(p, atpdev, sizeof(struct atp_unit)); |
2819 | if (atp870u_init_tables(shpnt) < 0) | 2822 | if (atp870u_init_tables(shpnt) < 0) |
2820 | goto unregister; | 2823 | goto unregister; |
2821 | 2824 | ||
@@ -2974,33 +2977,33 @@ flash_ok_885: | |||
2974 | printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d " | 2977 | printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d " |
2975 | "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); | 2978 | "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); |
2976 | 2979 | ||
2977 | atp_dev.ioport[0] = base_io; | 2980 | atpdev->ioport[0] = base_io; |
2978 | atp_dev.pciport[0] = base_io + 0x20; | 2981 | atpdev->pciport[0] = base_io + 0x20; |
2979 | atp_dev.dev_id = ent->device; | 2982 | atpdev->dev_id = ent->device; |
2980 | host_id &= 0x07; | 2983 | host_id &= 0x07; |
2981 | atp_dev.host_id[0] = host_id; | 2984 | atpdev->host_id[0] = host_id; |
2982 | tmport = base_io + 0x22; | 2985 | tmport = base_io + 0x22; |
2983 | atp_dev.scam_on = inb(tmport); | 2986 | atpdev->scam_on = inb(tmport); |
2984 | tmport += 0x0b; | 2987 | tmport += 0x0b; |
2985 | atp_dev.global_map[0] = inb(tmport++); | 2988 | atpdev->global_map[0] = inb(tmport++); |
2986 | atp_dev.ultra_map[0] = inw(tmport); | 2989 | atpdev->ultra_map[0] = inw(tmport); |
2987 | 2990 | ||
2988 | if (atp_dev.ultra_map[0] == 0) { | 2991 | if (atpdev->ultra_map[0] == 0) { |
2989 | atp_dev.scam_on = 0x00; | 2992 | atpdev->scam_on = 0x00; |
2990 | atp_dev.global_map[0] = 0x20; | 2993 | atpdev->global_map[0] = 0x20; |
2991 | atp_dev.ultra_map[0] = 0xffff; | 2994 | atpdev->ultra_map[0] = 0xffff; |
2992 | } | 2995 | } |
2993 | 2996 | ||
2994 | shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); | 2997 | shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); |
2995 | if (!shpnt) | 2998 | if (!shpnt) |
2996 | return -ENOMEM; | 2999 | goto err_nomem; |
2997 | 3000 | ||
2998 | p = (struct atp_unit *)&shpnt->hostdata; | 3001 | p = (struct atp_unit *)&shpnt->hostdata; |
2999 | 3002 | ||
3000 | atp_dev.host = shpnt; | 3003 | atpdev->host = shpnt; |
3001 | atp_dev.pdev = pdev; | 3004 | atpdev->pdev = pdev; |
3002 | pci_set_drvdata(pdev, p); | 3005 | pci_set_drvdata(pdev, p); |
3003 | memcpy(p, &atp_dev, sizeof atp_dev); | 3006 | memcpy(p, atpdev, sizeof(*atpdev)); |
3004 | if (atp870u_init_tables(shpnt) < 0) | 3007 | if (atp870u_init_tables(shpnt) < 0) |
3005 | goto unregister; | 3008 | goto unregister; |
3006 | 3009 | ||
@@ -3010,7 +3013,7 @@ flash_ok_885: | |||
3010 | } | 3013 | } |
3011 | 3014 | ||
3012 | spin_lock_irqsave(shpnt->host_lock, flags); | 3015 | spin_lock_irqsave(shpnt->host_lock, flags); |
3013 | if (atp_dev.chip_ver > 0x07) { /* check if atp876 chip then enable terminator */ | 3016 | if (atpdev->chip_ver > 0x07) { /* check if atp876 chip then enable terminator */ |
3014 | tmport = base_io + 0x3e; | 3017 | tmport = base_io + 0x3e; |
3015 | outb(0x00, tmport); | 3018 | outb(0x00, tmport); |
3016 | } | 3019 | } |
@@ -3044,7 +3047,7 @@ flash_ok_885: | |||
3044 | outb((inb(tmport) & 0xef), tmport); | 3047 | outb((inb(tmport) & 0xef), tmport); |
3045 | tmport++; | 3048 | tmport++; |
3046 | outb((inb(tmport) | 0x20), tmport); | 3049 | outb((inb(tmport) | 0x20), tmport); |
3047 | if (atp_dev.chip_ver == 4) | 3050 | if (atpdev->chip_ver == 4) |
3048 | shpnt->max_id = 16; | 3051 | shpnt->max_id = 16; |
3049 | else | 3052 | else |
3050 | shpnt->max_id = 8; | 3053 | shpnt->max_id = 8; |
@@ -3093,6 +3096,12 @@ unregister: | |||
3093 | printk("atp870u_prob:unregister\n"); | 3096 | printk("atp870u_prob:unregister\n"); |
3094 | scsi_host_put(shpnt); | 3097 | scsi_host_put(shpnt); |
3095 | return -1; | 3098 | return -1; |
3099 | err_eio: | ||
3100 | kfree(atpdev); | ||
3101 | return -EIO; | ||
3102 | err_nomem: | ||
3103 | kfree(atpdev); | ||
3104 | return -ENOMEM; | ||
3096 | } | 3105 | } |
3097 | 3106 | ||
3098 | /* The abort command does not leave the device in a clean state where | 3107 | /* The abort command does not leave the device in a clean state where |