* Re: [PATCH 2/2] act_mirred: optimization
From: Changli Gao @ 2009-11-16 13:22 UTC (permalink / raw)
To: David Miller; +Cc: hadi, shemminger, netdev
In-Reply-To: <20091116.051722.255835290.davem@davemloft.net>
On Mon, Nov 16, 2009 at 9:17 PM, David Miller <davem@davemloft.net> wrote:
> From: Changli Gao <xiaosuo@gmail.com>
> Date: Mon, 16 Nov 2009 21:05:28 +0800
>
>> I am sorry about that. But I did test it before submitting these two,
>> and I am just wondering if they are applied without any error. Would
>> you post the file after being patched? I think it will be helpful to
>> finger out the real problem.
>
> I don't have time for that sorry.
Thanks all the same!
>
> I think the problem might be that you are developing against
> either net-2.6 or Linus's tree, whereas you should be working
> against net-next-2.6
>
I am working against linux-next. I'll check if there is any
difference. BTW: were these patches applied in order, 1 - 2?
--
Regards,
Changli Gao(xiaosuo@gmail.com)
^ permalink raw reply
* Re: [RFC-PATCH] libiscsi dhcp handler
From: Rakesh Ranjan @ 2009-11-16 13:24 UTC (permalink / raw)
To: David Miller
Cc: michaelc, open-iscsi, netdev, linux-kernel, James.Bottomley, kxie
In-Reply-To: <20091116.051835.125328285.davem@davemloft.net>
David Miller wrote:
> From: Rakesh Ranjan <rakesh@chelsio.com>
> Date: Mon, 16 Nov 2009 18:41:49 +0530
>
>> Herein attached patches to support dhcp based provisioning for iSCSI
>> offload capable cards. I have made dhcp code as generic as possible,
>> please go through the code. Based on the feedback I will submit final
>> version of these patches.
>
> You can't really add objects to the build before the patch that
> adds the source for that object.
>
my mistake, the makefile part of patch is irrelevant. Will send new
patch in few mins.
Regards
Rakesh Ranjan
^ permalink raw reply
* Re: [PATCH 2/2] act_mirred: optimization
From: Jarek Poplawski @ 2009-11-16 13:27 UTC (permalink / raw)
To: Changli Gao; +Cc: David Miller, hadi, shemminger, netdev
In-Reply-To: <412e6f7f0911160505x10da9a92j694669db9d030da1@mail.gmail.com>
On 16-11-2009 14:05, Changli Gao wrote:
> On Mon, Nov 16, 2009 at 6:58 PM, David Miller <davem@davemloft.net> wrote:
>> From: David Miller <davem@davemloft.net>
>> Date: Mon, 16 Nov 2009 02:48:39 -0800 (PST)
>>
>>> From: Changli Gao <xiaosuo@gmail.com>
>>> Date: Mon, 16 Nov 2009 17:53:29 +0800
>>>
>>>> act_mirred: optimization.
>>>>
>>>> move checking if eaction is valid in tcf_mirred_init()
>>>>
>>>> Signed-off-by: Changli Gao <xiaosuo@gmail.com>
>>>> Signed-off-by: Jamal Hadi Salim <hadi@cyberus.ca>
>>> Also applied, thank you.
>> Nevermind, you're NOT TESTING the patches you are posting:
>>
>> net/sched/act_mirred.c: In function â??tcf_mirredâ??:
>> net/sched/act_mirred.c:168: error: label â??outâ?? used but not defined
>> net/sched/act_mirred.c:158: warning: unused variable â??errâ??
>> net/sched/act_mirred.c:158: warning: unused variable â??retvalâ??
>> make[2]: *** [net/sched/act_mirred.o] Error 1
>> make[1]: *** [net/sched] Error 2
>> make[1]: *** Waiting for unfinished jobs....
>>
>> I'm thus reverting both changes.
>>
>> Don't submit changes which are untested, it wastes my time.
>>
>
> I am sorry about that. But I did test it before submitting these two,
> and I am just wondering if they are applied without any error. Would
> you post the file after being patched? I think it will be helpful to
> finger out the real problem.
>
> BTW: since my email client thunderbird was broken, I used google
> webmail(with ViewSourceWith addon) to submit these two patches.
>
It seems PATCH 1/2 might be broken by email (but I got it second hand
from gmail). checkpatch output:
ERROR: patch seems to be corrupt (line wrapped?)
#17: FILE: net/sched/act_mirred.c:147:
struct tc_action *a,
WARNING: printk() should include KERN_ facility level
#34: FILE: net/sched/act_mirred.c:160:
+ printk("tcf_mirred unknown action %d\n",
total: 1 errors, 1 warnings, 89 lines checked
mirred1.diff has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
Jarek P.
^ permalink raw reply
* Re: KS8695: problem with ethernet driver
From: Figo.zhang @ 2009-11-12 14:44 UTC (permalink / raw)
To: zeal; +Cc: netdev, Vincent Sanders, Ben Dooks
In-Reply-To: <efc9214f0911160123t31d7df31tc1afcbd5129b7d86@mail.gmail.com>
On Mon, 2009-11-16 at 17:23 +0800, zeal wrote:
> Hi,
>
> I've two questions on the ks8695.
>
> 1. We knew recently Figo.zhang has added NAPI support for ks8695 net driver.
> Thanks him. But on our ks8695 board it couldn't work well as i thought.
> We used net-next-git kernel.
>
> IP layer cannot receive any frame from lan or wan port(s).
>
> After dig into the driver, I found the rx interrupt occurs,
> but the corresponding status bit is not set. So it won't go into napi
> schedule block.
would like to add debug information at ks8695_rx_irq() to see if the
interrupt function can work and the status value? in line 443, add :
printk(KERN_EMERG "rx status = 0x%x\n", status);
>
> if (status & mask_bit) {
> if (napi_schedule_prep(&ksp->napi)) {
> /*disable rx interrupt*/
> status &= ~mask_bit;
> writel(status , KS8695_IRQ_VA + KS8695_INTEN);
> __napi_schedule(&ksp->napi);
> }
> }
>
> Does anybody tested this NAPI driver succeeded before? If so it maybe
> hardware issue.
>
> 2. It's a extend topic about ks8695. Does the cpu port can tell the
> source port (i.e. lan port ID)
> when it receive a frame from LAN ports? I think a smart switch need
> know where the frame come from
> and then decide where it to go. And many switch-chip in this way.
> The manual can't help me at all as i've done according to it.
>
> Any hint is appreciated.
>
^ permalink raw reply
* Re: [PATCH 2/2] act_mirred: optimization
From: David Miller @ 2009-11-16 13:33 UTC (permalink / raw)
To: xiaosuo; +Cc: hadi, shemminger, netdev
In-Reply-To: <412e6f7f0911160522w34895b0eked14f69ccc62c96b@mail.gmail.com>
From: Changli Gao <xiaosuo@gmail.com>
Date: Mon, 16 Nov 2009 21:22:46 +0800
> I am working against linux-next. I'll check if there is any
> difference. BTW: were these patches applied in order, 1 - 2?
Yes, they were.
^ permalink raw reply
* [PATCH 1/2 net-next-2.6] net: add dev_txq_stats_fold() helper
From: Eric Dumazet @ 2009-11-16 13:36 UTC (permalink / raw)
To: David S. Miller; +Cc: Linux Netdev List
Some drivers ndo_get_stats() method need to perform txqueue stats folding.
Move folding from dev_get_stats() to a new dev_txq_stats_fold() function
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
include/linux/netdevice.h | 1
net/core/dev.c | 48 +++++++++++++++++++++---------------
2 files changed, 30 insertions(+), 19 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 7043f85..c8fa462 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1941,6 +1941,7 @@ extern void netdev_features_change(struct net_device *dev);
extern void dev_load(struct net *net, const char *name);
extern void dev_mcast_init(void);
extern const struct net_device_stats *dev_get_stats(struct net_device *dev);
+extern void dev_txq_stats_fold(const struct net_device *dev, struct net_device_stats *stats);
extern int netdev_max_backlog;
extern int weight_p;
diff --git a/net/core/dev.c b/net/core/dev.c
index 4b24d79..49417ba 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5168,6 +5168,32 @@ void netdev_run_todo(void)
}
/**
+ * dev_txq_stats_fold - fold tx_queues stats
+ * @dev: device to get statistics from
+ * @stats: struct net_device_stats to hold results
+ */
+void dev_txq_stats_fold(const struct net_device *dev,
+ struct net_device_stats *stats)
+{
+ unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
+ unsigned int i;
+ struct netdev_queue *txq;
+
+ for (i = 0; i < dev->num_tx_queues; i++) {
+ txq = netdev_get_tx_queue(dev, i);
+ tx_bytes += txq->tx_bytes;
+ tx_packets += txq->tx_packets;
+ tx_dropped += txq->tx_dropped;
+ }
+ if (tx_bytes || tx_packets || tx_dropped) {
+ stats->tx_bytes = tx_bytes;
+ stats->tx_packets = tx_packets;
+ stats->tx_dropped = tx_dropped;
+ }
+}
+EXPORT_SYMBOL(dev_txq_stats_fold);
+
+/**
* dev_get_stats - get network device statistics
* @dev: device to get statistics from
*
@@ -5181,25 +5207,9 @@ const struct net_device_stats *dev_get_stats(struct net_device *dev)
if (ops->ndo_get_stats)
return ops->ndo_get_stats(dev);
- else {
- unsigned long tx_bytes = 0, tx_packets = 0, tx_dropped = 0;
- struct net_device_stats *stats = &dev->stats;
- unsigned int i;
- struct netdev_queue *txq;
-
- for (i = 0; i < dev->num_tx_queues; i++) {
- txq = netdev_get_tx_queue(dev, i);
- tx_bytes += txq->tx_bytes;
- tx_packets += txq->tx_packets;
- tx_dropped += txq->tx_dropped;
- }
- if (tx_bytes || tx_packets || tx_dropped) {
- stats->tx_bytes = tx_bytes;
- stats->tx_packets = tx_packets;
- stats->tx_dropped = tx_dropped;
- }
- return stats;
- }
+
+ dev_txq_stats_fold(dev, &dev->stats);
+ return &dev->stats;
}
EXPORT_SYMBOL(dev_get_stats);
^ permalink raw reply related
* [PATCH 2/2 net-next-2.6] vlan: Precise RX stats accounting
From: Eric Dumazet @ 2009-11-16 13:37 UTC (permalink / raw)
To: David S. Miller; +Cc: Linux Netdev List
With multi queue devices, its possible that several cpu call
vlan RX routines simultaneously for the same vlan device.
We update RX stats counter without any locking, so we can
get slightly wrong counters.
One possible fix is to use percpu counters, to get precise
accounting and also get guarantee of no cache line ping pongs
between cpus.
In case dynamic percpu allocation fails, we fallback to previous
mode (sharing dev->stats counter)
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
---
net/8021q/vlan.c | 1
net/8021q/vlan.h | 10 +++++++
net/8021q/vlan_core.c | 19 ++++++++++----
net/8021q/vlan_dev.c | 53 +++++++++++++++++++++++++++++++++++-----
4 files changed, 72 insertions(+), 11 deletions(-)
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 39f8d01..db6a9bc 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -179,6 +179,7 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
/* Free the group, after all cpu's are done. */
call_rcu(&grp->rcu, vlan_rcu_free);
}
+ free_percpu(vlan->vlan_rx_stats);
/* Get rid of the vlan's reference to real_dev */
dev_put(real_dev);
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 68f9290..a211a55 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -16,6 +16,15 @@ struct vlan_priority_tci_mapping {
struct vlan_priority_tci_mapping *next;
};
+
+/* percpu rx stats */
+struct vlan_rx_stats {
+ unsigned long rx_packets;
+ unsigned long rx_bytes;
+ unsigned long multicast;
+ unsigned long rx_errors;
+};
+
/**
* struct vlan_dev_info - VLAN private device data
* @nr_ingress_mappings: number of ingress priority mappings
@@ -45,6 +54,7 @@ struct vlan_dev_info {
struct proc_dir_entry *dent;
unsigned long cnt_inc_headroom_on_tx;
unsigned long cnt_encap_on_xmit;
+ struct vlan_rx_stats *vlan_rx_stats;
};
static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev)
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index 971d375..9b97ffb 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -31,7 +31,7 @@ EXPORT_SYMBOL(__vlan_hwaccel_rx);
int vlan_hwaccel_do_receive(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- struct net_device_stats *stats;
+ struct vlan_rx_stats *rx_stats = NULL;
skb->dev = vlan_dev_info(dev)->real_dev;
netif_nit_deliver(skb);
@@ -40,15 +40,24 @@ int vlan_hwaccel_do_receive(struct sk_buff *skb)
skb->priority = vlan_get_ingress_priority(dev, skb->vlan_tci);
skb->vlan_tci = 0;
- stats = &dev->stats;
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
+ if (likely(vlan_dev_info(dev)->vlan_rx_stats)) {
+ rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
+ smp_processor_id());
+ rx_stats->rx_packets++;
+ rx_stats->rx_bytes += skb->len;
+ } else {
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ }
switch (skb->pkt_type) {
case PACKET_BROADCAST:
break;
case PACKET_MULTICAST:
- stats->multicast++;
+ if (likely(rx_stats))
+ rx_stats->multicast++;
+ else
+ dev->stats.multicast++;
break;
case PACKET_OTHERHOST:
/* Our lower layer thinks this is not local, let's make sure.
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 9159659..9ef1e0e 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -140,7 +140,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *ptype, struct net_device *orig_dev)
{
struct vlan_hdr *vhdr;
- struct net_device_stats *stats;
+ struct vlan_rx_stats *rx_stats = NULL;
u16 vlan_id;
u16 vlan_tci;
@@ -163,9 +163,15 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
goto err_unlock;
}
- stats = &skb->dev->stats;
- stats->rx_packets++;
- stats->rx_bytes += skb->len;
+ if (likely(vlan_dev_info(dev)->vlan_rx_stats)) {
+ rx_stats = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats,
+ smp_processor_id());
+ rx_stats->rx_packets++;
+ rx_stats->rx_bytes += skb->len;
+ } else {
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ }
skb_pull_rcsum(skb, VLAN_HLEN);
@@ -180,7 +186,10 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
break;
case PACKET_MULTICAST:
- stats->multicast++;
+ if (likely(rx_stats))
+ rx_stats->multicast++;
+ else
+ dev->stats.multicast++;
break;
case PACKET_OTHERHOST:
@@ -200,7 +209,10 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
skb = vlan_check_reorder_header(skb);
if (!skb) {
- stats->rx_errors++;
+ if (likely(rx_stats))
+ rx_stats->rx_errors++;
+ else
+ dev->stats.rx_errors++;
goto err_unlock;
}
@@ -775,6 +787,31 @@ static u32 vlan_ethtool_get_flags(struct net_device *dev)
return dev_ethtool_get_flags(vlan->real_dev);
}
+static struct net_device_stats *vlan_dev_get_stats(struct net_device *dev)
+{
+ struct net_device_stats *stats = &dev->stats;
+
+ dev_txq_stats_fold(dev, stats);
+
+ if (vlan_dev_info(dev)->vlan_rx_stats) {
+ struct vlan_rx_stats *p, rx = {0};
+ int i;
+
+ for_each_possible_cpu(i) {
+ p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i);
+ rx.rx_packets += p->rx_packets;
+ rx.rx_bytes += p->rx_bytes;
+ rx.rx_errors += p->rx_errors;
+ rx.multicast += p->multicast;
+ }
+ stats->rx_packets = rx.rx_packets;
+ stats->rx_bytes = rx.rx_bytes;
+ stats->rx_errors = rx.rx_errors;
+ stats->multicast = rx.multicast;
+ }
+ return stats;
+}
+
static const struct ethtool_ops vlan_ethtool_ops = {
.get_settings = vlan_ethtool_get_settings,
.get_drvinfo = vlan_ethtool_get_drvinfo,
@@ -797,6 +834,7 @@ static const struct net_device_ops vlan_netdev_ops = {
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
.ndo_do_ioctl = vlan_dev_ioctl,
.ndo_neigh_setup = vlan_dev_neigh_setup,
+ .ndo_get_stats = vlan_dev_get_stats,
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
.ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
.ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
@@ -820,6 +858,7 @@ static const struct net_device_ops vlan_netdev_accel_ops = {
.ndo_change_rx_flags = vlan_dev_change_rx_flags,
.ndo_do_ioctl = vlan_dev_ioctl,
.ndo_neigh_setup = vlan_dev_neigh_setup,
+ .ndo_get_stats = vlan_dev_get_stats,
#if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE)
.ndo_fcoe_ddp_setup = vlan_dev_fcoe_ddp_setup,
.ndo_fcoe_ddp_done = vlan_dev_fcoe_ddp_done,
@@ -841,5 +880,7 @@ void vlan_setup(struct net_device *dev)
dev->destructor = free_netdev;
dev->ethtool_ops = &vlan_ethtool_ops;
+ vlan_dev_info(dev)->vlan_rx_stats = alloc_percpu(struct vlan_rx_stats);
+
memset(dev->broadcast, 0, ETH_ALEN);
}
^ permalink raw reply related
* Re: [PATCH] ppp: fix BUG on non-linear SKB (multilink receive)
From: Ben McKeegan @ 2009-11-16 13:44 UTC (permalink / raw)
To: David Miller; +Cc: paulus, netdev, linux-ppp
In-Reply-To: <20091113.194650.214404898.davem@davemloft.net>
PPP does not correctly call pskb_may_pull() on all necessary receive paths
before reading the PPP protocol, thus causing PPP to report seemingly
random 'unsupported protocols' and eventually trigger BUG_ON(skb->len <
skb->data_len) in skb_pull_rcsum() when receiving multilink protocol in
non-linear skbs.
ppp_receive_nonmp_frame() does not call pskb_may_pull() before reading the
protocol number. For the non-mp receive path this is not a problem, as
this check is done in ppp_receive_frame(). For the mp receive path,
ppp_mp_reconstruct() usually copies the data into a new linear skb.
However, in the case where the frame is made up of a single mp fragment,
the mp header is pulled and the existing skb used. This skb was then
passed to ppp_receive_nonmp_frame() without checking if the encapsulated
protocol header could safely be read.
Signed-off-by: Ben McKeegan <ben@netservers.co.uk>
---
diff -uprN linux-2.6.31.6/drivers/net/ppp_generic.c linux-2.6.31.6-ppp-non-linear-skb/drivers/net/ppp_generic.c
--- linux-2.6.31.6/drivers/net/ppp_generic.c 2009-11-10 00:32:31.000000000 +0000
+++ linux-2.6.31.6-ppp-non-linear-skb/drivers/net/ppp_generic.c 2009-11-16 13:14:22.000000000 +0000
@@ -1943,8 +1943,15 @@ ppp_receive_mp_frame(struct ppp *ppp, st
}
/* Pull completed packets off the queue and receive them. */
- while ((skb = ppp_mp_reconstruct(ppp)))
- ppp_receive_nonmp_frame(ppp, skb);
+ while ((skb = ppp_mp_reconstruct(ppp))) {
+ if (pskb_may_pull(skb, 2))
+ ppp_receive_nonmp_frame(ppp, skb);
+ else {
+ ++ppp->dev->stats.rx_length_errors;
+ kfree_skb(skb);
+ ppp_receive_error(ppp);
+ }
+ }
return;
^ permalink raw reply
* Re: [RFC-PATCH] libiscsi dhcp handler
From: Rakesh Ranjan @ 2009-11-16 13:45 UTC (permalink / raw)
To: David Miller
Cc: michaelc, open-iscsi, netdev, linux-kernel, James.Bottomley, kxie,
Rakesh Ranjan
In-Reply-To: <20091116.051835.125328285.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 516 bytes --]
David Miller wrote:
> From: Rakesh Ranjan <rakesh@chelsio.com>
> Date: Mon, 16 Nov 2009 18:41:49 +0530
>
>> Herein attached patches to support dhcp based provisioning for iSCSI
>> offload capable cards. I have made dhcp code as generic as possible,
>> please go through the code. Based on the feedback I will submit final
>> version of these patches.
>
> You can't really add objects to the build before the patch that
> adds the source for that object.
>
Hi david,
Fixed patch attached.
Regards
Rakesh Ranjan
[-- Attachment #2: 0001-Required-changes-for-libiscsi-to-support-dhcp-based.patch --]
[-- Type: text/x-patch, Size: 3869 bytes --]
>From a643bfb01c4edbb2e686dd2500a564c93d402bba Mon Sep 17 00:00:00 2001
From: Rakesh Ranjan <rakesh@chelsio.com>
Date: Mon, 16 Nov 2009 19:07:40 +0530
Subject: [PATCH 1/2] Required changes for libiscsi to support dhcp based provisioning for offload capable cards.
These changes adds ISCSI_UEVENT_REQ_IPCONF message to invoke dhcp handler.
Signed-off-by: Rakesh Ranjan <rakesh@chelsio.com>
---
drivers/scsi/scsi_transport_iscsi.c | 25 +++++++++++++++++++++++++
include/scsi/iscsi_if.h | 4 ++++
include/scsi/libiscsi.h | 20 ++++++++++++++++++++
include/scsi/scsi_transport_iscsi.h | 1 +
4 files changed, 50 insertions(+), 0 deletions(-)
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index ad897df..4897a3f 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1508,6 +1508,28 @@ iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev)
}
static int
+iscsi_req_ipconf(struct iscsi_transport *transport, struct iscsi_uevent *ev)
+{
+ struct Scsi_Host *shost;
+ int err;
+
+ if (!transport->req_ipconf)
+ return -ENOSYS;
+
+ shost = scsi_host_lookup(ev->u.req_ipconf.host_no);
+ if (!shost) {
+ printk(KERN_ERR "ipconf req could not find host no %u\n",
+ ev->u.req_ipconf.host_no);
+ return -ENODEV;
+ }
+
+ err = transport->req_ipconf(shost);
+
+ scsi_host_put(shost);
+ return err;
+}
+
+static int
iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
{
int err = 0;
@@ -1627,6 +1649,9 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
case ISCSI_UEVENT_PATH_UPDATE:
err = iscsi_set_path(transport, ev);
break;
+ case ISCSI_UEVENT_REQ_IPCONF:
+ err = iscsi_req_ipconf(transport, ev);
+ break;
default:
err = -ENOSYS;
break;
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index d67dda2..135f229 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -59,6 +59,7 @@ enum iscsi_uevent_e {
ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST = UEVENT_BASE + 19,
ISCSI_UEVENT_PATH_UPDATE = UEVENT_BASE + 20,
+ ISCSI_UEVENT_REQ_IPCONF = UEVENT_BASE + 21,
/* up events */
ISCSI_KEVENT_RECV_PDU = KEVENT_BASE + 1,
@@ -172,6 +173,9 @@ struct iscsi_uevent {
struct msg_set_path {
uint32_t host_no;
} set_path;
+ struct mag_req_ipconf {
+ uint32_t host_no;
+ } req_ipconf;
} u;
union {
/* messages k -> u */
diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h
index a72edd4..a9af95e 100644
--- a/include/scsi/libiscsi.h
+++ b/include/scsi/libiscsi.h
@@ -330,6 +330,18 @@ struct iscsi_host {
char workq_name[20];
};
+/* libiscsi ipconfig */
+struct dhcp_info {
+ __be32 ltime;
+ __be32 serverid;
+ __be32 ipaddr;
+ __be32 netmask;
+ __be32 dnsaddr;
+ __be32 gipaddr;
+ __u8 *mac_addr;
+};
+
+
/*
* scsi host template
*/
@@ -427,6 +439,14 @@ extern void iscsi_pool_free(struct iscsi_pool *);
extern int iscsi_pool_init(struct iscsi_pool *, int, void ***, int);
/*
+ * libiscsi ipconfig helpers
+ */
+extern int libiscsi_do_ipconf(struct net_device *ndev,
+ struct dhcp_info *dinfo);
+extern int libiscsi_ipconfig_recv(struct net_device *ndev,
+ struct sk_buff *skb);
+
+/*
* inline functions to deal with padding.
*/
static inline unsigned int
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index 349c7f3..3e5fd96 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -134,6 +134,7 @@ struct iscsi_transport {
int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
uint32_t enable, struct sockaddr *dst_addr);
int (*set_path) (struct Scsi_Host *shost, struct iscsi_path *params);
+ int (*req_ipconf) (struct Scsi_Host *shost);
};
/*
--
1.6.0.6
[-- Attachment #3: 0002-dhcp-handler-for-libiscsi-to-support-dhcp-provisioni.patch --]
[-- Type: text/x-patch, Size: 11987 bytes --]
>From 604f882083472b515342c43790eb252dd0e9a18b Mon Sep 17 00:00:00 2001
From: Rakesh Ranjan <rakesh@chelsio.com>
Date: Mon, 16 Nov 2009 19:10:00 +0530
Subject: [PATCH 2/2] dhcp handler for libiscsi to support dhcp provisioning for offload capable cards.
This module contains a compact dhcp handler to support dhcp based provisioning for
offload capable cards.
Signed-off-by: Rakesh Ranjan <rakesh@chelsio.com>
---
drivers/scsi/Makefile | 2 +-
drivers/scsi/libiscsi_ipconfig.c | 466 ++++++++++++++++++++++++++++++++++++++
2 files changed, 467 insertions(+), 1 deletions(-)
create mode 100644 drivers/scsi/libiscsi_ipconfig.c
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 3ad61db..c53355f 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -129,7 +129,7 @@ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
obj-$(CONFIG_SCSI_MVSAS) += mvsas/
obj-$(CONFIG_PS3_ROM) += ps3rom.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_tcp.o cxgb3i/
+obj-$(CONFIG_SCSI_CXGB3_ISCSI) += libiscsi.o libiscsi_ipconfig.o libiscsi_tcp.o cxgb3i/
obj-$(CONFIG_SCSI_BNX2_ISCSI) += libiscsi.o bnx2i/
obj-$(CONFIG_BE2ISCSI) += libiscsi.o be2iscsi/
obj-$(CONFIG_SCSI_PMCRAID) += pmcraid.o
diff --git a/drivers/scsi/libiscsi_ipconfig.c b/drivers/scsi/libiscsi_ipconfig.c
new file mode 100644
index 0000000..4057aae
--- /dev/null
+++ b/drivers/scsi/libiscsi_ipconfig.c
@@ -0,0 +1,466 @@
+/* libiscsi_ipconfig.c: libiscsi dhcp client.
+ *
+ * Copyright (c) 2009 Chelsio Communications, Inc.
+ *
+ * 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.
+ *
+ * Written by: Rakesh Ranjan (rakesh@chelsio.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/in.h>
+#include <linux/delay.h>
+#include <linux/if_arp.h>
+#include <net/ip.h>
+#include <scsi/iscsi_if.h>
+#include <scsi/libiscsi.h>
+
+#define DHCP_REQUEST 1
+#define DHCP_REPLY 2
+#define DHCP_HTYPE_ETHERNET 1
+#define DHCP_HLEN_ETHERNET 6
+#define DHCP_MSG_LEN 236
+
+#define DHCPC_SERVER_PORT 67
+#define DHCPC_CLIENT_PORT 68
+
+/* DHCP message types */
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
+
+/* DHCP options */
+#define DHCP_OPTION_SUBNET_MASK 1
+#define DHCP_OPTION_ROUTER 3
+#define DHCP_OPTION_DNS_SERVER 6
+#define DHCP_OPTION_MTU 26
+#define DHCP_OPTION_REQ_IPADDR 50
+#define DHCP_OPTION_LEASE_TIME 51
+#define DHCP_OPTION_MSG_TYPE 53
+#define DHCP_OPTION_SERVER_ID 54
+#define DHCP_OPTION_REQ_LIST 55
+#define DHCP_OPTION_VCID 60
+#define DHCP_OPTION_END 255
+
+enum {
+ STATE_INIT = 0,
+ STATE_SENDING,
+ STATE_OFFER_REC,
+ STATE_CONFIG_REC,
+};
+
+struct dhcp_pkt {
+ struct iphdr iph;
+ struct udphdr udph;
+ u8 op;
+ u8 htype;
+ u8 hlen;
+ u8 hops;
+ __be32 xid;
+ __be16 secs;
+ __be16 flags;
+ __be32 cipaddr;
+ __be32 yipaddr;
+ __be32 sipaddr;
+ __be32 ripaddr;
+ u8 chwaddr[16];
+ u8 sname[64];
+ u8 bfile[128];
+ u8 options[312];
+};
+
+
+static struct dhcp_client_state {
+ struct sk_buff *skb;
+ struct dhcp_pkt *pkt;
+ struct net_device *ndev;
+ struct list_head list;
+ struct dhcp_info dinfo;
+
+ volatile __u8 state;
+ __be32 xid;
+
+} client_state;
+
+static DEFINE_SPINLOCK(rcv_lock);
+
+static const char *RFC2132_VENDOR_CLASS_ID = "libiscsi client";
+
+static const u8 magic_cookie[4] = { 99, 130, 83, 99 };
+
+static inline u8 *add_msg_type(u8 *optptr, u8 type)
+{
+ *optptr++ = DHCP_OPTION_MSG_TYPE;
+ *optptr++ = 1;
+ *optptr++ = type;
+ return optptr;
+}
+
+static inline u8 *add_req_options(u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_LIST;
+ *optptr++ = 4;
+ *optptr++ = DHCP_OPTION_SUBNET_MASK;
+ *optptr++ = DHCP_OPTION_ROUTER;
+ *optptr++ = DHCP_OPTION_DNS_SERVER;
+ *optptr++ = DHCP_OPTION_MTU;
+ return optptr;
+}
+
+static inline u8 *add_vendor_cid(u8 *optptr)
+{
+ u8 len = strlen(RFC2132_VENDOR_CLASS_ID);
+ *optptr++ = DHCP_OPTION_VCID;
+ *optptr++ = len;
+ memcpy(optptr, RFC2132_VENDOR_CLASS_ID, len);
+ optptr += len;
+ return optptr;
+}
+
+static inline u8 *add_server_id(__be32 *sid, u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_SERVER_ID;
+ *optptr++ = 4;
+ memcpy(optptr, sid, 4);
+ return optptr + 4;
+}
+
+static inline u8 *add_req_ipaddr(__be32 *ip, u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_REQ_IPADDR;
+ *optptr++ = 4;
+ memcpy(optptr, ip, 4);
+ return optptr + 4;
+}
+
+static inline u8 *add_end(u8 *optptr)
+{
+ *optptr++ = DHCP_OPTION_END;
+ return optptr;
+}
+
+static void
+libiscsi_process_dhcp_opts(struct dhcp_client_state *client, u8 *optptr,
+ int len)
+{
+ u8 *end = optptr + len;
+ u8 type = 0;
+
+ while (optptr < end) {
+ switch (*optptr) {
+ case DHCP_OPTION_SUBNET_MASK:
+ memcpy(&client->dinfo.netmask, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_ROUTER:
+ memcpy(&client->dinfo.gipaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_DNS_SERVER:
+ memcpy(&client->dinfo.dnsaddr, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_MSG_TYPE:
+ type = *(optptr + 2);
+ if (type == DHCPOFFER)
+ client->state = STATE_OFFER_REC;
+ else if (type == DHCPACK)
+ client->state = STATE_CONFIG_REC;
+ break;
+ case DHCP_OPTION_SERVER_ID:
+ memcpy(&client->dinfo.serverid, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_LEASE_TIME:
+ memcpy(&client->dinfo.ltime, optptr + 2, 4);
+ break;
+ case DHCP_OPTION_END:
+ break;
+ }
+
+ optptr += optptr[1] + 2;
+ }
+}
+
+static void
+libiscsi_process_dhcp_pack(struct dhcp_client_state *client,
+ struct dhcp_pkt *pkt)
+{
+ u8 *start, *end;
+ int opt_len;
+
+ start = &pkt->options[4];
+ end = (u8 *) pkt + ntohs(pkt->iph.tot_len);
+ opt_len = end - start;
+
+ if (pkt->op == DHCP_REPLY &&
+ !memcmp(&pkt->xid, &client->xid, sizeof(client->xid)) &&
+ !memcmp(pkt->chwaddr, client->dinfo.mac_addr, pkt->hlen)) {
+ memcpy(&client->dinfo.ipaddr, &pkt->yipaddr, 4);
+ libiscsi_process_dhcp_opts(client, start, opt_len);
+ }
+}
+
+static int
+libiscsi_ipconfig_send(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ struct sk_buff *lskb = client->skb;
+
+ lskb->dev = client->ndev;
+ lskb->protocol = htons(ETH_P_IP);
+
+ dev_hard_header(lskb, client->ndev, ntohs(lskb->protocol),
+ client->ndev->broadcast,
+ client->dinfo.mac_addr, lskb->len);
+ rc = dev_queue_xmit(lskb);
+
+ return rc;
+}
+
+int
+libiscsi_ipconfig_recv(struct net_device *ndev, struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct ethhdr *eh;
+ struct dhcp_pkt *pkt;
+ struct sk_buff *pskb;
+ int len, opts_len;
+ struct dhcp_client_state *client;
+ int rc = 0;
+
+
+ client = &client_state;
+
+ if (unlikely(client->state == STATE_INIT))
+ goto out;
+
+ if (skb->pkt_type != PACKET_OTHERHOST)
+ goto out;
+
+ pskb = skb_copy(skb, GFP_ATOMIC);
+ if (!pskb) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ eh = eth_hdr(pskb);
+ if (!is_valid_ether_addr(eh->h_dest))
+ goto drop;
+
+ if (compare_ether_addr(eh->h_dest, client->dinfo.mac_addr))
+ goto drop;
+
+ if (!pskb_may_pull(pskb, sizeof(struct iphdr) + sizeof(struct udphdr)))
+ goto drop;
+
+
+ skb_reset_network_header(pskb);
+ pkt = (struct dhcp_pkt *) skb_network_header(pskb);
+ iph = &pkt->iph;
+
+ if (iph->ihl != 5 || iph->version != 4 || iph->protocol != IPPROTO_UDP)
+ goto drop;
+
+ if (iph->frag_off & htons(IP_OFFSET | IP_MF))
+ goto drop;
+
+ if (skb->len < ntohs(iph->tot_len))
+ goto drop;
+
+ if (ip_fast_csum((u8 *)iph, iph->ihl))
+ goto drop;
+
+ udph = &pkt->udph;
+ if (udph->source != htons(67) || udph->dest != htons(68))
+ goto drop;
+
+ if (ntohs(iph->tot_len) < ntohs(udph->len) + sizeof(struct iphdr))
+ goto drop;
+
+ len = ntohs(udph->len) - sizeof(struct udphdr);
+ opts_len = len - (sizeof(*pkt) -
+ sizeof(struct iphdr) -
+ sizeof(struct udphdr) -
+ sizeof(pkt->options));
+ if (opts_len < 0)
+ goto drop;
+
+ if (memcmp(pkt->options, magic_cookie, 4))
+ goto drop;
+
+ spin_lock(&rcv_lock);
+
+ libiscsi_process_dhcp_pack(client, pkt);
+
+ spin_unlock(&rcv_lock);
+
+drop:
+ kfree(pskb);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(libiscsi_ipconfig_recv);
+
+static int
+libiscsi_create_dhcp_msg(struct dhcp_client_state *client)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ struct sk_buff *skb;
+ struct dhcp_pkt *pkt;
+ int rc = 0;
+
+ skb = alloc_skb(sizeof(*pkt) +
+ LL_ALLOCATED_SPACE(client->ndev) + 15,
+ GFP_KERNEL);
+ if (!skb) {
+ rc = -ENOMEM;
+ return rc;
+ }
+
+ client->skb = skb;
+ skb_reserve(skb, LL_RESERVED_SPACE(client->ndev));
+
+ pkt = (struct dhcp_pkt *) skb_put(skb, sizeof(*pkt));
+ BUG_ON(!pkt);
+ client->pkt = pkt;
+ memset(pkt, 0, sizeof(*pkt));
+
+ skb_reset_network_header(skb);
+
+ /* construct IP header */
+ iph = &pkt->iph;
+ iph->version = 4;
+ iph->ihl = 5;
+ iph->tot_len = htons(sizeof(struct dhcp_pkt));
+ iph->frag_off = htons(IP_DF);
+ iph->ttl = 64;
+ iph->protocol = IPPROTO_UDP;
+ iph->daddr = htonl(INADDR_BROADCAST);
+ iph->check = ip_fast_csum((u8 *) iph, iph->ihl);
+
+ /* Construct UDP header */
+ udph = &pkt->udph;
+ udph->source = htons(DHCPC_CLIENT_PORT);
+ udph->dest = htons(DHCPC_SERVER_PORT);
+ udph->len = htons(sizeof(struct dhcp_pkt) - sizeof(struct iphdr));
+
+ pkt->op = DHCP_REQUEST;
+ pkt->htype = DHCP_HTYPE_ETHERNET;
+ pkt->hlen = ETH_ALEN;
+
+ memcpy(pkt->chwaddr, client->dinfo.mac_addr, ETH_ALEN);
+ pkt->secs = htons(jiffies / HZ);
+ pkt->xid = client->xid;
+
+ memcpy(pkt->options, magic_cookie, sizeof(magic_cookie));
+
+ return rc;
+}
+
+static int libiscsi_send_dhcp_request(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ u8 *end;
+
+ rc = libiscsi_create_dhcp_msg(client);
+ if (rc)
+ return rc;
+
+ end = add_msg_type(&client->pkt->options[4], DHCPREQUEST);
+ end = add_server_id(&client->dinfo.serverid, end);
+ end = add_req_ipaddr(&client->dinfo.ipaddr, end);
+ end = add_vendor_cid(end);
+ end = add_end(end);
+
+ rc = libiscsi_ipconfig_send(client);
+
+ return rc;
+}
+
+static int libiscsi_send_dhcp_discover(struct dhcp_client_state *client)
+{
+ int rc = 0;
+ u8 *end;
+
+ rc = libiscsi_create_dhcp_msg(client);
+ if (rc)
+ return rc;
+
+ end = add_msg_type(&client->pkt->options[4], DHCPDISCOVER);
+ end = add_req_options(end);
+ end = add_vendor_cid(end);
+ end = add_end(end);
+
+ client->state = STATE_SENDING;
+ rc = libiscsi_ipconfig_send(client);
+
+ return rc;
+}
+
+static void
+libiscsi_wait_for_pack(struct dhcp_client_state *client, u8 state)
+{
+ unsigned long tout, ntout;
+
+ get_random_bytes(&tout, sizeof(tout));
+ tout = (tout % (unsigned)HZ) + (HZ * 2);
+
+ ntout = jiffies + tout;
+ while (time_before(jiffies, ntout) && (client->state != state))
+ schedule_timeout_uninterruptible(1);
+}
+
+int libiscsi_do_ipconf(struct net_device *ndev, struct dhcp_info *dinfo)
+{
+ int rc = 0;
+ int retry;
+ struct dhcp_client_state *client;
+ retry = 2;
+
+ client = &client_state;
+ client->dinfo.mac_addr = dinfo->mac_addr;
+ client->ndev = ndev;
+ client->state = STATE_INIT;
+
+ /* show time */
+ for (;;) {
+ get_random_bytes(&client->xid, sizeof(__be32));
+ libiscsi_send_dhcp_discover(client);
+ libiscsi_wait_for_pack(client, STATE_OFFER_REC);
+
+ if (client->state == STATE_OFFER_REC) {
+ libiscsi_send_dhcp_request(client);
+ libiscsi_wait_for_pack(client, STATE_CONFIG_REC);
+ if (client->state == STATE_CONFIG_REC) {
+ dinfo->ipaddr = client->dinfo.ipaddr;
+ dinfo->netmask = client->dinfo.netmask;
+ dinfo->ltime = client->dinfo.ltime;
+ client->state = STATE_INIT;
+ break;
+ }
+ }
+
+ if (!--retry) {
+ rc = -ENETUNREACH;
+ break;
+ }
+ }
+
+ return rc;
+}
+EXPORT_SYMBOL(libiscsi_do_ipconf);
+
+MODULE_AUTHOR("Rakesh Ranjan");
+MODULE_DESCRIPTION("iSCSI ipconfig functions");
+MODULE_LICENSE("GPL");
--
1.6.0.6
^ permalink raw reply related
* Re: [PATCH v1 resent] net: TCP_MSS_DEFAULT, TCP_MSS_DESIRED
From: William Allen Simpson @ 2009-11-16 14:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-kernel
In-Reply-To: <20091115.205442.77893528.davem@davemloft.net>
David Miller wrote:
> I already applied this patch to net-next-2.6, there is no need
> to resend it.
>
Cool, there wasn't your usual "applied" response to the list, so the
instructions say send again after waiting (5 days in this case), as it
might have been overlooked.
'git fetch' followed by 'git rebase origin/master' re-applies my patches
locally, but doesn't inform me that this patch has already been applied,
it just handles it silently....
I've found the log, it's commit bee7ca9ec03a26676ea2b1c28dc4039348eff3e1
Thanks!
^ permalink raw reply
* Re: [RFC PATCH] net: add dataref destructor to sk_buff
From: Gregory Haskins @ 2009-11-16 14:22 UTC (permalink / raw)
To: David Miller
Cc: herbert, ghaskins, mst, alacrityvm-devel, linux-kernel, netdev
In-Reply-To: <20091113.190438.78469912.davem@davemloft.net>
[-- Attachment #1: Type: text/plain, Size: 2245 bytes --]
David Miller wrote:
> From: Gregory Haskins <gregory.haskins@gmail.com>
> Date: Fri, 13 Nov 2009 20:33:35 -0500
>
>> Well, not with respect to the overall protocol, of course not. But with
>> respect to the buffer in question, it _has_ to be. Or am I missing
>> something?
>
> sendfile() absolutely, and positively, is not.
>
> Any entity can write to the pages being send via sendfile(), at will,
> and those writes will show up in the packet stream if they occur
> before the NIC DMA's the memory backed by those pages into it's
> buffer.
Right, understood.
>
> There is zero data synchronization whatsoever, we don't lock the
> pages, we don't block their usage while they are queued up in the
> socket send queue, nothing like that.
Understood.
>
> The user returns long before it every hits the wire and there is zero
> "notification" to the user that the pages in question for the
> sendfile() request are no longer in use.
Ok, this was the part I didn't know.
>
> It seems that your understanding of how buffering and synchronization
> works in the TCP stack has come out of a fairy tale :-)
I understand that we do not protect the buffers from modification from
other entities in process. This was purely a question of
synchronization from the producers standpoint.
IOW:
for (;;) {
char buf[512];
memcpy(buf, next, sizeof(buf));
write(fd, buf);
}
would work without worrying that the producer will stomp on buf itself.
It is now my understanding that for things other than sendfile, this
works because the buffer is copied before it returns control to the app.
For sendfile(), the producer is more or less on its own and therefore
has to be careful if they are reusing previous mmapped buffers. Ok.
But really, this is somewhat orthogonal to the original problem, so let
me see if we can bring it back on topic. Michael stated that this patch
in question may be problematic because there are places in the stack
that can get_page() without also maintaining a reference to the shinfo
object. Evgeniy seems to say the opposite. I am not sure who is right,
or if I misunderstood one or both of them. Any thoughts?
Kind Regards,
-Greg
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 267 bytes --]
^ permalink raw reply
* [PATCH 1/2] KS8695: fix ks8695_rx_irq() bug.
From: zealcook @ 2009-11-16 14:30 UTC (permalink / raw)
To: netdev; +Cc: ben, davem, jie.zeng
From: jie.zeng <jie.zeng@soliton.com.cn>
ks8695 rx irq is edge-level. Before arriving at irq handler, the
corresponding status bit has been clear(irq's ack).
So we should not check it after that.
Signed-off-by: jie.zeng <jie.zeng@soliton.com.cn>
---
drivers/net/arm/ks8695net.c | 20 +++++++-------------
1 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index 0073d19..64c683d 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -433,24 +433,18 @@ ks8695_rx_irq(int irq, void *dev_id)
{
struct net_device *ndev = (struct net_device *)dev_id;
struct ks8695_priv *ksp = netdev_priv(ndev);
- unsigned long status;
-
- unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
spin_lock(&ksp->rx_lock);
status = readl(KS8695_IRQ_VA + KS8695_INTST);
- /*clean rx status bit*/
- writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
-
- if (status & mask_bit) {
- if (napi_schedule_prep(&ksp->napi)) {
- /*disable rx interrupt*/
- status &= ~mask_bit;
- writel(status , KS8695_IRQ_VA + KS8695_INTEN);
- __napi_schedule(&ksp->napi);
- }
+ if (napi_schedule_prep(&ksp->napi)) {
+ unsigned long status;
+ unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
+ /*disable rx interrupt*/
+ status &= ~mask_bit;
+ writel(status , KS8695_IRQ_VA + KS8695_INTEN);
+ __napi_schedule(&ksp->napi);
}
spin_unlock(&ksp->rx_lock);
--
1.4.4.4
^ permalink raw reply related
* [PATCH 2/2] KS8695: fix ks8695_rx to block user space program.
From: zealcook @ 2009-11-16 14:30 UTC (permalink / raw)
To: netdev; +Cc: ben, davem, jie.zeng
In-Reply-To: <1258381819-10324-1-git-send-email-jie.zeng@soliton.com.cn>
From: jie.zeng <jie.zeng@soliton.com.cn>
ks8695_rx() will call refill_buffers() for every incoming packet.
Its not necessary. We just need do it after finishing receiving thing.
And the 'RX dma engine' is in the same situation.
This blocks our user space application. The following patch may fix it.
Signed-off-by: jie.zeng <jie.zeng@soliton.com.cn>
---
drivers/net/arm/ks8695net.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index 64c683d..a99be26 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -547,13 +547,14 @@ rx_finished:
(last_rx_processed + 1) &
MAX_RX_DESC_MASK;
- /* And refill the buffers */
- ks8695_refill_rxbuffers(ksp);
-
- /* Kick the RX DMA engine, in case it became
- * suspended */
- ks8695_writereg(ksp, KS8695_DRSC, 0);
}
+
+ /* And refill the buffers */
+ ks8695_refill_rxbuffers(ksp);
+
+ /* Kick the RX DMA engine, in case it became
+ * suspended */
+ ks8695_writereg(ksp, KS8695_DRSC, 0);
return received;
}
--
1.4.4.4
^ permalink raw reply related
* Re: [net-next-2.6 PATCH v6 2/7 RFC] TCPCT part 1b: generate Responder Cookie
From: William Allen Simpson @ 2009-11-16 14:39 UTC (permalink / raw)
To: Joe Perches
Cc: Linux Kernel Network Developers, Eric Dumazet, Paul E. McKenney
In-Reply-To: <1258135457.16857.107.camel@Joe-Laptop.home>
[-- Attachment #1: Type: text/plain, Size: 182 bytes --]
Joe Perches wrote:
> perhaps deleting the two unlocks above and moving it
> to the same indent level here is trivially better.
>
Done. I left the block comment.
Do I hear an Ack?
[-- Attachment #2: TCPCT+1b6++.patch --]
[-- Type: text/plain, Size: 6798 bytes --]
diff --git a/include/linux/cryptohash.h b/include/linux/cryptohash.h
index c118b2a..ec78a4b 100644
--- a/include/linux/cryptohash.h
+++ b/include/linux/cryptohash.h
@@ -2,6 +2,7 @@
#define __CRYPTOHASH_H
#define SHA_DIGEST_WORDS 5
+#define SHA_MESSAGE_BYTES (512 /*bits*/ / 8)
#define SHA_WORKSPACE_WORDS 80
void sha_init(__u32 *buf);
diff --git a/include/net/tcp.h b/include/net/tcp.h
index ec183fd..4a99a8e 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1478,6 +1478,14 @@ struct tcp_request_sock_ops {
#endif
};
+/* Using SHA1 for now, define some constants.
+ */
+#define COOKIE_DIGEST_WORDS (SHA_DIGEST_WORDS)
+#define COOKIE_MESSAGE_WORDS (SHA_MESSAGE_BYTES / 4)
+#define COOKIE_WORKSPACE_WORDS (COOKIE_DIGEST_WORDS + COOKIE_MESSAGE_WORDS)
+
+extern int tcp_cookie_generator(u32 *bakery);
+
extern void tcp_v4_init(void);
extern void tcp_init(void);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e0cfa63..86990e1 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -264,6 +264,7 @@
#include <linux/cache.h>
#include <linux/err.h>
#include <linux/crypto.h>
+#include <linux/time.h>
#include <net/icmp.h>
#include <net/tcp.h>
@@ -2842,6 +2843,135 @@ EXPORT_SYMBOL(tcp_md5_hash_key);
#endif
+/**
+ * Each Responder maintains up to two secret values concurrently for
+ * efficient secret rollover. Each secret value has 4 states:
+ *
+ * Generating. (tcp_secret_generating != tcp_secret_primary)
+ * Generates new Responder-Cookies, but not yet used for primary
+ * verification. This is a short-term state, typically lasting only
+ * one round trip time (RTT).
+ *
+ * Primary. (tcp_secret_generating == tcp_secret_primary)
+ * Used both for generation and primary verification.
+ *
+ * Retiring. (tcp_secret_retiring != tcp_secret_secondary)
+ * Used for verification, until the first failure that can be
+ * verified by the newer Generating secret. At that time, this
+ * cookie's state is changed to Secondary, and the Generating
+ * cookie's state is changed to Primary. This is a short-term state,
+ * typically lasting only one round trip time (RTT).
+ *
+ * Secondary. (tcp_secret_retiring == tcp_secret_secondary)
+ * Used for secondary verification, after primary verification
+ * failures. This state lasts no more than twice the Maximum Segment
+ * Lifetime (2MSL). Then, the secret is discarded.
+ */
+struct tcp_cookie_secret {
+ /* The secret is divided into two parts. The digest part is the
+ * equivalent of previously hashing a secret and saving the state,
+ * and serves as an initialization vector (IV). The message part
+ * serves as the trailing secret.
+ */
+ u32 secrets[COOKIE_WORKSPACE_WORDS];
+ unsigned long expires;
+};
+
+#define TCP_SECRET_1MSL (HZ * TCP_PAWS_MSL)
+#define TCP_SECRET_2MSL (HZ * TCP_PAWS_MSL * 2)
+#define TCP_SECRET_LIFE (HZ * 600)
+
+static struct tcp_cookie_secret tcp_secret_one;
+static struct tcp_cookie_secret tcp_secret_two;
+
+/* Essentially a circular list, without dynamic allocation. */
+static struct tcp_cookie_secret *tcp_secret_generating;
+static struct tcp_cookie_secret *tcp_secret_primary;
+static struct tcp_cookie_secret *tcp_secret_retiring;
+static struct tcp_cookie_secret *tcp_secret_secondary;
+
+static DEFINE_SPINLOCK(tcp_secret_locker);
+
+/* Select a pseudo-random word in the cookie workspace.
+ */
+static inline u32 tcp_cookie_work(const u32 *ws, const int n)
+{
+ return ws[COOKIE_DIGEST_WORDS + ((COOKIE_MESSAGE_WORDS-1) & ws[n])];
+}
+
+/* Fill bakery[COOKIE_WORKSPACE_WORDS] with generator, updating as needed.
+ * Called in softirq context.
+ * Returns: 0 for success.
+ */
+int tcp_cookie_generator(u32 *bakery)
+{
+ unsigned long jiffy = jiffies;
+
+ if (unlikely(time_after_eq(jiffy, tcp_secret_generating->expires))) {
+ spin_lock_bh(&tcp_secret_locker);
+ if (!time_after_eq(jiffy, tcp_secret_generating->expires)) {
+ /* refreshed by another */
+ memcpy(bakery,
+ &tcp_secret_generating->secrets[0],
+ COOKIE_WORKSPACE_WORDS);
+ } else {
+ /* still needs refreshing */
+ get_random_bytes(bakery, COOKIE_WORKSPACE_WORDS);
+
+ /* The first time, paranoia assumes that the
+ * randomization function isn't as strong. But,
+ * this secret initialization is delayed until
+ * the last possible moment (packet arrival).
+ * Although that time is observable, it is
+ * unpredictably variable. Mash in the most
+ * volatile clock bits available, and expire the
+ * secret extra quickly.
+ */
+ if (unlikely(tcp_secret_primary->expires ==
+ tcp_secret_secondary->expires)) {
+ struct timespec tv;
+
+ getnstimeofday(&tv);
+ bakery[COOKIE_DIGEST_WORDS+0] ^=
+ (u32)tv.tv_nsec;
+
+ tcp_secret_secondary->expires = jiffy
+ + TCP_SECRET_1MSL
+ + (0x0f & tcp_cookie_work(bakery, 0));
+ } else {
+ tcp_secret_secondary->expires = jiffy
+ + TCP_SECRET_LIFE
+ + (0xff & tcp_cookie_work(bakery, 1));
+ tcp_secret_primary->expires = jiffy
+ + TCP_SECRET_2MSL
+ + (0x1f & tcp_cookie_work(bakery, 2));
+ }
+ memcpy(&tcp_secret_secondary->secrets[0],
+ bakery, COOKIE_WORKSPACE_WORDS);
+
+ rcu_assign_pointer(tcp_secret_generating,
+ tcp_secret_secondary);
+ rcu_assign_pointer(tcp_secret_retiring,
+ tcp_secret_primary);
+ /*
+ * Neither call_rcu() nor synchronize_rcu() needed.
+ * Retiring data is not freed. It is replaced after
+ * further (locked) pointer updates, and a quiet time
+ * (minimum 1MSL, maximum LIFE - 2MSL).
+ */
+ }
+ spin_unlock_bh(&tcp_secret_locker);
+ } else {
+ rcu_read_lock_bh();
+ memcpy(bakery,
+ &rcu_dereference(tcp_secret_generating)->secrets[0],
+ COOKIE_WORKSPACE_WORDS);
+ rcu_read_unlock_bh();
+ }
+ return 0;
+}
+EXPORT_SYMBOL(tcp_cookie_generator);
+
void tcp_done(struct sock *sk)
{
if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV)
@@ -2876,6 +3006,7 @@ void __init tcp_init(void)
struct sk_buff *skb = NULL;
unsigned long nr_pages, limit;
int order, i, max_share;
+ unsigned long jiffy = jiffies;
BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > sizeof(skb->cb));
@@ -2969,6 +3100,15 @@ void __init tcp_init(void)
tcp_hashinfo.ehash_mask + 1, tcp_hashinfo.bhash_size);
tcp_register_congestion_control(&tcp_reno);
+
+ memset(&tcp_secret_one.secrets[0], 0, sizeof(tcp_secret_one.secrets));
+ memset(&tcp_secret_two.secrets[0], 0, sizeof(tcp_secret_two.secrets));
+ tcp_secret_one.expires = jiffy; /* past due */
+ tcp_secret_two.expires = jiffy; /* past due */
+ tcp_secret_generating = &tcp_secret_one;
+ tcp_secret_primary = &tcp_secret_one;
+ tcp_secret_retiring = &tcp_secret_two;
+ tcp_secret_secondary = &tcp_secret_two;
}
EXPORT_SYMBOL(tcp_close);
^ permalink raw reply related
* RE: [net-next] bnx2x: Handle Rx and Tx together in NAPI
From: Vladislav Zolotarov @ 2009-11-16 14:47 UTC (permalink / raw)
To: David Miller; +Cc: netdev@vger.kernel.org, Eilon Greenstein
In-Reply-To: <20091116.032400.204096446.davem@davemloft.net>
> > There is another decision to make: what to do when Rx hasn't
> > consumed the whole budget and there is still Tx work to do. I think
> > that in this case we need to return "budget", so that we pushed to
> > the end on the local NAPI's list, "consuming" some global Rx budget
> > of the local NAPI. Another option is to return the number of Rx
> > packets handled and make this NAPI be called at once. My decision is
> > based on the fact that there were scenarios when net_tx_action and
> > net_rx_action were running on different CPUs in UDP Tx test and were
> > feeding each other. In this case if I implemented the later option I
> > would prevent other local NAPIs to run.
>
> I think you should always process all of the pending TX work first,
> then do RX work and base your budget and rescheduling decisions
> purely on RX work.
Ok. I'm sending u a new patch.
^ permalink raw reply
* [PATCH 2/2 v2] KS8695: fix ks8695_rx() unreasonable action.
From: zeal @ 2009-11-16 14:58 UTC (permalink / raw)
To: netdev; +Cc: ben, davem, figo1802, zeal
In-Reply-To: <1258383490-13341-1-git-send-email-zeal>
From: zeal <zealcook@gmail.com>
ks8695_rx() will call refill_buffers() for every incoming packet.
Its not necessary. We just need do it after finishing receiving thing.
And the 'RX dma engine' is in the same situation.
This blocks our user space application. The following patch may fix it.
Signed-off-by: zeal <zealcook@gmail.com>
---
drivers/net/arm/ks8695net.c | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index e15451a..be256b3 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -544,14 +544,13 @@ rx_finished:
ksp->next_rx_desc_read =
(last_rx_processed + 1) &
MAX_RX_DESC_MASK;
-
- /* And refill the buffers */
- ks8695_refill_rxbuffers(ksp);
-
- /* Kick the RX DMA engine, in case it became
- * suspended */
- ks8695_writereg(ksp, KS8695_DRSC, 0);
}
+ /* And refill the buffers */
+ ks8695_refill_rxbuffers(ksp);
+
+ /* Kick the RX DMA engine, in case it became
+ * suspended */
+ ks8695_writereg(ksp, KS8695_DRSC, 0);
return received;
}
--
1.5.6.5
^ permalink raw reply related
* [PATCH 1/2 v2] KS8695: fix ks8695_rx_irq() bug.
From: zeal @ 2009-11-16 14:58 UTC (permalink / raw)
To: netdev; +Cc: ben, davem, figo1802, zeal
From: zeal <zealcook@gmail.com>
Sorry for the previously patches. THEY'RE NOT RIGHT. It's my mistake.
Please forgive my noise.
Please review the following patches and ignore the last (v1).
ks8695 rx irq is edge-level. Before arriving at irq handler, the
corresponding status bit has been clear(irq's ack).
So we should not check it after that.
Signed-off-by: zeal <zealcook@gmail.com>
---
drivers/net/arm/ks8695net.c | 22 +++++++---------------
1 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
index 0073d19..e15451a 100644
--- a/drivers/net/arm/ks8695net.c
+++ b/drivers/net/arm/ks8695net.c
@@ -433,24 +433,16 @@ ks8695_rx_irq(int irq, void *dev_id)
{
struct net_device *ndev = (struct net_device *)dev_id;
struct ks8695_priv *ksp = netdev_priv(ndev);
- unsigned long status;
-
- unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
spin_lock(&ksp->rx_lock);
- status = readl(KS8695_IRQ_VA + KS8695_INTST);
-
- /*clean rx status bit*/
- writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
-
- if (status & mask_bit) {
- if (napi_schedule_prep(&ksp->napi)) {
- /*disable rx interrupt*/
- status &= ~mask_bit;
- writel(status , KS8695_IRQ_VA + KS8695_INTEN);
- __napi_schedule(&ksp->napi);
- }
+ if (napi_schedule_prep(&ksp->napi)) {
+ unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
+ unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
+ /*disable rx interrupt*/
+ status &= ~mask_bit;
+ writel(status , KS8695_IRQ_VA + KS8695_INTEN);
+ __napi_schedule(&ksp->napi);
}
spin_unlock(&ksp->rx_lock);
--
1.5.6.5
^ permalink raw reply related
* Re: [PATCH 1/2 v2] KS8695: fix ks8695_rx_irq() bug.
From: Figo.zhang @ 2009-11-12 16:24 UTC (permalink / raw)
To: zeal; +Cc: netdev, ben, davem
In-Reply-To: <4b016886.1d255e0a.16f1.ffff866a@mx.google.com>
On Mon, 2009-11-16 at 22:58 +0800, zeal wrote:
> From: zeal <zealcook@gmail.com>
>
> Sorry for the previously patches. THEY'RE NOT RIGHT. It's my mistake.
> Please forgive my noise.
> Please review the following patches and ignore the last (v1).
>
> ks8695 rx irq is edge-level. Before arriving at irq handler, the
> corresponding status bit has been clear(irq's ack).
> So we should not check it after that.
see <KS8695X Integrated Multi-Port Gateway Solution Register
Description> Version 1.00
Interrupt Status Register(INTST Offset 0xE208)
it has said: This edge-triggered interrupt status is cleared by writting
1 , so we should write 1 to clear status bit manually.
>
> Signed-off-by: zeal <zealcook@gmail.com>
> ---
> drivers/net/arm/ks8695net.c | 22 +++++++---------------
> 1 files changed, 7 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
> index 0073d19..e15451a 100644
> --- a/drivers/net/arm/ks8695net.c
> +++ b/drivers/net/arm/ks8695net.c
> @@ -433,24 +433,16 @@ ks8695_rx_irq(int irq, void *dev_id)
> {
> struct net_device *ndev = (struct net_device *)dev_id;
> struct ks8695_priv *ksp = netdev_priv(ndev);
> - unsigned long status;
> -
> - unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
>
> spin_lock(&ksp->rx_lock);
>
> - status = readl(KS8695_IRQ_VA + KS8695_INTST);
> -
> - /*clean rx status bit*/
> - writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
> -
> - if (status & mask_bit) {
> - if (napi_schedule_prep(&ksp->napi)) {
> - /*disable rx interrupt*/
> - status &= ~mask_bit;
> - writel(status , KS8695_IRQ_VA + KS8695_INTEN);
> - __napi_schedule(&ksp->napi);
> - }
> + if (napi_schedule_prep(&ksp->napi)) {
> + unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
> + unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
> + /*disable rx interrupt*/
> + status &= ~mask_bit;
> + writel(status , KS8695_IRQ_VA + KS8695_INTEN);
> + __napi_schedule(&ksp->napi);
> }
>
> spin_unlock(&ksp->rx_lock);
^ permalink raw reply
* Re: [PATCH 1/2 v2] KS8695: fix ks8695_rx_irq() bug.
From: zeal @ 2009-11-16 15:18 UTC (permalink / raw)
To: Figo.zhang; +Cc: netdev, ben, davem
In-Reply-To: <1258043088.1931.13.camel@myhost>
On Fri, Nov 13, 2009 at 12:24 AM, Figo.zhang <figo1802@gmail.com> wrote:
> On Mon, 2009-11-16 at 22:58 +0800, zeal wrote:
>> From: zeal <zealcook@gmail.com>
>>
>> Sorry for the previously patches. THEY'RE NOT RIGHT. It's my mistake.
>> Please forgive my noise.
>> Please review the following patches and ignore the last (v1).
>>
>> ks8695 rx irq is edge-level. Before arriving at irq handler, the
>> corresponding status bit has been clear(irq's ack).
>> So we should not check it after that.
>
> see <KS8695X Integrated Multi-Port Gateway Solution Register
> Description> Version 1.00
>
> Interrupt Status Register(INTST Offset 0xE208)
>
> it has said: This edge-triggered interrupt status is cleared by writting
> 1 , so we should write 1 to clear status bit manually.
>
Yeah, but irq_chip's ack has done that.
Please check arch/arm/mach-ks8695/irq.c ks8695_irq_edge_chip->ack()
>>
>> Signed-off-by: zeal <zealcook@gmail.com>
>> ---
>> drivers/net/arm/ks8695net.c | 22 +++++++---------------
>> 1 files changed, 7 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
>> index 0073d19..e15451a 100644
>> --- a/drivers/net/arm/ks8695net.c
>> +++ b/drivers/net/arm/ks8695net.c
>> @@ -433,24 +433,16 @@ ks8695_rx_irq(int irq, void *dev_id)
>> {
>> struct net_device *ndev = (struct net_device *)dev_id;
>> struct ks8695_priv *ksp = netdev_priv(ndev);
>> - unsigned long status;
>> -
>> - unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
>>
>> spin_lock(&ksp->rx_lock);
>>
>> - status = readl(KS8695_IRQ_VA + KS8695_INTST);
>> -
>> - /*clean rx status bit*/
>> - writel(status | mask_bit , KS8695_IRQ_VA + KS8695_INTST);
>> -
>> - if (status & mask_bit) {
>> - if (napi_schedule_prep(&ksp->napi)) {
>> - /*disable rx interrupt*/
>> - status &= ~mask_bit;
>> - writel(status , KS8695_IRQ_VA + KS8695_INTEN);
>> - __napi_schedule(&ksp->napi);
>> - }
>> + if (napi_schedule_prep(&ksp->napi)) {
>> + unsigned long status = readl(KS8695_IRQ_VA + KS8695_INTEN);
>> + unsigned long mask_bit = 1 << ks8695_get_rx_enable_bit(ksp);
>> + /*disable rx interrupt*/
>> + status &= ~mask_bit;
>> + writel(status , KS8695_IRQ_VA + KS8695_INTEN);
>> + __napi_schedule(&ksp->napi);
>> }
>>
>> spin_unlock(&ksp->rx_lock);
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Thanks & Regards
zeal
^ permalink raw reply
* Re: [net-next-2.6 PATCH v6 2/7 RFC] TCPCT part 1b: generate Responder Cookie
From: Eric Dumazet @ 2009-11-16 15:34 UTC (permalink / raw)
To: William Allen Simpson
Cc: Joe Perches, Linux Kernel Network Developers, Paul E. McKenney
In-Reply-To: <4B016424.1030403@gmail.com>
William Allen Simpson a écrit :
> Joe Perches wrote:
>> perhaps deleting the two unlocks above and moving it
>> to the same indent level here is trivially better.
>>
> Done. I left the block comment.
>
> Do I hear an Ack?
>
Fine by me William
But you forgot to re-include full commit message and Signed-off-by:
Yes it seems cumbersome, but David is handling ~50 patches per day,
we shall give him as _perfect_ patches as possible.
^ permalink raw reply
* [PATCHv6 02/10] ib_core: Add RDMAoE transport protocol
From: Eli Cohen @ 2009-11-16 15:53 UTC (permalink / raw)
To: Roland Dreier; +Cc: Linux RDMA list, netdev, ewg
Add a new transport protocol, RDMAoE, used for transporting Infiniband traffic
over Ethernet fabrics.
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
---
include/rdma/ib_verbs.h | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 4cf42f3..d9146c4 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -69,7 +69,8 @@ enum rdma_node_type {
enum rdma_transport_type {
RDMA_TRANSPORT_IB,
- RDMA_TRANSPORT_IWARP
+ RDMA_TRANSPORT_IWARP,
+ RDMA_TRANSPORT_RDMAOE
};
enum ib_device_cap_flags {
--
1.6.5.2
^ permalink raw reply related
* [PATCHv6 04/10] IB/umad: Enable support only for IB ports
From: Eli Cohen @ 2009-11-16 15:53 UTC (permalink / raw)
To: Roland Dreier; +Cc: Linux RDMA list, netdev, ewg
Initialize umad context for devices that have any of their ports IB. Since
devices may have ports of two different protocols (for example,
RDMA_TRANSPORT_IB and RDMA_TRANSPORT_RDMAOE), ib_umad_add_one() needs to
succeed if any of the ports is IB but ib_umad_init_port() is called only for IB
ports.
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
---
drivers/infiniband/core/user_mad.c | 15 +++++++--------
1 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 6d6795d..d069689 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1124,10 +1124,6 @@ static void ib_umad_add_one(struct ib_device *device)
e = device->phys_port_cnt;
}
- for (i = s; i <= e; ++i)
- if (rdma_port_get_transport(device, i) != RDMA_TRANSPORT_IB)
- return;
-
umad_dev = kzalloc(sizeof *umad_dev +
(e - s + 1) * sizeof (struct ib_umad_port),
GFP_KERNEL);
@@ -1142,8 +1138,9 @@ static void ib_umad_add_one(struct ib_device *device)
for (i = s; i <= e; ++i) {
umad_dev->port[i - s].umad_dev = umad_dev;
- if (ib_umad_init_port(device, i, &umad_dev->port[i - s]))
- goto err;
+ if (rdma_port_get_transport(device, i) == RDMA_TRANSPORT_IB)
+ if (ib_umad_init_port(device, i, &umad_dev->port[i - s]))
+ goto err;
}
ib_set_client_data(device, &umad_client, umad_dev);
@@ -1152,7 +1149,8 @@ static void ib_umad_add_one(struct ib_device *device)
err:
while (--i >= s)
- ib_umad_kill_port(&umad_dev->port[i - s]);
+ if (rdma_port_get_transport(device, i) == RDMA_TRANSPORT_IB)
+ ib_umad_kill_port(&umad_dev->port[i - s]);
kref_put(&umad_dev->ref, ib_umad_release_dev);
}
@@ -1166,7 +1164,8 @@ static void ib_umad_remove_one(struct ib_device *device)
return;
for (i = 0; i <= umad_dev->end_port - umad_dev->start_port; ++i)
- ib_umad_kill_port(&umad_dev->port[i]);
+ if (rdma_port_get_transport(device, i + 1) == RDMA_TRANSPORT_IB)
+ ib_umad_kill_port(&umad_dev->port[i]);
kref_put(&umad_dev->ref, ib_umad_release_dev);
}
--
1.6.5.2
^ permalink raw reply related
* [PATCHv6 05/10] ib/cm: Enable CM support for RDMAoE
From: Eli Cohen @ 2009-11-16 15:53 UTC (permalink / raw)
To: Roland Dreier; +Cc: Linux RDMA list, netdev, ewg
CM messages can be transported on RDMAoE protocol ports so they are enabled
here.
Signed-off-by: Eli Cohen <eli@mellanox.co.il>
---
drivers/infiniband/core/cm.c | 5 +++--
drivers/infiniband/core/ucm.c | 12 +++++++++---
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index d082f59..c9f9122 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3680,7 +3680,8 @@ static void cm_add_one(struct ib_device *ib_device)
u8 i;
enum rdma_transport_type tt;
- if (!rdma_is_transport_supported(ib_device, RDMA_TRANSPORT_IB))
+ if (!rdma_is_transport_supported(ib_device, RDMA_TRANSPORT_IB) &&
+ !rdma_is_transport_supported(ib_device, RDMA_TRANSPORT_RDMAOE))
return;
cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
@@ -3702,7 +3703,7 @@ static void cm_add_one(struct ib_device *ib_device)
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
for (i = 1; i <= ib_device->phys_port_cnt; i++) {
tt = rdma_port_get_transport(ib_device, i);
- if (tt != RDMA_TRANSPORT_IB)
+ if (tt != RDMA_TRANSPORT_IB && tt != RDMA_TRANSPORT_RDMAOE)
continue;
port = kzalloc(sizeof *port, GFP_KERNEL);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index 43700b4..dce2cbb 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1241,13 +1241,19 @@ static void ib_ucm_add_one(struct ib_device *device)
{
struct ib_ucm_device *ucm_dev;
int i;
+ enum rdma_transport_type tt;
if (!device->alloc_ucontext)
return;
- for (i = 1; i <= device->phys_port_cnt; ++i)
- if (rdma_port_get_transport(device, i) != RDMA_TRANSPORT_IB)
- return;
+ for (i = 1; i <= device->phys_port_cnt; ++i) {
+ tt = rdma_port_get_transport(device, i);
+ if (tt == RDMA_TRANSPORT_IB || tt == RDMA_TRANSPORT_RDMAOE)
+ break;
+ }
+
+ if (i > device->phys_port_cnt)
+ return;
ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL);
if (!ucm_dev)
--
1.6.5.2
^ permalink raw reply related
* [PATCHv6 0/10] RDMAoE support
From: Eli Cohen @ 2009-11-16 15:53 UTC (permalink / raw)
To: Roland Dreier; +Cc: Linux RDMA list, netdev, ewg
RDMA over Ethernet (RDMAoE) allows running the IB transport protocol using
Ethernet frames, enabling the deployment of IB semantics on lossless Ethernet
fabrics. RDMAoE packets are standard Ethernet frames with an IEEE assigned
Ethertype, a GRH, unmodified IB transport headers and payload. IB subnet
management and SA services are not required for RDMAoE operation; Ethernet
management practices are used instead. RDMAoE encodes IP addresses into its
GIDs and resolves MAC addresses using the host IP stack. For multicast GIDs,
standard IP to MAC mappings apply.
To support RDMAoE, a new transport protocol was added to the IB core. An RDMA
device can have ports with different transports, which are identified by a port
transport attribute. The RDMA Verbs API is syntactically unmodified. When
referring to RDMAoE ports, Address handles are required to contain GIDs while
LID fields are ignored. The Ethernet L2 information is subsequently obtained by
the vendor-specific driver (in both kernel and user-space) while modifying QPs
to RTR and creating address handles. As there is no SA in RDMAoE, the CMA code
is modified to fill the necessary path record attributes locally before sending
CM packets. Similarly, the CMA provides to the user the required address handle
attributes when processing SIDR requests and joining multicast groups.
In this patch set, an RDMAoE port is currently assigned a single GID, encoding
the IPv6 link-local address of the corresponding netdev; the CMA RDMAoE code
temporarily uses IPv6 link-local addresses as GIDs instead of the IP address
provided by the user, thereby supporting any IP address.
To enable RDMAoE with the mlx4 driver stack, both the mlx4_en and mlx4_ib
drivers must be loaded, and the netdevice for the corresponding RDMAoE port
must be running. Individual ports of a multi port HCA can be independently
configured as Ethernet (with support for RDMAoE) or IB, as is already the case.
We have successfully tested MPI, SDP, RDS, and native Verbs applications over
RDMAoE.
Following is a series of 10 patches based on Roland's for-next branch. This new
series reflects changes based on feedback from the community on the previous
set of patches, and is tagged v6. Previous series were posted to the
openfabrics general list only.
Changes from v5:
1. Bug fixes.
2. NIC programming through dev_mc_add/delete were moved from CMA to the hw
specific driver. This allows native verbs applications to receive multicast
traffic too.
Signed-off-by: Eli Cohen <eli-VPRAkNaXOzVS1MOuV/RT9w@public.gmane.org>
---
drivers/infiniband/core/agent.c | 39 +-
drivers/infiniband/core/cm.c | 26 +
drivers/infiniband/core/cma.c | 272 ++++++++++++++++--
drivers/infiniband/core/mad.c | 78 +++--
drivers/infiniband/core/multicast.c | 4
drivers/infiniband/core/sa_query.c | 39 +-
drivers/infiniband/core/ucm.c | 14
drivers/infiniband/core/ucma.c | 33 ++
drivers/infiniband/core/ud_header.c | 111 +++++++
drivers/infiniband/core/user_mad.c | 13
drivers/infiniband/core/uverbs.h | 1
drivers/infiniband/core/uverbs_cmd.c | 32 ++
drivers/infiniband/core/uverbs_main.c | 1
drivers/infiniband/core/verbs.c | 35 ++
drivers/infiniband/hw/mlx4/ah.c | 181 ++++++++++--
drivers/infiniband/hw/mlx4/mad.c | 32 +-
drivers/infiniband/hw/mlx4/main.c | 436 +++++++++++++++++++++++++++---
drivers/infiniband/hw/mlx4/mlx4_ib.h | 29 +
drivers/infiniband/hw/mlx4/qp.c | 199 +++++++++----
drivers/infiniband/ulp/ipoib/ipoib_main.c | 12
drivers/net/mlx4/en_main.c | 15 -
drivers/net/mlx4/en_port.c | 4
drivers/net/mlx4/en_port.h | 3
drivers/net/mlx4/fw.c | 3
drivers/net/mlx4/intf.c | 20 +
drivers/net/mlx4/main.c | 6
drivers/net/mlx4/mlx4.h | 1
include/linux/mlx4/cmd.h | 1
include/linux/mlx4/device.h | 31 ++
include/linux/mlx4/driver.h | 16 -
include/linux/mlx4/qp.h | 8
include/rdma/ib_addr.h | 92 ++++++
include/rdma/ib_pack.h | 26 +
include/rdma/ib_user_verbs.h | 21 +
include/rdma/ib_verbs.h | 26 +
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 3
net/sunrpc/xprtrdma/svc_rdma_transport.c | 2
37 files changed, 1594 insertions(+), 271 deletions(-)
^ permalink raw reply
* [PATCHv6 01/10] ib_core: Refine device personality from node type to port type
From: Eli Cohen @ 2009-11-16 15:53 UTC (permalink / raw)
To: Roland Dreier; +Cc: Linux RDMA list, netdev, ewg
As a preparation to devices that, in general, support a different transport
protocol for each port, specifically RDMAoE, this patch defines a transport
type for each of a device's ports. As a result, rdma_node_get_transport() has
been unexported and is used internally by the implementation of the new API,
rdma_port_get_transport(), which gives the transport protocol of the queried
port. rdma_is_transport_supported() is also added to be used for verifying if a
given device supports a given protocol on any of its ports. All references to
rdma_node_get_transport() are changed to use the new APIs. Also, ib_port_attr
is extended to contain enum rdma_transport_type.
Signed-off-by: Eli Cohen <eli-VPRAkNaXOzVS1MOuV/RT9w@public.gmane.org>
---
drivers/infiniband/core/cm.c | 25 +++++++++----
drivers/infiniband/core/cma.c | 54 +++++++++++++++--------------
drivers/infiniband/core/mad.c | 49 ++++++++++++++++---------
drivers/infiniband/core/multicast.c | 4 +-
drivers/infiniband/core/sa_query.c | 39 +++++++++++++--------
drivers/infiniband/core/ucm.c | 8 +++-
drivers/infiniband/core/ucma.c | 2 +-
drivers/infiniband/core/user_mad.c | 6 +++-
drivers/infiniband/core/verbs.c | 25 ++++++++++++-
drivers/infiniband/ulp/ipoib/ipoib_main.c | 12 +++---
include/rdma/ib_verbs.h | 11 ++++--
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 3 +-
net/sunrpc/xprtrdma/svc_rdma_transport.c | 2 +-
13 files changed, 153 insertions(+), 87 deletions(-)
diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c
index 5130fc5..d082f59 100644
--- a/drivers/infiniband/core/cm.c
+++ b/drivers/infiniband/core/cm.c
@@ -3678,8 +3678,9 @@ static void cm_add_one(struct ib_device *ib_device)
unsigned long flags;
int ret;
u8 i;
+ enum rdma_transport_type tt;
- if (rdma_node_get_transport(ib_device->node_type) != RDMA_TRANSPORT_IB)
+ if (!rdma_is_transport_supported(ib_device, RDMA_TRANSPORT_IB))
return;
cm_dev = kzalloc(sizeof(*cm_dev) + sizeof(*port) *
@@ -3700,6 +3701,10 @@ static void cm_add_one(struct ib_device *ib_device)
set_bit(IB_MGMT_METHOD_SEND, reg_req.method_mask);
for (i = 1; i <= ib_device->phys_port_cnt; i++) {
+ tt = rdma_port_get_transport(ib_device, i);
+ if (tt != RDMA_TRANSPORT_IB)
+ continue;
+
port = kzalloc(sizeof *port, GFP_KERNEL);
if (!port)
goto error1;
@@ -3742,9 +3747,11 @@ error1:
port_modify.clr_port_cap_mask = IB_PORT_CM_SUP;
while (--i) {
port = cm_dev->port[i-1];
- ib_modify_port(ib_device, port->port_num, 0, &port_modify);
- ib_unregister_mad_agent(port->mad_agent);
- cm_remove_port_fs(port);
+ if (port) {
+ ib_modify_port(ib_device, port->port_num, 0, &port_modify);
+ ib_unregister_mad_agent(port->mad_agent);
+ cm_remove_port_fs(port);
+ }
}
device_unregister(cm_dev->device);
kfree(cm_dev);
@@ -3770,10 +3777,12 @@ static void cm_remove_one(struct ib_device *ib_device)
for (i = 1; i <= ib_device->phys_port_cnt; i++) {
port = cm_dev->port[i-1];
- ib_modify_port(ib_device, port->port_num, 0, &port_modify);
- ib_unregister_mad_agent(port->mad_agent);
- flush_workqueue(cm.wq);
- cm_remove_port_fs(port);
+ if (port) {
+ ib_modify_port(ib_device, port->port_num, 0, &port_modify);
+ ib_unregister_mad_agent(port->mad_agent);
+ flush_workqueue(cm.wq);
+ cm_remove_port_fs(port);
+ }
}
device_unregister(cm_dev->device);
kfree(cm_dev);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 0753178..8dc3472 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -329,24 +329,26 @@ static int cma_acquire_dev(struct rdma_id_private *id_priv)
struct cma_device *cma_dev;
union ib_gid gid;
int ret = -ENODEV;
-
- switch (rdma_node_get_transport(dev_addr->dev_type)) {
- case RDMA_TRANSPORT_IB:
- ib_addr_get_sgid(dev_addr, &gid);
- break;
- case RDMA_TRANSPORT_IWARP:
- iw_addr_get_sgid(dev_addr, &gid);
- break;
- default:
- return -ENODEV;
- }
+ int port;
list_for_each_entry(cma_dev, &dev_list, list) {
- ret = ib_find_cached_gid(cma_dev->device, &gid,
- &id_priv->id.port_num, NULL);
- if (!ret) {
- cma_attach_to_dev(id_priv, cma_dev);
- break;
+ for (port = 1; port <= cma_dev->device->phys_port_cnt; ++port) {
+ switch (rdma_port_get_transport(cma_dev->device, port)) {
+ case RDMA_TRANSPORT_IB:
+ ib_addr_get_sgid(dev_addr, &gid);
+ break;
+ case RDMA_TRANSPORT_IWARP:
+ iw_addr_get_sgid(dev_addr, &gid);
+ break;
+ default:
+ return -ENODEV;
+ }
+ ret = ib_find_cached_gid(cma_dev->device, &gid,
+ &id_priv->id.port_num, NULL);
+ if (!ret) {
+ cma_attach_to_dev(id_priv, cma_dev);
+ return ret;
+ }
}
}
return ret;
@@ -597,7 +599,7 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
int ret = 0;
id_priv = container_of(id, struct rdma_id_private, id);
- switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
+ switch (rdma_port_get_transport(id_priv->id.device, id_priv->id.port_num)) {
case RDMA_TRANSPORT_IB:
if (!id_priv->cm_id.ib || cma_is_ud_ps(id_priv->id.ps))
ret = cma_ib_init_qp_attr(id_priv, qp_attr, qp_attr_mask);
@@ -747,7 +749,7 @@ static inline int cma_user_data_offset(enum rdma_port_space ps)
static void cma_cancel_route(struct rdma_id_private *id_priv)
{
- switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
+ switch (rdma_port_get_transport(id_priv->id.device, id_priv->id.port_num)) {
case RDMA_TRANSPORT_IB:
if (id_priv->query)
ib_sa_cancel_query(id_priv->query_id, id_priv->query);
@@ -843,7 +845,7 @@ void rdma_destroy_id(struct rdma_cm_id *id)
mutex_lock(&lock);
if (id_priv->cma_dev) {
mutex_unlock(&lock);
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id_priv->id.device, id_priv->id.port_num)) {
case RDMA_TRANSPORT_IB:
if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
ib_destroy_cm_id(id_priv->cm_id.ib);
@@ -1500,7 +1502,7 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
id_priv->backlog = backlog;
if (id->device) {
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
ret = cma_ib_listen(id_priv);
if (ret)
@@ -1727,7 +1729,7 @@ int rdma_resolve_route(struct rdma_cm_id *id, int timeout_ms)
return -EINVAL;
atomic_inc(&id_priv->refcount);
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
ret = cma_resolve_ib_route(id_priv, timeout_ms);
break;
@@ -2407,7 +2409,7 @@ int rdma_connect(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
id_priv->srq = conn_param->srq;
}
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
if (cma_is_ud_ps(id->ps))
ret = cma_resolve_ib_udp(id_priv, conn_param);
@@ -2520,7 +2522,7 @@ int rdma_accept(struct rdma_cm_id *id, struct rdma_conn_param *conn_param)
id_priv->srq = conn_param->srq;
}
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
if (cma_is_ud_ps(id->ps))
ret = cma_send_sidr_rep(id_priv, IB_SIDR_SUCCESS,
@@ -2581,7 +2583,7 @@ int rdma_reject(struct rdma_cm_id *id, const void *private_data,
if (!cma_has_cm_dev(id_priv))
return -EINVAL;
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
if (cma_is_ud_ps(id->ps))
ret = cma_send_sidr_rep(id_priv, IB_SIDR_REJECT,
@@ -2612,7 +2614,7 @@ int rdma_disconnect(struct rdma_cm_id *id)
if (!cma_has_cm_dev(id_priv))
return -EINVAL;
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
ret = cma_modify_qp_err(id_priv);
if (ret)
@@ -2764,7 +2766,7 @@ int rdma_join_multicast(struct rdma_cm_id *id, struct sockaddr *addr,
list_add(&mc->list, &id_priv->mc_list);
spin_unlock(&id_priv->lock);
- switch (rdma_node_get_transport(id->device->node_type)) {
+ switch (rdma_port_get_transport(id->device, id->port_num)) {
case RDMA_TRANSPORT_IB:
ret = cma_join_ib_multicast(id_priv, mc);
break;
diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
index 7522008..28a47a8 100644
--- a/drivers/infiniband/core/mad.c
+++ b/drivers/infiniband/core/mad.c
@@ -2913,8 +2913,9 @@ static int ib_mad_port_close(struct ib_device *device, int port_num)
static void ib_mad_init_device(struct ib_device *device)
{
int start, end, i;
+ enum rdma_transport_type tt;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ if (!rdma_is_transport_supported(device, RDMA_TRANSPORT_IB))
return;
if (device->node_type == RDMA_NODE_IB_SWITCH) {
@@ -2926,6 +2927,10 @@ static void ib_mad_init_device(struct ib_device *device)
}
for (i = start; i <= end; i++) {
+ tt = rdma_port_get_transport(device, i);
+ if (tt != RDMA_TRANSPORT_IB)
+ continue;
+
if (ib_mad_port_open(device, i)) {
printk(KERN_ERR PFX "Couldn't open %s port %d\n",
device->name, i);
@@ -2941,21 +2946,25 @@ static void ib_mad_init_device(struct ib_device *device)
return;
error_agent:
- if (ib_mad_port_close(device, i))
- printk(KERN_ERR PFX "Couldn't close %s port %d\n",
- device->name, i);
+ tt = rdma_port_get_transport(device, i);
+ if (tt == RDMA_TRANSPORT_IB || tt == RDMA_TRANSPORT_RDMAOE)
+ if (ib_mad_port_close(device, i))
+ printk(KERN_ERR PFX "Couldn't close %s port %d\n",
+ device->name, i);
error:
i--;
while (i >= start) {
- if (ib_agent_port_close(device, i))
- printk(KERN_ERR PFX "Couldn't close %s port %d "
- "for agents\n",
- device->name, i);
- if (ib_mad_port_close(device, i))
- printk(KERN_ERR PFX "Couldn't close %s port %d\n",
- device->name, i);
+ if (rdma_port_get_transport(device, i) == RDMA_TRANSPORT_IB) {
+ if (ib_agent_port_close(device, i))
+ printk(KERN_ERR PFX "Couldn't close %s port %d "
+ "for agents\n",
+ device->name, i);
+ if (ib_mad_port_close(device, i))
+ printk(KERN_ERR PFX "Couldn't close %s port %d\n",
+ device->name, i);
+ }
i--;
}
}
@@ -2963,6 +2972,7 @@ error:
static void ib_mad_remove_device(struct ib_device *device)
{
int i, num_ports, cur_port;
+ enum rdma_transport_type tt;
if (device->node_type == RDMA_NODE_IB_SWITCH) {
num_ports = 1;
@@ -2972,13 +2982,16 @@ static void ib_mad_remove_device(struct ib_device *device)
cur_port = 1;
}
for (i = 0; i < num_ports; i++, cur_port++) {
- if (ib_agent_port_close(device, cur_port))
- printk(KERN_ERR PFX "Couldn't close %s port %d "
- "for agents\n",
- device->name, cur_port);
- if (ib_mad_port_close(device, cur_port))
- printk(KERN_ERR PFX "Couldn't close %s port %d\n",
- device->name, cur_port);
+ tt = rdma_port_get_transport(device, i);
+ if (tt == RDMA_TRANSPORT_IB) {
+ if (ib_agent_port_close(device, cur_port))
+ printk(KERN_ERR PFX "Couldn't close %s port %d "
+ "for agents\n",
+ device->name, cur_port);
+ if (ib_mad_port_close(device, cur_port))
+ printk(KERN_ERR PFX "Couldn't close %s port %d\n",
+ device->name, cur_port);
+ }
}
}
diff --git a/drivers/infiniband/core/multicast.c b/drivers/infiniband/core/multicast.c
index 8d82ba1..7d9887d 100644
--- a/drivers/infiniband/core/multicast.c
+++ b/drivers/infiniband/core/multicast.c
@@ -796,10 +796,10 @@ static void mcast_add_one(struct ib_device *device)
struct mcast_port *port;
int i;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ if (!rdma_is_transport_supported(device, RDMA_TRANSPORT_IB))
return;
- dev = kmalloc(sizeof *dev + device->phys_port_cnt * sizeof *port,
+ dev = kzalloc(sizeof *dev + device->phys_port_cnt * sizeof *port,
GFP_KERNEL);
if (!dev)
return;
diff --git a/drivers/infiniband/core/sa_query.c b/drivers/infiniband/core/sa_query.c
index 7e1ffd8..18b09c4 100644
--- a/drivers/infiniband/core/sa_query.c
+++ b/drivers/infiniband/core/sa_query.c
@@ -416,14 +416,16 @@ static void ib_sa_event(struct ib_event_handler *handler, struct ib_event *event
struct ib_sa_port *port =
&sa_dev->port[event->element.port_num - sa_dev->start_port];
- spin_lock_irqsave(&port->ah_lock, flags);
- if (port->sm_ah)
- kref_put(&port->sm_ah->ref, free_sm_ah);
- port->sm_ah = NULL;
- spin_unlock_irqrestore(&port->ah_lock, flags);
-
- schedule_work(&sa_dev->port[event->element.port_num -
- sa_dev->start_port].update_task);
+ if (rdma_port_get_transport(handler->device, port->port_num) == RDMA_TRANSPORT_IB) {
+ spin_lock_irqsave(&port->ah_lock, flags);
+ if (port->sm_ah)
+ kref_put(&port->sm_ah->ref, free_sm_ah);
+ port->sm_ah = NULL;
+ spin_unlock_irqrestore(&port->ah_lock, flags);
+
+ schedule_work(&sa_dev->port[event->element.port_num -
+ sa_dev->start_port].update_task);
+ }
}
}
@@ -997,7 +999,7 @@ static void ib_sa_add_one(struct ib_device *device)
struct ib_sa_device *sa_dev;
int s, e, i;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ if (!rdma_is_transport_supported(device, RDMA_TRANSPORT_IB))
return;
if (device->node_type == RDMA_NODE_IB_SWITCH)
@@ -1007,7 +1009,7 @@ static void ib_sa_add_one(struct ib_device *device)
e = device->phys_port_cnt;
}
- sa_dev = kmalloc(sizeof *sa_dev +
+ sa_dev = kzalloc(sizeof *sa_dev +
(e - s + 1) * sizeof (struct ib_sa_port),
GFP_KERNEL);
if (!sa_dev)
@@ -1017,6 +1019,9 @@ static void ib_sa_add_one(struct ib_device *device)
sa_dev->end_port = e;
for (i = 0; i <= e - s; ++i) {
+ if (rdma_port_get_transport(device, i + 1) != RDMA_TRANSPORT_IB)
+ continue;
+
sa_dev->port[i].sm_ah = NULL;
sa_dev->port[i].port_num = i + s;
spin_lock_init(&sa_dev->port[i].ah_lock);
@@ -1045,13 +1050,15 @@ static void ib_sa_add_one(struct ib_device *device)
goto err;
for (i = 0; i <= e - s; ++i)
- update_sm_ah(&sa_dev->port[i].update_task);
+ if (rdma_port_get_transport(device, i + 1) == RDMA_TRANSPORT_IB)
+ update_sm_ah(&sa_dev->port[i].update_task);
return;
err:
while (--i >= 0)
- ib_unregister_mad_agent(sa_dev->port[i].agent);
+ if (rdma_port_get_transport(device, i + 1) == RDMA_TRANSPORT_IB)
+ ib_unregister_mad_agent(sa_dev->port[i].agent);
kfree(sa_dev);
@@ -1071,9 +1078,11 @@ static void ib_sa_remove_one(struct ib_device *device)
flush_scheduled_work();
for (i = 0; i <= sa_dev->end_port - sa_dev->start_port; ++i) {
- ib_unregister_mad_agent(sa_dev->port[i].agent);
- if (sa_dev->port[i].sm_ah)
- kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+ if (rdma_port_get_transport(device, i + 1) == RDMA_TRANSPORT_IB) {
+ ib_unregister_mad_agent(sa_dev->port[i].agent);
+ if (sa_dev->port[i].sm_ah)
+ kref_put(&sa_dev->port[i].sm_ah->ref, free_sm_ah);
+ }
}
kfree(sa_dev);
diff --git a/drivers/infiniband/core/ucm.c b/drivers/infiniband/core/ucm.c
index f504c9b..43700b4 100644
--- a/drivers/infiniband/core/ucm.c
+++ b/drivers/infiniband/core/ucm.c
@@ -1240,11 +1240,15 @@ static DEVICE_ATTR(ibdev, S_IRUGO, show_ibdev, NULL);
static void ib_ucm_add_one(struct ib_device *device)
{
struct ib_ucm_device *ucm_dev;
+ int i;
- if (!device->alloc_ucontext ||
- rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ if (!device->alloc_ucontext)
return;
+ for (i = 1; i <= device->phys_port_cnt; ++i)
+ if (rdma_port_get_transport(device, i) != RDMA_TRANSPORT_IB)
+ return;
+
ucm_dev = kzalloc(sizeof *ucm_dev, GFP_KERNEL);
if (!ucm_dev)
return;
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index f1cbd26..fd831fd 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -616,7 +616,7 @@ static ssize_t ucma_query_route(struct ucma_file *file,
resp.node_guid = (__force __u64) ctx->cm_id->device->node_guid;
resp.port_num = ctx->cm_id->port_num;
- switch (rdma_node_get_transport(ctx->cm_id->device->node_type)) {
+ switch (rdma_port_get_transport(ctx->cm_id->device, ctx->cm_id->port_num)) {
case RDMA_TRANSPORT_IB:
ucma_copy_ib_route(&resp, &ctx->cm_id->route);
break;
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index 7de0296..6d6795d 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -1114,7 +1114,7 @@ static void ib_umad_add_one(struct ib_device *device)
struct ib_umad_device *umad_dev;
int s, e, i;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
+ if (!rdma_is_transport_supported(device, RDMA_TRANSPORT_IB))
return;
if (device->node_type == RDMA_NODE_IB_SWITCH)
@@ -1124,6 +1124,10 @@ static void ib_umad_add_one(struct ib_device *device)
e = device->phys_port_cnt;
}
+ for (i = s; i <= e; ++i)
+ if (rdma_port_get_transport(device, i) != RDMA_TRANSPORT_IB)
+ return;
+
umad_dev = kzalloc(sizeof *umad_dev +
(e - s + 1) * sizeof (struct ib_umad_port),
GFP_KERNEL);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index a7da9be..d81e217 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -77,7 +77,7 @@ enum ib_rate mult_to_ib_rate(int mult)
}
EXPORT_SYMBOL(mult_to_ib_rate);
-enum rdma_transport_type
+static enum rdma_transport_type
rdma_node_get_transport(enum rdma_node_type node_type)
{
switch (node_type) {
@@ -92,7 +92,28 @@ rdma_node_get_transport(enum rdma_node_type node_type)
return 0;
}
}
-EXPORT_SYMBOL(rdma_node_get_transport);
+
+enum rdma_transport_type rdma_port_get_transport(struct ib_device *device,
+ u8 port_num)
+{
+ return device->get_port_transport ?
+ device->get_port_transport(device, port_num) :
+ rdma_node_get_transport(device->node_type);
+}
+EXPORT_SYMBOL(rdma_port_get_transport);
+
+int rdma_is_transport_supported(struct ib_device *device,
+ enum rdma_transport_type transport)
+{
+ int i;
+
+ for (i = 1; i <= device->phys_port_cnt; ++i)
+ if (rdma_port_get_transport(device, i) == transport)
+ return 1;
+
+ return 0;
+}
+EXPORT_SYMBOL(rdma_is_transport_supported);
/* Protection domains */
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 2bf5116..de89e80 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1343,9 +1343,6 @@ static void ipoib_add_one(struct ib_device *device)
struct ipoib_dev_priv *priv;
int s, e, p;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
- return;
-
dev_list = kmalloc(sizeof *dev_list, GFP_KERNEL);
if (!dev_list)
return;
@@ -1361,6 +1358,9 @@ static void ipoib_add_one(struct ib_device *device)
}
for (p = s; p <= e; ++p) {
+ if (rdma_port_get_transport(device, p) != RDMA_TRANSPORT_IB)
+ continue;
+
dev = ipoib_add_port("ib%d", device, p);
if (!IS_ERR(dev)) {
priv = netdev_priv(dev);
@@ -1376,12 +1376,12 @@ static void ipoib_remove_one(struct ib_device *device)
struct ipoib_dev_priv *priv, *tmp;
struct list_head *dev_list;
- if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB)
- return;
-
dev_list = ib_get_client_data(device, &ipoib_client);
list_for_each_entry_safe(priv, tmp, dev_list, list) {
+ if (rdma_port_get_transport(device, priv->port) != RDMA_TRANSPORT_IB)
+ continue;
+
ib_unregister_event_handler(&priv->event_handler);
rtnl_lock();
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index c179318..4cf42f3 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -72,9 +72,6 @@ enum rdma_transport_type {
RDMA_TRANSPORT_IWARP
};
-enum rdma_transport_type
-rdma_node_get_transport(enum rdma_node_type node_type) __attribute_const__;
-
enum ib_device_cap_flags {
IB_DEVICE_RESIZE_MAX_WR = 1,
IB_DEVICE_BAD_PKEY_CNTR = (1<<1),
@@ -298,6 +295,7 @@ struct ib_port_attr {
u8 active_width;
u8 active_speed;
u8 phys_state;
+ enum rdma_transport_type transport;
};
enum ib_device_modify_flags {
@@ -1003,6 +1001,8 @@ struct ib_device {
int (*query_port)(struct ib_device *device,
u8 port_num,
struct ib_port_attr *port_attr);
+ enum rdma_transport_type (*get_port_transport)(struct ib_device *device,
+ u8 port_num);
int (*query_gid)(struct ib_device *device,
u8 port_num, int index,
union ib_gid *gid);
@@ -1213,6 +1213,11 @@ int ib_query_device(struct ib_device *device,
int ib_query_port(struct ib_device *device,
u8 port_num, struct ib_port_attr *port_attr);
+enum rdma_transport_type rdma_port_get_transport(struct ib_device *device,
+ u8 port_num);
+int rdma_is_transport_supported(struct ib_device *device,
+ enum rdma_transport_type transport);
+
int ib_query_gid(struct ib_device *device,
u8 port_num, int index, union ib_gid *gid);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 9e88438..1131c74 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -338,8 +338,7 @@ static int rdma_set_ctxt_sge(struct svcxprt_rdma *xprt,
static int rdma_read_max_sge(struct svcxprt_rdma *xprt, int sge_count)
{
if ((RDMA_TRANSPORT_IWARP ==
- rdma_node_get_transport(xprt->sc_cm_id->
- device->node_type))
+ rdma_port_get_transport(xprt->sc_cm_id->device, xprt->sc_cm_id->port_num))
&& sge_count > 1)
return 1;
else
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c
index 3fa5751..4e286f7 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_transport.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c
@@ -977,7 +977,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
/*
* Determine if a DMA MR is required and if so, what privs are required
*/
- switch (rdma_node_get_transport(newxprt->sc_cm_id->device->node_type)) {
+ switch (rdma_port_get_transport(newxprt->sc_cm_id->device, newxprt->sc_cm_id->port_num)) {
case RDMA_TRANSPORT_IWARP:
newxprt->sc_dev_caps |= SVCRDMA_DEVCAP_READ_W_INV;
if (!(newxprt->sc_dev_caps & SVCRDMA_DEVCAP_FAST_REG)) {
--
1.6.5.2
^ 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