⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mptlan.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
						       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 + -