net/smc: check port_idx of ib event
For robustness protect of higher port numbers than expected to avoid setting bits behind our port_event_mask. In case of an DEVICE_FATAL event all ports must be checked. The IB_EVENT_GID_CHANGE event is provided in the global event handler, so handle it there. And handle a QP_FATAL event instead of an DEVICE_FATAL event in the qp handler. Signed-off-by: Karsten Graul <kgraul@linux.ibm.com> Signed-off-by: Ursula Braun <ubraun@linux.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Родитель
e78b262226
Коммит
81cf643052
|
@ -257,13 +257,21 @@ static void smc_ib_global_event_handler(struct ib_event_handler *handler,
|
|||
smcibdev = container_of(handler, struct smc_ib_device, event_handler);
|
||||
|
||||
switch (ibevent->event) {
|
||||
case IB_EVENT_PORT_ERR:
|
||||
case IB_EVENT_DEVICE_FATAL:
|
||||
case IB_EVENT_PORT_ACTIVE:
|
||||
port_idx = ibevent->element.port_num - 1;
|
||||
set_bit(port_idx, &smcibdev->port_event_mask);
|
||||
/* terminate all ports on device */
|
||||
for (port_idx = 0; port_idx < SMC_MAX_PORTS; port_idx++)
|
||||
set_bit(port_idx, &smcibdev->port_event_mask);
|
||||
schedule_work(&smcibdev->port_event_work);
|
||||
break;
|
||||
case IB_EVENT_PORT_ERR:
|
||||
case IB_EVENT_PORT_ACTIVE:
|
||||
case IB_EVENT_GID_CHANGE:
|
||||
port_idx = ibevent->element.port_num - 1;
|
||||
if (port_idx < SMC_MAX_PORTS) {
|
||||
set_bit(port_idx, &smcibdev->port_event_mask);
|
||||
schedule_work(&smcibdev->port_event_work);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -294,13 +302,13 @@ static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
|
|||
u8 port_idx;
|
||||
|
||||
switch (ibevent->event) {
|
||||
case IB_EVENT_DEVICE_FATAL:
|
||||
case IB_EVENT_GID_CHANGE:
|
||||
case IB_EVENT_PORT_ERR:
|
||||
case IB_EVENT_QP_FATAL:
|
||||
case IB_EVENT_QP_ACCESS_ERR:
|
||||
port_idx = ibevent->element.qp->port - 1;
|
||||
set_bit(port_idx, &smcibdev->port_event_mask);
|
||||
schedule_work(&smcibdev->port_event_work);
|
||||
if (port_idx < SMC_MAX_PORTS) {
|
||||
set_bit(port_idx, &smcibdev->port_event_mask);
|
||||
schedule_work(&smcibdev->port_event_work);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче