X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmessage%2Ffusion%2Fmptlan.c;h=2936204d8ad629f367cbdc00af8156ffd14bf5a5;hb=refs%2Fheads%2Fvserver;hp=80c9b97eb3678890ea207defe23068c278971109;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 80c9b97eb..2936204d8 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -1,33 +1,11 @@ /* * linux/drivers/message/fusion/mptlan.c * IP Over Fibre Channel device driver. - * For use with PCI chip/adapter(s): - * LSIFC9xx/LSI409xx Fibre Channel + * For use with LSI Logic Fibre Channel PCI chip/adapters * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Credits: - * This driver would not exist if not for Alan Cox's development - * of the linux i2o driver. + * Copyright (c) 2000-2007 LSI Logic Corporation * - * Special thanks goes to the I2O LAN driver people at the - * University of Helsinki, who, unbeknownst to them, provided - * the inspiration and initial structure for this driver. - * - * A huge debt of gratitude is owed to David S. Miller (DaveM) - * for fixing much of the stupid and broken stuff in the early - * driver while porting to sparc64 platform. THANK YOU! - * - * A really huge debt of gratitude is owed to Eddie C. Dost - * for gobs of hard work fixing and optimizing LAN code. - * THANK YOU! - * - * (see also mptbase.c) - * - * Copyright (c) 2000-2004 LSI Logic Corporation - * Originally By: Noah Romer - * (mailto:mpt_linux_developer@lsil.com) - * - * $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -78,9 +56,11 @@ #include #include +#define my_VERSION MPT_LINUX_VERSION_COMMON #define MYNAM "mptlan" MODULE_LICENSE("GPL"); +MODULE_VERSION(my_VERSION); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -133,7 +113,8 @@ struct mpt_lan_priv { u32 total_received; struct net_device_stats stats; /* Per device statistics */ - struct work_struct post_buckets_task; + struct delayed_work post_buckets_task; + struct net_device *dev; unsigned long post_buckets_active; }; @@ -154,7 +135,7 @@ static int lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, static int mpt_lan_open(struct net_device *dev); static int mpt_lan_reset(struct net_device *dev); static int mpt_lan_close(struct net_device *dev); -static void mpt_lan_post_receive_buckets(void *dev_id); +static void mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv); static void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority); static int mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg); @@ -177,11 +158,9 @@ static int LanCtx = -1; static u32 max_buckets_out = 127; static u32 tx_max_out_p = 127 - 16; -static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1]; - #ifdef QLOGIC_NAA_WORKAROUND static struct NAA_Hosed *mpt_bad_naa = NULL; -rwlock_t bad_naa_lock; +DEFINE_RWLOCK(bad_naa_lock); #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -203,7 +182,7 @@ extern int mpt_lan_index; static int lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) { - struct net_device *dev = mpt_landev[ioc->id]; + struct net_device *dev = ioc->netdev; int FreeReqFrame = 0; dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n", @@ -223,7 +202,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) // NOTE! (Optimization) First case here is now caught in // mptbase.c::mpt_interrupt() routine and callcack here - // is now skipped for this case! 20001218 -sralston + // is now skipped for this case! #if 0 case LAN_REPLY_FORM_MESSAGE_CONTEXT: // dioprintk((KERN_INFO MYNAM "/lan_reply: " @@ -236,7 +215,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) // dioprintk((MYNAM "/lan_reply: " // "calling mpt_lan_send_reply (turbo)\n")); - // Potential BUG here? -sralston + // Potential BUG here? // FreeReqFrame = mpt_lan_send_turbo(dev, tmsg); // If/when mpt_lan_send_turbo would return 1 here, // calling routine (mptbase.c|mpt_interrupt) @@ -312,8 +291,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) case MPI_FUNCTION_EVENT_NOTIFICATION: case MPI_FUNCTION_EVENT_ACK: - /* UPDATE! 20010120 -sralston - * _EVENT_NOTIFICATION should NOT come down this path any more. + /* _EVENT_NOTIFICATION should NOT come down this path any more. * Should be routed to mpt_lan_event_process(), but just in case... */ FreeReqFrame = 1; @@ -336,8 +314,13 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) static int mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { - struct net_device *dev = mpt_landev[ioc->id]; - struct mpt_lan_priv *priv = netdev_priv(dev); + struct net_device *dev = ioc->netdev; + struct mpt_lan_priv *priv; + + if (dev == NULL) + return(1); + else + priv = netdev_priv(dev); dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n", reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( @@ -365,7 +348,7 @@ mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; spin_unlock_irqrestore(&priv->rxfidx_lock, flags); } else { - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); netif_wake_queue(dev); } @@ -431,14 +414,12 @@ mpt_lan_open(struct net_device *dev) goto out; priv->mpt_txfidx_tail = -1; - priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl), + priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl), GFP_KERNEL); if (priv->SendCtl == NULL) goto out_mpt_txfidx; - for (i = 0; i < priv->tx_max_out; i++) { - memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl)); + for (i = 0; i < priv->tx_max_out; i++) priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i; - } dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n")); @@ -448,15 +429,13 @@ mpt_lan_open(struct net_device *dev) goto out_SendCtl; priv->mpt_rxfidx_tail = -1; - priv->RcvCtl = kmalloc(priv->max_buckets_out * - sizeof(struct BufferControl), + priv->RcvCtl = kcalloc(priv->max_buckets_out, + sizeof(struct BufferControl), GFP_KERNEL); if (priv->RcvCtl == NULL) goto out_mpt_rxfidx; - for (i = 0; i < priv->max_buckets_out; i++) { - memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl)); + for (i = 0; i < priv->max_buckets_out; i++) priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; - } /**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - ")); /**/ for (i = 0; i < priv->tx_max_out; i++) @@ -465,7 +444,7 @@ mpt_lan_open(struct net_device *dev) dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n")); - mpt_lan_post_receive_buckets(dev); + mpt_lan_post_receive_buckets(priv); printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n", IOC_AND_NETDEV_NAMES_s_s(dev)); @@ -531,7 +510,7 @@ mpt_lan_close(struct net_device *dev) { struct mpt_lan_priv *priv = netdev_priv(dev); MPT_ADAPTER *mpt_dev = priv->mpt_dev; - unsigned int timeout; + unsigned long timeout; int i; dlprintk((KERN_INFO MYNAM ": mpt_lan_close called\n")); @@ -546,11 +525,9 @@ mpt_lan_close(struct net_device *dev) mpt_lan_reset(dev); - timeout = 2 * HZ; - while (atomic_read(&priv->buckets_out) && --timeout) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - } + timeout = jiffies + 2 * HZ; + while (atomic_read(&priv->buckets_out) && time_before(jiffies, timeout)) + schedule_timeout_interruptible(1); for (i = 0; i < priv->max_buckets_out; i++) { if (priv->RcvCtl[i].skb != NULL) { @@ -563,8 +540,8 @@ mpt_lan_close(struct net_device *dev) } } - kfree (priv->RcvCtl); - kfree (priv->mpt_rxfidx); + kfree(priv->RcvCtl); + kfree(priv->mpt_rxfidx); for (i = 0; i < priv->tx_max_out; i++) { if (priv->SendCtl[i].skb != NULL) { @@ -870,7 +847,7 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static inline void +static void mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) /* * @priority: 0 = put it on the timer queue, 1 = put it on the immediate queue @@ -880,7 +857,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) if (test_and_set_bit(0, &priv->post_buckets_active) == 0) { if (priority) { - schedule_work(&priv->post_buckets_task); + schedule_delayed_work(&priv->post_buckets_task, 0); } else { schedule_delayed_work(&priv->post_buckets_task, 1); dioprintk((KERN_INFO MYNAM ": post_buckets queued on " @@ -892,7 +869,7 @@ mpt_lan_wake_post_buckets_task(struct net_device *dev, int priority) } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static inline int +static int mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) { struct mpt_lan_priv *priv = dev->priv; @@ -1178,10 +1155,7 @@ mpt_lan_receive_post_reply(struct net_device *dev, priv->mpt_rxfidx_tail, MPT_LAN_MAX_BUCKETS_OUT); - panic("Damn it Jim! I'm a doctor, not a programmer! " - "Oh, wait a sec, I am a programmer. " - "And, who's Jim?!?!\n" - "Arrgghh! We've done it again!\n"); + return -1; } if (remaining == 0) @@ -1217,10 +1191,9 @@ mpt_lan_receive_post_reply(struct net_device *dev, /* Simple SGE's only at the moment */ static void -mpt_lan_post_receive_buckets(void *dev_id) +mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv) { - struct net_device *dev = dev_id; - struct mpt_lan_priv *priv = dev->priv; + struct net_device *dev = priv->dev; MPT_ADAPTER *mpt_dev = priv->mpt_dev; MPT_FRAME_HDR *mf; LANReceivePostRequest_t *pRecvReq; @@ -1334,7 +1307,7 @@ mpt_lan_post_receive_buckets(void *dev_id) if (pSimple == NULL) { /**/ printk (KERN_WARNING MYNAM "/%s: No buckets posted\n", /**/ __FUNCTION__); - mpt_free_msg_frame(LanCtx, mpt_dev, mf); + mpt_free_msg_frame(mpt_dev, mf); goto out; } @@ -1364,6 +1337,13 @@ out: clear_bit(0, &priv->post_buckets_active); } +static void +mpt_lan_post_receive_buckets_work(struct work_struct *work) +{ + mpt_lan_post_receive_buckets(container_of(work, struct mpt_lan_priv, + post_buckets_task.work)); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ static struct net_device * mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) @@ -1379,11 +1359,13 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) priv = netdev_priv(dev); + priv->dev = 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); + memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task)); + INIT_DELAYED_WORK(&priv->post_buckets_task, + mpt_lan_post_receive_buckets_work); priv->post_buckets_active = 0; dlprintk((KERN_INFO MYNAM "@%d: bucketlen = %d\n", @@ -1403,8 +1385,8 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) priv->max_buckets_out)); priv->bucketthresh = priv->max_buckets_out * 2 / 3; - priv->txfidx_lock = SPIN_LOCK_UNLOCKED; - priv->rxfidx_lock = SPIN_LOCK_UNLOCKED; + spin_lock_init(&priv->txfidx_lock); + spin_lock_init(&priv->rxfidx_lock); memset(&priv->stats, 0, sizeof(priv->stats)); @@ -1451,20 +1433,74 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) return dev; } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int __init mpt_lan_init (void) +static int +mptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - struct net_device *dev; - MPT_ADAPTER *p; - int i, j; + 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; + } - show_mptmod_ver(LANAME, LANVER); + 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; -#ifdef QLOGIC_NAA_WORKAROUND - /* 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); -#endif + return 0; + } + + return -ENODEV; +} + +static void +mptlan_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"); @@ -1476,88 +1512,32 @@ static int __init mpt_lan_init (void) dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx)); - if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) { - dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n")); - } else { + 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; } - for (j = 0; j < MPT_MAX_ADAPTERS; j++) { - mpt_landev[j] = NULL; - } - - list_for_each_entry(p, &ioc_list, list) { - for (i = 0; i < p->facts.NumberOfPorts; i++) { - printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n", - p->name, - p->pfacts[i].PortNumber, - p->pfacts[i].ProtocolFlags, - MPT_PROTOCOL_FLAGS_c_c_c_c(p->pfacts[i].ProtocolFlags)); - - if (!(p->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) { - printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n", - p->name); - continue; - } - - dev = mpt_register_lan_device (p, i); - if (!dev) { - printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n", - p->name, - p->pfacts[i].PortNumber); - } - printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n", - p->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); - j = p->id; - mpt_landev[j] = dev; - dlprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n", - dev, j, mpt_landev[j])); - - } - } - + 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) { - int i; - + mpt_device_driver_deregister(MPTLAN_DRIVER); mpt_reset_deregister(LanCtx); - for (i = 0; mpt_landev[i] != NULL; i++) { - struct net_device *dev = mpt_landev[i]; - - printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n", - IOC_AND_NETDEV_NAMES_s_s(dev)); - unregister_netdev(dev); - free_netdev(dev); - mpt_landev[i] = NULL; - } - if (LanCtx >= 0) { mpt_deregister(LanCtx); LanCtx = -1; mpt_lan_index = 0; } - - /* deregister any send/receive handler structs. I2Oism? */ } -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - module_init(mpt_lan_init); module_exit(mpt_lan_exit);