* Re: [PATCH net 0/5] net/ncsi: More bug fixes
From: Gavin Shan @ 2016-10-20 0:54 UTC (permalink / raw)
To: Gavin Shan; +Cc: netdev, davem, joel
In-Reply-To: <1476413614-24586-1-git-send-email-gwshan@linux.vnet.ibm.com>
On Fri, Oct 14, 2016 at 01:53:29PM +1100, Gavin Shan wrote:
>This series fixes 2 issues that were found during NCSI's availability
>testing on BCM5718 and improves HNCDSC AEN handler:
>
> * PATCH[1] and PATCH[2] refactors the code so that minimal code
> change is put to PATCH[3].
> * PATCH[3] fixes the NCSI channel's stale link state before doing
> failover.
> * PATCH[4] chooses the hot channel, which was ever chosen as active
> channel, when the available channels are all in link-down state.
> * PATCH[5] improves Host Network Controller Driver Status Change
> (HNCDSC) AEN handler
>
v2 addressing comments received from Joel has been posted. Joel, thanks
a lot for your time and comments :)
Thanks,
Gavin
>Gavin Shan (5):
> net/ncsi: Not fetch active package and channel again
> net/ncsi: Split out logic for ncsi_dev_state_suspend_select
> net/ncsi: Fix stale link state of inactive channels on failover
> net/ncsi: Choose hot channel as active one if necessary
> net/ncsi: Improve HNCDSC AEN handler
>
> net/ncsi/internal.h | 2 ++
> net/ncsi/ncsi-aen.c | 18 ++++++++++--
> net/ncsi/ncsi-manage.c | 80 ++++++++++++++++++++++++++++++++++++++------------
> 3 files changed, 79 insertions(+), 21 deletions(-)
>
>--
>2.1.0
>
^ permalink raw reply
* [PATCH v2 net 1/4] net/ncsi: Avoid if statements in ncsi_suspend_channel()
From: Gavin Shan @ 2016-10-20 0:45 UTC (permalink / raw)
To: netdev; +Cc: davem, joel, Gavin Shan
In-Reply-To: <1476924352-31165-1-git-send-email-gwshan@linux.vnet.ibm.com>
There are several if/else statements in the state machine implemented
by switch/case in ncsi_suspend_channel() to avoid duplicated code. It
makes the code a bit hard to be understood.
This drops if/else statements in ncsi_suspend_channel() to improve the
code readability as Joel Stanley suggested. Also, it becomes easy to
add more states in the state machine without affecting current code.
No logical changes introduced by this.
Suggested-by: Joel Stanley <joel@jms.id.au>
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
net/ncsi/ncsi-manage.c | 78 ++++++++++++++++++++++++++++++++------------------
1 file changed, 50 insertions(+), 28 deletions(-)
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 5e509e5..655d0d6 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -540,42 +540,60 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
nd->state = ncsi_dev_state_suspend_select;
/* Fall through */
case ncsi_dev_state_suspend_select:
+ ndp->pending_req_num = 1;
+
+ nca.type = NCSI_PKT_CMD_SP;
+ nca.package = np->id;
+ nca.channel = NCSI_RESERVED_CHANNEL;
+ if (ndp->flags & NCSI_DEV_HWA)
+ nca.bytes[0] = 0;
+ else
+ nca.bytes[0] = 1;
+
+ nd->state = ncsi_dev_state_suspend_dcnt;
+ ret = ncsi_xmit_cmd(&nca);
+ if (ret)
+ goto error;
+
+ break;
case ncsi_dev_state_suspend_dcnt:
+ ndp->pending_req_num = 1;
+
+ nca.type = NCSI_PKT_CMD_DCNT;
+ nca.package = np->id;
+ nca.channel = nc->id;
+
+ nd->state = ncsi_dev_state_suspend_dc;
+ ret = ncsi_xmit_cmd(&nca);
+ if (ret)
+ goto error;
+
+ break;
case ncsi_dev_state_suspend_dc:
+ ndp->pending_req_num = 1;
+
+ nca.type = NCSI_PKT_CMD_DC;
+ nca.package = np->id;
+ nca.channel = nc->id;
+ nca.bytes[0] = 1;
+
+ nd->state = ncsi_dev_state_suspend_deselect;
+ ret = ncsi_xmit_cmd(&nca);
+ if (ret)
+ goto error;
+
+ break;
case ncsi_dev_state_suspend_deselect:
ndp->pending_req_num = 1;
- np = ndp->active_package;
- nc = ndp->active_channel;
+ nca.type = NCSI_PKT_CMD_DP;
nca.package = np->id;
- if (nd->state == ncsi_dev_state_suspend_select) {
- nca.type = NCSI_PKT_CMD_SP;
- nca.channel = NCSI_RESERVED_CHANNEL;
- if (ndp->flags & NCSI_DEV_HWA)
- nca.bytes[0] = 0;
- else
- nca.bytes[0] = 1;
- nd->state = ncsi_dev_state_suspend_dcnt;
- } else if (nd->state == ncsi_dev_state_suspend_dcnt) {
- nca.type = NCSI_PKT_CMD_DCNT;
- nca.channel = nc->id;
- nd->state = ncsi_dev_state_suspend_dc;
- } else if (nd->state == ncsi_dev_state_suspend_dc) {
- nca.type = NCSI_PKT_CMD_DC;
- nca.channel = nc->id;
- nca.bytes[0] = 1;
- nd->state = ncsi_dev_state_suspend_deselect;
- } else if (nd->state == ncsi_dev_state_suspend_deselect) {
- nca.type = NCSI_PKT_CMD_DP;
- nca.channel = NCSI_RESERVED_CHANNEL;
- nd->state = ncsi_dev_state_suspend_done;
- }
+ nca.channel = NCSI_RESERVED_CHANNEL;
+ nd->state = ncsi_dev_state_suspend_done;
ret = ncsi_xmit_cmd(&nca);
- if (ret) {
- nd->state = ncsi_dev_state_functional;
- return;
- }
+ if (ret)
+ goto error;
break;
case ncsi_dev_state_suspend_done:
@@ -589,6 +607,10 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
netdev_warn(nd->dev, "Wrong NCSI state 0x%x in suspend\n",
nd->state);
}
+
+ return;
+error:
+ nd->state = ncsi_dev_state_functional;
}
static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
--
2.1.0
^ permalink raw reply related
* [PATCH v2 net 3/4] net/ncsi: Choose hot channel as active one if necessary
From: Gavin Shan @ 2016-10-20 0:45 UTC (permalink / raw)
To: netdev; +Cc: davem, joel, Gavin Shan
In-Reply-To: <1476924352-31165-1-git-send-email-gwshan@linux.vnet.ibm.com>
The issue was found on BCM5718 which has two NCSI channels in one
package: C0 and C1. C0 is in link-up state while C1 is in link-down
state. C0 is chosen as active channel until unplugging and plugging
C0's cable: On unplugging C0's cable, LSC (Link State Change) AEN
packet received on C0 to report link-down event. After that, C1 is
chosen as active channel. LSC AEN for link-up event is lost on C0
when plugging C0's cable back. We lose the network even C0 is usable.
This resolves the issue by recording the (hot) channel that was ever
chosen as active one. The hot channel is chosen to be active one
if none of available channels in link-up state. With this, C0 is still
the active one after unplugging C0's cable. LSC AEN packet received
on C0 when plugging its cable back.
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
net/ncsi/internal.h | 1 +
net/ncsi/ncsi-manage.c | 22 +++++++++++++++++++---
2 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index eac4858..1308a56 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -265,6 +265,7 @@ struct ncsi_dev_priv {
#endif
unsigned int package_num; /* Number of packages */
struct list_head packages; /* List of packages */
+ struct ncsi_channel *hot_channel; /* Channel was ever active */
struct ncsi_request requests[256]; /* Request table */
unsigned int request_id; /* Last used request ID */
#define NCSI_REQ_START_IDX 1
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 4789f86..a3bd5fa 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -645,6 +645,7 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
struct net_device *dev = nd->dev;
struct ncsi_package *np = ndp->active_package;
struct ncsi_channel *nc = ndp->active_channel;
+ struct ncsi_channel *hot_nc = NULL;
struct ncsi_cmd_arg nca;
unsigned char index;
unsigned long flags;
@@ -750,12 +751,20 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
break;
case ncsi_dev_state_config_done:
spin_lock_irqsave(&nc->lock, flags);
- if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1)
+ if (nc->modes[NCSI_MODE_LINK].data[2] & 0x1) {
+ hot_nc = nc;
nc->state = NCSI_CHANNEL_ACTIVE;
- else
+ } else {
+ hot_nc = NULL;
nc->state = NCSI_CHANNEL_INACTIVE;
+ }
spin_unlock_irqrestore(&nc->lock, flags);
+ /* Update the hot channel */
+ spin_lock_irqsave(&ndp->lock, flags);
+ ndp->hot_channel = hot_nc;
+ spin_unlock_irqrestore(&ndp->lock, flags);
+
ncsi_start_channel_monitor(nc);
ncsi_process_next_channel(ndp);
break;
@@ -773,10 +782,14 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp)
static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
{
struct ncsi_package *np;
- struct ncsi_channel *nc, *found;
+ struct ncsi_channel *nc, *found, *hot_nc;
struct ncsi_channel_mode *ncm;
unsigned long flags;
+ spin_lock_irqsave(&ndp->lock, flags);
+ hot_nc = ndp->hot_channel;
+ spin_unlock_irqrestore(&ndp->lock, flags);
+
/* The search is done once an inactive channel with up
* link is found.
*/
@@ -794,6 +807,9 @@ static int ncsi_choose_active_channel(struct ncsi_dev_priv *ndp)
if (!found)
found = nc;
+ if (nc == hot_nc)
+ found = nc;
+
ncm = &nc->modes[NCSI_MODE_LINK];
if (ncm->data[2] & 0x1) {
spin_unlock_irqrestore(&nc->lock, flags);
--
2.1.0
^ permalink raw reply related
* [PATCH v2 net 2/4] net/ncsi: Fix stale link state of inactive channels on failover
From: Gavin Shan @ 2016-10-20 0:45 UTC (permalink / raw)
To: netdev; +Cc: davem, joel, Gavin Shan
In-Reply-To: <1476924352-31165-1-git-send-email-gwshan@linux.vnet.ibm.com>
The issue was found on BCM5718 which has two NCSI channels in one
package: C0 and C1. Both of them are connected to different LANs,
means they are in link-up state and C0 is chosen as the active one
until resetting BCM5718 happens as below.
Resetting BCM5718 results in LSC (Link State Change) AEN packet
received on C0, meaning LSC AEN is missed on C1. When LSC AEN packet
received on C0 to report link-down, it fails over to C1 because C1
is in link-up state as software can see. However, C1 is in link-down
state in hardware. It means the link state is out of synchronization
between hardware and software, resulting in inappropriate channel (C1)
selected as active one.
This resolves the issue by sending separate GLS (Get Link Status)
commands to all channels in the package before trying to do failover.
The last link states of all channels in the package are retrieved.
With it, C0 (not C1) is selected as active one as expected.
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
net/ncsi/internal.h | 1 +
net/ncsi/ncsi-manage.c | 28 +++++++++++++++++++++++++++-
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/net/ncsi/internal.h b/net/ncsi/internal.h
index 13290a7..eac4858 100644
--- a/net/ncsi/internal.h
+++ b/net/ncsi/internal.h
@@ -246,6 +246,7 @@ enum {
ncsi_dev_state_config_gls,
ncsi_dev_state_config_done,
ncsi_dev_state_suspend_select = 0x0401,
+ ncsi_dev_state_suspend_gls,
ncsi_dev_state_suspend_dcnt,
ncsi_dev_state_suspend_dc,
ncsi_dev_state_suspend_deselect,
diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
index 655d0d6..4789f86 100644
--- a/net/ncsi/ncsi-manage.c
+++ b/net/ncsi/ncsi-manage.c
@@ -550,12 +550,38 @@ static void ncsi_suspend_channel(struct ncsi_dev_priv *ndp)
else
nca.bytes[0] = 1;
- nd->state = ncsi_dev_state_suspend_dcnt;
+ /* To retrieve the last link states of channels in current
+ * package when current active channel needs fail over to
+ * another one. It means we will possibly select another
+ * channel as next active one. The link states of channels
+ * are most important factor of the selection. So we need
+ * accurate link states. Unfortunately, the link states on
+ * inactive channels can't be updated with LSC AEN in time.
+ */
+ if (ndp->flags & NCSI_DEV_RESHUFFLE)
+ nd->state = ncsi_dev_state_suspend_gls;
+ else
+ nd->state = ncsi_dev_state_suspend_dcnt;
ret = ncsi_xmit_cmd(&nca);
if (ret)
goto error;
break;
+ case ncsi_dev_state_suspend_gls:
+ ndp->pending_req_num = np->channel_num;
+
+ nca.type = NCSI_PKT_CMD_GLS;
+ nca.package = np->id;
+
+ nd->state = ncsi_dev_state_suspend_dcnt;
+ NCSI_FOR_EACH_CHANNEL(np, nc) {
+ nca.channel = nc->id;
+ ret = ncsi_xmit_cmd(&nca);
+ if (ret)
+ goto error;
+ }
+
+ break;
case ncsi_dev_state_suspend_dcnt:
ndp->pending_req_num = 1;
--
2.1.0
^ permalink raw reply related
* [PATCH v2 net 4/4] net/ncsi: Improve HNCDSC AEN handler
From: Gavin Shan @ 2016-10-20 0:45 UTC (permalink / raw)
To: netdev; +Cc: davem, joel, Gavin Shan
In-Reply-To: <1476924352-31165-1-git-send-email-gwshan@linux.vnet.ibm.com>
This improves AEN handler for Host Network Controller Driver Status
Change (HNCDSC):
* The channel's lock should be hold when accessing its state.
* Do failover when host driver isn't ready.
* Configure channel when host driver becomes ready.
Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com>
---
net/ncsi/ncsi-aen.c | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/net/ncsi/ncsi-aen.c b/net/ncsi/ncsi-aen.c
index b41a661..6898e72 100644
--- a/net/ncsi/ncsi-aen.c
+++ b/net/ncsi/ncsi-aen.c
@@ -141,23 +141,35 @@ static int ncsi_aen_handler_hncdsc(struct ncsi_dev_priv *ndp,
return -ENODEV;
/* If the channel is active one, we need reconfigure it */
+ spin_lock_irqsave(&nc->lock, flags);
ncm = &nc->modes[NCSI_MODE_LINK];
hncdsc = (struct ncsi_aen_hncdsc_pkt *)h;
ncm->data[3] = ntohl(hncdsc->status);
if (!list_empty(&nc->link) ||
- nc->state != NCSI_CHANNEL_ACTIVE ||
- (ncm->data[3] & 0x1))
+ nc->state != NCSI_CHANNEL_ACTIVE) {
+ spin_unlock_irqrestore(&nc->lock, flags);
return 0;
+ }
- if (ndp->flags & NCSI_DEV_HWA)
+ spin_unlock_irqrestore(&nc->lock, flags);
+ if (!(ndp->flags & NCSI_DEV_HWA) && !(ncm->data[3] & 0x1))
ndp->flags |= NCSI_DEV_RESHUFFLE;
/* If this channel is the active one and the link doesn't
* work, we have to choose another channel to be active one.
* The logic here is exactly similar to what we do when link
* is down on the active channel.
+ *
+ * On the other hand, we need configure it when host driver
+ * state on the active channel becomes ready.
*/
ncsi_stop_channel_monitor(nc);
+
+ spin_lock_irqsave(&nc->lock, flags);
+ nc->state = (ncm->data[3] & 0x1) ? NCSI_CHANNEL_INACTIVE :
+ NCSI_CHANNEL_ACTIVE;
+ spin_unlock_irqrestore(&nc->lock, flags);
+
spin_lock_irqsave(&ndp->lock, flags);
list_add_tail_rcu(&nc->link, &ndp->channel_queue);
spin_unlock_irqrestore(&ndp->lock, flags);
--
2.1.0
^ permalink raw reply related
* [PATCH v2 net 0/4] net/ncsi: More bug fixes
From: Gavin Shan @ 2016-10-20 0:45 UTC (permalink / raw)
To: netdev; +Cc: davem, joel, Gavin Shan
This series fixes 2 issues that were found during NCSI's availability
testing on BCM5718 and improves HNCDSC AEN handler:
* PATCH[1] refactors the code so that minimal code change is put
to PATCH[2].
* PATCH[2] fixes the NCSI channel's stale link state before doing
failover.
* PATCH[3] chooses the hot channel, which was ever chosen as active
channel, when the available channels are all in link-down state.
* PATCH[4] improves Host Network Controller Driver Status Change
(HNCDSC) AEN handler
Changelog
=========
v2:
* Merged PATCH[v1 1/2] to PATCH[v2 1].
* Avoid if/else statements in ncsi_suspend_channel() as Joel suggested.
* Added comments to explain why we need retrieve last link states in
ncsi_suspend_channel().
Gavin Shan (4):
net/ncsi: Avoid if statements in ncsi_suspend_channel()
net/ncsi: Fix stale link state of inactive channels on failover
net/ncsi: Choose hot channel as active one if necessary
net/ncsi: Improve HNCDSC AEN handler
net/ncsi/internal.h | 2 +
net/ncsi/ncsi-aen.c | 18 +++++--
net/ncsi/ncsi-manage.c | 126 +++++++++++++++++++++++++++++++++++++------------
3 files changed, 112 insertions(+), 34 deletions(-)
--
2.1.0
^ permalink raw reply
* Re: [RFC 2/6] qed: Add iSCSI out of order packet handling.
From: Arun Easi @ 2016-10-20 0:43 UTC (permalink / raw)
To: Johannes Thumshirn
Cc: manish.rangankar, lduncan, cleech, martin.petersen, jejb,
linux-scsi, netdev, Yuval.Mintz, QLogic-Storage-Upstream,
Yuval Mintz
In-Reply-To: <20161019093923.y635a66joxvqgz5u@linux-x5ow.site>
On Wed, 19 Oct 2016, 2:39am, Johannes Thumshirn wrote:
> On Wed, Oct 19, 2016 at 01:01:09AM -0400, manish.rangankar@cavium.com wrote:
> > From: Yuval Mintz <Yuval.Mintz@qlogic.com>
> >
> > This patch adds out of order packet handling for hardware offloaded
> > iSCSI. Out of order packet handling requires driver buffer allocation
> > and assistance.
> >
> > Signed-off-by: Arun Easi <arun.easi@cavium.com>
> > Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
> > ---
>
> [...]
>
> > + if (IS_ENABLED(CONFIG_QEDI) &&
> > + p_ll2_conn->conn_type == QED_LL2_TYPE_ISCSI_OOO) {
>
> If you're going to implement the qed_is_iscsi_personallity() helper, please
> consider a qed_ll2_is_iscsi_oooo() as well.
I see that I can avoid the IS_ENABLED() here as well. I will fix this
in the next revision.
>
> > + struct qed_ooo_buffer *p_buffer;
>
> [...]
>
> > + while (cq_new_idx != cq_old_idx) {
> > + struct core_rx_fast_path_cqe *p_cqe_fp;
> > +
> > + cqe = qed_chain_consume(&p_rx->rcq_chain);
> > + cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);
> > + cqe_type = cqe->rx_cqe_sp.type;
> > +
> > + if (cqe_type != CORE_RX_CQE_TYPE_REGULAR) {
> > + DP_NOTICE(p_hwfn,
> > + "Got a non-regular LB LL2 completion [type 0x%02x]\n",
> > + cqe_type);
> > + return -EINVAL;
> > + }
> > + p_cqe_fp = &cqe->rx_cqe_fp;
> > +
> > + placement_offset = p_cqe_fp->placement_offset;
> > + parse_flags = le16_to_cpu(p_cqe_fp->parse_flags.flags);
> > + packet_length = le16_to_cpu(p_cqe_fp->packet_length);
> > + vlan = le16_to_cpu(p_cqe_fp->vlan);
> > + iscsi_ooo = (struct ooo_opaque *)&p_cqe_fp->opaque_data;
> > + qed_ooo_save_history_entry(p_hwfn, p_hwfn->p_ooo_info,
> > + iscsi_ooo);
> > + cid = le32_to_cpu(iscsi_ooo->cid);
> > +
> > + /* Process delete isle first */
> > + if (iscsi_ooo->drop_size)
> > + qed_ooo_delete_isles(p_hwfn, p_hwfn->p_ooo_info, cid,
> > + iscsi_ooo->drop_isle,
> > + iscsi_ooo->drop_size);
> > +
> > + if (iscsi_ooo->ooo_opcode == TCP_EVENT_NOP)
> > + continue;
> > +
> > + /* Now process create/add/join isles */
> > + if (list_empty(&p_rx->active_descq)) {
> > + DP_NOTICE(p_hwfn,
> > + "LL2 OOO RX chain has no submitted buffers\n");
> > + return -EIO;
> > + }
> > +
> > + p_pkt = list_first_entry(&p_rx->active_descq,
> > + struct qed_ll2_rx_packet, list_entry);
> > +
> > + if ((iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_NEW_ISLE) ||
> > + (iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_ISLE_RIGHT) ||
> > + (iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_ISLE_LEFT) ||
> > + (iscsi_ooo->ooo_opcode == TCP_EVENT_ADD_PEN) ||
> > + (iscsi_ooo->ooo_opcode == TCP_EVENT_JOIN)) {
> > + if (!p_pkt) {
> > + DP_NOTICE(p_hwfn,
> > + "LL2 OOO RX packet is not valid\n");
> > + return -EIO;
> > + }
> > + list_del(&p_pkt->list_entry);
> > + p_buffer = (struct qed_ooo_buffer *)p_pkt->cookie;
> > + p_buffer->packet_length = packet_length;
> > + p_buffer->parse_flags = parse_flags;
> > + p_buffer->vlan = vlan;
> > + p_buffer->placement_offset = placement_offset;
> > + qed_chain_consume(&p_rx->rxq_chain);
> > + list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);
> > +
> > + switch (iscsi_ooo->ooo_opcode) {
> > + case TCP_EVENT_ADD_NEW_ISLE:
> > + qed_ooo_add_new_isle(p_hwfn,
> > + p_hwfn->p_ooo_info,
> > + cid,
> > + iscsi_ooo->ooo_isle,
> > + p_buffer);
> > + break;
> > + case TCP_EVENT_ADD_ISLE_RIGHT:
> > + qed_ooo_add_new_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info,
> > + cid,
> > + iscsi_ooo->ooo_isle,
> > + p_buffer,
> > + QED_OOO_RIGHT_BUF);
> > + break;
> > + case TCP_EVENT_ADD_ISLE_LEFT:
> > + qed_ooo_add_new_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info,
> > + cid,
> > + iscsi_ooo->ooo_isle,
> > + p_buffer,
> > + QED_OOO_LEFT_BUF);
> > + break;
> > + case TCP_EVENT_JOIN:
> > + qed_ooo_add_new_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info,
> > + cid,
> > + iscsi_ooo->ooo_isle +
> > + 1,
> > + p_buffer,
> > + QED_OOO_LEFT_BUF);
> > + qed_ooo_join_isles(p_hwfn,
> > + p_hwfn->p_ooo_info,
> > + cid, iscsi_ooo->ooo_isle);
> > + break;
> > + case TCP_EVENT_ADD_PEN:
> > + num_ooo_add_to_peninsula++;
> > + qed_ooo_put_ready_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info,
> > + p_buffer, true);
> > + break;
> > + }
> > + } else {
> > + DP_NOTICE(p_hwfn,
> > + "Unexpected event (%d) TX OOO completion\n",
> > + iscsi_ooo->ooo_opcode);
> > + }
> > + }
>
> Can you factoror the body of that "while(cq_new_idx != cq_old_idx)" loop into
> a own function?
Ok, will do.
>
> >
> > - b_last = list_empty(&p_rx->active_descq);
> > + /* Submit RX buffer here */
> > + while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info))) {
>
> This could be an opportunity for a qed_for_each_free_buffer() or maybe even a
> qed_ooo_submit_rx_buffers() and qed_ooo_submit_tx_buffers() as this is mostly
> duplicate code.
Sure, will do. Thank you.
Regards,
-Arun
>
> > + rc = qed_ll2_post_rx_buffer(p_hwfn, p_ll2_conn->my_id,
> > + p_buffer->rx_buffer_phys_addr,
> > + 0, p_buffer, true);
> > + if (rc) {
> > + qed_ooo_put_free_buffer(p_hwfn, p_hwfn->p_ooo_info,
> > + p_buffer);
> > + break;
> > + }
> > }
> > +
> > + /* Submit Tx buffers here */
> > + while ((p_buffer = qed_ooo_get_ready_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info))) {
>
> Ditto.
>
> [...]
> > +
> > + /* Submit Tx buffers here */
> > + while ((p_buffer = qed_ooo_get_ready_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info))) {
>
>
> And here
>
> [...]
>
> > + while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info))) {
>
> [..]
>
> > + while ((p_buffer = qed_ooo_get_free_buffer(p_hwfn,
> > + p_hwfn->p_ooo_info))) {
>
> [...]
>
>
^ permalink raw reply
* Re: [RFC 1/6] qed: Add support for hardware offloaded iSCSI.
From: Arun Easi @ 2016-10-20 0:14 UTC (permalink / raw)
To: Johannes Thumshirn
Cc: manish.rangankar, lduncan, cleech, martin.petersen, jejb,
linux-scsi, netdev, Yuval.Mintz, QLogic-Storage-Upstream,
Yuval Mintz
In-Reply-To: <20161019090923.up3xgrbya3mxr7vu@linux-x5ow.site>
Thanks Johannes for the review, please see my response below.
On Wed, 19 Oct 2016, 2:09am, Johannes Thumshirn wrote:
> Hi Manish,
>
> Some initital comments
>
> On Wed, Oct 19, 2016 at 01:01:08AM -0400, manish.rangankar@cavium.com wrote:
> > From: Yuval Mintz <Yuval.Mintz@qlogic.com>
> >
> > This adds the backbone required for the various HW initalizations
> > which are necessary for the iSCSI driver (qedi) for QLogic FastLinQ
> > 4xxxx line of adapters - FW notification, resource initializations, etc.
> >
> > Signed-off-by: Arun Easi <arun.easi@cavium.com>
> > Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
> > ---
> > drivers/net/ethernet/qlogic/Kconfig | 15 +
> > drivers/net/ethernet/qlogic/qed/Makefile | 1 +
> > drivers/net/ethernet/qlogic/qed/qed.h | 8 +-
> > drivers/net/ethernet/qlogic/qed/qed_dev.c | 15 +
> > drivers/net/ethernet/qlogic/qed/qed_int.h | 1 -
> > drivers/net/ethernet/qlogic/qed/qed_iscsi.c | 1310 ++++++++++++++++++++++++
> > drivers/net/ethernet/qlogic/qed/qed_iscsi.h | 52 +
> > drivers/net/ethernet/qlogic/qed/qed_l2.c | 1 -
> > drivers/net/ethernet/qlogic/qed/qed_ll2.c | 35 +-
> > drivers/net/ethernet/qlogic/qed/qed_main.c | 2 -
> > drivers/net/ethernet/qlogic/qed/qed_mcp.h | 6 -
> > drivers/net/ethernet/qlogic/qed/qed_reg_addr.h | 2 +
> > drivers/net/ethernet/qlogic/qed/qed_spq.c | 15 +
> > include/linux/qed/qed_if.h | 2 +
> > include/linux/qed/qed_iscsi_if.h | 249 +++++
> > 15 files changed, 1692 insertions(+), 22 deletions(-)
> > create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.c
> > create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.h
> > create mode 100644 include/linux/qed/qed_iscsi_if.h
> >
> > diff --git a/drivers/net/ethernet/qlogic/Kconfig b/drivers/net/ethernet/qlogic/Kconfig
> > index 0df1391f9..bad4fae 100644
> > --- a/drivers/net/ethernet/qlogic/Kconfig
> > +++ b/drivers/net/ethernet/qlogic/Kconfig
> > @@ -118,4 +118,19 @@ config INFINIBAND_QEDR
> > for QLogic QED. This would be replaced by the 'real' option
> > once the QEDR driver is added [+relocated].
> >
> > +config QED_ISCSI
> > + bool
> > +
> > +config QEDI
> > + tristate "QLogic QED 25/40/100Gb iSCSI driver"
> > + depends on QED
> > + select QED_LL2
> > + select QED_ISCSI
> > + default n
> > + ---help---
> > + This provides a temporary node that allows the compilation
> > + and logical testing of the hardware offload iSCSI support
> > + for QLogic QED. This would be replaced by the 'real' option
> > + once the QEDI driver is added [+relocated].
> > +
> > endif # NET_VENDOR_QLOGIC
> > diff --git a/drivers/net/ethernet/qlogic/qed/Makefile b/drivers/net/ethernet/qlogic/qed/Makefile
> > index cda0af7..b76669c 100644
> > --- a/drivers/net/ethernet/qlogic/qed/Makefile
> > +++ b/drivers/net/ethernet/qlogic/qed/Makefile
> > @@ -6,3 +6,4 @@ qed-y := qed_cxt.o qed_dev.o qed_hw.o qed_init_fw_funcs.o qed_init_ops.o \
> > qed-$(CONFIG_QED_SRIOV) += qed_sriov.o qed_vf.o
> > qed-$(CONFIG_QED_LL2) += qed_ll2.o
> > qed-$(CONFIG_INFINIBAND_QEDR) += qed_roce.o
> > +qed-$(CONFIG_QED_ISCSI) += qed_iscsi.o
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed.h b/drivers/net/ethernet/qlogic/qed/qed.h
> > index 653bb57..a61b1c0 100644
> > --- a/drivers/net/ethernet/qlogic/qed/qed.h
> > +++ b/drivers/net/ethernet/qlogic/qed/qed.h
> > @@ -35,6 +35,7 @@
> >
> > #define QED_WFQ_UNIT 100
> >
> > +#define ISCSI_BDQ_ID(_port_id) (_port_id)
>
> This looks a bit odd to me.
>
> [...]
>
> > #endif
> > + if (IS_ENABLED(CONFIG_QEDI) &&
> > + p_hwfn->hw_info.personality == QED_PCI_ISCSI)
> > + qed_iscsi_free(p_hwfn, p_hwfn->p_iscsi_info);
>
>
> Why not introduce a small helper like:
> static inline bool qed_is_iscsi_personality()
> {
> return IS_ENABLED(CONFIG_QEDI) && p_hwfn->hw_info.personality ==
> QED_PCI_ISCSI;
> }
I think I can remove the IS_ENABLED() check in places like this
and have the check contained in header file. qed_iscsi_free()
already is taken care, if I do the same fore qed_ooo*, I think
the check would just be "p_hwfn->hw_info.personality ==
QED_PCI_ISCSI", which would keep it consistent with the other
areas where similar check is done for other protocols.
>
> > qed_iov_free(p_hwfn);
>
> [...]
>
> > +
> > + if (!GET_FIELD(p_ramrod->iscsi.flags,
> > + ISCSI_CONN_OFFLOAD_PARAMS_TCP_ON_CHIP_1B)) {
> > + p_tcp = &p_ramrod->tcp;
> > + ucval = p_conn->local_mac[1];
> > + ((u8 *)(&p_tcp->local_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->local_mac[0];
> > + ((u8 *)(&p_tcp->local_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->local_mac[3];
> > + ((u8 *)(&p_tcp->local_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->local_mac[2];
> > + ((u8 *)(&p_tcp->local_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->local_mac[5];
> > + ((u8 *)(&p_tcp->local_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->local_mac[4];
> > + ((u8 *)(&p_tcp->local_mac_addr_lo))[1] = ucval;
> > + ucval = p_conn->remote_mac[1];
> > + ((u8 *)(&p_tcp->remote_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->remote_mac[0];
> > + ((u8 *)(&p_tcp->remote_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->remote_mac[3];
> > + ((u8 *)(&p_tcp->remote_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->remote_mac[2];
> > + ((u8 *)(&p_tcp->remote_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->remote_mac[5];
> > + ((u8 *)(&p_tcp->remote_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->remote_mac[4];
> > + ((u8 *)(&p_tcp->remote_mac_addr_lo))[1] = ucval;
> > +
> > + p_tcp->vlan_id = cpu_to_le16(p_conn->vlan_id);
> > +
> > + p_tcp->flags = p_conn->tcp_flags;
> > + p_tcp->ip_version = p_conn->ip_version;
> > + for (i = 0; i < 4; i++) {
> > + dval = p_conn->remote_ip[i];
> > + p_tcp->remote_ip[i] = cpu_to_le32(dval);
> > + dval = p_conn->local_ip[i];
> > + p_tcp->local_ip[i] = cpu_to_le32(dval);
> > + }
> > + p_tcp->ka_max_probe_cnt = p_conn->ka_max_probe_cnt;
> > + p_tcp->dup_ack_theshold = p_conn->dup_ack_theshold;
> > +
> > + p_tcp->rcv_next = cpu_to_le32(p_conn->rcv_next);
> > + p_tcp->snd_una = cpu_to_le32(p_conn->snd_una);
> > + p_tcp->snd_next = cpu_to_le32(p_conn->snd_next);
> > + p_tcp->snd_max = cpu_to_le32(p_conn->snd_max);
> > + p_tcp->snd_wnd = cpu_to_le32(p_conn->snd_wnd);
> > + p_tcp->rcv_wnd = cpu_to_le32(p_conn->rcv_wnd);
> > + p_tcp->snd_wl1 = cpu_to_le32(p_conn->snd_wl1);
> > + p_tcp->cwnd = cpu_to_le32(p_conn->cwnd);
> > + p_tcp->ss_thresh = cpu_to_le32(p_conn->ss_thresh);
> > + p_tcp->srtt = cpu_to_le16(p_conn->srtt);
> > + p_tcp->rtt_var = cpu_to_le16(p_conn->rtt_var);
> > + p_tcp->ts_time = cpu_to_le32(p_conn->ts_time);
> > + p_tcp->ts_recent = cpu_to_le32(p_conn->ts_recent);
> > + p_tcp->ts_recent_age = cpu_to_le32(p_conn->ts_recent_age);
> > + p_tcp->total_rt = cpu_to_le32(p_conn->total_rt);
> > + dval = p_conn->ka_timeout_delta;
> > + p_tcp->ka_timeout_delta = cpu_to_le32(dval);
> > + dval = p_conn->rt_timeout_delta;
> > + p_tcp->rt_timeout_delta = cpu_to_le32(dval);
> > + p_tcp->dup_ack_cnt = p_conn->dup_ack_cnt;
> > + p_tcp->snd_wnd_probe_cnt = p_conn->snd_wnd_probe_cnt;
> > + p_tcp->ka_probe_cnt = p_conn->ka_probe_cnt;
> > + p_tcp->rt_cnt = p_conn->rt_cnt;
> > + p_tcp->flow_label = cpu_to_le32(p_conn->flow_label);
> > + p_tcp->ka_timeout = cpu_to_le32(p_conn->ka_timeout);
> > + p_tcp->ka_interval = cpu_to_le32(p_conn->ka_interval);
> > + p_tcp->max_rt_time = cpu_to_le32(p_conn->max_rt_time);
> > + dval = p_conn->initial_rcv_wnd;
> > + p_tcp->initial_rcv_wnd = cpu_to_le32(dval);
> > + p_tcp->ttl = p_conn->ttl;
> > + p_tcp->tos_or_tc = p_conn->tos_or_tc;
> > + p_tcp->remote_port = cpu_to_le16(p_conn->remote_port);
> > + p_tcp->local_port = cpu_to_le16(p_conn->local_port);
> > + p_tcp->mss = cpu_to_le16(p_conn->mss);
> > + p_tcp->snd_wnd_scale = p_conn->snd_wnd_scale;
> > + p_tcp->rcv_wnd_scale = p_conn->rcv_wnd_scale;
> > + dval = p_conn->ts_ticks_per_second;
> > + p_tcp->ts_ticks_per_second = cpu_to_le32(dval);
> > + wval = p_conn->da_timeout_value;
> > + p_tcp->da_timeout_value = cpu_to_le16(wval);
> > + p_tcp->ack_frequency = p_conn->ack_frequency;
> > + p_tcp->connect_mode = p_conn->connect_mode;
> > + } else {
> > + p_tcp2 =
> > + &((struct iscsi_spe_conn_offload_option2 *)p_ramrod)->tcp;
> > + ucval = p_conn->local_mac[1];
> > + ((u8 *)(&p_tcp2->local_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->local_mac[0];
> > + ((u8 *)(&p_tcp2->local_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->local_mac[3];
> > + ((u8 *)(&p_tcp2->local_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->local_mac[2];
> > + ((u8 *)(&p_tcp2->local_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->local_mac[5];
> > + ((u8 *)(&p_tcp2->local_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->local_mac[4];
> > + ((u8 *)(&p_tcp2->local_mac_addr_lo))[1] = ucval;
> > +
> > + ucval = p_conn->remote_mac[1];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->remote_mac[0];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->remote_mac[3];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->remote_mac[2];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->remote_mac[5];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->remote_mac[4];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_lo))[1] = ucval;
> > +
> > + p_tcp2->vlan_id = cpu_to_le16(p_conn->vlan_id);
> > + p_tcp2->flags = p_conn->tcp_flags;
> > +
> > + p_tcp2->ip_version = p_conn->ip_version;
> > + for (i = 0; i < 4; i++) {
> > + dval = p_conn->remote_ip[i];
> > + p_tcp2->remote_ip[i] = cpu_to_le32(dval);
> > + dval = p_conn->local_ip[i];
> > + p_tcp2->local_ip[i] = cpu_to_le32(dval);
> > + }
> > +
> > + p_tcp2->flow_label = cpu_to_le32(p_conn->flow_label);
> > + p_tcp2->ttl = p_conn->ttl;
> > + p_tcp2->tos_or_tc = p_conn->tos_or_tc;
> > + p_tcp2->remote_port = cpu_to_le16(p_conn->remote_port);
> > + p_tcp2->local_port = cpu_to_le16(p_conn->local_port);
> > + p_tcp2->mss = cpu_to_le16(p_conn->mss);
> > + p_tcp2->rcv_wnd_scale = p_conn->rcv_wnd_scale;
> > + p_tcp2->connect_mode = p_conn->connect_mode;
> > + wval = p_conn->syn_ip_payload_length;
> > + p_tcp2->syn_ip_payload_length = cpu_to_le16(wval);
> > + p_tcp2->syn_phy_addr_lo = DMA_LO_LE(p_conn->syn_phy_addr);
> > + p_tcp2->syn_phy_addr_hi = DMA_HI_LE(p_conn->syn_phy_addr);
> > + }
>
> Is there any chance you could factor out above blocks into own functions so
> you have
>
>
> if (!GET_FIELD(p_ramrod->iscsi.flags,
> ISCSI_CONN_OFFLOAD_PARAMS_TCP_ON_CHIP_1B)) {
> qedi_do_stuff_off_chip();
> else
> qedi_do_stuff_on_chip();
>
This function mostly fills data needed for the firmware interface.
By having all data necessary for the command
ISCSI_RAMROD_CMD_ID_OFFLOAD_CONN in this function it is easier to
refer what is being fed to firmware. If you do not have strong
objections, I would like to keep it this way.
> > +
>
> [...]
>
> > +static void __iomem *qed_iscsi_get_db_addr(struct qed_hwfn *p_hwfn, u32 cid)
> > +{
> > + return (u8 __iomem *)p_hwfn->doorbells +
> > + qed_db_addr(cid, DQ_DEMS_LEGACY);
> > +}
> > +
> > +static void __iomem *qed_iscsi_get_primary_bdq_prod(struct qed_hwfn *p_hwfn,
> > + u8 bdq_id)
> > +{
> > + u8 bdq_function_id = ISCSI_BDQ_ID(p_hwfn->port_id);
> > +
> > + return (u8 __iomem *)p_hwfn->regview + GTT_BAR0_MAP_REG_MSDM_RAM +
> > + MSTORM_SCSI_BDQ_EXT_PROD_OFFSET(bdq_function_id,
> > + bdq_id);
> > +}
> > +
> > +static void __iomem *qed_iscsi_get_secondary_bdq_prod(struct qed_hwfn *p_hwfn,
> > + u8 bdq_id)
> > +{
> > + u8 bdq_function_id = ISCSI_BDQ_ID(p_hwfn->port_id);
> > +
> > + return (u8 __iomem *)p_hwfn->regview + GTT_BAR0_MAP_REG_TSDM_RAM +
> > + TSTORM_SCSI_BDQ_EXT_PROD_OFFSET(bdq_function_id,
> > + bdq_id);
> > +}
>
> Why are you casting to u8* here, you're returning void*?
>
The cast is for the "p_hwfn->regview".
> [...]
>
> > +
> > + if (tasks) {
> > + struct qed_tid_mem *tid_info = kzalloc(sizeof(*tid_info),
> > + GFP_KERNEL);
> > +
> > + if (!tid_info) {
> > + DP_NOTICE(cdev,
> > + "Failed to allocate tasks information\n");
> > + qed_iscsi_stop(cdev);
> > + return -ENOMEM;
> > + }
> > +
> > + rc = qed_cxt_get_tid_mem_info(QED_LEADING_HWFN(cdev),
> > + tid_info);
> > + if (rc) {
> > + DP_NOTICE(cdev, "Failed to gather task information\n");
> > + qed_iscsi_stop(cdev);
> > + kfree(tid_info);
> > + return rc;
> > + }
> > +
> > + /* Fill task information */
> > + tasks->size = tid_info->tid_size;
> > + tasks->num_tids_per_block = tid_info->num_tids_per_block;
> > + memcpy(tasks->blocks, tid_info->blocks, MAX_TID_BLOCKS);
> > +
> > + kfree(tid_info);
> > + }
> > +
> > + return 0;
> > +}
>
> Maybe:
>
> struct qed_tid_mem *tid_info;
> [...]
> if (!tasks)
> return 0;
>
> tid_info = kzalloc(sizeof(*tid_info), GFP_KERNEL);
>
> if (!tid_info) {
> DP_NOTICE(cdev, "Failed to allocate tasks information\n");
> qed_iscsi_stop(cdev);
> return -ENOMEM;
> }
>
> rc = qed_cxt_get_tid_mem_info(QED_LEADING_HWFN(cdev), tid_info);
> if (rc) {
> DP_NOTICE(cdev, "Failed to gather task information\n");
> qed_iscsi_stop(cdev);
> kfree(tid_info);
> return rc;
> }
>
> /* Fill task information */
> tasks->size = tid_info->tid_size;
> tasks->num_tids_per_block = tid_info->num_tids_per_block;
> memcpy(tasks->blocks, tid_info->blocks, MAX_TID_BLOCKS);
>
> kfree(tid_info);
>
Sure, will do.
> > +
>
> [...]
>
> > +/**
> > + * @brief start iscsi in FW
> > + *
> > + * @param cdev
> > + * @param tasks - qed will fill information about tasks
> > + *
>
> Please use proper kerneldoc and not doxygen syntax.
>
Sure, will do.
Regards,
-Arun
^ permalink raw reply
* linux-next: manual merge of the net-next tree with the net tree
From: Stephen Rothwell @ 2016-10-20 0:01 UTC (permalink / raw)
To: David Miller, Networking
Cc: linux-next, linux-kernel, Ido Schimmel, David Ahern
Hi all,
Today's linux-next merge of the net-next tree got conflicts in:
include/linux/netdevice.h
net/core/dev.c
between commit:
e4961b076885 ("net: core: Correctly iterate over lower adjacency list")
from the net tree and commit:
1a3f060c1a47 ("net: Introduce new api for walking upper and lower devices")
f1170fd462c6 ("net: Remove all_adj_list and its references")
from the net-next tree.
I fixed it up (I just used the net-next tree version) and can carry the
fix as necessary. This is now fixed as far as linux-next is concerned,
but any non trivial conflicts should be mentioned to your upstream
maintainer when your tree is submitted for merging. You may also want
to consider cooperating with the maintainer of the conflicting tree to
minimise any particularly complex conflicts.
--
Cheers,
Stephen Rothwell
^ permalink raw reply
* [PATCH 4/4] posix-timers: make it configurable
From: Nicolas Pitre @ 2016-10-19 23:42 UTC (permalink / raw)
To: John Stultz, Richard Cochran, Yann E MORIN
Cc: Thomas Gleixner, Josh Triplett, netdev, linux-kbuild,
linux-kernel
In-Reply-To: <1476920573-14384-1-git-send-email-nicolas.pitre@linaro.org>
Many embedded systems typically don't need them. This removes about
22KB from the kernel binary size when configured out.
Corresponding syscalls are routed to a stub logging the attempt to
use those syscalls which should be enough of a clue if they were
disabled without proper consideration. They are: timer_create,
timer_gettime: timer_getoverrun, timer_settime, timer_delete,
clock_adjtime.
The clock_settime, clock_gettime, clock_getres and clock_nanosleep syscalls
are replaced by simple wrappers compatible with CLOCK_REALTIME,
CLOCK_MONOTONIC and CLOCK_BOOTTIME only.
Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
drivers/ptp/Kconfig | 2 +-
include/linux/posix-timers.h | 28 +++++++++-
include/linux/sched.h | 10 ++++
init/Kconfig | 17 +++++++
kernel/signal.c | 4 ++
kernel/time/Makefile | 10 +++-
kernel/time/posix-stubs.c | 118 +++++++++++++++++++++++++++++++++++++++++++
7 files changed, 184 insertions(+), 5 deletions(-)
create mode 100644 kernel/time/posix-stubs.c
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index 0f7492f8ea..bdce332911 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -6,7 +6,7 @@ menu "PTP clock support"
config PTP_1588_CLOCK
tristate "PTP clock support"
- depends on NET
+ depends on NET && POSIX_TIMERS
select PPS
select NET_PTP_CLASSIFY
help
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 62d44c1760..2288c5c557 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -118,6 +118,8 @@ struct k_clock {
extern struct k_clock clock_posix_cpu;
extern struct k_clock clock_posix_dynamic;
+#ifdef CONFIG_POSIX_TIMERS
+
void posix_timers_register_clock(const clockid_t clock_id, struct k_clock *new_clock);
/* function to call to trigger timer event */
@@ -131,8 +133,30 @@ void posix_cpu_timers_exit_group(struct task_struct *task);
void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
cputime_t *newval, cputime_t *oldval);
-long clock_nanosleep_restart(struct restart_block *restart_block);
-
void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
+#else
+
+#include <linux/random.h>
+
+static inline void posix_timers_register_clock(const clockid_t clock_id,
+ struct k_clock *new_clock) {}
+static inline int posix_timer_event(struct k_itimer *timr, int si_private)
+{ return 0; }
+static inline void run_posix_cpu_timers(struct task_struct *task) {}
+static inline void posix_cpu_timers_exit(struct task_struct *task)
+{
+ add_device_randomness((const void*) &task->se.sum_exec_runtime,
+ sizeof(unsigned long long));
+}
+static inline void posix_cpu_timers_exit_group(struct task_struct *task) {}
+static inline void set_process_cpu_timer(struct task_struct *task,
+ unsigned int clock_idx, cputime_t *newval, cputime_t *oldval) {}
+static inline void update_rlimit_cpu(struct task_struct *task,
+ unsigned long rlim_new) {}
+
+#endif
+
+long clock_nanosleep_restart(struct restart_block *restart_block);
+
#endif
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 348f51b0ec..ad716d5559 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2946,8 +2946,13 @@ static inline void exit_thread(struct task_struct *tsk)
extern void exit_files(struct task_struct *);
extern void __cleanup_sighand(struct sighand_struct *);
+#ifdef CONFIG_POSIX_TIMERS
extern void exit_itimers(struct signal_struct *);
extern void flush_itimer_signals(void);
+#else
+static inline void exit_itimers(struct signal_struct *s) {}
+static inline void flush_itimer_signals(void) {}
+#endif
extern void do_group_exit(int);
@@ -3450,7 +3455,12 @@ static __always_inline bool need_resched(void)
* Thread group CPU time accounting.
*/
void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
+#ifdef CONFIG_POSIX_TIMERS
void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times);
+#else
+static inline void thread_group_cputimer(struct task_struct *tsk,
+ struct task_cputime *times) {}
+#endif
/*
* Reevaluate whether the task has signals pending delivery.
diff --git a/init/Kconfig b/init/Kconfig
index 34407f15e6..351d422252 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1445,6 +1445,23 @@ config SYSCTL_SYSCALL
If unsure say N here.
+config POSIX_TIMERS
+ bool "Posix Clocks & timers" if EXPERT
+ default y
+ help
+ This includes native support for POSIX timers to the kernel.
+ Most embedded systems may have no use for them and therefore they
+ can be configured out to reduce the size of the kernel image.
+
+ When this option is disabled, the following syscalls won't be
+ available: timer_create, timer_gettime: timer_getoverrun,
+ timer_settime, timer_delete, clock_adjtime. Furthermore, the
+ clock_settime, clock_gettime, clock_getres and clock_nanosleep
+ syscalls will be limited to CLOCK_REALTIME and CLOCK_MONOTONIC
+ only.
+
+ If unsure say y.
+
config KALLSYMS
bool "Load all symbols for debugging/ksymoops" if EXPERT
default y
diff --git a/kernel/signal.c b/kernel/signal.c
index 75761acc77..0a38c9d646 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -427,6 +427,7 @@ void flush_signals(struct task_struct *t)
spin_unlock_irqrestore(&t->sighand->siglock, flags);
}
+#ifdef CONFIG_POSIX_TIMERS
static void __flush_itimer_signals(struct sigpending *pending)
{
sigset_t signal, retain;
@@ -460,6 +461,7 @@ void flush_itimer_signals(void)
__flush_itimer_signals(&tsk->signal->shared_pending);
spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
}
+#endif
void ignore_signals(struct task_struct *t)
{
@@ -611,6 +613,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
*/
current->jobctl |= JOBCTL_STOP_DEQUEUED;
}
+#ifdef CONFIG_POSIX_TIMERS
if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
/*
* Release the siglock to ensure proper locking order
@@ -622,6 +625,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
do_schedule_next_timer(info);
spin_lock(&tsk->sighand->siglock);
}
+#endif
return signr;
}
diff --git a/kernel/time/Makefile b/kernel/time/Makefile
index 49eca0beed..fc26c308f5 100644
--- a/kernel/time/Makefile
+++ b/kernel/time/Makefile
@@ -1,6 +1,12 @@
-obj-y += time.o timer.o hrtimer.o itimer.o posix-timers.o posix-cpu-timers.o
+obj-y += time.o timer.o hrtimer.o itimer.o
obj-y += timekeeping.o ntp.o clocksource.o jiffies.o timer_list.o
-obj-y += timeconv.o timecounter.o posix-clock.o alarmtimer.o
+obj-y += timeconv.o timecounter.o alarmtimer.o
+
+ifeq ($(CONFIG_POSIX_TIMERS),y)
+ obj-y += posix-timers.o posix-cpu-timers.o posix-clock.o
+else
+ obj-y += posix-stubs.o
+endif
obj-$(CONFIG_GENERIC_CLOCKEVENTS) += clockevents.o tick-common.o
ifeq ($(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST),y)
diff --git a/kernel/time/posix-stubs.c b/kernel/time/posix-stubs.c
new file mode 100644
index 0000000000..fe857bd4a0
--- /dev/null
+++ b/kernel/time/posix-stubs.c
@@ -0,0 +1,118 @@
+/*
+ * Dummy stubs used when CONFIG_POSIX_TIMERS=n
+ *
+ * Created by: Nicolas Pitre, July 2016
+ * Copyright: (C) 2016 Linaro Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/linkage.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/syscalls.h>
+#include <linux/ktime.h>
+#include <linux/timekeeping.h>
+#include <linux/posix-timers.h>
+
+asmlinkage long sys_ni_posix_timers(void)
+{
+ pr_err_once("process %d (%s) attempted a POSIX timer syscall "
+ "while CONFIG_POSIX_TIMERS is not set\n",
+ current->pid, current->comm);
+ return -ENOSYS;
+}
+
+#define SYS_NI(name) SYSCALL_ALIAS(sys_##name, sys_ni_posix_timers)
+
+SYS_NI(timer_create);
+SYS_NI(timer_gettime);
+SYS_NI(timer_getoverrun);
+SYS_NI(timer_settime);
+SYS_NI(timer_delete);
+SYS_NI(clock_adjtime);
+
+/*
+ * We preserve minimal support for CLOCK_REALTIME and CLOCK_MONOTONIC
+ * as it is easy to remain compatible with little code. CLOCK_BOOTTIME
+ * is also included for convenience as at least systemd uses it.
+ */
+
+SYSCALL_DEFINE2(clock_settime, const clockid_t, which_clock,
+ const struct timespec __user *, tp)
+{
+ struct timespec new_tp;
+
+ if (which_clock != CLOCK_REALTIME)
+ return -EINVAL;
+ if (copy_from_user(&new_tp, tp, sizeof (*tp)))
+ return -EFAULT;
+ return do_sys_settimeofday(&new_tp, NULL);
+}
+
+SYSCALL_DEFINE2(clock_gettime, const clockid_t, which_clock,
+ struct timespec __user *,tp)
+{
+ struct timespec kernel_tp;
+
+ switch (which_clock) {
+ case CLOCK_REALTIME: ktime_get_real_ts(&kernel_tp); break;
+ case CLOCK_MONOTONIC: ktime_get_ts(&kernel_tp); break;
+ case CLOCK_BOOTTIME: get_monotonic_boottime(&kernel_tp); break;
+ default: return -EINVAL;
+ }
+ if (copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
+ return -EFAULT;
+ return 0;
+}
+
+SYSCALL_DEFINE2(clock_getres, const clockid_t, which_clock, struct timespec __user *, tp)
+{
+ struct timespec rtn_tp = {
+ .tv_sec = 0,
+ .tv_nsec = hrtimer_resolution,
+ };
+
+ switch (which_clock) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC:
+ case CLOCK_BOOTTIME:
+ if (copy_to_user(tp, &rtn_tp, sizeof(rtn_tp)))
+ return -EFAULT;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
+ const struct timespec __user *, rqtp,
+ struct timespec __user *, rmtp)
+{
+ struct timespec t;
+
+ switch (which_clock) {
+ case CLOCK_REALTIME:
+ case CLOCK_MONOTONIC:
+ case CLOCK_BOOTTIME:
+ if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
+ return -EFAULT;
+ if (!timespec_valid(&t))
+ return -EINVAL;
+ return hrtimer_nanosleep(&t, rmtp, flags & TIMER_ABSTIME ?
+ HRTIMER_MODE_ABS : HRTIMER_MODE_REL,
+ which_clock);
+ default:
+ return -EINVAL;
+ }
+}
+
+#ifdef CONFIG_COMPAT
+long clock_nanosleep_restart(struct restart_block *restart_block)
+{
+ return hrtimer_nanosleep_restart(restart_block);
+}
+#endif
--
2.7.4
^ permalink raw reply related
* [PATCH 3/4] ptp_clock: allow for it to be optional
From: Nicolas Pitre @ 2016-10-19 23:42 UTC (permalink / raw)
To: John Stultz, Richard Cochran, Yann E MORIN
Cc: Thomas Gleixner, Josh Triplett, netdev, linux-kbuild,
linux-kernel
In-Reply-To: <1476920573-14384-1-git-send-email-nicolas.pitre@linaro.org>
In order to break the hard dependency between the PTP clock subsystem and
ethernet drivers capable of being clock providers, this patch provides
simple PTP stub functions to allow linkage of those drivers into the
kernel even when the PTP subsystem is configured out. Drivers must be
ready to accept NULL from ptp_clock_register() in that case.
And to make it possible for PTP to be configured out, the select statement
in those driver's Kconfig menu entries is converted to the new "imply"
statement. This way the PTP subsystem may have Kconfig dependencies of
its own, such as POSIX_TIMERS, without having to make those ethernet
drivers unavailable if POSIX timers are cconfigured out. And when support
for POSIX timers is selected again then the default config option for PTP
clock support will automatically be adjusted accordingly.
The pch_gbe driver is a bit special as it relies on extra code in
drivers/ptp/ptp_pch.c. Therefore we let the make process descend into
drivers/ptp/ even if PTP_1588_CLOCK is unselected.
Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
drivers/Makefile | 2 +-
drivers/net/ethernet/adi/Kconfig | 2 +-
drivers/net/ethernet/amd/Kconfig | 2 +-
drivers/net/ethernet/amd/xgbe/xgbe-main.c | 6 ++-
drivers/net/ethernet/broadcom/Kconfig | 4 +-
drivers/net/ethernet/cavium/Kconfig | 2 +-
drivers/net/ethernet/freescale/Kconfig | 2 +-
drivers/net/ethernet/intel/Kconfig | 10 ++--
drivers/net/ethernet/mellanox/mlx4/Kconfig | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 2 +-
drivers/net/ethernet/renesas/Kconfig | 2 +-
drivers/net/ethernet/samsung/Kconfig | 2 +-
drivers/net/ethernet/sfc/Kconfig | 2 +-
drivers/net/ethernet/stmicro/stmmac/Kconfig | 2 +-
drivers/net/ethernet/ti/Kconfig | 2 +-
drivers/net/ethernet/tile/Kconfig | 2 +-
drivers/ptp/Kconfig | 8 +--
include/linux/ptp_clock_kernel.h | 65 ++++++++++++++++---------
18 files changed, 69 insertions(+), 50 deletions(-)
diff --git a/drivers/Makefile b/drivers/Makefile
index f0afdfb3c7..8cfa1ff8f6 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -107,7 +107,7 @@ obj-$(CONFIG_INPUT) += input/
obj-$(CONFIG_RTC_LIB) += rtc/
obj-y += i2c/ media/
obj-$(CONFIG_PPS) += pps/
-obj-$(CONFIG_PTP_1588_CLOCK) += ptp/
+obj-y += ptp/
obj-$(CONFIG_W1) += w1/
obj-y += power/
obj-$(CONFIG_HWMON) += hwmon/
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
index 6b94ba6103..98cc8f5350 100644
--- a/drivers/net/ethernet/adi/Kconfig
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -58,7 +58,7 @@ config BFIN_RX_DESC_NUM
config BFIN_MAC_USE_HWSTAMP
bool "Use IEEE 1588 hwstamp"
depends on BFIN_MAC && BF518
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
default y
---help---
To support the IEEE 1588 Precision Time Protocol (PTP), select y here
diff --git a/drivers/net/ethernet/amd/Kconfig b/drivers/net/ethernet/amd/Kconfig
index 0038709fd3..713ea7ad22 100644
--- a/drivers/net/ethernet/amd/Kconfig
+++ b/drivers/net/ethernet/amd/Kconfig
@@ -177,7 +177,7 @@ config AMD_XGBE
depends on ARM64 || COMPILE_TEST
select BITREVERSE
select CRC32
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports the AMD 10GbE Ethernet device found on an
AMD SoC.
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-main.c b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
index 9de078819a..e10e569c0d 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-main.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-main.c
@@ -773,7 +773,8 @@ static int xgbe_probe(struct platform_device *pdev)
goto err_wq;
}
- xgbe_ptp_register(pdata);
+ if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
+ xgbe_ptp_register(pdata);
xgbe_debugfs_init(pdata);
@@ -812,7 +813,8 @@ static int xgbe_remove(struct platform_device *pdev)
xgbe_debugfs_exit(pdata);
- xgbe_ptp_unregister(pdata);
+ if (IS_REACHABLE(CONFIG_PTP_1588_CLOCK))
+ xgbe_ptp_unregister(pdata);
flush_workqueue(pdata->an_workqueue);
destroy_workqueue(pdata->an_workqueue);
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index bd8c80c0b7..6a8d74aeb6 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -110,7 +110,7 @@ config TIGON3
depends on PCI
select PHYLIB
select HWMON
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Broadcom Tigon3 based gigabit Ethernet cards.
@@ -120,7 +120,7 @@ config TIGON3
config BNX2X
tristate "Broadcom NetXtremeII 10Gb support"
depends on PCI
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select FW_LOADER
select ZLIB_INFLATE
select LIBCRC32C
diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig
index 92f411c9f0..2e64a96661 100644
--- a/drivers/net/ethernet/cavium/Kconfig
+++ b/drivers/net/ethernet/cavium/Kconfig
@@ -53,7 +53,7 @@ config THUNDER_NIC_RGX
config LIQUIDIO
tristate "Cavium LiquidIO support"
depends on 64BIT
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select FW_LOADER
select LIBCRC32C
---help---
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index d1ca45fbb1..5eb9280973 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -25,7 +25,7 @@ config FEC
ARCH_MXC || SOC_IMX28)
default ARCH_MXC || SOC_IMX28 if ARM
select PHYLIB
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
Say Y here if you want to use the built-in 10/100 Fast ethernet
controller on some Motorola ColdFire and Freescale i.MX processors.
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index c0e17433f6..1349b45f01 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -58,7 +58,7 @@ config E1000E
tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
depends on PCI && (!SPARC32 || BROKEN)
select CRC32
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
ethernet family of adapters. For PCI or PCI-X e1000 adapters,
@@ -83,7 +83,7 @@ config E1000E_HWTS
config IGB
tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
depends on PCI
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select I2C
select I2C_ALGOBIT
---help---
@@ -156,7 +156,7 @@ config IXGBE
tristate "Intel(R) 10GbE PCI Express adapters support"
depends on PCI
select MDIO
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Intel(R) 10GbE PCI Express family of
adapters. For more information on how to identify your adapter, go
@@ -213,7 +213,7 @@ config IXGBEVF
config I40E
tristate "Intel(R) Ethernet Controller XL710 Family support"
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
depends on PCI
---help---
This driver supports Intel(R) Ethernet Controller XL710 Family of
@@ -264,7 +264,7 @@ config FM10K
tristate "Intel(R) FM10000 Ethernet Switch Host Interface Support"
default n
depends on PCI_MSI
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Intel(R) FM10000 Ethernet Switch Host
Interface. For more information on how to identify your adapter,
diff --git a/drivers/net/ethernet/mellanox/mlx4/Kconfig b/drivers/net/ethernet/mellanox/mlx4/Kconfig
index 5098e7f219..22b1cc012b 100644
--- a/drivers/net/ethernet/mellanox/mlx4/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx4/Kconfig
@@ -7,7 +7,7 @@ config MLX4_EN
depends on MAY_USE_DEVLINK
depends on PCI
select MLX4_CORE
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports Mellanox Technologies ConnectX Ethernet
devices.
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
index aae46884bf..2cd841590e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig
@@ -14,7 +14,7 @@ config MLX5_CORE
config MLX5_CORE_EN
bool "Mellanox Technologies ConnectX-4 Ethernet support"
depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
default n
---help---
Ethernet support in Mellanox Technologies ConnectX-4 NIC.
diff --git a/drivers/net/ethernet/renesas/Kconfig b/drivers/net/ethernet/renesas/Kconfig
index 85ec447c2d..27be51f0a4 100644
--- a/drivers/net/ethernet/renesas/Kconfig
+++ b/drivers/net/ethernet/renesas/Kconfig
@@ -37,7 +37,7 @@ config RAVB
select MII
select MDIO_BITBANG
select PHYLIB
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
help
Renesas Ethernet AVB device driver.
This driver supports the following SoCs:
diff --git a/drivers/net/ethernet/samsung/Kconfig b/drivers/net/ethernet/samsung/Kconfig
index 2360d81507..fbd5e06654 100644
--- a/drivers/net/ethernet/samsung/Kconfig
+++ b/drivers/net/ethernet/samsung/Kconfig
@@ -21,7 +21,7 @@ config SXGBE_ETH
depends on HAS_IOMEM && HAS_DMA
select PHYLIB
select CRC32
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This is the driver for the SXGBE 10G Ethernet IP block found on
Samsung platforms.
diff --git a/drivers/net/ethernet/sfc/Kconfig b/drivers/net/ethernet/sfc/Kconfig
index 4dd92b7b80..83f4766a1d 100644
--- a/drivers/net/ethernet/sfc/Kconfig
+++ b/drivers/net/ethernet/sfc/Kconfig
@@ -5,7 +5,7 @@ config SFC
select CRC32
select I2C
select I2C_ALGOBIT
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports 10/40-gigabit Ethernet cards based on
the Solarflare SFC4000, SFC9000-family and SFC9100-family
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 3818c5e06e..139c85fa6a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -4,7 +4,7 @@ config STMMAC_ETH
select MII
select PHYLIB
select CRC32
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
select RESET_CONTROLLER
---help---
This is the driver for the Ethernet IPs are built around a
diff --git a/drivers/net/ethernet/ti/Kconfig b/drivers/net/ethernet/ti/Kconfig
index 9904d740d5..61b835a7e6 100644
--- a/drivers/net/ethernet/ti/Kconfig
+++ b/drivers/net/ethernet/ti/Kconfig
@@ -76,7 +76,7 @@ config TI_CPSW
config TI_CPTS
bool "TI Common Platform Time Sync (CPTS) Support"
depends on TI_CPSW
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
---help---
This driver supports the Common Platform Time Sync unit of
the CPSW Ethernet Switch. The unit can time stamp PTP UDP/IPv4
diff --git a/drivers/net/ethernet/tile/Kconfig b/drivers/net/ethernet/tile/Kconfig
index f59a6c2653..bdfeaf3d4f 100644
--- a/drivers/net/ethernet/tile/Kconfig
+++ b/drivers/net/ethernet/tile/Kconfig
@@ -9,7 +9,7 @@ config TILE_NET
select CRC32
select TILE_GXIO_MPIPE if TILEGX
select HIGH_RES_TIMERS if TILEGX
- select PTP_1588_CLOCK if TILEGX
+ imply PTP_1588_CLOCK if TILEGX
---help---
This is a standard Linux network device driver for the
on-chip Tilera Gigabit Ethernet and XAUI interfaces.
diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig
index ee3de3421f..0f7492f8ea 100644
--- a/drivers/ptp/Kconfig
+++ b/drivers/ptp/Kconfig
@@ -28,7 +28,7 @@ config PTP_1588_CLOCK
config PTP_1588_CLOCK_GIANFAR
tristate "Freescale eTSEC as PTP clock"
depends on GIANFAR
- select PTP_1588_CLOCK
+ depends on PTP_1588_CLOCK
default y
help
This driver adds support for using the eTSEC as a PTP
@@ -42,7 +42,7 @@ config PTP_1588_CLOCK_GIANFAR
config PTP_1588_CLOCK_IXP46X
tristate "Intel IXP46x as PTP clock"
depends on IXP4XX_ETH
- select PTP_1588_CLOCK
+ depends on PTP_1588_CLOCK
default y
help
This driver adds support for using the IXP46X as a PTP
@@ -60,7 +60,7 @@ config DP83640_PHY
tristate "Driver for the National Semiconductor DP83640 PHYTER"
depends on NETWORK_PHY_TIMESTAMPING
depends on PHYLIB
- select PTP_1588_CLOCK
+ depends on PTP_1588_CLOCK
---help---
Supports the DP83640 PHYTER with IEEE 1588 features.
@@ -76,7 +76,7 @@ config PTP_1588_CLOCK_PCH
tristate "Intel PCH EG20T as PTP clock"
depends on X86_32 || COMPILE_TEST
depends on HAS_IOMEM && NET
- select PTP_1588_CLOCK
+ imply PTP_1588_CLOCK
help
This driver adds support for using the PCH EG20T as a PTP
clock. The hardware supports time stamping of PTP packets
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index 5ad54fc66c..4b205fb5a4 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -122,30 +122,6 @@ struct ptp_clock_info {
struct ptp_clock;
-/**
- * ptp_clock_register() - register a PTP hardware clock driver
- *
- * @info: Structure describing the new clock.
- * @parent: Pointer to the parent device of the new clock.
- *
- * Returns a valid pointer on success or PTR_ERR on failure. If PHC
- * support is missing at the configuration level, this function
- * returns NULL, and drivers are expected to gracefully handle that
- * case separately.
- */
-
-extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
- struct device *parent);
-
-/**
- * ptp_clock_unregister() - unregister a PTP hardware clock driver
- *
- * @ptp: The clock to remove from service.
- */
-
-extern int ptp_clock_unregister(struct ptp_clock *ptp);
-
-
enum ptp_clock_events {
PTP_CLOCK_ALARM,
PTP_CLOCK_EXTTS,
@@ -171,6 +147,31 @@ struct ptp_clock_event {
};
};
+#if IS_REACHABLE(CONFIG_PTP_1588_CLOCK)
+
+/**
+ * ptp_clock_register() - register a PTP hardware clock driver
+ *
+ * @info: Structure describing the new clock.
+ * @parent: Pointer to the parent device of the new clock.
+ *
+ * Returns a valid pointer on success or PTR_ERR on failure. If PHC
+ * support is missing at the configuration level, this function
+ * returns NULL, and drivers are expected to gracefully handle that
+ * case separately.
+ */
+
+extern struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
+ struct device *parent);
+
+/**
+ * ptp_clock_unregister() - unregister a PTP hardware clock driver
+ *
+ * @ptp: The clock to remove from service.
+ */
+
+extern int ptp_clock_unregister(struct ptp_clock *ptp);
+
/**
* ptp_clock_event() - notify the PTP layer about an event
*
@@ -202,4 +203,20 @@ extern int ptp_clock_index(struct ptp_clock *ptp);
int ptp_find_pin(struct ptp_clock *ptp,
enum ptp_pin_function func, unsigned int chan);
+#else
+static inline struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
+ struct device *parent)
+{ return NULL; }
+static inline int ptp_clock_unregister(struct ptp_clock *ptp)
+{ return 0; }
+static inline void ptp_clock_event(struct ptp_clock *ptp,
+ struct ptp_clock_event *event)
+{ (void)event; }
+static inline int ptp_clock_index(struct ptp_clock *ptp)
+{ return -1; }
+static inline int ptp_find_pin(struct ptp_clock *ptp,
+ enum ptp_pin_function func, unsigned int chan)
+{ return -1; }
+#endif
+
#endif
--
2.7.4
^ permalink raw reply related
* [PATCH 2/4] kconfig: re-generate *.c_shipped files after previous change
From: Nicolas Pitre @ 2016-10-19 23:42 UTC (permalink / raw)
To: John Stultz, Richard Cochran, Yann E MORIN
Cc: Thomas Gleixner, Josh Triplett, netdev, linux-kbuild,
linux-kernel
In-Reply-To: <1476920573-14384-1-git-send-email-nicolas.pitre@linaro.org>
Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
scripts/kconfig/zconf.hash.c_shipped | 30 +-
scripts/kconfig/zconf.tab.c_shipped | 1581 ++++++++++++++++------------------
2 files changed, 753 insertions(+), 858 deletions(-)
diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index 360a62df2b..d51b15de07 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -55,10 +55,10 @@ kconf_id_hash (register const char *str, register unsigned int len)
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
- 73, 73, 73, 73, 73, 73, 73, 5, 25, 25,
+ 73, 73, 73, 73, 73, 73, 73, 10, 25, 25,
0, 0, 0, 5, 0, 0, 73, 73, 5, 0,
10, 5, 45, 73, 20, 20, 0, 15, 15, 73,
- 20, 5, 73, 73, 73, 73, 73, 73, 73, 73,
+ 20, 0, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
@@ -120,6 +120,7 @@ struct kconf_id_strings_t
char kconf_id_strings_str43[sizeof("hex")];
char kconf_id_strings_str46[sizeof("config")];
char kconf_id_strings_str47[sizeof("boolean")];
+ char kconf_id_strings_str50[sizeof("imply")];
char kconf_id_strings_str51[sizeof("string")];
char kconf_id_strings_str54[sizeof("help")];
char kconf_id_strings_str56[sizeof("prompt")];
@@ -157,6 +158,7 @@ static const struct kconf_id_strings_t kconf_id_strings_contents =
"hex",
"config",
"boolean",
+ "imply",
"string",
"help",
"prompt",
@@ -174,7 +176,7 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{
enum
{
- TOTAL_KEYWORDS = 34,
+ TOTAL_KEYWORDS = 35,
MIN_WORD_LENGTH = 2,
MAX_WORD_LENGTH = 14,
MIN_HASH_VALUE = 2,
@@ -205,15 +207,15 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str12, T_DEFAULT, TF_COMMAND, S_TRISTATE},
#line 36 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str13, T_DEFAULT, TF_COMMAND, S_BOOLEAN},
-#line 46 "scripts/kconfig/zconf.gperf"
+#line 47 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str14, T_OPT_DEFCONFIG_LIST,TF_OPTION},
{-1}, {-1},
-#line 44 "scripts/kconfig/zconf.gperf"
+#line 45 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str17, T_ON, TF_PARAM},
#line 29 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str18, T_OPTIONAL, TF_COMMAND},
{-1}, {-1},
-#line 43 "scripts/kconfig/zconf.gperf"
+#line 44 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str21, T_OPTION, TF_COMMAND},
#line 17 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str22, T_ENDMENU, TF_COMMAND},
@@ -223,9 +225,9 @@ kconf_id_lookup (register const char *str, register unsigned int len)
#line 23 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str25, T_MENUCONFIG, TF_COMMAND},
{-1},
-#line 45 "scripts/kconfig/zconf.gperf"
+#line 46 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str27, T_OPT_MODULES, TF_OPTION},
-#line 48 "scripts/kconfig/zconf.gperf"
+#line 49 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str28, T_OPT_ALLNOCONFIG_Y,TF_OPTION},
#line 16 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str29, T_MENU, TF_COMMAND},
@@ -234,10 +236,10 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str31, T_SELECT, TF_COMMAND},
#line 21 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str32, T_COMMENT, TF_COMMAND},
-#line 47 "scripts/kconfig/zconf.gperf"
+#line 48 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str33, T_OPT_ENV, TF_OPTION},
{-1},
-#line 41 "scripts/kconfig/zconf.gperf"
+#line 42 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str35, T_RANGE, TF_COMMAND},
#line 19 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str36, T_CHOICE, TF_COMMAND},
@@ -247,7 +249,7 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{-1},
#line 18 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str41, T_SOURCE, TF_COMMAND},
-#line 42 "scripts/kconfig/zconf.gperf"
+#line 43 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42, T_VISIBLE, TF_COMMAND},
#line 38 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43, T_TYPE, TF_COMMAND, S_HEX},
@@ -256,7 +258,9 @@ kconf_id_lookup (register const char *str, register unsigned int len)
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46, T_CONFIG, TF_COMMAND},
#line 35 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str47, T_TYPE, TF_COMMAND, S_BOOLEAN},
- {-1}, {-1}, {-1},
+ {-1}, {-1},
+#line 41 "scripts/kconfig/zconf.gperf"
+ {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str50, T_IMPLY, TF_COMMAND},
#line 39 "scripts/kconfig/zconf.gperf"
{(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str51, T_TYPE, TF_COMMAND, S_STRING},
{-1}, {-1},
@@ -289,5 +293,5 @@ kconf_id_lookup (register const char *str, register unsigned int len)
}
return 0;
}
-#line 49 "scripts/kconfig/zconf.gperf"
+#line 50 "scripts/kconfig/zconf.gperf"
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 7a4d658c20..65b7515a57 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.5.1. */
+/* A Bison parser, made by GNU Bison 3.0.4. */
/* Bison implementation for Yacc-like parsers in C
-
- Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-
+
+ Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, 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, either version 3 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, see <http://www.gnu.org/licenses/>. */
@@ -26,7 +26,7 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
-
+
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
@@ -44,7 +44,7 @@
#define YYBISON 1
/* Bison version. */
-#define YYBISON_VERSION "2.5.1"
+#define YYBISON_VERSION "3.0.4"
/* Skeleton name. */
#define YYSKELETON_NAME "yacc.c"
@@ -58,18 +58,16 @@
/* Pull parsers. */
#define YYPULL 1
-/* Using locations. */
-#define YYLSP_NEEDED 0
/* Substitute the variable and function names. */
#define yyparse zconfparse
#define yylex zconflex
#define yyerror zconferror
-#define yylval zconflval
-#define yychar zconfchar
#define yydebug zconfdebug
#define yynerrs zconfnerrs
+#define yylval zconflval
+#define yychar zconfchar
/* Copy the first part of user declarations. */
@@ -108,19 +106,14 @@ static struct menu *current_menu, *current_entry;
-# ifndef YY_NULL
+# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
-# define YY_NULL nullptr
+# define YY_NULLPTR nullptr
# else
-# define YY_NULL 0
+# define YY_NULLPTR 0
# endif
# endif
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
/* Enabling verbose error messages. */
#ifdef YYERROR_VERBOSE
# undef YYERROR_VERBOSE
@@ -129,62 +122,65 @@ static struct menu *current_menu, *current_entry;
# define YYERROR_VERBOSE 0
#endif
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
+/* Debug traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int zconfdebug;
+#endif
-/* Tokens. */
+/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- T_MAINMENU = 258,
- T_MENU = 259,
- T_ENDMENU = 260,
- T_SOURCE = 261,
- T_CHOICE = 262,
- T_ENDCHOICE = 263,
- T_COMMENT = 264,
- T_CONFIG = 265,
- T_MENUCONFIG = 266,
- T_HELP = 267,
- T_HELPTEXT = 268,
- T_IF = 269,
- T_ENDIF = 270,
- T_DEPENDS = 271,
- T_OPTIONAL = 272,
- T_PROMPT = 273,
- T_TYPE = 274,
- T_DEFAULT = 275,
- T_SELECT = 276,
- T_RANGE = 277,
- T_VISIBLE = 278,
- T_OPTION = 279,
- T_ON = 280,
- T_WORD = 281,
- T_WORD_QUOTE = 282,
- T_UNEQUAL = 283,
- T_LESS = 284,
- T_LESS_EQUAL = 285,
- T_GREATER = 286,
- T_GREATER_EQUAL = 287,
- T_CLOSE_PAREN = 288,
- T_OPEN_PAREN = 289,
- T_EOL = 290,
- T_OR = 291,
- T_AND = 292,
- T_EQUAL = 293,
- T_NOT = 294
- };
+ enum yytokentype
+ {
+ T_MAINMENU = 258,
+ T_MENU = 259,
+ T_ENDMENU = 260,
+ T_SOURCE = 261,
+ T_CHOICE = 262,
+ T_ENDCHOICE = 263,
+ T_COMMENT = 264,
+ T_CONFIG = 265,
+ T_MENUCONFIG = 266,
+ T_HELP = 267,
+ T_HELPTEXT = 268,
+ T_IF = 269,
+ T_ENDIF = 270,
+ T_DEPENDS = 271,
+ T_OPTIONAL = 272,
+ T_PROMPT = 273,
+ T_TYPE = 274,
+ T_DEFAULT = 275,
+ T_SELECT = 276,
+ T_IMPLY = 277,
+ T_RANGE = 278,
+ T_VISIBLE = 279,
+ T_OPTION = 280,
+ T_ON = 281,
+ T_WORD = 282,
+ T_WORD_QUOTE = 283,
+ T_UNEQUAL = 284,
+ T_LESS = 285,
+ T_LESS_EQUAL = 286,
+ T_GREATER = 287,
+ T_GREATER_EQUAL = 288,
+ T_CLOSE_PAREN = 289,
+ T_OPEN_PAREN = 290,
+ T_EOL = 291,
+ T_OR = 292,
+ T_AND = 293,
+ T_EQUAL = 294,
+ T_NOT = 295
+ };
#endif
-
-
+/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
+
+union YYSTYPE
{
@@ -196,14 +192,20 @@ typedef union YYSTYPE
const struct kconf_id *id;
+};
-} YYSTYPE;
+typedef union YYSTYPE YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
+extern YYSTYPE zconflval;
+
+int zconfparse (void);
+
+
+
/* Copy the second part of user declarations. */
@@ -224,11 +226,8 @@ typedef unsigned char yytype_uint8;
#ifdef YYTYPE_INT8
typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
#else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
#endif
#ifdef YYTYPE_UINT16
@@ -248,8 +247,7 @@ typedef short int yytype_int16;
# define YYSIZE_T __SIZE_TYPE__
# elif defined size_t
# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
# define YYSIZE_T size_t
# else
@@ -263,38 +261,67 @@ typedef short int yytype_int16;
# if defined YYENABLE_NLS && YYENABLE_NLS
# if ENABLE_NLS
# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# define YY_(Msgid) dgettext ("bison-runtime", Msgid)
# endif
# endif
# ifndef YY_
-# define YY_(msgid) msgid
+# define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__ \
+ && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__))) \
+ || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+# define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+# define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+ && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+# define _Noreturn __declspec (noreturn)
+# else
+# define _Noreturn YY_ATTRIBUTE ((__noreturn__))
# endif
#endif
/* Suppress unused-variable warnings by "using" E. */
#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
#else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
#endif
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized. */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+ _Pragma ("GCC diagnostic push") \
+ _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+ _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+ _Pragma ("GCC diagnostic pop")
#else
-static int
-YYID (yyi)
- int yyi;
+# define YY_INITIAL_VALUE(Value) Value
#endif
-{
- return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
#endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
#if ! defined yyoverflow || YYERROR_VERBOSE
@@ -313,8 +340,7 @@ YYID (yyi)
# define alloca _alloca
# else
# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
/* Use EXIT_SUCCESS as a witness for stdlib.h. */
# ifndef EXIT_SUCCESS
@@ -326,8 +352,8 @@ YYID (yyi)
# endif
# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+ /* Pacify GCC's 'empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
# ifndef YYSTACK_ALLOC_MAXIMUM
/* The OS might guarantee only one guard page at the bottom of the stack,
and a page size can be as small as 4096 bytes. So we cannot safely
@@ -343,7 +369,7 @@ YYID (yyi)
# endif
# if (defined __cplusplus && ! defined EXIT_SUCCESS \
&& ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
+ && (defined YYFREE || defined free)))
# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
# ifndef EXIT_SUCCESS
# define EXIT_SUCCESS 0
@@ -351,15 +377,13 @@ YYID (yyi)
# endif
# ifndef YYMALLOC
# define YYMALLOC malloc
-# if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined malloc && ! defined EXIT_SUCCESS
void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
# ifndef YYFREE
# define YYFREE free
-# if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
+# if ! defined free && ! defined EXIT_SUCCESS
void free (void *); /* INFRINGES ON USER NAME SPACE */
# endif
# endif
@@ -369,7 +393,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
#if (! defined yyoverflow \
&& (! defined __cplusplus \
- || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
/* A type that is properly aligned for any stack member. */
union yyalloc
@@ -394,16 +418,16 @@ union yyalloc
elements in the stack, and YYPTR gives the new location of the
stack. Advance YYPTR to a properly aligned location for the next
stack. */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
- Stack = &yyptr->Stack_alloc; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
+# define YYSTACK_RELOCATE(Stack_alloc, Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \
+ Stack = &yyptr->Stack_alloc; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (0)
#endif
@@ -422,7 +446,7 @@ union yyalloc
for (yyi = 0; yyi < (Count); yyi++) \
(Dst)[yyi] = (Src)[yyi]; \
} \
- while (YYID (0))
+ while (0)
# endif
# endif
#endif /* !YYCOPY_NEEDED */
@@ -430,25 +454,27 @@ union yyalloc
/* YYFINAL -- State number of the termination state. */
#define YYFINAL 11
/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 298
+#define YYLAST 301
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 40
+#define YYNTOKENS 41
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 50
/* YYNRULES -- Number of rules. */
-#define YYNRULES 122
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 199
+#define YYNRULES 124
+/* YYNSTATES -- Number of states. */
+#define YYNSTATES 204
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+ by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 294
+#define YYMAXUTOK 295
-#define YYTRANSLATE(YYX) \
+#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+ as returned by yylex, without out-of-bounds checking. */
static const yytype_uint8 yytranslate[] =
{
0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -480,90 +506,30 @@ static const yytype_uint8 yytranslate[] =
5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39
+ 35, 36, 37, 38, 39, 40
};
#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint16 yyprhs[] =
-{
- 0, 0, 3, 6, 8, 11, 13, 14, 17, 20,
- 23, 26, 31, 36, 40, 42, 44, 46, 48, 50,
- 52, 54, 56, 58, 60, 62, 64, 66, 68, 72,
- 75, 79, 82, 86, 89, 90, 93, 96, 99, 102,
- 105, 108, 112, 117, 122, 127, 133, 137, 138, 142,
- 143, 146, 150, 153, 155, 159, 160, 163, 166, 169,
- 172, 175, 180, 184, 187, 192, 193, 196, 200, 202,
- 206, 207, 210, 213, 216, 220, 224, 228, 230, 234,
- 235, 238, 241, 244, 248, 252, 255, 258, 261, 262,
- 265, 268, 271, 276, 277, 280, 283, 286, 287, 290,
- 292, 294, 297, 300, 303, 305, 308, 309, 312, 314,
- 318, 322, 326, 330, 334, 338, 342, 345, 349, 353,
- 355, 357, 358
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 41, 0, -1, 85, 42, -1, 42, -1, 67, 43,
- -1, 43, -1, -1, 43, 45, -1, 43, 59, -1,
- 43, 71, -1, 43, 84, -1, 43, 26, 1, 35,
- -1, 43, 44, 1, 35, -1, 43, 1, 35, -1,
- 16, -1, 18, -1, 19, -1, 21, -1, 17, -1,
- 22, -1, 20, -1, 23, -1, 35, -1, 65, -1,
- 75, -1, 48, -1, 50, -1, 73, -1, 26, 1,
- 35, -1, 1, 35, -1, 10, 26, 35, -1, 47,
- 51, -1, 11, 26, 35, -1, 49, 51, -1, -1,
- 51, 52, -1, 51, 53, -1, 51, 79, -1, 51,
- 77, -1, 51, 46, -1, 51, 35, -1, 19, 82,
- 35, -1, 18, 83, 86, 35, -1, 20, 87, 86,
- 35, -1, 21, 26, 86, 35, -1, 22, 88, 88,
- 86, 35, -1, 24, 54, 35, -1, -1, 54, 26,
- 55, -1, -1, 38, 83, -1, 7, 89, 35, -1,
- 56, 60, -1, 84, -1, 57, 62, 58, -1, -1,
- 60, 61, -1, 60, 79, -1, 60, 77, -1, 60,
- 35, -1, 60, 46, -1, 18, 83, 86, 35, -1,
- 19, 82, 35, -1, 17, 35, -1, 20, 26, 86,
- 35, -1, -1, 62, 45, -1, 14, 87, 85, -1,
- 84, -1, 63, 66, 64, -1, -1, 66, 45, -1,
- 66, 71, -1, 66, 59, -1, 3, 83, 85, -1,
- 4, 83, 35, -1, 68, 80, 78, -1, 84, -1,
- 69, 72, 70, -1, -1, 72, 45, -1, 72, 71,
- -1, 72, 59, -1, 6, 83, 35, -1, 9, 83,
- 35, -1, 74, 78, -1, 12, 35, -1, 76, 13,
- -1, -1, 78, 79, -1, 78, 35, -1, 78, 46,
- -1, 16, 25, 87, 35, -1, -1, 80, 81, -1,
- 80, 35, -1, 23, 86, -1, -1, 83, 86, -1,
- 26, -1, 27, -1, 5, 35, -1, 8, 35, -1,
- 15, 35, -1, 35, -1, 85, 35, -1, -1, 14,
- 87, -1, 88, -1, 88, 29, 88, -1, 88, 30,
- 88, -1, 88, 31, 88, -1, 88, 32, 88, -1,
- 88, 38, 88, -1, 88, 28, 88, -1, 34, 87,
- 33, -1, 39, 87, -1, 87, 36, 87, -1, 87,
- 37, 87, -1, 26, -1, 27, -1, -1, 26, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+ /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint16 yyrline[] =
{
- 0, 108, 108, 108, 110, 110, 112, 114, 115, 116,
- 117, 118, 119, 123, 127, 127, 127, 127, 127, 127,
- 127, 127, 131, 132, 133, 134, 135, 136, 140, 141,
- 147, 155, 161, 169, 179, 181, 182, 183, 184, 185,
- 186, 189, 197, 203, 213, 219, 225, 228, 230, 241,
- 242, 247, 256, 261, 269, 272, 274, 275, 276, 277,
- 278, 281, 287, 298, 304, 314, 316, 321, 329, 337,
- 340, 342, 343, 344, 349, 356, 363, 368, 376, 379,
- 381, 382, 383, 386, 394, 401, 408, 414, 421, 423,
- 424, 425, 428, 436, 438, 439, 442, 449, 451, 456,
- 457, 460, 461, 462, 466, 467, 470, 471, 474, 475,
- 476, 477, 478, 479, 480, 481, 482, 483, 484, 487,
- 488, 491, 492
+ 0, 109, 109, 109, 111, 111, 113, 115, 116, 117,
+ 118, 119, 120, 124, 128, 128, 128, 128, 128, 128,
+ 128, 128, 128, 132, 133, 134, 135, 136, 137, 141,
+ 142, 148, 156, 162, 170, 180, 182, 183, 184, 185,
+ 186, 187, 190, 198, 204, 214, 220, 226, 232, 235,
+ 237, 248, 249, 254, 263, 268, 276, 279, 281, 282,
+ 283, 284, 285, 288, 294, 305, 311, 321, 323, 328,
+ 336, 344, 347, 349, 350, 351, 356, 363, 370, 375,
+ 383, 386, 388, 389, 390, 393, 401, 408, 415, 421,
+ 428, 430, 431, 432, 435, 443, 445, 446, 449, 456,
+ 458, 463, 464, 467, 468, 469, 473, 474, 477, 478,
+ 481, 482, 483, 484, 485, 486, 487, 488, 489, 490,
+ 491, 494, 495, 498, 499
};
#endif
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 0
/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
@@ -571,9 +537,9 @@ static const char *const yytname[] =
"$end", "error", "$undefined", "T_MAINMENU", "T_MENU", "T_ENDMENU",
"T_SOURCE", "T_CHOICE", "T_ENDCHOICE", "T_COMMENT", "T_CONFIG",
"T_MENUCONFIG", "T_HELP", "T_HELPTEXT", "T_IF", "T_ENDIF", "T_DEPENDS",
- "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
- "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
- "T_LESS", "T_LESS_EQUAL", "T_GREATER", "T_GREATER_EQUAL",
+ "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_IMPLY",
+ "T_RANGE", "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE",
+ "T_UNEQUAL", "T_LESS", "T_LESS_EQUAL", "T_GREATER", "T_GREATER_EQUAL",
"T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
"T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
"common_stmt", "option_error", "config_entry_start", "config_stmt",
@@ -585,260 +551,254 @@ static const char *const yytname[] =
"menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
"comment", "comment_stmt", "help_start", "help", "depends_list",
"depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
- "end", "nl", "if_expr", "expr", "symbol", "word_opt", YY_NULL
+ "end", "nl", "if_expr", "expr", "symbol", "word_opt", YY_NULLPTR
};
#endif
# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+ (internal) symbol number NUM (which must be that of a token). */
static const yytype_uint16 yytoknum[] =
{
0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
275, 276, 277, 278, 279, 280, 281, 282, 283, 284,
- 285, 286, 287, 288, 289, 290, 291, 292, 293, 294
+ 285, 286, 287, 288, 289, 290, 291, 292, 293, 294,
+ 295
};
# endif
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
+#define YYPACT_NINF -92
+
+#define yypact_value_is_default(Yystate) \
+ (!!((Yystate) == (-92)))
+
+#define YYTABLE_NINF -88
+
+#define yytable_value_is_error(Yytable_value) \
+ 0
+
+ /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+static const yytype_int16 yypact[] =
{
- 0, 40, 41, 41, 42, 42, 43, 43, 43, 43,
- 43, 43, 43, 43, 44, 44, 44, 44, 44, 44,
- 44, 44, 45, 45, 45, 45, 45, 45, 46, 46,
- 47, 48, 49, 50, 51, 51, 51, 51, 51, 51,
- 51, 52, 52, 52, 52, 52, 53, 54, 54, 55,
- 55, 56, 57, 58, 59, 60, 60, 60, 60, 60,
- 60, 61, 61, 61, 61, 62, 62, 63, 64, 65,
- 66, 66, 66, 66, 67, 68, 69, 70, 71, 72,
- 72, 72, 72, 73, 74, 75, 76, 77, 78, 78,
- 78, 78, 79, 80, 80, 80, 81, 82, 82, 83,
- 83, 84, 84, 84, 85, 85, 86, 86, 87, 87,
- 87, 87, 87, 87, 87, 87, 87, 87, 87, 88,
- 88, 89, 89
+ 17, 41, -92, 15, -92, 150, -92, 19, -92, -92,
+ -13, -92, 28, 41, 38, 41, 50, 47, 41, 79,
+ 82, 44, 76, -92, -92, -92, -92, -92, -92, -92,
+ -92, -92, 118, -92, 129, -92, -92, -92, -92, -92,
+ -92, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ -92, -92, 184, -92, -92, 107, -92, 111, -92, 113,
+ -92, 116, -92, 139, 140, 151, -92, -92, 44, 44,
+ 142, 256, -92, 160, 173, 27, 117, 80, 51, 255,
+ -15, 255, 217, -92, -92, -92, -92, -92, -92, -8,
+ -92, 44, 44, 107, 87, 87, 87, 87, 87, 87,
+ -92, -92, 174, 176, 187, 41, 41, 44, 188, 189,
+ 87, -92, 213, -92, -92, -92, -92, 206, -92, -92,
+ 193, 41, 41, 203, -92, -92, -92, -92, -92, -92,
+ -92, -92, -92, -92, -92, -92, -92, 229, -92, 241,
+ -92, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ 216, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ 44, 229, 222, 229, 64, 229, 229, 87, 31, 231,
+ -92, -92, 229, 236, 229, 44, -92, 145, 242, -92,
+ -92, 243, 244, 245, 229, 251, -92, -92, 247, -92,
+ 257, 125, -92, -92, -92, -92, -92, 260, 41, -92,
+ -92, -92, -92, -92
};
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
+ /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+ Performed when YYTABLE does not specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
{
- 0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
- 2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 3, 2,
- 3, 2, 3, 2, 0, 2, 2, 2, 2, 2,
- 2, 3, 4, 4, 4, 5, 3, 0, 3, 0,
- 2, 3, 2, 1, 3, 0, 2, 2, 2, 2,
- 2, 4, 3, 2, 4, 0, 2, 3, 1, 3,
- 0, 2, 2, 2, 3, 3, 3, 1, 3, 0,
- 2, 2, 2, 3, 3, 2, 2, 2, 0, 2,
- 2, 2, 4, 0, 2, 2, 2, 0, 2, 1,
- 1, 2, 2, 2, 1, 2, 0, 2, 1, 3,
- 3, 3, 3, 3, 3, 3, 2, 3, 3, 1,
- 1, 0, 1
+ 6, 0, 106, 0, 3, 0, 6, 6, 101, 102,
+ 0, 1, 0, 0, 0, 0, 123, 0, 0, 0,
+ 0, 0, 0, 14, 19, 15, 16, 21, 17, 18,
+ 20, 22, 0, 23, 0, 7, 35, 26, 35, 27,
+ 57, 67, 8, 72, 24, 95, 81, 9, 28, 90,
+ 25, 10, 0, 107, 2, 76, 13, 0, 103, 0,
+ 124, 0, 104, 0, 0, 0, 121, 122, 0, 0,
+ 0, 110, 105, 0, 0, 0, 0, 0, 0, 0,
+ 90, 0, 0, 77, 85, 53, 86, 31, 33, 0,
+ 118, 0, 0, 69, 0, 0, 0, 0, 0, 0,
+ 11, 12, 0, 0, 0, 0, 99, 0, 0, 0,
+ 0, 49, 0, 41, 40, 36, 37, 0, 39, 38,
+ 0, 0, 99, 0, 61, 62, 58, 60, 59, 68,
+ 56, 55, 73, 75, 71, 74, 70, 108, 97, 0,
+ 96, 82, 84, 80, 83, 79, 92, 93, 91, 117,
+ 119, 120, 116, 111, 112, 113, 114, 115, 30, 88,
+ 0, 108, 0, 108, 108, 108, 108, 0, 0, 0,
+ 89, 65, 108, 0, 108, 0, 98, 0, 0, 42,
+ 100, 0, 0, 0, 108, 51, 48, 29, 0, 64,
+ 0, 109, 94, 43, 44, 45, 46, 0, 0, 50,
+ 63, 66, 47, 52
};
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
- Performed when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
+ /* YYPGOTO[NTERM-NUM]. */
+static const yytype_int16 yypgoto[] =
{
- 6, 0, 104, 0, 3, 0, 6, 6, 99, 100,
- 0, 1, 0, 0, 0, 0, 121, 0, 0, 0,
- 0, 0, 0, 14, 18, 15, 16, 20, 17, 19,
- 21, 0, 22, 0, 7, 34, 25, 34, 26, 55,
- 65, 8, 70, 23, 93, 79, 9, 27, 88, 24,
- 10, 0, 105, 2, 74, 13, 0, 101, 0, 122,
- 0, 102, 0, 0, 0, 119, 120, 0, 0, 0,
- 108, 103, 0, 0, 0, 0, 0, 0, 0, 88,
- 0, 0, 75, 83, 51, 84, 30, 32, 0, 116,
- 0, 0, 67, 0, 0, 0, 0, 0, 0, 11,
- 12, 0, 0, 0, 0, 97, 0, 0, 0, 47,
- 0, 40, 39, 35, 36, 0, 38, 37, 0, 0,
- 97, 0, 59, 60, 56, 58, 57, 66, 54, 53,
- 71, 73, 69, 72, 68, 106, 95, 0, 94, 80,
- 82, 78, 81, 77, 90, 91, 89, 115, 117, 118,
- 114, 109, 110, 111, 112, 113, 29, 86, 0, 106,
- 0, 106, 106, 106, 0, 0, 0, 87, 63, 106,
- 0, 106, 0, 96, 0, 0, 41, 98, 0, 0,
- 106, 49, 46, 28, 0, 62, 0, 107, 92, 42,
- 43, 44, 0, 0, 48, 61, 64, 45, 50
+ -92, -92, 285, 291, -92, 32, -66, -92, -92, -92,
+ -92, 261, -92, -92, -92, -92, -92, -92, -92, 1,
+ -92, -92, -92, -92, -92, -92, -92, -92, -92, -92,
+ -92, 24, -92, -92, -92, -92, -92, 221, 220, -64,
+ -92, -92, 179, -1, 67, 0, 110, -67, -91, -92
};
-/* YYDEFGOTO[NTERM-NUM]. */
+ /* YYDEFGOTO[NTERM-NUM]. */
static const yytype_int16 yydefgoto[] =
{
- -1, 3, 4, 5, 33, 34, 112, 35, 36, 37,
- 38, 74, 113, 114, 165, 194, 39, 40, 128, 41,
- 76, 124, 77, 42, 132, 43, 78, 6, 44, 45,
- 141, 46, 80, 47, 48, 49, 115, 116, 81, 117,
- 79, 138, 160, 161, 50, 7, 173, 69, 70, 60
+ -1, 3, 4, 5, 34, 35, 114, 36, 37, 38,
+ 39, 75, 115, 116, 168, 199, 40, 41, 130, 42,
+ 77, 126, 78, 43, 134, 44, 79, 6, 45, 46,
+ 143, 47, 81, 48, 49, 50, 117, 118, 82, 119,
+ 80, 140, 162, 163, 51, 7, 176, 70, 71, 61
};
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -91
-static const yytype_int16 yypact[] =
+ /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule whose
+ number is the opposite. If YYTABLE_NINF, syntax error. */
+static const yytype_int16 yytable[] =
{
- 19, 37, -91, 13, -91, 79, -91, 20, -91, -91,
- -16, -91, 21, 37, 25, 37, 41, 36, 37, 78,
- 83, 31, 56, -91, -91, -91, -91, -91, -91, -91,
- -91, 116, -91, 127, -91, -91, -91, -91, -91, -91,
- -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
- -91, 147, -91, -91, 105, -91, 109, -91, 111, -91,
- 114, -91, 136, 137, 142, -91, -91, 31, 31, 76,
- 254, -91, 143, 146, 27, 115, 207, 258, 243, -14,
- 243, 179, -91, -91, -91, -91, -91, -91, -7, -91,
- 31, 31, 105, 51, 51, 51, 51, 51, 51, -91,
- -91, 156, 168, 181, 37, 37, 31, 178, 51, -91,
- 206, -91, -91, -91, -91, 196, -91, -91, 175, 37,
- 37, 185, -91, -91, -91, -91, -91, -91, -91, -91,
- -91, -91, -91, -91, -91, 214, -91, 230, -91, -91,
- -91, -91, -91, -91, -91, -91, -91, -91, 183, -91,
- -91, -91, -91, -91, -91, -91, -91, -91, 31, 214,
- 194, 214, 45, 214, 51, 26, 195, -91, -91, 214,
- 197, 214, 31, -91, 139, 208, -91, -91, 220, 224,
- 214, 222, -91, -91, 226, -91, 227, 123, -91, -91,
- -91, -91, 235, 37, -91, -91, -91, -91, -91
+ 10, 89, 90, 152, 153, 154, 155, 156, 157, 137,
+ 55, 125, 57, 128, 59, 11, 147, 63, 148, 167,
+ 1, 138, 1, 2, 150, 151, 149, -32, 102, 91,
+ 92, -32, -32, -32, -32, -32, -32, -32, -32, 103,
+ 164, -32, -32, 104, -32, 105, 106, 107, 108, 109,
+ 110, -32, 111, 2, 112, 53, 14, 15, 185, 17,
+ 18, 19, 20, 113, 56, 21, 22, 186, 8, 9,
+ 93, 66, 67, 147, 58, 148, 184, 60, 175, 68,
+ 133, 102, 142, 62, 69, -54, -54, 33, -54, -54,
+ -54, -54, 103, 177, -54, -54, 104, 120, 121, 122,
+ 123, 91, 92, 135, 161, 144, 64, 112, 191, 65,
+ 129, 132, 72, 141, 66, 67, 124, -34, 102, 73,
+ 172, -34, -34, -34, -34, -34, -34, -34, -34, 103,
+ 74, -34, -34, 104, -34, 105, 106, 107, 108, 109,
+ 110, -34, 111, 53, 112, 131, 136, 83, 145, 84,
+ -5, 12, 85, 113, 13, 14, 15, 16, 17, 18,
+ 19, 20, 91, 92, 21, 22, 23, 24, 25, 26,
+ 27, 28, 29, 30, 31, 86, 87, 32, 2, 91,
+ 92, 192, 91, 92, -4, 12, 33, 88, 13, 14,
+ 15, 16, 17, 18, 19, 20, 100, 203, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 101,
+ 158, 32, 159, 160, 169, 165, 166, -87, 102, 170,
+ 33, -87, -87, -87, -87, -87, -87, -87, -87, 171,
+ 174, -87, -87, 104, -87, -87, -87, -87, -87, -87,
+ -87, -87, 102, 175, 112, -78, -78, -78, -78, -78,
+ -78, -78, -78, 146, 92, -78, -78, 104, 179, 13,
+ 14, 15, 16, 17, 18, 19, 20, 187, 112, 21,
+ 22, 178, 189, 180, 181, 182, 183, 146, 193, 194,
+ 195, 196, 188, 200, 190, 94, 95, 96, 97, 98,
+ 198, 33, 54, 201, 197, 99, 202, 52, 127, 76,
+ 139, 173
};
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int16 yypgoto[] =
+static const yytype_uint8 yycheck[] =
{
- -91, -91, 264, 268, -91, 30, -65, -91, -91, -91,
- -91, 238, -91, -91, -91, -91, -91, -91, -91, -12,
- -91, -91, -91, -91, -91, -91, -91, -91, -91, -91,
- -91, -5, -91, -91, -91, -91, -91, 200, 209, -61,
- -91, -91, 170, -1, 65, 0, 118, -66, -90, -91
+ 1, 68, 69, 94, 95, 96, 97, 98, 99, 24,
+ 10, 77, 13, 77, 15, 0, 82, 18, 82, 110,
+ 3, 36, 3, 36, 91, 92, 34, 0, 1, 37,
+ 38, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 107, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 36, 27, 36, 5, 6, 27, 8,
+ 9, 10, 11, 36, 36, 14, 15, 36, 27, 28,
+ 70, 27, 28, 139, 36, 139, 167, 27, 14, 35,
+ 79, 1, 81, 36, 40, 5, 6, 36, 8, 9,
+ 10, 11, 12, 160, 14, 15, 16, 17, 18, 19,
+ 20, 37, 38, 79, 105, 81, 27, 27, 175, 27,
+ 78, 79, 36, 81, 27, 28, 36, 0, 1, 1,
+ 121, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 1, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 36, 27, 78, 79, 36, 81, 36,
+ 0, 1, 36, 36, 4, 5, 6, 7, 8, 9,
+ 10, 11, 37, 38, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 36, 36, 27, 36, 37,
+ 38, 36, 37, 38, 0, 1, 36, 36, 4, 5,
+ 6, 7, 8, 9, 10, 11, 36, 198, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 36,
+ 36, 27, 36, 26, 1, 27, 27, 0, 1, 13,
+ 36, 4, 5, 6, 7, 8, 9, 10, 11, 36,
+ 27, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 1, 14, 27, 4, 5, 6, 7, 8,
+ 9, 10, 11, 36, 38, 14, 15, 16, 36, 4,
+ 5, 6, 7, 8, 9, 10, 11, 36, 27, 14,
+ 15, 161, 36, 163, 164, 165, 166, 36, 36, 36,
+ 36, 36, 172, 36, 174, 29, 30, 31, 32, 33,
+ 39, 36, 7, 36, 184, 39, 36, 6, 77, 38,
+ 80, 122
};
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -86
-static const yytype_int16 yytable[] =
+ /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
{
- 10, 88, 89, 150, 151, 152, 153, 154, 155, 135,
- 54, 123, 56, 11, 58, 126, 145, 62, 164, 2,
- 146, 136, 1, 1, 148, 149, 147, -31, 101, 90,
- 91, -31, -31, -31, -31, -31, -31, -31, -31, 102,
- 162, -31, -31, 103, -31, 104, 105, 106, 107, 108,
- -31, 109, 181, 110, 2, 52, 55, 65, 66, 172,
- 57, 182, 111, 8, 9, 67, 131, 59, 140, 92,
- 68, 61, 145, 133, 180, 142, 146, 65, 66, -5,
- 12, 90, 91, 13, 14, 15, 16, 17, 18, 19,
- 20, 71, 174, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 159, 63, 31, 187, 127, 130, 64,
- 139, 2, 90, 91, 32, -33, 101, 72, 169, -33,
- -33, -33, -33, -33, -33, -33, -33, 102, 73, -33,
- -33, 103, -33, 104, 105, 106, 107, 108, -33, 109,
- 52, 110, 129, 134, 82, 143, 83, -4, 12, 84,
- 111, 13, 14, 15, 16, 17, 18, 19, 20, 90,
- 91, 21, 22, 23, 24, 25, 26, 27, 28, 29,
- 30, 85, 86, 31, 188, 90, 91, 87, 99, -85,
- 101, 100, 32, -85, -85, -85, -85, -85, -85, -85,
- -85, 156, 198, -85, -85, 103, -85, -85, -85, -85,
- -85, -85, -85, 157, 163, 110, 158, 166, 101, 167,
- 168, 171, -52, -52, 144, -52, -52, -52, -52, 102,
- 91, -52, -52, 103, 118, 119, 120, 121, 172, 176,
- 183, 101, 185, 110, -76, -76, -76, -76, -76, -76,
- -76, -76, 122, 189, -76, -76, 103, 13, 14, 15,
- 16, 17, 18, 19, 20, 190, 110, 21, 22, 191,
- 193, 195, 196, 14, 15, 144, 17, 18, 19, 20,
- 197, 53, 21, 22, 51, 75, 125, 175, 32, 177,
- 178, 179, 93, 94, 95, 96, 97, 184, 137, 186,
- 170, 0, 98, 32, 0, 0, 0, 0, 192
+ 0, 3, 36, 42, 43, 44, 68, 86, 27, 28,
+ 84, 0, 1, 4, 5, 6, 7, 8, 9, 10,
+ 11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 27, 36, 45, 46, 48, 49, 50, 51,
+ 57, 58, 60, 64, 66, 69, 70, 72, 74, 75,
+ 76, 85, 44, 36, 43, 86, 36, 84, 36, 84,
+ 27, 90, 36, 84, 27, 27, 27, 28, 35, 40,
+ 88, 89, 36, 1, 1, 52, 52, 61, 63, 67,
+ 81, 73, 79, 36, 36, 36, 36, 36, 36, 88,
+ 88, 37, 38, 86, 29, 30, 31, 32, 33, 39,
+ 36, 36, 1, 12, 16, 18, 19, 20, 21, 22,
+ 23, 25, 27, 36, 47, 53, 54, 77, 78, 80,
+ 17, 18, 19, 20, 36, 47, 62, 78, 80, 46,
+ 59, 85, 46, 60, 65, 72, 85, 24, 36, 79,
+ 82, 46, 60, 71, 72, 85, 36, 47, 80, 34,
+ 88, 88, 89, 89, 89, 89, 89, 89, 36, 36,
+ 26, 84, 83, 84, 88, 27, 27, 89, 55, 1,
+ 13, 36, 84, 83, 27, 14, 87, 88, 87, 36,
+ 87, 87, 87, 87, 89, 27, 36, 36, 87, 36,
+ 87, 88, 36, 36, 36, 36, 36, 87, 39, 56,
+ 36, 36, 36, 84
};
-#define yypact_value_is_default(yystate) \
- ((yystate) == (-91))
-
-#define yytable_value_is_error(yytable_value) \
- YYID (0)
-
-static const yytype_int16 yycheck[] =
+ /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
{
- 1, 67, 68, 93, 94, 95, 96, 97, 98, 23,
- 10, 76, 13, 0, 15, 76, 81, 18, 108, 35,
- 81, 35, 3, 3, 90, 91, 33, 0, 1, 36,
- 37, 4, 5, 6, 7, 8, 9, 10, 11, 12,
- 106, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 26, 26, 35, 35, 35, 26, 27, 14,
- 35, 35, 35, 26, 27, 34, 78, 26, 80, 69,
- 39, 35, 137, 78, 164, 80, 137, 26, 27, 0,
- 1, 36, 37, 4, 5, 6, 7, 8, 9, 10,
- 11, 35, 158, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 104, 26, 26, 172, 77, 78, 26,
- 80, 35, 36, 37, 35, 0, 1, 1, 119, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 1, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 35, 26, 77, 78, 35, 80, 35, 0, 1, 35,
- 35, 4, 5, 6, 7, 8, 9, 10, 11, 36,
- 37, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 35, 35, 26, 35, 36, 37, 35, 35, 0,
- 1, 35, 35, 4, 5, 6, 7, 8, 9, 10,
- 11, 35, 193, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 35, 26, 26, 25, 1, 1, 13,
- 35, 26, 5, 6, 35, 8, 9, 10, 11, 12,
- 37, 14, 15, 16, 17, 18, 19, 20, 14, 35,
- 35, 1, 35, 26, 4, 5, 6, 7, 8, 9,
- 10, 11, 35, 35, 14, 15, 16, 4, 5, 6,
- 7, 8, 9, 10, 11, 35, 26, 14, 15, 35,
- 38, 35, 35, 5, 6, 35, 8, 9, 10, 11,
- 35, 7, 14, 15, 6, 37, 76, 159, 35, 161,
- 162, 163, 28, 29, 30, 31, 32, 169, 79, 171,
- 120, -1, 38, 35, -1, -1, -1, -1, 180
+ 0, 41, 42, 42, 43, 43, 44, 44, 44, 44,
+ 44, 44, 44, 44, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 46, 46, 46, 46, 46, 46, 47,
+ 47, 48, 49, 50, 51, 52, 52, 52, 52, 52,
+ 52, 52, 53, 53, 53, 53, 53, 53, 54, 55,
+ 55, 56, 56, 57, 58, 59, 60, 61, 61, 61,
+ 61, 61, 61, 62, 62, 62, 62, 63, 63, 64,
+ 65, 66, 67, 67, 67, 67, 68, 69, 70, 71,
+ 72, 73, 73, 73, 73, 74, 75, 76, 77, 78,
+ 79, 79, 79, 79, 80, 81, 81, 81, 82, 83,
+ 83, 84, 84, 85, 85, 85, 86, 86, 87, 87,
+ 88, 88, 88, 88, 88, 88, 88, 88, 88, 88,
+ 88, 89, 89, 90, 90
};
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
+ /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
{
- 0, 3, 35, 41, 42, 43, 67, 85, 26, 27,
- 83, 0, 1, 4, 5, 6, 7, 8, 9, 10,
- 11, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 26, 35, 44, 45, 47, 48, 49, 50, 56,
- 57, 59, 63, 65, 68, 69, 71, 73, 74, 75,
- 84, 43, 35, 42, 85, 35, 83, 35, 83, 26,
- 89, 35, 83, 26, 26, 26, 27, 34, 39, 87,
- 88, 35, 1, 1, 51, 51, 60, 62, 66, 80,
- 72, 78, 35, 35, 35, 35, 35, 35, 87, 87,
- 36, 37, 85, 28, 29, 30, 31, 32, 38, 35,
- 35, 1, 12, 16, 18, 19, 20, 21, 22, 24,
- 26, 35, 46, 52, 53, 76, 77, 79, 17, 18,
- 19, 20, 35, 46, 61, 77, 79, 45, 58, 84,
- 45, 59, 64, 71, 84, 23, 35, 78, 81, 45,
- 59, 70, 71, 84, 35, 46, 79, 33, 87, 87,
- 88, 88, 88, 88, 88, 88, 35, 35, 25, 83,
- 82, 83, 87, 26, 88, 54, 1, 13, 35, 83,
- 82, 26, 14, 86, 87, 86, 35, 86, 86, 86,
- 88, 26, 35, 35, 86, 35, 86, 87, 35, 35,
- 35, 35, 86, 38, 55, 35, 35, 35, 83
+ 0, 2, 2, 1, 2, 1, 0, 2, 2, 2,
+ 2, 4, 4, 3, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 3,
+ 2, 3, 2, 3, 2, 0, 2, 2, 2, 2,
+ 2, 2, 3, 4, 4, 4, 4, 5, 3, 0,
+ 3, 0, 2, 3, 2, 1, 3, 0, 2, 2,
+ 2, 2, 2, 4, 3, 2, 4, 0, 2, 3,
+ 1, 3, 0, 2, 2, 2, 3, 3, 3, 1,
+ 3, 0, 2, 2, 2, 3, 3, 2, 2, 2,
+ 0, 2, 2, 2, 4, 0, 2, 2, 2, 0,
+ 2, 1, 1, 2, 2, 2, 1, 2, 0, 2,
+ 1, 3, 3, 3, 3, 3, 3, 3, 2, 3,
+ 3, 1, 1, 0, 1
};
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. However,
- YYFAIL appears to be in use. Nevertheless, it is formally deprecated
- in Bison 2.4.2's NEWS entry, where a plan to phase it out is
- discussed. */
-
-#define YYFAIL goto yyerrlab
-#if defined YYFAIL
- /* This is here to suppress warnings from the GCC cpp's
- -Wunused-macros. Normally we don't worry about that warning, but
- some users do, and we want to make it easy for users to remove
- YYFAIL uses, which will produce warnings from Bison 2.5. */
-#endif
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
#define YYRECOVERING() (!!yyerrstatus)
@@ -855,55 +815,15 @@ do \
else \
{ \
yyerror (YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* This macro is provided for backward compatibility. */
-
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+ YYERROR; \
+ } \
+while (0)
+/* Error token number */
+#define YYTERROR 1
+#define YYERRCODE 256
-/* YYLEX -- calling `yylex' with the right arguments. */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
/* Enable debugging if requested. */
#if YYDEBUG
@@ -913,40 +833,36 @@ while (YYID (0))
# define YYFPRINTF fprintf
# endif
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (0)
+
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
+
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (0)
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT. |
+`----------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
{
FILE *yyo = yyoutput;
YYUSE (yyo);
@@ -955,14 +871,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
# ifdef YYPRINT
if (yytype < YYNTOKENS)
YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
# endif
- switch (yytype)
- {
- default:
- break;
- }
+ YYUSE (yytype);
}
@@ -970,22 +880,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
| Print this symbol on YYOUTPUT. |
`--------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
-#endif
{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+ YYFPRINTF (yyoutput, "%s %s (",
+ yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
yy_symbol_value_print (yyoutput, yytype, yyvaluep);
YYFPRINTF (yyoutput, ")");
@@ -996,16 +895,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
| TOP (included). |
`------------------------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
- yytype_int16 *yybottom;
- yytype_int16 *yytop;
-#endif
{
YYFPRINTF (stderr, "Stack now");
for (; yybottom <= yytop; yybottom++)
@@ -1016,49 +907,42 @@ yy_stack_print (yybottom, yytop)
YYFPRINTF (stderr, "\n");
}
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (0)
/*------------------------------------------------.
| Report that the YYRULE is going to be reduced. |
`------------------------------------------------*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
- YYSTYPE *yyvsp;
- int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
{
+ unsigned long int yylno = yyrline[yyrule];
int yynrhs = yyr2[yyrule];
int yyi;
- unsigned long int yylno = yyrline[yyrule];
YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
+ yyrule - 1, yylno);
/* The symbols being reduced. */
for (yyi = 0; yyi < yynrhs; yyi++)
{
YYFPRINTF (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- );
+ yy_symbol_print (stderr,
+ yystos[yyssp[yyi + 1 - yynrhs]],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ );
YYFPRINTF (stderr, "\n");
}
}
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
/* Nonzero means print parse trace. It is left uninitialized so that
multiple parsers can coexist. */
@@ -1072,7 +956,7 @@ int yydebug;
/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
+#ifndef YYINITDEPTH
# define YYINITDEPTH 200
#endif
@@ -1095,15 +979,8 @@ int yydebug;
# define yystrlen strlen
# else
/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static YYSIZE_T
yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
{
YYSIZE_T yylen;
for (yylen = 0; yystr[yylen]; yylen++)
@@ -1119,16 +996,8 @@ yystrlen (yystr)
# else
/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static char *
yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
{
char *yyd = yydest;
const char *yys = yysrc;
@@ -1158,27 +1027,27 @@ yytnamerr (char *yyres, const char *yystr)
char const *yyp = yystr;
for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
do_not_strip_quotes: ;
}
@@ -1201,12 +1070,11 @@ static int
yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
yytype_int16 *yyssp, int yytoken)
{
- YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+ YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
/* Internationalized format string. */
- const char *yyformat = YY_NULL;
+ const char *yyformat = YY_NULLPTR;
/* Arguments of yyformat. */
char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
/* Number of reported tokens (one for the "unexpected", one per
@@ -1214,10 +1082,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
int yycount = 0;
/* There are many possibilities here to consider:
- - Assume YYFAIL is not used. It's too flawed to consider. See
- <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
- for details. YYERROR is fine as it does not invoke this
- function.
- If this state is a consistent state with a default action, then
the only way this function was invoked is if the default action
is an error action. In that case, don't check for expected
@@ -1266,11 +1130,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
break;
}
yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
- if (! (yysize <= yysize1
- && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ {
+ YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+ if (! (yysize <= yysize1
+ && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
}
}
}
@@ -1290,10 +1156,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
# undef YYCASE_
}
- yysize1 = yysize + yystrlen (yyformat);
- if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
- return 2;
- yysize = yysize1;
+ {
+ YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+ if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+ return 2;
+ yysize = yysize1;
+ }
if (*yymsg_alloc < yysize)
{
@@ -1330,78 +1198,58 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
| Release the memory associated to this symbol. |
`-----------------------------------------------*/
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
-#endif
{
YYUSE (yyvaluep);
-
if (!yymsg)
yymsg = "Deleting";
YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
switch (yytype)
{
- case 57: /* "choice_entry" */
+ case 58: /* choice_entry */
- {
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
- if (current_menu == (yyvaluep->menu))
+ ((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+ if (current_menu == ((*yyvaluep).menu))
menu_end_menu();
-};
+}
+
+ break;
- break;
- case 63: /* "if_entry" */
+ case 64: /* if_entry */
- {
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
- if (current_menu == (yyvaluep->menu))
+ ((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+ if (current_menu == ((*yyvaluep).menu))
menu_end_menu();
-};
+}
- break;
- case 69: /* "menu_entry" */
+ break;
- {
+ case 70: /* menu_entry */
+
+ {
fprintf(stderr, "%s:%d: missing end statement for this entry\n",
- (yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
- if (current_menu == (yyvaluep->menu))
+ ((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+ if (current_menu == ((*yyvaluep).menu))
menu_end_menu();
-};
+}
+
+ break;
- break;
default:
- break;
+ break;
}
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
}
-/* Prevent warnings from -Wmissing-prototypes. */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
/* The lookahead symbol. */
@@ -1409,7 +1257,6 @@ int yychar;
/* The semantic value of the lookahead symbol. */
YYSTYPE yylval;
-
/* Number of syntax errors so far. */
int yynerrs;
@@ -1418,35 +1265,16 @@ int yynerrs;
| yyparse. |
`----------*/
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
int
yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
{
int yystate;
/* Number of tokens to shift before error messages enabled. */
int yyerrstatus;
/* The stacks and their tools:
- `yyss': related to states.
- `yyvs': related to semantic values.
+ 'yyss': related to states.
+ 'yyvs': related to semantic values.
Refer to the stacks through separate pointers, to allow yyoverflow
to reallocate them elsewhere. */
@@ -1466,7 +1294,7 @@ yyparse ()
int yyn;
int yyresult;
/* Lookahead token as an internal (translated) token number. */
- int yytoken;
+ int yytoken = 0;
/* The variables used to return semantic value and location from the
action routines. */
YYSTYPE yyval;
@@ -1484,9 +1312,8 @@ yyparse ()
Keep to zero when no symbol should be popped. */
int yylen = 0;
- yytoken = 0;
- yyss = yyssa;
- yyvs = yyvsa;
+ yyssp = yyss = yyssa;
+ yyvsp = yyvs = yyvsa;
yystacksize = YYINITDEPTH;
YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1495,14 +1322,6 @@ yyparse ()
yyerrstatus = 0;
yynerrs = 0;
yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
- yyssp = yyss;
- yyvsp = yyvs;
-
goto yysetstate;
/*------------------------------------------------------------.
@@ -1523,23 +1342,23 @@ yyparse ()
#ifdef yyoverflow
{
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
- &yystacksize);
-
- yyss = yyss1;
- yyvs = yyvs1;
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
}
#else /* no yyoverflow */
# ifndef YYSTACK_RELOCATE
@@ -1547,22 +1366,22 @@ yyparse ()
# else
/* Extend the stack our own way. */
if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
+ goto yyexhaustedlab;
yystacksize *= 2;
if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
+ yystacksize = YYMAXDEPTH;
{
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss_alloc, yyss);
- YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss_alloc, yyss);
+ YYSTACK_RELOCATE (yyvs_alloc, yyvs);
# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
}
# endif
#endif /* no yyoverflow */
@@ -1571,10 +1390,10 @@ yyparse ()
yyvsp = yyvs + yysize - 1;
YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
+ (unsigned long int) yystacksize));
if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
+ YYABORT;
}
YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1603,7 +1422,7 @@ yybackup:
if (yychar == YYEMPTY)
{
YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
+ yychar = yylex ();
}
if (yychar <= YYEOF)
@@ -1643,7 +1462,9 @@ yybackup:
yychar = YYEMPTY;
yystate = yyn;
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
goto yynewstate;
@@ -1666,7 +1487,7 @@ yyreduce:
yylen = yyr2[yyn];
/* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
+ '$$ = $1'.
Otherwise, the following line sets YYVAL to garbage.
This behavior is undocumented and Bison
@@ -1682,64 +1503,73 @@ yyreduce:
case 10:
{ zconf_error("unexpected end statement"); }
+
break;
case 11:
- { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); }
+ { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); }
+
break;
case 12:
{
- zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
+ zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
}
+
break;
case 13:
{ zconf_error("invalid statement"); }
+
break;
- case 28:
+ case 29:
+
+ { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); }
- { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); }
break;
- case 29:
+ case 30:
{ zconf_error("invalid option"); }
+
break;
- case 30:
+ case 31:
{
- struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+ struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+ printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
}
+
break;
- case 31:
+ case 32:
{
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 32:
+ case 33:
{
- struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+ struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
sym->flags |= SYMBOL_OPTIONAL;
menu_add_entry(sym);
- printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+ printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
}
+
break;
- case 33:
+ case 34:
{
if (current_entry->prompt)
@@ -1749,352 +1579,410 @@ yyreduce:
menu_end_entry();
printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 41:
+ case 42:
{
- menu_set_type((yyvsp[(1) - (3)].id)->stype);
+ menu_set_type((yyvsp[-2].id)->stype);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[(1) - (3)].id)->stype);
+ (yyvsp[-2].id)->stype);
}
+
break;
- case 42:
+ case 43:
{
- menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+ menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 43:
+ case 44:
{
- menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
- if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN)
- menu_set_type((yyvsp[(1) - (4)].id)->stype);
+ menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
+ if ((yyvsp[-3].id)->stype != S_UNKNOWN)
+ menu_set_type((yyvsp[-3].id)->stype);
printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[(1) - (4)].id)->stype);
+ (yyvsp[-3].id)->stype);
}
+
break;
- case 44:
+ case 45:
{
- menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+ menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 45:
+ case 46:
{
- menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
+ menu_add_symbol(P_IMPLY, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+ printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
+}
+
+ break;
+
+ case 47:
+
+ {
+ menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 48:
+ case 50:
{
- const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+ const struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string)));
if (id && id->flags & TF_OPTION)
- menu_add_option(id->token, (yyvsp[(3) - (3)].string));
+ menu_add_option(id->token, (yyvsp[0].string));
else
- zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string));
- free((yyvsp[(2) - (3)].string));
+ zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string));
+ free((yyvsp[-1].string));
}
+
break;
- case 49:
+ case 51:
{ (yyval.string) = NULL; }
+
break;
- case 50:
+ case 52:
+
+ { (yyval.string) = (yyvsp[0].string); }
- { (yyval.string) = (yyvsp[(2) - (2)].string); }
break;
- case 51:
+ case 53:
{
- struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
+ struct symbol *sym = sym_lookup((yyvsp[-1].string), SYMBOL_CHOICE);
sym->flags |= SYMBOL_AUTO;
menu_add_entry(sym);
menu_add_expr(P_CHOICE, NULL, NULL);
printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 52:
+ case 54:
{
(yyval.menu) = menu_add_menu();
}
+
break;
- case 53:
+ case 55:
{
- if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
+ if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
}
}
+
break;
- case 61:
+ case 63:
{
- menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+ menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 62:
+ case 64:
{
- if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
- menu_set_type((yyvsp[(1) - (3)].id)->stype);
+ if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
+ menu_set_type((yyvsp[-2].id)->stype);
printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
zconf_curname(), zconf_lineno(),
- (yyvsp[(1) - (3)].id)->stype);
+ (yyvsp[-2].id)->stype);
} else
YYERROR;
}
+
break;
- case 63:
+ case 65:
{
current_entry->sym->flags |= SYMBOL_OPTIONAL;
printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 64:
+ case 66:
{
- if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
- menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+ if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
+ menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:default\n",
zconf_curname(), zconf_lineno());
} else
YYERROR;
}
+
break;
- case 67:
+ case 69:
{
printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
menu_add_entry(NULL);
- menu_add_dep((yyvsp[(2) - (3)].expr));
+ menu_add_dep((yyvsp[-1].expr));
(yyval.menu) = menu_add_menu();
}
+
break;
- case 68:
+ case 70:
{
- if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
+ if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
}
}
+
break;
- case 74:
+ case 76:
{
- menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+ menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
}
+
break;
- case 75:
+ case 77:
{
menu_add_entry(NULL);
- menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+ menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 76:
+ case 78:
{
(yyval.menu) = menu_add_menu();
}
+
break;
- case 77:
+ case 79:
{
- if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
+ if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
menu_end_menu();
printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
}
}
+
break;
- case 83:
+ case 85:
{
- printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
- zconf_nextfile((yyvsp[(2) - (3)].string));
+ printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
+ zconf_nextfile((yyvsp[-1].string));
}
+
break;
- case 84:
+ case 86:
{
menu_add_entry(NULL);
- menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);
+ menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL);
printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
}
+
break;
- case 85:
+ case 87:
{
menu_end_entry();
}
+
break;
- case 86:
+ case 88:
{
printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
zconf_starthelp();
}
+
break;
- case 87:
+ case 89:
{
- current_entry->help = (yyvsp[(2) - (2)].string);
+ current_entry->help = (yyvsp[0].string);
}
+
break;
- case 92:
+ case 94:
{
- menu_add_dep((yyvsp[(3) - (4)].expr));
+ menu_add_dep((yyvsp[-1].expr));
printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
}
- break;
-
- case 96:
- {
- menu_add_visibility((yyvsp[(2) - (2)].expr));
-}
break;
case 98:
{
- menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
+ menu_add_visibility((yyvsp[0].expr));
}
- break;
- case 101:
-
- { (yyval.id) = (yyvsp[(1) - (2)].id); }
break;
- case 102:
+ case 100:
+
+ {
+ menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
+}
- { (yyval.id) = (yyvsp[(1) - (2)].id); }
break;
case 103:
- { (yyval.id) = (yyvsp[(1) - (2)].id); }
+ { (yyval.id) = (yyvsp[-1].id); }
+
break;
- case 106:
+ case 104:
+
+ { (yyval.id) = (yyvsp[-1].id); }
- { (yyval.expr) = NULL; }
break;
- case 107:
+ case 105:
+
+ { (yyval.id) = (yyvsp[-1].id); }
- { (yyval.expr) = (yyvsp[(2) - (2)].expr); }
break;
case 108:
- { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); }
+ { (yyval.expr) = NULL; }
+
break;
case 109:
- { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = (yyvsp[0].expr); }
+
break;
case 110:
- { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); }
+
break;
case 111:
- { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 112:
- { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 113:
- { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 114:
- { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+ { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 115:
- { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
+ { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 116:
- { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); }
+ { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
break;
case 117:
- { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+ { (yyval.expr) = (yyvsp[-1].expr); }
+
break;
case 118:
- { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+ { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); }
+
break;
case 119:
- { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); }
+ { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
break;
case 120:
- { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); }
+ { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
break;
case 121:
+ { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); }
+
+ break;
+
+ case 122:
+
+ { (yyval.symbol) = sym_lookup((yyvsp[0].string), SYMBOL_CONST); free((yyvsp[0].string)); }
+
+ break;
+
+ case 123:
+
{ (yyval.string) = NULL; }
+
break;
@@ -2120,7 +2008,7 @@ yyreduce:
*++yyvsp = yyval;
- /* Now `shift' the result of the reduction. Determine what state
+ /* Now 'shift' the result of the reduction. Determine what state
that goes to, based on the state we popped back to and the rule
number reduced by. */
@@ -2135,9 +2023,9 @@ yyreduce:
goto yynewstate;
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error. |
+`--------------------------------------*/
yyerrlab:
/* Make sure we have latest lookahead translation. See comments at
user semantic actions for why this is necessary. */
@@ -2188,20 +2076,20 @@ yyerrlab:
if (yyerrstatus == 3)
{
/* If just tried and failed to reuse lookahead token after an
- error, discard it. */
+ error, discard it. */
if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval);
- yychar = YYEMPTY;
- }
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval);
+ yychar = YYEMPTY;
+ }
}
/* Else will try to reuse lookahead token after shifting the error
@@ -2220,7 +2108,7 @@ yyerrorlab:
if (/*CONSTCOND*/ 0)
goto yyerrorlab;
- /* Do not reclaim the symbols of the rule which action triggered
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYERROR. */
YYPOPSTACK (yylen);
yylen = 0;
@@ -2233,35 +2121,37 @@ yyerrorlab:
| yyerrlab1 -- common code for both syntax error and YYERROR. |
`-------------------------------------------------------------*/
yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
for (;;)
{
yyn = yypact[yystate];
if (!yypact_value_is_default (yyn))
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
/* Pop the current state because it cannot handle the error token. */
if (yyssp == yyss)
- YYABORT;
+ YYABORT;
yydestruct ("Error: popping",
- yystos[yystate], yyvsp);
+ yystos[yystate], yyvsp);
YYPOPSTACK (1);
yystate = *yyssp;
YY_STACK_PRINT (yyss, yyssp);
}
+ YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
*++yyvsp = yylval;
+ YY_IGNORE_MAYBE_UNINITIALIZED_END
/* Shift the error token. */
@@ -2304,14 +2194,14 @@ yyreturn:
yydestruct ("Cleanup: discarding lookahead",
yytoken, &yylval);
}
- /* Do not reclaim the symbols of the rule which action triggered
+ /* Do not reclaim the symbols of the rule whose action triggered
this YYABORT or YYACCEPT. */
YYPOPSTACK (yylen);
YY_STACK_PRINT (yyss, yyssp);
while (yyssp != yyss)
{
yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp);
+ yystos[*yyssp], yyvsp);
YYPOPSTACK (1);
}
#ifndef yyoverflow
@@ -2322,14 +2212,11 @@ yyreturn:
if (yymsg != yymsgbuf)
YYSTACK_FREE (yymsg);
#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
+ return yyresult;
}
-
-
void conf_parse(const char *name)
{
struct symbol *sym;
@@ -2501,6 +2388,11 @@ static void print_symbol(FILE *out, struct menu *menu)
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
+ case P_IMPLY:
+ fputs( " imply ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
@@ -2577,4 +2469,3 @@ void zconfdump(FILE *out)
#include "expr.c"
#include "symbol.c"
#include "menu.c"
-
--
2.7.4
^ permalink raw reply related
* [PATCH 1/4] kconfig: introduce the "imply" keyword
From: Nicolas Pitre @ 2016-10-19 23:42 UTC (permalink / raw)
To: John Stultz, Richard Cochran, Yann E MORIN
Cc: Thomas Gleixner, Josh Triplett, netdev, linux-kbuild,
linux-kernel
In-Reply-To: <1476920573-14384-1-git-send-email-nicolas.pitre@linaro.org>
The "imply" keyword is a weak version of "select" where the target
config symbol can still be turned off, avoiding those pitfalls that come
with the "select" keyword.
This is useful e.g. with multiple drivers that want to indicate their
ability to hook into a given subsystem while still being able to
configure that subsystem out and keep those drivers selected.
Currently, the same effect can almost be achieved with:
config DRIVER_A
tristate
config DRIVER_B
tristate
config DRIVER_C
tristate
config DRIVER_D
tristate
[...]
config SUBSYSTEM_X
tristate
default DRIVER_A || DRIVER_B || DRIVER_C || DRIVER_D || [...]
This is unwieldly to maintain especially with a large number of drivers.
Furthermore, there is no easy way to restrict the choice for SUBSYSTEM_X
to y or n, excluding m, when some drivers are built-in. The "select"
keyword allows for excluding m, but it excludes n as well. Hence
this "imply" keyword. The above becomes:
config DRIVER_A
tristate
imply SUBSYSTEM_X
config DRIVER_B
tristate
imply SUBSYSTEM_X
[...]
config SUBSYSTEM_X
tristate
This is much cleaner, and way more flexible than "select". SUBSYSTEM_X
can still be configured out, and it can be set as a module when none of
the drivers are selected or all of them are also modular.
Signed-off-by: Nicolas Pitre <nico@linaro.org>
---
Documentation/kbuild/kconfig-language.txt | 28 ++++++++++++++++
scripts/kconfig/expr.h | 2 ++
| 55 ++++++++++++++++++++++---------
scripts/kconfig/symbol.c | 26 ++++++++++++++-
scripts/kconfig/zconf.gperf | 1 +
scripts/kconfig/zconf.y | 16 +++++++--
6 files changed, 109 insertions(+), 19 deletions(-)
diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index 069fcb3eef..c96127f648 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -113,6 +113,33 @@ applicable everywhere (see syntax).
That will limit the usefulness but on the other hand avoid
the illegal configurations all over.
+- weak reverse dependencies: "imply" <symbol> ["if" <expr>]
+ This is similar to "select" as it enforces a lower limit on another
+ symbol except that the "implied" config symbol's value may still be
+ set to n from a direct dependency or with a visible prompt.
+ Given the following example:
+
+ config FOO
+ tristate
+ imply BAZ
+
+ config BAZ
+ tristate
+ depends on BAr
+
+ The following values are possible:
+
+ FOO BAR BAR's default choice for BAZ
+ --------------- --------------- --------------- --------------
+ n y n N/m/y
+ m y m M/y/n
+ y y y Y/n
+ y n * N
+
+ This is useful e.g. with multiple drivers that want to indicate their
+ ability to hook into a given subsystem while still being able to
+ configure that subsystem out and keep those drivers selected.
+
- limiting menu display: "visible if" <expr>
This attribute is only applicable to menu blocks, if the condition is
false, the menu block is not displayed to the user (the symbols
@@ -481,6 +508,7 @@ historical issues resolved through these different solutions.
b) Match dependency semantics:
b1) Swap all "select FOO" to "depends on FOO" or,
b2) Swap all "depends on FOO" to "select FOO"
+ c) Consider the use of "imply" instead of "select"
The resolution to a) can be tested with the sample Kconfig file
Documentation/kbuild/Kconfig.recursion-issue-01 through the removal
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 973b6f7333..a73f762c48 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -85,6 +85,7 @@ struct symbol {
struct property *prop;
struct expr_value dir_dep;
struct expr_value rev_dep;
+ struct expr_value implied;
};
#define for_all_symbols(i, sym) for (i = 0; i < SYMBOL_HASHSIZE; i++) for (sym = symbol_hash[i]; sym; sym = sym->next) if (sym->type != S_OTHER)
@@ -136,6 +137,7 @@ enum prop_type {
P_DEFAULT, /* default y */
P_CHOICE, /* choice value */
P_SELECT, /* select BAR */
+ P_IMPLY, /* imply BAR */
P_RANGE, /* range 7..100 (for a symbol) */
P_ENV, /* value from environment variable */
P_SYMBOL, /* where a symbol is defined */
--git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index aed678e8a7..e9357931b4 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -233,6 +233,8 @@ static void sym_check_prop(struct symbol *sym)
{
struct property *prop;
struct symbol *sym2;
+ char *use;
+
for (prop = sym->prop; prop; prop = prop->next) {
switch (prop->type) {
case P_DEFAULT:
@@ -252,18 +254,20 @@ static void sym_check_prop(struct symbol *sym)
}
break;
case P_SELECT:
+ case P_IMPLY:
+ use = prop->type == P_SELECT ? "select" : "imply";
sym2 = prop_get_symbol(prop);
if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
prop_warn(prop,
- "config symbol '%s' uses select, but is "
- "not boolean or tristate", sym->name);
+ "config symbol '%s' uses %s, but is "
+ "not boolean or tristate", sym->name, use);
else if (sym2->type != S_UNKNOWN &&
sym2->type != S_BOOLEAN &&
sym2->type != S_TRISTATE)
prop_warn(prop,
- "'%s' has wrong type. 'select' only "
+ "'%s' has wrong type. '%s' only "
"accept arguments of boolean and "
- "tristate type", sym2->name);
+ "tristate type", sym2->name, use);
break;
case P_RANGE:
if (sym->type != S_INT && sym->type != S_HEX)
@@ -333,6 +337,10 @@ void menu_finalize(struct menu *parent)
struct symbol *es = prop_get_symbol(prop);
es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+ } else if (prop->type == P_IMPLY) {
+ struct symbol *es = prop_get_symbol(prop);
+ es->implied.expr = expr_alloc_or(es->implied.expr,
+ expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
}
}
}
@@ -612,13 +620,30 @@ static struct property *get_symbol_prop(struct symbol *sym)
return prop;
}
+static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
+ enum prop_type tok, const char *prefix)
+{
+ bool hit = false;
+ struct property *prop;
+
+ for_all_properties(sym, prop, tok) {
+ if (!hit) {
+ str_append(r, prefix);
+ hit = true;
+ } else
+ str_printf(r, " && ");
+ expr_gstr_print(prop->expr, r);
+ }
+ if (hit)
+ str_append(r, "\n");
+}
+
/*
* head is optional and may be NULL
*/
static void get_symbol_str(struct gstr *r, struct symbol *sym,
struct list_head *head)
{
- bool hit;
struct property *prop;
if (sym && sym->name) {
@@ -648,22 +673,20 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
}
}
- hit = false;
- for_all_properties(sym, prop, P_SELECT) {
- if (!hit) {
- str_append(r, " Selects: ");
- hit = true;
- } else
- str_printf(r, " && ");
- expr_gstr_print(prop->expr, r);
- }
- if (hit)
- str_append(r, "\n");
+ get_symbol_props_str(r, sym, P_SELECT, _(" Selects: "));
if (sym->rev_dep.expr) {
str_append(r, _(" Selected by: "));
expr_gstr_print(sym->rev_dep.expr, r);
str_append(r, "\n");
}
+
+ get_symbol_props_str(r, sym, P_IMPLY, _(" Implies: "));
+ if (sym->implied.expr) {
+ str_append(r, _(" Implied by: "));
+ expr_gstr_print(sym->implied.expr, r);
+ str_append(r, "\n");
+ }
+
str_append(r, "\n\n");
}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 2432298487..074fb66d9a 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -258,6 +258,15 @@ static void sym_calc_visibility(struct symbol *sym)
sym->rev_dep.tri = tri;
sym_set_changed(sym);
}
+ tri = no;
+ if (sym->implied.expr)
+ tri = expr_calc_value(sym->implied.expr);
+ if (tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ tri = yes;
+ if (sym->implied.tri != tri) {
+ sym->implied.tri = tri;
+ sym_set_changed(sym);
+ }
}
/*
@@ -397,6 +406,12 @@ void sym_calc_value(struct symbol *sym)
newval.tri = EXPR_AND(expr_calc_value(prop->expr),
prop->visible.tri);
}
+ if (sym->dir_dep.tri != no &&
+ sym->implied.tri != no) {
+ /* implied symbols have implied defaults */
+ sym->flags |= SYMBOL_WRITE;
+ newval.tri = EXPR_OR(newval.tri, sym->implied.tri);
+ }
}
calc_newval:
if (sym->dir_dep.tri == no && sym->rev_dep.tri != no) {
@@ -413,7 +428,8 @@ void sym_calc_value(struct symbol *sym)
}
newval.tri = EXPR_OR(newval.tri, sym->rev_dep.tri);
}
- if (newval.tri == mod && sym_get_type(sym) == S_BOOLEAN)
+ if (newval.tri == mod &&
+ (sym_get_type(sym) == S_BOOLEAN || sym->implied.tri == yes))
newval.tri = yes;
break;
case S_STRING:
@@ -498,6 +514,8 @@ bool sym_tristate_within_range(struct symbol *sym, tristate val)
return false;
if (sym->visible <= sym->rev_dep.tri)
return false;
+ if (sym->implied.tri == yes && val == mod)
+ return false;
if (sym_is_choice_value(sym) && sym->visible == yes)
return val == yes;
return val >= sym->rev_dep.tri && val <= sym->visible;
@@ -750,6 +768,10 @@ const char *sym_get_string_default(struct symbol *sym)
if (sym->type == S_BOOLEAN && val == mod)
val = yes;
+ /* adjust the default value if this symbol is implied by another */
+ if (val < sym->implied.tri)
+ val = sym->implied.tri;
+
switch (sym->type) {
case S_BOOLEAN:
case S_TRISTATE:
@@ -1352,6 +1374,8 @@ const char *prop_get_type_name(enum prop_type type)
return "choice";
case P_SELECT:
return "select";
+ case P_IMPLY:
+ return "imply";
case P_RANGE:
return "range";
case P_SYMBOL:
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index ac498f01b4..ead02edec9 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -38,6 +38,7 @@ int, T_TYPE, TF_COMMAND, S_INT
hex, T_TYPE, TF_COMMAND, S_HEX
string, T_TYPE, TF_COMMAND, S_STRING
select, T_SELECT, TF_COMMAND
+imply, T_IMPLY, TF_COMMAND
range, T_RANGE, TF_COMMAND
visible, T_VISIBLE, TF_COMMAND
option, T_OPTION, TF_COMMAND
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 71bf8bff69..001305fa08 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE];
static struct menu *current_menu, *current_entry;
%}
-%expect 30
+%expect 32
%union
{
@@ -62,6 +62,7 @@ static struct menu *current_menu, *current_entry;
%token <id>T_TYPE
%token <id>T_DEFAULT
%token <id>T_SELECT
+%token <id>T_IMPLY
%token <id>T_RANGE
%token <id>T_VISIBLE
%token <id>T_OPTION
@@ -124,7 +125,7 @@ stmt_list:
;
option_name:
- T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
+ T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_IMPLY | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
;
common_stmt:
@@ -216,6 +217,12 @@ config_option: T_SELECT T_WORD if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
};
+config_option: T_IMPLY T_WORD if_expr T_EOL
+{
+ menu_add_symbol(P_IMPLY, sym_lookup($2, 0), $3);
+ printd(DEBUG_PARSE, "%s:%d:imply\n", zconf_curname(), zconf_lineno());
+};
+
config_option: T_RANGE symbol symbol if_expr T_EOL
{
menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
@@ -664,6 +671,11 @@ static void print_symbol(FILE *out, struct menu *menu)
expr_fprint(prop->expr, out);
fputc('\n', out);
break;
+ case P_IMPLY:
+ fputs( " imply ", out);
+ expr_fprint(prop->expr, out);
+ fputc('\n', out);
+ break;
case P_RANGE:
fputs( " range ", out);
expr_fprint(prop->expr, out);
--
2.7.4
^ permalink raw reply related
* [PATCH 0/4] make POSIX timers optional with some Kconfig help
From: Nicolas Pitre @ 2016-10-19 23:42 UTC (permalink / raw)
To: John Stultz, Richard Cochran, Yann E MORIN
Cc: Thomas Gleixner, Josh Triplett, netdev, linux-kbuild,
linux-kernel
Many embedded systems don't need the full POSIX timer support.
Configuring them out provides a nice kernel image size reduction.
When POSIX timers are configured out, the PTP clock subsystem should be
left out as well. However a bunch of ethernet drivers currently *select*
the later in their Kconfig entries. Therefore some more work was needed
to break that hard dependency from those drivers without preventing their
usage altogether.
Therefore this series also includes kconfig changes to implement a new
keyword to express some reverse dependencies like "select" does, named
"imply", and still allowing for the target config symbol to be disabled
if the user or a direct dependency says so.
How to deal with the dependencies across three subsystems for potential
upstream merging needs to be figured out.
The bulk of the diffstat comes from the kconfig lex parser regeneration.
diffstat:
Documentation/kbuild/kconfig-language.txt | 28 +
drivers/Makefile | 2 +-
drivers/net/ethernet/adi/Kconfig | 2 +-
drivers/net/ethernet/amd/Kconfig | 2 +-
drivers/net/ethernet/amd/xgbe/xgbe-main.c | 6 +-
drivers/net/ethernet/broadcom/Kconfig | 4 +-
drivers/net/ethernet/cavium/Kconfig | 2 +-
drivers/net/ethernet/freescale/Kconfig | 2 +-
drivers/net/ethernet/intel/Kconfig | 10 +-
drivers/net/ethernet/mellanox/mlx4/Kconfig | 2 +-
drivers/net/ethernet/mellanox/mlx5/core/Kconfig | 2 +-
drivers/net/ethernet/renesas/Kconfig | 2 +-
drivers/net/ethernet/samsung/Kconfig | 2 +-
drivers/net/ethernet/sfc/Kconfig | 2 +-
drivers/net/ethernet/stmicro/stmmac/Kconfig | 2 +-
drivers/net/ethernet/ti/Kconfig | 2 +-
drivers/net/ethernet/tile/Kconfig | 2 +-
drivers/ptp/Kconfig | 10 +-
include/linux/posix-timers.h | 28 +-
include/linux/ptp_clock_kernel.h | 65 +-
include/linux/sched.h | 10 +
init/Kconfig | 17 +
kernel/signal.c | 4 +
kernel/time/Makefile | 10 +-
kernel/time/posix-stubs.c | 118 ++
scripts/kconfig/expr.h | 2 +
scripts/kconfig/menu.c | 55 +-
scripts/kconfig/symbol.c | 26 +-
scripts/kconfig/zconf.gperf | 1 +
scripts/kconfig/zconf.hash.c_shipped | 30 +-
scripts/kconfig/zconf.tab.c_shipped | 1581 ++++++++---------
scripts/kconfig/zconf.y | 16 +-
32 files changed, 1115 insertions(+), 932 deletions(-)
^ permalink raw reply
* Re: [Patch net] ipv6: fix a potential deadlock in do_ipv6_setsockopt()
From: Cong Wang @ 2016-10-19 23:41 UTC (permalink / raw)
To: Eric Dumazet
Cc: Linux Kernel Network Developers, Baozeng Ding,
Marcelo Ricardo Leitner
In-Reply-To: <1476920329.5650.77.camel@edumazet-glaptop3.roam.corp.google.com>
On Wed, Oct 19, 2016 at 4:38 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
>> index 46ad699..b8c8d20 100644
>> --- a/net/ipv6/af_inet6.c
>> +++ b/net/ipv6/af_inet6.c
>> @@ -414,7 +414,9 @@ int inet6_release(struct socket *sock)
>> return -EINVAL;
>>
>> /* Free mc lists */
>> + rtnl_lock();
>
> Certainly not.
>
> Some people want IPv6 being reasonably fast.
Oh, good catch, I should move the 'if' check out too...
^ permalink raw reply
* Re: [Patch net] ipv6: fix a potential deadlock in do_ipv6_setsockopt()
From: Eric Dumazet @ 2016-10-19 23:38 UTC (permalink / raw)
To: Cong Wang; +Cc: netdev, sploving1, Marcelo Ricardo Leitner
In-Reply-To: <1476901218-15635-1-git-send-email-xiyou.wangcong@gmail.com>
On Wed, 2016-10-19 at 11:20 -0700, Cong Wang wrote:
> Baozeng reported this deadlock case:
>
> CPU0 CPU1
> ---- ----
> lock([ 165.136033] sk_lock-AF_INET6);
> lock([ 165.136033] rtnl_mutex);
> lock([ 165.136033] sk_lock-AF_INET6);
> lock([ 165.136033] rtnl_mutex);
>
> Similar to commit 87e9f0315952
> ("ipv4: fix a potential deadlock in mcast getsockopt() path")
> this is due to we still have a case, ipv6_sock_mc_close(),
> where we acquire sk_lock before rtnl_lock. Close this deadlock
> with the similar solution, that is always acquire rtnl lock first.
>
> Fixes: baf606d9c9b1 ("ipv4,ipv6: grab rtnl before locking the socket")
> Reported-by: Baozeng Ding <sploving1@gmail.com>
> Tested-by: Baozeng Ding <sploving1@gmail.com>
> Cc: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
> ---
> net/ipv6/af_inet6.c | 2 ++
> net/ipv6/ipv6_sockglue.c | 1 +
> net/ipv6/mcast.c | 4 ++--
> 3 files changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
> index 46ad699..b8c8d20 100644
> --- a/net/ipv6/af_inet6.c
> +++ b/net/ipv6/af_inet6.c
> @@ -414,7 +414,9 @@ int inet6_release(struct socket *sock)
> return -EINVAL;
>
> /* Free mc lists */
> + rtnl_lock();
Certainly not.
Some people want IPv6 being reasonably fast.
> ipv6_sock_mc_close(sk);
> + rtnl_unlock();
>
^ permalink raw reply
* [PATCH v4 net-next 4/7] udp: UDP flow dissector
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161019230309.3746853-1-tom@herbertland.com>
Add infrastructure for performing per protocol flow dissection and
support flow dissection in UDP payloads (e.g. flow dissection on a
UDP encapsulated tunnel.
The per protocol flow dissector is called by flow_dissect function
in the offload_callbacks of a protocol. The arguments of this function
include the necessary information to do flow dissection as derived
from __skb_flow_dissect which is where the callback is intended to be
called from. There are return codes from the callback in the form
FLOW_DIS_RET_* that indicate the result. FLOW_DIS_RET_IPPROTO
means that the payload should be dissected as an IP proto, the
specific protocol is returned in a pointer argument. Likewise,
FLOW_DIS_RET_PROTO indicate the payload should be processed as
an ethertype which is returned in another argument.
A case for IPPROTO_UDP was added to __skb_flow_dissect. Since
UDP flow dissector involves a relatively expensive socket lookup
there is a static key check first to see if there are any sockets
that have enabled flow dissection. After this check, the offload
ops for UDP for either IPv4 or IPv6 is considered. If the
flow_dissect function is it is called. Upon return the result
is processed (pass, out_bad, process as IP protocol, process
as ethertype). Note that if the result indicates a protocol must
be processed it is expected that nhoff has been updated to the
encapsulated protocol header.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/linux/netdevice.h | 5 +++
include/linux/udp.h | 7 ++++
include/net/flow_dissector.h | 8 +++++
include/net/udp.h | 4 +++
net/core/flow_dissector.c | 85 ++++++++++++++++++++++++++++++++++++++++++--
net/ipv4/udp.c | 3 ++
6 files changed, 110 insertions(+), 2 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index bf341b6..ad0d4f4 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2203,6 +2203,11 @@ struct offload_callbacks {
struct sk_buff **(*gro_receive)(struct sk_buff **head,
struct sk_buff *skb);
int (*gro_complete)(struct sk_buff *skb, int nhoff);
+ int (*flow_dissect)(const struct sk_buff *skb,
+ void *data, int hlen,
+ int *nhoff, u8 *ip_proto,
+ __be16 *proto,
+ const struct flow_dissector_key_addrs *key_addrs);
};
struct packet_offload {
diff --git a/include/linux/udp.h b/include/linux/udp.h
index d1fd8cd..608ebf4 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -79,6 +79,13 @@ struct udp_sock {
int (*gro_complete)(struct sock *sk,
struct sk_buff *skb,
int nhoff);
+
+ /* Flow dissector function for UDP socket */
+ int (*flow_dissect)(struct sock *sk,
+ const struct sk_buff *skb,
+ void *data, int hlen,
+ int *nhoff, u8 *ip_proto,
+ __be16 *proto);
};
static inline struct udp_sock *udp_sk(const struct sock *sk)
diff --git a/include/net/flow_dissector.h b/include/net/flow_dissector.h
index d953492..9de4904 100644
--- a/include/net/flow_dissector.h
+++ b/include/net/flow_dissector.h
@@ -203,4 +203,12 @@ static inline void *skb_flow_dissector_target(struct flow_dissector *flow_dissec
return ((char *)target_container) + flow_dissector->offset[key_id];
}
+/* Return codes from per socket flow dissector (e.g. UDP) */
+enum {
+ FLOW_DIS_RET_PASS = 0,
+ FLOW_DIS_RET_BAD,
+ FLOW_DIS_RET_IPPROTO,
+ FLOW_DIS_RET_PROTO,
+};
+
#endif
diff --git a/include/net/udp.h b/include/net/udp.h
index 717a972..8d364e8 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -360,4 +360,8 @@ void udp_encap_enable(void);
#if IS_ENABLED(CONFIG_IPV6)
void udpv6_encap_enable(void);
#endif
+
+void udp_flow_dissect_enable(void);
+void udp_flow_dissect_disable(void);
+
#endif /* _UDP_H */
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 919bd02..06ccfd5 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -8,6 +8,8 @@
#include <net/ipv6.h>
#include <net/gre.h>
#include <net/pptp.h>
+#include <net/protocol.h>
+#include <net/udp.h>
#include <linux/igmp.h>
#include <linux/icmp.h>
#include <linux/sctp.h>
@@ -57,6 +59,20 @@ void skb_flow_dissector_init(struct flow_dissector *flow_dissector,
}
EXPORT_SYMBOL(skb_flow_dissector_init);
+static struct static_key udp_flow_dissect __read_mostly;
+
+void udp_flow_dissect_enable(void)
+{
+ static_key_slow_inc(&udp_flow_dissect);
+}
+EXPORT_SYMBOL(udp_flow_dissect_enable);
+
+void udp_flow_dissect_disable(void)
+{
+ static_key_slow_dec(&udp_flow_dissect);
+}
+EXPORT_SYMBOL(udp_flow_dissect_disable);
+
/**
* __skb_flow_get_ports - extract the upper layer ports and return them
* @skb: sk_buff to extract the ports from
@@ -131,7 +147,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
{
struct flow_dissector_key_control *key_control;
struct flow_dissector_key_basic *key_basic;
- struct flow_dissector_key_addrs *key_addrs;
+ struct flow_dissector_key_addrs *key_addrs = NULL;
struct flow_dissector_key_ports *key_ports;
struct flow_dissector_key_tags *key_tags;
struct flow_dissector_key_vlan *key_vlan;
@@ -262,7 +278,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
}
case htons(ETH_P_8021AD):
case htons(ETH_P_8021Q): {
- const struct vlan_hdr *vlan;
+ const struct vlan_hdr *vlan = NULL;
if (skb_vlan_tag_present(skb))
proto = skb->protocol;
@@ -552,6 +568,71 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
case IPPROTO_MPLS:
proto = htons(ETH_P_MPLS_UC);
DISSECT_AGAIN(mpls);
+ case IPPROTO_UDP:
+ {
+ const struct net_offload **offloads;
+ const struct net_offload *ops;
+ int ret;
+
+ if (!static_key_false(&udp_flow_dissect))
+ break;
+
+ if (depth) {
+ /* Only try to parse the UDP encapsulation if no
+ * encapsulation has been encountered yet. With an
+ * encapsulated packet there is a good chance that it is
+ * in a different namespace so the UDP lookup to get
+ * flow dissection may be invalid.
+ */
+ break;
+ }
+
+ if (!key_addrs)
+ break;
+
+ /* See if there is a flow dissector for UDP protocol */
+
+ switch (key_control->addr_type) {
+#ifdef CONFIG_INET
+ case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
+ offloads = inet_offloads;
+ break;
+ case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
+ offloads = inet6_offloads;
+ break;
+#endif
+ default:
+ goto udp_finish;
+ }
+
+ rcu_read_lock();
+
+ ops = rcu_dereference(offloads[IPPROTO_UDP]);
+
+ if (!ops || !ops->callbacks.flow_dissect) {
+ rcu_read_unlock();
+ goto udp_finish;
+ }
+
+ ret = ops->callbacks.flow_dissect(skb, data, hlen, &nhoff,
+ &ip_proto, &proto, key_addrs);
+
+ rcu_read_unlock();
+
+ switch (ret) {
+ case FLOW_DIS_RET_IPPROTO:
+ DISSECT_AGAIN(ip_proto_again);
+ case FLOW_DIS_RET_PROTO:
+ DISSECT_AGAIN(again);
+ case FLOW_DIS_RET_BAD:
+ goto out_bad;
+ case FLOW_DIS_RET_PASS:
+ default:
+ break;
+ }
+udp_finish:
+ break;
+ }
default:
break;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 7f84c51..b4b528e 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1977,6 +1977,9 @@ void udp_destroy_sock(struct sock *sk)
if (encap_destroy)
encap_destroy(sk);
}
+
+ if (up->flow_dissect)
+ udp_flow_dissect_disable();
}
/*
--
2.9.3
^ permalink raw reply related
* [PATCH v4 net-next 2/7] flow_dissector: Limit processing of next encaps and extensions
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161019230309.3746853-1-tom@herbertland.com>
Flow dissector does not limit the number of encapsulated packets or IPv6
header extensions that will be processed. This could easily be
suceptible to DOS attack-- for instance a 1500 byte packet could contain
75 IPIP headers.
This patch places limits on the number of encapsulations and IPv6 extension
headers that are processed in flow dissector
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/core/flow_dissector.c | 37 +++++++++++++++++++++++++++----------
1 file changed, 27 insertions(+), 10 deletions(-)
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 1a7b80f..919bd02 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -91,6 +91,22 @@ __be32 __skb_flow_get_ports(const struct sk_buff *skb, int thoff, u8 ip_proto,
}
EXPORT_SYMBOL(__skb_flow_get_ports);
+#define MAX_DISSECT_DEPTH 10
+#define MAX_DISSECT_EXT 10
+
+#define __DISSECT_AGAIN(_target, _depth, _limit) do { \
+ (_depth)++; \
+ if ((_depth) > (_limit)) \
+ goto out_good; \
+ else \
+ goto _target; \
+} while (0)
+
+#define DISSECT_AGAIN(target) \
+ __DISSECT_AGAIN(target, depth, MAX_DISSECT_DEPTH)
+#define DISSECT_AGAIN_EXT(target) \
+ __DISSECT_AGAIN(target, ext_cnt, MAX_DISSECT_EXT)
+
/**
* __skb_flow_dissect - extract the flow_keys struct and return it
* @skb: sk_buff to extract the flow from, can be NULL if the rest are specified
@@ -123,6 +139,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
bool skip_vlan = false;
u8 ip_proto = 0;
bool ret = false;
+ int depth = 0, ext_cnt = 0;
if (!data) {
data = skb->data;
@@ -262,7 +279,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
proto = vlan->h_vlan_encapsulated_proto;
nhoff += sizeof(*vlan);
if (skip_vlan)
- goto again;
+ DISSECT_AGAIN(again);
}
skip_vlan = true;
@@ -285,7 +302,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
}
}
- goto again;
+ DISSECT_AGAIN(again);
}
case htons(ETH_P_PPP_SES): {
struct {
@@ -299,9 +316,9 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
nhoff += PPPOE_SES_HLEN;
switch (proto) {
case htons(PPP_IP):
- goto ip;
+ DISSECT_AGAIN(ip);
case htons(PPP_IPV6):
- goto ipv6;
+ DISSECT_AGAIN(ipv6);
default:
goto out_bad;
}
@@ -472,7 +489,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
goto out_good;
- goto again;
+ DISSECT_AGAIN(again);
}
case NEXTHDR_HOP:
case NEXTHDR_ROUTING:
@@ -490,7 +507,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
ip_proto = opthdr[0];
nhoff += (opthdr[1] + 1) << 3;
- goto ip_proto_again;
+ DISSECT_AGAIN_EXT(ip_proto_again);
}
case NEXTHDR_FRAGMENT: {
struct frag_hdr _fh, *fh;
@@ -512,7 +529,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (!(fh->frag_off & htons(IP6_OFFSET))) {
key_control->flags |= FLOW_DIS_FIRST_FRAG;
if (flags & FLOW_DISSECTOR_F_PARSE_1ST_FRAG)
- goto ip_proto_again;
+ DISSECT_AGAIN_EXT(ip_proto_again);
}
goto out_good;
}
@@ -523,7 +540,7 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
goto out_good;
- goto ip;
+ DISSECT_AGAIN(ip);
case IPPROTO_IPV6:
proto = htons(ETH_P_IPV6);
@@ -531,10 +548,10 @@ bool __skb_flow_dissect(const struct sk_buff *skb,
if (flags & FLOW_DISSECTOR_F_STOP_AT_ENCAP)
goto out_good;
- goto ipv6;
+ DISSECT_AGAIN(ipv6);
case IPPROTO_MPLS:
proto = htons(ETH_P_MPLS_UC);
- goto mpls;
+ DISSECT_AGAIN(mpls);
default:
break;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v4 net-next 5/7] udp: Add UDP flow dissection functions to IPv4 and IPv6
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161019230309.3746853-1-tom@herbertland.com>
Add per protocol offload callbacks for flow_dissect to UDP for
IPv4 and IPv6. The callback functions extract the port number
information and with the packet addresses (given in an argument with
type flow_dissector_key_addrs) it performs a lookup on the UDP
socket. If a socket is found and flow_dissect is set for the
socket then that function is called.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
net/ipv4/udp_offload.c | 39 +++++++++++++++++++++++++++++++++++++++
net/ipv6/udp_offload.c | 40 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 78 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index f9333c9..b4631e7 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -377,11 +377,50 @@ static int udp4_gro_complete(struct sk_buff *skb, int nhoff)
return udp_gro_complete(skb, nhoff, udp4_lib_lookup_skb);
}
+/* Assumes rcu lock is held */
+static int udp4_flow_dissect(const struct sk_buff *skb, void *data, int hlen,
+ int *nhoff, u8 *ip_proto, __be16 *proto,
+ const struct flow_dissector_key_addrs *key_addrs)
+{
+ u16 _ports[2], *ports;
+ struct net *net;
+ struct sock *sk;
+ int dif = -1;
+
+ /* See if there is a flow dissector in the UDP socket */
+
+ if (skb->dev) {
+ net = dev_net(skb->dev);
+ dif = skb->dev->ifindex;
+ } else if (skb->sk) {
+ net = sock_net(skb->sk);
+ } else {
+ return FLOW_DIS_RET_PASS;
+ }
+
+ ports = __skb_header_pointer(skb, *nhoff, sizeof(_ports),
+ data, hlen, &_ports);
+ if (!ports)
+ return FLOW_DIS_RET_BAD;
+
+ sk = udp4_lib_lookup_noref(net,
+ key_addrs->v4addrs.src, ports[0],
+ key_addrs->v4addrs.dst, ports[1],
+ dif);
+
+ if (sk && udp_sk(sk)->flow_dissect)
+ return udp_sk(sk)->flow_dissect(sk, skb, data, hlen, nhoff,
+ ip_proto, proto);
+ else
+ return FLOW_DIS_RET_PASS;
+}
+
static const struct net_offload udpv4_offload = {
.callbacks = {
.gso_segment = udp4_ufo_fragment,
.gro_receive = udp4_gro_receive,
.gro_complete = udp4_gro_complete,
+ .flow_dissect = udp4_flow_dissect,
},
};
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
index ac858c4..12d9a92 100644
--- a/net/ipv6/udp_offload.c
+++ b/net/ipv6/udp_offload.c
@@ -1,5 +1,5 @@
/*
- * IPV6 GSO/GRO offload support
+ * ipv6 gso/gro offload support
* Linux INET6 implementation
*
* This program is free software; you can redistribute it and/or
@@ -163,11 +163,49 @@ static int udp6_gro_complete(struct sk_buff *skb, int nhoff)
return udp_gro_complete(skb, nhoff, udp6_lib_lookup_skb);
}
+/* Assumes rcu lock is held */
+static int udp6_flow_dissect(const struct sk_buff *skb, void *data, int hlen,
+ int *nhoff, u8 *ip_proto, __be16 *proto,
+ const struct flow_dissector_key_addrs *key_addrs)
+{
+ u16 _ports[2], *ports;
+ struct net *net;
+ struct sock *sk;
+ int dif = -1;
+
+ /* See if there is a flow dissector in the UDP socket */
+
+ if (skb->dev) {
+ net = dev_net(skb->dev);
+ dif = skb->dev->ifindex;
+ } else if (skb->sk) {
+ net = sock_net(skb->sk);
+ } else {
+ return FLOW_DIS_RET_PASS;
+ }
+
+ ports = __skb_header_pointer(skb, *nhoff, sizeof(_ports),
+ data, hlen, &_ports);
+ if (!ports)
+ return FLOW_DIS_RET_BAD;
+
+ sk = udp6_lib_lookup_noref(net,
+ &key_addrs->v6addrs.src, ports[0],
+ &key_addrs->v6addrs.dst, ports[1],
+ dif);
+
+ if (sk && udp_sk(sk)->flow_dissect)
+ return udp_sk(sk)->flow_dissect(sk, skb, data, hlen, nhoff,
+ ip_proto, proto);
+ return FLOW_DIS_RET_PASS;
+}
+
static const struct net_offload udpv6_offload = {
.callbacks = {
.gso_segment = udp6_ufo_fragment,
.gro_receive = udp6_gro_receive,
.gro_complete = udp6_gro_complete,
+ .flow_dissect = udp6_flow_dissect,
},
};
--
2.9.3
^ permalink raw reply related
* [PATCH v4 net-next 6/7] udp: UDP tunnel flow dissection infrastructure
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161019230309.3746853-1-tom@herbertland.com>
Add infrastructure to allow UDP tunnels to setup flow dissecion.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/udp_tunnel.h | 5 +++++
net/ipv4/udp_tunnel.c | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h
index 02c5be0..81d2584 100644
--- a/include/net/udp_tunnel.h
+++ b/include/net/udp_tunnel.h
@@ -69,6 +69,10 @@ typedef struct sk_buff **(*udp_tunnel_gro_receive_t)(struct sock *sk,
struct sk_buff *skb);
typedef int (*udp_tunnel_gro_complete_t)(struct sock *sk, struct sk_buff *skb,
int nhoff);
+typedef int (*udp_tunnel_flow_dissect_t)(struct sock *sk,
+ const struct sk_buff *skb,
+ void *data, int hlen, int *nhoff,
+ u8 *ip_proto, __be16 *proto);
struct udp_tunnel_sock_cfg {
void *sk_user_data; /* user data used by encap_rcv call back */
@@ -78,6 +82,7 @@ struct udp_tunnel_sock_cfg {
udp_tunnel_encap_destroy_t encap_destroy;
udp_tunnel_gro_receive_t gro_receive;
udp_tunnel_gro_complete_t gro_complete;
+ udp_tunnel_flow_dissect_t flow_dissect;
};
/* Setup the given (UDP) sock to receive UDP encapsulated packets */
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c
index 58bd39f..4459288 100644
--- a/net/ipv4/udp_tunnel.c
+++ b/net/ipv4/udp_tunnel.c
@@ -72,6 +72,11 @@ void setup_udp_tunnel_sock(struct net *net, struct socket *sock,
udp_sk(sk)->gro_receive = cfg->gro_receive;
udp_sk(sk)->gro_complete = cfg->gro_complete;
+ if (cfg->flow_dissect) {
+ udp_sk(sk)->flow_dissect = cfg->flow_dissect;
+ udp_flow_dissect_enable();
+ }
+
udp_tunnel_encap_enable(sock);
}
EXPORT_SYMBOL_GPL(setup_udp_tunnel_sock);
--
2.9.3
^ permalink raw reply related
* [PATCH v4 net-next 7/7] fou: Support flow dissection
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161019230309.3746853-1-tom@herbertland.com>
This patch performs flow dissection for GUE and FOU. This is an
optional feature on the receiver and is set by FOU_ATTR_DEEP_HASH
netlink configuration. When enable the UDP socket flow_dissect
function is set to fou_flow_dissect or gue_flow_dissect as
appropriate. These functions return FLOW_DIS_RET_IPPROTO and
set ip protocol argument. In the case of GUE the header is
parsed to find the protocol number.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/uapi/linux/fou.h | 1 +
net/ipv4/fou.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 68 insertions(+), 1 deletion(-)
diff --git a/include/uapi/linux/fou.h b/include/uapi/linux/fou.h
index d2947c5..2c837eb 100644
--- a/include/uapi/linux/fou.h
+++ b/include/uapi/linux/fou.h
@@ -15,6 +15,7 @@ enum {
FOU_ATTR_IPPROTO, /* u8 */
FOU_ATTR_TYPE, /* u8 */
FOU_ATTR_REMCSUM_NOPARTIAL, /* flag */
+ FOU_ATTR_DEEP_HASH, /* flag */
__FOU_ATTR_MAX,
};
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
index cf50f7e..95ac5a8 100644
--- a/net/ipv4/fou.c
+++ b/net/ipv4/fou.c
@@ -27,7 +27,8 @@ struct fou {
struct rcu_head rcu;
};
-#define FOU_F_REMCSUM_NOPARTIAL BIT(0)
+#define FOU_F_REMCSUM_NOPARTIAL BIT(0)
+#define FOU_F_DEEP_HASH BIT(1)
struct fou_cfg {
u16 type;
@@ -281,6 +282,16 @@ static int fou_gro_complete(struct sock *sk, struct sk_buff *skb,
return err;
}
+static int fou_flow_dissect(struct sock *sk, const struct sk_buff *skb,
+ void *data, int hlen, int *nhoff, u8 *ip_proto,
+ __be16 *proto)
+{
+ *ip_proto = fou_from_sock(sk)->protocol;
+ *nhoff += sizeof(struct udphdr);
+
+ return FLOW_DIS_RET_IPPROTO;
+}
+
static struct guehdr *gue_gro_remcsum(struct sk_buff *skb, unsigned int off,
struct guehdr *guehdr, void *data,
size_t hdrlen, struct gro_remcsum *grc,
@@ -498,6 +509,48 @@ static int gue_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
return err;
}
+static int gue_flow_dissect(struct sock *sk, const struct sk_buff *skb,
+ void *data, int hlen, int *nhoff, u8 *ip_proto,
+ __be16 *proto)
+{
+ struct guehdr _hdr, *hdr;
+
+ hdr = __skb_header_pointer(skb, *nhoff + sizeof(struct udphdr),
+ sizeof(_hdr), data, hlen, &_hdr);
+ if (!hdr)
+ return FLOW_DIS_RET_BAD;
+
+ switch (hdr->version) {
+ case 0: /* Full GUE header present */
+ if (hdr->control)
+ return FLOW_DIS_RET_PASS;
+
+ *nhoff += sizeof(struct udphdr) + sizeof(_hdr) +
+ (hdr->hlen << 2);
+ *ip_proto = hdr->proto_ctype;
+
+ return FLOW_DIS_RET_IPPROTO;
+ case 1:
+ /* Direct encasulation of IPv4 or IPv6 */
+
+ switch (((struct iphdr *)hdr)->version) {
+ case 4:
+ *nhoff += sizeof(struct udphdr);
+ *ip_proto = IPPROTO_IPIP;
+ return FLOW_DIS_RET_IPPROTO;
+ case 6:
+ *nhoff += sizeof(struct udphdr);
+ *ip_proto = IPPROTO_IPV6;
+ return FLOW_DIS_RET_IPPROTO;
+ default:
+ return FLOW_DIS_RET_PASS;
+ }
+
+ default:
+ return FLOW_DIS_RET_PASS;
+ }
+}
+
static int fou_add_to_port_list(struct net *net, struct fou *fou)
{
struct fou_net *fn = net_generic(net, fou_net_id);
@@ -568,12 +621,16 @@ static int fou_create(struct net *net, struct fou_cfg *cfg,
tunnel_cfg.encap_rcv = fou_udp_recv;
tunnel_cfg.gro_receive = fou_gro_receive;
tunnel_cfg.gro_complete = fou_gro_complete;
+ if (cfg->flags & FOU_F_DEEP_HASH)
+ tunnel_cfg.flow_dissect = fou_flow_dissect;
fou->protocol = cfg->protocol;
break;
case FOU_ENCAP_GUE:
tunnel_cfg.encap_rcv = gue_udp_recv;
tunnel_cfg.gro_receive = gue_gro_receive;
tunnel_cfg.gro_complete = gue_gro_complete;
+ if (cfg->flags & FOU_F_DEEP_HASH)
+ tunnel_cfg.flow_dissect = gue_flow_dissect;
break;
default:
err = -EINVAL;
@@ -637,6 +694,7 @@ static const struct nla_policy fou_nl_policy[FOU_ATTR_MAX + 1] = {
[FOU_ATTR_IPPROTO] = { .type = NLA_U8, },
[FOU_ATTR_TYPE] = { .type = NLA_U8, },
[FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, },
+ [FOU_ATTR_DEEP_HASH] = { .type = NLA_FLAG },
};
static int parse_nl_config(struct genl_info *info,
@@ -677,6 +735,9 @@ static int parse_nl_config(struct genl_info *info,
if (info->attrs[FOU_ATTR_REMCSUM_NOPARTIAL])
cfg->flags |= FOU_F_REMCSUM_NOPARTIAL;
+ if (info->attrs[FOU_ATTR_DEEP_HASH])
+ cfg->flags |= FOU_F_DEEP_HASH;
+
return 0;
}
@@ -717,6 +778,11 @@ static int fou_fill_info(struct fou *fou, struct sk_buff *msg)
if (fou->flags & FOU_F_REMCSUM_NOPARTIAL)
if (nla_put_flag(msg, FOU_ATTR_REMCSUM_NOPARTIAL))
return -1;
+
+ if (fou->flags & FOU_F_DEEP_HASH)
+ if (nla_put_flag(msg, FOU_ATTR_DEEP_HASH))
+ return -1;
+
return 0;
}
--
2.9.3
^ permalink raw reply related
* [PATCH v4 net-next 3/7] udp: Add socket lookup functions with noref
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161019230309.3746853-1-tom@herbertland.com>
Create udp4_lib_lookup_noref and udp6_lib_lookup_noref. These perfrom
a socket lookup on addresses and ports without taking a reference.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
include/net/udp.h | 8 ++++++++
net/ipv4/udp.c | 8 ++++++++
net/ipv6/udp.c | 10 ++++++++++
3 files changed, 26 insertions(+)
diff --git a/include/net/udp.h b/include/net/udp.h
index ea53a87..717a972 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -275,6 +275,10 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
struct udp_table *tbl, struct sk_buff *skb);
struct sock *udp4_lib_lookup_skb(struct sk_buff *skb,
__be16 sport, __be16 dport);
+struct sock *udp4_lib_lookup_noref(struct net *net,
+ __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport,
+ int dif);
struct sock *udp6_lib_lookup(struct net *net,
const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
@@ -286,6 +290,10 @@ struct sock *__udp6_lib_lookup(struct net *net,
struct sk_buff *skb);
struct sock *udp6_lib_lookup_skb(struct sk_buff *skb,
__be16 sport, __be16 dport);
+struct sock *udp6_lib_lookup_noref(struct net *net,
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif);
/*
* SNMP statistics for UDP and UDP-Lite
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 7d96dc2..7f84c51 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -595,6 +595,14 @@ struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
EXPORT_SYMBOL_GPL(udp4_lib_lookup);
#endif
+struct sock *udp4_lib_lookup_noref(struct net *net, __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport, int dif)
+{
+ return __udp4_lib_lookup(net, saddr, sport, daddr, dport,
+ dif, &udp_table, NULL);
+}
+EXPORT_SYMBOL_GPL(udp4_lib_lookup_noref);
+
static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
__be16 loc_port, __be32 loc_addr,
__be16 rmt_port, __be32 rmt_addr,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 9aa7c1c..6e382d9 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -317,6 +317,16 @@ struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be
EXPORT_SYMBOL_GPL(udp6_lib_lookup);
#endif
+struct sock *udp6_lib_lookup_noref(struct net *net,
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif)
+{
+ return __udp6_lib_lookup(net, saddr, sport, daddr, dport,
+ dif, &udp_table, NULL);
+}
+EXPORT_SYMBOL_GPL(udp6_lib_lookup_noref);
+
/*
* This should be easy, if there is something there we
* return it, otherwise we block.
--
2.9.3
^ permalink raw reply related
* [PATCH v4 net-next 1/7] ipv6: Fix Makefile conditional to use CONFIG_INET
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
In-Reply-To: <20161019230309.3746853-1-tom@herbertland.com>
ipv6 directory was being built based on CONFIG_NET not CONFIG_INET.
Signed-off-by: Tom Herbert <tom@herbertland.com>
---
drivers/net/usb/cdc_mbim.c | 4 ++++
include/net/ipv6.h | 15 +++++++++++++++
include/net/net_namespace.h | 2 ++
net/Makefile | 2 +-
4 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 96a5028..6b38e0c 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -301,6 +301,7 @@ static struct sk_buff *cdc_mbim_tx_fixup(struct usbnet *dev, struct sk_buff *skb
return NULL;
}
+#ifdef CONFIG_INET
/* Some devices are known to send Neigbor Solicitation messages and
* require Neigbor Advertisement replies. The IPv6 core will not
* respond since IFF_NOARP is set, so we must handle them ourselves.
@@ -350,6 +351,7 @@ static void do_neigh_solicit(struct usbnet *dev, u8 *buf, u16 tci)
out:
dev_put(netdev);
}
+#endif
static bool is_neigh_solicit(u8 *buf, size_t len)
{
@@ -377,8 +379,10 @@ static struct sk_buff *cdc_mbim_process_dgram(struct usbnet *dev, u8 *buf, size_
proto = htons(ETH_P_IP);
break;
case 0x60:
+#ifdef CONFIG_INET
if (is_neigh_solicit(buf, len))
do_neigh_solicit(dev, buf, tci);
+#endif
proto = htons(ETH_P_IPV6);
break;
default:
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 8fed1cd..cbb1ce0 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -936,8 +936,15 @@ void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,
u8 *proto);
+#ifdef CONFIG_INET
int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp,
__be16 *frag_offp);
+#else
+static inline int ipv6_skip_exthdr(const struct sk_buff *skb, int start,
+ u8 *nexthdrp, __be16 *frag_offp) {
+ return -1;
+}
+#endif
bool ipv6_ext_hdr(u8 nexthdr);
@@ -948,8 +955,16 @@ enum {
};
/* find specified header and get offset to it */
+#ifdef CONFIG_INET
int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target,
unsigned short *fragoff, int *fragflg);
+#else
+static inline int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+ int target, unsigned short *fragoff,
+ int *fragflg) {
+ return -EPROTONOSUPPORT;
+}
+#endif
int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type);
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index fc4f757..b4c4a5f 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -352,8 +352,10 @@ static inline void rt_genid_bump_ipv4(struct net *net)
extern void (*__fib6_flush_trees)(struct net *net);
static inline void rt_genid_bump_ipv6(struct net *net)
{
+#ifdef CONFIG_INET
if (__fib6_flush_trees)
__fib6_flush_trees(net);
+#endif
}
#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN)
diff --git a/net/Makefile b/net/Makefile
index 4cafaa2..82ffb91 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -17,7 +17,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/
obj-$(CONFIG_INET) += ipv4/
obj-$(CONFIG_XFRM) += xfrm/
obj-$(CONFIG_UNIX) += unix/
-obj-$(CONFIG_NET) += ipv6/
+obj-$(CONFIG_INET) += ipv6/
obj-$(CONFIG_PACKET) += packet/
obj-$(CONFIG_NET_KEY) += key/
obj-$(CONFIG_BRIDGE) += bridge/
--
2.9.3
^ permalink raw reply related
* [PATCH v4 net-next 0/7] udp: Flow dissection for tunnels
From: Tom Herbert @ 2016-10-19 23:03 UTC (permalink / raw)
To: davem, netdev; +Cc: kernel-team
Now that we have a means to perform a UDP socket lookup without taking
a reference, it is feasible to have flow dissector crack open UDP
encapsulated packets. Generally, we would expect that the UDP source
port or the flow label in IPv6 would contain enough entropy about
the encapsulated flow. However, there will be cases, such as a static
UDP tunnel with fixed ports, where dissecting the encapsulated packet
is valuable.
The model is here is similar to that implemented for UDP GRO. A
tunnel implementation (e.g. GUE) may set a flow_dissect function
in the udp_sk. In __skb_flow_dissect a case has been added for
UDP to check if there is a socket with flow_dissect set. If there
is the function is called. The (per tunnel implementation)
function can parse the encapsulation headers and return the
next protocol for __skb_flow_dissect to process and it's position
in nhoff.
Since performing a UDP lookup on every packet might be expensive
I added a static key check to bypass the lookup if there are no
sockets with flow_dissect set. I should mention that doing the
lookup wasn't particularly a big hit anyway.
Fou/gue was modified to perform tunnel dissection. This is enabled
on each listener socket via a netlink configuration option.
v2:
- davem suggested that we don't need udp_flow_dissect and that
udp{v6}_encap_needed could be used. Problem is that those are
in respective udp.c and flow_dissector.c is in net/core. Keep
udp_flow_dissect as more generic item.
- Fixed Makefile issue where we were using CONFIG_NET instead of
CONFIG_INET.
- Added limits inf flow dissector from controlling number of nested
encapsulations or EHs that are dissected.
- Added CONFIG_INET around use of inet_offloads in flow_dissector.c.
v3:
- Fix build issues with modules that call IPv6 functions and
CONFIG_INET is not set.
- Fix compilation error in init'ing .flow_dissect in IPv6 UDP
offload.
v4:
- Fix compilation error in init'ing .flow_dissect in IPv6 UDP
offload. (hopefully for real this time).
Tested:
Running 200 streams with TCP_RR.
GRE/GUE variable source port (baseline)
RSS distributes packets, RFS is effective
1211702 tps
147/241/442 50/90/99% latencies
87.95 CPU utilization
GRE/GUE fixed source port
All packets to one CPU, RFS is ineffective
173680 tps
1170/1377/1853 50/90/99% latencies
7.42 CPU utilization
GRE/GUE fixed source port with deep hash enabled
All packets to one CPU, but now RFS is effective
730359 tps
263/325/464 50/90/99% latencies
38.25% CPU utilization (Interrupting CPU is maxed out)
Tom Herbert (7):
ipv6: Fix Makefile conditional to use CONFIG_INET
flow_dissector: Limit processing of next encaps and extensions
udp: Add socket lookup functions with noref
udp: UDP flow dissector
udp: Add UDP flow dissection functions to IPv4 and IPv6
udp: UDP tunnel flow dissection infrastructure
fou: Support flow dissection
drivers/net/usb/cdc_mbim.c | 4 ++
include/linux/netdevice.h | 5 ++
include/linux/udp.h | 7 +++
include/net/flow_dissector.h | 8 +++
include/net/ipv6.h | 15 ++++++
include/net/net_namespace.h | 2 +
include/net/udp.h | 12 +++++
include/net/udp_tunnel.h | 5 ++
include/uapi/linux/fou.h | 1 +
net/Makefile | 2 +-
net/core/flow_dissector.c | 122 ++++++++++++++++++++++++++++++++++++++-----
net/ipv4/fou.c | 68 +++++++++++++++++++++++-
net/ipv4/udp.c | 11 ++++
net/ipv4/udp_offload.c | 39 ++++++++++++++
net/ipv4/udp_tunnel.c | 5 ++
net/ipv6/udp.c | 10 ++++
net/ipv6/udp_offload.c | 40 +++++++++++++-
17 files changed, 341 insertions(+), 15 deletions(-)
--
2.9.3
^ permalink raw reply
* Re: [RFC 1/6] qed: Add support for hardware offloaded iSCSI.
From: Arun Easi @ 2016-10-19 22:28 UTC (permalink / raw)
To: Hannes Reinecke
Cc: manish.rangankar, lduncan, cleech, martin.petersen, jejb,
linux-scsi, netdev, Yuval.Mintz, QLogic-Storage-Upstream,
Yuval Mintz
In-Reply-To: <263515de-e1d4-ea86-644b-3f214bcff5ac@suse.de>
Thanks Hannes for the review. Please see my comments inline..
On Wed, 19 Oct 2016, 12:31am, Hannes Reinecke wrote:
> On 10/19/2016 07:01 AM, manish.rangankar@cavium.com wrote:
> > From: Yuval Mintz <Yuval.Mintz@qlogic.com>
> >
> > This adds the backbone required for the various HW initalizations
> > which are necessary for the iSCSI driver (qedi) for QLogic FastLinQ
> > 4xxxx line of adapters - FW notification, resource initializations, etc.
> >
> > Signed-off-by: Arun Easi <arun.easi@cavium.com>
> > Signed-off-by: Yuval Mintz <yuval.mintz@cavium.com>
> > ---
> > drivers/net/ethernet/qlogic/Kconfig | 15 +
> > drivers/net/ethernet/qlogic/qed/Makefile | 1 +
> > drivers/net/ethernet/qlogic/qed/qed.h | 8 +-
> > drivers/net/ethernet/qlogic/qed/qed_dev.c | 15 +
> > drivers/net/ethernet/qlogic/qed/qed_int.h | 1 -
> > drivers/net/ethernet/qlogic/qed/qed_iscsi.c | 1310 ++++++++++++++++++++++++
> > drivers/net/ethernet/qlogic/qed/qed_iscsi.h | 52 +
> > drivers/net/ethernet/qlogic/qed/qed_l2.c | 1 -
> > drivers/net/ethernet/qlogic/qed/qed_ll2.c | 35 +-
> > drivers/net/ethernet/qlogic/qed/qed_main.c | 2 -
> > drivers/net/ethernet/qlogic/qed/qed_mcp.h | 6 -
> > drivers/net/ethernet/qlogic/qed/qed_reg_addr.h | 2 +
> > drivers/net/ethernet/qlogic/qed/qed_spq.c | 15 +
> > include/linux/qed/qed_if.h | 2 +
> > include/linux/qed/qed_iscsi_if.h | 249 +++++
> > 15 files changed, 1692 insertions(+), 22 deletions(-)
> > create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.c
> > create mode 100644 drivers/net/ethernet/qlogic/qed/qed_iscsi.h
> > create mode 100644 include/linux/qed/qed_iscsi_if.h
> >
-- snipped --
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
> > new file mode 100644
> > index 0000000..cb22dad
> > --- /dev/null
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c
> > @@ -0,0 +1,1310 @@
> > +/* QLogic qed NIC Driver
>
> Shouldn't that be qedi iSCSI Driver?
Actually, this is the common module under drivers/net/, which was
submitted along with the NIC driver, qede, so the comment stayed.
In this driver architecture, for all protocols, there is this
common module, qed, as well as a protocol module (qede, qedr, qedi
etc.).
This comment needs to be changed in all files under qed/. We will submit
another patch to do that.
> > +static int qed_sp_iscsi_conn_offload(struct qed_hwfn *p_hwfn,
> > + struct qed_iscsi_conn *p_conn,
> > + enum spq_mode comp_mode,
> > + struct qed_spq_comp_cb *p_comp_addr)
> > +{
> > + struct iscsi_spe_conn_offload *p_ramrod = NULL;
> > + struct tcp_offload_params_opt2 *p_tcp2 = NULL;
> > + struct tcp_offload_params *p_tcp = NULL;
> > + struct qed_spq_entry *p_ent = NULL;
> > + struct qed_sp_init_data init_data;
> > + union qed_qm_pq_params pq_params;
> > + u16 pq0_id = 0, pq1_id = 0;
> > + dma_addr_t r2tq_pbl_addr;
> > + dma_addr_t xhq_pbl_addr;
> > + dma_addr_t uhq_pbl_addr;
> > + int rc = 0;
> > + u32 dval;
> > + u16 wval;
> > + u8 ucval;
> > + u8 i;
> > +
> > + /* Get SPQ entry */
> > + memset(&init_data, 0, sizeof(init_data));
> > + init_data.cid = p_conn->icid;
> > + init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
> > + init_data.comp_mode = comp_mode;
> > + init_data.p_comp_data = p_comp_addr;
> > +
> > + rc = qed_sp_init_request(p_hwfn, &p_ent,
> > + ISCSI_RAMROD_CMD_ID_OFFLOAD_CONN,
> > + PROTOCOLID_ISCSI, &init_data);
> > + if (rc)
> > + return rc;
> > +
> > + p_ramrod = &p_ent->ramrod.iscsi_conn_offload;
> > +
> > + /* Transmission PQ is the first of the PF */
> > + memset(&pq_params, 0, sizeof(pq_params));
> > + pq0_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_ISCSI, &pq_params);
> > + p_conn->physical_q0 = cpu_to_le16(pq0_id);
> > + p_ramrod->iscsi.physical_q0 = cpu_to_le16(pq0_id);
> > +
> > + /* iSCSI Pure-ACK PQ */
> > + pq_params.iscsi.q_idx = 1;
> > + pq1_id = qed_get_qm_pq(p_hwfn, PROTOCOLID_ISCSI, &pq_params);
> > + p_conn->physical_q1 = cpu_to_le16(pq1_id);
> > + p_ramrod->iscsi.physical_q1 = cpu_to_le16(pq1_id);
> > +
> > + p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_OFFLOAD_CONN;
> > + SET_FIELD(p_ramrod->hdr.flags, ISCSI_SLOW_PATH_HDR_LAYER_CODE,
> > + p_conn->layer_code);
> > +
> > + p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id);
> > + p_ramrod->fw_cid = cpu_to_le32(p_conn->icid);
> > +
> > + DMA_REGPAIR_LE(p_ramrod->iscsi.sq_pbl_addr, p_conn->sq_pbl_addr);
> > +
> > + r2tq_pbl_addr = qed_chain_get_pbl_phys(&p_conn->r2tq);
> > + DMA_REGPAIR_LE(p_ramrod->iscsi.r2tq_pbl_addr, r2tq_pbl_addr);
> > +
> > + xhq_pbl_addr = qed_chain_get_pbl_phys(&p_conn->xhq);
> > + DMA_REGPAIR_LE(p_ramrod->iscsi.xhq_pbl_addr, xhq_pbl_addr);
> > +
> > + uhq_pbl_addr = qed_chain_get_pbl_phys(&p_conn->uhq);
> > + DMA_REGPAIR_LE(p_ramrod->iscsi.uhq_pbl_addr, uhq_pbl_addr);
> > +
> > + p_ramrod->iscsi.initial_ack = cpu_to_le32(p_conn->initial_ack);
> > + p_ramrod->iscsi.flags = p_conn->offl_flags;
> > + p_ramrod->iscsi.default_cq = p_conn->default_cq;
> > + p_ramrod->iscsi.stat_sn = cpu_to_le32(p_conn->stat_sn);
> > +
> > + if (!GET_FIELD(p_ramrod->iscsi.flags,
> > + ISCSI_CONN_OFFLOAD_PARAMS_TCP_ON_CHIP_1B)) {
> > + p_tcp = &p_ramrod->tcp;
> > + ucval = p_conn->local_mac[1];
> > + ((u8 *)(&p_tcp->local_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->local_mac[0];
> > + ((u8 *)(&p_tcp->local_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->local_mac[3];
> > + ((u8 *)(&p_tcp->local_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->local_mac[2];
> > + ((u8 *)(&p_tcp->local_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->local_mac[5];
> > + ((u8 *)(&p_tcp->local_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->local_mac[4];
> > + ((u8 *)(&p_tcp->local_mac_addr_lo))[1] = ucval;
> > + ucval = p_conn->remote_mac[1];
> > + ((u8 *)(&p_tcp->remote_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->remote_mac[0];
> > + ((u8 *)(&p_tcp->remote_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->remote_mac[3];
> > + ((u8 *)(&p_tcp->remote_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->remote_mac[2];
> > + ((u8 *)(&p_tcp->remote_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->remote_mac[5];
> > + ((u8 *)(&p_tcp->remote_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->remote_mac[4];
> > + ((u8 *)(&p_tcp->remote_mac_addr_lo))[1] = ucval;
> > +
> This looks terribly like endianness swapping. You sure this is
> applicable for all architecture and endianness settings?
> And wouldn't it be better to use one of the get_unaligned_XXX functions
> here?
The mac address in the p_tcp structure takes mac in the reverse order as
in p_conn. A for loop, or 3 swab16p for each copy would also do, will make
that change.
>
> > + p_tcp->vlan_id = cpu_to_le16(p_conn->vlan_id);
> > +
> > + p_tcp->flags = p_conn->tcp_flags;
> > + p_tcp->ip_version = p_conn->ip_version;
> > + for (i = 0; i < 4; i++) {
> > + dval = p_conn->remote_ip[i];
> > + p_tcp->remote_ip[i] = cpu_to_le32(dval);
> > + dval = p_conn->local_ip[i];
> > + p_tcp->local_ip[i] = cpu_to_le32(dval);
> > + }
> > + p_tcp->ka_max_probe_cnt = p_conn->ka_max_probe_cnt;
> > + p_tcp->dup_ack_theshold = p_conn->dup_ack_theshold;
> > +
> > + p_tcp->rcv_next = cpu_to_le32(p_conn->rcv_next);
> > + p_tcp->snd_una = cpu_to_le32(p_conn->snd_una);
> > + p_tcp->snd_next = cpu_to_le32(p_conn->snd_next);
> > + p_tcp->snd_max = cpu_to_le32(p_conn->snd_max);
> > + p_tcp->snd_wnd = cpu_to_le32(p_conn->snd_wnd);
> > + p_tcp->rcv_wnd = cpu_to_le32(p_conn->rcv_wnd);
> > + p_tcp->snd_wl1 = cpu_to_le32(p_conn->snd_wl1);
> > + p_tcp->cwnd = cpu_to_le32(p_conn->cwnd);
> > + p_tcp->ss_thresh = cpu_to_le32(p_conn->ss_thresh);
> > + p_tcp->srtt = cpu_to_le16(p_conn->srtt);
> > + p_tcp->rtt_var = cpu_to_le16(p_conn->rtt_var);
> > + p_tcp->ts_time = cpu_to_le32(p_conn->ts_time);
> > + p_tcp->ts_recent = cpu_to_le32(p_conn->ts_recent);
> > + p_tcp->ts_recent_age = cpu_to_le32(p_conn->ts_recent_age);
> > + p_tcp->total_rt = cpu_to_le32(p_conn->total_rt);
> > + dval = p_conn->ka_timeout_delta;
> > + p_tcp->ka_timeout_delta = cpu_to_le32(dval);
> > + dval = p_conn->rt_timeout_delta;
> > + p_tcp->rt_timeout_delta = cpu_to_le32(dval);
> > + p_tcp->dup_ack_cnt = p_conn->dup_ack_cnt;
> > + p_tcp->snd_wnd_probe_cnt = p_conn->snd_wnd_probe_cnt;
> > + p_tcp->ka_probe_cnt = p_conn->ka_probe_cnt;
> > + p_tcp->rt_cnt = p_conn->rt_cnt;
> > + p_tcp->flow_label = cpu_to_le32(p_conn->flow_label);
> > + p_tcp->ka_timeout = cpu_to_le32(p_conn->ka_timeout);
> > + p_tcp->ka_interval = cpu_to_le32(p_conn->ka_interval);
> > + p_tcp->max_rt_time = cpu_to_le32(p_conn->max_rt_time);
> > + dval = p_conn->initial_rcv_wnd;
> > + p_tcp->initial_rcv_wnd = cpu_to_le32(dval);
> > + p_tcp->ttl = p_conn->ttl;
> > + p_tcp->tos_or_tc = p_conn->tos_or_tc;
> > + p_tcp->remote_port = cpu_to_le16(p_conn->remote_port);
> > + p_tcp->local_port = cpu_to_le16(p_conn->local_port);
> > + p_tcp->mss = cpu_to_le16(p_conn->mss);
> > + p_tcp->snd_wnd_scale = p_conn->snd_wnd_scale;
> > + p_tcp->rcv_wnd_scale = p_conn->rcv_wnd_scale;
> > + dval = p_conn->ts_ticks_per_second;
> > + p_tcp->ts_ticks_per_second = cpu_to_le32(dval);
> > + wval = p_conn->da_timeout_value;
> > + p_tcp->da_timeout_value = cpu_to_le16(wval);
> > + p_tcp->ack_frequency = p_conn->ack_frequency;
> > + p_tcp->connect_mode = p_conn->connect_mode;
> > + } else {
> > + p_tcp2 =
> > + &((struct iscsi_spe_conn_offload_option2 *)p_ramrod)->tcp;
> > + ucval = p_conn->local_mac[1];
> > + ((u8 *)(&p_tcp2->local_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->local_mac[0];
> > + ((u8 *)(&p_tcp2->local_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->local_mac[3];
> > + ((u8 *)(&p_tcp2->local_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->local_mac[2];
> > + ((u8 *)(&p_tcp2->local_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->local_mac[5];
> > + ((u8 *)(&p_tcp2->local_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->local_mac[4];
> > + ((u8 *)(&p_tcp2->local_mac_addr_lo))[1] = ucval;
> > +
> > + ucval = p_conn->remote_mac[1];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_hi))[0] = ucval;
> > + ucval = p_conn->remote_mac[0];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_hi))[1] = ucval;
> > + ucval = p_conn->remote_mac[3];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_mid))[0] = ucval;
> > + ucval = p_conn->remote_mac[2];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_mid))[1] = ucval;
> > + ucval = p_conn->remote_mac[5];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_lo))[0] = ucval;
> > + ucval = p_conn->remote_mac[4];
> > + ((u8 *)(&p_tcp2->remote_mac_addr_lo))[1] = ucval;
> > +
> Same here.
Noted.
>
> > + p_tcp2->vlan_id = cpu_to_le16(p_conn->vlan_id);
-- snip --
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_iscsi.h b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
> > new file mode 100644
> > index 0000000..269848c
> > --- /dev/null
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.h
> > @@ -0,0 +1,52 @@
> > +/* QLogic qed NIC Driver
> > + * Copyright (c) 2015 QLogic Corporation
> > + *
> > + * This software is available under the terms of the GNU General Public License
> > + * (GPL) Version 2, available from the file COPYING in the main directory of
> > + * this source tree.
> > + */
> > +
> > +#ifndef _QED_ISCSI_H
> > +#define _QED_ISCSI_H
> > +#include <linux/types.h>
> > +#include <linux/list.h>
> > +#include <linux/slab.h>
> > +#include <linux/spinlock.h>
> > +#include <linux/qed/tcp_common.h>
> > +#include <linux/qed/qed_iscsi_if.h>
> > +#include <linux/qed/qed_chain.h>
> > +#include "qed.h"
> > +#include "qed_hsi.h"
> > +#include "qed_mcp.h"
> > +#include "qed_sp.h"
> > +
> > +struct qed_iscsi_info {
> > + spinlock_t lock;
> > + struct list_head free_list;
> > + u16 max_num_outstanding_tasks;
> > + void *event_context;
> > + iscsi_event_cb_t event_cb;
> > +};
> > +
> > +#ifdef CONFIG_QED_LL2
> > +extern const struct qed_ll2_ops qed_ll2_ops_pass;
> > +#endif
> > +
> > +#if IS_ENABLED(CONFIG_QEDI)
> > +struct qed_iscsi_info *qed_iscsi_alloc(struct qed_hwfn *p_hwfn);
> > +
> > +void qed_iscsi_setup(struct qed_hwfn *p_hwfn,
> > + struct qed_iscsi_info *p_iscsi_info);
> > +
> > +void qed_iscsi_free(struct qed_hwfn *p_hwfn,
> > + struct qed_iscsi_info *p_iscsi_info);
> > +#else /* IS_ENABLED(CONFIG_QEDI) */
> > +static inline struct qed_iscsi_info *qed_iscsi_alloc(
> > + struct qed_hwfn *p_hwfn) { return NULL; }
> > +static inline void qed_iscsi_setup(struct qed_hwfn *p_hwfn,
> > + struct qed_iscsi_info *p_iscsi_info) {}
> > +static inline void qed_iscsi_free(struct qed_hwfn *p_hwfn,
> > + struct qed_iscsi_info *p_iscsi_info) {}
> > +#endif /* IS_ENABLED(CONFIG_QEDI) */
> > +
> > +#endif
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
> > index ddd410a..07e2f77 100644
> > --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
> > @@ -2187,6 +2187,5 @@ const struct qed_eth_ops *qed_get_eth_ops(void)
> >
> > void qed_put_eth_ops(void)
> > {
> > - /* TODO - reference count for module? */
> > }
> > EXPORT_SYMBOL(qed_put_eth_ops);
> >
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_ll2.c b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
> > index a6db107..e67f3c9 100644
> > --- a/drivers/net/ethernet/qlogic/qed/qed_ll2.c
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_ll2.c
> > @@ -299,6 +299,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
> > p_tx->cur_completing_bd_idx = 1;
> > b_last_frag = p_tx->cur_completing_bd_idx == p_pkt->bd_used;
> > tx_frag = p_pkt->bds_set[0].tx_frag;
> > +#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
> > if (p_ll2_conn->gsi_enable)
> > qed_ll2b_release_tx_gsi_packet(p_hwfn,
> > p_ll2_conn->my_id,
> > @@ -307,6 +308,7 @@ static void qed_ll2_txq_flush(struct qed_hwfn *p_hwfn, u8 connection_handle)
> > b_last_frag,
> > b_last_packet);
> > else
> > +#endif
> > qed_ll2b_complete_tx_packet(p_hwfn,
> > p_ll2_conn->my_id,
> > p_pkt->cookie,
> Huh? What is that doing here?
>
This is the infiniband part of the common module. The "#if" was to
prevent a compile error when infiniband part was not used (like
for this, iSCSI).
BTW, there is another patch that was submitted by Yuval M. to fix
that, this RFC just came in between. We will be pulling in that
change for the next series.
> > @@ -367,6 +369,7 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
> >
> > spin_unlock_irqrestore(&p_tx->lock, flags);
> > tx_frag = p_pkt->bds_set[0].tx_frag;
> > +#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
> > if (p_ll2_conn->gsi_enable)
> > qed_ll2b_complete_tx_gsi_packet(p_hwfn,
> > p_ll2_conn->my_id,
> > @@ -374,6 +377,7 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
> > tx_frag,
> > b_last_frag, !num_bds);
> > else
> > +#endif
> > qed_ll2b_complete_tx_packet(p_hwfn,
> > p_ll2_conn->my_id,
> > p_pkt->cookie,
> > @@ -421,6 +425,7 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
> > "Mismatch between active_descq and the LL2 Rx chain\n");
> > list_add_tail(&p_pkt->list_entry, &p_rx->free_descq);
> >
> > +#if IS_ENABLED(CONFIG_INFINIBAND_QEDR)
> > spin_unlock_irqrestore(&p_rx->lock, lock_flags);
> > qed_ll2b_complete_rx_gsi_packet(p_hwfn,
> > p_ll2_info->my_id,
> > @@ -433,6 +438,7 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
> > src_mac_addrhi,
> > src_mac_addrlo, b_last_cqe);
> > spin_lock_irqsave(&p_rx->lock, lock_flags);
> > +#endif
> >
> > return 0;
> > }
> > @@ -1516,11 +1522,12 @@ static void qed_ll2_register_cb_ops(struct qed_dev *cdev,
> >
> > static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
> > {
> > - struct qed_ll2_info ll2_info;
> > + struct qed_ll2_info *ll2_info;
> > struct qed_ll2_buffer *buffer;
> > enum qed_ll2_conn_type conn_type;
> > struct qed_ptt *p_ptt;
> > int rc, i;
> > + u8 gsi_enable = 1;
> >
> > /* Initialize LL2 locks & lists */
> > INIT_LIST_HEAD(&cdev->ll2->list);
> > @@ -1552,6 +1559,7 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
> > switch (QED_LEADING_HWFN(cdev)->hw_info.personality) {
> > case QED_PCI_ISCSI:
> > conn_type = QED_LL2_TYPE_ISCSI;
> > + gsi_enable = 0;
> > break;
> > case QED_PCI_ETH_ROCE:
> > conn_type = QED_LL2_TYPE_ROCE;
> > @@ -1561,18 +1569,23 @@ static int qed_ll2_start(struct qed_dev *cdev, struct qed_ll2_params *params)
> > }
> >
> > /* Prepare the temporary ll2 information */
> > - memset(&ll2_info, 0, sizeof(ll2_info));
> > - ll2_info.conn_type = conn_type;
> > - ll2_info.mtu = params->mtu;
> > - ll2_info.rx_drop_ttl0_flg = params->drop_ttl0_packets;
> > - ll2_info.rx_vlan_removal_en = params->rx_vlan_stripping;
> > - ll2_info.tx_tc = 0;
> > - ll2_info.tx_dest = CORE_TX_DEST_NW;
> > - ll2_info.gsi_enable = 1;
> > -
> > - rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), &ll2_info,
> > + ll2_info = kzalloc(sizeof(*ll2_info), GFP_KERNEL);
> > + if (!ll2_info) {
> > + DP_INFO(cdev, "Failed to allocate LL2 info buffer\n");
> > + goto fail;
> > + }
> > + ll2_info->conn_type = conn_type;
> > + ll2_info->mtu = params->mtu;
> > + ll2_info->rx_drop_ttl0_flg = params->drop_ttl0_packets;
> > + ll2_info->rx_vlan_removal_en = params->rx_vlan_stripping;
> > + ll2_info->tx_tc = 0;
> > + ll2_info->tx_dest = CORE_TX_DEST_NW;
> > + ll2_info->gsi_enable = gsi_enable;
> > +
> > + rc = qed_ll2_acquire_connection(QED_LEADING_HWFN(cdev), ll2_info,
> > QED_LL2_RX_SIZE, QED_LL2_TX_SIZE,
> > &cdev->ll2->handle);
> > + kfree(ll2_info);
> > if (rc) {
> > DP_INFO(cdev, "Failed to acquire LL2 connection\n");
> > goto fail;
> Where is the benefit of this hunk? And is it related to iSCSI?
This hunk was to prevent a large stack warning (was present with
gcc 4.8.3). This is a common function applicable to iSCSI as well.
>
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c
> > index 4ee3151..a01ad9d 100644
> > --- a/drivers/net/ethernet/qlogic/qed/qed_main.c
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c
> > @@ -1239,7 +1239,6 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
> > if (link.link_up)
> > if_link->link_up = true;
> >
> > - /* TODO - at the moment assume supported and advertised speed equal */
> > if_link->supported_caps = QED_LM_FIBRE_BIT;
> > if (params.speed.autoneg)
> > if_link->supported_caps |= QED_LM_Autoneg_BIT;
> > @@ -1294,7 +1293,6 @@ static void qed_fill_link(struct qed_hwfn *hwfn,
> > if (link.link_up)
> > if_link->speed = link.speed;
> >
> > - /* TODO - fill duplex properly */
> > if_link->duplex = DUPLEX_FULL;
> > qed_mcp_get_media_type(hwfn->cdev, &media_type);
> > if_link->port = qed_get_port_type(media_type);
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.h b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
> > index dff520e..2e5f51b 100644
> > --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.h
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.h
> > @@ -314,9 +314,6 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn,
> >
> > /* Using hwfn number (and not pf_num) is required since in CMT mode,
> > * same pf_num may be used by two different hwfn
> > - * TODO - this shouldn't really be in .h file, but until all fields
> > - * required during hw-init will be placed in their correct place in shmem
> > - * we need it in qed_dev.c [for readin the nvram reflection in shmem].
> > */
> > #define MCP_PF_ID_BY_REL(p_hwfn, rel_pfid) (QED_IS_BB((p_hwfn)->cdev) ? \
> > ((rel_pfid) | \
> > @@ -324,9 +321,6 @@ int qed_mcp_bist_clock_test(struct qed_hwfn *p_hwfn,
> > rel_pfid)
> > #define MCP_PF_ID(p_hwfn) MCP_PF_ID_BY_REL(p_hwfn, (p_hwfn)->rel_pf_id)
> >
> > -/* TODO - this is only correct as long as only BB is supported, and
> > - * no port-swapping is implemented; Afterwards we'll need to fix it.
> > - */
> > #define MFW_PORT(_p_hwfn) ((_p_hwfn)->abs_pf_id % \
> > ((_p_hwfn)->cdev->num_ports_in_engines * 2))
> > struct qed_mcp_info {
> Please split off the patch and use a separate one to remove all the TODO
> entries. They do not relate to the iSCSI offload bit.
>
Will do.
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
> > index b414a05..9754420 100644
> > --- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
> > @@ -82,6 +82,8 @@
> > 0x1c80000UL
> > #define BAR0_MAP_REG_XSDM_RAM \
> > 0x1e00000UL
> > +#define BAR0_MAP_REG_YSDM_RAM \
> > + 0x1e80000UL
> > #define NIG_REG_RX_LLH_BRB_GATE_DNTFWD_PERPF \
> > 0x5011f4UL
> > #define PRS_REG_SEARCH_TCP \
> > diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c
> > index caff415..d3fa578 100644
> > --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c
> > +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c
> > @@ -24,6 +24,7 @@
> > #include "qed_hsi.h"
> > #include "qed_hw.h"
> > #include "qed_int.h"
> > +#include "qed_iscsi.h"
> > #include "qed_mcp.h"
> > #include "qed_reg_addr.h"
> > #include "qed_sp.h"
> > @@ -249,6 +250,20 @@ static int qed_spq_hw_post(struct qed_hwfn *p_hwfn,
> > return qed_sriov_eqe_event(p_hwfn,
> > p_eqe->opcode,
> > p_eqe->echo, &p_eqe->data);
> > + case PROTOCOLID_ISCSI:
> > + if (!IS_ENABLED(CONFIG_QEDI))
> > + return -EINVAL;
> > +
> > + if (p_hwfn->p_iscsi_info->event_cb) {
> > + struct qed_iscsi_info *p_iscsi = p_hwfn->p_iscsi_info;
> > +
> > + return p_iscsi->event_cb(p_iscsi->event_context,
> > + p_eqe->opcode, &p_eqe->data);
> > + } else {
> > + DP_NOTICE(p_hwfn,
> > + "iSCSI async completion is not set\n");
> > + return -EINVAL;
> > + }
> > default:
> > DP_NOTICE(p_hwfn,
> > "Unknown Async completion for protocol: %d\n",
> > diff --git a/include/linux/qed/qed_if.h b/include/linux/qed/qed_if.h
> > index f9ae903..c0c9fa8 100644
> > --- a/include/linux/qed/qed_if.h
> > +++ b/include/linux/qed/qed_if.h
> > @@ -165,6 +165,7 @@ struct qed_iscsi_pf_params {
> > u32 max_cwnd;
> > u16 cq_num_entries;
> > u16 cmdq_num_entries;
> > + u32 two_msl_timer;
> > u16 dup_ack_threshold;
> > u16 tx_sws_timer;
> > u16 min_rto;
> > @@ -271,6 +272,7 @@ struct qed_dev_info {
> > enum qed_sb_type {
> > QED_SB_TYPE_L2_QUEUE,
> > QED_SB_TYPE_CNQ,
> > + QED_SB_TYPE_STORAGE,
> > };
> >
> > enum qed_protocol {
> > diff --git a/include/linux/qed/qed_iscsi_if.h b/include/linux/qed/qed_iscsi_if.h
> > new file mode 100644
> > index 0000000..6735ee5
> > --- /dev/null
> > +++ b/include/linux/qed/qed_iscsi_if.h
> > @@ -0,0 +1,249 @@
> > +/* QLogic qed NIC Driver
> Again, this is the iSCSI driver, is it not?
>
> > + * Copyright (c) 2015 QLogic Corporation
> > + *
> And you _might_ want to check the copyright, seeing that it's being
> posted from the cavium.com domain ...
>
Yes, rest of the files (already existing) for qed has the same
copyright, so this patch did not modify it. qedi, OTOH, has all
new files and are using the updated ones. A new patch will be
posted to update the qed files.
Regards,
-Arun
^ permalink raw reply
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