📄 mptlan.c
字号:
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(LanCtx, mpt_dev->id, 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->id, 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);}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/struct net_device *mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum){ struct net_device *dev = NULL; struct mpt_lan_priv *priv = NULL; u8 HWaddr[FC_ALEN], *a; dev = init_fcdev(NULL, sizeof(struct mpt_lan_priv)); if (!dev) return (NULL); dev->mtu = MPT_LAN_MTU; priv = (struct mpt_lan_priv *) dev->priv; priv->mpt_dev = mpt_dev; priv->pnum = pnum; memset(&priv->post_buckets_task, 0, sizeof(struct tq_struct)); priv->post_buckets_task.routine = mpt_lan_post_receive_buckets; priv->post_buckets_task.data = dev; priv->post_buckets_active = 0; dprintk((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; dprintk((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; priv->txfidx_lock = SPIN_LOCK_UNLOCKED; priv->rxfidx_lock = SPIN_LOCK_UNLOCKED; 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; dprintk((KERN_INFO MYNAM ": Finished registering dev " "and setting initial values\n")); SET_MODULE_OWNER(dev); return dev;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/int __initmpt_lan_init (void){ struct net_device *dev; MPT_ADAPTER *curadapter; int i = 0, j; show_mptmod_ver(LANAME, LANVER); /* Init the global r/w lock for the bad_naa list. We want to do this before any boards are initialized and may be used. */ rwlock_init(&bad_naa_lock); 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; dprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx)); if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) { dprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); } else { 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; } for (j = 0; j < MPT_MAX_ADAPTERS; j++) { mpt_landev[j] = NULL; } j = 0; curadapter = mpt_adapter_find_first(); while (curadapter != NULL) { for (i = 0; i < curadapter->facts.NumberOfPorts; i++) { printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n", curadapter->name, curadapter->pfacts[i].PortNumber, curadapter->pfacts[i].ProtocolFlags, MPT_PROTOCOL_FLAGS_c_c_c_c(curadapter->pfacts[i].ProtocolFlags)); if (curadapter->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) { dev = mpt_register_lan_device (curadapter, i); if (dev != NULL) { printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n", curadapter->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]);// printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n",// IOC_AND_NETDEV_NAMES_s_s(dev),// NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out); mpt_landev[j] = dev; dprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n", dev, j, mpt_landev[j])); j++; } else { printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n", curadapter->name, curadapter->pfacts[i].PortNumber); } } else { printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n", curadapter->name); } } curadapter = mpt_adapter_find_next(curadapter); } return 0;}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/void __init mpt_lan_exit(void){ int i; mpt_reset_deregister(LanCtx); for (i = 0; mpt_landev[i] != NULL; i++) { struct net_device *dev = mpt_landev[i]; printk (KERN_INFO MYNAM ": %s/%s: Fusion MPT LAN device unregistered\n", IOC_AND_NETDEV_NAMES_s_s(dev)); unregister_fcdev(dev); mpt_landev[i] = (struct net_device *) 0xdeadbeef; /* Debug */ } if (LanCtx >= 0) { mpt_deregister(LanCtx); LanCtx = -1; mpt_lan_index = 0; } /* deregister any send/receive handler structs. I2Oism? */}/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/MODULE_PARM(tx_max_out_p, "i");MODULE_PARM(max_buckets_out, "i"); // Debug stuff. FIXME!MODULE_LICENSE("GPL");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; u16 source_naa = fch->stype, found = 0; 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; /* 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)) dprintk ((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; dprintk ((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; dprintk ((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); dprintk ((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]; dprintk ((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); } /* 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 + -