aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/libfcoe.c
diff options
context:
space:
mode:
authorJoe Eykholt <jeykholt@cisco.com>2010-11-30 19:19:56 -0500
committerJames Bottomley <James.Bottomley@suse.de>2010-12-21 13:24:32 -0500
commit794d98e77f5901ceded697f1633463e88f078038 (patch)
tree97ac82ba7b14821472f81400f8d1a7230e037cb7 /drivers/scsi/fcoe/libfcoe.c
parentb69ae0ae3f322d9a6bc4e209049b5b6e193ad652 (diff)
[SCSI] libfcoe: retry rejected FLOGI to another FCF if possible
Switches using multiple-FCFs may reject FLOGI in order to balance the load between multiple FCFs. Even though the FCF was available, it may have more load at the point we actually send the FLOGI. If the FLOGI fails, select a different FCF if possible, among those with the same priority. If no other FCF is available, just deliver the reject to libfc for retry. Signed-off-by: Joe Eykholt <jeykholt@cisco.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/fcoe/libfcoe.c')
-rw-r--r--drivers/scsi/fcoe/libfcoe.c207
1 files changed, 177 insertions, 30 deletions
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index 826c260f7951..c90622c28b6c 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -54,6 +54,8 @@ MODULE_LICENSE("GPL v2");
54static void fcoe_ctlr_timeout(unsigned long); 54static void fcoe_ctlr_timeout(unsigned long);
55static void fcoe_ctlr_timer_work(struct work_struct *); 55static void fcoe_ctlr_timer_work(struct work_struct *);
56static void fcoe_ctlr_recv_work(struct work_struct *); 56static void fcoe_ctlr_recv_work(struct work_struct *);
57static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
58static void fcoe_ctlr_select(struct fcoe_ctlr *);
57 59
58static void fcoe_ctlr_vn_start(struct fcoe_ctlr *); 60static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
59static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *); 61static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
@@ -176,6 +178,7 @@ void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
176 fip->mode = mode; 178 fip->mode = mode;
177 INIT_LIST_HEAD(&fip->fcfs); 179 INIT_LIST_HEAD(&fip->fcfs);
178 mutex_init(&fip->ctlr_mutex); 180 mutex_init(&fip->ctlr_mutex);
181 spin_lock_init(&fip->ctlr_lock);
179 fip->flogi_oxid = FC_XID_UNKNOWN; 182 fip->flogi_oxid = FC_XID_UNKNOWN;
180 setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip); 183 setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
181 INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work); 184 INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
@@ -231,17 +234,31 @@ void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
231EXPORT_SYMBOL(fcoe_ctlr_destroy); 234EXPORT_SYMBOL(fcoe_ctlr_destroy);
232 235
233/** 236/**
234 * fcoe_ctlr_announce() - announce new selection 237 * fcoe_ctlr_announce() - announce new FCF selection
235 * @fip: The FCoE controller 238 * @fip: The FCoE controller
236 * 239 *
237 * Also sets the destination MAC for FCoE and control packets 240 * Also sets the destination MAC for FCoE and control packets
241 *
242 * Called with neither ctlr_mutex nor ctlr_lock held.
238 */ 243 */
239static void fcoe_ctlr_announce(struct fcoe_ctlr *fip) 244static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
240{ 245{
241 struct fcoe_fcf *sel = fip->sel_fcf; 246 struct fcoe_fcf *sel;
247 struct fcoe_fcf *fcf;
248
249 mutex_lock(&fip->ctlr_mutex);
250 spin_lock_bh(&fip->ctlr_lock);
251
252 kfree_skb(fip->flogi_req);
253 fip->flogi_req = NULL;
254 list_for_each_entry(fcf, &fip->fcfs, list)
255 fcf->flogi_sent = 0;
256
257 spin_unlock_bh(&fip->ctlr_lock);
258 sel = fip->sel_fcf;
242 259
243 if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr)) 260 if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
244 return; 261 goto unlock;
245 if (!is_zero_ether_addr(fip->dest_addr)) { 262 if (!is_zero_ether_addr(fip->dest_addr)) {
246 printk(KERN_NOTICE "libfcoe: host%d: " 263 printk(KERN_NOTICE "libfcoe: host%d: "
247 "FIP Fibre-Channel Forwarder MAC %pM deselected\n", 264 "FIP Fibre-Channel Forwarder MAC %pM deselected\n",
@@ -255,6 +272,8 @@ static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
255 memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN); 272 memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
256 fip->map_dest = 0; 273 fip->map_dest = 0;
257 } 274 }
275unlock:
276 mutex_unlock(&fip->ctlr_mutex);
258} 277}
259 278
260/** 279/**
@@ -591,6 +610,9 @@ static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
591 * The caller must check that the length is a multiple of 4. 610 * The caller must check that the length is a multiple of 4.
592 * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes). 611 * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
593 * The the skb must also be an fc_frame. 612 * The the skb must also be an fc_frame.
613 *
614 * This is called from the lower-level driver with spinlocks held,
615 * so we must not take a mutex here.
594 */ 616 */
595int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, 617int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
596 struct sk_buff *skb) 618 struct sk_buff *skb)
@@ -628,7 +650,15 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
628 switch (op) { 650 switch (op) {
629 case ELS_FLOGI: 651 case ELS_FLOGI:
630 op = FIP_DT_FLOGI; 652 op = FIP_DT_FLOGI;
631 break; 653 if (fip->mode == FIP_MODE_VN2VN)
654 break;
655 spin_lock_bh(&fip->ctlr_lock);
656 kfree_skb(fip->flogi_req);
657 fip->flogi_req = skb;
658 fip->flogi_req_send = 1;
659 spin_unlock_bh(&fip->ctlr_lock);
660 schedule_work(&fip->timer_work);
661 return -EINPROGRESS;
632 case ELS_FDISC: 662 case ELS_FDISC:
633 if (ntoh24(fh->fh_s_id)) 663 if (ntoh24(fh->fh_s_id))
634 return 0; 664 return 0;
@@ -1088,18 +1118,24 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
1088 els_op = *(u8 *)(fh + 1); 1118 els_op = *(u8 *)(fh + 1);
1089 1119
1090 if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) && 1120 if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
1091 sub == FIP_SC_REP && els_op == ELS_LS_ACC && 1121 sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
1092 fip->mode != FIP_MODE_VN2VN) { 1122 if (els_op == ELS_LS_ACC) {
1093 if (!is_valid_ether_addr(granted_mac)) { 1123 if (!is_valid_ether_addr(granted_mac)) {
1094 LIBFCOE_FIP_DBG(fip, 1124 LIBFCOE_FIP_DBG(fip,
1095 "Invalid MAC address %pM in FIP ELS\n", 1125 "Invalid MAC address %pM in FIP ELS\n",
1096 granted_mac); 1126 granted_mac);
1097 goto drop; 1127 goto drop;
1098 } 1128 }
1099 memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN); 1129 memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
1100 1130
1101 if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) 1131 if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
1102 fip->flogi_oxid = FC_XID_UNKNOWN; 1132 fip->flogi_oxid = FC_XID_UNKNOWN;
1133 if (els_dtype == FIP_DT_FLOGI)
1134 fcoe_ctlr_announce(fip);
1135 }
1136 } else if (els_dtype == FIP_DT_FLOGI &&
1137 !fcoe_ctlr_flogi_retry(fip))
1138 goto drop; /* retrying FLOGI so drop reject */
1103 } 1139 }
1104 1140
1105 if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) && 1141 if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
@@ -1355,12 +1391,15 @@ drop:
1355 * 1391 *
1356 * If there are conflicting advertisements, no FCF can be chosen. 1392 * If there are conflicting advertisements, no FCF can be chosen.
1357 * 1393 *
1394 * If there is already a selected FCF, this will choose a better one or
1395 * an equivalent one that hasn't already been sent a FLOGI.
1396 *
1358 * Called with lock held. 1397 * Called with lock held.
1359 */ 1398 */
1360static void fcoe_ctlr_select(struct fcoe_ctlr *fip) 1399static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
1361{ 1400{
1362 struct fcoe_fcf *fcf; 1401 struct fcoe_fcf *fcf;
1363 struct fcoe_fcf *best = NULL; 1402 struct fcoe_fcf *best = fip->sel_fcf;
1364 struct fcoe_fcf *first; 1403 struct fcoe_fcf *first;
1365 1404
1366 first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list); 1405 first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
@@ -1377,6 +1416,8 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
1377 "or FC-MAP\n"); 1416 "or FC-MAP\n");
1378 return NULL; 1417 return NULL;
1379 } 1418 }
1419 if (fcf->flogi_sent)
1420 continue;
1380 if (!fcoe_ctlr_fcf_usable(fcf)) { 1421 if (!fcoe_ctlr_fcf_usable(fcf)) {
1381 LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx " 1422 LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
1382 "map %x %svalid %savailable\n", 1423 "map %x %svalid %savailable\n",
@@ -1386,11 +1427,7 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
1386 "" : "un"); 1427 "" : "un");
1387 continue; 1428 continue;
1388 } 1429 }
1389 if (!best) { 1430 if (!best || fcf->pri < best->pri || best->flogi_sent)
1390 best = fcf;
1391 continue;
1392 }
1393 if (fcf->pri < best->pri)
1394 best = fcf; 1431 best = fcf;
1395 } 1432 }
1396 fip->sel_fcf = best; 1433 fip->sel_fcf = best;
@@ -1404,6 +1441,121 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
1404} 1441}
1405 1442
1406/** 1443/**
1444 * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
1445 * @fip: The FCoE controller
1446 *
1447 * Returns non-zero error if it could not be sent.
1448 *
1449 * Called with ctlr_mutex and ctlr_lock held.
1450 * Caller must verify that fip->sel_fcf is not NULL.
1451 */
1452static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
1453{
1454 struct sk_buff *skb;
1455 struct sk_buff *skb_orig;
1456 struct fc_frame_header *fh;
1457 int error;
1458
1459 skb_orig = fip->flogi_req;
1460 if (!skb_orig)
1461 return -EINVAL;
1462
1463 /*
1464 * Clone and send the FLOGI request. If clone fails, use original.
1465 */
1466 skb = skb_clone(skb_orig, GFP_ATOMIC);
1467 if (!skb) {
1468 skb = skb_orig;
1469 fip->flogi_req = NULL;
1470 }
1471 fh = (struct fc_frame_header *)skb->data;
1472 error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
1473 ntoh24(fh->fh_d_id));
1474 if (error) {
1475 kfree_skb(skb);
1476 return error;
1477 }
1478 fip->send(fip, skb);
1479 fip->sel_fcf->flogi_sent = 1;
1480 return 0;
1481}
1482
1483/**
1484 * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
1485 * @fip: The FCoE controller
1486 *
1487 * Returns non-zero error code if there's no FLOGI request to retry or
1488 * no alternate FCF available.
1489 */
1490static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
1491{
1492 struct fcoe_fcf *fcf;
1493 int error;
1494
1495 mutex_lock(&fip->ctlr_mutex);
1496 spin_lock_bh(&fip->ctlr_lock);
1497 LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
1498 fcoe_ctlr_select(fip);
1499 fcf = fip->sel_fcf;
1500 if (!fcf || fcf->flogi_sent) {
1501 kfree_skb(fip->flogi_req);
1502 fip->flogi_req = NULL;
1503 error = -ENOENT;
1504 } else {
1505 fcoe_ctlr_solicit(fip, NULL);
1506 error = fcoe_ctlr_flogi_send_locked(fip);
1507 }
1508 spin_unlock_bh(&fip->ctlr_lock);
1509 mutex_unlock(&fip->ctlr_mutex);
1510 return error;
1511}
1512
1513
1514/**
1515 * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
1516 * @fip: The FCoE controller that timed out
1517 *
1518 * Done here because fcoe_ctlr_els_send() can't get mutex.
1519 *
1520 * Called with ctlr_mutex held. The caller must not hold ctlr_lock.
1521 */
1522static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
1523{
1524 struct fcoe_fcf *fcf;
1525
1526 spin_lock_bh(&fip->ctlr_lock);
1527 fcf = fip->sel_fcf;
1528 if (!fcf || !fip->flogi_req_send)
1529 goto unlock;
1530
1531 LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
1532
1533 /*
1534 * If this FLOGI is being sent due to a timeout retry
1535 * to the same FCF as before, select a different FCF if possible.
1536 */
1537 if (fcf->flogi_sent) {
1538 LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
1539 fcoe_ctlr_select(fip);
1540 fcf = fip->sel_fcf;
1541 if (!fcf || fcf->flogi_sent) {
1542 LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
1543 list_for_each_entry(fcf, &fip->fcfs, list)
1544 fcf->flogi_sent = 0;
1545 fcoe_ctlr_select(fip);
1546 fcf = fip->sel_fcf;
1547 }
1548 }
1549 if (fcf) {
1550 fcoe_ctlr_flogi_send_locked(fip);
1551 fip->flogi_req_send = 0;
1552 } else /* XXX */
1553 LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
1554unlock:
1555 spin_unlock_bh(&fip->ctlr_lock);
1556}
1557
1558/**
1407 * fcoe_ctlr_timeout() - FIP timeout handler 1559 * fcoe_ctlr_timeout() - FIP timeout handler
1408 * @arg: The FCoE controller that timed out 1560 * @arg: The FCoE controller that timed out
1409 */ 1561 */
@@ -1455,15 +1607,10 @@ static void fcoe_ctlr_timer_work(struct work_struct *work)
1455 next_timer = fip->sel_time; 1607 next_timer = fip->sel_time;
1456 } 1608 }
1457 1609
1458 if (sel != fcf) { 1610 if (sel && fip->flogi_req_send)
1459 fcf = sel; /* the old FCF may have been freed */ 1611 fcoe_ctlr_flogi_send(fip);
1460 fcoe_ctlr_announce(fip); 1612 else if (!sel && fcf)
1461 if (sel) { 1613 reset = 1;
1462 if (time_after(next_timer, fip->ctlr_ka_time))
1463 next_timer = fip->ctlr_ka_time;
1464 } else
1465 reset = 1;
1466 }
1467 1614
1468 if (sel && !sel->fd_flags) { 1615 if (sel && !sel->fd_flags) {
1469 if (time_after_eq(jiffies, fip->ctlr_ka_time)) { 1616 if (time_after_eq(jiffies, fip->ctlr_ka_time)) {