* Re: [PATCH 1/1] drivers/net/usb/usbnet.c: Use FIELD_SIZEOF macro in usbnet_init() function.
From: David Miller @ 2011-04-18 0:49 UTC (permalink / raw)
To: tfransosi; +Cc: linux-kernel, dbrownell, gregkh, netdev, linux-usb
In-Reply-To: <3f3e63ecef46abc5d23053c051b3fef52104cbe7.1303080236.git.tfransosi@gmail.com>
From: Thiago Farina <tfransosi@gmail.com>
Date: Sun, 17 Apr 2011 19:46:04 -0300
> Signed-off-by: Thiago Farina <tfransosi@gmail.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-2.6] bnx2x: Fix port identification problem
From: David Miller @ 2011-04-18 0:50 UTC (permalink / raw)
To: yanivr; +Cc: netdev, eilong
In-Reply-To: <1303022132.18593.16.camel@lb-tlvb-dmitry>
From: "Yaniv Rosner" <yanivr@broadcom.com>
Date: Sun, 17 Apr 2011 09:35:32 +0300
> This patch fixes port identification on optic devices when there's no link on the port.
>
> Signed-off-by: Yaniv Rosner <yanivr@broadcom.com>
> Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Applied to net-2.6, thanks.
^ permalink raw reply
* Re: [PATCH v3] net: cxgb4{,vf}: convert to hw_features
From: David Miller @ 2011-04-18 0:51 UTC (permalink / raw)
To: dm; +Cc: mirq-linux, netdev, leedom
In-Reply-To: <4DAA3A76.3010508@chelsio.com>
From: Dimitris Michailidis <dm@chelsio.com>
Date: Sat, 16 Apr 2011 17:55:18 -0700
> Michał Mirosław wrote:
>> Signed-off-by: Michał Mirosław <mirq-linux@rere.qmqm.pl>
>
> Looks good for both drivers.
>
> Acked-by: Dimitris Michailidis <dm@chelsio.com>
Applied, thanks.
^ permalink raw reply
* Re: [PATCH net-next] bridge: fix accidental creation of sysfs directory
From: David Miller @ 2011-04-18 0:53 UTC (permalink / raw)
To: shemminger; +Cc: netdev
In-Reply-To: <20110416090915.2594a78e@nehalam>
From: Stephen Hemminger <shemminger@vyatta.com>
Date: Sat, 16 Apr 2011 09:09:15 -0700
> Commit bb900b27a2f49b37bc38c08e656ea13048fee13b introduced a bug in net-next
> because of a typo in notifier. Every device would have the sysfs
> bridge directory (and files).
>
> Signed-off-by: Stephen Hemminger <shemminger@vyatta.com>
Applied, thanks Stephen.
^ permalink raw reply
* Re: [PATCH 1/2] via_rhine: Use netdev_<level> and pr_<level>
From: David Miller @ 2011-04-18 0:56 UTC (permalink / raw)
To: joe; +Cc: mr.nuke.me, rl, netdev, linux-kernel
In-Reply-To: <15b0ca3fc5ba6a16b207fb32b0c2e3c809f376d1.1302998994.git.joe@perches.com>
From: Joe Perches <joe@perches.com>
Date: Sat, 16 Apr 2011 17:15:25 -0700
> Use the more current logging styles.
>
> Add #define DEBUG to make netdev_dbg always active.
>
> Signed-off-by: Joe Perches <joe@perches.com>
Applied.
^ permalink raw reply
* Re: [PATCH 2/2] via-rhine: Assign random MAC address if necessary
From: David Miller @ 2011-04-18 0:57 UTC (permalink / raw)
To: joe; +Cc: mr.nuke.me, rl, netdev, linux-kernel
In-Reply-To: <c7efaaf6a943f911162261edd7a2186086cda953.1302998994.git.joe@perches.com>
From: Joe Perches <joe@perches.com>
Date: Sat, 16 Apr 2011 17:15:26 -0700
> Roger Luethi has had several reports of Rhine NICs providing
> an invalid MAC address. If so, assign a random MAC address so
> the hardware can still be used.
>
> Tested as a standalone interface, as carrier for ppp, and as a
> bonding slave.
>
> Original-patch-by: Alexandru Gagniuc <mr.nuke.me@gmail.com>
> Signed-off-by: Joe Perches <joe@perches.com>
Applied.
^ permalink raw reply
* Re: net: Automatic IRQ siloing for network devices
From: Neil Horman @ 2011-04-18 1:08 UTC (permalink / raw)
To: Ben Hutchings; +Cc: Stephen Hemminger, netdev, davem, Thomas Gleixner
In-Reply-To: <1303065539.5282.938.camel@localhost>
On Sun, Apr 17, 2011 at 07:38:59PM +0100, Ben Hutchings wrote:
> On Sun, 2011-04-17 at 13:20 -0400, Neil Horman wrote:
> > On Sat, Apr 16, 2011 at 09:17:04AM -0700, Stephen Hemminger wrote:
> [...]
> > > My gut feeling is that:
> > > * kernel should default to a simple static sane irq policy without user
> > > space. This is especially true for multi-queue devices where the default
> > > puts all IRQ's on one cpu.
> > >
> > Thats not how it currently works, AFAICS. The default kernel policy is
> > currently that cpu affinity for any newly requested irq is all cpus. Any
> > restriction beyond that is the purview and doing of userspace (irqbalance or
> > manual affinity setting).
>
> Right. Though it may be reasonable for the kernel to use the hint as
> the initial affinity for a newly allocated IRQ (not sure quite how we
> determine that).
>
So I understand what your saying here, but I'm having a hard time reconciling
the two notions. Currently as it stands, affinity_hint gets set by a single
function call in the kernel (irq_set_affinity_hint), and is called by drivers
wishing to guide irqbalances behavior (currently only ixgbe does this). The
behavior a driver is capable of guiding however are either overly simple (ixgbe
just tells irqbalance to place each irq on a separate cpu, which irqbalance
would do anyway) or overly complex (forcing policy into the kernel, which I
tried to do with this patch series, but based on the responses I've gotten here,
that seems non-desireable).
I personally like the idea of using affinity_hint to export various guidelines
to drive irqbalances behavior, but I think I'm in the minority on that. Given
the responses here, It almost seems to me like we should do away with
affinity_hint alltogether (or perhaps just continue to ignore it), and rather
export data relevent to balancing in various other locations, and just have
irqbalance use that info directly.
> [...]
> > > * irqbalance should not do the hacks it does to try and guess at network traffic.
> > >
> > Well, I can certainly agree with that, but I'm not sure what that looks like.
> >
> > I could envision something like:
> >
> > 1) Use irqbalance to do a one time placement of interrupts, keeping a simple
> > (possibly sub-optimal) policy, perhaps something like new irqs get assigned to
> > the least loaded cpu within the numa node of the device the irq is originating
> > from.
> >
> > 2) Add a udev event on the addition of new interrupts, to rerun irqbalance
>
> Yes, making irqbalance more (or entirely) event-driven seems like a good
> thing.
>
Yeah, I can do that, it shouldn't be hard. Do we need to worry about bursty
interfaces (i.e. irqs that have high volume counts for periods of time followed
by periods of low activity). A periodic irqbalance can reblance behavior like
that wheras a one-shot cannot. Can we just assume that the one-shot rebalance
would give a 'good enough' placement in that situation?
> > 3) Add some exported information to identify processes that are high users of
> > network traffic, and correlate that usage to a rxq/irq that produces that
> > information (possibly some per-task proc file)
> >
> > 4) Create/expand an additional user space daemon to monitor the highest users of
> > network traffic on various rxq/irqs (as identified in (3)) and restrict those
> > processes execution to those cpus which are on the same L2 cache as the irq
> > itself. The cpuset cgroup could be usefull in doing this perhaps.
>
> I just don't see that you're going to get processes associated with
> specific RX queues unless you make use of flow steering.
>
> The 128-entry flow hash indirection table is part of Microsoft's
> requirements for RSS so most multiqueue hardware is going to let you do
> limited flow steering that way.
>
Yes, Agreed. I had presumed that any feature like this would assume RFS was
available and enabled. If it wasn't, we'd have to re-implement some metric
gathering code along with code to correlate sockets to rx queues and irqs. That
would be 90% of the RFS code and this patch series :)
> > Actually, as I read back to myself, that acutally sounds kind of good to me. It
> > keeps all the policy for this in user space, and minimizes what we have to add
> > to the kernel to make it happen (some process information in /proc and another
> > udev event). I'd like to get some feedback before I start implementing this,
> > but I think this could be done. What do you think?
>
> I don't think it's a good idea to override the scheduler dynamically
> like this.
>
Why not? Not disagreeing here, but I'm curious as to why you think this is bad.
We already have several interfaces for doing this in user space (cgroups and
taskset come to mind). Nominally they are used directly by sysadmins, and used
sparingly for specific configurations. All I'm suggesting is that we create a
daemon to identify processes that would benefit from running closer to the nics
they are getting data from, and restricting them to cpus that fit that benefit.
If a sysadmin doesn't want that behavior, they can stop the daemon, or change
its configuration to avoid including processes they don't want to move/restrict.
Thanks & Regards
Neil
> Ben.
>
> --
> Ben Hutchings, Senior Software Engineer, Solarflare
> Not speaking for my employer; that's the marketing department's job.
> They asked us to note that Solarflare product names are trademarked.
>
>
^ permalink raw reply
* Re: [PATCH 6/42] decnet: Fix set-but-unused variable.
From: Ben Hutchings @ 2011-04-18 2:12 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20110417.173250.183050174.davem@davemloft.net>
On Sun, 2011-04-17 at 17:32 -0700, David Miller wrote:
> "next" in dn_rebuild_zone() is set but not actually used,
> kill it off.
>
> Signed-off-by: David S. Miller <davem@davemloft.net>
> ---
> net/decnet/dn_table.c | 3 +--
> 1 files changed, 1 insertions(+), 2 deletions(-)
>
> diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
> index 99d8d3a..d8ea583 100644
> --- a/net/decnet/dn_table.c
> +++ b/net/decnet/dn_table.c
> @@ -124,11 +124,10 @@ static inline void dn_rebuild_zone(struct dn_zone *dz,
> int old_divisor)
> {
> int i;
> - struct dn_fib_node *f, **fp, *next;
> + struct dn_fib_node *f, **fp;
>
> for(i = 0; i < old_divisor; i++) {
> for(f = old_ht[i]; f; f = f->fn_next) {
> - next = f->fn_next;
> for(fp = dn_chain_p(f->fn_key, dz);
> *fp && dn_key_leq((*fp)->fn_key, f->fn_key);
> fp = &(*fp)->fn_next)
This function is rebuilding a hash table after the number of buckets is
changed. After moving each element into a new bucket, it needs to carry
on iterating over the old bucket. Therefore the 'next' variable is
really needed and the second for-loop should use it: 'f = next', not
'f = f->fn_next'.
Currently this must just leak routes as the table grows, but I suppose
no-one really uses DECnet any more.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 0/42] Kill -Wunused-but-set warnings
From: Ben Hutchings @ 2011-04-18 2:19 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <20110417.173233.193710905.davem@davemloft.net>
On Sun, 2011-04-17 at 17:32 -0700, David Miller wrote:
> The weather is real nice, so I decided to lock myself inside and
> fix compiler warnings.
>
> I started using gcc-4.6.x on my primary sparc64 build test machine the
> other week and it now enables -Wunused-but-set with -Wall and it does
> catch a bunch of bogus stuff.
[...]
In most of these cases there is presumably no need for the variable at
all. In others, the variable should have been used - which I believe is
the main reason for the warning - and by removing it you will be hiding
a bug.
Ben.
--
Ben Hutchings, Senior Software Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply
* Re: [PATCH 02/27] HFI: Add HFI adapter control structure
From: Jim Dykman @ 2011-04-18 3:21 UTC (permalink / raw)
To: Ben Hutchings
Cc: Stephen Hemminger, netdev, Piyush Chaudhary, Fu-Chung Chang,
William S. Cadden, Wen C. Chen, Scot Sakolish, Jian Xiao,
Carol L. Soto, Sarah J. Sheppard
In-Reply-To: <1299105870.4277.37.camel@localhost>
On 3/2/2011 5:44 PM, Ben Hutchings wrote:
> On Wed, 2011-03-02 at 14:21 -0800, Stephen Hemminger wrote:
>> On Wed, 2 Mar 2011 16:09:48 -0500
>> dykmanj@linux.vnet.ibm.com wrote:
>>
>>> diff --git a/drivers/net/hfi/core/Makefile b/drivers/net/hfi/core/Makefile
>>> index 80790c6..6fe4e60 100644
>>> --- a/drivers/net/hfi/core/Makefile
>>> +++ b/drivers/net/hfi/core/Makefile
>>> @@ -1,5 +1,6 @@
>>> #
>>> # Makefile for the HFI device driver for IBM eServer System p
>>> #
>>> -hfi_core-objs:= hfidd_init.o
>>> +hfi_core-objs:= hfidd_adpt.o \
>>> + hfidd_init.o
>>> obj-$(CONFIG_HFI) += hfi_core.o
>>> diff --git a/drivers/net/hfi/core/hfidd_adpt.c b/drivers/net/hfi/core/hfidd_adpt.c
>>> new file mode 100644
>>> index 0000000..d64fa38
>>> --- /dev/null
>>> +++ b/drivers/net/hfi/core/hfidd_adpt.c
> [...]
>>> +void hfidd_free_adapter(struct hfidd_acs *p_acs)
>>> +{
>>> + kfree(p_acs);
>>> + p_acs = NULL;
>>> + return;
>>> +}
>>
>> If these were not in a separate file the could be marked as static.
>
> I assume they're intending to add some more interesting code here in the
> next installment.
>
Yes, there is more to come.
>> Doing a return; on last line of a void function is considered poor
>> style since it is unnecessary.
>
> Assigning to a local variable just before returning is also silly.
>
> Ben.
>
Both removed in v2.
Jim
^ permalink raw reply
* Re: [PATCH 24/27] HFI: hf network driver
From: Jim Dykman @ 2011-04-18 3:21 UTC (permalink / raw)
To: Stephen Hemminger
Cc: netdev, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <20110302142617.112bd9cb@nehalam>
On 3/2/2011 5:26 PM, Stephen Hemminger wrote:
> On Wed, 2 Mar 2011 16:10:10 -0500
> dykmanj@linux.vnet.ibm.com wrote:
>
>> +struct hf_if {
>> + u32 idx; /* 0, 1, 2, 3 ... */
>> + u32 ai; /* 0=hfi0, 1=hfi1 */
>> + char name[HF_MAX_NAME_LEN];
>> + u32 isr_id;
>> + u32 ip_addr;
>> + u32 state; /* CLOSE, OPEN */
>> + spinlock_t lock; /* lock for state */
>> + u32 sfifo_fv_polarity;
>> + u32 sfifo_slots_per_blk;
>> + u32 sfifo_packets;
>> + void __iomem *doorbell; /* mapped mmio_regs */
>> + struct hf_fifo tx_fifo;
>> + struct hf_fifo rx_fifo;
>> + struct hfi_client_info client;
>> + struct sk_buff **tx_skb; /* array to store tx
>> + 2k skb */
>> + void *sfifo_finishvec;
>> + struct net_device_stats net_stats;
>> +};
>
> You don't need net_stats in this structure if you use
> the standard netdev->stats structure instead.
>
> You won't need hf_get_stats then..
>
Ok, done in v2
Jim
^ permalink raw reply
* Re: [PATCH 24/27] HFI: hf network driver
From: Jim Dykman @ 2011-04-18 3:21 UTC (permalink / raw)
To: Ben Hutchings
Cc: netdev, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1299105612.4277.34.camel@localhost>
On 3/2/2011 5:40 PM, Ben Hutchings wrote:
> On Wed, 2011-03-02 at 16:10 -0500, dykmanj@linux.vnet.ibm.com wrote:
>> From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
>>
>> It is a separate binary because it is not strictly necessary to use the HFI.
>> This patch includes module load/unload and the window open/setup with the
>> hfi device driver.
> [...]
>> diff --git a/drivers/net/hfi/ip/Kconfig b/drivers/net/hfi/ip/Kconfig
>> new file mode 100644
>> index 0000000..1a2c21d
>> --- /dev/null
>> +++ b/drivers/net/hfi/ip/Kconfig
>> @@ -0,0 +1,9 @@
>> +config HFI_IP
>> + tristate "IP-over-HFI"
>> + depends on NETDEVICES && INET && HFI
>> + ---help---
>> + Support for the IP over HFI. It transports IP
>> + packets over HFI.
>> +
>> + To compile the driver as a module, choose M here. The module
>> + will be called hf.
>
> You actually call it hf_if! But why it is not called hfi_ip?
>
That IS a good name. Ok, we'll call it hfi_ip.
>> diff --git a/drivers/net/hfi/ip/Makefile b/drivers/net/hfi/ip/Makefile
>> new file mode 100644
>> index 0000000..59eff9b
>> --- /dev/null
>> +++ b/drivers/net/hfi/ip/Makefile
>> @@ -0,0 +1,6 @@
>> +#
>> +# Makefile for the HF IP interface for IBM eServer System p
>> +#
>> +obj-$(CONFIG_HFI_IP) += hf_if.o
>> +
>> +hf_if-objs := hf_if_main.o
>> diff --git a/drivers/net/hfi/ip/hf_if_main.c b/drivers/net/hfi/ip/hf_if_main.c
>> new file mode 100644
>> index 0000000..329baa1
>> --- /dev/null
>> +++ b/drivers/net/hfi/ip/hf_if_main.c
> [...]
>> +static int hf_inet_event(struct notifier_block *this,
>> + unsigned long event,
>> + void *ifa)
>> +{
>> + struct in_device *in_dev;
>> + struct net_device *netdev;
>> +
>> + in_dev = ((struct in_ifaddr *)ifa)->ifa_dev;
>> +
>> + netdev = in_dev->dev;
>> +
>> + if (!net_eq(dev_net(netdev), &init_net))
>> + return NOTIFY_DONE;
>> +
>> + if (event == NETDEV_UP) {
>> + struct hf_if *net_if;
>> +
>> + net_if = &(((struct hf_net *)(netdev_priv(netdev)))->hfif);
>
> Try running:
>
> # ifconfig lo down
> # ifconfig lo up
>
> and watch the explosion.
>
> You need to check that this is actually one of your devices. I've done
> this by comparing netdev->netdev_ops pointer.
>
Check added to v2.
> [...]
>> +static int hf_alloc_tx_resource(struct hf_if *net_if)
>> +{
> [...]
>> + if (net_if->tx_fifo.addr == 0) {
>> + printk(KERN_ERR "%s: hf_alloc_tx_resource: "
>> + "tx_fifo fail, size=0x%x\n",
>> + net_if->name, net_if->tx_fifo.size);
> [...]
>
> The netdev_err() and netif_err() (etc.) macros are the standard way to
> format messages relating to a net device.
>
Fixed in v2
> [...]
>> +static int hf_set_mac_addr(struct net_device *netdev, void *p)
>> +{
>> + struct hf_net *net = netdev_priv(netdev);
>> + struct hf_if *net_if = &(net->hfif);
>> +
>> + /* Mac address format: 02:ClusterID:ISR:ISR:HFI_WIN:WIN */
>> +
>> + /* Locally administered MAC address */
>> + netdev->dev_addr[0] = 0x2; /* bit6=1, bit7=0 */
>> +
>> + netdev->dev_addr[1] = 0x0; /* cluster id */
>> +
>> + *(u16 *)(&(netdev->dev_addr[2])) = (u16)(net_if->isr_id);
>> +
>> + *(u16 *)(&(netdev->dev_addr[4])) = (u16)
>> + (((net_if->ai) << HF_MAC_HFI_SHIFT) | (net_if->client.window));
>
> These two assignments should perhaps include an explicit cpu_to_be16().
>
The HFIs live in a chip on the motherboard of one specific Power7 server.
Power arch is big-endian. I'm going to leave this asis.
> [...]
>> +static int hf_net_close(struct net_device *netdev)
>> +{
>> + struct hf_net *net = netdev_priv(netdev);
>> + struct hf_if *net_if = &(net->hfif);
>> + struct hfidd_acs *p_acs = HF_ACS(net_if);
>> +
>> + if (net_if->state == HF_NET_CLOSE)
>> + return 0;
>
> I'm a bit puzzled by this. Do you not trust the networking core to keep
> track of your device state?
>
Removed in v2.
>> + spin_lock(&(net_if->lock));
>> + if (net_if->state == HF_NET_OPEN) {
>> + hf_close_ip_window(net_if, p_acs);
>> +
>> + hf_free_resource(net_if);
>> + }
>> +
>> + hf_register_hfi_ready_callback(netdev, p_acs,
>> + HFIDD_REQ_EVENT_UNREGISTER);
>> +
>> + net_if->state = HF_NET_CLOSE;
>> + spin_unlock(&(net_if->lock));
>> +
>> + return 0;
>> +}
>> +
>> +struct net_device_stats *hf_get_stats(struct net_device *netdev)
>> +{
>> + struct hf_net *net = netdev_priv(netdev);
>> + struct hf_if *net_if = &(net->hfif);
>> +
>> + return &(net_if->net_stats);
>> +}
>
> Please use the stats contained in struct net_device instead.
>
Ok
>> +static int hf_change_mtu(struct net_device *netdev, int new_mtu)
>> +{
>> + if ((new_mtu <= 0) || (new_mtu > HF_NET_MTU))
>> + return -ERANGE;
>
> Since this interface apparently only passes ARP and IPv4, the minimum
> MTU should be the minimum for IPv4, which is 68. (The spec says 576 but
> the Linux IPv4 implementation uses this value.)
>
Ok
> [...]
>> +static void hf_if_setup(struct net_device *netdev)
>> +{
>> + netdev->type = ARPHRD_HFI;
>> + netdev->mtu = HF_NET_MTU;
>> + netdev->tx_queue_len = 1000;
>> + netdev->flags = IFF_BROADCAST;
>> + netdev->hard_header_len = HF_HLEN;
>> + netdev->addr_len = HF_ALEN;
>> + netdev->needed_headroom = 0;
>> +
>> + netdev->header_ops = &hf_header_ops;
>> + netdev->netdev_ops = &hf_netdev_ops;
>> +
>> + netdev->features |= NETIF_F_SG;
>
> You can't provide NETIF_F_SG without checksum offload.
>
Removed in v2.
>> + memcpy(netdev->broadcast, hfi_bcast_addr, HF_ALEN);
>> +}
>> +
>> +static struct hf_net *hf_init_netdev(int idx, int ai)
>> +{
>> + struct net_device *netdev;
>> + struct hf_net *net;
>> + int ii;
>> + int rc;
>> + char ifname[HF_MAX_NAME_LEN];
>> +
>> + ii = (idx * MAX_HFIS) + ai;
>> + sprintf(ifname, "hf%d", ii);
>> + netdev = alloc_netdev(sizeof(struct hf_net), ifname, hf_if_setup);
>> + if (!netdev) {
>> + printk(KERN_ERR "hf_init_netdev: "
>> + "alloc_netdev for hfi%d:hf%d fail\n", ai, idx);
>> + return (struct hf_net *) -ENODEV;
>
> Use ERR_PTR() instead of writing this sort of cast yourself.
>
Ok.
> [...]
>> +static int __init hf_init_module(void)
>> +{
>> + u32 idx, ai;
>> + struct hf_net *net;
>> +
>> + memset(&hf_ginfo, 0, sizeof(struct hf_global_info));
>> +
>> + for (idx = 0; idx < MAX_HF_PER_HFI; idx++) {
>> + for (ai = 0; ai < MAX_HFIS; ai++) {
>> + net = hf_init_netdev(idx, ai);
>> + if (IS_ERR(net)) {
>> + printk(KERN_ERR "hf_init_module: hf_init_netdev"
>> + " for idx %d ai %d failed rc"
>> + " 0x%016llx\n",
>> + idx, ai, (u64)(PTR_ERR(net)));
>
> Whyever are you formatting the error like this? Use %ld and remove the
> (u64) cast.
>
>
Fixed in v2.
>> +
>> + goto err_out;
>> + }
>> +
>> + hf_ginfo.net[idx][ai] = net;
>> + }
>> + }
>> +
>> + register_inetaddr_notifier(&hf_inet_notifier);
>> +
>> + printk(KERN_INFO "hf module loaded\n");
>> + return 0;
>> +
>> +err_out:
>> + for (idx = 0; idx < MAX_HF_PER_HFI; idx++) {
>> + for (ai = 0; ai < MAX_HFIS; ai++) {
>> + net = hf_ginfo.net[idx][ai];
>> + if (net != NULL) {
>> + hf_del_netdev(net);
>> + hf_ginfo.net[idx][ai] = NULL;
>> + }
>> + }
>> + }
>> +
>> + return -EINVAL;
>
> Use the error code you were given:
>
> return PTR_ERR(net);
>
Also fixed in v2.
>> +}
>> +
>> +static void __exit hf_cleanup_module(void)
>> +{
>> + u32 idx, ai;
>> + struct hf_net *net;
>> +
>> + unregister_inetaddr_notifier(&hf_inet_notifier);
>> + for (idx = 0; idx < MAX_HF_PER_HFI; idx++) {
>> + for (ai = 0; ai < MAX_HFIS; ai++) {
>> + net = hf_ginfo.net[idx][ai];
>> + if (net != NULL) {
>> + hf_del_netdev(net);
>> + hf_ginfo.net[idx][ai] = NULL;
>> + }
>> + }
>> + }
>> +
>> + return;
>
> Redundant statement is redundant.
>
These are all removed in v2.
>> +}
> [...]
>> --- /dev/null
>> +++ b/include/linux/hfi/hf_if.h
> [...]
>> +struct hfi_ip_extended_hdr { /* 16B */
>> + u32 immediate_len:7;/* In bytes */
>> + u32 num_desc:3; /* number of descriptors */
>> + /* Logical Port ID: */
>> + u32 lpid_valid:1; /* set by sending HFI */
>> + u32 lpid:4; /* set by sending HFI */
>> + /* Ethernet Service Header is 113 bits, which is 14 bytes + 1 bit */
>> + u32 ethernet_svc_hdr_hi:1; /* Not used by HFI */
>> + char ethernet_svc_hdr[12]; /* Not used by HFI */
>> + __sum16 bcast_csum;
>> +} __packed;
>
> It looks like you're relying on gcc to treat a set of bitfields with
> type u32 and only 16 bits assigned as having a size of 2 in a packed
> structure. This might be true now, but I wouldn't want to rely on that
> being true for later versions. Why not define the set of bitfields with
> type u16?
>
They're not 16 bits long either, so I'm changing these to unsigned int
> Also the above appears to assume big-endian byte and bit order.
>
Again, Power arch is big endian and HFI is Power-only.
> [...]
>> +#define HF_ALEN 6
>> +struct hf_hwhdr {
>> + u8 h_dest[HF_ALEN];
>> + u8 h_source[HF_ALEN];
>> + __be16 h_proto;
>> +};
>> +
>> +#define HF_HLEN sizeof(struct hf_hwhdr)
> [...]
>
> This looks familiar! Maybe you should just use the existing struct
> ethhdr?
>
Ok
> Ben.
>
Jim
^ permalink raw reply
* [PATCH v2 00/27] HFI: minimal device driver/ip driver
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev; +Cc: Jim Dykman
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
The HFI ("Host Fabric Interface") network interface is the internal cluster
fabric of IBM's PERCS supercomputer. The hardware design is under US export
control, so we cannot release hardware specs. There is a writeup of
publically available information about the system available here:
http://sourceforge.net/projects/hfidevicedriver/files/docs/hfi_general_desc_v2.1.txt
hfi_core contains the resource management to set up communications paths for
network traffic. Calls are provided for kernel drivers, and also for setting
up direct user-space access to HFI windows.
hfi_ip contains the kernel network driver.
The driver has been running in the lab for several months. The full patch is
around 22000 lines, so we've split out a minimal device/network driver that
can send and receive through the simplest path. Once that much gets accepted
we'll start adding on to it.
Patches are against net-next-2.6.
Jim Dykman
Changelog:
----------
v2:
Remove return; at the end of void funcs
hfidd_free_adapter: p_acs = NULL unneccesssary, remove
remove net_stats, and use netdev->stats, remove hf_get_stats
rename network driver to hfi_ip
hf_inet_event: NETDEV_UP needs to check event is for us, check
netdev->netdev_ops == ours
change printk()s to netdev_err() and friends
hf_net_close: remove redundant CLOSE check
hf_change_mtu: minimum mtu should be 68
remove NETIF_F_SG flag
hf_init_netdev: Use ERR_PTR
hf_init_module: %ld / formatting
pass up return code from failed call
use unsigned int instead of u32 for bit fields <32 bits
use struct ethhdr instead of hf_hwhdr
hf_get_sset_count: default return -EINVAL not -EOPNOTSUPP
Remove "hfidd_callback_event: enter" message that printed on every
recv interrupt
hfidd_destroy_devices: hfidd_rmdev() after hfidd_free_adapter() so
dev_printk doesn't oops on rmmod
^ permalink raw reply
* [PATCH v2 01/27] HFI: skeleton driver
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Device driver Makefile & Kconfig plumbing plus simple mod_init and mod_exit
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/Kconfig | 2 +
drivers/net/Makefile | 2 +
drivers/net/hfi/Makefile | 1 +
drivers/net/hfi/core/Kconfig | 8 ++
drivers/net/hfi/core/Makefile | 5 +
drivers/net/hfi/core/hfidd_init.c | 142 ++++++++++++++++++++++++++++++++++++
include/linux/Kbuild | 1 +
include/linux/hfi/Kbuild | 1 +
include/linux/hfi/hfidd_client.h | 40 ++++++++++
include/linux/hfi/hfidd_internal.h | 53 +++++++++++++
10 files changed, 255 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/hfi/Makefile
create mode 100644 drivers/net/hfi/core/Kconfig
create mode 100644 drivers/net/hfi/core/Makefile
create mode 100644 drivers/net/hfi/core/hfidd_init.c
create mode 100644 include/linux/hfi/Kbuild
create mode 100644 include/linux/hfi/hfidd_client.h
create mode 100644 include/linux/hfi/hfidd_internal.h
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index dc280bc..1abbfd9 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -3436,4 +3436,6 @@ config VMXNET3
To compile this driver as a module, choose M here: the
module will be called vmxnet3.
+source "drivers/net/hfi/core/Kconfig"
+
endif # NETDEVICES
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 01b604a..e9ea418 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -304,3 +304,5 @@ obj-$(CONFIG_CAIF) += caif/
obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
obj-$(CONFIG_PCH_GBE) += pch_gbe/
obj-$(CONFIG_TILE_NET) += tile/
+
+obj-$(CONFIG_HFI) += hfi/
diff --git a/drivers/net/hfi/Makefile b/drivers/net/hfi/Makefile
new file mode 100644
index 0000000..0440cbe
--- /dev/null
+++ b/drivers/net/hfi/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_HFI) += core/
diff --git a/drivers/net/hfi/core/Kconfig b/drivers/net/hfi/core/Kconfig
new file mode 100644
index 0000000..3cd637c
--- /dev/null
+++ b/drivers/net/hfi/core/Kconfig
@@ -0,0 +1,8 @@
+config HFI
+ tristate "HFI driver support"
+ depends on IBMEBUS
+ ---help---
+ This driver supports the IBM System p HFI adapter.
+
+ To compile the driver as a module, choose M here. The module
+ will be called hfi_core.
diff --git a/drivers/net/hfi/core/Makefile b/drivers/net/hfi/core/Makefile
new file mode 100644
index 0000000..80790c6
--- /dev/null
+++ b/drivers/net/hfi/core/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the HFI device driver for IBM eServer System p
+#
+hfi_core-objs:= hfidd_init.o
+obj-$(CONFIG_HFI) += hfi_core.o
diff --git a/drivers/net/hfi/core/hfidd_init.c b/drivers/net/hfi/core/hfidd_init.c
new file mode 100644
index 0000000..e03620e
--- /dev/null
+++ b/drivers/net/hfi/core/hfidd_init.c
@@ -0,0 +1,142 @@
+/*
+ * hfidd_init.c
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
+ *
+ * (C) Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <linux/hfi/hfidd_internal.h>
+
+MODULE_VERSION("1.0");
+MODULE_DESCRIPTION("Device Driver for IBM eServer HFI for IBM System p");
+MODULE_AUTHOR("James Dykman <dykmanj@linux.vnet.ibm.com> and "
+ "Piyush Chaudhary <piyushc@linux.vnet.ibm.com>");
+MODULE_LICENSE("GPL v2");
+
+struct hfidd_global hfidd_global;
+EXPORT_SYMBOL_GPL(hfidd_global);
+
+static dev_t hfidd_dev;
+
+#define MAX_HFI_DEVS (MAX_HFIS + 1)
+
+/* Function to get our internal traces */
+static ssize_t hfidd_read(struct file *filep, char *buf, size_t count,
+ loff_t *pos)
+{
+ return 0;
+}
+
+/* Entry point for user space to do driver requests. */
+static ssize_t hfidd_cmd_write(struct file *filep, const char __user *buf,
+ size_t count, loff_t *pos)
+{
+ return 0;
+}
+
+static const struct file_operations hfidd_fops = {
+ .owner = THIS_MODULE,
+ .read = hfidd_read,
+ .write = hfidd_cmd_write,
+};
+
+/* Destroy the HFI class */
+static inline void hfidd_destroy_class(void)
+{
+ class_destroy(hfidd_global.class);
+ cdev_del(&hfidd_global.cdev);
+ unregister_chrdev_region(hfidd_dev, MAX_HFI_DEVS);
+}
+
+/* Create the HFI class */
+static int hfidd_create_class(void)
+{
+ int rc;
+
+ rc = alloc_chrdev_region(&hfidd_dev, 0, MAX_HFI_DEVS, HFIDD_DEV_NAME);
+ if (rc) {
+ printk(KERN_ERR "%s: hfidd_create_class: alloc_chrdev_region"
+ " failed rc 0x%x\n", HFIDD_DEV_NAME, rc);
+ return rc;
+ }
+
+ cdev_init(&hfidd_global.cdev, &hfidd_fops);
+ hfidd_global.cdev.owner = THIS_MODULE;
+ kobject_set_name(&hfidd_global.cdev.kobj, HFIDD_DEV_NAME);
+ rc = cdev_add(&hfidd_global.cdev, hfidd_dev, MAX_HFI_DEVS);
+ if (rc) {
+ printk(KERN_ERR "%s: hfidd_create_class cdev_add fail"
+ " rc = %d\n", HFIDD_DEV_NAME, rc);
+ goto hfidd_create_class_error1;
+ }
+
+ hfidd_global.class = class_create(THIS_MODULE, HFIDD_CLASS_NAME);
+ if (IS_ERR(hfidd_global.class)) {
+ rc = PTR_ERR(hfidd_global.class);
+ printk(KERN_ERR "%s: hfidd_create_class class_create fail rc = %d\n",
+ HFIDD_DEV_NAME, rc);
+ goto hfidd_create_class_error2;
+ }
+
+ return rc;
+
+hfidd_create_class_error2:
+ cdev_del(&hfidd_global.cdev);
+hfidd_create_class_error1:
+ unregister_chrdev_region(hfidd_dev, MAX_HFI_DEVS);
+
+ return rc;
+}
+
+static int __init hfidd_mod_init(void)
+{
+ int rc = 0;
+
+ rc = hfidd_create_class();
+ if (rc < 0) {
+ printk(KERN_ERR "%s: hfidd_mod_init: hfidd_create_class failed"
+ " rc=%d\n", HFIDD_DEV_NAME, rc);
+ return -1;
+ }
+
+ printk(KERN_INFO "IBM hfi device driver loaded sucessfully\n");
+ return 0;
+}
+
+static void __exit hfidd_mod_exit(void)
+{
+ hfidd_destroy_class();
+}
+
+module_init(hfidd_mod_init);
+module_exit(hfidd_mod_exit);
diff --git a/include/linux/Kbuild b/include/linux/Kbuild
index 75cf611..df925b4 100644
--- a/include/linux/Kbuild
+++ b/include/linux/Kbuild
@@ -3,6 +3,7 @@ header-y += can/
header-y += caif/
header-y += dvb/
header-y += hdlc/
+header-y += hfi/
header-y += isdn/
header-y += nfsd/
header-y += raid/
diff --git a/include/linux/hfi/Kbuild b/include/linux/hfi/Kbuild
new file mode 100644
index 0000000..3a742ce
--- /dev/null
+++ b/include/linux/hfi/Kbuild
@@ -0,0 +1 @@
+header-y += hfidd_client.h
diff --git a/include/linux/hfi/hfidd_client.h b/include/linux/hfi/hfidd_client.h
new file mode 100644
index 0000000..b738f4b
--- /dev/null
+++ b/include/linux/hfi/hfidd_client.h
@@ -0,0 +1,40 @@
+/*
+ * hfidd_client.h
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
+ *
+ * (C) Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#ifndef _HFIDD_CLIENT_H_
+#define _HFIDD_CLIENT_H_
+
+#define MAX_TORRENTS 1
+#define MAX_HFI_PER_TORRENT 2
+#define MAX_HFIS (MAX_TORRENTS * MAX_HFI_PER_TORRENT)
+
+#endif /* _HFIDD_CLIENT_H_ */
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
new file mode 100644
index 0000000..f5de1bb
--- /dev/null
+++ b/include/linux/hfi/hfidd_internal.h
@@ -0,0 +1,53 @@
+/*
+ * hfidd_internal.h
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
+ *
+ * (C) Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#ifndef _HFI_INTERNAL_H_
+#define _HFI_INTERNAL_H_
+
+#include <linux/fs.h>
+#include <linux/kobject.h>
+#include <linux/cdev.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#include <linux/hfi/hfidd_client.h>
+
+#define HFIDD_DEV_NAME "hfi"
+#define HFIDD_CLASS_NAME "hfi"
+
+/* DD global */
+struct hfidd_global {
+ struct cdev cdev;
+ struct class *class;
+};
+
+#endif
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 02/27] HFI: Add HFI adapter control structure
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Alloc/free of hfidd_acs to track the state of each HFI
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/Makefile | 3 +-
drivers/net/hfi/core/hfidd_adpt.c | 58 ++++++++++++++++++++++++++++++++++++
drivers/net/hfi/core/hfidd_init.c | 57 +++++++++++++++++++++++++++++++++++
drivers/net/hfi/core/hfidd_proto.h | 39 ++++++++++++++++++++++++
include/linux/hfi/hfidd_adpt.h | 45 ++++++++++++++++++++++++++++
include/linux/hfi/hfidd_internal.h | 14 ++++++++
6 files changed, 215 insertions(+), 1 deletions(-)
create mode 100644 drivers/net/hfi/core/hfidd_adpt.c
create mode 100644 drivers/net/hfi/core/hfidd_proto.h
create mode 100644 include/linux/hfi/hfidd_adpt.h
diff --git a/drivers/net/hfi/core/Makefile b/drivers/net/hfi/core/Makefile
index 80790c6..6fe4e60 100644
--- a/drivers/net/hfi/core/Makefile
+++ b/drivers/net/hfi/core/Makefile
@@ -1,5 +1,6 @@
#
# Makefile for the HFI device driver for IBM eServer System p
#
-hfi_core-objs:= hfidd_init.o
+hfi_core-objs:= hfidd_adpt.o \
+ hfidd_init.o
obj-$(CONFIG_HFI) += hfi_core.o
diff --git a/drivers/net/hfi/core/hfidd_adpt.c b/drivers/net/hfi/core/hfidd_adpt.c
new file mode 100644
index 0000000..3d315b9
--- /dev/null
+++ b/drivers/net/hfi/core/hfidd_adpt.c
@@ -0,0 +1,58 @@
+/*
+ * hfidd_adpt.c
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
+ *
+ * (C) Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/hfi/hfidd_internal.h>
+#include "hfidd_proto.h"
+
+int hfidd_alloc_adapter(struct hfidd_acs **adpt, dev_t devno, void *uiop)
+{
+
+ struct hfidd_acs *p_acs = NULL;
+
+ p_acs = kzalloc(sizeof(*p_acs), GFP_KERNEL);
+ if (p_acs == NULL)
+ return -ENOMEM;
+
+ p_acs->dev_num = devno;
+ p_acs->index = MINOR(devno);
+ p_acs->state = HFI_INVALID;
+ snprintf(p_acs->name, HFI_DEVICE_NAME_MAX - 1,
+ "%s%d", HFIDD_DEV_NAME, p_acs->index);
+
+ *adpt = p_acs;
+ return 0;
+}
+
+void hfidd_free_adapter(struct hfidd_acs *p_acs)
+{
+ kfree(p_acs);
+}
diff --git a/drivers/net/hfi/core/hfidd_init.c b/drivers/net/hfi/core/hfidd_init.c
index e03620e..114b772 100644
--- a/drivers/net/hfi/core/hfidd_init.c
+++ b/drivers/net/hfi/core/hfidd_init.c
@@ -36,6 +36,7 @@
#include <linux/device.h>
#include <linux/hfi/hfidd_internal.h>
+#include "hfidd_proto.h"
MODULE_VERSION("1.0");
MODULE_DESCRIPTION("Device Driver for IBM eServer HFI for IBM System p");
@@ -118,10 +119,52 @@ hfidd_create_class_error1:
return rc;
}
+/* Free adapter resources and the devicese */
+static void hfidd_destroy_devices(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_HFIS; i++) {
+ hfidd_free_adapter(hfidd_global.p_acs[i]);
+ hfidd_global.p_acs[i] = NULL;
+ hfidd_global.acs_cnt--;
+ }
+}
+
+/*
+ * Create the adapter structure, allocate resources and create
+ * the hfi devices
+ */
+static int hfidd_create_devices(void)
+{
+ int i, j;
+ int rc = 0;
+
+ for (i = 0; i < MAX_HFIS; i++) {
+ rc = hfidd_alloc_adapter(&(hfidd_global.p_acs[i]),
+ MKDEV(MAJOR(hfidd_dev), i), NULL);
+ if (rc) {
+ printk(KERN_ERR "%s: hfidd_create_devices: "
+ "hfidd_alloc_adapter fail rc = %d\n",
+ HFIDD_DEV_NAME, rc);
+ for (j = 0; j < i; j++) {
+ hfidd_free_adapter(hfidd_global.p_acs[j]);
+ hfidd_global.p_acs[j] = NULL;
+ hfidd_global.acs_cnt--;
+ }
+ return rc;
+ }
+ hfidd_global.acs_cnt++;
+ }
+ return rc;
+}
+
static int __init hfidd_mod_init(void)
{
int rc = 0;
+ hfidd_global.acs_cnt = 0;
+
rc = hfidd_create_class();
if (rc < 0) {
printk(KERN_ERR "%s: hfidd_mod_init: hfidd_create_class failed"
@@ -129,12 +172,26 @@ static int __init hfidd_mod_init(void)
return -1;
}
+ rc = hfidd_create_devices();
+ if (rc < 0) {
+ printk(KERN_ERR "%s: hfidd_mod_init: hfidd_create_devices"
+ " failed rc = %d\n", HFIDD_DEV_NAME, rc);
+ goto error1;
+ }
+
printk(KERN_INFO "IBM hfi device driver loaded sucessfully\n");
return 0;
+
+error1:
+ hfidd_destroy_class();
+
+ /* Returning -1 so insmod will fail */
+ return -1;
}
static void __exit hfidd_mod_exit(void)
{
+ hfidd_destroy_devices();
hfidd_destroy_class();
}
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
new file mode 100644
index 0000000..01a5ba2
--- /dev/null
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -0,0 +1,39 @@
+/*
+ * hfidd_proto.h
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com)
+ *
+ * Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#ifndef _HFIDD_PROTO_H_
+#define _HFIDD_PROTO_H_
+
+int hfidd_alloc_adapter(struct hfidd_acs **adpt, dev_t, void *uiop);
+void hfidd_free_adapter(struct hfidd_acs *p_acs);
+
+#endif
diff --git a/include/linux/hfi/hfidd_adpt.h b/include/linux/hfi/hfidd_adpt.h
new file mode 100644
index 0000000..6b1432d
--- /dev/null
+++ b/include/linux/hfi/hfidd_adpt.h
@@ -0,0 +1,45 @@
+/*
+ * hfidd_adpt.h
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
+ *
+ * (C) Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#ifndef _HFIDD_ADPT_H_
+#define _HFIDD_ADPT_H_
+
+#include <linux/hfi/hfidd_client.h>
+
+
+/* Adpt state */
+#define HFI_INVALID 0
+#define HFI_AVAIL 1
+#define HFI_GOING_UNAVAIL 2
+#define HFI_UNAVAIL 3
+
+#endif /* _HFIDD_ADPT_H_ */
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
index f5de1bb..2c58b56 100644
--- a/include/linux/hfi/hfidd_internal.h
+++ b/include/linux/hfi/hfidd_internal.h
@@ -38,16 +38,30 @@
#include <linux/cdev.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/slab.h>
#include <linux/hfi/hfidd_client.h>
+#include <linux/hfi/hfidd_adpt.h>
#define HFIDD_DEV_NAME "hfi"
#define HFIDD_CLASS_NAME "hfi"
+#define HFI_DEVICE_NAME_MAX 64
+/* hfi global */
+struct hfidd_acs {
+ dev_t dev_num;
+ char name[HFI_DEVICE_NAME_MAX];
+ unsigned int index;
+ unsigned int acs_cnt;
+ unsigned int state;
+};
+
/* DD global */
struct hfidd_global {
struct cdev cdev;
struct class *class;
+ int acs_cnt;
+ struct hfidd_acs *p_acs[MAX_HFIS];
};
#endif
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 04/27] HFI: Find HFI devices in the device tree
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_adpt.c | 10 +++
drivers/net/hfi/core/hfidd_init.c | 108 ++++++++++++++++++++++++++++++++++++
drivers/net/hfi/core/hfidd_proto.h | 1 +
include/linux/hfi/hfidd_adpt.h | 5 ++
include/linux/hfi/hfidd_client.h | 3 +
include/linux/hfi/hfidd_internal.h | 12 ++++
6 files changed, 139 insertions(+), 0 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_adpt.c b/drivers/net/hfi/core/hfidd_adpt.c
index 3d315b9..45e0c31 100644
--- a/drivers/net/hfi/core/hfidd_adpt.c
+++ b/drivers/net/hfi/core/hfidd_adpt.c
@@ -36,6 +36,7 @@
int hfidd_alloc_adapter(struct hfidd_acs **adpt, dev_t devno, void *uiop)
{
+ int ret = 0;
struct hfidd_acs *p_acs = NULL;
p_acs = kzalloc(sizeof(*p_acs), GFP_KERNEL);
@@ -48,8 +49,17 @@ int hfidd_alloc_adapter(struct hfidd_acs **adpt, dev_t devno, void *uiop)
snprintf(p_acs->name, HFI_DEVICE_NAME_MAX - 1,
"%s%d", HFIDD_DEV_NAME, p_acs->index);
+ ret = hfidd_init_adapter(p_acs, uiop);
+ if (ret)
+ goto err_exit0;
+
*adpt = p_acs;
return 0;
+
+err_exit0:
+ kfree(p_acs);
+ p_acs = NULL;
+ return ret;
}
void hfidd_free_adapter(struct hfidd_acs *p_acs)
diff --git a/drivers/net/hfi/core/hfidd_init.c b/drivers/net/hfi/core/hfidd_init.c
index 1e4898b..854d676 100644
--- a/drivers/net/hfi/core/hfidd_init.c
+++ b/drivers/net/hfi/core/hfidd_init.c
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/of.h>
#include <linux/hfi/hfidd_internal.h>
#include "hfidd_proto.h"
@@ -104,6 +105,113 @@ static void hfidd_rmdev(int ai)
device_destroy(hfidd_global.class, MKDEV(MAJOR(hfidd_dev), ai));
}
+/*
+ * Read the hfi device tree attributes and
+ * fill the hfidd_dds structure to be used by the driver
+ */
+static int hfidd_dds_init(struct hfidd_acs *p_acs, struct hfidd_dds *pdds)
+{
+ struct device_node *node;
+ struct device_node *child_node = NULL;
+ unsigned long long *lp;
+ int *p;
+ unsigned char octant;
+ unsigned char id;
+ int found = 0;
+
+ node = of_find_node_by_name(NULL, "hfi-iohub");
+ if (!node) {
+ printk(KERN_ERR "%s: hfidd_dds_init: of_find_node_by_name"
+ " 'hfi-iohub' failed\n", p_acs->name);
+ return -EINVAL;
+ }
+
+ lp = (unsigned long long *)of_get_property(node, "reg", NULL);
+ if (!lp) {
+ printk(KERN_ERR "%s: hfidd_dds_init: of_get_property"
+ " 'hfi-iohub/reg' failed\n", p_acs->name);
+ return -EINVAL;
+ }
+ pdds->torr_id = *lp;
+
+ lp = (unsigned long long *)of_get_property(node,
+ "ibm,fw-ec-level", NULL);
+ if (!lp) {
+ printk(KERN_ERR "%s: hfidd_dds_init: of_get_property"
+ " 'ibm,fw-ec-level' failed\n", p_acs->name);
+ return -EINVAL;
+ }
+ pdds->fw_ec_level = *lp;
+
+ octant = (node->full_name[strlen(node->full_name) - 1] - '0');
+ if (octant > HFI_MAX_OCTANT) {
+ printk(KERN_ERR "%s: hfidd_dds_init: invalid hfi-iohub octant"
+ " '%s'\n", node->full_name, p_acs->name);
+ return -EINVAL;
+ }
+
+ id = ((octant << HFI_SHIFT_OCTANT) | p_acs->index);
+
+ while ((child_node = of_get_next_child(node, child_node))) {
+ p = (int *)of_get_property(child_node, "reg", NULL);
+ if (!p) {
+ printk(KERN_ERR "%s: hfidd_dds_init: of_get_property "
+ "'reg' failed\n", p_acs->name);
+ return -EINVAL;
+ }
+
+ if (id == *p) {
+ pdds->hfi_id = *p;
+ found = 1;
+ break;
+ }
+ }
+
+ if (found == 0) {
+ printk(KERN_ERR "%s: hfidd_dds_init: can not find child\n",
+ p_acs->name);
+ return -EINVAL;
+ }
+
+ lp = (unsigned long long *)of_get_property(child_node,
+ "ibm,hfi-windows", NULL);
+ if (!lp) {
+ printk(KERN_ERR "%s: hfidd_dds_init: of_get_property"
+ " 'ibm,hfi-windows' failed\n", p_acs->name);
+ return -EINVAL;
+ }
+
+ pdds->window_num = (int) (*lp >> HFI_WNUM_SHIFT);
+ pdds->window_start = (int) *lp;
+
+ if (pdds->window_num > MAX_WIN_PER_HFI) {
+ printk(KERN_ERR "%s: hfidd_dds_init: Max windows exceeded,"
+ " windows=%d\n", p_acs->name, pdds->window_num);
+ return -EINVAL;
+ }
+
+ lp = (unsigned long long *)of_get_property(child_node,
+ "ibm,hfi-misc-user-base-addr", NULL);
+ if (!lp) {
+ printk(KERN_ERR "%s: hfidd_dds_init: of_get_property"
+ " 'ibm,hfi-misc-user-base-addr' failed\n", p_acs->name);
+ return -EINVAL;
+ }
+ pdds->misc_base_address = *lp;
+
+ return 0;
+}
+
+/* Initialize adapter structure */
+int hfidd_init_adapter(struct hfidd_acs *p_acs, void *uiop)
+{
+ int rc = 0;
+
+ rc = hfidd_dds_init(p_acs, &(p_acs->dds));
+ p_acs->dds.num_d_windows = HFI_DYN_WINS_DEFAULT;
+ return rc;
+}
+
/* Destroy the HFI class */
static inline void hfidd_destroy_class(void)
{
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
index 01a5ba2..e2ed4c9 100644
--- a/drivers/net/hfi/core/hfidd_proto.h
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -35,5 +35,6 @@
int hfidd_alloc_adapter(struct hfidd_acs **adpt, dev_t, void *uiop);
void hfidd_free_adapter(struct hfidd_acs *p_acs);
+int hfidd_init_adapter(struct hfidd_acs *p_acs, void *uiop);
#endif
diff --git a/include/linux/hfi/hfidd_adpt.h b/include/linux/hfi/hfidd_adpt.h
index 6b1432d..e3271e9 100644
--- a/include/linux/hfi/hfidd_adpt.h
+++ b/include/linux/hfi/hfidd_adpt.h
@@ -36,6 +36,11 @@
#include <linux/hfi/hfidd_client.h>
+#define HFI_WNUM_SHIFT 32
+#define HFI_CAUNUM_SHIFT 32
+#define HFI_SHIFT_OCTANT 3
+#define HFI_MAX_OCTANT 7
+
/* Adpt state */
#define HFI_INVALID 0
#define HFI_AVAIL 1
diff --git a/include/linux/hfi/hfidd_client.h b/include/linux/hfi/hfidd_client.h
index b738f4b..28f1693 100644
--- a/include/linux/hfi/hfidd_client.h
+++ b/include/linux/hfi/hfidd_client.h
@@ -36,5 +36,8 @@
#define MAX_TORRENTS 1
#define MAX_HFI_PER_TORRENT 2
#define MAX_HFIS (MAX_TORRENTS * MAX_HFI_PER_TORRENT)
+#define MAX_WIN_PER_HFI 256
+
+#define HFI_DYN_WINS_DEFAULT 32
#endif /* _HFIDD_CLIENT_H_ */
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
index 695d7f4..fafca96 100644
--- a/include/linux/hfi/hfidd_internal.h
+++ b/include/linux/hfi/hfidd_internal.h
@@ -46,6 +46,17 @@
#define HFIDD_DEV_NAME "hfi"
#define HFIDD_CLASS_NAME "hfi"
+struct hfidd_dds {
+ unsigned int version; /* HFI adapter type */
+ unsigned long long misc_base_address; /* Misc user base address */
+ int window_start; /* window start for this HFI */
+ int window_num; /* window count for this HFI */
+ unsigned int num_d_windows; /* number of dynamic windows */
+ unsigned long long torr_id; /* torrent chip id */
+ unsigned int hfi_id; /* HFI Unit Id */
+ unsigned long long fw_ec_level; /* Firmware Level */
+};
+
#define HFI_DEVICE_NAME_MAX 64
/* hfi global */
struct hfidd_acs {
@@ -55,6 +66,7 @@ struct hfidd_acs {
unsigned int acs_cnt;
unsigned int state;
struct device *hfidd_dev;
+ struct hfidd_dds dds;
};
/* DD global */
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 07/27] HFI: Add nMMU start/stop hypervisor calls
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
H_NMMU_START resets/inits state for the nMMU in the hypervisor.
H_NMMU_STOP cleans up hypervisor nMMU state, called on DD unload after HFIs are
stopped.
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_adpt.c | 36 +++++++++++++++++++++++++++++++++++
drivers/net/hfi/core/hfidd_hcalls.c | 33 ++++++++++++++++++++++++++++++++
drivers/net/hfi/core/hfidd_init.c | 29 +++++++++++++++++++++++++--
drivers/net/hfi/core/hfidd_proto.h | 3 ++
include/linux/hfi/hfidd_hcalls.h | 2 +
5 files changed, 100 insertions(+), 3 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_adpt.c b/drivers/net/hfi/core/hfidd_adpt.c
index d2bef84..ef795bf 100644
--- a/drivers/net/hfi/core/hfidd_adpt.c
+++ b/drivers/net/hfi/core/hfidd_adpt.c
@@ -162,6 +162,42 @@ query1:
return rc;
}
+int hfidd_start_nmmu(struct hfidd_acs *p_acs)
+{
+ long long hvrc;
+ int rc = 0;
+ struct nmmu_info *nmmu_info;
+ caddr_t laddr = NULL;
+ u64 start_time = get_jiffies_64();
+
+ rc = hfidd_get_phyp_page(p_acs, (caddr_t *)&nmmu_info, &laddr,
+ PAGE_SIZE_4K);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_start_nmmu: hfidd_get_phyp_page failed\n");
+ return -ENOMEM;
+ }
+
+ while (1) {
+ hvrc = hfi_start_nmmu(p_acs->dds.torr_id,
+ (struct nmmu_info *) laddr);
+ if (hvrc != H_BUSY)
+ break;
+ if (hfidd_age_hcall(start_time))
+ break;
+ }
+
+ if (hvrc != H_SUCCESS) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_start_nmmu: HFI_START_NMMU failed "
+ "hvrc 0x%llx\n", hvrc);
+ rc = -EPERM;
+ }
+
+ hfidd_release_phyp_page((caddr_t)nmmu_info, PAGE_SIZE_4K);
+ return rc;
+}
+
int hfidd_start_interface(struct hfidd_acs *p_acs)
{
long long hvrc = 0;
diff --git a/drivers/net/hfi/core/hfidd_hcalls.c b/drivers/net/hfi/core/hfidd_hcalls.c
index 84467b3..2ca1c8a 100644
--- a/drivers/net/hfi/core/hfidd_hcalls.c
+++ b/drivers/net/hfi/core/hfidd_hcalls.c
@@ -33,6 +33,18 @@
#include <linux/hfi/hfidd_internal.h>
#include "hfidd_proto.h"
+static inline long long h_nmmu_start(int token,
+ u64 torrent_chip_ID,
+ void *output_page_ptr)
+{
+ return plpar_hcall_norets(token, torrent_chip_ID, output_page_ptr);
+}
+
+static inline long long h_nmmu_stop(int token, u64 torrent_chip_ID)
+{
+ return plpar_hcall_norets(token, torrent_chip_ID);
+}
+
static inline long long h_hfi_start_interface(int token,
u64 HFI_chip_ID)
{
@@ -61,6 +73,27 @@ static inline long long h_hfi_query_interface(int token,
return rc;
}
+long long hfi_start_nmmu(u64 chip_id, void *nmmu_info)
+{
+ return h_nmmu_start(H_NMMU_START, chip_id, nmmu_info);
+}
+
+long long hfi_stop_nmmu(u64 chip_id)
+{
+ long long hvrc;
+ u64 start_time = get_jiffies_64();
+
+ while (1) {
+ hvrc = h_nmmu_stop(H_NMMU_STOP,
+ chip_id);
+ if (hvrc != H_BUSY)
+ break;
+ if (hfidd_age_hcall(start_time))
+ break;
+ }
+ return hvrc;
+}
+
long long hfi_hquery_interface(u64 unit_id, u64 subtype,
u64 query_p, u64 *state)
{
diff --git a/drivers/net/hfi/core/hfidd_init.c b/drivers/net/hfi/core/hfidd_init.c
index 99bacab..cbc616d 100644
--- a/drivers/net/hfi/core/hfidd_init.c
+++ b/drivers/net/hfi/core/hfidd_init.c
@@ -321,30 +321,43 @@ hfidd_create_devices_error0:
/*
* Disable message passing to each adapter by calling the
- * Stop Interface hcall.
+ * Stop Interface hcall and free phyp NMMU tables for this
+ * lpar by calling STOP NMMU
*/
static void hfidd_stop_adapter(void)
{
int i;
+ long long hvrc;
for (i = 0; i < MAX_HFIS; i++) {
hfidd_stop_interface(hfidd_global.p_acs[i],
hfidd_global.p_acs[i]->dds.hfi_id);
}
+ hvrc = hfi_stop_nmmu(hfidd_global.p_acs[0]->dds.torr_id);
+ if (hvrc != H_SUCCESS)
+ dev_printk(KERN_ERR, hfidd_global.p_acs[0]->hfidd_dev,
+ "%s: hfidd_stop_adapter: HFI_STOP_NMMU failed"
+ " hvrc = 0x%llx\n", HFIDD_DEV_NAME, hvrc);
}
/*
* Query the interface to check the logical state of HFI.
- * Enable message passing to each adapter by calling Start
- * Interface hcall.
+ * Initialize the phyp NMMU tables for this lpar by calling
+ * the START NMMU hcall and enable message passing to each
+ * adapter by calling Start Interface hcall.
*/
static int hfidd_start_adapter(void)
{
+ long long hvrc;
unsigned long long hfi_state;
int i, j;
int rc = 0;
for (i = 0; i < MAX_HFIS; i++) {
+ /* query interface before doing START_NMMU.
+ * If we crashed the LPAR a few minutes ago, we never did the
+ * stop interface and the stop nmmu. Do it now.
+ */
rc = hfidd_query_interface(hfidd_global.p_acs[i], COMP_QUERY,
hfidd_global.p_acs[i]->dds.hfi_id, &hfi_state);
if (hfi_state != NOT_STARTED) {
@@ -375,6 +388,15 @@ static int hfidd_start_adapter(void)
}
+ hfi_stop_nmmu(hfidd_global.p_acs[0]->dds.torr_id);
+ hvrc = hfidd_start_nmmu(hfidd_global.p_acs[0]);
+ if (hvrc != H_SUCCESS) {
+ dev_printk(KERN_ERR, hfidd_global.p_acs[0]->hfidd_dev,
+ "%s: hfidd_start_adapter: HFI_START_NMMU failed"
+ " hvrc = 0x%llx\n", HFIDD_DEV_NAME, hvrc);
+ return -EIO;
+ }
+
for (i = 0; i < MAX_HFIS; i++) {
rc = hfidd_start_interface(hfidd_global.p_acs[i]);
if (rc) {
@@ -403,6 +425,7 @@ hfidd_start_adapter_err:
hfidd_stop_interface(hfidd_global.p_acs[j],
hfidd_global.p_acs[j]->dds.hfi_id);
}
+ hfi_stop_nmmu(hfidd_global.p_acs[0]->dds.torr_id);
return rc;
}
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
index 6ec9245..320f41f 100644
--- a/drivers/net/hfi/core/hfidd_proto.h
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -42,8 +42,11 @@ int hfidd_get_phyp_page(struct hfidd_acs *p_acs, caddr_t *page,
void hfidd_release_phyp_page(caddr_t page, int size);
int hfidd_query_interface(struct hfidd_acs *p_acs, unsigned int subtype,
unsigned int hfi_id, unsigned long long *state);
+int hfidd_start_nmmu(struct hfidd_acs *p_acs);
int hfidd_start_interface(struct hfidd_acs *p_acs);
int hfidd_stop_interface(struct hfidd_acs *p_acs, unsigned int hfi_id);
+long long hfi_start_nmmu(u64 chip_id, void *nmmu_info);
+long long hfi_stop_nmmu(u64 chip_id);
long long hfi_hquery_interface(u64 unit_id, u64 subtype, u64 query_p,
u64 *state);
long long hfi_start_interface(u64 unit_id);
diff --git a/include/linux/hfi/hfidd_hcalls.h b/include/linux/hfi/hfidd_hcalls.h
index 5349e9e..2a374e6 100644
--- a/include/linux/hfi/hfidd_hcalls.h
+++ b/include/linux/hfi/hfidd_hcalls.h
@@ -39,6 +39,8 @@
#define H_HFI_START_INTERFACE 0xF000
#define H_HFI_QUERY_INTERFACE 0xF004
#define H_HFI_STOP_INTERFACE 0xF008
+#define H_NMMU_START 0xF028
+#define H_NMMU_STOP 0xF02C
#define EEH_QUERY 1
#define COMP_QUERY 2
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 09/27] HFI: Add HFI window resource tracking
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
An HFI window is very roughly similar to an infiniband UD queue pair.
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_adpt.c | 64 ++++++++++++++++++++++++++++++++++++
drivers/net/hfi/core/hfidd_proto.h | 2 +
include/linux/hfi/hfidd_adpt.h | 10 ++++++
include/linux/hfi/hfidd_client.h | 27 +++++++++++++++
include/linux/hfi/hfidd_internal.h | 43 ++++++++++++++++++++++++
5 files changed, 146 insertions(+), 0 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_adpt.c b/drivers/net/hfi/core/hfidd_adpt.c
index ef795bf..b99303b 100644
--- a/drivers/net/hfi/core/hfidd_adpt.c
+++ b/drivers/net/hfi/core/hfidd_adpt.c
@@ -66,6 +66,16 @@ int hfidd_alloc_adapter(struct hfidd_acs **adpt, dev_t devno, void *uiop)
goto err_exit0;
*adpt = p_acs;
+
+ /* alloc window structures */
+ ret = hfidd_alloc_windows(p_acs);
+ if (ret) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_alloc_adapter: hfidd_alloc_windows failed, "
+ "ret = 0x%x\n", ret);
+ goto err_exit0;
+ }
+
return 0;
err_exit0:
@@ -76,9 +86,63 @@ err_exit0:
void hfidd_free_adapter(struct hfidd_acs *p_acs)
{
+ hfidd_free_windows(p_acs);
kfree(p_acs);
}
+int hfidd_alloc_windows(struct hfidd_acs *p_acs)
+{
+ int i;
+
+ p_acs->win = kzalloc(sizeof(*p_acs->win) * p_acs->dds.window_num,
+ GFP_KERNEL);
+
+ if (p_acs->win == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_alloc_windows: kzalloc p_acs->win failed\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < p_acs->dds.window_num; i++) {
+ p_acs->win[i] = kzalloc(sizeof(*(p_acs->win[i])),
+ GFP_KERNEL);
+ if (p_acs->win[i] == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_alloc_windows: kzalloc win 0x%x "
+ "failed\n", i);
+ hfidd_free_windows(p_acs);
+ return -ENOMEM;
+ }
+
+ /* Initialize window fields */
+ spin_lock_init(&(p_acs->win[i]->win_lock));
+
+ p_acs->win[i]->ai = p_acs->index;
+ p_acs->win[i]->index = p_acs->dds.window_start + i;
+
+ if (p_acs->win[i]->index < (p_acs->dds.window_start +
+ MAX_D_WIN_PER_HFI)) {
+ p_acs->win[i]->type = HFIDD_DYNAMIC_WIN;
+ } else {
+ p_acs->win[i]->type = HFIDD_RESERVE_WIN;
+ }
+ p_acs->win[i]->state = WIN_AVAILABLE;
+ }
+ return 0;
+}
+
+void hfidd_free_windows(struct hfidd_acs *p_acs)
+{
+ int i;
+
+ for (i = 0; i < p_acs->dds.window_num; i++) {
+ kfree(p_acs->win[i]);
+ p_acs->win[i] = NULL;
+ }
+ kfree(p_acs->win);
+ p_acs->win = NULL;
+}
+
/* Allocate the page for the HCALL */
int hfidd_get_phyp_page(struct hfidd_acs *p_acs, caddr_t *page, caddr_t *laddr,
int size)
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
index 320f41f..c61387e 100644
--- a/drivers/net/hfi/core/hfidd_proto.h
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -35,6 +35,8 @@
int hfidd_alloc_adapter(struct hfidd_acs **adpt, dev_t, void *uiop);
void hfidd_free_adapter(struct hfidd_acs *p_acs);
+int hfidd_alloc_windows(struct hfidd_acs *p_acs);
+void hfidd_free_windows(struct hfidd_acs *p_acs);
int hfidd_init_adapter(struct hfidd_acs *p_acs, void *uiop);
int hfidd_age_hcall(u64 time_start);
int hfidd_get_phyp_page(struct hfidd_acs *p_acs, caddr_t *page,
diff --git a/include/linux/hfi/hfidd_adpt.h b/include/linux/hfi/hfidd_adpt.h
index e3271e9..babdb14 100644
--- a/include/linux/hfi/hfidd_adpt.h
+++ b/include/linux/hfi/hfidd_adpt.h
@@ -47,4 +47,14 @@
#define HFI_GOING_UNAVAIL 2
#define HFI_UNAVAIL 3
+/* HFI window states */
+#define WIN_AVAILABLE 0
+#define WIN_RESERVED 1
+#define WIN_OPENED 2
+#define WIN_SUSPENDED 3
+#define WIN_ERROR 4
+#define WIN_HERROR 5
+#define WIN_PENDING 6
+#define WIN_FAIL_CLOSE 7
+
#endif /* _HFIDD_ADPT_H_ */
diff --git a/include/linux/hfi/hfidd_client.h b/include/linux/hfi/hfidd_client.h
index b2ebd01..c3c8fef 100644
--- a/include/linux/hfi/hfidd_client.h
+++ b/include/linux/hfi/hfidd_client.h
@@ -64,6 +64,33 @@ struct hfi_req_hdr {
};
#define HFIDD_REQ_HDR_SIZE sizeof(struct hfi_req_hdr)
+struct fifo_info {
+ struct hfi_64b eaddr;
+ unsigned long long size; /* bytes */
+};
+
+#define HFIDD_IP_WIN 1 /* IP windows get broadcasts forwarded
+ to them... */
+#define HFIDD_KERNEL_WIN 2 /* ... other kernel windows do not */
+#define HFIDD_RESERVE_WIN 3 /* Must be reserved by job scheduler */
+#define HFIDD_DYNAMIC_WIN 4 /* First come, first served. Window# is
+ returned */
+struct hfi_client_info {
+ struct hfi_req_hdr hdr;
+
+ unsigned int window;
+ unsigned int win_type; /* HFIDD_*_WIN */
+ unsigned int job_id;
+ unsigned int protection_key_flag;
+ unsigned int protection_key;
+ unsigned int local_isrid; /* Output */
+ struct fifo_info sfifo;
+ struct fifo_info rfifo;
+ struct hfi_64b sfifo_finish_vec;
+ unsigned int sfifo_lkey; /* Output */
+ struct hfi_64b mmio_regs; /* Output */
+};
+
#define MAX_TORRENTS 1
#define MAX_HFI_PER_TORRENT 2
#define MAX_HFIS (MAX_TORRENTS * MAX_HFI_PER_TORRENT)
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
index 311f906..a36c244 100644
--- a/include/linux/hfi/hfidd_internal.h
+++ b/include/linux/hfi/hfidd_internal.h
@@ -59,9 +59,13 @@
#include <asm/pgalloc.h>
#include <asm/ibmebus.h>
#include <linux/kthread.h>
+
#include <linux/hfi/hfidd_client.h>
#include <linux/hfi/hfidd_adpt.h>
#include <linux/hfi/hfidd_hcalls.h>
+
+#define MAX_D_WIN_PER_HFI (p_acs->dds.num_d_windows)
+
#define HFIDD_DEV_NAME "hfi"
#define HFIDD_CLASS_NAME "hfi"
@@ -76,6 +80,44 @@ struct hfidd_dds {
unsigned long long fw_ec_level; /* Firmware Level */
};
+struct hfidd_fifo {
+ unsigned long long eaddr;
+ unsigned long long size;
+};
+
+#define IRQ_NAME_SIZE 20
+
+struct hfidd_window {
+ spinlock_t win_lock; /* lock for window */
+ int index;
+ unsigned int type; /* dynamic/scheduled */
+ int state;
+
+ unsigned int ai; /* index to p_acs */
+ unsigned int is_ip;
+
+ unsigned int job_id;
+ unsigned int pid;
+ unsigned int protection_key_flag; /* by job/task */
+
+ unsigned int recv_intr; /* Recv interrupt */
+ unsigned int send_intr; /* Send interrupt */
+ char recv_name[IRQ_NAME_SIZE];
+ char send_name[IRQ_NAME_SIZE];
+
+ uid_t uid;
+
+ struct hfi_client_info client_info; /* From user input */
+ struct win_open_info *win_open_info_p; /* virtual addr
+ OPEN_WINDOW hcall */
+ caddr_t win_open_info_laddr; /* logical addr
+ OPEN_WINDOW hcall */
+ unsigned long long mmio_regs; /* logical addr from
+ OPEN WINDOW hcall */
+ struct hfidd_vlxmem *sfifo_x_tab;
+ struct hfidd_vlxmem *rfifo_x_tab;
+};
+
#define HFI_DEVICE_NAME_MAX 64
/* hfi global */
struct hfidd_acs {
@@ -87,6 +129,7 @@ struct hfidd_acs {
unsigned int isr;
+ struct hfidd_window **win;
struct device *hfidd_dev;
struct hfidd_dds dds;
};
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 15/27] HFI: Set up nMMU page tables for the send and receive fifos
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_proto.h | 3 +
drivers/net/hfi/core/hfidd_window.c | 259 ++++++++++++++++++++++++++++++++++-
include/linux/hfi/hfidd_hcalls.h | 16 ++
include/linux/hfi/hfidd_internal.h | 2 +
4 files changed, 279 insertions(+), 1 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
index fb9c8c8..ff39a02 100644
--- a/drivers/net/hfi/core/hfidd_proto.h
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -54,6 +54,9 @@ int hfidd_get_page_num(struct hfidd_acs *p_acs, void *start_addr,
int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
struct hfi_client_info *user_p,
struct hfi_client_info *out_p);
+int hfi_register_rpages(struct hfidd_acs *p_acs, unsigned long long mr_handle,
+ unsigned int submr, struct hfidd_vlxmem *xtab_p,
+ unsigned int *mapped_pages);
int hfidd_get_phyp_page(struct hfidd_acs *p_acs, caddr_t *page,
caddr_t *laddr, int size);
void hfidd_release_phyp_page(caddr_t page, int size);
diff --git a/drivers/net/hfi/core/hfidd_window.c b/drivers/net/hfi/core/hfidd_window.c
index de2e56d..6d90af6 100644
--- a/drivers/net/hfi/core/hfidd_window.c
+++ b/drivers/net/hfi/core/hfidd_window.c
@@ -359,6 +359,220 @@ static int hfi_validate_window_parm(struct hfidd_acs *p_acs,
return 0;
}
+
+/*
+ * Map the Effective Address pages for Memory Regions.
+ * If more than one page, need to setup a page containing
+ * all the effective address pages
+ */
+int hfi_register_rpages(struct hfidd_acs *p_acs,
+ unsigned long long mr_handle,
+ unsigned int submr,
+ struct hfidd_vlxmem *xtab_p,
+ unsigned int *mapped_pages)
+{
+ unsigned int map_num;
+ long long hvrc = 0;
+ unsigned int num_page_left, num_page_total;
+ char *effective_addr;
+ void *l_pages;
+ void *hcall_array = NULL;
+ unsigned long long logical_hcall_array = 0;
+ unsigned long long logical_addr = 0;
+ struct page_num_code num_page_sz;
+ int rc = 0;
+
+ effective_addr = xtab_p->m_addr;
+ num_page_total = xtab_p->num_page_sz.num_code.fields.pg_num;
+ num_page_sz.num_code.fields.pg_code =
+ xtab_p->num_page_sz.num_code.fields.pg_code;
+ l_pages = xtab_p->l_pages;
+
+ if (num_page_total > MIN_NUM_PAGES_NMMU_HCALL) {
+ hcall_array = (void *)__get_free_pages(GFP_KERNEL,
+ get_order(PAGE_SIZE_4K));
+ if (hcall_array == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_register_rpages: __get_free_pages "
+ "failed\n");
+ return -ENOMEM;
+ }
+
+ logical_hcall_array = __pa(hcall_array);
+ memset(hcall_array, 0, PAGE_SIZE_4K);
+ }
+
+ num_page_left = num_page_total;
+ while (num_page_left > 0) {
+ if (num_page_left > MAX_NUM_PAGES_NMMU_HCALL)
+ map_num = MAX_NUM_PAGES_NMMU_HCALL;
+ else
+ map_num = num_page_left;
+
+ num_page_sz.num_code.fields.pg_num = map_num;
+
+ if (map_num == MIN_NUM_PAGES_NMMU_HCALL) {
+ logical_addr = *(unsigned long long *)(l_pages);
+ } else {
+ memcpy(hcall_array, l_pages,
+ sizeof(unsigned long long) *
+ map_num);
+ logical_addr = logical_hcall_array;
+ }
+
+ hvrc = hfi_modify_mr(p_acs->dds.torr_id,
+ (unsigned long long)NMMU_MAP,
+ (unsigned long long)mr_handle,
+ (unsigned long long)submr,
+ (unsigned long long)effective_addr,
+ logical_addr,
+ (unsigned long long)
+ num_page_sz.num_code.llu_value);
+
+ if (hvrc != H_SUCCESS) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_register_rpages: HFI_MODIFY_MR "
+ "failed, map_num=0x%x, m_addr=0x%llx\n",
+ map_num, (unsigned long long)effective_addr);
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_register_rpages: HFI_MODIFY_MR "
+ "failed, page_sz=0x%llx, hvrc=0x%llx\n",
+ xtab_p->page_sz, hvrc);
+ rc = -EINVAL;
+ break;
+ }
+
+ effective_addr += map_num * (xtab_p->map_page_sz);
+ l_pages += map_num * sizeof(unsigned long long);
+ num_page_left -= map_num;
+ }
+
+ /* pass back the number of pages successfully mapped */
+ if (mapped_pages)
+ *mapped_pages = num_page_total - num_page_left;
+ if (num_page_total > MIN_NUM_PAGES_NMMU_HCALL)
+ free_pages((unsigned long)hcall_array, get_order(PAGE_SIZE_4K));
+
+ vfree(xtab_p->l_pages);
+ xtab_p->l_pages = NULL;
+ return rc;
+}
+
+/*
+ * Setup Memory regions for FIFOs. First call
+ * ALLOCATE MR hcall and then MODIFY MR hcall with MAP flag.
+ */
+static int hfi_register_MMU(struct hfidd_acs *p_acs, unsigned int win_index,
+ unsigned int jid, struct hfidd_vlxmem *xtab_p)
+{
+ long long hvrc = 0;
+ int rc = 0;
+ unsigned long long access_ctl;
+ unsigned int page_code;
+ unsigned long long l_key = 0;
+ unsigned long long liobn = 0;
+ caddr_t addr;
+
+ page_code = (xtab_p->num_page_sz.num_code.fields.pg_code >>
+ HFI_PAGE_CODE_SHIFT) & PAGE_CODE_MASK;
+
+ /* primary and second must be same size */
+ access_ctl = (page_code << HFI_PRI_PAGE_SIZE_SHIFT) |
+ (page_code << HFI_SEC_PAGE_SIZE_SHIFT) |
+ (1 << HFI_ELWA_SHIFT);
+ access_ctl = access_ctl << HFI_ACCESS_CTL_SHIFT;
+
+ hvrc = hfi_allocate_mr(p_acs->dds.torr_id,
+ NMMU_MR,
+ (unsigned long long)
+ (xtab_p->e_addr), /* aligned userinput addr */
+ (unsigned long long)
+ (xtab_p->num_page * xtab_p->page_sz),
+ access_ctl,
+ (unsigned long long)jid,
+ (unsigned long long)xtab_p->mr_handle,
+ (unsigned long long *)&(xtab_p->mr_handle),
+ &l_key,
+ &liobn);
+
+ xtab_p->l_key = (unsigned int)l_key;
+ addr = xtab_p->e_addr;
+ if (hvrc != H_SUCCESS) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_register_MMU: HFI_ALLOCATE_MR failed, "
+ "hvrc = 0x%llx\n", hvrc);
+ return -EINVAL;
+ }
+
+ rc = hfi_register_rpages(p_acs, xtab_p->mr_handle, 0, xtab_p, NULL);
+ if (rc != 0) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_register_MMU: hfi_register_rpages failed, "
+ "rc = 0x%x\n", rc);
+
+ hvrc = hfi_free_mr(p_acs->dds.torr_id,
+ NMMU_MR,
+ (unsigned long long)xtab_p->mr_handle,
+ 0);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* Call FREE MR hcall to free the FIFOs and RDMA context memory regions */
+static int hfi_unregister_MMU(struct hfidd_acs *p_acs,
+ struct hfidd_vlxmem *xtab_p)
+{
+ long long hvrc = 0;
+ int rc = 0;
+
+ hvrc = hfi_free_mr(p_acs->dds.torr_id,
+ NMMU_MR,
+ (unsigned long long)xtab_p->mr_handle,
+ 0);
+ if (hvrc != H_SUCCESS) {
+ rc = -EIO;
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_unregister_MMU: HFI_FREE_MR failed, "
+ "hvrc = 0x%llx\n", hvrc);
+ }
+ return rc;
+}
+
+/* Setup all the window Memory Regions needed for network traffic */
+static int hfi_setup_window_in_MMU(struct hfidd_acs *p_acs,
+ unsigned int is_userspace, struct hfidd_window *win_p)
+{
+ int rc = 0;
+
+ /* Register sfifo and finish vector memory in MMU */
+ rc = hfi_register_MMU(p_acs, win_p->index, win_p->job_id,
+ win_p->sfifo_x_tab);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_setup_window_in_MMU: sfifo register "
+ "failed, rc = 0x%x\n", rc);
+ goto sfifo_err;
+ }
+
+ /* Register rfifo */
+ rc = hfi_register_MMU(p_acs, win_p->index, win_p->job_id,
+ win_p->rfifo_x_tab);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_setup_window_in_MMU: rfifo register "
+ "failed, rc = 0x%x\n", rc);
+ goto rfifo_err;
+ }
+
+ return 0;
+
+rfifo_err:
+ hfi_unregister_MMU(p_acs, win_p->sfifo_x_tab);
+sfifo_err:
+ return rc;
+}
+
static int hfi_xlate_fifos(struct hfidd_acs *p_acs,
unsigned int is_userspace,
struct hfidd_window *win_p,
@@ -399,7 +613,7 @@ hfi_xlate_fifos_err1:
return rc;
}
-int hfi_unxlate_fifos(struct hfidd_acs *p_acs, unsigned int is_userspace,
+static int hfi_unxlate_fifos(struct hfidd_acs *p_acs, unsigned int is_userspace,
struct hfidd_window *win_p, struct hfi_client_info *client_p)
{
int rc = 0;
@@ -451,6 +665,15 @@ hfi_alloc_xlate_tab_err1:
return -ENOMEM;
}
+static void hfi_free_win_resource(struct hfidd_acs *p_acs,
+ unsigned int is_userspace,
+ struct hfidd_window *win_p,
+ struct hfi_client_info *client_p)
+{
+ hfi_unxlate_fifos(p_acs, is_userspace, win_p, client_p);
+ hfi_free_xlate_tab(win_p);
+}
+
static int hfi_alloc_win_resource(struct hfidd_acs *p_acs,
unsigned int is_userspace,
struct hfidd_window *win_p,
@@ -478,6 +701,30 @@ static int hfi_alloc_win_resource(struct hfidd_acs *p_acs,
return 0;
}
+static int hfi_setup_window_parm(struct hfidd_acs *p_acs,
+ unsigned int is_userspace,
+ struct hfidd_window *win_p,
+ struct hfi_client_info *client_p)
+{
+ int rc = 0;
+
+ /* Copy client info into window */
+ memcpy(&(win_p->client_info), client_p, sizeof(struct hfi_client_info));
+
+ /* Call hcall to allocate/map MR in the MMU */
+ rc = hfi_setup_window_in_MMU(p_acs, is_userspace, win_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_setup_window_parm: hfi_setup_window_in_MMU "
+ "failed, rc = 0x%x\n", rc);
+ goto setup_window_parm_err1;
+ }
+ return 0;
+
+setup_window_parm_err1:
+ return rc;
+}
+
/*
* Allows an user/kernel window to send/receive network traffic thru HFI
* adapter. This function will allocate the system resources needed to open
@@ -528,9 +775,19 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
goto hfidd_open_window_func_err2;
}
+ rc = hfi_setup_window_parm(p_acs, is_userspace, win_p, local_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_open_window_func: hfi_setup_window_parm "
+ "failed, rc = 0x%x\n", rc);
+ goto hfidd_open_window_func_err3;
+ }
+
kfree(local_p);
return rc;
+hfidd_open_window_func_err3:
+ hfi_free_win_resource(p_acs, is_userspace, win_p, local_p);
hfidd_open_window_func_err2:
hfi_restore_window_parm(p_acs, win_p);
hfidd_open_window_func_err1:
diff --git a/include/linux/hfi/hfidd_hcalls.h b/include/linux/hfi/hfidd_hcalls.h
index 9fa87c5..3c9f556 100644
--- a/include/linux/hfi/hfidd_hcalls.h
+++ b/include/linux/hfi/hfidd_hcalls.h
@@ -45,7 +45,23 @@
#define H_NMMU_FREE_RESOURCE 0xF034
#define H_NMMU_MODIFY_RESOURCE 0xF03C
+#define NMMU_MR 0
+
+#define NMMU_MAP 1
+#define NMMU_UNMAP 0
+#define NMMU_CHECK 2
+
#define HFI_PAGE_CODE_SHIFT 28
+#define HFI_PRI_PAGE_SIZE_SHIFT 24
+#define HFI_ELWA_SHIFT 23
+#define HFI_ERWA_SHIFt 22
+#define HFI_ERRA_SHIFT 21
+#define HFI_ERAO_SHIFT 20
+#define HFI_ESMR_SHIFT 18
+#define HFI_SEC_PAGE_SIZE_SHIFT 14
+#define HFI_SUBMR_NUM_SHIFT 11
+
+#define HFI_ACCESS_CTL_SHIFT 32
#define EEH_QUERY 1
#define COMP_QUERY 2
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
index 216546b..0d6b77b 100644
--- a/include/linux/hfi/hfidd_internal.h
+++ b/include/linux/hfi/hfidd_internal.h
@@ -66,6 +66,8 @@
#include <linux/hfi/hfidd_xlat_map.h>
#define MAX_D_WIN_PER_HFI (p_acs->dds.num_d_windows)
+#define MAX_NUM_PAGES_NMMU_HCALL 512
+#define MIN_NUM_PAGES_NMMU_HCALL 1
#define HFIDD_DEV_NAME "hfi"
#define HFIDD_CLASS_NAME "hfi"
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 17/27] HFI: Set up and call the open window hypercall
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_window.c | 179 +++++++++++++++++++++++++++++++++++
include/linux/hfi/hfidd_hcalls.h | 2 +
2 files changed, 181 insertions(+), 0 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_window.c b/drivers/net/hfi/core/hfidd_window.c
index 6d90af6..c20277b 100644
--- a/drivers/net/hfi/core/hfidd_window.c
+++ b/drivers/net/hfi/core/hfidd_window.c
@@ -359,6 +359,105 @@ static int hfi_validate_window_parm(struct hfidd_acs *p_acs,
return 0;
}
+/*
+ * Setup a page for phyp with the window parameters needed for
+ * OPEN WINDOW hcall
+ */
+int hfi_build_window_info(struct hfidd_acs *p_acs, struct hfidd_window *win_p)
+{
+ caddr_t laddr;
+
+#define WIN_INFO (win_p->win_open_info_p)
+#define CLIENT_INFO (win_p->client_info)
+
+ /* OPEN WINDOW hcall requires a page to pass arguments */
+ win_p->win_open_info_p = (struct win_open_info *)
+ __get_free_pages(GFP_KERNEL, get_order(PAGE_SIZE_4K));
+ if (win_p->win_open_info_p == NULL) {
+
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_build_window_info: ___get_free_pages failed\n");
+ return -ENOMEM;
+ }
+ memset((void *)(win_p->win_open_info_p), 0, PAGE_SIZE_4K);
+
+ /* Translate virtual adress into logical addres */
+ laddr = (caddr_t)__pa((caddr_t)win_p->win_open_info_p);
+
+ win_p->win_open_info_laddr = laddr;
+ WIN_INFO->job_id = CLIENT_INFO.job_id;
+ WIN_INFO->protection_domain = win_p->job_id;
+
+ WIN_INFO->sfifo_base_eaddr = CLIENT_INFO.sfifo.eaddr.use.allu;
+ WIN_INFO->sfifo_lkey = win_p->sfifo_x_tab->l_key;
+ WIN_INFO->sfifo_size = CLIENT_INFO.sfifo.size;
+ WIN_INFO->sfifo_finish_vec = CLIENT_INFO.sfifo_finish_vec.use.allu;
+
+ WIN_INFO->rfifo_base_eaddr = CLIENT_INFO.rfifo.eaddr.use.allu;
+ WIN_INFO->rfifo_lkey = win_p->rfifo_x_tab->l_key;
+ WIN_INFO->rfifo_size = CLIENT_INFO.rfifo.size;
+
+ /* Save IP context */
+ WIN_INFO->is_ip_window = win_p->is_ip;
+ if (win_p->is_ip) {
+ WIN_INFO->multicast_enable = HFI_MULTICAST_ENABLE;
+ WIN_INFO->disable_src_isr_id_stamp = 0;
+ WIN_INFO->logical_port_id_valid = 0;
+ WIN_INFO->logical_port_id = 0;
+ }
+
+ return 0;
+}
+
+/* Free the phyp page used at OPEN WINDOW hcall */
+static inline void hfi_destroy_window_info(struct hfidd_acs *p_acs,
+ struct hfidd_window *win_p)
+{
+ free_pages((unsigned long)win_p->win_open_info_p,
+ get_order(PAGE_SIZE_4K));
+ win_p->win_open_info_p = NULL;
+}
+
+/* Call to OPEN WINDOW hcall */
+static int hfi_hcall_to_open_window(struct hfidd_acs *p_acs,
+ struct hfidd_window *win_p)
+{
+ int rc = 0;
+ long long hvrc = 0;
+ u64 ummio_regs;
+ u64 pmmio_regs;
+ u64 send_intr;
+ u64 recv_intr;
+
+ hvrc = hfi_open_window(p_acs->dds.hfi_id,
+ win_p->index,
+ H_OPEN,
+ (u64)win_p->win_open_info_laddr,
+ &ummio_regs,
+ &pmmio_regs,
+ &send_intr,
+ &recv_intr);
+
+ if (hvrc != H_SUCCESS) {
+ if (hvrc == H_HARDWARE) {
+ win_p->state = WIN_HERROR;
+ rc = -EIO;
+ } else {
+ rc = -EINVAL;
+ }
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_hcall_to_open_window: OPEN WINDOW failed, "
+ "hvrc=0x%llx\n", hvrc);
+ return rc;
+ }
+
+ /* Copy mmio_regs logical page from OPEN_WINDOW hcall */
+ win_p->mmio_regs = ummio_regs;
+ win_p->send_intr = (unsigned int)send_intr;
+ win_p->recv_intr = (unsigned int)recv_intr;
+
+ return 0;
+}
/*
* Map the Effective Address pages for Memory Regions.
@@ -573,6 +672,31 @@ sfifo_err:
return rc;
}
+/* Free all the window memory regions */
+static int hfi_takedown_window_in_MMU(struct hfidd_acs *p_acs,
+ unsigned int is_userspace, struct hfidd_window *win_p)
+{
+ int rc = 0;
+
+ rc = hfi_unregister_MMU(p_acs, win_p->rfifo_x_tab);
+ if (rc != 0) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_takedown_window_in_MMU: rfifo mr failed,"
+ "rc = 0x%x\n", rc);
+ return rc;
+ }
+
+ rc = hfi_unregister_MMU(p_acs, win_p->sfifo_x_tab);
+ if (rc != 0) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_takedown_window_in_MMU: sfifo mr failed,"
+ "rc = 0x%x\n", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
static int hfi_xlate_fifos(struct hfidd_acs *p_acs,
unsigned int is_userspace,
struct hfidd_window *win_p,
@@ -701,6 +825,19 @@ static int hfi_alloc_win_resource(struct hfidd_acs *p_acs,
return 0;
}
+static int hfi_destroy_window_parm(struct hfidd_acs *p_acs,
+ unsigned int is_userspace,
+ struct hfidd_window *win_p,
+ struct hfi_client_info *client_p)
+{
+ int rc = 0;
+
+ hfi_destroy_window_info(p_acs, win_p);
+
+ rc = hfi_takedown_window_in_MMU(p_acs, is_userspace, win_p);
+ return rc;
+}
+
static int hfi_setup_window_parm(struct hfidd_acs *p_acs,
unsigned int is_userspace,
struct hfidd_window *win_p,
@@ -719,8 +856,20 @@ static int hfi_setup_window_parm(struct hfidd_acs *p_acs,
"failed, rc = 0x%x\n", rc);
goto setup_window_parm_err1;
}
+
+ /* Build window information for OPEN WINDOW hcall */
+ rc = hfi_build_window_info(p_acs, win_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_setup_window_parm: hfi_build_window_info "
+ "failed, rc = 0x%x\n", rc);
+ goto setup_window_parm_err2;
+ }
+
return 0;
+setup_window_parm_err2:
+ hfi_takedown_window_in_MMU(p_acs, is_userspace, win_p);
setup_window_parm_err1:
return rc;
}
@@ -783,9 +932,39 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
goto hfidd_open_window_func_err3;
}
+ rc = hfi_hcall_to_open_window(p_acs, win_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_open_window_func: hfi_hcall_to_open_window "
+ "failed, rc = 0x%x\n", rc);
+ goto hfidd_open_window_func_err4;
+ }
+
+ /* tell user the local ISR id */
+ local_p->local_isrid = p_acs->isr;
+ win_p->client_info.local_isrid = p_acs->isr;
+
+ /* Copy out the client info back to user */
+ rc = hfi_copy_to_user((void *)out_p, (void *)local_p,
+ is_userspace, sizeof(struct hfi_client_info));
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_open_window_func: hfi_copy_to_user "
+ "failed, rc = 0x%x\n", rc);
+ goto hfidd_open_window_func_err4;
+ }
+
+ spin_lock(&(win_p->win_lock));
+ /* Update the window information */
+ win_p->pid = current->tgid;
+ win_p->state = WIN_OPENED;
+ spin_unlock(&(win_p->win_lock));
+
kfree(local_p);
return rc;
+hfidd_open_window_func_err4:
+ hfi_destroy_window_parm(p_acs, is_userspace, win_p, local_p);
hfidd_open_window_func_err3:
hfi_free_win_resource(p_acs, is_userspace, win_p, local_p);
hfidd_open_window_func_err2:
diff --git a/include/linux/hfi/hfidd_hcalls.h b/include/linux/hfi/hfidd_hcalls.h
index a97bb5e..1e007c5 100644
--- a/include/linux/hfi/hfidd_hcalls.h
+++ b/include/linux/hfi/hfidd_hcalls.h
@@ -70,6 +70,8 @@
#define HFI_ACCESS_CTL_SHIFT 32
+#define HFI_MULTICAST_ENABLE 1
+
struct win_open_info {
/* Hyp Feedback */
unsigned long long hypervisor_capabilities;
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 14/27] HFI: Add hypercalls to create/modify/free page tables in the nMMU
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_hcalls.c | 124 +++++++++++++++++++++++++++++++++++
drivers/net/hfi/core/hfidd_proto.h | 15 ++++
include/linux/hfi/hfidd_hcalls.h | 3 +
3 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_hcalls.c b/drivers/net/hfi/core/hfidd_hcalls.c
index 2ca1c8a..aabb2a8 100644
--- a/drivers/net/hfi/core/hfidd_hcalls.c
+++ b/drivers/net/hfi/core/hfidd_hcalls.c
@@ -45,6 +45,64 @@ static inline long long h_nmmu_stop(int token, u64 torrent_chip_ID)
return plpar_hcall_norets(token, torrent_chip_ID);
}
+static inline long long h_nmmu_allocate_resource(int token,
+ u64 torrent_chip_ID,
+ u64 resource_name,
+ u64 eaddr,
+ u64 memory_region_size,
+ u64 access_controls,
+ u64 protection_domain,
+ u64 MR_Handle_In,
+ u64 *MR_Handle_out,
+ u64 *L_Key,
+ u64 *liobn)
+{
+ u64 hyp_outputs[PLPAR_HCALL9_BUFSIZE];
+ long long rc;
+
+ rc = plpar_hcall9(token, (unsigned long *)hyp_outputs,
+ torrent_chip_ID, resource_name, eaddr,
+ memory_region_size, access_controls,
+ protection_domain, MR_Handle_In);
+ *MR_Handle_out = hyp_outputs[0]; /* 1st ret value */
+ *L_Key = hyp_outputs[1]; /* 2nd */
+ *liobn = hyp_outputs[3]; /* 4th */
+
+ return rc;
+}
+
+static inline long long h_nmmu_free_resource(int token,
+ u64 torrent_chip_ID,
+ u64 resource_name,
+ u64 MR_Handle,
+ u64 subregion)
+{
+ return plpar_hcall_norets(token,
+ torrent_chip_ID,
+ resource_name,
+ MR_Handle,
+ subregion);
+}
+
+static inline long long h_nmmu_modify_resource(int token,
+ u64 torrent_chip_ID,
+ u64 request,
+ u64 MR_Handle,
+ u64 subregion,
+ u64 eaddr,
+ u64 laddr,
+ u64 num_pg_sz)
+{
+ return plpar_hcall_norets(token,
+ torrent_chip_ID,
+ request,
+ MR_Handle,
+ subregion,
+ eaddr,
+ laddr,
+ num_pg_sz);
+}
+
static inline long long h_hfi_start_interface(int token,
u64 HFI_chip_ID)
{
@@ -94,6 +152,72 @@ long long hfi_stop_nmmu(u64 chip_id)
return hvrc;
}
+long long hfi_allocate_mr(u64 chip_id, u64 res, u64 addr, u64 mr_size,
+ u64 access,
+ u64 job_id,
+ u64 mr_handle_in,
+ u64 *mr_handle_out,
+ u64 *lkey_p,
+ u64 *liobn)
+{
+ return h_nmmu_allocate_resource(H_NMMU_ALLOCATE_RESOURCE,
+ chip_id,
+ res,
+ addr,
+ mr_size,
+ access,
+ job_id,
+ mr_handle_in,
+ mr_handle_out,
+ lkey_p,
+ liobn);
+}
+
+long long hfi_modify_mr(u64 chip_id, u64 request, u64 mr_handle,
+ u64 sub_id,
+ u64 e_addr,
+ u64 l_addr,
+ u64 num_pg_sz)
+{
+ long long hvrc;
+ u64 start_time = get_jiffies_64();
+
+ while (1) {
+ hvrc = h_nmmu_modify_resource(H_NMMU_MODIFY_RESOURCE,
+ chip_id,
+ request,
+ mr_handle,
+ sub_id,
+ e_addr,
+ l_addr,
+ num_pg_sz);
+ if (hvrc != H_BUSY)
+ break;
+ if (hfidd_age_hcall(start_time))
+ break;
+ }
+ return hvrc;
+}
+
+long long hfi_free_mr(u64 chip_id, u64 res, u64 mr_handle, u64 sub_region_id)
+{
+ long long hvrc;
+ u64 start_time = get_jiffies_64();
+
+ while (1) {
+ hvrc = h_nmmu_free_resource(H_NMMU_FREE_RESOURCE,
+ chip_id,
+ res,
+ mr_handle,
+ sub_region_id);
+ if (hvrc != H_BUSY)
+ break;
+ if (hfidd_age_hcall(start_time))
+ break;
+ }
+ return hvrc;
+}
+
long long hfi_hquery_interface(u64 unit_id, u64 subtype,
u64 query_p, u64 *state)
{
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
index 001f6d5..fb9c8c8 100644
--- a/drivers/net/hfi/core/hfidd_proto.h
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -64,6 +64,21 @@ int hfidd_start_interface(struct hfidd_acs *p_acs);
int hfidd_stop_interface(struct hfidd_acs *p_acs, unsigned int hfi_id);
long long hfi_start_nmmu(u64 chip_id, void *nmmu_info);
long long hfi_stop_nmmu(u64 chip_id);
+long long hfi_allocate_mr(u64 chip_id, u64 res, u64 addr,
+ u64 mr_size,
+ u64 access,
+ u64 job_id,
+ u64 mr_handle_in,
+ u64 *mr_handle_out,
+ u64 *lkey_p,
+ u64 *liobn);
+long long hfi_modify_mr(u64 chip_id, u64 request, u64 mr_handle,
+ u64 sub_id,
+ u64 e_addr,
+ u64 l_addr,
+ u64 num_pg_sz);
+long long hfi_free_mr(u64 chip_id, u64 res, u64 mr_handle,
+ u64 sub_region_id);
long long hfi_hquery_interface(u64 unit_id, u64 subtype, u64 query_p,
u64 *state);
long long hfi_start_interface(u64 unit_id);
diff --git a/include/linux/hfi/hfidd_hcalls.h b/include/linux/hfi/hfidd_hcalls.h
index 57140a0..9fa87c5 100644
--- a/include/linux/hfi/hfidd_hcalls.h
+++ b/include/linux/hfi/hfidd_hcalls.h
@@ -41,6 +41,9 @@
#define H_HFI_STOP_INTERFACE 0xF008
#define H_NMMU_START 0xF028
#define H_NMMU_STOP 0xF02C
+#define H_NMMU_ALLOCATE_RESOURCE 0xF030
+#define H_NMMU_FREE_RESOURCE 0xF034
+#define H_NMMU_MODIFY_RESOURCE 0xF03C
#define HFI_PAGE_CODE_SHIFT 28
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 13/27] HFI: Send and receive fifo address translation
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Prepare for a hypervisor call to set up page tables in the nMMU for the
send and receive fifo.
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_proto.h | 9 ++
drivers/net/hfi/core/hfidd_window.c | 132 ++++++++++++++++++++++
drivers/net/hfi/core/hfidd_xlat.c | 210 +++++++++++++++++++++++++++++++++++
include/linux/hfi/hfidd_adpt.h | 28 +++++
include/linux/hfi/hfidd_hcalls.h | 2 +
include/linux/hfi/hfidd_internal.h | 1 +
include/linux/hfi/hfidd_xlat_map.h | 91 +++++++++++++++
7 files changed, 473 insertions(+), 0 deletions(-)
create mode 100644 include/linux/hfi/hfidd_xlat_map.h
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
index 66ea5da..001f6d5 100644
--- a/drivers/net/hfi/core/hfidd_proto.h
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -39,9 +39,18 @@ int hfidd_alloc_windows(struct hfidd_acs *p_acs);
void hfidd_free_windows(struct hfidd_acs *p_acs);
int hfidd_init_adapter(struct hfidd_acs *p_acs, void *uiop);
int hfidd_age_hcall(u64 time_start);
+int hfidd_fifo_xlat(struct hfidd_acs *p_acs, struct fifo_info *fifo_in,
+ int is_userspace, struct hfidd_vlxmem *xlat_p);
+int hfidd_fifo_unxlat(struct hfidd_acs *p_acs, struct fifo_info *fifo_in,
+ int is_userspace, struct hfidd_vlxmem *xlat_p);
+int hfidd_fill_xlat_tab(struct hfidd_acs *p_acs, struct fifo_info *fifo_in,
+ unsigned int is_userspace, struct hfidd_vlxmem *xlat_p);
int hfidd_get_page_size(struct hfidd_acs *p_acs, void *addr,
unsigned int is_userspace, unsigned int length,
unsigned long long *page_size);
+int hfidd_get_page_num(struct hfidd_acs *p_acs, void *start_addr,
+ unsigned long long len, unsigned long long page_sz,
+ unsigned int *pg_num_p);
int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
struct hfi_client_info *user_p,
struct hfi_client_info *out_p);
diff --git a/drivers/net/hfi/core/hfidd_window.c b/drivers/net/hfi/core/hfidd_window.c
index 5a4f395..de2e56d 100644
--- a/drivers/net/hfi/core/hfidd_window.c
+++ b/drivers/net/hfi/core/hfidd_window.c
@@ -359,6 +359,125 @@ static int hfi_validate_window_parm(struct hfidd_acs *p_acs,
return 0;
}
+static int hfi_xlate_fifos(struct hfidd_acs *p_acs,
+ unsigned int is_userspace,
+ struct hfidd_window *win_p,
+ struct hfi_client_info *client_p)
+{
+ int rc = 0;
+
+ /*
+ * add 4K(finish vector) to the sfifo size then call to
+ * xlate when return, restore the sfifo size back..............
+ */
+ client_p->sfifo.size += PAGE_SIZE_4K;
+ rc = hfidd_fifo_xlat(p_acs, &(client_p->sfifo), is_userspace,
+ win_p->sfifo_x_tab);
+ client_p->sfifo.size -= PAGE_SIZE_4K;
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_xlate_fifos: hfidd_fifo_xlat failed, "
+ "rc = 0x%x\n", rc);
+ return rc;
+ }
+
+ rc = hfidd_fifo_xlat(p_acs, &(client_p->rfifo), is_userspace,
+ win_p->rfifo_x_tab);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_xlate_fifos: hfidd_fifo_xlat failed, "
+ "rc = 0x%x\n", rc);
+ goto hfi_xlate_fifos_err1;
+ }
+
+hfi_xlate_fifos_err1:
+ client_p->sfifo.size += PAGE_SIZE_4K;
+ hfidd_fifo_unxlat(p_acs, &(client_p->sfifo), is_userspace,
+ win_p->sfifo_x_tab);
+ client_p->sfifo.size -= PAGE_SIZE_4K;
+
+ return rc;
+}
+
+int hfi_unxlate_fifos(struct hfidd_acs *p_acs, unsigned int is_userspace,
+ struct hfidd_window *win_p, struct hfi_client_info *client_p)
+{
+ int rc = 0;
+
+ hfidd_fifo_unxlat(p_acs, &(client_p->rfifo),
+ is_userspace, win_p->rfifo_x_tab);
+
+ client_p->sfifo.size += PAGE_SIZE_4K;
+ hfidd_fifo_unxlat(p_acs, &(client_p->sfifo),
+ is_userspace, win_p->sfifo_x_tab);
+ client_p->sfifo.size -= PAGE_SIZE_4K;
+
+ return rc;
+}
+
+static inline void hfi_free_xlate_tab(struct hfidd_window *win_p)
+{
+ kfree(win_p->sfifo_x_tab);
+ win_p->sfifo_x_tab = NULL;
+ kfree(win_p->rfifo_x_tab);
+ win_p->rfifo_x_tab = NULL;
+}
+
+static int hfi_alloc_xlate_tab(struct hfidd_acs *p_acs,
+ struct hfidd_window *win_p,
+ struct hfi_client_info *client_p)
+{
+ win_p->sfifo_x_tab = kzalloc(sizeof(*(win_p->sfifo_x_tab)),
+ GFP_KERNEL);
+ if (win_p->sfifo_x_tab == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_alloc_xlate_tab: kzalloc sfifo_x_tab failed\n");
+ return -ENOMEM;
+ }
+
+ win_p->rfifo_x_tab = kzalloc(sizeof(*(win_p->rfifo_x_tab)),
+ GFP_KERNEL);
+ if (win_p->rfifo_x_tab == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_alloc_xlate_tab: kzalloc rfifo_x_tab failed\n");
+ goto hfi_alloc_xlate_tab_err1;
+ }
+
+ return 0;
+
+hfi_alloc_xlate_tab_err1:
+ kfree(win_p->sfifo_x_tab);
+ win_p->sfifo_x_tab = NULL;
+ return -ENOMEM;
+}
+
+static int hfi_alloc_win_resource(struct hfidd_acs *p_acs,
+ unsigned int is_userspace,
+ struct hfidd_window *win_p,
+ struct hfi_client_info *client_p)
+{
+ int rc = 0;
+
+ rc = hfi_alloc_xlate_tab(p_acs, win_p, client_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_alloc_win_resource: hfi_alloc_xlate_tab "
+ "failed, rc = 0x%x\n", rc);
+ return rc;
+ }
+
+ rc = hfi_xlate_fifos(p_acs, is_userspace, win_p, client_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_alloc_win_resource: hfi_xlate_fifos "
+ "failed, rc = 0x%x\n", rc);
+ hfi_free_xlate_tab(win_p);
+ return rc;
+ }
+
+ return 0;
+}
+
/*
* Allows an user/kernel window to send/receive network traffic thru HFI
* adapter. This function will allocate the system resources needed to open
@@ -371,6 +490,7 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
{
int rc = 0;
struct hfi_client_info *local_p = NULL;
+ struct hfidd_window *win_p = NULL;
/* Allocate local data structure */
local_p = kmalloc(sizeof(struct hfi_client_info), GFP_KERNEL);
@@ -398,9 +518,21 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
goto hfidd_open_window_func_err1;
}
+ win_p = hfi_window(p_acs, local_p->window);
+
+ rc = hfi_alloc_win_resource(p_acs, is_userspace, win_p, local_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_open_window_func: hfi_alloc_win_resource "
+ "failed, rc = 0x%x\n", rc);
+ goto hfidd_open_window_func_err2;
+ }
+
kfree(local_p);
return rc;
+hfidd_open_window_func_err2:
+ hfi_restore_window_parm(p_acs, win_p);
hfidd_open_window_func_err1:
kfree(local_p);
return rc;
diff --git a/drivers/net/hfi/core/hfidd_xlat.c b/drivers/net/hfi/core/hfidd_xlat.c
index 23236cc..760d7e6 100644
--- a/drivers/net/hfi/core/hfidd_xlat.c
+++ b/drivers/net/hfi/core/hfidd_xlat.c
@@ -129,3 +129,213 @@ out1:
kfree(page_list);
return rc;
}
+
+int hfidd_get_page_num(struct hfidd_acs *p_acs,
+ void *start_addr,
+ unsigned long long len,
+ unsigned long long page_sz,
+ unsigned int *pg_num_p)
+{
+ int rc = 0;
+ int pg_shift_count;
+ unsigned long long address_mask;
+ unsigned long long offset_mask;
+ unsigned long long offset;
+
+ if (pg_num_p == NULL || len == 0) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_get_page_num: len=%llx pg_num_p=0x%llx\n",
+ len, (unsigned long long)pg_num_p);
+ return -EINVAL;
+ }
+
+ /*
+ * Pre-Calculate Masks and shift count:
+ */
+ if (page_sz == PAGE_SIZE_4K) {
+ offset_mask = PAGE_MASK_4K;
+ pg_shift_count = PAGE_SHIFT_4K;
+ } else if (page_sz == PAGE_SIZE_64K) {
+ offset_mask = PAGE_MASK_64K;
+ pg_shift_count = PAGE_SHIFT_64K;
+ } else if (page_sz == PAGE_SIZE_16M) {
+ offset_mask = PAGE_MASK_16M;
+ pg_shift_count = PAGE_SHIFT_16M;
+ } else if (page_sz == PAGE_SIZE_4G) {
+ offset_mask = PAGE_MASK_4G;
+ pg_shift_count = PAGE_SHIFT_4G;
+ } else {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_get_page_num: invalid page_sz 0x%llx "
+ "return EINVAL\n", page_sz);
+ return -EINVAL;
+ }
+ address_mask = ~offset_mask;
+
+ /*
+ * Calculate the buffer offsets into the first page:
+ */
+ offset = (unsigned long long)start_addr & offset_mask;
+ *pg_num_p = (len + offset + offset_mask) >> pg_shift_count;
+
+ return rc;
+}
+
+int hfidd_fill_xlat_tab(struct hfidd_acs *p_acs, struct fifo_info *fifo_in,
+ unsigned int is_userspace, struct hfidd_vlxmem *xlat_p)
+{
+ unsigned int num_pages;
+ unsigned long long page_size;
+ int rc = 0;
+
+ rc = hfidd_get_page_size(p_acs, fifo_in->eaddr.use.kptr, is_userspace,
+ fifo_in->size, &page_size);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fill_xlat_tab: hfidd_get_page_size failed, "
+ " rc=0x%x\n", rc);
+ return rc;
+ }
+
+ /* Get num of pages based in buffer page size */
+ rc = hfidd_get_page_num(p_acs, fifo_in->eaddr.use.kptr,
+ fifo_in->size, page_size, &num_pages);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fill_xlat_tab:: hfidd_get_page_num return "
+ "rc 0x%x\n", rc);
+ return rc;
+ }
+
+ xlat_p->v_addr = (caddr_t)(fifo_in->eaddr.use.kptr);
+ xlat_p->e_addr = (caddr_t)(fifo_in->eaddr.use.allu & ~(page_size - 1));
+ xlat_p->page_sz = page_size;
+ xlat_p->num_page = num_pages;
+ xlat_p->len = num_pages * page_size;
+ xlat_p->num_kpage = (xlat_p->len) / PAGE_SIZE;
+
+ return 0;
+}
+
+int hfidd_fifo_xlat(struct hfidd_acs *p_acs, struct fifo_info *fifo_in,
+ int is_userspace, struct hfidd_vlxmem *xlat_p)
+{
+ int rc = 0;
+ int i;
+ unsigned int num_pages, pg_code;
+ unsigned long long page_size;
+ unsigned long long *l_pages;
+ struct page **page_list;
+ unsigned int hw_page = 0;
+
+ if ((fifo_in == NULL) || (xlat_p == NULL)) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fifo_xlat: Invalid fifo_in 0x%llx\n",
+ (unsigned long long)fifo_in);
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fifo_xlat: Invalid xlat_p 0x%llx\n",
+ (unsigned long long)xlat_p);
+ return -EINVAL;
+ }
+
+ rc = hfidd_fill_xlat_tab(p_acs, fifo_in, is_userspace, xlat_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fifo_xlat: hfidd_fill_xlat_tab failed, "
+ "rc = 0x%x\n", rc);
+ return rc;
+ }
+
+ /* num_page is number of pages of page_sz */
+ num_pages = xlat_p->num_page;
+ page_size = xlat_p->page_sz;
+
+ l_pages = vmalloc(num_pages * sizeof(unsigned long long));
+ if (l_pages == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fifo_xlat: vmalloc failed for l_pages\n");
+ return -ENOMEM;
+ }
+
+ if (!is_userspace) {
+ void *curr_addr = xlat_p->e_addr;
+
+ for (i = 0; i < num_pages; i++) {
+ l_pages[i] = __pa(curr_addr);
+ curr_addr += page_size;
+ }
+ } else {
+ /* For page_list use number of kernel pages */
+ page_list = kzalloc(xlat_p->num_kpage * sizeof(struct page *),
+ GFP_KERNEL);
+ if (page_list == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fifo_xlat: kzalloc failed "
+ "for page_list\n");
+ rc = -ENOMEM;
+ goto out_err0;
+ }
+
+ down_read(¤t->mm->mmap_sem);
+ rc = get_user_pages(current, current->mm,
+ (unsigned long long)(xlat_p->e_addr),
+ xlat_p->num_kpage, 1, 0, /* write, !force */
+ page_list, NULL);
+ up_read(¤t->mm->mmap_sem);
+
+ if (rc < xlat_p->num_kpage) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_fifo_xlat: get_user_pages failed, "
+ "rc = 0x%x\n", rc);
+ goto out_err1;
+ }
+
+ for (i = 0; i < num_pages;) {
+ l_pages[hw_page] = page_to_phys(page_list[i]);
+ hw_page++;
+ i += (page_size / PAGE_SIZE);
+ }
+
+ xlat_p->page_list = (void *)page_list;
+ }
+
+ xlat_p->l_pages = (void *)l_pages;
+ xlat_p->map_page_sz = page_size;
+ xlat_p->m_addr = xlat_p->e_addr;
+ xlat_p->num_page_sz.num_code.fields.pg_num = num_pages;
+ encode_pg_sz(page_size, &pg_code);
+ xlat_p->num_page_sz.num_code.fields.pg_code =
+ (pg_code << HFI_PAGE_CODE_SHIFT);
+ return 0;
+
+out_err1:
+ if (rc > 0) {
+ for (i = 0; i < rc; i++)
+ page_cache_release(page_list[i]);
+ rc = -EINVAL;
+ }
+ kfree(page_list);
+out_err0:
+ vfree(l_pages);
+ return rc;
+}
+
+int hfidd_fifo_unxlat(struct hfidd_acs *p_acs, struct fifo_info *fifo_in,
+ int is_userspace, struct hfidd_vlxmem *xlat_p)
+{
+ int rc = 0;
+ int i;
+ struct page **page_list;
+
+ if (!is_userspace)
+ return 0;
+ page_list = (struct page **)xlat_p->page_list;
+ if (page_list != NULL) {
+ /* For page list we used number of kernel pages */
+ for (i = 0; i < xlat_p->num_kpage; i++)
+ page_cache_release(page_list[i]);
+ kfree(page_list);
+ xlat_p->page_list = NULL;
+ }
+ return rc;
+}
diff --git a/include/linux/hfi/hfidd_adpt.h b/include/linux/hfi/hfidd_adpt.h
index a41825f..8eab059 100644
--- a/include/linux/hfi/hfidd_adpt.h
+++ b/include/linux/hfi/hfidd_adpt.h
@@ -74,4 +74,32 @@
#define PAGE_MASK_4G (PAGE_SIZE_4G - 1)
#define PAGE_MASK_16G (PAGE_SIZE_16G - 1)
+#define PAGE_CODE_4K 0x00000000
+#define PAGE_CODE_64K 0x00000001
+#define PAGE_CODE_1M 0x00000002
+#define PAGE_CODE_16M 0x00000003
+#define PAGE_CODE_256M 0x00000004
+#define PAGE_CODE_4G 0x00000005
+#define PAGE_CODE_INVAL 0x00000007
+#define PAGE_CODE_MASK 0x00000007
+
+static inline void encode_pg_sz(unsigned long long pg_sz,
+ unsigned int *pg_sz_code)
+{
+ if (pg_sz == PAGE_SIZE_4K)
+ *pg_sz_code = PAGE_CODE_4K;
+ else if (pg_sz == PAGE_SIZE_64K)
+ *pg_sz_code = PAGE_CODE_64K;
+ else if (pg_sz == PAGE_SIZE_1M)
+ *pg_sz_code = PAGE_CODE_1M;
+ else if (pg_sz == PAGE_SIZE_16M)
+ *pg_sz_code = PAGE_CODE_16M;
+ else if (pg_sz == PAGE_SIZE_256M)
+ *pg_sz_code = PAGE_CODE_256M;
+ else if (pg_sz == PAGE_SIZE_4G)
+ *pg_sz_code = PAGE_CODE_4G;
+ else
+ *pg_sz_code = PAGE_CODE_INVAL;
+}
+
#endif /* _HFIDD_ADPT_H_ */
diff --git a/include/linux/hfi/hfidd_hcalls.h b/include/linux/hfi/hfidd_hcalls.h
index 2a374e6..57140a0 100644
--- a/include/linux/hfi/hfidd_hcalls.h
+++ b/include/linux/hfi/hfidd_hcalls.h
@@ -42,6 +42,8 @@
#define H_NMMU_START 0xF028
#define H_NMMU_STOP 0xF02C
+#define HFI_PAGE_CODE_SHIFT 28
+
#define EEH_QUERY 1
#define COMP_QUERY 2
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
index 1781d52..216546b 100644
--- a/include/linux/hfi/hfidd_internal.h
+++ b/include/linux/hfi/hfidd_internal.h
@@ -63,6 +63,7 @@
#include <linux/hfi/hfidd_client.h>
#include <linux/hfi/hfidd_adpt.h>
#include <linux/hfi/hfidd_hcalls.h>
+#include <linux/hfi/hfidd_xlat_map.h>
#define MAX_D_WIN_PER_HFI (p_acs->dds.num_d_windows)
diff --git a/include/linux/hfi/hfidd_xlat_map.h b/include/linux/hfi/hfidd_xlat_map.h
new file mode 100644
index 0000000..e5d1869
--- /dev/null
+++ b/include/linux/hfi/hfidd_xlat_map.h
@@ -0,0 +1,91 @@
+/*
+ * hfidd_xlat_map.h
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
+ *
+ * (C) Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#ifndef _HFIDD_XLAT_MAP_H_
+#define _HFIDD_XLAT_MAP_H_
+
+#include <linux/hfi/hfidd_client.h>
+
+/*
+ * So we can shift rather than divide!
+ */
+#define PAGE_SHIFT_2K 11
+#define PAGE_SHIFT_4K 12
+#define PAGE_SHIFT_64K 16
+#define PAGE_SHIFT_1M 20
+#define PAGE_SHIFT_16M 24
+#define PAGE_SHIFT_4G 32
+
+struct page_num_code {
+ union {
+ unsigned long long llu_value;
+ struct num_and_code {
+ unsigned int pg_num;
+ unsigned int pg_code;
+ } fields;
+ } num_code;
+};
+
+struct hfidd_vlxmem {
+ unsigned long long page_sz; /* actual page size */
+ unsigned int num_page; /* calculated using actual
+ page size */
+ unsigned int rsvd;
+ struct page_num_code num_page_sz; /* page num and size code
+ mapping */
+ unsigned long long map_page_sz; /* page size used for mapping */
+ caddr_t m_addr; /* aligned address start for
+ mapping */
+ caddr_t v_addr; /* user given vaddr */
+ caddr_t e_addr;
+
+ unsigned long long len;
+ unsigned long long access_flag;
+ void *l_pages;
+
+ unsigned long long mr_handle;
+ unsigned int l_key;
+
+ struct task *xd;
+
+ int num_kpage; /* num of kernel pages */
+ atomic_t *share_cnt; /* # of processes sharing this
+ submr */
+ unsigned int num_chunks; /* number of chunks the mr is
+ divided */
+ caddr_t mr_addr; /* aligned submr starting
+ address */
+ void *page_list; /* struct page_list */
+ unsigned int liobn; /* logical I/O bus number */
+};
+
+#endif
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 10/27] HFI: HFIDD_REQ_OPEN_WINDOW request
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Set up protocol access to an HFI window.
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/Makefile | 1 +
drivers/net/hfi/core/hfidd_init.c | 14 +++++++
drivers/net/hfi/core/hfidd_proto.h | 3 +
drivers/net/hfi/core/hfidd_window.c | 70 +++++++++++++++++++++++++++++++++++
include/linux/hfi/hfidd_client.h | 22 +++++++++++
include/linux/hfi/hfidd_internal.h | 26 +++++++++++++
include/linux/hfi/hfidd_requests.h | 1 +
7 files changed, 137 insertions(+), 0 deletions(-)
create mode 100644 drivers/net/hfi/core/hfidd_window.c
diff --git a/drivers/net/hfi/core/Makefile b/drivers/net/hfi/core/Makefile
index 4e6cbd6..0224a57 100644
--- a/drivers/net/hfi/core/Makefile
+++ b/drivers/net/hfi/core/Makefile
@@ -2,6 +2,7 @@
# Makefile for the HFI device driver for IBM eServer System p
#
hfi_core-objs:= hfidd_adpt.o \
+ hfidd_window.o \
hfidd_init.o \
hfidd_hcalls.o
obj-$(CONFIG_HFI) += hfi_core.o
diff --git a/drivers/net/hfi/core/hfidd_init.c b/drivers/net/hfi/core/hfidd_init.c
index ecb6a2f..197fcc3 100644
--- a/drivers/net/hfi/core/hfidd_init.c
+++ b/drivers/net/hfi/core/hfidd_init.c
@@ -130,6 +130,20 @@ static ssize_t hfidd_cmd_write(struct file *filep, const char __user *buf,
}
switch (cmd.req) {
+ case HFIDD_REQ_OPEN_WINDOW:
+ if (cmd.req_len != sizeof(struct hfi_client_info)) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfidd_cmd_write: hdr.reqlen 0x%x expected "
+ "0x%lx for cmd req 0x%x\n",
+ cmd.req_len,
+ sizeof(struct hfi_client_info), cmd.req);
+ return -EINVAL;
+ }
+ rc = hfidd_open_window_func(p_acs, is_userspace,
+ (struct hfi_client_info *) buf,
+ (struct hfi_client_info *) cmd.result.use.kptr);
+ break;
+
case HFIDD_REQ_QUERY_DD_INFO:
if (cmd.req_len != sizeof(struct hfi_query_dd_info)) {
dev_printk(KERN_ERR, p_acs->hfidd_dev,
diff --git a/drivers/net/hfi/core/hfidd_proto.h b/drivers/net/hfi/core/hfidd_proto.h
index c61387e..e7f2901 100644
--- a/drivers/net/hfi/core/hfidd_proto.h
+++ b/drivers/net/hfi/core/hfidd_proto.h
@@ -39,6 +39,9 @@ int hfidd_alloc_windows(struct hfidd_acs *p_acs);
void hfidd_free_windows(struct hfidd_acs *p_acs);
int hfidd_init_adapter(struct hfidd_acs *p_acs, void *uiop);
int hfidd_age_hcall(u64 time_start);
+int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
+ struct hfi_client_info *user_p,
+ struct hfi_client_info *out_p);
int hfidd_get_phyp_page(struct hfidd_acs *p_acs, caddr_t *page,
caddr_t *laddr, int size);
void hfidd_release_phyp_page(caddr_t page, int size);
diff --git a/drivers/net/hfi/core/hfidd_window.c b/drivers/net/hfi/core/hfidd_window.c
new file mode 100644
index 0000000..f16caf7
--- /dev/null
+++ b/drivers/net/hfi/core/hfidd_window.c
@@ -0,0 +1,70 @@
+/*
+ * hfidd_window.c
+ *
+ * HFI device driver for IBM System p
+ *
+ * Authors:
+ * Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
+ * William S. Cadden <wscadden@linux.vnet.ibm.com>
+ * Wen C. Chen <winstonc@linux.vnet.ibm.com>
+ * Scot Sakolish <sakolish@linux.vnet.ibm.com>
+ * Jian Xiao <jian@linux.vnet.ibm.com>
+ * Carol L. Soto <clsoto@linux.vnet.ibm.com>
+ * Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
+ *
+ * (C) Copyright IBM Corp. 2010
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * 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
+ *
+ */
+
+#include <linux/hfi/hfidd_internal.h>
+#include <linux/hfi/hfidd_hcalls.h>
+#include "hfidd_proto.h"
+#include <linux/hfi/hfidd_requests.h>
+
+/*
+ * Allows an user/kernel window to send/receive network traffic thru HFI
+ * adapter. This function will allocate the system resources needed to open
+ * a window. If any problem detected, then the request will fail. This function
+ * is called directly by kernel users and by a write system call by userspace.
+ */
+int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
+ struct hfi_client_info *user_p,
+ struct hfi_client_info *out_p)
+{
+ int rc = 0;
+ struct hfi_client_info *local_p = NULL;
+
+ /* Allocate local data structure */
+ local_p = kmalloc(sizeof(struct hfi_client_info), GFP_KERNEL);
+ if (local_p == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "open_window_func: kmalloc local_p failed\n");
+ return -ENOMEM;
+ }
+
+ /* Copy into local from user */
+ rc = hfi_copy_from_user((void *)local_p, (void *)user_p,
+ is_userspace, sizeof(struct hfi_client_info));
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "open_window_func: hfi_copy_from_user failed\n");
+ }
+
+ kfree(local_p);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(hfidd_open_window_func);
diff --git a/include/linux/hfi/hfidd_client.h b/include/linux/hfi/hfidd_client.h
index c3c8fef..7e4c1a7 100644
--- a/include/linux/hfi/hfidd_client.h
+++ b/include/linux/hfi/hfidd_client.h
@@ -69,6 +69,28 @@ struct fifo_info {
unsigned long long size; /* bytes */
};
+/*
+ * HFIDD_REQ_OPEN_WINDOW: Window Open
+ * For reserved windows
+ * The job scheduler provides the application with window number and
+ * jobid, which need to be passed in/will be checked on the window open.
+ * Immediate send slots were also reserved by the job scheduler, and the
+ * DD returns the count. The application has the option of setting
+ * protection keys by task or by jobid. Protection key is passed in.
+ * For Dynamic windows
+ * The DD will select a free dynamic window and return its window number.
+ * The jobid will be assigned by the DD (upper bits set to select a
+ * reserved range of jobids, lower bits come from userid). The
+ * protection key flag is always by task. The protection key is passed in.
+ * For Kernel/IP windows
+ * The DD will select a free dynamic window and return its window number.
+ * The jobid is passed in. The jobid is used for the protection key.
+ *
+ * Finished vectors:
+ * sfifo_finishvec and imm_finishvec must reside in an extra page (last
+ * page) in the sfifo memory range, provided by the user.
+ */
+
#define HFIDD_IP_WIN 1 /* IP windows get broadcasts forwarded
to them... */
#define HFIDD_KERNEL_WIN 2 /* ... other kernel windows do not */
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
index a36c244..dd1ce4c 100644
--- a/include/linux/hfi/hfidd_internal.h
+++ b/include/linux/hfi/hfidd_internal.h
@@ -142,4 +142,30 @@ struct hfidd_global {
struct hfidd_acs *p_acs[MAX_HFIS];
};
+static inline int hfi_copy_to_user(void *user_p, void *local_p,
+ unsigned int is_userspace, unsigned int size)
+{
+ int rc = 0;
+
+ if (is_userspace)
+ rc = copy_to_user(user_p, local_p, size);
+ else
+ memcpy(user_p, local_p, size);
+
+ return rc;
+}
+
+static inline int hfi_copy_from_user(void *local_p, void *user_p,
+ unsigned int is_userspace, unsigned int size)
+{
+ int rc = 0;
+
+ if (is_userspace)
+ rc = copy_from_user(local_p, user_p, size);
+ else
+ memcpy(local_p, user_p, size);
+
+ return rc;
+}
+
#endif
diff --git a/include/linux/hfi/hfidd_requests.h b/include/linux/hfi/hfidd_requests.h
index b6e255f..4f1c74d 100644
--- a/include/linux/hfi/hfidd_requests.h
+++ b/include/linux/hfi/hfidd_requests.h
@@ -33,6 +33,7 @@
#ifndef _HFIDD_REQUESTS_H_
#define _HFIDD_REQUESTS_H_
+#define HFIDD_REQ_OPEN_WINDOW 0x00000a01
#define HFIDD_REQ_QUERY_DD_INFO 0x00001004
#endif /* _HFIDD_REQUESTS_H_ */
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 06/27] HFI: Add DD calls to START/STOP INTERFACE HCALLs
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_init.c | 97 +++++++++++++++++++++++++++++++++++++
1 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_init.c b/drivers/net/hfi/core/hfidd_init.c
index 854d676..99bacab 100644
--- a/drivers/net/hfi/core/hfidd_init.c
+++ b/drivers/net/hfi/core/hfidd_init.c
@@ -319,6 +319,93 @@ hfidd_create_devices_error0:
return rc;
}
+/*
+ * Disable message passing to each adapter by calling the
+ * Stop Interface hcall.
+ */
+static void hfidd_stop_adapter(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_HFIS; i++) {
+ hfidd_stop_interface(hfidd_global.p_acs[i],
+ hfidd_global.p_acs[i]->dds.hfi_id);
+ }
+}
+
+/*
+ * Query the interface to check the logical state of HFI.
+ * Enable message passing to each adapter by calling Start
+ * Interface hcall.
+ */
+static int hfidd_start_adapter(void)
+{
+ unsigned long long hfi_state;
+ int i, j;
+ int rc = 0;
+
+ for (i = 0; i < MAX_HFIS; i++) {
+ rc = hfidd_query_interface(hfidd_global.p_acs[i], COMP_QUERY,
+ hfidd_global.p_acs[i]->dds.hfi_id, &hfi_state);
+ if (hfi_state != NOT_STARTED) {
+ rc = hfidd_stop_interface(hfidd_global.p_acs[i],
+ hfidd_global.p_acs[i]->dds.hfi_id);
+ if (rc) {
+ dev_printk(KERN_ERR,
+ hfidd_global.p_acs[i]->hfidd_dev,
+ "%s: hfidd_start_adapter:"
+ " hfidd_stop_interface failed rc = "
+ " 0x%x\n", hfidd_global.p_acs[i]->name,
+ rc);
+ }
+
+ rc = hfidd_query_interface(hfidd_global.p_acs[i],
+ COMP_QUERY,
+ hfidd_global.p_acs[i]->dds.hfi_id,
+ &hfi_state);
+ if (hfi_state != NOT_STARTED) {
+ dev_printk(KERN_ERR,
+ hfidd_global.p_acs[i]->hfidd_dev,
+ "%s: hfidd_start_adapter: query"
+ " interface bad state 0x%llx\n",
+ hfidd_global.p_acs[i]->name, hfi_state);
+ return -EIO;
+ }
+ }
+
+ }
+
+ for (i = 0; i < MAX_HFIS; i++) {
+ rc = hfidd_start_interface(hfidd_global.p_acs[i]);
+ if (rc) {
+ dev_printk(KERN_ERR, hfidd_global.p_acs[i]->hfidd_dev,
+ "%s: hfidd_start_adapter: "
+ "hfidd_start_interface failed rc = "
+ "%d\n", hfidd_global.p_acs[i]->name, rc);
+ goto hfidd_start_adapter_err;
+ }
+
+ /* query interface to get src ISR */
+ rc = hfidd_query_interface(hfidd_global.p_acs[i], COMP_QUERY,
+ hfidd_global.p_acs[i]->dds.hfi_id, &hfi_state);
+ if (rc) {
+ dev_printk(KERN_ERR, hfidd_global.p_acs[i]->hfidd_dev,
+ "%s: hfidd_start_adapter: "
+ "hfidd_query_interface failed rc = %d\n",
+ hfidd_global.p_acs[i]->name, rc);
+ goto hfidd_start_adapter_err;
+ }
+ }
+ return 0;
+
+hfidd_start_adapter_err:
+ for (j = 0; j < i; j++) {
+ hfidd_stop_interface(hfidd_global.p_acs[j],
+ hfidd_global.p_acs[j]->dds.hfi_id);
+ }
+ return rc;
+}
+
static int __init hfidd_mod_init(void)
{
int rc = 0;
@@ -339,9 +426,18 @@ static int __init hfidd_mod_init(void)
goto error1;
}
+ rc = hfidd_start_adapter();
+ if (rc < 0) {
+ printk(KERN_ERR "%s: hfidd_mod_init: hfidd_start_adapter failed"
+ " rc = %d\n", HFIDD_DEV_NAME, rc);
+ goto error2;
+ }
+
printk(KERN_INFO "IBM hfi device driver loaded sucessfully\n");
return 0;
+error2:
+ hfidd_destroy_devices();
error1:
hfidd_destroy_class();
@@ -351,6 +447,7 @@ error1:
static void __exit hfidd_mod_exit(void)
{
+ hfidd_stop_adapter();
hfidd_destroy_devices();
hfidd_destroy_class();
}
--
1.7.3.5
^ permalink raw reply related
* [PATCH v2 11/27] HFI: Check window number/assign window number
From: dykmanj @ 2011-04-18 3:21 UTC (permalink / raw)
To: netdev
Cc: Jim Dykman, Piyush Chaudhary, Fu-Chung Chang, William S. Cadden,
Wen C. Chen, Scot Sakolish, Jian Xiao, Carol L. Soto,
Sarah J. Sheppard
In-Reply-To: <1303096919-7367-1-git-send-email-dykmanj@linux.vnet.ibm.com>
From: Jim Dykman <dykmanj@linux.vnet.ibm.com>
RESERVED windows are reserved by a job scheduler before the application starts.
the application is given a list of windows to use, the DD has to check that
they are opening one of the windows assigned to that jobid.
DYNAMIC windows are used without a job scheduler; the application calls into
the DD and asks for any free window.
Signed-off-by: Piyush Chaudhary <piyushc@linux.vnet.ibm.com>
Signed-off-by: Jim Dykman <dykmanj@linux.vnet.ibm.com>
Signed-off-by: Fu-Chung Chang <fcchang@linux.vnet.ibm.com>
Signed-off-by: William S. Cadden <wscadden@linux.vnet.ibm.com>
Signed-off-by: Wen C. Chen <winstonc@linux.vnet.ibm.com>
Signed-off-by: Scot Sakolish <sakolish@linux.vnet.ibm.com>
Signed-off-by: Jian Xiao <jian@linux.vnet.ibm.com>
Signed-off-by: Carol L. Soto <clsoto@linux.vnet.ibm.com>
Signed-off-by: Sarah J. Sheppard <sjsheppa@linux.vnet.ibm.com>
---
drivers/net/hfi/core/hfidd_window.c | 161 +++++++++++++++++++++++++++++++++++
include/linux/hfi/hfidd_internal.h | 16 ++++
2 files changed, 177 insertions(+), 0 deletions(-)
diff --git a/drivers/net/hfi/core/hfidd_window.c b/drivers/net/hfi/core/hfidd_window.c
index f16caf7..cc775e3 100644
--- a/drivers/net/hfi/core/hfidd_window.c
+++ b/drivers/net/hfi/core/hfidd_window.c
@@ -35,6 +35,153 @@
#include "hfidd_proto.h"
#include <linux/hfi/hfidd_requests.h>
+/* Validate the type, state and job id for RESERVED window */
+static int hfi_validate_reserve_window_id(struct hfidd_acs *p_acs,
+ struct hfi_client_info *client_p)
+{
+ struct hfidd_window *win_p;
+
+ /* Check if win is between min_hfi_windows and max_hfi_windows */
+ if ((client_p->window < min_hfi_windows(p_acs)) ||
+ (client_p->window >= max_hfi_windows(p_acs))) {
+
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_validate_reserve_window_id: window = 0x%x too big\n",
+ client_p->window);
+ return -EINVAL;
+ }
+
+ /* Check if win_p indexed by window is not NULL */
+ win_p = hfi_window(p_acs, client_p->window);
+ if (win_p == NULL) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_validate_reserve_window_id: win 0x%x win_p is NULL\n",
+ client_p->window);
+ return -EINVAL;
+ }
+
+ spin_lock(&(win_p->win_lock));
+ /*
+ * Check if win_p->type is HFIDD_RESERVE_WIN
+ * win_p->state is WIN_RESERVED,
+ * job id is matched
+ */
+ if ((win_p->type != HFIDD_RESERVE_WIN) ||
+ (win_p->state != WIN_RESERVED) ||
+ (win_p->job_id != client_p->job_id)) {
+ spin_unlock(&(win_p->win_lock));
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_validate_reserve_window_id: win 0x%x type0x%x/"
+ "state0x%x/jid invalid\n",
+ client_p->window, win_p->type, win_p->state);
+ return -EINVAL;
+ }
+ spin_unlock(&(win_p->win_lock));
+ return 0;
+}
+
+/* Find an available dynamic window for open window request */
+static int hfi_validate_dynamic_window_id(struct hfidd_acs *p_acs,
+ struct hfi_client_info *client_p)
+{
+ int i;
+ struct hfidd_window *win_p;
+
+ /* Find out next available dynamic window */
+ for (i = min_hfi_windows(p_acs);
+ i < max_hfi_windows(p_acs); i++) {
+
+ win_p = hfi_window(p_acs, i);
+ if (win_p == NULL)
+ continue;
+
+ /* if the spinlock is busy, the window is in use */
+ if (!spin_trylock(&(win_p->win_lock)))
+ continue;
+
+ if ((win_p->type == HFIDD_DYNAMIC_WIN) &&
+ (win_p->state == WIN_AVAILABLE)) {
+ /*
+ * Fill in the window number into
+ * client info and update state
+ */
+ client_p->window = win_p->index;
+ win_p->job_id = client_p->job_id;
+ win_p->state = WIN_RESERVED;
+ win_p->type = client_p->win_type;
+
+ /* Set isIP flag if came from IP */
+ if (win_p->type == HFIDD_IP_WIN)
+ win_p->is_ip = 1;
+ else
+ win_p->is_ip = 0;
+ spin_unlock(&(win_p->win_lock));
+ return 0;
+ }
+ spin_unlock(&(win_p->win_lock));
+ }
+
+ /* We are out of dynamic windows */
+ if (i == max_hfi_windows(p_acs)) {
+ client_p->window = 0;
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_validate_dynamic_window_id: out of dynamic window\n");
+ return -ENOBUFS;
+ }
+
+ return 0;
+}
+
+/* Validate the window request for RESERVED or DYNAMIC window */
+static inline int hfi_validate_window_id(struct hfidd_acs *p_acs,
+ struct hfi_client_info *client_p, unsigned int is_userspace)
+{
+ int rc = 0;
+
+ /* Check the type of window request */
+ switch (client_p->win_type) {
+ case HFIDD_RESERVE_WIN:
+ rc = hfi_validate_reserve_window_id(p_acs, client_p);
+ break;
+ case HFIDD_IP_WIN:
+ case HFIDD_KERNEL_WIN:
+ if (is_userspace) {
+ rc = -EINVAL;
+ break;
+ }
+ /* fall thru here....*/
+ case HFIDD_DYNAMIC_WIN:
+ rc = hfi_validate_dynamic_window_id(p_acs, client_p);
+ break;
+ default:
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_validate_window_id: invalid win type 0x%x\n",
+ client_p->win_type);
+ rc = -EINVAL;
+ break;
+ }
+
+ return rc;
+}
+
+/* Validate window number and type for open window request */
+static int hfi_validate_window_parm(struct hfidd_acs *p_acs,
+ unsigned int is_userspace,
+ struct hfi_client_info *client_p)
+{
+ int rc = 0;
+
+ /* Validate the window number */
+ rc = hfi_validate_window_id(p_acs, client_p, is_userspace);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "hfi_validate_window_parm: hfi_validate_window_id "
+ "failed, rc = 0x%x\n", rc);
+ return rc;
+ }
+ return 0;
+}
+
/*
* Allows an user/kernel window to send/receive network traffic thru HFI
* adapter. This function will allocate the system resources needed to open
@@ -62,9 +209,23 @@ int hfidd_open_window_func(struct hfidd_acs *p_acs, unsigned int is_userspace,
if (rc) {
dev_printk(KERN_ERR, p_acs->hfidd_dev,
"open_window_func: hfi_copy_from_user failed\n");
+ goto hfidd_open_window_func_err1;
+ }
+
+ /* Validate the window parms */
+ rc = hfi_validate_window_parm(p_acs, is_userspace, local_p);
+ if (rc) {
+ dev_printk(KERN_ERR, p_acs->hfidd_dev,
+ "open_window_func: hfi_validate_window_parm failed, "
+ "rc = 0x%x\n", rc);
+ goto hfidd_open_window_func_err1;
}
kfree(local_p);
return rc;
+
+hfidd_open_window_func_err1:
+ kfree(local_p);
+ return rc;
}
EXPORT_SYMBOL_GPL(hfidd_open_window_func);
diff --git a/include/linux/hfi/hfidd_internal.h b/include/linux/hfi/hfidd_internal.h
index dd1ce4c..1781d52 100644
--- a/include/linux/hfi/hfidd_internal.h
+++ b/include/linux/hfi/hfidd_internal.h
@@ -142,6 +142,22 @@ struct hfidd_global {
struct hfidd_acs *p_acs[MAX_HFIS];
};
+static inline struct hfidd_window *hfi_window(struct hfidd_acs *p,
+ unsigned int idx)
+{
+ return p->win[idx - p->dds.window_start];
+}
+
+static inline unsigned int min_hfi_windows(struct hfidd_acs *p)
+{
+ return p->dds.window_start;
+}
+
+static inline unsigned int max_hfi_windows(struct hfidd_acs *p)
+{
+ return p->dds.window_start + p->dds.window_num;
+}
+
static inline int hfi_copy_to_user(void *user_p, void *local_p,
unsigned int is_userspace, unsigned int size)
{
--
1.7.3.5
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox