From: Robert Jennings <rcj@linux.vnet.ibm.com>
To: paulus@samba.org
Cc: netdev@vger.kernel.org, linuxppc-dev@ozlabs.org,
David Darrington <ddarring@linux.vnet.ibm.com>,
Brian King <brking@linux.vnet.ibm.com>
Subject: [PATCH 17/19] ibmveth: enable driver for CMO
Date: Thu, 12 Jun 2008 17:23:11 -0500 [thread overview]
Message-ID: <20080612222311.GY30916@linux.vnet.ibm.com> (raw)
In-Reply-To: <20080612215312.GF30916@linux.vnet.ibm.com>
=46rom: Robert Jennings <rcj@linux.vnet.ibm.com>
Enable ibmveth for Cooperative Memory Overcommitment (CMO). For this driver
it means calculating a desired amount of IO memory based on the current MTU
and updating this value with the bus when MTU changes occur. Because DMA
mappings can fail, we have added a bounce buffer for temporary cases where
the driver can not map IO memory for the buffer pool.
The following changes are made to enable the driver for CMO:
* DMA mapping errors will not result in error messages if entitlement has
been exceeded and resources were not available.
* DMA mapping errors are handled gracefully, ibmveth_replenish_buffer_pool=
()
is corrected to check the return from dma_map_single and fail gracefully.
* The driver will have a get_io_entitlement function defined to function
in a CMO environment.
* When the MTU is changed, the driver will update the device IO entitlement
Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
Signed-off-by: Santiago Leon <santil@us.ibm.com>
---
drivers/net/ibmveth.c | 169 ++++++++++++++++++++++++++++++++++++++++-----=
-----
drivers/net/ibmveth.h | 5 +
2 files changed, 140 insertions(+), 34 deletions(-)
Index: b/drivers/net/ibmveth.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -33,6 +33,7 @@
*/
=20
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/ioport.h>
@@ -52,7 +53,9 @@
#include <asm/hvcall.h>
#include <asm/atomic.h>
#include <asm/vio.h>
+#include <asm/iommu.h>
#include <asm/uaccess.h>
+#include <asm/firmware.h>
#include <linux/seq_file.h>
=20
#include "ibmveth.h"
@@ -94,8 +97,10 @@ static void ibmveth_proc_register_adapte
static void ibmveth_proc_unregister_adapter(struct ibmveth_adapter *adapte=
r);
static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance);
static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter);
+static unsigned long ibmveth_get_io_entitlement(struct vio_dev *vdev);
static struct kobj_type ktype_veth_pool;
=20
+
#ifdef CONFIG_PROC_FS
#define IBMVETH_PROC_DIR "ibmveth"
static struct proc_dir_entry *ibmveth_proc_dir;
@@ -226,16 +231,16 @@ static void ibmveth_replenish_buffer_poo
u32 i;
u32 count =3D pool->size - atomic_read(&pool->available);
u32 buffers_added =3D 0;
+ struct sk_buff *skb;
+ unsigned int free_index, index;
+ u64 correlator;
+ unsigned long lpar_rc;
+ dma_addr_t dma_addr;
=20
mb();
=20
for(i =3D 0; i < count; ++i) {
- struct sk_buff *skb;
- unsigned int free_index, index;
- u64 correlator;
union ibmveth_buf_desc desc;
- unsigned long lpar_rc;
- dma_addr_t dma_addr;
=20
skb =3D alloc_skb(pool->buff_size, GFP_ATOMIC);
=20
@@ -255,6 +260,9 @@ static void ibmveth_replenish_buffer_poo
dma_addr =3D dma_map_single(&adapter->vdev->dev, skb->data,
pool->buff_size, DMA_FROM_DEVICE);
=20
+ if (dma_mapping_error(dma_addr))
+ goto failure;
+
pool->free_map[free_index] =3D IBM_VETH_INVALID_MAP;
pool->dma_addr[index] =3D dma_addr;
pool->skbuff[index] =3D skb;
@@ -267,20 +275,9 @@ static void ibmveth_replenish_buffer_poo
=20
lpar_rc =3D h_add_logical_lan_buffer(adapter->vdev->unit_address, desc.d=
esc);
=20
- if(lpar_rc !=3D H_SUCCESS) {
- pool->free_map[free_index] =3D index;
- pool->skbuff[index] =3D NULL;
- if (pool->consumer_index =3D=3D 0)
- pool->consumer_index =3D pool->size - 1;
- else
- pool->consumer_index--;
- dma_unmap_single(&adapter->vdev->dev,
- pool->dma_addr[index], pool->buff_size,
- DMA_FROM_DEVICE);
- dev_kfree_skb_any(skb);
- adapter->replenish_add_buff_failure++;
- break;
- } else {
+ if (lpar_rc !=3D H_SUCCESS)
+ goto failure;
+ else {
buffers_added++;
adapter->replenish_add_buff_success++;
}
@@ -288,6 +285,24 @@ static void ibmveth_replenish_buffer_poo
=20
mb();
atomic_add(buffers_added, &(pool->available));
+ return;
+
+failure:
+ pool->free_map[free_index] =3D index;
+ pool->skbuff[index] =3D NULL;
+ if (pool->consumer_index =3D=3D 0)
+ pool->consumer_index =3D pool->size - 1;
+ else
+ pool->consumer_index--;
+ if (!dma_mapping_error(dma_addr))
+ dma_unmap_single(&adapter->vdev->dev,
+ pool->dma_addr[index], pool->buff_size,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(skb);
+ adapter->replenish_add_buff_failure++;
+
+ mb();
+ atomic_add(buffers_added, &(pool->available));
}
=20
/* replenish routine */
@@ -297,7 +312,7 @@ static void ibmveth_replenish_task(struc
=20
adapter->replenish_task_cycles++;
=20
- for(i =3D 0; i < IbmVethNumBufferPools; i++)
+ for (i =3D (IbmVethNumBufferPools - 1); i >=3D 0; i--)
if(adapter->rx_buff_pool[i].active)
ibmveth_replenish_buffer_pool(adapter,
&adapter->rx_buff_pool[i]);
@@ -472,6 +487,18 @@ static void ibmveth_cleanup(struct ibmve
if (adapter->rx_buff_pool[i].active)
ibmveth_free_buffer_pool(adapter,
&adapter->rx_buff_pool[i]);
+
+ if(adapter->bounce_buffer !=3D NULL) {
+ if(!dma_mapping_error(adapter->bounce_buffer_dma)) {
+ dma_unmap_single(&adapter->vdev->dev,
+ adapter->bounce_buffer_dma,
+ adapter->netdev->mtu + IBMVETH_BUFF_OH,
+ DMA_BIDIRECTIONAL);
+ adapter->bounce_buffer_dma =3D DMA_ERROR_CODE;
+ }
+ kfree(adapter->bounce_buffer);
+ adapter->bounce_buffer =3D NULL;
+ }
}
=20
static int ibmveth_register_logical_lan(struct ibmveth_adapter *adapter,
@@ -607,6 +634,24 @@ static int ibmveth_open(struct net_devic
return rc;
}
=20
+ adapter->bounce_buffer =3D
+ kmalloc(netdev->mtu + IBMVETH_BUFF_OH, GFP_KERNEL);
+ if(!adapter->bounce_buffer) {
+ ibmveth_error_printk("unable to allocate bounce buffer\n");
+ ibmveth_cleanup(adapter);
+ napi_disable(&adapter->napi);
+ return -ENOMEM;
+ }
+ adapter->bounce_buffer_dma =3D
+ dma_map_single(&adapter->vdev->dev, adapter->bounce_buffer,
+ netdev->mtu + IBMVETH_BUFF_OH, DMA_BIDIRECTIONAL);
+ if(dma_mapping_error(adapter->bounce_buffer_dma)) {
+ ibmveth_error_printk("unable to map bounce buffer\n");
+ ibmveth_cleanup(adapter);
+ napi_disable(&adapter->napi);
+ return -ENOMEM;
+ }
+
ibmveth_debug_printk("initial replenish cycle\n");
ibmveth_interrupt(netdev->irq, netdev);
=20
@@ -853,10 +898,12 @@ static int ibmveth_start_xmit(struct sk_
unsigned int tx_packets =3D 0;
unsigned int tx_send_failed =3D 0;
unsigned int tx_map_failed =3D 0;
+ int used_bounce =3D 0;
+ unsigned long data_dma_addr;
=20
desc.fields.flags_len =3D IBMVETH_BUF_VALID | skb->len;
- desc.fields.address =3D dma_map_single(&adapter->vdev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
+ data_dma_addr =3D dma_map_single(&adapter->vdev->dev, skb->data,
+ skb->len, DMA_TO_DEVICE);
=20
if (skb->ip_summed =3D=3D CHECKSUM_PARTIAL &&
ip_hdr(skb)->protocol !=3D IPPROTO_TCP && skb_checksum_help(skb)) {
@@ -875,12 +922,16 @@ static int ibmveth_start_xmit(struct sk_
buf[1] =3D 0;
}
=20
- if (dma_mapping_error(desc.fields.address)) {
- ibmveth_error_printk("tx: unable to map xmit buffer\n");
+ if (dma_mapping_error(data_dma_addr)) {
+ if (!firmware_has_feature(FW_FEATURE_CMO))
+ ibmveth_error_printk("tx: unable to map xmit buffer\n");
+ skb_copy_from_linear_data(skb, adapter->bounce_buffer,
+ skb->len);
+ desc.fields.address =3D adapter->bounce_buffer_dma;
tx_map_failed++;
- tx_dropped++;
- goto out;
- }
+ used_bounce =3D 1;
+ } else
+ desc.fields.address =3D data_dma_addr;
=20
/* send the frame. Arbitrarily set retrycount to 1024 */
correlator =3D 0;
@@ -904,8 +955,9 @@ static int ibmveth_start_xmit(struct sk_
netdev->trans_start =3D jiffies;
}
=20
- dma_unmap_single(&adapter->vdev->dev, desc.fields.address,
- skb->len, DMA_TO_DEVICE);
+ if (!used_bounce)
+ dma_unmap_single(&adapter->vdev->dev, data_dma_addr,
+ skb->len, DMA_TO_DEVICE);
=20
out: spin_lock_irqsave(&adapter->stats_lock, flags);
netdev->stats.tx_dropped +=3D tx_dropped;
@@ -1053,8 +1105,9 @@ static void ibmveth_set_multicast_list(s
static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
{
struct ibmveth_adapter *adapter =3D dev->priv;
+ struct vio_dev *viodev =3D adapter->vdev;
int new_mtu_oh =3D new_mtu + IBMVETH_BUFF_OH;
- int i, rc;
+ int i;
=20
if (new_mtu < IBMVETH_MAX_MTU)
return -EINVAL;
@@ -1085,10 +1138,15 @@ static int ibmveth_change_mtu(struct net
ibmveth_close(adapter->netdev);
adapter->pool_config =3D 0;
dev->mtu =3D new_mtu;
- if ((rc =3D ibmveth_open(adapter->netdev)))
- return rc;
- } else
- dev->mtu =3D new_mtu;
+ vio_cmo_set_dev_desired(viodev,
+ ibmveth_get_io_entitlement
+ (viodev));
+ return ibmveth_open(adapter->netdev);
+ }
+ dev->mtu =3D new_mtu;
+ vio_cmo_set_dev_desired(viodev,
+ ibmveth_get_io_entitlement
+ (viodev));
return 0;
}
}
@@ -1103,6 +1161,46 @@ static void ibmveth_poll_controller(stru
}
#endif
=20
+/**
+ * ibmveth_get_io_entitlement - Calculate IO entitlement needed by the dri=
ver
+ *
+ * @vdev: struct vio_dev for the device whose entitlement is to be returned
+ *
+ * Return value:
+ * Number of bytes of IO data the driver will need to perform well.
+ */
+static unsigned long ibmveth_get_io_entitlement(struct vio_dev *vdev)
+{
+ struct net_device *netdev =3D dev_get_drvdata(&vdev->dev);
+ struct ibmveth_adapter *adapter;
+ unsigned long ret;
+ int i;
+ int rxqentries =3D 1;
+
+ /* netdev inits at probe time along with the structures we need below*/
+ if (netdev =3D=3D NULL)
+ return IOMMU_PAGE_ALIGN(IBMVETH_IO_ENTITLEMENT_DEFAULT);
+
+ adapter =3D netdev_priv(netdev);
+
+ ret =3D IBMVETH_BUFF_LIST_SIZE + IBMVETH_FILT_LIST_SIZE;
+ ret +=3D IOMMU_PAGE_ALIGN(netdev->mtu);
+
+ for (i =3D 0; i < IbmVethNumBufferPools; i++) {
+ /* add the size of the active receive buffers */
+ if (adapter->rx_buff_pool[i].active)
+ ret +=3D
+ adapter->rx_buff_pool[i].size *
+ IOMMU_PAGE_ALIGN(adapter->rx_buff_pool[i].
+ buff_size);
+ rxqentries +=3D adapter->rx_buff_pool[i].size;
+ }
+ /* add the size of the receive queue entries */
+ ret +=3D IOMMU_PAGE_ALIGN(rxqentries * sizeof(struct ibmveth_rx_q_entry));
+
+ return ret;
+}
+
static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_d=
evice_id *id)
{
int rc, i;
@@ -1247,6 +1345,8 @@ static int __devexit ibmveth_remove(stru
ibmveth_proc_unregister_adapter(adapter);
=20
free_netdev(netdev);
+ dev_set_drvdata(&dev->dev, NULL);
+
return 0;
}
=20
@@ -1491,6 +1591,7 @@ static struct vio_driver ibmveth_driver=20
.id_table =3D ibmveth_device_table,
.probe =3D ibmveth_probe,
.remove =3D ibmveth_remove,
+ .get_io_entitlement =3D ibmveth_get_io_entitlement,
.driver =3D {
.name =3D ibmveth_driver_name,
.owner =3D THIS_MODULE,
Index: b/drivers/net/ibmveth.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- a/drivers/net/ibmveth.h
+++ b/drivers/net/ibmveth.h
@@ -93,9 +93,12 @@ static inline long h_illan_attributes(un
plpar_hcall_norets(H_CHANGE_LOGICAL_LAN_MAC, ua, mac)
=20
#define IbmVethNumBufferPools 5
+#define IBMVETH_IO_ENTITLEMENT_DEFAULT 4243456 /* MTU of 1500 needs 4.2Mb =
*/
#define IBMVETH_BUFF_OH 22 /* Overhead: 14 ethernet header + 8 opaque hand=
le */
#define IBMVETH_MAX_MTU 68
#define IBMVETH_MAX_POOL_COUNT 4096
+#define IBMVETH_BUFF_LIST_SIZE 4096
+#define IBMVETH_FILT_LIST_SIZE 4096
#define IBMVETH_MAX_BUF_SIZE (1024 * 128)
=20
static int pool_size[] =3D { 512, 1024 * 2, 1024 * 16, 1024 * 32, 1024 * 6=
4 };
@@ -143,6 +146,8 @@ struct ibmveth_adapter {
struct ibmveth_rx_q rx_queue;
int pool_config;
int rx_csum;
+ void * bounce_buffer;
+ dma_addr_t bounce_buffer_dma;
=20
/* adapter specific stats */
u64 replenish_task_cycles;
next prev parent reply other threads:[~2008-06-12 22:24 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-06-12 21:53 [PATCH 00/19] powerpc: pSeries Cooperative Memory Overcommitment support Robert Jennings
2008-06-12 22:08 ` [PATCH 01/19] powerpc: Remove extraneous error reporting for hcall failures in lparcfg Robert Jennings
2008-06-12 22:08 ` [PATCH 02/19] powerpc: Split processor entitlement retrieval and gathering to helper routines Robert Jennings
2008-06-13 0:23 ` Stephen Rothwell
2008-06-13 19:11 ` Nathan Fontenot
2008-06-16 16:07 ` Nathan Fontenot
2008-06-12 22:09 ` [PATCH 03/19] powerpc: Add memory entitlement capabilities to /proc/ppc64/lparcfg Robert Jennings
2008-06-16 16:09 ` [PATCH 03/19][v2] " Nathan Fontenot
2008-06-16 20:47 ` [PATCH 03/19][v3] " Nathan Fontenot
2008-06-24 14:23 ` Brian King
2008-06-24 15:26 ` [PATCH 03/19] " Nathan Fontenot
2008-06-12 22:11 ` [PATCH 04/19] powerpc: Split retrieval of processor entitlement data into a helper routine Robert Jennings
2008-06-12 22:11 ` [PATCH 05/19] powerpc: Enable CMO feature during platform setup Robert Jennings
2008-06-12 22:12 ` [PATCH 06/19] powerpc: Utilities to set firmware page state Robert Jennings
2008-06-12 22:13 ` [PATCH 07/19] powerpc: Add collaborative memory manager Robert Jennings
2008-06-12 22:13 ` [PATCH 08/19] powerpc: Do not probe PCI buses or eBus devices if CMO is enabled Robert Jennings
2008-06-12 22:14 ` [PATCH 09/19] powerpc: Add CMO paging statistics Robert Jennings
2008-06-12 22:15 ` [PATCH 10/19] powerpc: move get_longbusy_msecs out of ehca/ehea Robert Jennings
2008-06-12 22:18 ` [PATCH 10/19] [repost] " Robert Jennings
2008-06-13 18:24 ` Brian King
2008-06-13 19:55 ` Jeff Garzik
2008-06-12 22:19 ` [PATCH 11/19] powerpc: iommu enablement for CMO Robert Jennings
2008-06-13 1:43 ` Olof Johansson
2008-06-20 15:03 ` Robert Jennings
2008-06-20 15:12 ` [PATCH 11/19][v2] " Robert Jennings
2008-06-12 22:19 ` [PATCH 12/19] powerpc: vio bus support " Robert Jennings
2008-06-13 5:12 ` Stephen Rothwell
2008-06-23 20:23 ` Robert Jennings
2008-06-23 20:25 ` [PATCH 12/19][v2] " Robert Jennings
2008-06-12 22:21 ` [PATCH 13/19] powerpc: Verify CMO memory entitlement updates with virtual I/O Robert Jennings
2008-06-12 22:21 ` [PATCH 14/19] powerpc: hvc enablement for CMO Robert Jennings
2008-06-12 22:22 ` [PATCH 15/19] powerpc: hvcs " Robert Jennings
2008-06-12 22:22 ` [PATCH 16/19] ibmveth: Automatically enable larger rx buffer pools for larger mtu Robert Jennings
2008-06-13 5:18 ` Stephen Rothwell
2008-06-23 20:21 ` [PATCH 16/19][v2] " Robert Jennings
2008-06-12 22:23 ` Robert Jennings [this message]
2008-06-13 5:25 ` [PATCH 17/19] ibmveth: enable driver for CMO Stephen Rothwell
2008-06-23 20:20 ` [PATCH 17/19][v2] " Robert Jennings
2008-06-12 22:24 ` [PATCH 18/19] ibmvscsi: driver enablement " Robert Jennings
2008-06-13 18:30 ` Brian King
2008-06-12 22:31 ` [PATCH 19/19] powerpc: Update arch vector to indicate support " Robert Jennings
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080612222311.GY30916@linux.vnet.ibm.com \
--to=rcj@linux.vnet.ibm.com \
--cc=brking@linux.vnet.ibm.com \
--cc=ddarring@linux.vnet.ibm.com \
--cc=linuxppc-dev@ozlabs.org \
--cc=netdev@vger.kernel.org \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).