diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/message/fusion/mptlan.c | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/message/fusion/mptlan.c')
-rw-r--r-- | ANDROID_3.4.5/drivers/message/fusion/mptlan.c | 1544 |
1 files changed, 0 insertions, 1544 deletions
diff --git a/ANDROID_3.4.5/drivers/message/fusion/mptlan.c b/ANDROID_3.4.5/drivers/message/fusion/mptlan.c deleted file mode 100644 index cbe96072..00000000 --- a/ANDROID_3.4.5/drivers/message/fusion/mptlan.c +++ /dev/null @@ -1,1544 +0,0 @@ -/* - * linux/drivers/message/fusion/mptlan.c - * IP Over Fibre Channel device driver. - * For use with LSI Fibre Channel PCI chip/adapters - * running LSI Fusion MPT (Message Passing Technology) firmware. - * - * Copyright (c) 2000-2008 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - */ -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - NO WARRANTY - THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - solely responsible for determining the appropriateness of using and - distributing the Program and assumes all risks associated with its - exercise of rights under this Agreement, including but not limited to - the risks and costs of program errors, damage to or loss of data, - programs or equipment, and unavailability or interruption of operations. - - DISCLAIMER OF LIABILITY - NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Define statements used for debugging - */ -//#define MPT_LAN_IO_DEBUG - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -#include "mptlan.h" -#include <linux/init.h> -#include <linux/module.h> -#include <linux/fs.h> -#include <linux/sched.h> -#include <linux/slab.h> - -#define my_VERSION MPT_LINUX_VERSION_COMMON -#define MYNAM "mptlan" - -MODULE_LICENSE("GPL"); -MODULE_VERSION(my_VERSION); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * MPT LAN message sizes without variable part. - */ -#define MPT_LAN_RECEIVE_POST_REQUEST_SIZE \ - (sizeof(LANReceivePostRequest_t) - sizeof(SGE_MPI_UNION)) - -#define MPT_LAN_TRANSACTION32_SIZE \ - (sizeof(SGETransaction32_t) - sizeof(u32)) - -/* - * Fusion MPT LAN private structures - */ - -struct BufferControl { - struct sk_buff *skb; - dma_addr_t dma; - unsigned int len; -}; - -struct mpt_lan_priv { - MPT_ADAPTER *mpt_dev; - u8 pnum; /* Port number in the IOC. This is not a Unix network port! */ - - atomic_t buckets_out; /* number of unused buckets on IOC */ - int bucketthresh; /* Send more when this many left */ - - int *mpt_txfidx; /* Free Tx Context list */ - int mpt_txfidx_tail; - spinlock_t txfidx_lock; - - int *mpt_rxfidx; /* Free Rx Context list */ - int mpt_rxfidx_tail; - spinlock_t rxfidx_lock; - - struct BufferControl *RcvCtl; /* Receive BufferControl structs */ - struct BufferControl *SendCtl; /* Send BufferControl structs */ - - int max_buckets_out; /* Max buckets to send to IOC */ - int tx_max_out; /* IOC's Tx queue len */ - - u32 total_posted; - u32 total_received; - - struct delayed_work post_buckets_task; - struct net_device *dev; - unsigned long post_buckets_active; -}; - -struct mpt_lan_ohdr { - u16 dtype; - u8 daddr[FC_ALEN]; - u16 stype; - u8 saddr[FC_ALEN]; -}; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ - -/* - * Forward protos... - */ -static int lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, - MPT_FRAME_HDR *reply); -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(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); -static int mpt_lan_receive_post_reply(struct net_device *dev, - LANReceivePostReply_t *pRecvRep); -static int mpt_lan_send_turbo(struct net_device *dev, u32 tmsg); -static int mpt_lan_send_reply(struct net_device *dev, - LANSendReply_t *pSendRep); -static int mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase); -static int mpt_lan_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply); -static unsigned short mpt_lan_type_trans(struct sk_buff *skb, - struct net_device *dev); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Fusion MPT LAN private data - */ -static u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS; - -static u32 max_buckets_out = 127; -static u32 tx_max_out_p = 127 - 16; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/** - * lan_reply - Handle all data sent from the hardware. - * @ioc: Pointer to MPT_ADAPTER structure - * @mf: Pointer to original MPT request frame (NULL if TurboReply) - * @reply: Pointer to MPT reply frame - * - * Returns 1 indicating original alloc'd request frame ptr - * should be freed, or 0 if it shouldn't. - */ -static int -lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) -{ - struct net_device *dev = ioc->netdev; - int FreeReqFrame = 0; - - dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n", - IOC_AND_NETDEV_NAMES_s_s(dev))); - -// dioprintk((KERN_INFO MYNAM "@lan_reply: mf = %p, reply = %p\n", -// mf, reply)); - - if (mf == NULL) { - u32 tmsg = CAST_PTR_TO_U32(reply); - - dioprintk((KERN_INFO MYNAM ": %s/%s: @lan_reply, tmsg %08x\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - tmsg)); - - switch (GET_LAN_FORM(tmsg)) { - - // NOTE! (Optimization) First case here is now caught in - // mptbase.c::mpt_interrupt() routine and callcack here - // is now skipped for this case! -#if 0 - case LAN_REPLY_FORM_MESSAGE_CONTEXT: -// dioprintk((KERN_INFO MYNAM "/lan_reply: " -// "MessageContext turbo reply received\n")); - FreeReqFrame = 1; - break; -#endif - - case LAN_REPLY_FORM_SEND_SINGLE: -// dioprintk((MYNAM "/lan_reply: " -// "calling mpt_lan_send_reply (turbo)\n")); - - // 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) - // would Oops because mf has already been set - // to NULL. So after return from this func, - // mpt_interrupt() will attempt to put (NULL) mf ptr - // item back onto its adapter FreeQ - Oops!:-( - // It's Ok, since mpt_lan_send_turbo() *currently* - // always returns 0, but..., just in case: - - (void) mpt_lan_send_turbo(dev, tmsg); - FreeReqFrame = 0; - - break; - - case LAN_REPLY_FORM_RECEIVE_SINGLE: -// dioprintk((KERN_INFO MYNAM "@lan_reply: " -// "rcv-Turbo = %08x\n", tmsg)); - mpt_lan_receive_post_turbo(dev, tmsg); - break; - - default: - printk (KERN_ERR MYNAM "/lan_reply: Got a turbo reply " - "that I don't know what to do with\n"); - - /* CHECKME! Hmmm... FreeReqFrame is 0 here; is that right? */ - - break; - } - - return FreeReqFrame; - } - -// msg = (u32 *) reply; -// dioprintk((KERN_INFO MYNAM "@lan_reply: msg = %08x %08x %08x %08x\n", -// le32_to_cpu(msg[0]), le32_to_cpu(msg[1]), -// le32_to_cpu(msg[2]), le32_to_cpu(msg[3]))); -// dioprintk((KERN_INFO MYNAM "@lan_reply: Function = %02xh\n", -// reply->u.hdr.Function)); - - switch (reply->u.hdr.Function) { - - case MPI_FUNCTION_LAN_SEND: - { - LANSendReply_t *pSendRep; - - pSendRep = (LANSendReply_t *) reply; - FreeReqFrame = mpt_lan_send_reply(dev, pSendRep); - break; - } - - case MPI_FUNCTION_LAN_RECEIVE: - { - LANReceivePostReply_t *pRecvRep; - - pRecvRep = (LANReceivePostReply_t *) reply; - if (pRecvRep->NumberOfContexts) { - mpt_lan_receive_post_reply(dev, pRecvRep); - if (!(pRecvRep->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) - FreeReqFrame = 1; - } else - dioprintk((KERN_INFO MYNAM "@lan_reply: zero context " - "ReceivePostReply received.\n")); - break; - } - - case MPI_FUNCTION_LAN_RESET: - /* Just a default reply. Might want to check it to - * make sure that everything went ok. - */ - FreeReqFrame = 1; - break; - - case MPI_FUNCTION_EVENT_NOTIFICATION: - case MPI_FUNCTION_EVENT_ACK: - /* _EVENT_NOTIFICATION should NOT come down this path any more. - * Should be routed to mpt_lan_event_process(), but just in case... - */ - FreeReqFrame = 1; - break; - - default: - printk (KERN_ERR MYNAM "/lan_reply: Got a non-turbo " - "reply that I don't know what to do with\n"); - - /* CHECKME! Hmmm... FreeReqFrame is 0 here; is that right? */ - FreeReqFrame = 1; - - break; - } - - return FreeReqFrame; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) -{ - 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" : ( - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); - - if (priv->mpt_rxfidx == NULL) - return (1); - - if (reset_phase == MPT_IOC_SETUP_RESET) { - ; - } else if (reset_phase == MPT_IOC_PRE_RESET) { - int i; - unsigned long flags; - - netif_stop_queue(dev); - - dlprintk ((KERN_INFO "mptlan/ioc_reset: called netif_stop_queue for %s.\n", dev->name)); - - atomic_set(&priv->buckets_out, 0); - - /* Reset Rx Free Tail index and re-populate the queue. */ - spin_lock_irqsave(&priv->rxfidx_lock, flags); - priv->mpt_rxfidx_tail = -1; - for (i = 0; i < priv->max_buckets_out; i++) - priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; - spin_unlock_irqrestore(&priv->rxfidx_lock, flags); - } else { - mpt_lan_post_receive_buckets(priv); - netif_wake_queue(dev); - } - - return 1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) -{ - dlprintk((KERN_INFO MYNAM ": MPT event routed to LAN driver!\n")); - - switch (le32_to_cpu(pEvReply->Event)) { - case MPI_EVENT_NONE: /* 00 */ - case MPI_EVENT_LOG_DATA: /* 01 */ - case MPI_EVENT_STATE_CHANGE: /* 02 */ - case MPI_EVENT_UNIT_ATTENTION: /* 03 */ - case MPI_EVENT_IOC_BUS_RESET: /* 04 */ - case MPI_EVENT_EXT_BUS_RESET: /* 05 */ - case MPI_EVENT_RESCAN: /* 06 */ - /* Ok, do we need to do anything here? As far as - I can tell, this is when a new device gets added - to the loop. */ - case MPI_EVENT_LINK_STATUS_CHANGE: /* 07 */ - case MPI_EVENT_LOOP_STATE_CHANGE: /* 08 */ - case MPI_EVENT_LOGOUT: /* 09 */ - case MPI_EVENT_EVENT_CHANGE: /* 0A */ - default: - break; - } - - /* - * NOTE: pEvent->AckRequired handling now done in mptbase.c; - * Do NOT do it here now! - */ - - return 1; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_open(struct net_device *dev) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - int i; - - if (mpt_lan_reset(dev) != 0) { - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - - printk (KERN_WARNING MYNAM "/lan_open: lan_reset failed."); - - if (mpt_dev->active) - printk ("The ioc is active. Perhaps it needs to be" - " reset?\n"); - else - printk ("The ioc in inactive, most likely in the " - "process of being reset. Please try again in " - "a moment.\n"); - } - - priv->mpt_txfidx = kmalloc(priv->tx_max_out * sizeof(int), GFP_KERNEL); - if (priv->mpt_txfidx == NULL) - goto out; - priv->mpt_txfidx_tail = -1; - - 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++) - priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i; - - dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n")); - - priv->mpt_rxfidx = kmalloc(priv->max_buckets_out * sizeof(int), - GFP_KERNEL); - if (priv->mpt_rxfidx == NULL) - goto out_SendCtl; - priv->mpt_rxfidx_tail = -1; - - 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++) - priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i; - -/**/ dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - ")); -/**/ for (i = 0; i < priv->tx_max_out; i++) -/**/ dlprintk((" %xh", priv->mpt_txfidx[i])); -/**/ dlprintk(("\n")); - - dlprintk((KERN_INFO MYNAM "/lo: Finished initializing RcvCtl\n")); - - mpt_lan_post_receive_buckets(priv); - printk(KERN_INFO MYNAM ": %s/%s: interface up & active\n", - IOC_AND_NETDEV_NAMES_s_s(dev)); - - if (mpt_event_register(LanCtx, mpt_lan_event_process) != 0) { - printk (KERN_WARNING MYNAM "/lo: Unable to register for Event" - " Notifications. This is a bad thing! We're not going " - "to go ahead, but I'd be leery of system stability at " - "this point.\n"); - } - - netif_start_queue(dev); - dlprintk((KERN_INFO MYNAM "/lo: Done.\n")); - - return 0; -out_mpt_rxfidx: - kfree(priv->mpt_rxfidx); - priv->mpt_rxfidx = NULL; -out_SendCtl: - kfree(priv->SendCtl); - priv->SendCtl = NULL; -out_mpt_txfidx: - kfree(priv->mpt_txfidx); - priv->mpt_txfidx = NULL; -out: return -ENOMEM; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Send a LanReset message to the FW. This should result in the FW returning - any buckets it still has. */ -static int -mpt_lan_reset(struct net_device *dev) -{ - MPT_FRAME_HDR *mf; - LANResetRequest_t *pResetReq; - struct mpt_lan_priv *priv = netdev_priv(dev); - - mf = mpt_get_msg_frame(LanCtx, priv->mpt_dev); - - if (mf == NULL) { -/* dlprintk((KERN_ERR MYNAM "/reset: Evil funkiness abounds! " - "Unable to allocate a request frame.\n")); -*/ - return -1; - } - - pResetReq = (LANResetRequest_t *) mf; - - pResetReq->Function = MPI_FUNCTION_LAN_RESET; - pResetReq->ChainOffset = 0; - pResetReq->Reserved = 0; - pResetReq->PortNumber = priv->pnum; - pResetReq->MsgFlags = 0; - pResetReq->Reserved2 = 0; - - mpt_put_msg_frame(LanCtx, priv->mpt_dev, mf); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_close(struct net_device *dev) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - unsigned long timeout; - int i; - - dlprintk((KERN_INFO MYNAM ": mpt_lan_close called\n")); - - mpt_event_deregister(LanCtx); - - dlprintk((KERN_INFO MYNAM ":lan_close: Posted %d buckets " - "since driver was loaded, %d still out\n", - priv->total_posted,atomic_read(&priv->buckets_out))); - - netif_stop_queue(dev); - - mpt_lan_reset(dev); - - 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) { -/**/ dlprintk((KERN_INFO MYNAM "/lan_close: bucket %05x " -/**/ "is still out\n", i)); - pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[i].dma, - priv->RcvCtl[i].len, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(priv->RcvCtl[i].skb); - } - } - - kfree(priv->RcvCtl); - kfree(priv->mpt_rxfidx); - - for (i = 0; i < priv->tx_max_out; i++) { - if (priv->SendCtl[i].skb != NULL) { - pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[i].dma, - priv->SendCtl[i].len, - PCI_DMA_TODEVICE); - dev_kfree_skb(priv->SendCtl[i].skb); - } - } - - kfree(priv->SendCtl); - kfree(priv->mpt_txfidx); - - atomic_set(&priv->buckets_out, 0); - - printk(KERN_INFO MYNAM ": %s/%s: interface down & inactive\n", - IOC_AND_NETDEV_NAMES_s_s(dev)); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < MPT_LAN_MIN_MTU) || (new_mtu > MPT_LAN_MAX_MTU)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Tx timeout handler. */ -static void -mpt_lan_tx_timeout(struct net_device *dev) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - - if (mpt_dev->active) { - dlprintk (("mptlan/tx_timeout: calling netif_wake_queue for %s.\n", dev->name)); - netif_wake_queue(dev); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -//static inline int -static int -mpt_lan_send_turbo(struct net_device *dev, u32 tmsg) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - struct sk_buff *sent; - unsigned long flags; - u32 ctx; - - ctx = GET_LAN_BUFFER_CONTEXT(tmsg); - sent = priv->SendCtl[ctx].skb; - - dev->stats.tx_packets++; - dev->stats.tx_bytes += sent->len; - - dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - __func__, sent)); - - priv->SendCtl[ctx].skb = NULL; - pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma, - priv->SendCtl[ctx].len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(sent); - - spin_lock_irqsave(&priv->txfidx_lock, flags); - priv->mpt_txfidx[++priv->mpt_txfidx_tail] = ctx; - spin_unlock_irqrestore(&priv->txfidx_lock, flags); - - netif_wake_queue(dev); - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_send_reply(struct net_device *dev, LANSendReply_t *pSendRep) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - struct sk_buff *sent; - unsigned long flags; - int FreeReqFrame = 0; - u32 *pContext; - u32 ctx; - u8 count; - - count = pSendRep->NumberOfContexts; - - dioprintk((KERN_INFO MYNAM ": send_reply: IOCStatus: %04x\n", - le16_to_cpu(pSendRep->IOCStatus))); - - /* Add check for Loginfo Flag in IOCStatus */ - - switch (le16_to_cpu(pSendRep->IOCStatus) & MPI_IOCSTATUS_MASK) { - case MPI_IOCSTATUS_SUCCESS: - dev->stats.tx_packets += count; - break; - - case MPI_IOCSTATUS_LAN_CANCELED: - case MPI_IOCSTATUS_LAN_TRANSMIT_ABORTED: - break; - - case MPI_IOCSTATUS_INVALID_SGL: - dev->stats.tx_errors += count; - printk (KERN_ERR MYNAM ": %s/%s: ERROR - Invalid SGL sent to IOC!\n", - IOC_AND_NETDEV_NAMES_s_s(dev)); - goto out; - - default: - dev->stats.tx_errors += count; - break; - } - - pContext = &pSendRep->BufferContext; - - spin_lock_irqsave(&priv->txfidx_lock, flags); - while (count > 0) { - ctx = GET_LAN_BUFFER_CONTEXT(le32_to_cpu(*pContext)); - - sent = priv->SendCtl[ctx].skb; - dev->stats.tx_bytes += sent->len; - - dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, skb %p sent.\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - __func__, sent)); - - priv->SendCtl[ctx].skb = NULL; - pci_unmap_single(mpt_dev->pcidev, priv->SendCtl[ctx].dma, - priv->SendCtl[ctx].len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(sent); - - priv->mpt_txfidx[++priv->mpt_txfidx_tail] = ctx; - - pContext++; - count--; - } - spin_unlock_irqrestore(&priv->txfidx_lock, flags); - -out: - if (!(pSendRep->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) - FreeReqFrame = 1; - - netif_wake_queue(dev); - return FreeReqFrame; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_sdu_send (struct sk_buff *skb, struct net_device *dev) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - MPT_FRAME_HDR *mf; - LANSendRequest_t *pSendReq; - SGETransaction32_t *pTrans; - SGESimple64_t *pSimple; - const unsigned char *mac; - dma_addr_t dma; - unsigned long flags; - int ctx; - u16 cur_naa = 0x1000; - - dioprintk((KERN_INFO MYNAM ": %s called, skb_addr = %p\n", - __func__, skb)); - - spin_lock_irqsave(&priv->txfidx_lock, flags); - if (priv->mpt_txfidx_tail < 0) { - netif_stop_queue(dev); - spin_unlock_irqrestore(&priv->txfidx_lock, flags); - - printk (KERN_ERR "%s: no tx context available: %u\n", - __func__, priv->mpt_txfidx_tail); - return NETDEV_TX_BUSY; - } - - mf = mpt_get_msg_frame(LanCtx, mpt_dev); - if (mf == NULL) { - netif_stop_queue(dev); - spin_unlock_irqrestore(&priv->txfidx_lock, flags); - - printk (KERN_ERR "%s: Unable to alloc request frame\n", - __func__); - return NETDEV_TX_BUSY; - } - - ctx = priv->mpt_txfidx[priv->mpt_txfidx_tail--]; - spin_unlock_irqrestore(&priv->txfidx_lock, flags); - -// dioprintk((KERN_INFO MYNAM ": %s/%s: Creating new msg frame (send).\n", -// IOC_AND_NETDEV_NAMES_s_s(dev))); - - pSendReq = (LANSendRequest_t *) mf; - - /* Set the mac.raw pointer, since this apparently isn't getting - * done before we get the skb. Pull the data pointer past the mac data. - */ - skb_reset_mac_header(skb); - skb_pull(skb, 12); - - dma = pci_map_single(mpt_dev->pcidev, skb->data, skb->len, - PCI_DMA_TODEVICE); - - priv->SendCtl[ctx].skb = skb; - priv->SendCtl[ctx].dma = dma; - priv->SendCtl[ctx].len = skb->len; - - /* Message Header */ - pSendReq->Reserved = 0; - pSendReq->Function = MPI_FUNCTION_LAN_SEND; - pSendReq->ChainOffset = 0; - pSendReq->Reserved2 = 0; - pSendReq->MsgFlags = 0; - pSendReq->PortNumber = priv->pnum; - - /* Transaction Context Element */ - pTrans = (SGETransaction32_t *) pSendReq->SG_List; - - /* No Flags, 8 bytes of Details, 32bit Context (bloody turbo replies) */ - pTrans->ContextSize = sizeof(u32); - pTrans->DetailsLength = 2 * sizeof(u32); - pTrans->Flags = 0; - pTrans->TransactionContext[0] = cpu_to_le32(ctx); - -// dioprintk((KERN_INFO MYNAM ": %s/%s: BC = %08x, skb = %p, buff = %p\n", -// IOC_AND_NETDEV_NAMES_s_s(dev), -// ctx, skb, skb->data)); - - mac = skb_mac_header(skb); - - pTrans->TransactionDetails[0] = cpu_to_le32((cur_naa << 16) | - (mac[0] << 8) | - (mac[1] << 0)); - pTrans->TransactionDetails[1] = cpu_to_le32((mac[2] << 24) | - (mac[3] << 16) | - (mac[4] << 8) | - (mac[5] << 0)); - - pSimple = (SGESimple64_t *) &pTrans->TransactionDetails[2]; - - /* If we ever decide to send more than one Simple SGE per LANSend, then - we will need to make sure that LAST_ELEMENT only gets set on the - last one. Otherwise, bad voodoo and evil funkiness will commence. */ - pSimple->FlagsLength = cpu_to_le32( - ((MPI_SGE_FLAGS_LAST_ELEMENT | - MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_SIMPLE_ELEMENT | - MPI_SGE_FLAGS_SYSTEM_ADDRESS | - MPI_SGE_FLAGS_HOST_TO_IOC | - MPI_SGE_FLAGS_64_BIT_ADDRESSING | - MPI_SGE_FLAGS_END_OF_LIST) << MPI_SGE_FLAGS_SHIFT) | - skb->len); - pSimple->Address.Low = cpu_to_le32((u32) dma); - if (sizeof(dma_addr_t) > sizeof(u32)) - pSimple->Address.High = cpu_to_le32((u32) ((u64) dma >> 32)); - else - pSimple->Address.High = 0; - - mpt_put_msg_frame (LanCtx, mpt_dev, mf); - dev->trans_start = jiffies; - - dioprintk((KERN_INFO MYNAM ": %s/%s: Sending packet. FlagsLength = %08x.\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - le32_to_cpu(pSimple->FlagsLength))); - - return NETDEV_TX_OK; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -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 - */ -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - - if (test_and_set_bit(0, &priv->post_buckets_active) == 0) { - if (priority) { - 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 " - "timer.\n")); - } - dioprintk((KERN_INFO MYNAM ": %s/%s: Queued post_buckets task.\n", - IOC_AND_NETDEV_NAMES_s_s(dev) )); - } -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_receive_skb(struct net_device *dev, struct sk_buff *skb) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - - skb->protocol = mpt_lan_type_trans(skb, dev); - - dioprintk((KERN_INFO MYNAM ": %s/%s: Incoming packet (%d bytes) " - "delivered to upper level.\n", - IOC_AND_NETDEV_NAMES_s_s(dev), skb->len)); - - dev->stats.rx_bytes += skb->len; - dev->stats.rx_packets++; - - skb->dev = dev; - netif_rx(skb); - - dioprintk((MYNAM "/receive_skb: %d buckets remaining\n", - atomic_read(&priv->buckets_out))); - - if (atomic_read(&priv->buckets_out) < priv->bucketthresh) - mpt_lan_wake_post_buckets_task(dev, 1); - - dioprintk((KERN_INFO MYNAM "/receive_post_reply: %d buckets " - "remaining, %d received back since sod\n", - atomic_read(&priv->buckets_out), priv->total_received)); - - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -//static inline int -static int -mpt_lan_receive_post_turbo(struct net_device *dev, u32 tmsg) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - struct sk_buff *skb, *old_skb; - unsigned long flags; - u32 ctx, len; - - ctx = GET_LAN_BUCKET_CONTEXT(tmsg); - skb = priv->RcvCtl[ctx].skb; - - len = GET_LAN_PACKET_LENGTH(tmsg); - - if (len < MPT_LAN_RX_COPYBREAK) { - old_skb = skb; - - skb = (struct sk_buff *)dev_alloc_skb(len); - if (!skb) { - printk (KERN_ERR MYNAM ": %s/%s: ERROR - Can't allocate skb! (%s@%d)\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - __FILE__, __LINE__); - return -ENOMEM; - } - - pci_dma_sync_single_for_cpu(mpt_dev->pcidev, priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE); - - skb_copy_from_linear_data(old_skb, skb_put(skb, len), len); - - pci_dma_sync_single_for_device(mpt_dev->pcidev, priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE); - goto out; - } - - skb_put(skb, len); - - priv->RcvCtl[ctx].skb = NULL; - - pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE); - -out: - spin_lock_irqsave(&priv->rxfidx_lock, flags); - priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx; - spin_unlock_irqrestore(&priv->rxfidx_lock, flags); - - atomic_dec(&priv->buckets_out); - priv->total_received++; - - return mpt_lan_receive_skb(dev, skb); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_receive_post_free(struct net_device *dev, - LANReceivePostReply_t *pRecvRep) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - unsigned long flags; - struct sk_buff *skb; - u32 ctx; - int count; - int i; - - count = pRecvRep->NumberOfContexts; - -/**/ dlprintk((KERN_INFO MYNAM "/receive_post_reply: " - "IOC returned %d buckets, freeing them...\n", count)); - - spin_lock_irqsave(&priv->rxfidx_lock, flags); - for (i = 0; i < count; i++) { - ctx = le32_to_cpu(pRecvRep->BucketContext[i]); - - skb = priv->RcvCtl[ctx].skb; - -// dlprintk((KERN_INFO MYNAM ": %s: dev_name = %s\n", -// IOC_AND_NETDEV_NAMES_s_s(dev))); -// dlprintk((KERN_INFO MYNAM "@rpr[2], priv = %p, buckets_out addr = %p", -// priv, &(priv->buckets_out))); -// dlprintk((KERN_INFO MYNAM "@rpr[2] TC + 3\n")); - - priv->RcvCtl[ctx].skb = NULL; - pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(skb); - - priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx; - } - spin_unlock_irqrestore(&priv->rxfidx_lock, flags); - - atomic_sub(count, &priv->buckets_out); - -// for (i = 0; i < priv->max_buckets_out; i++) -// if (priv->RcvCtl[i].skb != NULL) -// dlprintk((KERN_INFO MYNAM "@rpr: bucket %03x " -// "is still out\n", i)); - -/* dlprintk((KERN_INFO MYNAM "/receive_post_reply: freed %d buckets\n", - count)); -*/ -/**/ dlprintk((KERN_INFO MYNAM "@receive_post_reply: %d buckets " -/**/ "remaining, %d received back since sod.\n", -/**/ atomic_read(&priv->buckets_out), priv->total_received)); - return 0; -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int -mpt_lan_receive_post_reply(struct net_device *dev, - LANReceivePostReply_t *pRecvRep) -{ - struct mpt_lan_priv *priv = netdev_priv(dev); - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - struct sk_buff *skb, *old_skb; - unsigned long flags; - u32 len, ctx, offset; - u32 remaining = le32_to_cpu(pRecvRep->BucketsRemaining); - int count; - int i, l; - - dioprintk((KERN_INFO MYNAM ": mpt_lan_receive_post_reply called\n")); - dioprintk((KERN_INFO MYNAM ": receive_post_reply: IOCStatus: %04x\n", - le16_to_cpu(pRecvRep->IOCStatus))); - - if ((le16_to_cpu(pRecvRep->IOCStatus) & MPI_IOCSTATUS_MASK) == - MPI_IOCSTATUS_LAN_CANCELED) - return mpt_lan_receive_post_free(dev, pRecvRep); - - len = le32_to_cpu(pRecvRep->PacketLength); - if (len == 0) { - printk (KERN_ERR MYNAM ": %s/%s: ERROR - Got a non-TURBO " - "ReceivePostReply w/ PacketLength zero!\n", - IOC_AND_NETDEV_NAMES_s_s(dev)); - printk (KERN_ERR MYNAM ": MsgFlags = %02x, IOCStatus = %04x\n", - pRecvRep->MsgFlags, le16_to_cpu(pRecvRep->IOCStatus)); - return -1; - } - - ctx = le32_to_cpu(pRecvRep->BucketContext[0]); - count = pRecvRep->NumberOfContexts; - skb = priv->RcvCtl[ctx].skb; - - offset = le32_to_cpu(pRecvRep->PacketOffset); -// if (offset != 0) { -// printk (KERN_INFO MYNAM ": %s/%s: Got a ReceivePostReply " -// "w/ PacketOffset %u\n", -// IOC_AND_NETDEV_NAMES_s_s(dev), -// offset); -// } - - dioprintk((KERN_INFO MYNAM ": %s/%s: @rpr, offset = %d, len = %d\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - offset, len)); - - if (count > 1) { - int szrem = len; - -// dioprintk((KERN_INFO MYNAM ": %s/%s: Multiple buckets returned " -// "for single packet, concatenating...\n", -// IOC_AND_NETDEV_NAMES_s_s(dev))); - - skb = (struct sk_buff *)dev_alloc_skb(len); - if (!skb) { - printk (KERN_ERR MYNAM ": %s/%s: ERROR - Can't allocate skb! (%s@%d)\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - __FILE__, __LINE__); - return -ENOMEM; - } - - spin_lock_irqsave(&priv->rxfidx_lock, flags); - for (i = 0; i < count; i++) { - - ctx = le32_to_cpu(pRecvRep->BucketContext[i]); - old_skb = priv->RcvCtl[ctx].skb; - - l = priv->RcvCtl[ctx].len; - if (szrem < l) - l = szrem; - -// dioprintk((KERN_INFO MYNAM ": %s/%s: Buckets = %d, len = %u\n", -// IOC_AND_NETDEV_NAMES_s_s(dev), -// i, l)); - - pci_dma_sync_single_for_cpu(mpt_dev->pcidev, - priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(old_skb, skb_put(skb, l), l); - - pci_dma_sync_single_for_device(mpt_dev->pcidev, - priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, - PCI_DMA_FROMDEVICE); - - priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx; - szrem -= l; - } - spin_unlock_irqrestore(&priv->rxfidx_lock, flags); - - } else if (len < MPT_LAN_RX_COPYBREAK) { - - old_skb = skb; - - skb = (struct sk_buff *)dev_alloc_skb(len); - if (!skb) { - printk (KERN_ERR MYNAM ": %s/%s: ERROR - Can't allocate skb! (%s@%d)\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - __FILE__, __LINE__); - return -ENOMEM; - } - - pci_dma_sync_single_for_cpu(mpt_dev->pcidev, - priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, - PCI_DMA_FROMDEVICE); - - skb_copy_from_linear_data(old_skb, skb_put(skb, len), len); - - pci_dma_sync_single_for_device(mpt_dev->pcidev, - priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, - PCI_DMA_FROMDEVICE); - - spin_lock_irqsave(&priv->rxfidx_lock, flags); - priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx; - spin_unlock_irqrestore(&priv->rxfidx_lock, flags); - - } else { - spin_lock_irqsave(&priv->rxfidx_lock, flags); - - priv->RcvCtl[ctx].skb = NULL; - - pci_unmap_single(mpt_dev->pcidev, priv->RcvCtl[ctx].dma, - priv->RcvCtl[ctx].len, PCI_DMA_FROMDEVICE); - priv->RcvCtl[ctx].dma = 0; - - priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx; - spin_unlock_irqrestore(&priv->rxfidx_lock, flags); - - skb_put(skb,len); - } - - atomic_sub(count, &priv->buckets_out); - priv->total_received += count; - - if (priv->mpt_rxfidx_tail >= MPT_LAN_MAX_BUCKETS_OUT) { - printk (KERN_ERR MYNAM ": %s/%s: Yoohoo! mpt_rxfidx_tail = %d, " - "MPT_LAN_MAX_BUCKETS_OUT = %d\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - priv->mpt_rxfidx_tail, - MPT_LAN_MAX_BUCKETS_OUT); - - return -1; - } - - if (remaining == 0) - printk (KERN_WARNING MYNAM ": %s/%s: WARNING - IOC out of buckets! " - "(priv->buckets_out = %d)\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - atomic_read(&priv->buckets_out)); - else if (remaining < 10) - printk (KERN_INFO MYNAM ": %s/%s: IOC says %d buckets left. " - "(priv->buckets_out = %d)\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - remaining, atomic_read(&priv->buckets_out)); - - if ((remaining < priv->bucketthresh) && - ((atomic_read(&priv->buckets_out) - remaining) > - MPT_LAN_BUCKETS_REMAIN_MISMATCH_THRESH)) { - - printk (KERN_WARNING MYNAM " Mismatch between driver's " - "buckets_out count and fw's BucketsRemaining " - "count has crossed the threshold, issuing a " - "LanReset to clear the fw's hashtable. You may " - "want to check your /var/log/messages for \"CRC " - "error\" event notifications.\n"); - - mpt_lan_reset(dev); - mpt_lan_wake_post_buckets_task(dev, 0); - } - - return mpt_lan_receive_skb(dev, skb); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* Simple SGE's only at the moment */ - -static void -mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv) -{ - struct net_device *dev = priv->dev; - MPT_ADAPTER *mpt_dev = priv->mpt_dev; - MPT_FRAME_HDR *mf; - LANReceivePostRequest_t *pRecvReq; - SGETransaction32_t *pTrans; - SGESimple64_t *pSimple; - struct sk_buff *skb; - dma_addr_t dma; - u32 curr, buckets, count, max; - u32 len = (dev->mtu + dev->hard_header_len + 4); - unsigned long flags; - int i; - - curr = atomic_read(&priv->buckets_out); - buckets = (priv->max_buckets_out - curr); - - dioprintk((KERN_INFO MYNAM ": %s/%s: @%s, Start_buckets = %u, buckets_out = %u\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - __func__, buckets, curr)); - - max = (mpt_dev->req_sz - MPT_LAN_RECEIVE_POST_REQUEST_SIZE) / - (MPT_LAN_TRANSACTION32_SIZE + sizeof(SGESimple64_t)); - - while (buckets) { - mf = mpt_get_msg_frame(LanCtx, mpt_dev); - if (mf == NULL) { - printk (KERN_ERR "%s: Unable to alloc request frame\n", - __func__); - dioprintk((KERN_ERR "%s: %u buckets remaining\n", - __func__, buckets)); - goto out; - } - pRecvReq = (LANReceivePostRequest_t *) mf; - - i = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - mpt_dev->RequestNB[i] = 0; - count = buckets; - if (count > max) - count = max; - - pRecvReq->Function = MPI_FUNCTION_LAN_RECEIVE; - pRecvReq->ChainOffset = 0; - pRecvReq->MsgFlags = 0; - pRecvReq->PortNumber = priv->pnum; - - pTrans = (SGETransaction32_t *) pRecvReq->SG_List; - pSimple = NULL; - - for (i = 0; i < count; i++) { - int ctx; - - spin_lock_irqsave(&priv->rxfidx_lock, flags); - if (priv->mpt_rxfidx_tail < 0) { - printk (KERN_ERR "%s: Can't alloc context\n", - __func__); - spin_unlock_irqrestore(&priv->rxfidx_lock, - 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", - __func__); - 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", -/**/ __func__); - 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", - __func__, buckets, atomic_read(&priv->buckets_out))); - dioprintk((KERN_INFO MYNAM "/%s: Posted %u buckets and received %u back\n", - __func__, priv->total_posted, priv->total_received)); - - 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 const struct net_device_ops mpt_netdev_ops = { - .ndo_open = mpt_lan_open, - .ndo_stop = mpt_lan_close, - .ndo_start_xmit = mpt_lan_sdu_send, - .ndo_change_mtu = mpt_lan_change_mtu, - .ndo_tx_timeout = mpt_lan_tx_timeout, -}; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static struct net_device * -mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) -{ - struct net_device *dev; - struct mpt_lan_priv *priv; - u8 HWaddr[FC_ALEN], *a; - - dev = alloc_fcdev(sizeof(struct mpt_lan_priv)); - if (!dev) - return NULL; - - dev->mtu = MPT_LAN_MTU; - - priv = netdev_priv(dev); - - priv->dev = dev; - priv->mpt_dev = mpt_dev; - priv->pnum = pnum; - - 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", - __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); - - /* 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->netdev_ops = &mpt_netdev_ops; - dev->watchdog_timeo = MPT_LAN_TX_TIMEOUT; - - dlprintk((KERN_INFO MYNAM ": Finished registering dev " - "and setting initial values\n")); - - if (register_netdev(dev) != 0) { - free_netdev(dev); - dev = NULL; - } - return dev; -} - -static int -mptlan_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 = %pM\n", - IOC_AND_NETDEV_NAMES_s_s(dev), - dev->dev_addr); - - ioc->netdev = dev; - - 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); - - LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER, - "lan_reply"); - if (LanCtx <= 0) { - printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n"); - return -EBUSY; - } - - 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")); - - mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER); - return 0; -} - -static void __exit mpt_lan_exit(void) -{ - mpt_device_driver_deregister(MPTLAN_DRIVER); - mpt_reset_deregister(LanCtx); - - if (LanCtx) { - mpt_deregister(LanCtx); - LanCtx = MPT_MAX_PROTOCOL_DRIVERS; - } -} - -module_init(mpt_lan_init); -module_exit(mpt_lan_exit); - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static unsigned short -mpt_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_reset_mac_header(skb); - 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 = %pM\n", - fch->saddr); - } - - 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; - - /* 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); -} - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ |