With multiple lports created per netdev, the packet_type structure is no longer sufficient for receive demux. Instead we need to match on the fabric ID.
Signed-off-by: Chris Leech <[email protected]> --- drivers/scsi/fcoe/fcoe.c | 70 +++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 66 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index 381e4e2..86d8b23 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -146,10 +146,48 @@ static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev, struct net_device *orig_dev) { struct fcoe_softc *fc; + struct fc_lport *tlp, *lp = NULL; + struct Scsi_Host *shost; + struct fc_vport *vport; + unsigned long flags; + u32 d_id; + struct fc_frame_header *fh; + struct fip_header *fiph; + + fiph = (void *)skb->data; + fh = ((void *)skb->data) + sizeof(*fiph); + d_id = ntoh24(fh->fh_d_id); fc = container_of(ptype, struct fcoe_softc, fip_packet_type); + tlp = fc->ctlr.lp; + + /* Might be an NPIV port, check the vport list */ + + if (d_id == fc_host_port_id(tlp->host) || + !fc_host_port_id(tlp->host)) { + lp = tlp; + } else { + shost = tlp->host; + spin_lock_irqsave(shost->host_lock, flags); + list_for_each_entry(vport, &fc_host_vports(shost), peers) { + tlp = vport->dd_data; + if (d_id == fc_host_port_id(tlp->host) || + !fc_host_port_id(tlp->host)) { + lp = tlp; + break; + } + } + spin_unlock_irqrestore(shost->host_lock, flags); + } + if (unlikely(!lp)) + goto err; + + fc = lport_priv(lp); fcoe_ctlr_recv(&fc->ctlr, skb); return 0; +err: + kfree(skb); + return 0; } /** @@ -821,21 +859,24 @@ static struct notifier_block fcoe_cpu_notifier = { int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *olddev) { - struct fc_lport *lp; + struct fc_lport *lp = NULL, *tlp; struct fcoe_rcv_info *fr; struct fcoe_softc *fc; struct fc_frame_header *fh; struct fcoe_percpu_s *fps; unsigned short oxid; unsigned int cpu = 0; + struct fc_vport *vport; + struct Scsi_Host *shost; + unsigned long flags; fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); - lp = fc->ctlr.lp; - if (unlikely(lp == NULL)) { + tlp = fc->ctlr.lp; + if (unlikely(tlp == NULL)) { FCOE_NETDEV_DBG(dev, "Cannot find hba structure"); goto err2; } - if (!lp->link_up) + if (!tlp->link_up) goto err2; FCOE_NETDEV_DBG(dev, "skb_info: len:%d data_len:%d head:%p " @@ -863,6 +904,27 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, oxid = ntohs(fh->fh_ox_id); + /* Might be an NPIV port, check the vport list */ + + if (ntoh24(fh->fh_d_id) == fc_host_port_id(tlp->host) || + !fc_host_port_id(tlp->host)) { + lp = tlp; + } else { + shost = tlp->host; + spin_lock_irqsave(shost->host_lock, flags); + list_for_each_entry(vport, &fc_host_vports(shost), peers) { + tlp = vport->dd_data; + if (ntoh24(fh->fh_d_id) == fc_host_port_id(tlp->host) || + !fc_host_port_id(tlp->host)) { + lp = tlp; + break; + } + } + spin_unlock_irqrestore(shost->host_lock, flags); + } + if (unlikely(!lp)) + goto err2; + fr = fcoe_dev_from_skb(skb); fr->fr_dev = lp; fr->ptype = ptype; _______________________________________________ devel mailing list [email protected] http://www.open-fcoe.org/mailman/listinfo/devel
