Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/721/?format=api
{ "id": 721, "url": "http://patchwork.ozlabs.org/api/patches/721/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/48D536CF.5030503@myri.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<48D536CF.5030503@myri.com>", "list_archive_url": null, "date": "2008-09-20T17:45:51", "name": "[RESEND,2.6.28] myri10ge: Add multiqueue TX support", "commit_ref": null, "pull_url": null, "state": "changes-requested", "archived": true, "hash": "c896e7755dc2d0fe3257ba012308f0a3d42454e1", "submitter": { "id": 345, "url": "http://patchwork.ozlabs.org/api/people/345/?format=api", "name": "Brice Goglin", "email": "brice@myri.com" }, "delegate": { "id": 36, "url": "http://patchwork.ozlabs.org/api/users/36/?format=api", "username": "jgarzik", "first_name": "Jeff", "last_name": "Garzik", "email": "jgarzik@pobox.com" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/48D536CF.5030503@myri.com/mbox/", "series": [], "comments": "http://patchwork.ozlabs.org/api/patches/721/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/721/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.176.167])\n\tby ozlabs.org (Postfix) with ESMTP id 2C05EDDDFF\n\tfor <patchwork-incoming@ozlabs.org>;\n\tSun, 21 Sep 2008 03:47:30 +1000 (EST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S1750900AbYITRrZ (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tSat, 20 Sep 2008 13:47:25 -0400", "(majordomo@vger.kernel.org) by vger.kernel.org id S1750851AbYITRrZ\n\t(ORCPT <rfc822; netdev-outgoing>); Sat, 20 Sep 2008 13:47:25 -0400", "from mailbox2.myri.com ([64.172.73.26]:1964 \"EHLO myri.com\"\n\trhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP\n\tid S1750779AbYITRrY (ORCPT <rfc822;netdev@vger.kernel.org>);\n\tSat, 20 Sep 2008 13:47:24 -0400", "from [172.31.134.203] (brice-ovpn.sw.myri.com [172.31.134.203])\n\tby myri.com (8.13.7+Sun/8.13.7) with ESMTP id m8KHkQ2m019598;\n\tSat, 20 Sep 2008 10:46:39 -0700 (PDT)" ], "Message-ID": "<48D536CF.5030503@myri.com>", "Date": "Sat, 20 Sep 2008 19:45:51 +0200", "From": "Brice Goglin <brice@myri.com>", "User-Agent": "Mozilla-Thunderbird 2.0.0.16 (X11/20080724)", "MIME-Version": "1.0", "To": "Jeff Garzik <jeff@garzik.org>, netdev@vger.kernel.org", "Subject": "[RESEND][PATCH 2.6.28] myri10ge: Add multiqueue TX support", "X-Enigmail-Version": "0.95.0", "Content-Type": "text/plain; charset=ISO-8859-1", "Content-Transfer-Encoding": "7bit", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "Add multiqueue TX support to myri10ge.\n \nSigned-off-by: Brice Goglin <brice@myri.com>\n\n \n struct myri10ge_tx_buf {\n \tstruct mcp_kreq_ether_send __iomem *lanai;\t/* lanai ptr for sendq */\n+\t__be32 __iomem *send_go;\t/* \"go\" doorbell ptr */\n+\t__be32 __iomem *send_stop;\t/* \"stop\" doorbell ptr */\n \tstruct mcp_kreq_ether_send *req_list;\t/* host shadow of sendq */\n \tchar *req_bytes;\n \tstruct myri10ge_tx_buffer_state *info;\n@@ -149,6 +154,7 @@ struct myri10ge_tx_buf {\n \tint done ____cacheline_aligned;\t/* transmit slots completed */\n \tint pkt_done;\t\t/* packets completed */\n \tint wake_queue;\n+\tint queue_active;\n };\n \n struct myri10ge_rx_done {\n@@ -420,6 +426,12 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,\n \t\t\treturn -ENOSYS;\n \t\t} else if (result == MXGEFW_CMD_ERROR_UNALIGNED) {\n \t\t\treturn -E2BIG;\n+\t\t} else if (result == MXGEFW_CMD_ERROR_RANGE &&\n+\t\t\t cmd == MXGEFW_CMD_ENABLE_RSS_QUEUES &&\n+\t\t\t (data->\n+\t\t\t data1 & MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES) !=\n+\t\t\t 0) {\n+\t\t\treturn -ERANGE;\n \t\t} else {\n \t\t\tdev_err(&mgp->pdev->dev,\n \t\t\t\t\"command %d failed, result = %d\\n\",\n@@ -949,9 +961,24 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)\n \t\t */\n \n \t\tcmd.data0 = mgp->num_slices;\n-\t\tcmd.data1 = 1;\t/* use MSI-X */\n+\t\tcmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;\n+\t\tif (mgp->dev->real_num_tx_queues > 1)\n+\t\t\tcmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;\n \t\tstatus = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,\n \t\t\t\t\t &cmd, 0);\n+\n+\t\t/* Firmware older than 1.4.32 only supports multiple\n+\t\t * RX queues, so if we get an error, first retry using a\n+\t\t * single TX queue before giving up */\n+\t\tif (status != 0 && mgp->dev->real_num_tx_queues > 1) {\n+\t\t\tmgp->dev->real_num_tx_queues = 1;\n+\t\t\tcmd.data0 = mgp->num_slices;\n+\t\t\tcmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;\n+\t\t\tstatus = myri10ge_send_cmd(mgp,\n+\t\t\t\t\t\t MXGEFW_CMD_ENABLE_RSS_QUEUES,\n+\t\t\t\t\t\t &cmd, 0);\n+\t\t}\n+\n \t\tif (status != 0) {\n \t\t\tdev_err(&mgp->pdev->dev,\n \t\t\t\t\"failed to set number of slices\\n\");\n@@ -1319,6 +1346,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)\n {\n \tstruct pci_dev *pdev = ss->mgp->pdev;\n \tstruct myri10ge_tx_buf *tx = &ss->tx;\n+\tstruct netdev_queue *dev_queue;\n \tstruct sk_buff *skb;\n \tint idx, len;\n \n@@ -1352,11 +1380,31 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)\n \t\t\t\t\t PCI_DMA_TODEVICE);\n \t\t}\n \t}\n+\n+\tdev_queue = netdev_get_tx_queue(ss->dev, ss - ss->mgp->ss);\n+\t/*\n+\t * Make a minimal effort to prevent the NIC from polling an\n+\t * idle tx queue. If we can't get the lock we leave the queue\n+\t * active. In this case, either a thread was about to start\n+\t * using the queue anyway, or we lost a race and the NIC will\n+\t * waste some of its resources polling an inactive queue for a\n+\t * while.\n+\t */\n+\n+\tif ((ss->mgp->dev->real_num_tx_queues > 1) &&\n+\t __netif_tx_trylock(dev_queue)) {\n+\t\tif (tx->req == tx->done) {\n+\t\t\ttx->queue_active = 0;\n+\t\t\tput_be32(htonl(1), tx->send_stop);\n+\t\t}\n+\t\t__netif_tx_unlock(dev_queue);\n+\t}\n+\n \t/* start the queue if we've stopped it */\n-\tif (netif_queue_stopped(ss->dev)\n+\tif (netif_tx_queue_stopped(dev_queue)\n \t && tx->req - tx->done < (tx->mask >> 1)) {\n \t\ttx->wake_queue++;\n-\t\tnetif_wake_queue(ss->dev);\n+\t\tnetif_tx_wake_queue(dev_queue);\n \t}\n }\n \n@@ -1484,9 +1532,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)\n \tu32 send_done_count;\n \tint i;\n \n-\t/* an interrupt on a non-zero slice is implicitly valid\n-\t * since MSI-X irqs are not shared */\n-\tif (ss != mgp->ss) {\n+\t/* an interrupt on a non-zero receive-only slice is implicitly\n+\t * valid since MSI-X irqs are not shared */\n+\tif ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {\n \t\tnetif_rx_schedule(ss->dev, &ss->napi);\n \t\treturn (IRQ_HANDLED);\n \t}\n@@ -1528,7 +1576,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)\n \t\tbarrier();\n \t}\n \n-\tmyri10ge_check_statblock(mgp);\n+\t/* Only slice 0 updates stats */\n+\tif (ss == mgp->ss)\n+\t\tmyri10ge_check_statblock(mgp);\n \n \tput_be32(htonl(3), ss->irq_claim + 1);\n \treturn (IRQ_HANDLED);\n@@ -1886,6 +1936,7 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)\n \t/* ensure req_list entries are aligned to 8 bytes */\n \tss->tx.req_list = (struct mcp_kreq_ether_send *)\n \t ALIGN((unsigned long)ss->tx.req_bytes, 8);\n+\tss->tx.queue_active = 0;\n \n \tbytes = rx_ring_entries * sizeof(*ss->rx_small.shadow);\n \tss->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);\n@@ -2366,11 +2417,14 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)\n \tint status;\n \n \tss = &mgp->ss[slice];\n-\tcmd.data0 = 0;\t\t/* single slice for now */\n-\tstatus = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);\n-\tss->tx.lanai = (struct mcp_kreq_ether_send __iomem *)\n-\t (mgp->sram + cmd.data0);\n-\n+\tstatus = 0;\n+\tif (slice == 0 || (mgp->dev->real_num_tx_queues > 1)) {\n+\t\tcmd.data0 = slice;\n+\t\tstatus = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET,\n+\t\t\t\t\t &cmd, 0);\n+\t\tss->tx.lanai = (struct mcp_kreq_ether_send __iomem *)\n+\t\t (mgp->sram + cmd.data0);\n+\t}\n \tcmd.data0 = slice;\n \tstatus |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET,\n \t\t\t\t &cmd, 0);\n@@ -2382,6 +2436,10 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)\n \tss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)\n \t (mgp->sram + cmd.data0);\n \n+\tss->tx.send_go = (__iomem __be32 *)\n+\t (mgp->sram + MXGEFW_ETH_SEND_GO + 64 * slice);\n+\tss->tx.send_stop = (__iomem __be32 *)\n+\t (mgp->sram + MXGEFW_ETH_SEND_STOP + 64 * slice);\n \treturn status;\n \n }\n@@ -2395,7 +2453,7 @@ static int myri10ge_set_stats(struct myri10ge_priv *mgp, int slice)\n \tss = &mgp->ss[slice];\n \tcmd.data0 = MYRI10GE_LOWPART_TO_U32(ss->fw_stats_bus);\n \tcmd.data1 = MYRI10GE_HIGHPART_TO_U32(ss->fw_stats_bus);\n-\tcmd.data2 = sizeof(struct mcp_irq_data);\n+\tcmd.data2 = sizeof(struct mcp_irq_data) | (slice << 16);\n \tstatus = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);\n \tif (status == -ENOSYS) {\n \t\tdma_addr_t bus = ss->fw_stats_bus;\n@@ -2436,7 +2494,9 @@ static int myri10ge_open(struct net_device *dev)\n \n \tif (mgp->num_slices > 1) {\n \t\tcmd.data0 = mgp->num_slices;\n-\t\tcmd.data1 = 1;\t/* use MSI-X */\n+\t\tcmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;\n+\t\tif (mgp->dev->real_num_tx_queues > 1)\n+\t\t\tcmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;\n \t\tstatus = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,\n \t\t\t\t\t &cmd, 0);\n \t\tif (status != 0) {\n@@ -2457,6 +2517,7 @@ static int myri10ge_open(struct net_device *dev)\n \t\t\tprintk(KERN_ERR\n \t\t\t \"myri10ge: %s: failed to setup rss tables\\n\",\n \t\t\t dev->name);\n+\t\t\tgoto abort_with_nothing;\n \t\t}\n \n \t\t/* just enable an identity mapping */\n@@ -2527,7 +2602,11 @@ static int myri10ge_open(struct net_device *dev)\n \t\tstatus = myri10ge_allocate_rings(ss);\n \t\tif (status != 0)\n \t\t\tgoto abort_with_rings;\n-\t\tif (slice == 0)\n+\n+\t\t/* only firmware which supports multiple TX queues\n+\t\t * supports setting up the tx stats on non-zero\n+\t\t * slices */\n+\t\tif (slice == 0 || mgp->dev->real_num_tx_queues > 1)\n \t\t\tstatus = myri10ge_set_stats(mgp, slice);\n \t\tif (status) {\n \t\t\tprintk(KERN_ERR\n@@ -2593,7 +2672,8 @@ static int myri10ge_open(struct net_device *dev)\n \tmgp->running = MYRI10GE_ETH_RUNNING;\n \tmgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;\n \tadd_timer(&mgp->watchdog_timer);\n-\tnetif_wake_queue(dev);\n+\tnetif_tx_wake_all_queues(dev);\n+\n \treturn 0;\n \n abort_with_rings:\n@@ -2620,13 +2705,15 @@ static int myri10ge_close(struct net_device *dev)\n \tif (mgp->ss[0].tx.req_bytes == NULL)\n \t\treturn 0;\n \n+\tdev->select_queue = NULL;\n \tdel_timer_sync(&mgp->watchdog_timer);\n \tmgp->running = MYRI10GE_ETH_STOPPING;\n \tfor (i = 0; i < mgp->num_slices; i++) {\n \t\tnapi_disable(&mgp->ss[i].napi);\n \t}\n \tnetif_carrier_off(dev);\n-\tnetif_stop_queue(dev);\n+\n+\tnetif_tx_stop_all_queues(dev);\n \told_down_cnt = mgp->down_cnt;\n \tmb();\n \tstatus = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);\n@@ -2731,18 +2823,23 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)\n \tstruct mcp_kreq_ether_send *req;\n \tstruct myri10ge_tx_buf *tx;\n \tstruct skb_frag_struct *frag;\n+\tstruct netdev_queue *netdev_queue;\n \tdma_addr_t bus;\n \tu32 low;\n \t__be32 high_swapped;\n \tunsigned int len;\n \tint idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;\n-\tu16 pseudo_hdr_offset, cksum_offset;\n+\tu16 pseudo_hdr_offset, cksum_offset, queue;\n \tint cum_len, seglen, boundary, rdma_count;\n \tu8 flags, odd_flag;\n \n-\t/* always transmit through slot 0 */\n-\tss = mgp->ss;\n+\tqueue = skb_get_queue_mapping(skb);\n+\tqueue &= (mgp->num_slices - 1);\n+\n+\tss = &mgp->ss[queue];\n+\tnetdev_queue = netdev_get_tx_queue(mgp->dev, queue);\n \ttx = &ss->tx;\n+\n again:\n \treq = tx->req_list;\n \tavail = tx->mask - 1 - (tx->req - tx->done);\n@@ -2758,7 +2855,7 @@ again:\n \tif ((unlikely(avail < max_segments))) {\n \t\t/* we are out of transmit resources */\n \t\ttx->stop_queue++;\n-\t\tnetif_stop_queue(dev);\n+\t\tnetif_tx_stop_queue(netdev_queue);\n \t\treturn 1;\n \t}\n \n@@ -2951,10 +3048,16 @@ again:\n \tidx = ((count - 1) + tx->req) & tx->mask;\n \ttx->info[idx].last = 1;\n \tmyri10ge_submit_req(tx, tx->req_list, count);\n+\t/* if using multiple tx queues, make sure NIC polls the\n+\t * current slice */\n+\tif ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) {\n+\t\ttx->queue_active = 1;\n+\t\tput_be32(htonl(1), tx->send_go);\n+\t}\n \ttx->pkt_start++;\n \tif ((avail - count) < MXGEFW_MAX_SEND_DESC) {\n \t\ttx->stop_queue++;\n-\t\tnetif_stop_queue(dev);\n+\t\tnetif_tx_stop_queue(netdev_queue);\n \t}\n \tdev->trans_start = jiffies;\n \treturn 0;\n@@ -3532,20 +3635,21 @@ static void myri10ge_watchdog(struct work_struct *work)\n \t\tfor (i = 0; i < mgp->num_slices; i++) {\n \t\t\ttx = &mgp->ss[i].tx;\n \t\t\tprintk(KERN_INFO\n-\t\t\t \"myri10ge: %s: (%d): %d %d %d %d %d\\n\",\n-\t\t\t mgp->dev->name, i, tx->req, tx->done,\n-\t\t\t tx->pkt_start, tx->pkt_done,\n+\t\t\t \"myri10ge: %s: (%d): %d %d %d %d %d %d\\n\",\n+\t\t\t mgp->dev->name, i, tx->queue_active, tx->req,\n+\t\t\t tx->done, tx->pkt_start, tx->pkt_done,\n \t\t\t (int)ntohl(mgp->ss[i].fw_stats->\n \t\t\t\t\t send_done_count));\n \t\t\tmsleep(2000);\n \t\t\tprintk(KERN_INFO\n-\t\t\t \"myri10ge: %s: (%d): %d %d %d %d %d\\n\",\n-\t\t\t mgp->dev->name, i, tx->req, tx->done,\n-\t\t\t tx->pkt_start, tx->pkt_done,\n+\t\t\t \"myri10ge: %s: (%d): %d %d %d %d %d %d\\n\",\n+\t\t\t mgp->dev->name, i, tx->queue_active, tx->req,\n+\t\t\t tx->done, tx->pkt_start, tx->pkt_done,\n \t\t\t (int)ntohl(mgp->ss[i].fw_stats->\n \t\t\t\t\t send_done_count));\n \t\t}\n \t}\n+\n \trtnl_lock();\n \tmyri10ge_close(mgp->dev);\n \tstatus = myri10ge_load_firmware(mgp, 1);\n@@ -3600,10 +3704,14 @@ static void myri10ge_watchdog_timer(unsigned long arg)\n \t\t\t/* nic seems like it might be stuck.. */\n \t\t\tif (rx_pause_cnt != mgp->watchdog_pause) {\n \t\t\t\tif (net_ratelimit())\n-\t\t\t\t\tprintk(KERN_WARNING \"myri10ge %s:\"\n+\t\t\t\t\tprintk(KERN_WARNING\n+\t\t\t\t\t \"myri10ge %s slice %d:\"\n \t\t\t\t\t \"TX paused, check link partner\\n\",\n-\t\t\t\t\t mgp->dev->name);\n+\t\t\t\t\t mgp->dev->name, i);\n \t\t\t} else {\n+\t\t\t\tprintk(KERN_WARNING\n+\t\t\t\t \"myri10ge %s slice %d stuck:\",\n+\t\t\t\t mgp->dev->name, i);\n \t\t\t\treset_needed = 1;\n \t\t\t}\n \t\t}\n@@ -3789,6 +3897,9 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp)\n \t\t\t\t\t mgp->num_slices);\n \t\tif (status == 0) {\n \t\t\tpci_disable_msix(pdev);\n+#ifdef CONFIG_NETDEVICES_MULTIQUEUE\n+\t\t\tmgp->features |= NETIF_F_MULTI_QUEUE;\n+#endif\n \t\t\treturn;\n \t\t}\n \t\tif (status > 0)\n@@ -3818,7 +3929,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \tint status = -ENXIO;\n \tint dac_enabled;\n \n-\tnetdev = alloc_etherdev(sizeof(*mgp));\n+\tnetdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);\n \tif (netdev == NULL) {\n \t\tdev_err(dev, \"Could not allocate ethernet device\\n\");\n \t\treturn -ENOMEM;\n@@ -3923,7 +4034,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \t\tdev_err(&pdev->dev, \"failed to alloc slice state\\n\");\n \t\tgoto abort_with_firmware;\n \t}\n-\n+\tnetdev->real_num_tx_queues = mgp->num_slices;\n \tstatus = myri10ge_reset(mgp);\n \tif (status != 0) {\n \t\tdev_err(&pdev->dev, \"failed reset\\n\");\n@@ -3947,6 +4058,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)\n \tnetdev->set_multicast_list = myri10ge_set_multicast_list;\n \tnetdev->set_mac_address = myri10ge_set_mac_address;\n \tnetdev->features = mgp->features;\n+\n \tif (dac_enabled)\n \t\tnetdev->features |= NETIF_F_HIGHDMA;\n \n@@ -4102,8 +4214,7 @@ static __init int myri10ge_init_module(void)\n \tprintk(KERN_INFO \"%s: Version %s\\n\", myri10ge_driver.name,\n \t MYRI10GE_VERSION_STR);\n \n-\tif (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_SRC_PORT ||\n-\t myri10ge_rss_hash < MXGEFW_RSS_HASH_TYPE_IPV4) {\n+\tif (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX) {\n \t\tprintk(KERN_ERR\n \t\t \"%s: Illegal rssh hash type %d, defaulting to source port\\n\",\n \t\t myri10ge_driver.name, myri10ge_rss_hash);\n@@ -4112,6 +4223,8 @@ static __init int myri10ge_init_module(void)\n #ifdef CONFIG_DCA\n \tdca_register_notify(&myri10ge_dca_notifier);\n #endif\n+\tif (myri10ge_max_slices > MYRI10GE_MAX_SLICES)\n+\t\tmyri10ge_max_slices = MYRI10GE_MAX_SLICES;\n \n \treturn pci_register_driver(&myri10ge_driver);\n }\n\n\n--\nTo unsubscribe from this list: send the line \"unsubscribe netdev\" in\nthe body of a message to majordomo@vger.kernel.org\nMore majordomo info at http://vger.kernel.org/majordomo-info.html", "diff": "--- a/drivers/net/myri10ge/myri10ge.c\n+++ b/drivers/net/myri10ge/myri10ge.c\n@@ -102,6 +102,9 @@ MODULE_LICENSE(\"Dual BSD/GPL\");\n #define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)\n #define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)\n \n+#define MYRI10GE_MAX_SLICES 32\n+\n struct myri10ge_rx_buffer_state {\n \tstruct page *page;\n \tint page_offset;\n@@ -138,6 +141,8 @@ struct myri10ge_rx_buf {\n", "prefixes": [ "RESEND", "2.6.28" ] }