aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJan-Bernd Themann <ossthema@de.ibm.com>2008-07-03 10:18:51 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-07-04 08:10:41 -0400
commit2f69ae01c83a94af5dc3c20e8135b974687ed004 (patch)
treefba9563322f4f0932b0222f4b026cb96485dc0c5 /drivers
parentb0afffe89be619f42ae4215554ed66e67de7bb0e (diff)
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: Jan-Bernd Themann <themann@de.ibm.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ehea/ehea.h6
-rw-r--r--drivers/net/ehea/ehea_main.c17
2 files changed, 16 insertions, 7 deletions
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index bf57e1532f5e..e01926b7b5b7 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
40#include <asm/io.h> 40#include <asm/io.h>
41 41
42#define DRV_NAME "ehea" 42#define DRV_NAME "ehea"
43#define DRV_VERSION "EHEA_0091" 43#define DRV_VERSION "EHEA_0092"
44 44
45/* eHEA capability flags */ 45/* eHEA capability flags */
46#define DLPAR_PORT_ADD_REM 1 46#define DLPAR_PORT_ADD_REM 1
@@ -478,6 +478,7 @@ struct ehea_port {
478 int num_add_tx_qps; 478 int num_add_tx_qps;
479 int num_mcs; 479 int num_mcs;
480 int resets; 480 int resets;
481 u64 flags;
481 u64 mac_addr; 482 u64 mac_addr;
482 u32 logical_port_id; 483 u32 logical_port_id;
483 u32 port_speed; 484 u32 port_speed;
@@ -501,7 +502,8 @@ struct port_res_cfg {
501}; 502};
502 503
503enum ehea_flag_bits { 504enum ehea_flag_bits {
504 __EHEA_STOP_XFER 505 __EHEA_STOP_XFER,
506 __EHEA_DISABLE_PORT_RESET
505}; 507};
506 508
507void ehea_set_ethtool_ops(struct net_device *netdev); 509void ehea_set_ethtool_ops(struct net_device *netdev);
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 6ebcb221cd5e..49ba6a9a7b06 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -138,6 +138,12 @@ void ehea_dump(void *adr, int len, char *msg)
138 } 138 }
139} 139}
140 140
141void ehea_schedule_port_reset(struct ehea_port *port)
142{
143 if (!test_bit(__EHEA_DISABLE_PORT_RESET, &port->flags))
144 schedule_work(&port->reset_task);
145}
146
141static void ehea_update_firmware_handles(void) 147static void ehea_update_firmware_handles(void)
142{ 148{
143 struct ehea_fw_handle_entry *arr = NULL; 149 struct ehea_fw_handle_entry *arr = NULL;
@@ -588,7 +594,7 @@ static int ehea_treat_poll_error(struct ehea_port_res *pr, int rq,
588 "Resetting port.", pr->qp->init_attr.qp_nr); 594 "Resetting port.", pr->qp->init_attr.qp_nr);
589 ehea_dump(cqe, sizeof(*cqe), "CQE"); 595 ehea_dump(cqe, sizeof(*cqe), "CQE");
590 } 596 }
591 schedule_work(&pr->port->reset_task); 597 ehea_schedule_port_reset(pr->port);
592 return 1; 598 return 1;
593 } 599 }
594 600
@@ -766,7 +772,7 @@ static struct ehea_cqe *ehea_proc_cqes(struct ehea_port_res *pr, int my_quota)
766 ehea_error("Send Completion Error: Resetting port"); 772 ehea_error("Send Completion Error: Resetting port");
767 if (netif_msg_tx_err(pr->port)) 773 if (netif_msg_tx_err(pr->port))
768 ehea_dump(cqe, sizeof(*cqe), "Send CQE"); 774 ehea_dump(cqe, sizeof(*cqe), "Send CQE");
769 schedule_work(&pr->port->reset_task); 775 ehea_schedule_port_reset(pr->port);
770 break; 776 break;
771 } 777 }
772 778
@@ -886,7 +892,7 @@ static irqreturn_t ehea_qp_aff_irq_handler(int irq, void *param)
886 eqe = ehea_poll_eq(port->qp_eq); 892 eqe = ehea_poll_eq(port->qp_eq);
887 } 893 }
888 894
889 schedule_work(&port->reset_task); 895 ehea_schedule_port_reset(port);
890 896
891 return IRQ_HANDLED; 897 return IRQ_HANDLED;
892} 898}
@@ -2606,13 +2612,14 @@ static int ehea_stop(struct net_device *dev)
2606 if (netif_msg_ifdown(port)) 2612 if (netif_msg_ifdown(port))
2607 ehea_info("disabling port %s", dev->name); 2613 ehea_info("disabling port %s", dev->name);
2608 2614
2615 set_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
2609 cancel_work_sync(&port->reset_task); 2616 cancel_work_sync(&port->reset_task);
2610
2611 mutex_lock(&port->port_lock); 2617 mutex_lock(&port->port_lock);
2612 netif_stop_queue(dev); 2618 netif_stop_queue(dev);
2613 port_napi_disable(port); 2619 port_napi_disable(port);
2614 ret = ehea_down(dev); 2620 ret = ehea_down(dev);
2615 mutex_unlock(&port->port_lock); 2621 mutex_unlock(&port->port_lock);
2622 clear_bit(__EHEA_DISABLE_PORT_RESET, &port->flags);
2616 return ret; 2623 return ret;
2617} 2624}
2618 2625
@@ -2942,7 +2949,7 @@ static void ehea_tx_watchdog(struct net_device *dev)
2942 2949
2943 if (netif_carrier_ok(dev) && 2950 if (netif_carrier_ok(dev) &&
2944 !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags)) 2951 !test_bit(__EHEA_STOP_XFER, &ehea_driver_flags))
2945 schedule_work(&port->reset_task); 2952 ehea_schedule_port_reset(port);
2946} 2953}
2947 2954
2948int ehea_sense_adapter_attr(struct ehea_adapter *adapter) 2955int ehea_sense_adapter_attr(struct ehea_adapter *adapter)