📄 mptlan.c
字号:
flags); break; } ctx = priv->mpt_rxfidx[priv->mpt_rxfidx_tail--]; skb = priv->RcvCtl[ctx].skb; if (skb && (priv->RcvCtl[ctx].len != len)) { pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma, priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE); dev_kfree_skb(priv->RcvCtl[ctx].skb); skb = priv->RcvCtl[ctx].skb = NULL; } if (skb == NULL) { skb = dev_alloc_skb(len); if (skb == NULL) { printk (KERN_WARNING MYNAM "/%s: Can't alloc skb\n", __FUNCTION__); priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx; spin_unlock_irqrestore(&priv->rxfidx_lock, flags); break; } dma = pci_map_single(mpt_dev->pcidev, skb->data, len, PCI_DMA_FROMDEVICE); priv->RcvCtl[ctx].skb = skb; priv->RcvCtl[ctx].dma = dma; priv->RcvCtl[ctx].len = len; } spin_unlock_irqrestore(&priv->rxfidx_lock, flags); pTrans->ContextSize = sizeof(u32); pTrans->DetailsLength = 0; pTrans->Flags = 0; pTrans->TransactionContext[0] = cpu_to_le32(ctx); pSimple = (SGESimple64_t *) pTrans->TransactionDetails; pSimple->FlagsLength = cpu_to_le32( ((MPI_SGE_FLAGS_END_OF_BUFFER | MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_64_BIT_ADDRESSING) << MPI_SGE_FLAGS_SHIFT) | len); pSimple->Address.Low = cpu_to_le32((u32) priv->RcvCtl[ctx].dma); if (sizeof(dma_addr_t) > sizeof(u32)) pSimple->Address.High = cpu_to_le32((u32) ((u64) priv->RcvCtl[ctx].dma >> 32)); else pSimple->Address.High = 0; pTrans = (SGETransaction32_t *) (pSimple + 1); } if (pSimple == NULL) {/**/ printk (KERN_WARNING MYNAM "/%s: No buckets posted\n",/**/ __FUNCTION__); mpt_free_msg_frame(mpt_dev, mf); goto out; } pSimple->FlagsLength |= cpu_to_le32(MPI_SGE_FLAGS_END_OF_LIST << MPI_SGE_FLAGS_SHIFT); pRecvReq->BucketCount = cpu_to_le32(i);/* printk(KERN_INFO MYNAM ": posting buckets\n "); * for (i = 0; i < j + 2; i ++) * printk (" %08x", le32_to_cpu(msg[i])); * printk ("\n"); */ mpt_put_msg_frame(LanCtx, mpt_dev, mf); priv->total_posted += i; buckets -= i; atomic_add(i, &priv->buckets_out); }out: dioprintk((KERN_INFO MYNAM "/%s: End_buckets = %u, priv->buckets_out = %u\n", __FUNCTION__, buckets, atomic_read(&priv->buckets_out))); dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n", __FUNCTION__, priv->total_posted, priv->total_received)); clear_bit(0, &priv->post_buckets_active);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static struct net_device *mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum){ struct net_device *dev = alloc_fcdev(sizeof(struct mpt_lan_priv)); struct mpt_lan_priv *priv = NULL; u8 HWaddr[FC_ALEN], *a; if (!dev) return NULL; dev->mtu = MPT_LAN_MTU; priv = netdev_priv(dev); priv->mpt_dev = mpt_dev; priv->pnum = pnum; memset(&priv->post_buckets_task, 0, sizeof(struct work_struct)); INIT_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets, dev); priv->post_buckets_active = 0; dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n", __LINE__, dev->mtu + dev->hard_header_len + 4)); atomic_set(&priv->buckets_out, 0); priv->total_posted = 0; priv->total_received = 0; priv->max_buckets_out = max_buckets_out; if (mpt_dev->pfacts[0].MaxLanBuckets < max_buckets_out) priv->max_buckets_out = mpt_dev->pfacts[0].MaxLanBuckets; dlprintk((KERN_INFO MYNAM "@%d: MaxLanBuckets=%d, max_buckets_out/priv=%d/%d\n", __LINE__, mpt_dev->pfacts[0].MaxLanBuckets, max_buckets_out, priv->max_buckets_out)); priv->bucketthresh = priv->max_buckets_out * 2 / 3; spin_lock_init(&priv->txfidx_lock); spin_lock_init(&priv->rxfidx_lock); memset(&priv->stats, 0, sizeof(priv->stats)); /* Grab pre-fetched LANPage1 stuff. :-) */ a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow; HWaddr[0] = a[5]; HWaddr[1] = a[4]; HWaddr[2] = a[3]; HWaddr[3] = a[2]; HWaddr[4] = a[1]; HWaddr[5] = a[0]; dev->addr_len = FC_ALEN; memcpy(dev->dev_addr, HWaddr, FC_ALEN); memset(dev->broadcast, 0xff, FC_ALEN); /* The Tx queue is 127 deep on the 909. * Give ourselves some breathing room. */ priv->tx_max_out = (tx_max_out_p <= MPT_TX_MAX_OUT_LIM) ? tx_max_out_p : MPT_TX_MAX_OUT_LIM; dev->open = mpt_lan_open; dev->stop = mpt_lan_close; dev->get_stats = mpt_lan_get_stats; dev->set_multicast_list = NULL; dev->change_mtu = mpt_lan_change_mtu; dev->hard_start_xmit = mpt_lan_sdu_send;/* Not in 2.3.42. Need 2.3.45+ */ dev->tx_timeout = mpt_lan_tx_timeout; dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT; dlprintk((KERN_INFO MYNAM ": Finished registering dev " "and setting initial values\n")); SET_MODULE_OWNER(dev); if (register_netdev(dev) != 0) { free_netdev(dev); dev = NULL; } return dev;}static intmptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct net_device *dev; int i; for (i = 0; i < ioc->facts.NumberOfPorts; i++) { printk(KERN_INFO MYNAM ": %s: PortNum=%x, " "ProtocolFlags=%02Xh (%c%c%c%c)\n", ioc->name, ioc->pfacts[i].PortNumber, ioc->pfacts[i].ProtocolFlags, MPT_PROTOCOL_FLAGS_c_c_c_c( ioc->pfacts[i].ProtocolFlags)); if (!(ioc->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { printk(KERN_INFO MYNAM ": %s: Hmmm... LAN protocol " "seems to be disabled on this adapter port!\n", ioc->name); continue; } dev = mpt_register_lan_device(ioc, i); if (!dev) { printk(KERN_ERR MYNAM ": %s: Unable to register " "port%d as a LAN device\n", ioc->name, ioc->pfacts[i].PortNumber); continue; } printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device " "registered as '%s'\n", ioc->name, dev->name); printk(KERN_INFO MYNAM ": %s/%s: " "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", IOC_AND_NETDEV_NAMES_s_s(dev), dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2], dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]); ioc->netdev = dev; return 0; } return -ENODEV;}static voidmptlan_remove(struct pci_dev *pdev){ MPT_ADAPTER *ioc = pci_get_drvdata(pdev); struct net_device *dev = ioc->netdev; if(dev != NULL) { unregister_netdev(dev); free_netdev(dev); }}static struct mpt_pci_driver mptlan_driver = { .probe = mptlan_probe, .remove = mptlan_remove,};static int __init mpt_lan_init (void){ show_mptmod_ver(LANAME, LANVER); if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) { printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n"); return -EBUSY; } /* Set the callback index to be used by driver core for turbo replies */ mpt_lan_index = LanCtx; dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx)); if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) { printk(KERN_ERR MYNAM ": Eieee! unable to register a reset " "handler with mptbase! The world is at an end! " "Everything is fading to black! Goodbye.\n"); return -EBUSY; } dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); if (mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER)) dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n")); return 0;}static void __exit mpt_lan_exit(void){ mpt_device_driver_deregister(MPTLAN_DRIVER); mpt_reset_deregister(LanCtx); if (LanCtx >= 0) { mpt_deregister(LanCtx); LanCtx = -1; mpt_lan_index = 0; }}module_init(mpt_lan_init);module_exit(mpt_lan_exit);/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/static unsigned shortmpt_lan_type_trans(struct sk_buff *skb, struct net_device *dev){ struct mpt_lan_ohdr *fch = (struct mpt_lan_ohdr *)skb->data; struct fcllc *fcllc; skb->mac.raw = skb->data; skb_pull(skb, sizeof(struct mpt_lan_ohdr)); if (fch->dtype == htons(0xffff)) { u32 *p = (u32 *) fch; swab32s(p + 0); swab32s(p + 1); swab32s(p + 2); swab32s(p + 3); printk (KERN_WARNING MYNAM ": %s: WARNING - Broadcast swap F/W bug detected!\n", NETDEV_PTR_TO_IOC_NAME_s(dev)); printk (KERN_WARNING MYNAM ": Please update sender @ MAC_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", fch->saddr[0], fch->saddr[1], fch->saddr[2], fch->saddr[3], fch->saddr[4], fch->saddr[5]); } if (*fch->daddr & 1) { if (!memcmp(fch->daddr, dev->broadcast, FC_ALEN)) { skb->pkt_type = PACKET_BROADCAST; } else { skb->pkt_type = PACKET_MULTICAST; } } else { if (memcmp(fch->daddr, dev->dev_addr, FC_ALEN)) { skb->pkt_type = PACKET_OTHERHOST; } else { skb->pkt_type = PACKET_HOST; } } fcllc = (struct fcllc *)skb->data;#ifdef QLOGIC_NAA_WORKAROUND{ u16 source_naa = fch->stype, found = 0; /* Workaround for QLogic not following RFC 2625 in regards to the NAA value. */ if ((source_naa & 0xF000) == 0) source_naa = swab16(source_naa); if (fcllc->ethertype == htons(ETH_P_ARP)) dlprintk ((KERN_INFO "mptlan/type_trans: got arp req/rep w/ naa of " "%04x.\n", source_naa)); if ((fcllc->ethertype == htons(ETH_P_ARP)) && ((source_naa >> 12) != MPT_LAN_NAA_RFC2625)){ struct NAA_Hosed *nh, *prevnh; int i; dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep from " "system with non-RFC 2625 NAA value (%04x).\n", source_naa)); write_lock_irq(&bad_naa_lock); for (prevnh = nh = mpt_bad_naa; nh != NULL; prevnh=nh, nh=nh->next) { if ((nh->ieee[0] == fch->saddr[0]) && (nh->ieee[1] == fch->saddr[1]) && (nh->ieee[2] == fch->saddr[2]) && (nh->ieee[3] == fch->saddr[3]) && (nh->ieee[4] == fch->saddr[4]) && (nh->ieee[5] == fch->saddr[5])) { found = 1; dlprintk ((KERN_INFO "mptlan/type_trans: ARP Re" "q/Rep w/ bad NAA from system already" " in DB.\n")); break; } } if ((!found) && (nh == NULL)) { nh = kmalloc(sizeof(struct NAA_Hosed), GFP_KERNEL); dlprintk ((KERN_INFO "mptlan/type_trans: ARP Req/Rep w/" " bad NAA from system not yet in DB.\n")); if (nh != NULL) { nh->next = NULL; if (!mpt_bad_naa) mpt_bad_naa = nh; if (prevnh) prevnh->next = nh; nh->NAA = source_naa; /* Set the S_NAA value. */ for (i = 0; i < FC_ALEN; i++) nh->ieee[i] = fch->saddr[i]; dlprintk ((KERN_INFO "Got ARP from %02x:%02x:%02x:%02x:" "%02x:%02x with non-compliant S_NAA value.\n", fch->saddr[0], fch->saddr[1], fch->saddr[2], fch->saddr[3], fch->saddr[4],fch->saddr[5])); } else { printk (KERN_ERR "mptlan/type_trans: Unable to" " kmalloc a NAA_Hosed struct.\n"); } } else if (!found) { printk (KERN_ERR "mptlan/type_trans: found not" " set, but nh isn't null. Evil " "funkiness abounds.\n"); } write_unlock_irq(&bad_naa_lock); }}#endif /* Strip the SNAP header from ARP packets since we don't * pass them through to the 802.2/SNAP layers. */ if (fcllc->dsap == EXTENDED_SAP && (fcllc->ethertype == htons(ETH_P_IP) || fcllc->ethertype == htons(ETH_P_ARP))) { skb_pull(skb, sizeof(struct fcllc)); return fcllc->ethertype; } return htons(ETH_P_802_2);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -