Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] fnic: FIP VLAN Discovery Feature Support

FIP VLAN discovery discovers the FCoE VLAN that will be used by all other FIP
protocols as well as by the FCoE encapsulation for Fibre Channel payloads on
the established virtual link. One of the goals of FC-BB-5 was to be as
nonintrusive as possible on initiators and targets, and therefore FIP VLAN
discovery occurs in the native VLAN used by the initiator or target to
exchange Ethernet traffic. The FIP VLAN discovery protocol is the only FIP
protocol running on the native VLAN; all other FIP protocols run on the
discovered FCoE VLANs.

If an administrator has manually configured FCoE VLANs on ENodes and FCFs,
there is no need to use this protocol. FIP and FCoE will run over the
configured VLANs.

An ENode without FCoE VLANs configuration would use this automated discovery
protocol to discover over which VLANs FCoE is running.

The ENode sends a FIP VLAN discovery request to a multicast MAC address called
All-FCF-MACs, which is a multicast MAC address to which all FCFs listen.

All FCFs that can be reached in the native VLAN of the ENode are expected to
respond on the same VLAN with a response that lists one or more FCoE VLANs
that are available for the ENode's VN_Port login. This protocol has the sole
purpose of allowing the ENode to discover all the available FCoE VLANs.

Now the ENode may enable a subset of these VLANs for FCoE Running the FIP
protocol in these VLANs on a per VLAN basis. And FCoE data transactions also
would occur on this VLAN. Hence, Except for FIP VLAN discovery, all other FIP
and FCoE traffic runs on the selected FCoE VLAN. Its only the FIP VLAN
Discovery protocol that is permitted to run on the Default native VLAN of the
system.

[**** NOTE ****]
We are working on moving this feature definitions and functionality to libfcoe
module. We need this patch to be approved, as Suse is looking forward to merge
this feature in SLES 11 SP3 release. Once this patch is approved, we will
submit patch which should move vlan discovery feature to libfoce.

[Fengguang Wu <fengguang.wu@intel.com>: kmalloc cast removal]
Signed-off-by: Anantha Prakash T <atungara@cisco.com>
Signed-off-by: Hiral Patel <hiralpat@cisco.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

authored by

Hiral Patel and committed by
James Bottomley
d3c995f1 73287a43

+784 -4
+32
drivers/scsi/fnic/fnic.h
··· 192 192 193 193 struct mempool; 194 194 195 + enum fnic_evt { 196 + FNIC_EVT_START_VLAN_DISC = 1, 197 + FNIC_EVT_START_FCF_DISC = 2, 198 + FNIC_EVT_MAX, 199 + }; 200 + 201 + struct fnic_event { 202 + struct list_head list; 203 + struct fnic *fnic; 204 + enum fnic_evt event; 205 + }; 206 + 195 207 /* Per-instance private data structure */ 196 208 struct fnic { 197 209 struct fc_lport *lport; ··· 266 254 struct sk_buff_head frame_queue; 267 255 struct sk_buff_head tx_queue; 268 256 257 + /*** FIP related data members -- start ***/ 258 + void (*set_vlan)(struct fnic *, u16 vlan); 259 + struct work_struct fip_frame_work; 260 + struct sk_buff_head fip_frame_queue; 261 + struct timer_list fip_timer; 262 + struct list_head vlans; 263 + spinlock_t vlans_lock; 264 + 265 + struct work_struct event_work; 266 + struct list_head evlist; 267 + /*** FIP related data members -- end ***/ 268 + 269 269 /* copy work queue cache line section */ 270 270 ____cacheline_aligned struct vnic_wq_copy wq_copy[FNIC_WQ_COPY_MAX]; 271 271 /* completion queue cache line section */ ··· 302 278 } 303 279 304 280 extern struct workqueue_struct *fnic_event_queue; 281 + extern struct workqueue_struct *fnic_fip_queue; 305 282 extern struct device_attribute *fnic_attrs[]; 306 283 307 284 void fnic_clear_intr_mode(struct fnic *fnic); ··· 314 289 void fnic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf); 315 290 void fnic_handle_frame(struct work_struct *work); 316 291 void fnic_handle_link(struct work_struct *work); 292 + void fnic_handle_event(struct work_struct *work); 317 293 int fnic_rq_cmpl_handler(struct fnic *fnic, int); 318 294 int fnic_alloc_rq_frame(struct vnic_rq *rq); 319 295 void fnic_free_rq_buf(struct vnic_rq *rq, struct vnic_rq_buf *buf); ··· 346 320 void fnic_handle_link_event(struct fnic *fnic); 347 321 348 322 int fnic_is_abts_pending(struct fnic *, struct scsi_cmnd *); 323 + 324 + void fnic_handle_fip_frame(struct work_struct *work); 325 + void fnic_handle_fip_event(struct fnic *fnic); 326 + void fnic_fcoe_reset_vlans(struct fnic *fnic); 327 + void fnic_fcoe_evlist_free(struct fnic *fnic); 328 + extern void fnic_handle_fip_timer(struct fnic *fnic); 349 329 350 330 static inline int 351 331 fnic_chk_state_flags_locked(struct fnic *fnic, unsigned long st_flags)
+556 -2
drivers/scsi/fnic/fnic_fcs.c
··· 31 31 #include <scsi/libfc.h> 32 32 #include "fnic_io.h" 33 33 #include "fnic.h" 34 + #include "fnic_fip.h" 34 35 #include "cq_enet_desc.h" 35 36 #include "cq_exch_desc.h" 36 37 38 + static u8 fcoe_all_fcfs[ETH_ALEN]; 39 + struct workqueue_struct *fnic_fip_queue; 37 40 struct workqueue_struct *fnic_event_queue; 38 41 39 42 static void fnic_set_eth_mode(struct fnic *); 43 + static void fnic_fcoe_send_vlan_req(struct fnic *fnic); 44 + static void fnic_fcoe_start_fcf_disc(struct fnic *fnic); 45 + static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *); 46 + static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag); 47 + static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb); 40 48 41 49 void fnic_handle_link(struct work_struct *work) 42 50 { ··· 77 69 FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, 78 70 "link down\n"); 79 71 fcoe_ctlr_link_down(&fnic->ctlr); 72 + if (fnic->config.flags & VFCF_FIP_CAPABLE) { 73 + /* start FCoE VLAN discovery */ 74 + fnic_fcoe_send_vlan_req(fnic); 75 + return; 76 + } 80 77 FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, 81 78 "link up\n"); 82 79 fcoe_ctlr_link_up(&fnic->ctlr); ··· 92 79 } else if (fnic->link_status) { 93 80 /* DOWN -> UP */ 94 81 spin_unlock_irqrestore(&fnic->fnic_lock, flags); 82 + if (fnic->config.flags & VFCF_FIP_CAPABLE) { 83 + /* start FCoE VLAN discovery */ 84 + fnic_fcoe_send_vlan_req(fnic); 85 + return; 86 + } 95 87 FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, "link up\n"); 96 88 fcoe_ctlr_link_up(&fnic->ctlr); 97 89 } else { ··· 146 128 } 147 129 } 148 130 131 + void fnic_fcoe_evlist_free(struct fnic *fnic) 132 + { 133 + struct fnic_event *fevt = NULL; 134 + struct fnic_event *next = NULL; 135 + unsigned long flags; 136 + 137 + spin_lock_irqsave(&fnic->fnic_lock, flags); 138 + if (list_empty(&fnic->evlist)) { 139 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 140 + return; 141 + } 142 + 143 + list_for_each_entry_safe(fevt, next, &fnic->evlist, list) { 144 + list_del(&fevt->list); 145 + kfree(fevt); 146 + } 147 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 148 + } 149 + 150 + void fnic_handle_event(struct work_struct *work) 151 + { 152 + struct fnic *fnic = container_of(work, struct fnic, event_work); 153 + struct fnic_event *fevt = NULL; 154 + struct fnic_event *next = NULL; 155 + unsigned long flags; 156 + 157 + spin_lock_irqsave(&fnic->fnic_lock, flags); 158 + if (list_empty(&fnic->evlist)) { 159 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 160 + return; 161 + } 162 + 163 + list_for_each_entry_safe(fevt, next, &fnic->evlist, list) { 164 + if (fnic->stop_rx_link_events) { 165 + list_del(&fevt->list); 166 + kfree(fevt); 167 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 168 + return; 169 + } 170 + /* 171 + * If we're in a transitional state, just re-queue and return. 172 + * The queue will be serviced when we get to a stable state. 173 + */ 174 + if (fnic->state != FNIC_IN_FC_MODE && 175 + fnic->state != FNIC_IN_ETH_MODE) { 176 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 177 + return; 178 + } 179 + 180 + list_del(&fevt->list); 181 + switch (fevt->event) { 182 + case FNIC_EVT_START_VLAN_DISC: 183 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 184 + fnic_fcoe_send_vlan_req(fnic); 185 + spin_lock_irqsave(&fnic->fnic_lock, flags); 186 + break; 187 + case FNIC_EVT_START_FCF_DISC: 188 + FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, 189 + "Start FCF Discovery\n"); 190 + fnic_fcoe_start_fcf_disc(fnic); 191 + break; 192 + default: 193 + FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, 194 + "Unknown event 0x%x\n", fevt->event); 195 + break; 196 + } 197 + kfree(fevt); 198 + } 199 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 200 + } 201 + 202 + /** 203 + * Check if the Received FIP FLOGI frame is rejected 204 + * @fip: The FCoE controller that received the frame 205 + * @skb: The received FIP frame 206 + * 207 + * Returns non-zero if the frame is rejected with unsupported cmd with 208 + * insufficient resource els explanation. 209 + */ 210 + static inline int is_fnic_fip_flogi_reject(struct fcoe_ctlr *fip, 211 + struct sk_buff *skb) 212 + { 213 + struct fc_lport *lport = fip->lp; 214 + struct fip_header *fiph; 215 + struct fc_frame_header *fh = NULL; 216 + struct fip_desc *desc; 217 + struct fip_encaps *els; 218 + enum fip_desc_type els_dtype = 0; 219 + u16 op; 220 + u8 els_op; 221 + u8 sub; 222 + 223 + size_t els_len = 0; 224 + size_t rlen; 225 + size_t dlen = 0; 226 + 227 + if (skb_linearize(skb)) 228 + return 0; 229 + 230 + if (skb->len < sizeof(*fiph)) 231 + return 0; 232 + 233 + fiph = (struct fip_header *)skb->data; 234 + op = ntohs(fiph->fip_op); 235 + sub = fiph->fip_subcode; 236 + 237 + if (op != FIP_OP_LS) 238 + return 0; 239 + 240 + if (sub != FIP_SC_REP) 241 + return 0; 242 + 243 + rlen = ntohs(fiph->fip_dl_len) * 4; 244 + if (rlen + sizeof(*fiph) > skb->len) 245 + return 0; 246 + 247 + desc = (struct fip_desc *)(fiph + 1); 248 + dlen = desc->fip_dlen * FIP_BPW; 249 + 250 + if (desc->fip_dtype == FIP_DT_FLOGI) { 251 + 252 + shost_printk(KERN_DEBUG, lport->host, 253 + " FIP TYPE FLOGI: fab name:%llx " 254 + "vfid:%d map:%x\n", 255 + fip->sel_fcf->fabric_name, fip->sel_fcf->vfid, 256 + fip->sel_fcf->fc_map); 257 + if (dlen < sizeof(*els) + sizeof(*fh) + 1) 258 + return 0; 259 + 260 + els_len = dlen - sizeof(*els); 261 + els = (struct fip_encaps *)desc; 262 + fh = (struct fc_frame_header *)(els + 1); 263 + els_dtype = desc->fip_dtype; 264 + 265 + if (!fh) 266 + return 0; 267 + 268 + /* 269 + * ELS command code, reason and explanation should be = Reject, 270 + * unsupported command and insufficient resource 271 + */ 272 + els_op = *(u8 *)(fh + 1); 273 + if (els_op == ELS_LS_RJT) { 274 + shost_printk(KERN_INFO, lport->host, 275 + "Flogi Request Rejected by Switch\n"); 276 + return 1; 277 + } 278 + shost_printk(KERN_INFO, lport->host, 279 + "Flogi Request Accepted by Switch\n"); 280 + } 281 + return 0; 282 + } 283 + 284 + static void fnic_fcoe_send_vlan_req(struct fnic *fnic) 285 + { 286 + struct fcoe_ctlr *fip = &fnic->ctlr; 287 + struct sk_buff *skb; 288 + char *eth_fr; 289 + int fr_len; 290 + struct fip_vlan *vlan; 291 + u64 vlan_tov; 292 + 293 + fnic_fcoe_reset_vlans(fnic); 294 + fnic->set_vlan(fnic, 0); 295 + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, 296 + "Sending VLAN request...\n"); 297 + skb = dev_alloc_skb(sizeof(struct fip_vlan)); 298 + if (!skb) 299 + return; 300 + 301 + fr_len = sizeof(*vlan); 302 + eth_fr = (char *)skb->data; 303 + vlan = (struct fip_vlan *)eth_fr; 304 + 305 + memset(vlan, 0, sizeof(*vlan)); 306 + memcpy(vlan->eth.h_source, fip->ctl_src_addr, ETH_ALEN); 307 + memcpy(vlan->eth.h_dest, fcoe_all_fcfs, ETH_ALEN); 308 + vlan->eth.h_proto = htons(ETH_P_FIP); 309 + 310 + vlan->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER); 311 + vlan->fip.fip_op = htons(FIP_OP_VLAN); 312 + vlan->fip.fip_subcode = FIP_SC_VL_REQ; 313 + vlan->fip.fip_dl_len = htons(sizeof(vlan->desc) / FIP_BPW); 314 + 315 + vlan->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC; 316 + vlan->desc.mac.fd_desc.fip_dlen = sizeof(vlan->desc.mac) / FIP_BPW; 317 + memcpy(&vlan->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN); 318 + 319 + vlan->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME; 320 + vlan->desc.wwnn.fd_desc.fip_dlen = sizeof(vlan->desc.wwnn) / FIP_BPW; 321 + put_unaligned_be64(fip->lp->wwnn, &vlan->desc.wwnn.fd_wwn); 322 + 323 + skb_put(skb, sizeof(*vlan)); 324 + skb->protocol = htons(ETH_P_FIP); 325 + skb_reset_mac_header(skb); 326 + skb_reset_network_header(skb); 327 + fip->send(fip, skb); 328 + 329 + /* set a timer so that we can retry if there no response */ 330 + vlan_tov = jiffies + msecs_to_jiffies(FCOE_CTLR_FIPVLAN_TOV); 331 + mod_timer(&fnic->fip_timer, round_jiffies(vlan_tov)); 332 + } 333 + 334 + static void fnic_fcoe_process_vlan_resp(struct fnic *fnic, struct sk_buff *skb) 335 + { 336 + struct fcoe_ctlr *fip = &fnic->ctlr; 337 + struct fip_header *fiph; 338 + struct fip_desc *desc; 339 + u16 vid; 340 + size_t rlen; 341 + size_t dlen; 342 + struct fcoe_vlan *vlan; 343 + u64 sol_time; 344 + unsigned long flags; 345 + 346 + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, 347 + "Received VLAN response...\n"); 348 + 349 + fiph = (struct fip_header *) skb->data; 350 + 351 + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, 352 + "Received VLAN response... OP 0x%x SUB_OP 0x%x\n", 353 + ntohs(fiph->fip_op), fiph->fip_subcode); 354 + 355 + rlen = ntohs(fiph->fip_dl_len) * 4; 356 + fnic_fcoe_reset_vlans(fnic); 357 + spin_lock_irqsave(&fnic->vlans_lock, flags); 358 + desc = (struct fip_desc *)(fiph + 1); 359 + while (rlen > 0) { 360 + dlen = desc->fip_dlen * FIP_BPW; 361 + switch (desc->fip_dtype) { 362 + case FIP_DT_VLAN: 363 + vid = ntohs(((struct fip_vlan_desc *)desc)->fd_vlan); 364 + shost_printk(KERN_INFO, fnic->lport->host, 365 + "process_vlan_resp: FIP VLAN %d\n", vid); 366 + vlan = kmalloc(sizeof(*vlan), 367 + GFP_ATOMIC); 368 + if (!vlan) { 369 + /* retry from timer */ 370 + spin_unlock_irqrestore(&fnic->vlans_lock, 371 + flags); 372 + goto out; 373 + } 374 + memset(vlan, 0, sizeof(struct fcoe_vlan)); 375 + vlan->vid = vid & 0x0fff; 376 + vlan->state = FIP_VLAN_AVAIL; 377 + list_add_tail(&vlan->list, &fnic->vlans); 378 + break; 379 + } 380 + desc = (struct fip_desc *)((char *)desc + dlen); 381 + rlen -= dlen; 382 + } 383 + 384 + /* any VLAN descriptors present ? */ 385 + if (list_empty(&fnic->vlans)) { 386 + /* retry from timer */ 387 + FNIC_FCS_DBG(KERN_INFO, fnic->lport->host, 388 + "No VLAN descriptors in FIP VLAN response\n"); 389 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 390 + goto out; 391 + } 392 + 393 + vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); 394 + fnic->set_vlan(fnic, vlan->vid); 395 + vlan->state = FIP_VLAN_SENT; /* sent now */ 396 + vlan->sol_count++; 397 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 398 + 399 + /* start the solicitation */ 400 + fcoe_ctlr_link_up(fip); 401 + 402 + sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY); 403 + mod_timer(&fnic->fip_timer, round_jiffies(sol_time)); 404 + out: 405 + return; 406 + } 407 + 408 + static void fnic_fcoe_start_fcf_disc(struct fnic *fnic) 409 + { 410 + unsigned long flags; 411 + struct fcoe_vlan *vlan; 412 + u64 sol_time; 413 + 414 + spin_lock_irqsave(&fnic->vlans_lock, flags); 415 + vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); 416 + fnic->set_vlan(fnic, vlan->vid); 417 + vlan->state = FIP_VLAN_SENT; /* sent now */ 418 + vlan->sol_count = 1; 419 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 420 + 421 + /* start the solicitation */ 422 + fcoe_ctlr_link_up(&fnic->ctlr); 423 + 424 + sol_time = jiffies + msecs_to_jiffies(FCOE_CTLR_START_DELAY); 425 + mod_timer(&fnic->fip_timer, round_jiffies(sol_time)); 426 + } 427 + 428 + static int fnic_fcoe_vlan_check(struct fnic *fnic, u16 flag) 429 + { 430 + unsigned long flags; 431 + struct fcoe_vlan *fvlan; 432 + 433 + spin_lock_irqsave(&fnic->vlans_lock, flags); 434 + if (list_empty(&fnic->vlans)) { 435 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 436 + return -EINVAL; 437 + } 438 + 439 + fvlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); 440 + if (fvlan->state == FIP_VLAN_USED) { 441 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 442 + return 0; 443 + } 444 + 445 + if (fvlan->state == FIP_VLAN_SENT) { 446 + fvlan->state = FIP_VLAN_USED; 447 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 448 + return 0; 449 + } 450 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 451 + return -EINVAL; 452 + } 453 + 454 + static void fnic_event_enq(struct fnic *fnic, enum fnic_evt ev) 455 + { 456 + struct fnic_event *fevt; 457 + unsigned long flags; 458 + 459 + fevt = kmalloc(sizeof(*fevt), GFP_ATOMIC); 460 + if (!fevt) 461 + return; 462 + 463 + fevt->fnic = fnic; 464 + fevt->event = ev; 465 + 466 + spin_lock_irqsave(&fnic->fnic_lock, flags); 467 + list_add_tail(&fevt->list, &fnic->evlist); 468 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 469 + 470 + schedule_work(&fnic->event_work); 471 + } 472 + 473 + static int fnic_fcoe_handle_fip_frame(struct fnic *fnic, struct sk_buff *skb) 474 + { 475 + struct fip_header *fiph; 476 + int ret = 1; 477 + u16 op; 478 + u8 sub; 479 + 480 + if (!skb || !(skb->data)) 481 + return -1; 482 + 483 + if (skb_linearize(skb)) 484 + goto drop; 485 + 486 + fiph = (struct fip_header *)skb->data; 487 + op = ntohs(fiph->fip_op); 488 + sub = fiph->fip_subcode; 489 + 490 + if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER) 491 + goto drop; 492 + 493 + if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len) 494 + goto drop; 495 + 496 + if (op == FIP_OP_DISC && sub == FIP_SC_ADV) { 497 + if (fnic_fcoe_vlan_check(fnic, ntohs(fiph->fip_flags))) 498 + goto drop; 499 + /* pass it on to fcoe */ 500 + ret = 1; 501 + } else if (op == FIP_OP_VLAN && sub == FIP_SC_VL_REP) { 502 + /* set the vlan as used */ 503 + fnic_fcoe_process_vlan_resp(fnic, skb); 504 + ret = 0; 505 + } else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK) { 506 + /* received CVL request, restart vlan disc */ 507 + fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); 508 + /* pass it on to fcoe */ 509 + ret = 1; 510 + } 511 + drop: 512 + return ret; 513 + } 514 + 515 + void fnic_handle_fip_frame(struct work_struct *work) 516 + { 517 + struct fnic *fnic = container_of(work, struct fnic, fip_frame_work); 518 + unsigned long flags; 519 + struct sk_buff *skb; 520 + struct ethhdr *eh; 521 + 522 + while ((skb = skb_dequeue(&fnic->fip_frame_queue))) { 523 + spin_lock_irqsave(&fnic->fnic_lock, flags); 524 + if (fnic->stop_rx_link_events) { 525 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 526 + dev_kfree_skb(skb); 527 + return; 528 + } 529 + /* 530 + * If we're in a transitional state, just re-queue and return. 531 + * The queue will be serviced when we get to a stable state. 532 + */ 533 + if (fnic->state != FNIC_IN_FC_MODE && 534 + fnic->state != FNIC_IN_ETH_MODE) { 535 + skb_queue_head(&fnic->fip_frame_queue, skb); 536 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 537 + return; 538 + } 539 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 540 + eh = (struct ethhdr *)skb->data; 541 + if (eh->h_proto == htons(ETH_P_FIP)) { 542 + skb_pull(skb, sizeof(*eh)); 543 + if (fnic_fcoe_handle_fip_frame(fnic, skb) <= 0) { 544 + dev_kfree_skb(skb); 545 + continue; 546 + } 547 + /* 548 + * If there's FLOGI rejects - clear all 549 + * fcf's & restart from scratch 550 + */ 551 + if (is_fnic_fip_flogi_reject(&fnic->ctlr, skb)) { 552 + shost_printk(KERN_INFO, fnic->lport->host, 553 + "Trigger a Link down - VLAN Disc\n"); 554 + fcoe_ctlr_link_down(&fnic->ctlr); 555 + /* start FCoE VLAN discovery */ 556 + fnic_fcoe_send_vlan_req(fnic); 557 + dev_kfree_skb(skb); 558 + continue; 559 + } 560 + fcoe_ctlr_recv(&fnic->ctlr, skb); 561 + continue; 562 + } 563 + } 564 + } 565 + 149 566 /** 150 567 * fnic_import_rq_eth_pkt() - handle received FCoE or FIP frame. 151 568 * @fnic: fnic instance. ··· 603 150 skb_reset_mac_header(skb); 604 151 } 605 152 if (eh->h_proto == htons(ETH_P_FIP)) { 606 - skb_pull(skb, sizeof(*eh)); 607 - fcoe_ctlr_recv(&fnic->ctlr, skb); 153 + skb_queue_tail(&fnic->fip_frame_queue, skb); 154 + queue_work(fnic_fip_queue, &fnic->fip_frame_work); 608 155 return 1; /* let caller know packet was used */ 609 156 } 610 157 if (eh->h_proto != htons(ETH_P_FCOE)) ··· 1172 719 1173 720 dev_kfree_skb(fp_skb(fp)); 1174 721 buf->os_buf = NULL; 722 + } 723 + 724 + void fnic_fcoe_reset_vlans(struct fnic *fnic) 725 + { 726 + unsigned long flags; 727 + struct fcoe_vlan *vlan; 728 + struct fcoe_vlan *next; 729 + 730 + /* 731 + * indicate a link down to fcoe so that all fcf's are free'd 732 + * might not be required since we did this before sending vlan 733 + * discovery request 734 + */ 735 + spin_lock_irqsave(&fnic->vlans_lock, flags); 736 + if (!list_empty(&fnic->vlans)) { 737 + list_for_each_entry_safe(vlan, next, &fnic->vlans, list) { 738 + list_del(&vlan->list); 739 + kfree(vlan); 740 + } 741 + } 742 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 743 + } 744 + 745 + void fnic_handle_fip_timer(struct fnic *fnic) 746 + { 747 + unsigned long flags; 748 + struct fcoe_vlan *vlan; 749 + u64 sol_time; 750 + 751 + spin_lock_irqsave(&fnic->fnic_lock, flags); 752 + if (fnic->stop_rx_link_events) { 753 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 754 + return; 755 + } 756 + spin_unlock_irqrestore(&fnic->fnic_lock, flags); 757 + 758 + if (fnic->ctlr.mode == FIP_ST_NON_FIP) 759 + return; 760 + 761 + spin_lock_irqsave(&fnic->vlans_lock, flags); 762 + if (list_empty(&fnic->vlans)) { 763 + /* no vlans available, try again */ 764 + FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, 765 + "Start VLAN Discovery\n"); 766 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 767 + fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); 768 + return; 769 + } 770 + 771 + vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, list); 772 + shost_printk(KERN_DEBUG, fnic->lport->host, 773 + "fip_timer: vlan %d state %d sol_count %d\n", 774 + vlan->vid, vlan->state, vlan->sol_count); 775 + switch (vlan->state) { 776 + case FIP_VLAN_USED: 777 + FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, 778 + "FIP VLAN is selected for FC transaction\n"); 779 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 780 + break; 781 + case FIP_VLAN_FAILED: 782 + /* if all vlans are in failed state, restart vlan disc */ 783 + FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host, 784 + "Start VLAN Discovery\n"); 785 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 786 + fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); 787 + break; 788 + case FIP_VLAN_SENT: 789 + if (vlan->sol_count >= FCOE_CTLR_MAX_SOL) { 790 + /* 791 + * no response on this vlan, remove from the list. 792 + * Try the next vlan 793 + */ 794 + shost_printk(KERN_INFO, fnic->lport->host, 795 + "Dequeue this VLAN ID %d from list\n", 796 + vlan->vid); 797 + list_del(&vlan->list); 798 + kfree(vlan); 799 + vlan = NULL; 800 + if (list_empty(&fnic->vlans)) { 801 + /* we exhausted all vlans, restart vlan disc */ 802 + spin_unlock_irqrestore(&fnic->vlans_lock, 803 + flags); 804 + shost_printk(KERN_INFO, fnic->lport->host, 805 + "fip_timer: vlan list empty, " 806 + "trigger vlan disc\n"); 807 + fnic_event_enq(fnic, FNIC_EVT_START_VLAN_DISC); 808 + return; 809 + } 810 + /* check the next vlan */ 811 + vlan = list_first_entry(&fnic->vlans, struct fcoe_vlan, 812 + list); 813 + fnic->set_vlan(fnic, vlan->vid); 814 + vlan->state = FIP_VLAN_SENT; /* sent now */ 815 + } 816 + spin_unlock_irqrestore(&fnic->vlans_lock, flags); 817 + vlan->sol_count++; 818 + sol_time = jiffies + msecs_to_jiffies 819 + (FCOE_CTLR_START_DELAY); 820 + mod_timer(&fnic->fip_timer, round_jiffies(sol_time)); 821 + break; 822 + } 1175 823 }
+68
drivers/scsi/fnic/fnic_fip.h
··· 1 + /* 2 + * Copyright 2008 Cisco Systems, Inc. All rights reserved. 3 + * Copyright 2007 Nuova Systems, Inc. All rights reserved. 4 + * 5 + * This program is free software; you may redistribute it and/or modify 6 + * it under the terms of the GNU General Public License as published by 7 + * the Free Software Foundation; version 2 of the License. 8 + * 9 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 10 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 11 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 12 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 13 + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 14 + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 15 + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 16 + * SOFTWARE. 17 + */ 18 + 19 + #ifndef _FNIC_FIP_H_ 20 + #define _FNIC_FIP_H_ 21 + 22 + 23 + #define FCOE_CTLR_START_DELAY 2000 /* ms after first adv. to choose FCF */ 24 + #define FCOE_CTLR_FIPVLAN_TOV 2000 /* ms after FIP VLAN disc */ 25 + #define FCOE_CTLR_MAX_SOL 8 26 + 27 + #define FINC_MAX_FLOGI_REJECTS 8 28 + 29 + /* 30 + * FIP_DT_VLAN descriptor. 31 + */ 32 + struct fip_vlan_desc { 33 + struct fip_desc fd_desc; 34 + __be16 fd_vlan; 35 + } __attribute__((packed)); 36 + 37 + struct vlan { 38 + __be16 vid; 39 + __be16 type; 40 + }; 41 + 42 + /* 43 + * VLAN entry. 44 + */ 45 + struct fcoe_vlan { 46 + struct list_head list; 47 + u16 vid; /* vlan ID */ 48 + u16 sol_count; /* no. of sols sent */ 49 + u16 state; /* state */ 50 + }; 51 + 52 + enum fip_vlan_state { 53 + FIP_VLAN_AVAIL = 0, /* don't do anything */ 54 + FIP_VLAN_SENT = 1, /* sent */ 55 + FIP_VLAN_USED = 2, /* succeed */ 56 + FIP_VLAN_FAILED = 3, /* failed to response */ 57 + }; 58 + 59 + struct fip_vlan { 60 + struct ethhdr eth; 61 + struct fip_header fip; 62 + struct { 63 + struct fip_mac_desc mac; 64 + struct fip_wwn_desc wwnn; 65 + } desc; 66 + }; 67 + 68 + #endif /* __FINC_FIP_H_ */
+49 -2
drivers/scsi/fnic/fnic_main.c
··· 39 39 #include "vnic_intr.h" 40 40 #include "vnic_stats.h" 41 41 #include "fnic_io.h" 42 + #include "fnic_fip.h" 42 43 #include "fnic.h" 43 44 44 45 #define PCI_DEVICE_ID_CISCO_FNIC 0x0045 ··· 293 292 round_jiffies(jiffies + FNIC_NOTIFY_TIMER_PERIOD)); 294 293 } 295 294 295 + static void fnic_fip_notify_timer(unsigned long data) 296 + { 297 + struct fnic *fnic = (struct fnic *)data; 298 + 299 + fnic_handle_fip_timer(fnic); 300 + } 301 + 296 302 static void fnic_notify_timer_start(struct fnic *fnic) 297 303 { 298 304 switch (vnic_dev_get_intr_mode(fnic->vdev)) { ··· 409 401 struct fnic *fnic = lport_priv(lport); 410 402 411 403 return fnic->data_src_addr; 404 + } 405 + 406 + static void fnic_set_vlan(struct fnic *fnic, u16 vlan_id) 407 + { 408 + u16 old_vlan; 409 + old_vlan = vnic_dev_set_default_vlan(fnic->vdev, vlan_id); 412 410 } 413 411 414 412 static int fnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ··· 634 620 vnic_dev_packet_filter(fnic->vdev, 1, 1, 0, 0, 0); 635 621 vnic_dev_add_addr(fnic->vdev, FIP_ALL_ENODE_MACS); 636 622 vnic_dev_add_addr(fnic->vdev, fnic->ctlr.ctl_src_addr); 623 + fnic->set_vlan = fnic_set_vlan; 637 624 fcoe_ctlr_init(&fnic->ctlr, FIP_MODE_AUTO); 625 + setup_timer(&fnic->fip_timer, fnic_fip_notify_timer, 626 + (unsigned long)fnic); 627 + spin_lock_init(&fnic->vlans_lock); 628 + INIT_WORK(&fnic->fip_frame_work, fnic_handle_fip_frame); 629 + INIT_WORK(&fnic->event_work, fnic_handle_event); 630 + skb_queue_head_init(&fnic->fip_frame_queue); 631 + spin_lock_irqsave(&fnic_list_lock, flags); 632 + if (!fnic_fip_queue) { 633 + fnic_fip_queue = 634 + create_singlethread_workqueue("fnic_fip_q"); 635 + if (!fnic_fip_queue) { 636 + spin_unlock_irqrestore(&fnic_list_lock, flags); 637 + printk(KERN_ERR PFX "fnic FIP work queue " 638 + "create failed\n"); 639 + err = -ENOMEM; 640 + goto err_out_free_max_pool; 641 + } 642 + } 643 + spin_unlock_irqrestore(&fnic_list_lock, flags); 644 + INIT_LIST_HEAD(&fnic->evlist); 645 + INIT_LIST_HEAD(&fnic->vlans); 638 646 } else { 639 647 shost_printk(KERN_INFO, fnic->lport->host, 640 648 "firmware uses non-FIP mode\n"); ··· 843 807 skb_queue_purge(&fnic->frame_queue); 844 808 skb_queue_purge(&fnic->tx_queue); 845 809 810 + if (fnic->config.flags & VFCF_FIP_CAPABLE) { 811 + del_timer_sync(&fnic->fip_timer); 812 + skb_queue_purge(&fnic->fip_frame_queue); 813 + fnic_fcoe_reset_vlans(fnic); 814 + fnic_fcoe_evlist_free(fnic); 815 + } 816 + 846 817 /* 847 818 * Log off the fabric. This stops all remote ports, dns port, 848 819 * logs off the fabric. This flushes all rport, disc, lport work ··· 932 889 len = sizeof(struct fnic_sgl_list); 933 890 fnic_sgl_cache[FNIC_SGL_CACHE_MAX] = kmem_cache_create 934 891 ("fnic_sgl_max", len + FNIC_SG_DESC_ALIGN, FNIC_SG_DESC_ALIGN, 935 - SLAB_HWCACHE_ALIGN, 936 - NULL); 892 + SLAB_HWCACHE_ALIGN, 893 + NULL); 937 894 if (!fnic_sgl_cache[FNIC_SGL_CACHE_MAX]) { 938 895 printk(KERN_ERR PFX "failed to create fnic max sgl slab\n"); 939 896 err = -ENOMEM; ··· 994 951 { 995 952 pci_unregister_driver(&fnic_driver); 996 953 destroy_workqueue(fnic_event_queue); 954 + if (fnic_fip_queue) { 955 + flush_workqueue(fnic_fip_queue); 956 + destroy_workqueue(fnic_fip_queue); 957 + } 997 958 kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_MAX]); 998 959 kmem_cache_destroy(fnic_sgl_cache[FNIC_SGL_CACHE_DFLT]); 999 960 kmem_cache_destroy(fnic_io_req_cache);
+10
drivers/scsi/fnic/vnic_dev.c
··· 584 584 return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait); 585 585 } 586 586 587 + u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev, u16 new_default_vlan) 588 + { 589 + u64 a0 = new_default_vlan, a1 = 0; 590 + int wait = 1000; 591 + int old_vlan = 0; 592 + 593 + old_vlan = vnic_dev_cmd(vdev, CMD_SET_DEFAULT_VLAN, &a0, &a1, wait); 594 + return (u16)old_vlan; 595 + } 596 + 587 597 int vnic_dev_link_status(struct vnic_dev *vdev) 588 598 { 589 599 if (vdev->linkstatus)
+2
drivers/scsi/fnic/vnic_dev.h
··· 148 148 int vnic_dev_open(struct vnic_dev *vdev, int arg); 149 149 int vnic_dev_open_done(struct vnic_dev *vdev, int *done); 150 150 int vnic_dev_init(struct vnic_dev *vdev, int arg); 151 + u16 vnic_dev_set_default_vlan(struct vnic_dev *vdev, 152 + u16 new_default_vlan); 151 153 int vnic_dev_soft_reset(struct vnic_dev *vdev, int arg); 152 154 int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done); 153 155 void vnic_dev_set_intr_mode(struct vnic_dev *vdev,
+67
drivers/scsi/fnic/vnic_devcmd.h
··· 196 196 197 197 /* undo initialize of virtual link */ 198 198 CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34), 199 + 200 + /* check fw capability of a cmd: 201 + * in: (u32)a0=cmd 202 + * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */ 203 + CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36), 204 + 205 + /* persistent binding info 206 + * in: (u64)a0=paddr of arg 207 + * (u32)a1=CMD_PERBI_XXX */ 208 + CMD_PERBI = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_FC, 37), 209 + 210 + /* Interrupt Assert Register functionality 211 + * in: (u16)a0=interrupt number to assert 212 + */ 213 + CMD_IAR = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 38), 214 + 215 + /* initiate hangreset, like softreset after hang detected */ 216 + CMD_HANG_RESET = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 39), 217 + 218 + /* hangreset status: 219 + * out: a0=0 reset complete, a0=1 reset in progress */ 220 + CMD_HANG_RESET_STATUS = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 40), 221 + 222 + /* 223 + * Set hw ingress packet vlan rewrite mode: 224 + * in: (u32)a0=new vlan rewrite mode 225 + * out: (u32)a0=old vlan rewrite mode */ 226 + CMD_IG_VLAN_REWRITE_MODE = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ENET, 41), 227 + 228 + /* 229 + * in: (u16)a0=bdf of target vnic 230 + * (u32)a1=cmd to proxy 231 + * a2-a15=args to cmd in a1 232 + * out: (u32)a0=status of proxied cmd 233 + * a1-a15=out args of proxied cmd */ 234 + CMD_PROXY_BY_BDF = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 42), 235 + 236 + /* 237 + * As for BY_BDF except a0 is index of hvnlink subordinate vnic 238 + * or SR-IOV virtual vnic 239 + */ 240 + CMD_PROXY_BY_INDEX = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 43), 241 + 242 + /* 243 + * For HPP toggle: 244 + * adapter-info-get 245 + * in: (u64)a0=phsical address of buffer passed in from caller. 246 + * (u16)a1=size of buffer specified in a0. 247 + * out: (u64)a0=phsical address of buffer passed in from caller. 248 + * (u16)a1=actual bytes from VIF-CONFIG-INFO TLV, or 249 + * 0 if no VIF-CONFIG-INFO TLV was ever received. */ 250 + CMD_CONFIG_INFO_GET = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 44), 251 + 252 + /* 253 + * INT13 API: (u64)a0=paddr to vnic_int13_params struct 254 + * (u32)a1=INT13_CMD_xxx 255 + */ 256 + CMD_INT13_ALL = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 45), 257 + 258 + /* 259 + * Set default vlan: 260 + * in: (u16)a0=new default vlan 261 + * (u16)a1=zero for overriding vlan with param a0, 262 + * non-zero for resetting vlan to the default 263 + * out: (u16)a0=old default vlan 264 + */ 265 + CMD_SET_DEFAULT_VLAN = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 46) 199 266 }; 200 267 201 268 /* flags for CMD_OPEN */