Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+83 −74
Original line number Diff line number Diff line
@@ -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 char host_id;
	struct Scsi_Host *shpnt = NULL;
	struct atp_unit atp_dev, *p;
	struct atp_unit *atpdev, *p;
	unsigned char setupdata[2][16];
	int count = 0;

	atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
	if (!atpdev)
		return -ENOMEM;

	if (pci_enable_device(pdev))
		return -EIO;
		goto err_eio;

        if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
        } else {
                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
	 * this than via the PCI device table
	 */
	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
		error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
		if (atp_dev.chip_ver < 2)
			return -EIO;
		error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atpdev->chip_ver);
		if (atpdev->chip_ver < 2)
			goto err_eio;
	}

	switch (ent->device) {
@@ -2656,7 +2659,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	case ATP880_DEVID1:	
	case ATP880_DEVID2:	
	case ATP885_DEVID:	
		atp_dev.chip_ver = 0x04;
		atpdev->chip_ver = 0x04;
	default:
		break;
	}
@@ -2664,7 +2667,7 @@ static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
	base_io &= 0xfffffff8;

	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

		host_id = inb(base_io + 0x39);
@@ -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"
			"    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
		atp_dev.ioport[0] = base_io + 0x40;
		atp_dev.pciport[0] = base_io + 0x28;
		atp_dev.dev_id = ent->device;
		atp_dev.host_id[0] = host_id;
		atpdev->ioport[0] = base_io + 0x40;
		atpdev->pciport[0] = base_io + 0x28;
		atpdev->dev_id = ent->device;
		atpdev->host_id[0] = host_id;

		tmport = base_io + 0x22;
		atp_dev.scam_on = inb(tmport);
		atpdev->scam_on = inb(tmport);
		tmport += 0x13;
		atp_dev.global_map[0] = inb(tmport);
		atpdev->global_map[0] = inb(tmport);
		tmport += 0x07;
		atp_dev.ultra_map[0] = inw(tmport);
		atpdev->ultra_map[0] = inw(tmport);

		n = 0x3f09;
next_fblk_880:
@@ -2695,57 +2698,57 @@ next_fblk_880:
		if (inb(base_io + 0x30) == 0xff)
			goto flash_ok_880;

		atp_dev.sp[0][m++] = inb(base_io + 0x30);
		atp_dev.sp[0][m++] = inb(base_io + 0x31);
		atp_dev.sp[0][m++] = inb(base_io + 0x32);
		atp_dev.sp[0][m++] = inb(base_io + 0x33);
		atpdev->sp[0][m++] = inb(base_io + 0x30);
		atpdev->sp[0][m++] = inb(base_io + 0x31);
		atpdev->sp[0][m++] = inb(base_io + 0x32);
		atpdev->sp[0][m++] = inb(base_io + 0x33);
		outw(n, base_io + 0x34);
		n += 0x0002;
		atp_dev.sp[0][m++] = inb(base_io + 0x30);
		atp_dev.sp[0][m++] = inb(base_io + 0x31);
		atp_dev.sp[0][m++] = inb(base_io + 0x32);
		atp_dev.sp[0][m++] = inb(base_io + 0x33);
		atpdev->sp[0][m++] = inb(base_io + 0x30);
		atpdev->sp[0][m++] = inb(base_io + 0x31);
		atpdev->sp[0][m++] = inb(base_io + 0x32);
		atpdev->sp[0][m++] = inb(base_io + 0x33);
		outw(n, base_io + 0x34);
		n += 0x0002;
		atp_dev.sp[0][m++] = inb(base_io + 0x30);
		atp_dev.sp[0][m++] = inb(base_io + 0x31);
		atp_dev.sp[0][m++] = inb(base_io + 0x32);
		atp_dev.sp[0][m++] = inb(base_io + 0x33);
		atpdev->sp[0][m++] = inb(base_io + 0x30);
		atpdev->sp[0][m++] = inb(base_io + 0x31);
		atpdev->sp[0][m++] = inb(base_io + 0x32);
		atpdev->sp[0][m++] = inb(base_io + 0x33);
		outw(n, base_io + 0x34);
		n += 0x0002;
		atp_dev.sp[0][m++] = inb(base_io + 0x30);
		atp_dev.sp[0][m++] = inb(base_io + 0x31);
		atp_dev.sp[0][m++] = inb(base_io + 0x32);
		atp_dev.sp[0][m++] = inb(base_io + 0x33);
		atpdev->sp[0][m++] = inb(base_io + 0x30);
		atpdev->sp[0][m++] = inb(base_io + 0x31);
		atpdev->sp[0][m++] = inb(base_io + 0x32);
		atpdev->sp[0][m++] = inb(base_io + 0x33);
		n += 0x0018;
		goto next_fblk_880;
flash_ok_880:
		outw(0, base_io + 0x34);
		atp_dev.ultra_map[0] = 0;
		atp_dev.async[0] = 0;
		atpdev->ultra_map[0] = 0;
		atpdev->async[0] = 0;
		for (k = 0; k < 16; k++) {
			n = 1;
			n = n << k;
			if (atp_dev.sp[0][k] > 1) {
				atp_dev.ultra_map[0] |= n;
			if (atpdev->sp[0][k] > 1) {
				atpdev->ultra_map[0] |= n;
			} else {
				if (atp_dev.sp[0][k] == 0)
					atp_dev.async[0] |= n;
				if (atpdev->sp[0][k] == 0)
					atpdev->async[0] |= n;
 			}
	 	}
		atp_dev.async[0] = ~(atp_dev.async[0]);
		outb(atp_dev.global_map[0], base_io + 0x35);
		atpdev->async[0] = ~(atpdev->async[0]);
		outb(atpdev->global_map[0], base_io + 0x35);
 
		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
		if (!shpnt)
			return -ENOMEM;
			goto err_nomem;

		p = (struct atp_unit *)&shpnt->hostdata;

		atp_dev.host = shpnt;
		atp_dev.pdev = pdev;
		atpdev->host = shpnt;
		atpdev->pdev = pdev;
		pci_set_drvdata(pdev, p);
		memcpy(p, &atp_dev, sizeof atp_dev);
		memcpy(p, atpdev, sizeof(*atpdev));
		if (atp870u_init_tables(shpnt) < 0) {
			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
			goto unregister;
@@ -2798,24 +2801,24 @@ flash_ok_880:
			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
			       , base_io, pdev->irq);
        	
		atp_dev.pdev = pdev;	
		atp_dev.dev_id  = ent->device;
		atp_dev.baseport = base_io;
		atp_dev.ioport[0] = base_io + 0x80;
		atp_dev.ioport[1] = base_io + 0xc0;
		atp_dev.pciport[0] = base_io + 0x40;
		atp_dev.pciport[1] = base_io + 0x50;
		atpdev->pdev = pdev;
		atpdev->dev_id  = ent->device;
		atpdev->baseport = base_io;
		atpdev->ioport[0] = base_io + 0x80;
		atpdev->ioport[1] = base_io + 0xc0;
		atpdev->pciport[0] = base_io + 0x40;
		atpdev->pciport[1] = base_io + 0x50;
				
		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
		if (!shpnt)
			return -ENOMEM;
			goto err_nomem;
        	
		p = (struct atp_unit *)&shpnt->hostdata;
        	
		atp_dev.host = shpnt;
		atp_dev.pdev = pdev;
		atpdev->host = shpnt;
		atpdev->pdev = pdev;
		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)
			goto unregister;
			
@@ -2974,33 +2977,33 @@ flash_ok_885:
		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);

		atp_dev.ioport[0] = base_io;
		atp_dev.pciport[0] = base_io + 0x20;
		atp_dev.dev_id = ent->device;
		atpdev->ioport[0] = base_io;
		atpdev->pciport[0] = base_io + 0x20;
		atpdev->dev_id = ent->device;
		host_id &= 0x07;
		atp_dev.host_id[0] = host_id;
		atpdev->host_id[0] = host_id;
		tmport = base_io + 0x22;
		atp_dev.scam_on = inb(tmport);
		atpdev->scam_on = inb(tmport);
		tmport += 0x0b;
		atp_dev.global_map[0] = inb(tmport++);
		atp_dev.ultra_map[0] = inw(tmport);
		atpdev->global_map[0] = inb(tmport++);
		atpdev->ultra_map[0] = inw(tmport);

		if (atp_dev.ultra_map[0] == 0) {
			atp_dev.scam_on = 0x00;
			atp_dev.global_map[0] = 0x20;
			atp_dev.ultra_map[0] = 0xffff;
		if (atpdev->ultra_map[0] == 0) {
			atpdev->scam_on = 0x00;
			atpdev->global_map[0] = 0x20;
			atpdev->ultra_map[0] = 0xffff;
		}

		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
		if (!shpnt)
			return -ENOMEM;
			goto err_nomem;

		p = (struct atp_unit *)&shpnt->hostdata;
		
		atp_dev.host = shpnt;
		atp_dev.pdev = pdev;
		atpdev->host = shpnt;
		atpdev->pdev = pdev;
		pci_set_drvdata(pdev, p);
		memcpy(p, &atp_dev, sizeof atp_dev);
		memcpy(p, atpdev, sizeof(*atpdev));
		if (atp870u_init_tables(shpnt) < 0)
			goto unregister;

@@ -3010,7 +3013,7 @@ flash_ok_885:
		}

		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;
			outb(0x00, tmport);
		}
@@ -3044,7 +3047,7 @@ flash_ok_885:
		outb((inb(tmport) & 0xef), tmport);
		tmport++;
		outb((inb(tmport) | 0x20), tmport);
		if (atp_dev.chip_ver == 4)
		if (atpdev->chip_ver == 4)
			shpnt->max_id = 16;
		else		
			shpnt->max_id = 8;
@@ -3093,6 +3096,12 @@ unregister:
	printk("atp870u_prob:unregister\n");
	scsi_host_put(shpnt);
	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