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

Commit b1209983 authored by Alexey Khoroshilov's avatar Alexey Khoroshilov Committed by Greg Kroah-Hartman
Browse files

tty: synclinkmp: do not ignore errors in probe()



synclinkmp_init_one() ignores all errors and does not release
all resources if something fails.

The patch adds returned code to device_init() and add_device()
and proper error handling.

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: default avatarAlexey Khoroshilov <khoroshilov@ispras.ru>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1051937d
Loading
Loading
Loading
Loading
+28 −16
Original line number Diff line number Diff line
@@ -549,8 +549,8 @@ static int tiocmset(struct tty_struct *tty,
			unsigned int set, unsigned int clear);
static int  set_break(struct tty_struct *tty, int break_state);

static void add_device(SLMP_INFO *info);
static void device_init(int adapter_num, struct pci_dev *pdev);
static int  add_device(SLMP_INFO *info);
static int  device_init(int adapter_num, struct pci_dev *pdev);
static int  claim_resources(SLMP_INFO *info);
static void release_resources(SLMP_INFO *info);

@@ -3688,7 +3688,7 @@ static void release_resources(SLMP_INFO *info)
/* Add the specified device instance data structure to the
 * global linked list of devices and increment the device count.
 */
static void add_device(SLMP_INFO *info)
static int add_device(SLMP_INFO *info)
{
	info->next_device = NULL;
	info->line = synclinkmp_device_count;
@@ -3726,7 +3726,9 @@ static void add_device(SLMP_INFO *info)
		info->max_frame_size );

#if SYNCLINK_GENERIC_HDLC
	hdlcdev_init(info);
	return hdlcdev_init(info);
#else
	return 0;
#endif
}

@@ -3815,10 +3817,10 @@ static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
	return info;
}

static void device_init(int adapter_num, struct pci_dev *pdev)
static int device_init(int adapter_num, struct pci_dev *pdev)
{
	SLMP_INFO *port_array[SCA_MAX_PORTS];
	int port;
	int port, rc;

	/* allocate device instances for up to SCA_MAX_PORTS devices */
	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
@@ -3828,14 +3830,16 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
				tty_port_destroy(&port_array[port]->port);
				kfree(port_array[port]);
			}
			return;
			return -ENOMEM;
		}
	}

	/* give copy of port_array to all ports and add to device list  */
	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
		memcpy(port_array[port]->port_array,port_array,sizeof(port_array));
		add_device( port_array[port] );
		rc = add_device( port_array[port] );
		if (rc)
			goto err_add;
		spin_lock_init(&port_array[port]->lock);
	}

@@ -3855,21 +3859,30 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
			alloc_dma_bufs(port_array[port]);
		}

		if ( request_irq(port_array[0]->irq_level,
		rc = request_irq(port_array[0]->irq_level,
					synclinkmp_interrupt,
					port_array[0]->irq_flags,
					port_array[0]->device_name,
					port_array[0]) < 0 ) {
					port_array[0]);
		if ( rc ) {
			printk( "%s(%d):%s Can't request interrupt, IRQ=%d\n",
				__FILE__,__LINE__,
				port_array[0]->device_name,
				port_array[0]->irq_level );
			goto err_irq;
		}
		else {
		port_array[0]->irq_requested = true;
		adapter_test(port_array[0]);
	}
	return 0;
err_irq:
	release_resources( port_array[0] );
err_add:
	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
		tty_port_destroy(&port_array[port]->port);
		kfree(port_array[port]);
	}
	return rc;
}

static const struct tty_operations ops = {
@@ -5584,8 +5597,7 @@ static int synclinkmp_init_one (struct pci_dev *dev,
		printk("error enabling pci device %p\n", dev);
		return -EIO;
	}
	device_init( ++synclinkmp_adapter_count, dev );
	return 0;
	return device_init( ++synclinkmp_adapter_count, dev );
}

static void synclinkmp_remove_one (struct pci_dev *dev)