aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/fcoe/fcoe.c
diff options
context:
space:
mode:
authorChris Leech <christopher.leech@intel.com>2009-11-03 14:46:29 -0500
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 13:00:58 -0500
commit11b561886643d4e23d0fd58c205d830a448dd0a2 (patch)
tree3d28650e6727589dd672ea3985d2aa2643a99549 /drivers/scsi/fcoe/fcoe.c
parentdb36c06cc6802d03bcba08982377f7c03a3cda7f (diff)
[SCSI] libfcoe, fcoe: libfcoe NPIV support
The FIP code in libfcoe needed several changes to support NPIV 1) dst_src_addr needs to be managed per-n_port-ID for FPMA fabrics with NPIV enabled. Managing the MAC address is now handled in fcoe, with some slight changes to update_mac() and a new get_src_addr() function pointer. 2) The libfc elsct_send() hook is used to setup FCoE specific response handlers for FIP encapsulated ELS exchanges. This lets the FCoE specific handling know which VN_Port the exchange is for, and doesn't require tracking OX_IDs. It might be possible to roll back to the full FIP frame in these, but for now I've just stashed the contents of the MAC address descriptor in the skb context block for later use. Also, because fcoe_elsct_send() just passes control on to fc_elsct_send(), all transmits still come through the normal frame_send() path. 3) The NPIV changes added a mutex hold in the keep alive sending, the lport mutex is protecting the vport list. We can't take a mutex from a timer, so move the FIP keep alive logic to the link work struct. Signed-off-by: Chris Leech <christopher.leech@intel.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/fcoe.c')
-rw-r--r--drivers/scsi/fcoe/fcoe.c147
1 files changed, 128 insertions, 19 deletions
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
index 8ca488de492d..a64c398c981e 100644
--- a/drivers/scsi/fcoe/fcoe.c
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -226,7 +226,8 @@ static int fcoe_interface_setup(struct fcoe_interface *fcoe,
226} 226}
227 227
228static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb); 228static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb);
229static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new); 229static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr);
230static u8 *fcoe_get_src_mac(struct fc_lport *lport);
230static void fcoe_destroy_work(struct work_struct *work); 231static void fcoe_destroy_work(struct work_struct *work);
231 232
232/** 233/**
@@ -254,6 +255,7 @@ static struct fcoe_interface *fcoe_interface_create(struct net_device *netdev)
254 fcoe_ctlr_init(&fcoe->ctlr); 255 fcoe_ctlr_init(&fcoe->ctlr);
255 fcoe->ctlr.send = fcoe_fip_send; 256 fcoe->ctlr.send = fcoe_fip_send;
256 fcoe->ctlr.update_mac = fcoe_update_src_mac; 257 fcoe->ctlr.update_mac = fcoe_update_src_mac;
258 fcoe->ctlr.get_src_addr = fcoe_get_src_mac;
257 259
258 fcoe_interface_setup(fcoe, netdev); 260 fcoe_interface_setup(fcoe, netdev);
259 261
@@ -286,8 +288,6 @@ void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
286 /* Delete secondary MAC addresses */ 288 /* Delete secondary MAC addresses */
287 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN); 289 memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
288 dev_unicast_delete(netdev, flogi_maddr); 290 dev_unicast_delete(netdev, flogi_maddr);
289 if (!is_zero_ether_addr(fip->data_src_addr))
290 dev_unicast_delete(netdev, fip->data_src_addr);
291 if (fip->spma) 291 if (fip->spma)
292 dev_unicast_delete(netdev, fip->ctl_src_addr); 292 dev_unicast_delete(netdev, fip->ctl_src_addr);
293 dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0); 293 dev_mc_delete(netdev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
@@ -369,26 +369,38 @@ static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
369 369
370/** 370/**
371 * fcoe_update_src_mac() - Update Ethernet MAC filters. 371 * fcoe_update_src_mac() - Update Ethernet MAC filters.
372 * @fip: FCoE controller. 372 * @lport: libfc lport
373 * @old: Unicast MAC address to delete if the MAC is non-zero. 373 * @addr: Unicast MAC address to add.
374 * @new: Unicast MAC address to add.
375 * 374 *
376 * Remove any previously-set unicast MAC filter. 375 * Remove any previously-set unicast MAC filter.
377 * Add secondary FCoE MAC address filter for our OUI. 376 * Add secondary FCoE MAC address filter for our OUI.
378 */ 377 */
379static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new) 378static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr)
380{ 379{
381 struct fcoe_interface *fcoe; 380 struct fcoe_port *port = lport_priv(lport);
381 struct fcoe_interface *fcoe = port->fcoe;
382 382
383 fcoe = fcoe_from_ctlr(fip);
384 rtnl_lock(); 383 rtnl_lock();
385 if (!is_zero_ether_addr(old)) 384 if (!is_zero_ether_addr(port->data_src_addr))
386 dev_unicast_delete(fcoe->netdev, old); 385 dev_unicast_delete(fcoe->netdev, port->data_src_addr);
387 dev_unicast_add(fcoe->netdev, new); 386 if (!is_zero_ether_addr(addr))
387 dev_unicast_add(fcoe->netdev, addr);
388 memcpy(port->data_src_addr, addr, ETH_ALEN);
388 rtnl_unlock(); 389 rtnl_unlock();
389} 390}
390 391
391/** 392/**
393 * fcoe_get_src_mac() - return the Ethernet source address for an lport
394 * @lport: libfc lport
395 */
396static u8 *fcoe_get_src_mac(struct fc_lport *lport)
397{
398 struct fcoe_port *port = lport_priv(lport);
399
400 return port->data_src_addr;
401}
402
403/**
392 * fcoe_lport_config() - sets up the fc_lport 404 * fcoe_lport_config() - sets up the fc_lport
393 * @lp: ptr to the fc_lport 405 * @lp: ptr to the fc_lport
394 * 406 *
@@ -650,6 +662,11 @@ static void fcoe_if_destroy(struct fc_lport *lport)
650 /* Free existing transmit skbs */ 662 /* Free existing transmit skbs */
651 fcoe_clean_pending_queue(lport); 663 fcoe_clean_pending_queue(lport);
652 664
665 rtnl_lock();
666 if (!is_zero_ether_addr(port->data_src_addr))
667 dev_unicast_delete(netdev, port->data_src_addr);
668 rtnl_unlock();
669
653 /* receives may not be stopped until after this */ 670 /* receives may not be stopped until after this */
654 fcoe_interface_put(fcoe); 671 fcoe_interface_put(fcoe);
655 672
@@ -706,10 +723,16 @@ static int fcoe_ddp_done(struct fc_lport *lp, u16 xid)
706 return 0; 723 return 0;
707} 724}
708 725
726static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport,
727 u32 did, struct fc_frame *fp, unsigned int op,
728 void (*resp)(struct fc_seq *, struct fc_frame *, void *),
729 void *arg, u32 timeout);
730
709static struct libfc_function_template fcoe_libfc_fcn_templ = { 731static struct libfc_function_template fcoe_libfc_fcn_templ = {
710 .frame_send = fcoe_xmit, 732 .frame_send = fcoe_xmit,
711 .ddp_setup = fcoe_ddp_setup, 733 .ddp_setup = fcoe_ddp_setup,
712 .ddp_done = fcoe_ddp_done, 734 .ddp_done = fcoe_ddp_done,
735 .elsct_send = fcoe_elsct_send,
713}; 736};
714 737
715/** 738/**
@@ -1226,7 +1249,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
1226 } 1249 }
1227 1250
1228 if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) && 1251 if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
1229 fcoe_ctlr_els_send(&fcoe->ctlr, skb)) 1252 fcoe_ctlr_els_send(&fcoe->ctlr, lp, skb))
1230 return 0; 1253 return 0;
1231 1254
1232 sof = fr_sof(fp); 1255 sof = fr_sof(fp);
@@ -1291,7 +1314,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
1291 if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN)) 1314 if (unlikely(fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN))
1292 memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN); 1315 memcpy(eh->h_source, fcoe->ctlr.ctl_src_addr, ETH_ALEN);
1293 else 1316 else
1294 memcpy(eh->h_source, fcoe->ctlr.data_src_addr, ETH_ALEN); 1317 memcpy(eh->h_source, port->data_src_addr, ETH_ALEN);
1295 1318
1296 hp = (struct fcoe_hdr *)(eh + 1); 1319 hp = (struct fcoe_hdr *)(eh + 1);
1297 memset(hp, 0, sizeof(*hp)); 1320 memset(hp, 0, sizeof(*hp));
@@ -1464,11 +1487,6 @@ int fcoe_percpu_receive_thread(void *arg)
1464 } 1487 }
1465 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; 1488 fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
1466 } 1489 }
1467 if (unlikely(port->fcoe->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
1468 fcoe_ctlr_recv_flogi(&port->fcoe->ctlr, fp, mac)) {
1469 fc_frame_free(fp);
1470 continue;
1471 }
1472 fc_exch_recv(lp, fp); 1490 fc_exch_recv(lp, fp);
1473 } 1491 }
1474 return 0; 1492 return 0;
@@ -2061,3 +2079,94 @@ static void __exit fcoe_exit(void)
2061 fcoe_if_exit(); 2079 fcoe_if_exit();
2062} 2080}
2063module_exit(fcoe_exit); 2081module_exit(fcoe_exit);
2082
2083/**
2084 * fcoe_flogi_resp() - FCoE specific FLOGI and FDISC response handler
2085 * @seq: active sequence in the FLOGI or FDISC exchange
2086 * @fp: response frame, or error encoded in a pointer (timeout)
2087 * @arg: pointer the the fcoe_ctlr structure
2088 *
2089 * This handles MAC address managment for FCoE, then passes control on to
2090 * the libfc FLOGI response handler.
2091 */
2092static void fcoe_flogi_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
2093{
2094 struct fcoe_ctlr *fip = arg;
2095 struct fc_exch *exch = fc_seq_exch(seq);
2096 struct fc_lport *lport = exch->lp;
2097 u8 *mac;
2098
2099 if (IS_ERR(fp))
2100 goto done;
2101
2102 mac = fr_cb(fp)->granted_mac;
2103 if (is_zero_ether_addr(mac)) {
2104 /* pre-FIP */
2105 mac = eth_hdr(&fp->skb)->h_source;
2106 if (fcoe_ctlr_recv_flogi(fip, lport, fp, mac)) {
2107 fc_frame_free(fp);
2108 return;
2109 }
2110 } else {
2111 /* FIP, libfcoe has already seen it */
2112 fip->update_mac(lport, fr_cb(fp)->granted_mac);
2113 }
2114done:
2115 fc_lport_flogi_resp(seq, fp, lport);
2116}
2117
2118/**
2119 * fcoe_logo_resp() - FCoE specific LOGO response handler
2120 * @seq: active sequence in the LOGO exchange
2121 * @fp: response frame, or error encoded in a pointer (timeout)
2122 * @arg: pointer the the fcoe_ctlr structure
2123 *
2124 * This handles MAC address managment for FCoE, then passes control on to
2125 * the libfc LOGO response handler.
2126 */
2127static void fcoe_logo_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
2128{
2129 struct fcoe_ctlr *fip = arg;
2130 struct fc_exch *exch = fc_seq_exch(seq);
2131 struct fc_lport *lport = exch->lp;
2132 static u8 zero_mac[ETH_ALEN] = { 0 };
2133
2134 if (!IS_ERR(fp))
2135 fip->update_mac(lport, zero_mac);
2136 fc_lport_logo_resp(seq, fp, lport);
2137}
2138
2139/**
2140 * fcoe_elsct_send - FCoE specific ELS handler
2141 *
2142 * This does special case handling of FIP encapsualted ELS exchanges for FCoE,
2143 * using FCoE specific response handlers and passing the FIP controller as
2144 * the argument (the lport is still available from the exchange).
2145 *
2146 * Most of the work here is just handed off to the libfc routine.
2147 */
2148static struct fc_seq *fcoe_elsct_send(struct fc_lport *lport,
2149 u32 did, struct fc_frame *fp, unsigned int op,
2150 void (*resp)(struct fc_seq *, struct fc_frame *, void *),
2151 void *arg, u32 timeout)
2152{
2153 struct fcoe_port *port = lport_priv(lport);
2154 struct fcoe_interface *fcoe = port->fcoe;
2155 struct fcoe_ctlr *fip = &fcoe->ctlr;
2156 struct fc_frame_header *fh = fc_frame_header_get(fp);
2157
2158 switch (op) {
2159 case ELS_FLOGI:
2160 case ELS_FDISC:
2161 return fc_elsct_send(lport, did, fp, op, fcoe_flogi_resp,
2162 fip, timeout);
2163 case ELS_LOGO:
2164 /* only hook onto fabric logouts, not port logouts */
2165 if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
2166 break;
2167 return fc_elsct_send(lport, did, fp, op, fcoe_logo_resp,
2168 fip, timeout);
2169 }
2170 return fc_elsct_send(lport, did, fp, op, resp, arg, timeout);
2171}
2172