aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSathya Perla <sathyap@serverengines.com>2009-06-17 20:05:54 -0400
committerDavid S. Miller <davem@davemloft.net>2009-06-19 03:18:40 -0400
commit6ac7b687cb3acc437a586794949a43f5249956bb (patch)
tree249aa952dfafa22a8c299dc344df1aa7aeea8364
parent5fb379ee67a7ec55ff65b467b472f3d69b60ba16 (diff)
be2net: Use MCC queue for cmds that may be called in BH context
Currenlty multicast_set and promiscuous_config cmds -- that may be called in BH context -- use the blocking MCC mbox to post cmds. An mbox cmd is protected via a spin_lock(cmd_lock) and not spin_lock_bh() as it is undesirable to disable BHs while a blocking mbox cmd is in progress (and take long to finish.) This can lockup a cmd in progress in process context. So, these two cmds in BH context must use the MCC queue to post cmds. Signed-off-by: Sathya Perla <sathyap@serverengines.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/benet/be_cmds.c69
1 files changed, 52 insertions, 17 deletions
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index f1ec191f0c0d..e4ad5e67fde7 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -17,7 +17,7 @@
17 17
18#include "be.h" 18#include "be.h"
19 19
20void be_mcc_notify(struct be_ctrl_info *ctrl) 20static void be_mcc_notify(struct be_ctrl_info *ctrl)
21{ 21{
22 struct be_queue_info *mccq = &ctrl->mcc_obj.q; 22 struct be_queue_info *mccq = &ctrl->mcc_obj.q;
23 u32 val = 0; 23 u32 val = 0;
@@ -101,6 +101,28 @@ void be_process_mcc(struct be_ctrl_info *ctrl)
101 spin_unlock_bh(&ctrl->mcc_cq_lock); 101 spin_unlock_bh(&ctrl->mcc_cq_lock);
102} 102}
103 103
104/* Wait till no more pending mcc requests are present */
105static void be_mcc_wait_compl(struct be_ctrl_info *ctrl)
106{
107#define mcc_timeout 50000 /* 5s timeout */
108 int i;
109 for (i = 0; i < mcc_timeout; i++) {
110 be_process_mcc(ctrl);
111 if (atomic_read(&ctrl->mcc_obj.q.used) == 0)
112 break;
113 udelay(100);
114 }
115 if (i == mcc_timeout)
116 printk(KERN_WARNING DRV_NAME "mcc poll timed out\n");
117}
118
119/* Notify MCC requests and wait for completion */
120static void be_mcc_notify_wait(struct be_ctrl_info *ctrl)
121{
122 be_mcc_notify(ctrl);
123 be_mcc_wait_compl(ctrl);
124}
125
104static int be_mbox_db_ready_wait(void __iomem *db) 126static int be_mbox_db_ready_wait(void __iomem *db)
105{ 127{
106 int cnt = 0, wait = 5; 128 int cnt = 0, wait = 5;
@@ -872,14 +894,18 @@ int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array,
872 return status; 894 return status;
873} 895}
874 896
897/* Use MCC for this command as it may be called in BH context */
875int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) 898int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
876{ 899{
877 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 900 struct be_mcc_wrb *wrb;
878 struct be_cmd_req_promiscuous_config *req = embedded_payload(wrb); 901 struct be_cmd_req_promiscuous_config *req;
879 int status;
880 902
881 spin_lock(&ctrl->mbox_lock); 903 spin_lock_bh(&ctrl->mcc_lock);
882 memset(wrb, 0, sizeof(*wrb)); 904
905 wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
906 BUG_ON(!wrb);
907
908 req = embedded_payload(wrb);
883 909
884 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 910 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
885 911
@@ -891,21 +917,29 @@ int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en)
891 else 917 else
892 req->port0_promiscuous = en; 918 req->port0_promiscuous = en;
893 919
894 status = be_mbox_db_ring(ctrl); 920 be_mcc_notify_wait(ctrl);
895 921
896 spin_unlock(&ctrl->mbox_lock); 922 spin_unlock_bh(&ctrl->mcc_lock);
897 return status; 923 return 0;
898} 924}
899 925
926/*
927 * Use MCC for this command as it may be called in BH context
928 * (mc == NULL) => multicast promiscous
929 */
900int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, 930int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table,
901 u32 num, bool promiscuous) 931 u32 num, bool promiscuous)
902{ 932{
903 struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); 933#define BE_MAX_MC 32 /* set mcast promisc if > 32 */
904 struct be_cmd_req_mcast_mac_config *req = embedded_payload(wrb); 934 struct be_mcc_wrb *wrb;
905 int status; 935 struct be_cmd_req_mcast_mac_config *req;
906 936
907 spin_lock(&ctrl->mbox_lock); 937 spin_lock_bh(&ctrl->mcc_lock);
908 memset(wrb, 0, sizeof(*wrb)); 938
939 wrb = wrb_from_mcc(&ctrl->mcc_obj.q);
940 BUG_ON(!wrb);
941
942 req = embedded_payload(wrb);
909 943
910 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); 944 be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0);
911 945
@@ -920,10 +954,11 @@ int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table,
920 memcpy(req->mac, mac_table, ETH_ALEN * num); 954 memcpy(req->mac, mac_table, ETH_ALEN * num);
921 } 955 }
922 956
923 status = be_mbox_db_ring(ctrl); 957 be_mcc_notify_wait(ctrl);
924 958
925 spin_unlock(&ctrl->mbox_lock); 959 spin_unlock_bh(&ctrl->mcc_lock);
926 return status; 960
961 return 0;
927} 962}
928 963
929int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) 964int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc)