Commit dc6a78f1 authored by Randy Dunlap's avatar Randy Dunlap Committed by James Bottomley

[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: default avatarRandy Dunlap <rdunlap@xenotime.net>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 87cf8986
...@@ -2625,29 +2625,32 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2625,29 +2625,32 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
unsigned int base_io, tmport, error,n; unsigned int base_io, tmport, error,n;
unsigned char host_id; unsigned char host_id;
struct Scsi_Host *shpnt = NULL; struct Scsi_Host *shpnt = NULL;
struct atp_unit atp_dev, *p; struct atp_unit *atpdev, *p;
unsigned char setupdata[2][16]; unsigned char setupdata[2][16];
int count = 0; int count = 0;
atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
if (!atpdev)
return -ENOMEM;
if (pci_enable_device(pdev)) if (pci_enable_device(pdev))
return -EIO; goto err_eio;
if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_INFO "atp870u: use 32bit DMA mask.\n"); printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
} else { } else {
printk(KERN_ERR "atp870u: DMA mask required but not available.\n"); printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
return -EIO; goto err_eio;
} }
memset(&atp_dev, 0, sizeof atp_dev);
/* /*
* It's probably easier to weed out some revisions like * It's probably easier to weed out some revisions like
* this than via the PCI device table * this than via the PCI device table
*/ */
if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) { if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver); error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
if (atp_dev.chip_ver < 2) if (atpdev->chip_ver < 2)
return -EIO; goto err_eio;
} }
switch (ent->device) { switch (ent->device) {
...@@ -2656,15 +2659,15 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2656,15 +2659,15 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
case ATP880_DEVID1: case ATP880_DEVID1:
case ATP880_DEVID2: case ATP880_DEVID2:
case ATP885_DEVID: case ATP885_DEVID:
atp_dev.chip_ver = 0x04; atpdev->chip_ver = 0x04;
default: default:
break; break;
} }
base_io = pci_resource_start(pdev, 0); base_io = pci_resource_start(pdev, 0);
base_io &= 0xfffffff8; base_io &= 0xfffffff8;
if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) { if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver); error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803 pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
host_id = inb(base_io + 0x39); 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,17 +2675,17 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d" printk(KERN_INFO " ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
" IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); " IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
atp_dev.ioport[0] = base_io + 0x40; atpdev->ioport[0] = base_io + 0x40;
atp_dev.pciport[0] = base_io + 0x28; atpdev->pciport[0] = base_io + 0x28;
atp_dev.dev_id = ent->device; atpdev->dev_id = ent->device;
atp_dev.host_id[0] = host_id; atpdev->host_id[0] = host_id;
tmport = base_io + 0x22; tmport = base_io + 0x22;
atp_dev.scam_on = inb(tmport); atpdev->scam_on = inb(tmport);
tmport += 0x13; tmport += 0x13;
atp_dev.global_map[0] = inb(tmport); atpdev->global_map[0] = inb(tmport);
tmport += 0x07; tmport += 0x07;
atp_dev.ultra_map[0] = inw(tmport); atpdev->ultra_map[0] = inw(tmport);
n = 0x3f09; n = 0x3f09;
next_fblk_880: next_fblk_880:
...@@ -2695,57 +2698,57 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2695,57 +2698,57 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (inb(base_io + 0x30) == 0xff) if (inb(base_io + 0x30) == 0xff)
goto flash_ok_880; goto flash_ok_880;
atp_dev.sp[0][m++] = inb(base_io + 0x30); atpdev->sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[0][m++] = inb(base_io + 0x31); atpdev->sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[0][m++] = inb(base_io + 0x32); atpdev->sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[0][m++] = inb(base_io + 0x33); atpdev->sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34); outw(n, base_io + 0x34);
n += 0x0002; n += 0x0002;
atp_dev.sp[0][m++] = inb(base_io + 0x30); atpdev->sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[0][m++] = inb(base_io + 0x31); atpdev->sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[0][m++] = inb(base_io + 0x32); atpdev->sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[0][m++] = inb(base_io + 0x33); atpdev->sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34); outw(n, base_io + 0x34);
n += 0x0002; n += 0x0002;
atp_dev.sp[0][m++] = inb(base_io + 0x30); atpdev->sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[0][m++] = inb(base_io + 0x31); atpdev->sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[0][m++] = inb(base_io + 0x32); atpdev->sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[0][m++] = inb(base_io + 0x33); atpdev->sp[0][m++] = inb(base_io + 0x33);
outw(n, base_io + 0x34); outw(n, base_io + 0x34);
n += 0x0002; n += 0x0002;
atp_dev.sp[0][m++] = inb(base_io + 0x30); atpdev->sp[0][m++] = inb(base_io + 0x30);
atp_dev.sp[0][m++] = inb(base_io + 0x31); atpdev->sp[0][m++] = inb(base_io + 0x31);
atp_dev.sp[0][m++] = inb(base_io + 0x32); atpdev->sp[0][m++] = inb(base_io + 0x32);
atp_dev.sp[0][m++] = inb(base_io + 0x33); atpdev->sp[0][m++] = inb(base_io + 0x33);
n += 0x0018; n += 0x0018;
goto next_fblk_880; goto next_fblk_880;
flash_ok_880: flash_ok_880:
outw(0, base_io + 0x34); outw(0, base_io + 0x34);
atp_dev.ultra_map[0] = 0; atpdev->ultra_map[0] = 0;
atp_dev.async[0] = 0; atpdev->async[0] = 0;
for (k = 0; k < 16; k++) { for (k = 0; k < 16; k++) {
n = 1; n = 1;
n = n << k; n = n << k;
if (atp_dev.sp[0][k] > 1) { if (atpdev->sp[0][k] > 1) {
atp_dev.ultra_map[0] |= n; atpdev->ultra_map[0] |= n;
} else { } else {
if (atp_dev.sp[0][k] == 0) if (atpdev->sp[0][k] == 0)
atp_dev.async[0] |= n; atpdev->async[0] |= n;
} }
} }
atp_dev.async[0] = ~(atp_dev.async[0]); atpdev->async[0] = ~(atpdev->async[0]);
outb(atp_dev.global_map[0], base_io + 0x35); outb(atpdev->global_map[0], base_io + 0x35);
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt) if (!shpnt)
return -ENOMEM; goto err_nomem;
p = (struct atp_unit *)&shpnt->hostdata; p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt; atpdev->host = shpnt;
atp_dev.pdev = pdev; atpdev->pdev = pdev;
pci_set_drvdata(pdev, p); pci_set_drvdata(pdev, p);
memcpy(p, &atp_dev, sizeof atp_dev); memcpy(p, atpdev, sizeof(*atpdev));
if (atp870u_init_tables(shpnt) < 0) { if (atp870u_init_tables(shpnt) < 0) {
printk(KERN_ERR "Unable to allocate tables for Acard controller\n"); printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
goto unregister; goto unregister;
...@@ -2798,24 +2801,24 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2798,24 +2801,24 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n" printk(KERN_INFO " ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: IO:%x, IRQ:%d.\n"
, base_io, pdev->irq); , base_io, pdev->irq);
atp_dev.pdev = pdev; atpdev->pdev = pdev;
atp_dev.dev_id = ent->device; atpdev->dev_id = ent->device;
atp_dev.baseport = base_io; atpdev->baseport = base_io;
atp_dev.ioport[0] = base_io + 0x80; atpdev->ioport[0] = base_io + 0x80;
atp_dev.ioport[1] = base_io + 0xc0; atpdev->ioport[1] = base_io + 0xc0;
atp_dev.pciport[0] = base_io + 0x40; atpdev->pciport[0] = base_io + 0x40;
atp_dev.pciport[1] = base_io + 0x50; atpdev->pciport[1] = base_io + 0x50;
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt) if (!shpnt)
return -ENOMEM; goto err_nomem;
p = (struct atp_unit *)&shpnt->hostdata; p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt; atpdev->host = shpnt;
atp_dev.pdev = pdev; atpdev->pdev = pdev;
pci_set_drvdata(pdev, p); pci_set_drvdata(pdev, p);
memcpy(p, &atp_dev, sizeof(struct atp_unit)); memcpy(p, atpdev, sizeof(struct atp_unit));
if (atp870u_init_tables(shpnt) < 0) if (atp870u_init_tables(shpnt) < 0)
goto unregister; goto unregister;
...@@ -2974,33 +2977,33 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2974,33 +2977,33 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d " printk(KERN_INFO " ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq); "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
atp_dev.ioport[0] = base_io; atpdev->ioport[0] = base_io;
atp_dev.pciport[0] = base_io + 0x20; atpdev->pciport[0] = base_io + 0x20;
atp_dev.dev_id = ent->device; atpdev->dev_id = ent->device;
host_id &= 0x07; host_id &= 0x07;
atp_dev.host_id[0] = host_id; atpdev->host_id[0] = host_id;
tmport = base_io + 0x22; tmport = base_io + 0x22;
atp_dev.scam_on = inb(tmport); atpdev->scam_on = inb(tmport);
tmport += 0x0b; tmport += 0x0b;
atp_dev.global_map[0] = inb(tmport++); atpdev->global_map[0] = inb(tmport++);
atp_dev.ultra_map[0] = inw(tmport); atpdev->ultra_map[0] = inw(tmport);
if (atp_dev.ultra_map[0] == 0) { if (atpdev->ultra_map[0] == 0) {
atp_dev.scam_on = 0x00; atpdev->scam_on = 0x00;
atp_dev.global_map[0] = 0x20; atpdev->global_map[0] = 0x20;
atp_dev.ultra_map[0] = 0xffff; atpdev->ultra_map[0] = 0xffff;
} }
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit)); shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt) if (!shpnt)
return -ENOMEM; goto err_nomem;
p = (struct atp_unit *)&shpnt->hostdata; p = (struct atp_unit *)&shpnt->hostdata;
atp_dev.host = shpnt; atpdev->host = shpnt;
atp_dev.pdev = pdev; atpdev->pdev = pdev;
pci_set_drvdata(pdev, p); pci_set_drvdata(pdev, p);
memcpy(p, &atp_dev, sizeof atp_dev); memcpy(p, atpdev, sizeof(*atpdev));
if (atp870u_init_tables(shpnt) < 0) if (atp870u_init_tables(shpnt) < 0)
goto unregister; goto unregister;
...@@ -3010,7 +3013,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3010,7 +3013,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
spin_lock_irqsave(shpnt->host_lock, flags); spin_lock_irqsave(shpnt->host_lock, flags);
if (atp_dev.chip_ver > 0x07) { /* check if atp876 chip then enable terminator */ if (atpdev->chip_ver > 0x07) { /* check if atp876 chip then enable terminator */
tmport = base_io + 0x3e; tmport = base_io + 0x3e;
outb(0x00, tmport); outb(0x00, tmport);
} }
...@@ -3044,7 +3047,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3044,7 +3047,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
outb((inb(tmport) & 0xef), tmport); outb((inb(tmport) & 0xef), tmport);
tmport++; tmport++;
outb((inb(tmport) | 0x20), tmport); outb((inb(tmport) | 0x20), tmport);
if (atp_dev.chip_ver == 4) if (atpdev->chip_ver == 4)
shpnt->max_id = 16; shpnt->max_id = 16;
else else
shpnt->max_id = 8; shpnt->max_id = 8;
...@@ -3093,6 +3096,12 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -3093,6 +3096,12 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
printk("atp870u_prob:unregister\n"); printk("atp870u_prob:unregister\n");
scsi_host_put(shpnt); scsi_host_put(shpnt);
return -1; return -1;
err_eio:
kfree(atpdev);
return -EIO;
err_nomem:
kfree(atpdev);
return -ENOMEM;
} }
/* The abort command does not leave the device in a clean state where /* The abort command does not leave the device in a clean state where
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment