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

Commit 2f69ae01 authored by Jan-Bernd Themann's avatar Jan-Bernd Themann Committed by Jeff Garzik
Browse files

ehea: fix race condition



When ehea_stop is called the function
cancel_work_sync(&port->reset_task) is used to ensure
that the reset task is not running anymore. We need an
additional flag to ensure that it can not be scheduled
after this call again for a certain time.

Signed-off-by: default avatarJan-Bernd Themann <themann@de.ibm.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent b0afffe8
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@
#include <asm/io.h>

#define DRV_NAME	"ehea"
#define DRV_VERSION	"EHEA_0091"
#define DRV_VERSION	"EHEA_0092"

/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
@@ -478,6 +478,7 @@ struct ehea_port {
	int num_add_tx_qps;
	int num_mcs;
	int resets;
	u64 flags;
	u64 mac_addr;
	u32 logical_port_id;
	u32 port_speed;
@@ -501,7 +502,8 @@ struct port_res_cfg {
};

enum ehea_flag_bits {
	__EHEA_STOP_XFER
	__EHEA_STOP_XFER,
	__EHEA_DISABLE_PORT_RESET
};

void ehea_set_ethtool_ops(struct net_device *netdev);
+12 −5
Original line number Diff line number Diff line
@@ -138,6 +138,12 @@ void ehea_dump(void *adr, int len, char *msg)
	}
}

void ehea_schedule_port_reset(struct ehea_port *port)
{
	if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
		schedule_work(&port->reset_task);
}

static void ehea_update_firmware_handles(void)
{
	struct ehea_fw_handle_entry *arr = NULL;
@@ -588,7 +594,7 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
				   "Resetting port.", pr->qp->init_attr.qp_nr);
			ehea_dump(cqe, sizeof(*cqe), "CQE");
		}
		schedule_work(&pr->port->reset_task);
		ehea_schedule_port_reset(pr->port);
		return 1;
	}

@@ -766,7 +772,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
			ehea_error("Send Completion Error: Resetting port");
			if (netif_msg_tx_err(pr->port))
				ehea_dump(cqe, sizeof(*cqe), "Send CQE");
			schedule_work(&pr->port->reset_task);
			ehea_schedule_port_reset(pr->port);
			break;
		}

@@ -886,7 +892,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
		eqe = ehea_poll_eq(port->qp_eq);
	}

	schedule_work(&port->reset_task);
	ehea_schedule_port_reset(port);

	return IRQ_HANDLED;
}
@@ -2606,13 +2612,14 @@ static int ehea_stop(struct net_device *dev)
	if (netif_msg_ifdown(port))
		ehea_info("disabling port %s", dev->name);

	set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
	cancel_work_sync(&port->reset_task);

	mutex_lock(&port->port_lock);
	netif_stop_queue(dev);
	port_napi_disable(port);
	ret = ehea_down(dev);
	mutex_unlock(&port->port_lock);
	clear_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
	return ret;
}

@@ -2942,7 +2949,7 @@ static void ehea_tx_watchdog(struct net_device *dev)

	if (netif_carrier_ok(dev) &&
	    !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
		schedule_work(&port->reset_task);
		ehea_schedule_port_reset(port);
}

int ehea_sense_adapter_attr(struct ehea_adapter *adapter)