aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe_ctlr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/fcoe/fcoe_ctlr.c')
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c159
1 files changed, 145 insertions, 14 deletions
diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c
index 5a4c7250aa77..d68d57241ee6 100644
--- a/drivers/scsi/fcoe/fcoe_ctlr.c
+++ b/drivers/scsi/fcoe/fcoe_ctlr.c
@@ -160,6 +160,76 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
160} 160}
161EXPORT_SYMBOL(fcoe_ctlr_init); 161EXPORT_SYMBOL(fcoe_ctlr_init);
162 162
163static int fcoe_sysfs_fcf_add(struct fcoe_fcf *new)
164{
165 struct fcoe_ctlr *fip = new->fip;
166 struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
167 struct fcoe_fcf_device temp, *fcf_dev;
168 int rc = 0;
169
170 LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
171 new->fabric_name, new->fcf_mac);
172
173 mutex_lock(&ctlr_dev->lock);
174
175 temp.fabric_name = new->fabric_name;
176 temp.switch_name = new->switch_name;
177 temp.fc_map = new->fc_map;
178 temp.vfid = new->vfid;
179 memcpy(temp.mac, new->fcf_mac, ETH_ALEN);
180 temp.priority = new->pri;
181 temp.fka_period = new->fka_period;
182 temp.selected = 0; /* default to unselected */
183
184 fcf_dev = fcoe_fcf_device_add(ctlr_dev, &temp);
185 if (unlikely(!fcf_dev)) {
186 rc = -ENOMEM;
187 goto out;
188 }
189
190 /*
191 * The fcoe_sysfs layer can return a CONNECTED fcf that
192 * has a priv (fcf was never deleted) or a CONNECTED fcf
193 * that doesn't have a priv (fcf was deleted). However,
194 * libfcoe will always delete FCFs before trying to add
195 * them. This is ensured because both recv_adv and
196 * age_fcfs are protected by the the fcoe_ctlr's mutex.
197 * This means that we should never get a FCF with a
198 * non-NULL priv pointer.
199 */
200 BUG_ON(fcf_dev->priv);
201
202 fcf_dev->priv = new;
203 new->fcf_dev = fcf_dev;
204
205 list_add(&new->list, &fip->fcfs);
206 fip->fcf_count++;
207
208out:
209 mutex_unlock(&ctlr_dev->lock);
210 return rc;
211}
212
213static void fcoe_sysfs_fcf_del(struct fcoe_fcf *new)
214{
215 struct fcoe_ctlr *fip = new->fip;
216 struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
217 struct fcoe_fcf_device *fcf_dev;
218
219 list_del(&new->list);
220 fip->fcf_count--;
221
222 mutex_lock(&ctlr_dev->lock);
223
224 fcf_dev = fcoe_fcf_to_fcf_dev(new);
225 WARN_ON(!fcf_dev);
226 new->fcf_dev = NULL;
227 fcoe_fcf_device_delete(fcf_dev);
228 kfree(new);
229
230 mutex_unlock(&ctlr_dev->lock);
231}
232
163/** 233/**
164 * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller 234 * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller
165 * @fip: The FCoE controller whose FCFs are to be reset 235 * @fip: The FCoE controller whose FCFs are to be reset
@@ -173,10 +243,10 @@ static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
173 243
174 fip->sel_fcf = NULL; 244 fip->sel_fcf = NULL;
175 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { 245 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
176 list_del(&fcf->list); 246 fcoe_sysfs_fcf_del(fcf);
177 kfree(fcf);
178 } 247 }
179 fip->fcf_count = 0; 248 WARN_ON(fip->fcf_count);
249
180 fip->sel_time = 0; 250 fip->sel_time = 0;
181} 251}
182 252
@@ -717,8 +787,11 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
717 unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD); 787 unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
718 unsigned long deadline; 788 unsigned long deadline;
719 unsigned long sel_time = 0; 789 unsigned long sel_time = 0;
790 struct list_head del_list;
720 struct fcoe_dev_stats *stats; 791 struct fcoe_dev_stats *stats;
721 792
793 INIT_LIST_HEAD(&del_list);
794
722 stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu()); 795 stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu());
723 796
724 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) { 797 list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
@@ -739,10 +812,13 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
739 if (time_after_eq(jiffies, deadline)) { 812 if (time_after_eq(jiffies, deadline)) {
740 if (fip->sel_fcf == fcf) 813 if (fip->sel_fcf == fcf)
741 fip->sel_fcf = NULL; 814 fip->sel_fcf = NULL;
815 /*
816 * Move to delete list so we can call
817 * fcoe_sysfs_fcf_del (which can sleep)
818 * after the put_cpu().
819 */
742 list_del(&fcf->list); 820 list_del(&fcf->list);
743 WARN_ON(!fip->fcf_count); 821 list_add(&fcf->list, &del_list);
744 fip->fcf_count--;
745 kfree(fcf);
746 stats->VLinkFailureCount++; 822 stats->VLinkFailureCount++;
747 } else { 823 } else {
748 if (time_after(next_timer, deadline)) 824 if (time_after(next_timer, deadline))
@@ -753,6 +829,12 @@ static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
753 } 829 }
754 } 830 }
755 put_cpu(); 831 put_cpu();
832
833 list_for_each_entry_safe(fcf, next, &del_list, list) {
834 /* Removes fcf from current list */
835 fcoe_sysfs_fcf_del(fcf);
836 }
837
756 if (sel_time && !fip->sel_fcf && !fip->sel_time) { 838 if (sel_time && !fip->sel_fcf && !fip->sel_time) {
757 sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY); 839 sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
758 fip->sel_time = sel_time; 840 fip->sel_time = sel_time;
@@ -903,23 +985,23 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
903{ 985{
904 struct fcoe_fcf *fcf; 986 struct fcoe_fcf *fcf;
905 struct fcoe_fcf new; 987 struct fcoe_fcf new;
906 struct fcoe_fcf *found;
907 unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV); 988 unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
908 int first = 0; 989 int first = 0;
909 int mtu_valid; 990 int mtu_valid;
991 int found = 0;
992 int rc = 0;
910 993
911 if (fcoe_ctlr_parse_adv(fip, skb, &new)) 994 if (fcoe_ctlr_parse_adv(fip, skb, &new))
912 return; 995 return;
913 996
914 mutex_lock(&fip->ctlr_mutex); 997 mutex_lock(&fip->ctlr_mutex);
915 first = list_empty(&fip->fcfs); 998 first = list_empty(&fip->fcfs);
916 found = NULL;
917 list_for_each_entry(fcf, &fip->fcfs, list) { 999 list_for_each_entry(fcf, &fip->fcfs, list) {
918 if (fcf->switch_name == new.switch_name && 1000 if (fcf->switch_name == new.switch_name &&
919 fcf->fabric_name == new.fabric_name && 1001 fcf->fabric_name == new.fabric_name &&
920 fcf->fc_map == new.fc_map && 1002 fcf->fc_map == new.fc_map &&
921 compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) { 1003 compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
922 found = fcf; 1004 found = 1;
923 break; 1005 break;
924 } 1006 }
925 } 1007 }
@@ -931,9 +1013,16 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
931 if (!fcf) 1013 if (!fcf)
932 goto out; 1014 goto out;
933 1015
934 fip->fcf_count++;
935 memcpy(fcf, &new, sizeof(new)); 1016 memcpy(fcf, &new, sizeof(new));
936 list_add(&fcf->list, &fip->fcfs); 1017 fcf->fip = fip;
1018 rc = fcoe_sysfs_fcf_add(fcf);
1019 if (rc) {
1020 printk(KERN_ERR "Failed to allocate sysfs instance "
1021 "for FCF, fab %16.16llx mac %pM\n",
1022 new.fabric_name, new.fcf_mac);
1023 kfree(fcf);
1024 goto out;
1025 }
937 } else { 1026 } else {
938 /* 1027 /*
939 * Update the FCF's keep-alive descriptor flags. 1028 * Update the FCF's keep-alive descriptor flags.
@@ -954,6 +1043,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
954 fcf->fka_period = new.fka_period; 1043 fcf->fka_period = new.fka_period;
955 memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN); 1044 memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
956 } 1045 }
1046
957 mtu_valid = fcoe_ctlr_mtu_valid(fcf); 1047 mtu_valid = fcoe_ctlr_mtu_valid(fcf);
958 fcf->time = jiffies; 1048 fcf->time = jiffies;
959 if (!found) 1049 if (!found)
@@ -996,6 +1086,7 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
996 time_before(fip->sel_time, fip->timer.expires)) 1086 time_before(fip->sel_time, fip->timer.expires))
997 mod_timer(&fip->timer, fip->sel_time); 1087 mod_timer(&fip->timer, fip->sel_time);
998 } 1088 }
1089
999out: 1090out:
1000 mutex_unlock(&fip->ctlr_mutex); 1091 mutex_unlock(&fip->ctlr_mutex);
1001} 1092}
@@ -2718,9 +2809,9 @@ unlock:
2718 2809
2719/** 2810/**
2720 * fcoe_libfc_config() - Sets up libfc related properties for local port 2811 * fcoe_libfc_config() - Sets up libfc related properties for local port
2721 * @lp: The local port to configure libfc for 2812 * @lport: The local port to configure libfc for
2722 * @fip: The FCoE controller in use by the local port 2813 * @fip: The FCoE controller in use by the local port
2723 * @tt: The libfc function template 2814 * @tt: The libfc function template
2724 * @init_fcp: If non-zero, the FCP portion of libfc should be initialized 2815 * @init_fcp: If non-zero, the FCP portion of libfc should be initialized
2725 * 2816 *
2726 * Returns : 0 for success 2817 * Returns : 0 for success
@@ -2753,3 +2844,43 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
2753 return 0; 2844 return 0;
2754} 2845}
2755EXPORT_SYMBOL_GPL(fcoe_libfc_config); 2846EXPORT_SYMBOL_GPL(fcoe_libfc_config);
2847
2848void fcoe_fcf_get_selected(struct fcoe_fcf_device *fcf_dev)
2849{
2850 struct fcoe_ctlr_device *ctlr_dev = fcoe_fcf_dev_to_ctlr_dev(fcf_dev);
2851 struct fcoe_ctlr *fip = fcoe_ctlr_device_priv(ctlr_dev);
2852 struct fcoe_fcf *fcf;
2853
2854 mutex_lock(&fip->ctlr_mutex);
2855 mutex_lock(&ctlr_dev->lock);
2856
2857 fcf = fcoe_fcf_device_priv(fcf_dev);
2858 if (fcf)
2859 fcf_dev->selected = (fcf == fip->sel_fcf) ? 1 : 0;
2860 else
2861 fcf_dev->selected = 0;
2862
2863 mutex_unlock(&ctlr_dev->lock);
2864 mutex_unlock(&fip->ctlr_mutex);
2865}
2866EXPORT_SYMBOL(fcoe_fcf_get_selected);
2867
2868void fcoe_ctlr_get_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
2869{
2870 struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
2871
2872 mutex_lock(&ctlr->ctlr_mutex);
2873 switch (ctlr->mode) {
2874 case FIP_MODE_FABRIC:
2875 ctlr_dev->mode = FIP_CONN_TYPE_FABRIC;
2876 break;
2877 case FIP_MODE_VN2VN:
2878 ctlr_dev->mode = FIP_CONN_TYPE_VN2VN;
2879 break;
2880 default:
2881 ctlr_dev->mode = FIP_CONN_TYPE_UNKNOWN;
2882 break;
2883 }
2884 mutex_unlock(&ctlr->ctlr_mutex);
2885}
2886EXPORT_SYMBOL(fcoe_ctlr_get_fip_mode);