* [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type
2008-12-17 14:07 [RFC] [PATCH 0/5] Phonet enhancements Rémi Denis-Courmont
@ 2008-12-17 14:07 ` Rémi Denis-Courmont
2008-12-17 20:07 ` Marcel Holtmann
2008-12-17 23:52 ` David Miller
2008-12-17 14:07 ` [PATCH 2/5] Phonet: allocate separate ARP type for GPRS over a Phonet pipe Rémi Denis-Courmont
` (4 subsequent siblings)
5 siblings, 2 replies; 17+ messages in thread
From: Rémi Denis-Courmont @ 2008-12-17 14:07 UTC (permalink / raw)
To: netdev
Also leave some room for more 802.11 types.
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
include/linux/if_arp.h | 2 ++
net/core/dev.c | 8 ++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 4d34018..11df77a 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -87,6 +87,8 @@
#define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */
#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */
+#define ARPHRD_PHONET 820 /* PhoNet media type */
+
#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
#define ARPHRD_NONE 0xFFFE /* zero header length */
diff --git a/net/core/dev.c b/net/core/dev.c
index d8d7d1f..15aab0c 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -283,8 +283,8 @@ static const unsigned short netdev_lock_type[] =
ARPHRD_PIMREG, ARPHRD_HIPPI, ARPHRD_ASH, ARPHRD_ECONET,
ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL,
ARPHRD_FCFABRIC, ARPHRD_IEEE802_TR, ARPHRD_IEEE80211,
- ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_VOID,
- ARPHRD_NONE};
+ ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET,
+ ARPHRD_VOID, ARPHRD_NONE};
static const char *netdev_lock_name[] =
{"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
@@ -300,8 +300,8 @@ static const char *netdev_lock_name[] =
"_xmit_PIMREG", "_xmit_HIPPI", "_xmit_ASH", "_xmit_ECONET",
"_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL",
"_xmit_FCFABRIC", "_xmit_IEEE802_TR", "_xmit_IEEE80211",
- "_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_VOID",
- "_xmit_NONE"};
+ "_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET",
+ "_xmit_VOID", "_xmit_NONE"};
static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)];
static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
--
1.5.4.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type
2008-12-17 14:07 ` [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type Rémi Denis-Courmont
@ 2008-12-17 20:07 ` Marcel Holtmann
2008-12-17 22:18 ` Rémi Denis-Courmont
2008-12-17 23:52 ` David Miller
1 sibling, 1 reply; 17+ messages in thread
From: Marcel Holtmann @ 2008-12-17 20:07 UTC (permalink / raw)
To: Rémi Denis-Courmont; +Cc: netdev
Hi Remi,
> Also leave some room for more 802.11 types.
>
> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
> ---
> include/linux/if_arp.h | 2 ++
> net/core/dev.c | 8 ++++----
> 2 files changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
> index 4d34018..11df77a 100644
> --- a/include/linux/if_arp.h
> +++ b/include/linux/if_arp.h
> @@ -87,6 +87,8 @@
> #define ARPHRD_IEEE80211_PRISM 802 /* IEEE 802.11 + Prism2 header */
> #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */
>
> +#define ARPHRD_PHONET 820 /* PhoNet media type */
> +
> #define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
> #define ARPHRD_NONE 0xFFFE /* zero header length */
what kind of communication are you doing over that device. Is it pure IP
communication or a PhoNet specific one. In case of pure and simple IP,
then please use the officially assigned Pure IP type from here:
http://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
Regards
Marcel
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type
2008-12-17 20:07 ` Marcel Holtmann
@ 2008-12-17 22:18 ` Rémi Denis-Courmont
0 siblings, 0 replies; 17+ messages in thread
From: Rémi Denis-Courmont @ 2008-12-17 22:18 UTC (permalink / raw)
To: Marcel Holtmann; +Cc: Rémi Denis-Courmont, netdev
Le mercredi 17 décembre 2008, Marcel Holtmann a écrit :
> what kind of communication are you doing over that device.
Phonet packets on the wire. That is to say, Phonet packets including the
leading media type byte, which the Linux Phonet implementation consider
to be the Phonet "link-layer", and is not visible to the Phonet sockets
stack.
No IP here.
--
Rémi Denis-Courmont
http://www.remlab.net/
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type
2008-12-17 14:07 ` [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type Rémi Denis-Courmont
2008-12-17 20:07 ` Marcel Holtmann
@ 2008-12-17 23:52 ` David Miller
1 sibling, 0 replies; 17+ messages in thread
From: David Miller @ 2008-12-17 23:52 UTC (permalink / raw)
To: remi.denis-courmont; +Cc: netdev
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Date: Wed, 17 Dec 2008 16:07:50 +0200
> Also leave some room for more 802.11 types.
>
> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Applied.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 2/5] Phonet: allocate separate ARP type for GPRS over a Phonet pipe
2008-12-17 14:07 [RFC] [PATCH 0/5] Phonet enhancements Rémi Denis-Courmont
2008-12-17 14:07 ` [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type Rémi Denis-Courmont
@ 2008-12-17 14:07 ` Rémi Denis-Courmont
2008-12-17 23:52 ` David Miller
2008-12-17 14:07 ` [PATCH 3/5] Phonet: use atomic for packet TX window Rémi Denis-Courmont
` (3 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Rémi Denis-Courmont @ 2008-12-17 14:07 UTC (permalink / raw)
To: netdev
A separate xmit lock class supports GPRS over a Phonet pipe over a TUN
device (type ARPHRD_NONE).
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
include/linux/if_arp.h | 1 +
net/core/dev.c | 4 ++--
net/phonet/pep-gprs.c | 2 +-
3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 11df77a..5ff8980 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -88,6 +88,7 @@
#define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */
#define ARPHRD_PHONET 820 /* PhoNet media type */
+#define ARPHRD_PHONET_PIPE 821 /* PhoNet pipe header */
#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
#define ARPHRD_NONE 0xFFFE /* zero header length */
diff --git a/net/core/dev.c b/net/core/dev.c
index 15aab0c..048cf11 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -284,7 +284,7 @@ static const unsigned short netdev_lock_type[] =
ARPHRD_IRDA, ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL,
ARPHRD_FCFABRIC, ARPHRD_IEEE802_TR, ARPHRD_IEEE80211,
ARPHRD_IEEE80211_PRISM, ARPHRD_IEEE80211_RADIOTAP, ARPHRD_PHONET,
- ARPHRD_VOID, ARPHRD_NONE};
+ ARPHRD_PHONET_PIPE, ARPHRD_VOID, ARPHRD_NONE};
static const char *netdev_lock_name[] =
{"_xmit_NETROM", "_xmit_ETHER", "_xmit_EETHER", "_xmit_AX25",
@@ -301,7 +301,7 @@ static const char *netdev_lock_name[] =
"_xmit_IRDA", "_xmit_FCPP", "_xmit_FCAL", "_xmit_FCPL",
"_xmit_FCFABRIC", "_xmit_IEEE802_TR", "_xmit_IEEE80211",
"_xmit_IEEE80211_PRISM", "_xmit_IEEE80211_RADIOTAP", "_xmit_PHONET",
- "_xmit_VOID", "_xmit_NONE"};
+ "_xmit_PHONET_PIPE", "_xmit_VOID", "_xmit_NONE"};
static struct lock_class_key netdev_xmit_lock_key[ARRAY_SIZE(netdev_lock_type)];
static struct lock_class_key netdev_addr_lock_key[ARRAY_SIZE(netdev_lock_type)];
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index 0b640b0..a287320 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -260,7 +260,7 @@ static int gprs_set_mtu(struct net_device *dev, int new_mtu)
static void gprs_setup(struct net_device *dev)
{
dev->features = NETIF_F_FRAGLIST;
- dev->type = ARPHRD_NONE;
+ dev->type = ARPHRD_PHONET_PIPE;
dev->flags = IFF_POINTOPOINT | IFF_NOARP;
dev->mtu = GPRS_DEFAULT_MTU;
dev->hard_header_len = 0;
--
1.5.4.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 3/5] Phonet: use atomic for packet TX window
2008-12-17 14:07 [RFC] [PATCH 0/5] Phonet enhancements Rémi Denis-Courmont
2008-12-17 14:07 ` [PATCH 1/5] Phonet: allocate a non-Ethernet ARP type Rémi Denis-Courmont
2008-12-17 14:07 ` [PATCH 2/5] Phonet: allocate separate ARP type for GPRS over a Phonet pipe Rémi Denis-Courmont
@ 2008-12-17 14:07 ` Rémi Denis-Courmont
2008-12-17 23:53 ` David Miller
2008-12-17 14:07 ` [PATCH 4/5] Phonet: get rid of deferred work on the transmission path Rémi Denis-Courmont
` (2 subsequent siblings)
5 siblings, 1 reply; 17+ messages in thread
From: Rémi Denis-Courmont @ 2008-12-17 14:07 UTC (permalink / raw)
To: netdev
GPRS TX flow control won't need to lock the underlying socket anymore.
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
include/net/phonet/pep.h | 2 +-
net/phonet/pep.c | 38 +++++++++++++++++++++-----------------
net/phonet/socket.c | 2 +-
3 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/include/net/phonet/pep.h b/include/net/phonet/pep.h
index fcd7930..4c61cdc 100644
--- a/include/net/phonet/pep.h
+++ b/include/net/phonet/pep.h
@@ -35,12 +35,12 @@ struct pep_sock {
struct sock *listener;
struct sk_buff_head ctrlreq_queue;
#define PNPIPE_CTRLREQ_MAX 10
+ atomic_t tx_credits;
int ifindex;
u16 peer_type; /* peer type/subtype */
u8 pipe_handle;
u8 rx_credits;
- u8 tx_credits;
u8 rx_fc; /* RX flow control */
u8 tx_fc; /* TX flow control */
u8 init_enable; /* auto-enable at creation */
diff --git a/net/phonet/pep.c b/net/phonet/pep.c
index bc6d50f..bb3e678 100644
--- a/net/phonet/pep.c
+++ b/net/phonet/pep.c
@@ -225,6 +225,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
{
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *hdr = pnp_hdr(skb);
+ int wake = 0;
if (!pskb_may_pull(skb, sizeof(*hdr) + 4))
return -EINVAL;
@@ -241,16 +242,16 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
case PN_LEGACY_FLOW_CONTROL:
switch (hdr->data[4]) {
case PEP_IND_BUSY:
- pn->tx_credits = 0;
+ atomic_set(&pn->tx_credits, 0);
break;
case PEP_IND_READY:
- pn->tx_credits = 1;
+ atomic_set(&pn->tx_credits, wake = 1);
break;
}
break;
case PN_ONE_CREDIT_FLOW_CONTROL:
if (hdr->data[4] == PEP_IND_READY)
- pn->tx_credits = 1;
+ atomic_set(&pn->tx_credits, wake = 1);
break;
}
break;
@@ -258,10 +259,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
case PN_PEP_IND_ID_MCFC_GRANT_CREDITS:
if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL)
break;
- if (pn->tx_credits + hdr->data[4] > 0xff)
- pn->tx_credits = 0xff;
- else
- pn->tx_credits += hdr->data[4];
+ atomic_add(wake = hdr->data[4], &pn->tx_credits);
break;
default:
@@ -269,7 +267,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
(unsigned)hdr->data[1]);
return -EOPNOTSUPP;
}
- if (pn->tx_credits)
+ if (wake)
sk->sk_write_space(sk);
return 0;
}
@@ -343,7 +341,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
}
/* fall through */
case PNS_PEP_DISABLE_REQ:
- pn->tx_credits = 0;
+ atomic_set(&pn->tx_credits, 0);
pep_reply(sk, skb, PN_PIPE_NO_ERROR, NULL, 0, GFP_ATOMIC);
break;
@@ -390,7 +388,7 @@ static int pipe_do_rcv(struct sock *sk, struct sk_buff *skb)
/* fall through */
case PNS_PIPE_ENABLED_IND:
if (!pn_flow_safe(pn->tx_fc)) {
- pn->tx_credits = 1;
+ atomic_set(&pn->tx_credits, 1);
sk->sk_write_space(sk);
}
if (sk->sk_state == TCP_ESTABLISHED)
@@ -504,8 +502,9 @@ static int pep_connreq_rcv(struct sock *sk, struct sk_buff *skb)
newpn->pn_sk.resource = pn->pn_sk.resource;
skb_queue_head_init(&newpn->ctrlreq_queue);
newpn->pipe_handle = pipe_handle;
+ atomic_set(&newpn->tx_credits, 0);
newpn->peer_type = peer_type;
- newpn->rx_credits = newpn->tx_credits = 0;
+ newpn->rx_credits = 0;
newpn->rx_fc = newpn->tx_fc = PN_LEGACY_FLOW_CONTROL;
newpn->init_enable = enabled;
@@ -821,14 +820,18 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
struct pep_sock *pn = pep_sk(sk);
struct pnpipehdr *ph;
+ if (pn_flow_safe(pn->tx_fc) &&
+ !atomic_add_unless(&pn->tx_credits, -1, 0)) {
+ kfree_skb(skb);
+ return -ENOBUFS;
+ }
+
skb_push(skb, 3);
skb_reset_transport_header(skb);
ph = pnp_hdr(skb);
ph->utid = 0;
ph->message_id = PNS_PIPE_DATA;
ph->pipe_handle = pn->pipe_handle;
- if (pn_flow_safe(pn->tx_fc) && pn->tx_credits)
- pn->tx_credits--;
return pn_skb_send(sk, skb, &pipe_srv);
}
@@ -866,7 +869,7 @@ disabled:
BUG_ON(sk->sk_state != TCP_ESTABLISHED);
/* Wait until flow control allows TX */
- done = pn->tx_credits > 0;
+ done = atomic_read(&pn->tx_credits);
while (!done) {
DEFINE_WAIT(wait);
@@ -881,7 +884,7 @@ disabled:
prepare_to_wait(&sk->sk_socket->wait, &wait,
TASK_INTERRUPTIBLE);
- done = sk_wait_event(sk, &timeo, pn->tx_credits > 0);
+ done = sk_wait_event(sk, &timeo, atomic_read(&pn->tx_credits));
finish_wait(&sk->sk_socket->wait, &wait);
if (sk->sk_state != TCP_ESTABLISHED)
@@ -895,7 +898,8 @@ disabled:
goto out;
skb_reserve(skb, MAX_PHONET_HEADER + 3);
- if (sk->sk_state != TCP_ESTABLISHED || !pn->tx_credits)
+ if (sk->sk_state != TCP_ESTABLISHED ||
+ !atomic_read(&pn->tx_credits))
goto disabled; /* sock_alloc_send_skb might sleep */
}
@@ -917,7 +921,7 @@ int pep_writeable(struct sock *sk)
{
struct pep_sock *pn = pep_sk(sk);
- return (sk->sk_state == TCP_ESTABLISHED) ? pn->tx_credits : 0;
+ return atomic_read(&pn->tx_credits);
}
int pep_write(struct sock *sk, struct sk_buff *skb)
diff --git a/net/phonet/socket.c b/net/phonet/socket.c
index c75aa5c..ada2a35 100644
--- a/net/phonet/socket.c
+++ b/net/phonet/socket.c
@@ -227,7 +227,7 @@ static unsigned int pn_socket_poll(struct file *file, struct socket *sock,
if (!mask && sk->sk_state == TCP_CLOSE_WAIT)
return POLLHUP;
- if (sk->sk_state == TCP_ESTABLISHED && pn->tx_credits)
+ if (sk->sk_state == TCP_ESTABLISHED && atomic_read(&pn->tx_credits))
mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
return mask;
--
1.5.4.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 4/5] Phonet: get rid of deferred work on the transmission path
2008-12-17 14:07 [RFC] [PATCH 0/5] Phonet enhancements Rémi Denis-Courmont
` (2 preceding siblings ...)
2008-12-17 14:07 ` [PATCH 3/5] Phonet: use atomic for packet TX window Rémi Denis-Courmont
@ 2008-12-17 14:07 ` Rémi Denis-Courmont
2008-12-17 23:53 ` David Miller
2008-12-17 14:07 ` [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework Rémi Denis-Courmont
2008-12-17 23:46 ` [RFC] [PATCH 0/5] Phonet enhancements David Miller
5 siblings, 1 reply; 17+ messages in thread
From: Rémi Denis-Courmont @ 2008-12-17 14:07 UTC (permalink / raw)
To: netdev
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
net/phonet/pep-gprs.c | 91 +++++++++++++++----------------------------------
1 files changed, 28 insertions(+), 63 deletions(-)
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index a287320..b0ceac2 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -41,11 +41,6 @@ struct gprs_dev {
void (*old_write_space)(struct sock *);
struct net_device *dev;
-
- struct sk_buff_head tx_queue;
- struct work_struct tx_work;
- spinlock_t tx_lock;
- unsigned tx_max;
};
static __be16 gprs_type_trans(struct sk_buff *skb)
@@ -66,6 +61,14 @@ static __be16 gprs_type_trans(struct sk_buff *skb)
return htons(0);
}
+static void gprs_writeable(struct gprs_dev *gp)
+{
+ struct net_device *dev = gp->dev;
+
+ if (pep_writeable(gp->sk))
+ netif_wake_queue(dev);
+}
+
/*
* Socket callbacks
*/
@@ -157,14 +160,9 @@ static void gprs_data_ready(struct sock *sk, int len)
static void gprs_write_space(struct sock *sk)
{
struct gprs_dev *gp = sk->sk_user_data;
- struct net_device *dev = gp->dev;
- unsigned credits = pep_writeable(sk);
- spin_lock_bh(&gp->tx_lock);
- gp->tx_max = credits;
- if (credits > skb_queue_len(&gp->tx_queue) && netif_running(dev))
- netif_wake_queue(dev);
- spin_unlock_bh(&gp->tx_lock);
+ if (netif_running(gp->dev))
+ gprs_writeable(gp);
}
/*
@@ -175,22 +173,21 @@ static int gprs_open(struct net_device *dev)
{
struct gprs_dev *gp = netdev_priv(dev);
- gprs_write_space(gp->sk);
+ gprs_writeable(gp);
return 0;
}
static int gprs_close(struct net_device *dev)
{
- struct gprs_dev *gp = netdev_priv(dev);
-
netif_stop_queue(dev);
- flush_work(&gp->tx_work);
return 0;
}
static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct gprs_dev *gp = netdev_priv(dev);
+ struct sock *sk = gp->sk;
+ int len, err;
switch (skb->protocol) {
case htons(ETH_P_IP):
@@ -201,51 +198,24 @@ static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
- spin_lock(&gp->tx_lock);
- if (likely(skb_queue_len(&gp->tx_queue) < gp->tx_max)) {
- skb_queue_tail(&gp->tx_queue, skb);
- skb = NULL;
- }
- if (skb_queue_len(&gp->tx_queue) >= gp->tx_max)
- netif_stop_queue(dev);
- spin_unlock(&gp->tx_lock);
-
- schedule_work(&gp->tx_work);
- if (unlikely(skb))
+ skb_orphan(skb);
+ skb_set_owner_w(skb, sk);
+ len = skb->len;
+ err = pep_write(sk, skb);
+ if (err) {
+ LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n",
+ dev->name, err);
+ dev->stats.tx_aborted_errors++;
+ dev->stats.tx_errors++;
dev_kfree_skb(skb);
- return 0;
-}
-
-static void gprs_tx(struct work_struct *work)
-{
- struct gprs_dev *gp = container_of(work, struct gprs_dev, tx_work);
- struct net_device *dev = gp->dev;
- struct sock *sk = gp->sk;
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&gp->tx_queue)) != NULL) {
- int err;
-
- dev->stats.tx_bytes += skb->len;
+ } else {
dev->stats.tx_packets++;
-
- skb_orphan(skb);
- skb_set_owner_w(skb, sk);
-
- lock_sock(sk);
- err = pep_write(sk, skb);
- if (err) {
- LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n",
- dev->name, err);
- dev->stats.tx_aborted_errors++;
- dev->stats.tx_errors++;
- }
- release_sock(sk);
+ dev->stats.tx_bytes += len;
}
- lock_sock(sk);
- gprs_write_space(sk);
- release_sock(sk);
+ if (!pep_writeable(sk))
+ netif_stop_queue(dev);
+ return 0;
}
static int gprs_set_mtu(struct net_device *dev, int new_mtu)
@@ -297,11 +267,8 @@ int gprs_attach(struct sock *sk)
if (!dev)
return -ENOMEM;
gp = netdev_priv(dev);
+ gp->sk = sk;
gp->dev = dev;
- gp->tx_max = 0;
- spin_lock_init(&gp->tx_lock);
- skb_queue_head_init(&gp->tx_queue);
- INIT_WORK(&gp->tx_work, gprs_tx);
netif_stop_queue(dev);
err = register_netdev(dev);
@@ -328,9 +295,7 @@ int gprs_attach(struct sock *sk)
sk->sk_data_ready = gprs_data_ready;
sk->sk_write_space = gprs_write_space;
release_sock(sk);
-
sock_hold(sk);
- gp->sk = sk;
printk(KERN_DEBUG"%s: attached\n", dev->name);
return dev->ifindex;
--
1.5.4.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework
2008-12-17 14:07 [RFC] [PATCH 0/5] Phonet enhancements Rémi Denis-Courmont
` (3 preceding siblings ...)
2008-12-17 14:07 ` [PATCH 4/5] Phonet: get rid of deferred work on the transmission path Rémi Denis-Courmont
@ 2008-12-17 14:07 ` Rémi Denis-Courmont
2008-12-17 23:53 ` David Miller
2008-12-29 15:44 ` Marcel Holtmann
2008-12-17 23:46 ` [RFC] [PATCH 0/5] Phonet enhancements David Miller
5 siblings, 2 replies; 17+ messages in thread
From: Rémi Denis-Courmont @ 2008-12-17 14:07 UTC (permalink / raw)
To: netdev
This implements the Nokia vendor-specific communication device class
function to exchange Phonet messages over USB. This function is already
found in the "PC suite" USB profile of (non-Linux) Nokia handsets.
Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
---
drivers/usb/gadget/f_phonet.c | 621 +++++++++++++++++++++++++++++++++++++++++
drivers/usb/gadget/u_phonet.h | 21 ++
2 files changed, 642 insertions(+), 0 deletions(-)
create mode 100644 drivers/usb/gadget/f_phonet.c
create mode 100644 drivers/usb/gadget/u_phonet.h
diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c
new file mode 100644
index 0000000..d8fc9b3
--- /dev/null
+++ b/drivers/usb/gadget/f_phonet.c
@@ -0,0 +1,621 @@
+/*
+ * f_phonet.c -- USB CDC Phonet function
+ *
+ * Copyright (C) 2007-2008 Nokia Corporation. All rights reserved.
+ *
+ * Author: Rémi Denis-Courmont
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_phonet.h>
+#include <linux/if_arp.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/composite.h>
+
+#include "u_phonet.h"
+
+#define PN_MEDIA_USB 0x1B
+
+/*-------------------------------------------------------------------------*/
+
+struct phonet_port {
+ struct f_phonet *usb;
+ spinlock_t lock;
+};
+
+struct f_phonet {
+ struct usb_function function;
+ struct net_device *dev;
+ struct usb_ep *in_ep, *out_ep;
+
+ struct usb_request *in_req;
+ struct usb_request *out_reqv[0];
+};
+
+static int phonet_rxq_size = 2;
+
+static inline struct f_phonet *func_to_pn(struct usb_function *f)
+{
+ return container_of(f, struct f_phonet, function);
+}
+
+/*-------------------------------------------------------------------------*/
+
+#define USB_CDC_SUBCLASS_PHONET 0xfe
+#define USB_CDC_PHONET_TYPE 0xab
+
+static struct usb_interface_descriptor
+pn_control_intf_desc = {
+ .bLength = sizeof pn_control_intf_desc,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC, */
+ .bInterfaceClass = USB_CLASS_COMM,
+ .bInterfaceSubClass = USB_CDC_SUBCLASS_PHONET,
+};
+
+static const struct usb_cdc_header_desc
+pn_header_desc = {
+ .bLength = sizeof pn_header_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_HEADER_TYPE,
+ .bcdCDC = __constant_cpu_to_le16(0x0110),
+};
+
+static const struct usb_cdc_header_desc
+pn_phonet_desc = {
+ .bLength = sizeof pn_phonet_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_PHONET_TYPE,
+ .bcdCDC = __constant_cpu_to_le16(0x1505), /* ??? */
+};
+
+static struct usb_cdc_union_desc
+pn_union_desc = {
+ .bLength = sizeof pn_union_desc,
+ .bDescriptorType = USB_DT_CS_INTERFACE,
+ .bDescriptorSubType = USB_CDC_UNION_TYPE,
+
+ /* .bMasterInterface0 = DYNAMIC, */
+ /* .bSlaveInterface0 = DYNAMIC, */
+};
+
+static struct usb_interface_descriptor
+pn_data_nop_intf_desc = {
+ .bLength = sizeof pn_data_nop_intf_desc,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC, */
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+};
+
+static struct usb_interface_descriptor
+pn_data_intf_desc = {
+ .bLength = sizeof pn_data_intf_desc,
+ .bDescriptorType = USB_DT_INTERFACE,
+
+ /* .bInterfaceNumber = DYNAMIC, */
+ .bAlternateSetting = 1,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = USB_CLASS_CDC_DATA,
+};
+
+static struct usb_endpoint_descriptor
+pn_fs_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor
+pn_hs_sink_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor
+pn_fs_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+};
+
+static struct usb_endpoint_descriptor
+pn_hs_source_desc = {
+ .bLength = USB_DT_ENDPOINT_SIZE,
+ .bDescriptorType = USB_DT_ENDPOINT,
+
+ .bEndpointAddress = USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = __constant_cpu_to_le16(512),
+};
+
+static struct usb_descriptor_header *fs_pn_function[] = {
+ (struct usb_descriptor_header *) &pn_control_intf_desc,
+ (struct usb_descriptor_header *) &pn_header_desc,
+ (struct usb_descriptor_header *) &pn_phonet_desc,
+ (struct usb_descriptor_header *) &pn_union_desc,
+ (struct usb_descriptor_header *) &pn_data_nop_intf_desc,
+ (struct usb_descriptor_header *) &pn_data_intf_desc,
+ (struct usb_descriptor_header *) &pn_fs_sink_desc,
+ (struct usb_descriptor_header *) &pn_fs_source_desc,
+ NULL,
+};
+
+static struct usb_descriptor_header *hs_pn_function[] = {
+ (struct usb_descriptor_header *) &pn_control_intf_desc,
+ (struct usb_descriptor_header *) &pn_header_desc,
+ (struct usb_descriptor_header *) &pn_phonet_desc,
+ (struct usb_descriptor_header *) &pn_union_desc,
+ (struct usb_descriptor_header *) &pn_data_nop_intf_desc,
+ (struct usb_descriptor_header *) &pn_data_intf_desc,
+ (struct usb_descriptor_header *) &pn_hs_sink_desc,
+ (struct usb_descriptor_header *) &pn_hs_source_desc,
+ NULL,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int pn_net_open(struct net_device *dev)
+{
+ if (netif_carrier_ok(dev))
+ netif_wake_queue(dev);
+ return 0;
+}
+
+static int pn_net_close(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ return 0;
+}
+
+static void pn_tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_phonet *fp = ep->driver_data;
+ struct net_device *dev = fp->dev;
+ struct sk_buff *skb = req->context;
+
+ switch (req->status) {
+ case 0:
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+ break;
+
+ case -ESHUTDOWN: /* disconnected */
+ case -ECONNRESET: /* disabled */
+ dev->stats.tx_aborted_errors++;
+ default:
+ dev->stats.tx_errors++;
+ }
+
+ dev_kfree_skb_any(skb);
+ if (netif_carrier_ok(dev))
+ netif_wake_queue(dev);
+}
+
+static int pn_net_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct phonet_port *port = netdev_priv(dev);
+ struct f_phonet *fp;
+ struct usb_request *req;
+ unsigned long flags;
+
+ if (skb->protocol != htons(ETH_P_PHONET))
+ goto out;
+
+ spin_lock_irqsave(&port->lock, flags);
+ fp = port->usb;
+ if (unlikely(!fp)) /* race with carrier loss */
+ goto out_unlock;
+
+ req = fp->in_req;
+ req->buf = skb->data;
+ req->length = skb->len;
+ req->complete = pn_tx_complete;
+ req->zero = 1;
+ req->context = skb;
+
+ if (unlikely(usb_ep_queue(fp->in_ep, req, GFP_ATOMIC)))
+ goto out_unlock;
+
+ netif_stop_queue(dev);
+ skb = NULL;
+
+out_unlock:
+ spin_unlock_irqrestore(&port->lock, flags);
+out:
+ if (unlikely(skb)) {
+ dev_kfree_skb_any(skb);
+ dev->stats.tx_dropped++;
+ }
+ return 0;
+}
+
+static int pn_net_mtu(struct net_device *dev, int new_mtu)
+{
+ struct phonet_port *port = netdev_priv(dev);
+ unsigned long flags;
+ int err = -EBUSY;
+
+ if ((new_mtu < PHONET_MIN_MTU) || (new_mtu > PHONET_MAX_MTU))
+ return -EINVAL;
+
+ spin_lock_irqsave(&port->lock, flags);
+ if (!netif_carrier_ok(dev)) {
+ dev->mtu = new_mtu;
+ err = 0;
+ }
+ spin_unlock_irqrestore(&port->lock, flags);
+ return err;
+}
+
+static void pn_net_setup(struct net_device *dev)
+{
+ dev->features = 0;
+ dev->type = ARPHRD_PHONET;
+ dev->flags = IFF_POINTOPOINT | IFF_NOARP;
+ dev->mtu = PHONET_DEV_MTU;
+ dev->hard_header_len = 1;
+ dev->dev_addr[0] = PN_MEDIA_USB;
+ dev->addr_len = 1;
+ dev->tx_queue_len = 1;
+
+ dev->destructor = free_netdev;
+ dev->header_ops = &phonet_header_ops;
+ dev->open = pn_net_open;
+ dev->stop = pn_net_close;
+ dev->hard_start_xmit = pn_net_xmit; /* mandatory */
+ dev->change_mtu = pn_net_mtu;
+}
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Queue buffer for data from the host
+ */
+static int
+pn_rx_submit(struct f_phonet *fp, struct usb_request *req, gfp_t gfp_flags)
+{
+ struct sk_buff *skb;
+ const size_t size = fp->dev->mtu;
+ int err;
+
+ skb = alloc_skb(size, gfp_flags);
+ if (!skb)
+ return -ENOMEM;
+
+ req->buf = skb->data;
+ req->length = size;
+ req->context = skb;
+
+ err = usb_ep_queue(fp->out_ep, req, gfp_flags);
+ if (unlikely(err))
+ dev_kfree_skb_any(skb);
+ return err;
+}
+
+static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+ struct f_phonet *fp = ep->driver_data;
+ struct net_device *dev = fp->dev;
+ struct sk_buff *skb = req->context;
+ int status = req->status;
+
+ switch (status) {
+ case 0:
+ if (unlikely(!netif_running(dev)))
+ break;
+ if (unlikely(req->actual < 1))
+ break;
+ skb_put(skb, req->actual);
+ skb->protocol = htons(ETH_P_PHONET);
+ skb_reset_mac_header(skb);
+ __skb_pull(skb, 1);
+ skb->dev = dev;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+
+ netif_rx(skb);
+ skb = NULL;
+ break;
+
+ /* Do not resubmit in these cases: */
+ case -ESHUTDOWN: /* disconnect */
+ case -ECONNABORTED: /* hw reset */
+ case -ECONNRESET: /* dequeued (unlink or netif down) */
+ req = NULL;
+ break;
+
+ /* Do resubmit in these cases: */
+ case -EOVERFLOW: /* request buffer overflow */
+ dev->stats.rx_over_errors++;
+ default:
+ dev->stats.rx_errors++;
+ break;
+ }
+
+ if (skb)
+ dev_kfree_skb_any(skb);
+ if (req)
+ pn_rx_submit(fp, req, GFP_ATOMIC);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static void __pn_reset(struct usb_function *f)
+{
+ struct f_phonet *fp = func_to_pn(f);
+ struct net_device *dev = fp->dev;
+ struct phonet_port *port = netdev_priv(dev);
+
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+ port->usb = NULL;
+
+ usb_ep_disable(fp->out_ep);
+ usb_ep_disable(fp->in_ep);
+}
+
+static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+ struct f_phonet *fp = func_to_pn(f);
+ struct usb_gadget *gadget = fp->function.config->cdev->gadget;
+
+ if (intf == pn_control_intf_desc.bInterfaceNumber)
+ /* control interface, no altsetting */
+ return (alt > 0) ? -EINVAL : 0;
+
+ if (intf == pn_data_intf_desc.bInterfaceNumber) {
+ struct net_device *dev = fp->dev;
+ struct phonet_port *port = netdev_priv(dev);
+
+ /* data intf (0: inactive, 1: active) */
+ if (alt > 1)
+ return -EINVAL;
+
+ spin_lock(&port->lock);
+ __pn_reset(f);
+ if (alt == 1) {
+ struct usb_endpoint_descriptor *out, *in;
+ int i;
+
+ out = ep_choose(gadget,
+ &pn_hs_sink_desc,
+ &pn_fs_sink_desc);
+ in = ep_choose(gadget,
+ &pn_hs_source_desc,
+ &pn_fs_source_desc);
+ usb_ep_enable(fp->out_ep, out);
+ usb_ep_enable(fp->in_ep, in);
+
+ port->usb = fp;
+ fp->out_ep->driver_data = fp;
+ fp->in_ep->driver_data = fp;
+
+ netif_carrier_on(dev);
+ if (netif_running(dev))
+ netif_wake_queue(dev);
+ for (i = 0; i < phonet_rxq_size; i++)
+ pn_rx_submit(fp, fp->out_reqv[i], GFP_ATOMIC);
+ }
+ spin_unlock(&port->lock);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int pn_get_alt(struct usb_function *f, unsigned intf)
+{
+ struct f_phonet *fp = func_to_pn(f);
+
+ if (intf == pn_control_intf_desc.bInterfaceNumber)
+ return 0;
+
+ if (intf == pn_data_intf_desc.bInterfaceNumber) {
+ struct phonet_port *port = netdev_priv(fp->dev);
+ u8 alt;
+
+ spin_lock(&port->lock);
+ alt = port->usb != NULL;
+ spin_unlock(&port->lock);
+ return alt;
+ }
+
+ return -EINVAL;
+}
+
+static void pn_disconnect(struct usb_function *f)
+{
+ struct f_phonet *fp = func_to_pn(f);
+ struct phonet_port *port = netdev_priv(fp->dev);
+ unsigned long flags;
+
+ /* remain disabled until set_alt */
+ spin_lock_irqsave(&port->lock, flags);
+ __pn_reset(f);
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static __init
+int pn_bind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct usb_composite_dev *cdev = c->cdev;
+ struct usb_gadget *gadget = cdev->gadget;
+ struct f_phonet *fp = func_to_pn(f);
+ struct usb_ep *ep;
+ int status, i;
+
+ /* Reserve interface IDs */
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto err;
+ pn_control_intf_desc.bInterfaceNumber = status;
+ pn_union_desc.bMasterInterface0 = status;
+
+ status = usb_interface_id(c, f);
+ if (status < 0)
+ goto err;
+ pn_data_nop_intf_desc.bInterfaceNumber = status;
+ pn_data_intf_desc.bInterfaceNumber = status;
+ pn_union_desc.bSlaveInterface0 = status;
+
+ /* Reserve endpoints */
+ status = -ENODEV;
+ ep = usb_ep_autoconfig(gadget, &pn_fs_sink_desc);
+ if (!ep)
+ goto err;
+ fp->out_ep = ep;
+ ep->driver_data = fp; /* Claim */
+
+ ep = usb_ep_autoconfig(gadget, &pn_fs_source_desc);
+ if (!ep)
+ goto err;
+ fp->in_ep = ep;
+ ep->driver_data = fp; /* Claim */
+
+ pn_hs_sink_desc.bEndpointAddress =
+ pn_fs_sink_desc.bEndpointAddress;
+ pn_hs_source_desc.bEndpointAddress =
+ pn_fs_source_desc.bEndpointAddress;
+
+ /* Do not try to bind Phonet twice... */
+ fp->function.descriptors = fs_pn_function;
+ fp->function.hs_descriptors = hs_pn_function;
+
+ /* Incoming USB requests */
+ status = -ENOMEM;
+ for (i = 0; i < phonet_rxq_size; i++) {
+ struct usb_request *req;
+
+ req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);
+ if (!req)
+ goto err;
+
+ req->complete = pn_rx_complete;
+ fp->out_reqv[i] = req;
+ }
+
+ /* Outgoing USB requests */
+ fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);
+ if (!fp->in_req)
+ goto err;
+
+ INFO(cdev, "USB CDC Phonet function\n");
+ INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,
+ fp->out_ep->name, fp->in_ep->name);
+ return 0;
+
+err:
+ if (fp->out_ep)
+ fp->out_ep->driver_data = NULL;
+ if (fp->in_ep)
+ fp->in_ep->driver_data = NULL;
+ ERROR(cdev, "USB CDC Phonet: cannot autoconfigure\n");
+ return status;
+}
+
+static void
+pn_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+ struct f_phonet *fp = func_to_pn(f);
+ int i;
+
+ /* We are already disconnected */
+ if (fp->in_req)
+ usb_ep_free_request(fp->in_ep, fp->in_req);
+ for (i = 0; i < phonet_rxq_size; i++)
+ if (fp->out_reqv[i])
+ usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
+
+ kfree(fp);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct net_device *dev;
+
+int __init phonet_bind_config(struct usb_configuration *c)
+{
+ struct f_phonet *fp;
+ int err;
+
+ fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+ if (!fp)
+ return -ENOMEM;
+
+ fp->dev = dev;
+ fp->function.name = "phonet";
+ fp->function.bind = pn_bind;
+ fp->function.unbind = pn_unbind;
+ fp->function.set_alt = pn_set_alt;
+ fp->function.get_alt = pn_get_alt;
+ fp->function.disable = pn_disconnect;
+
+ err = usb_add_function(c, &fp->function);
+ if (err)
+ kfree(fp);
+ return err;
+}
+
+int __init gphonet_setup(struct usb_gadget *gadget)
+{
+ struct phonet_port *port;
+ int err;
+
+ /* Create net device */
+ BUG_ON(dev);
+ dev = alloc_netdev(sizeof(*port)
+ + (phonet_rxq_size * sizeof(struct usb_request *)),
+ "upnlink%d", pn_net_setup);
+ if (!dev)
+ return -ENOMEM;
+
+ port = netdev_priv(dev);
+ spin_lock_init(&port->lock);
+ netif_carrier_off(dev);
+ netif_stop_queue(dev);
+ SET_NETDEV_DEV(dev, &gadget->dev);
+
+ err = register_netdev(dev);
+ if (err)
+ free_netdev(dev);
+ return err;
+}
+
+void gphonet_cleanup(void)
+{
+ unregister_netdev(dev);
+}
diff --git a/drivers/usb/gadget/u_phonet.h b/drivers/usb/gadget/u_phonet.h
new file mode 100644
index 0000000..09a7525
--- /dev/null
+++ b/drivers/usb/gadget/u_phonet.h
@@ -0,0 +1,21 @@
+/*
+ * u_phonet.h - interface to Phonet
+ *
+ * Copyright (C) 2007-2008 by Nokia Corporation
+ *
+ * This software is distributed under the terms of the GNU General
+ * Public License ("GPL") as published by the Free Software Foundation,
+ * either version 2 of that License or (at your option) any later version.
+ */
+
+#ifndef __U_PHONET_H
+#define __U_PHONET_H
+
+#include <linux/usb/composite.h>
+#include <linux/usb/cdc.h>
+
+int gphonet_setup(struct usb_gadget *gadget);
+int phonet_bind_config(struct usb_configuration *c);
+void gphonet_cleanup(void);
+
+#endif /* __U_PHONET_H */
--
1.5.4.3
^ permalink raw reply related [flat|nested] 17+ messages in thread* Re: [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework
2008-12-17 14:07 ` [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework Rémi Denis-Courmont
@ 2008-12-17 23:53 ` David Miller
2008-12-29 15:44 ` Marcel Holtmann
1 sibling, 0 replies; 17+ messages in thread
From: David Miller @ 2008-12-17 23:53 UTC (permalink / raw)
To: remi.denis-courmont; +Cc: netdev
From: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Date: Wed, 17 Dec 2008 16:07:54 +0200
> This implements the Nokia vendor-specific communication device class
> function to exchange Phonet messages over USB. This function is already
> found in the "PC suite" USB profile of (non-Linux) Nokia handsets.
>
> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
Applied.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework
2008-12-17 14:07 ` [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework Rémi Denis-Courmont
2008-12-17 23:53 ` David Miller
@ 2008-12-29 15:44 ` Marcel Holtmann
2009-01-08 7:54 ` Rémi Denis-Courmont
1 sibling, 1 reply; 17+ messages in thread
From: Marcel Holtmann @ 2008-12-29 15:44 UTC (permalink / raw)
To: Rémi Denis-Courmont; +Cc: netdev
Hi Remi,
> This implements the Nokia vendor-specific communication device class
> function to exchange Phonet messages over USB. This function is already
> found in the "PC suite" USB profile of (non-Linux) Nokia handsets.
>
> Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
> ---
> drivers/usb/gadget/f_phonet.c | 621 +++++++++++++++++++++++++++++++++++++++++
> drivers/usb/gadget/u_phonet.h | 21 ++
> 2 files changed, 642 insertions(+), 0 deletions(-)
> create mode 100644 drivers/usb/gadget/f_phonet.c
> create mode 100644 drivers/usb/gadget/u_phonet.h
any reason why you didn't add an option to Kconfig to actually select
this gadget?
Regards
Marcel
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework
2008-12-29 15:44 ` Marcel Holtmann
@ 2009-01-08 7:54 ` Rémi Denis-Courmont
2009-01-08 17:15 ` Marcel Holtmann
0 siblings, 1 reply; 17+ messages in thread
From: Rémi Denis-Courmont @ 2009-01-08 7:54 UTC (permalink / raw)
To: ext Marcel Holtmann; +Cc: netdev
On Monday 29 December 2008 17:44:08 ext Marcel Holtmann, you wrote:
> > This implements the Nokia vendor-specific communication device class
> > function to exchange Phonet messages over USB. This function is already
> > found in the "PC suite" USB profile of (non-Linux) Nokia handsets.
> >
> > Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
> > ---
> > drivers/usb/gadget/f_phonet.c | 621
> > +++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/u_phonet.h |
> > 21 ++
> > 2 files changed, 642 insertions(+), 0 deletions(-)
> > create mode 100644 drivers/usb/gadget/f_phonet.c
> > create mode 100644 drivers/usb/gadget/u_phonet.h
>
> any reason why you didn't add an option to Kconfig to actually select
> this gadget?
Yeah: this is NOT a gadget. This is a function for any gadget that wishes to
use it. Same as the OBEX function in fact. What would be needed is a Kconfig
for some gadget that actually uses that.
A -slightly outdated- example is here:
http://repository.maemo.org/pool/maemo5.0/free/k/kernel/
Regards,
--
Rémi Denis-Courmont
Maemo Software, Nokia Devices R&D
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework
2009-01-08 7:54 ` Rémi Denis-Courmont
@ 2009-01-08 17:15 ` Marcel Holtmann
0 siblings, 0 replies; 17+ messages in thread
From: Marcel Holtmann @ 2009-01-08 17:15 UTC (permalink / raw)
To: Rémi Denis-Courmont; +Cc: netdev
Hi Remi,
> > > This implements the Nokia vendor-specific communication device class
> > > function to exchange Phonet messages over USB. This function is already
> > > found in the "PC suite" USB profile of (non-Linux) Nokia handsets.
> > >
> > > Signed-off-by: Rémi Denis-Courmont <remi.denis-courmont@nokia.com>
> > > ---
> > > drivers/usb/gadget/f_phonet.c | 621
> > > +++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/u_phonet.h |
> > > 21 ++
> > > 2 files changed, 642 insertions(+), 0 deletions(-)
> > > create mode 100644 drivers/usb/gadget/f_phonet.c
> > > create mode 100644 drivers/usb/gadget/u_phonet.h
> >
> > any reason why you didn't add an option to Kconfig to actually select
> > this gadget?
>
> Yeah: this is NOT a gadget. This is a function for any gadget that wishes to
> use it. Same as the OBEX function in fact. What would be needed is a Kconfig
> for some gadget that actually uses that.
>
> A -slightly outdated- example is here:
> http://repository.maemo.org/pool/maemo5.0/free/k/kernel/
I see. Makes sense to me now. Any reason why the g_nokia gadget is not
merged upstream? Would be nice to have this around for actually testing
the PhoNet stuff.
Regards
Marcel
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [RFC] [PATCH 0/5] Phonet enhancements
2008-12-17 14:07 [RFC] [PATCH 0/5] Phonet enhancements Rémi Denis-Courmont
` (4 preceding siblings ...)
2008-12-17 14:07 ` [PATCH 5/5] Phonet: USB CDC Phonet function for gadget framework Rémi Denis-Courmont
@ 2008-12-17 23:46 ` David Miller
5 siblings, 0 replies; 17+ messages in thread
From: David Miller @ 2008-12-17 23:46 UTC (permalink / raw)
To: remi.denis-courmont; +Cc: netdev
From: "Rémi Denis-Courmont" <remi.denis-courmont@nokia.com>
Date: Wed, 17 Dec 2008 16:07:14 +0200
> This simplifies the GPRS over Phonet virtual interface driver, and
> adds support for a Phonet USB gadget (the latter will need to go
> through linux-usb?). Comments welcome.
I'll put the USB bits into net-next-2.6 for now.
If it causes merge hassles for the USB folks we'll need
to figure something out, but I doubt it will cause
real problems.
^ permalink raw reply [flat|nested] 17+ messages in thread