* [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl. @ 2010-06-17 16:55 sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation sjur.brandeland 2010-06-21 3:38 ` [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl David Miller 0 siblings, 2 replies; 8+ messages in thread From: sjur.brandeland @ 2010-06-17 16:55 UTC (permalink / raw) To: sjurbr, netdev, davem; +Cc: linus.walleij, Sjur Braendeland From: Sjur Braendeland <sjur.brandeland@stericsson.com> Flow control is not used by all CAIF services. The usage of flow control is now part of the gerneal initialization function for CAIF Services. Signed-off-by: Sjur Braendeland@stericsson.com --- include/net/caif/cfsrvl.h | 6 ++++-- net/caif/cfctrl.c | 2 +- net/caif/cfdbgl.c | 2 +- net/caif/cfdgml.c | 2 +- net/caif/cfrfml.c | 12 ++++-------- net/caif/cfsrvl.c | 14 ++++++++++++-- net/caif/cfutill.c | 2 +- net/caif/cfveil.c | 2 +- net/caif/cfvidl.c | 2 +- 9 files changed, 26 insertions(+), 18 deletions(-) diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h index 2dc9eb1..5d921f5 100644 --- a/include/net/caif/cfsrvl.h +++ b/include/net/caif/cfsrvl.h @@ -16,6 +16,7 @@ struct cfsrvl { bool open; bool phy_flow_on; bool modem_flow_on; + bool supports_flowctrl; struct dev_info dev_info; struct kref ref; }; @@ -30,8 +31,9 @@ struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); void cfservl_destroy(struct cflayer *layer); void cfsrvl_init(struct cfsrvl *service, - u8 channel_id, - struct dev_info *dev_info); + u8 channel_id, + struct dev_info *dev_info, + bool supports_flowctrl); bool cfsrvl_ready(struct cfsrvl *service, int *err); u8 cfsrvl_getphyid(struct cflayer *layer); diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index fcfda98..107c4b2 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -43,7 +43,7 @@ struct cflayer *cfctrl_create(void) memset(&dev_info, 0, sizeof(dev_info)); dev_info.id = 0xff; memset(this, 0, sizeof(*this)); - cfsrvl_init(&this->serv, 0, &dev_info); + cfsrvl_init(&this->serv, 0, &dev_info, false); atomic_set(&this->req_seq_no, 1); atomic_set(&this->rsp_seq_no, 1); this->serv.layer.receive = cfctrl_recv; diff --git a/net/caif/cfdbgl.c b/net/caif/cfdbgl.c index ab6b6dc..676648c 100644 --- a/net/caif/cfdbgl.c +++ b/net/caif/cfdbgl.c @@ -22,7 +22,7 @@ struct cflayer *cfdbgl_create(u8 channel_id, struct dev_info *dev_info) } caif_assert(offsetof(struct cfsrvl, layer) == 0); memset(dbg, 0, sizeof(struct cfsrvl)); - cfsrvl_init(dbg, channel_id, dev_info); + cfsrvl_init(dbg, channel_id, dev_info, false); dbg->layer.receive = cfdbgl_receive; dbg->layer.transmit = cfdbgl_transmit; snprintf(dbg->layer.name, CAIF_LAYER_NAME_SZ - 1, "dbg%d", channel_id); diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c index 5319484..32d9f0d 100644 --- a/net/caif/cfdgml.c +++ b/net/caif/cfdgml.c @@ -30,7 +30,7 @@ struct cflayer *cfdgml_create(u8 channel_id, struct dev_info *dev_info) } caif_assert(offsetof(struct cfsrvl, layer) == 0); memset(dgm, 0, sizeof(struct cfsrvl)); - cfsrvl_init(dgm, channel_id, dev_info); + cfsrvl_init(dgm, channel_id, dev_info, true); dgm->layer.receive = cfdgml_receive; dgm->layer.transmit = cfdgml_transmit; snprintf(dgm->layer.name, CAIF_LAYER_NAME_SZ - 1, "dgm%d", channel_id); diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index fd27b17..689cbfd 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -23,30 +23,26 @@ static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt); static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt); -static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl); struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info) { struct cfsrvl *rfm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); + if (!rfm) { pr_warning("CAIF: %s(): Out of memory\n", __func__); return NULL; } + caif_assert(offsetof(struct cfsrvl, layer) == 0); + memset(rfm, 0, sizeof(struct cfsrvl)); - cfsrvl_init(rfm, channel_id, dev_info); - rfm->layer.modemcmd = cfservl_modemcmd; + cfsrvl_init(rfm, channel_id, dev_info, false); rfm->layer.receive = cfrfml_receive; rfm->layer.transmit = cfrfml_transmit; snprintf(rfm->layer.name, CAIF_LAYER_NAME_SZ, "rfm%d", channel_id); return &rfm->layer; } -static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) -{ - return -EPROTO; -} - static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt) { u8 tmp; diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 6e5b707..7aa1f03 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -24,8 +24,10 @@ static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, int phyid) { struct cfsrvl *service = container_obj(layr); + caif_assert(layr->up != NULL); caif_assert(layr->up->ctrlcmd != NULL); + switch (ctrl) { case CAIF_CTRLCMD_INIT_RSP: service->open = true; @@ -89,9 +91,14 @@ static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) { struct cfsrvl *service = container_obj(layr); + caif_assert(layr != NULL); caif_assert(layr->dn != NULL); caif_assert(layr->dn->transmit != NULL); + + if (!service->supports_flowctrl) + return 0; + switch (ctrl) { case CAIF_MODEMCMD_FLOW_ON_REQ: { @@ -153,8 +160,10 @@ void cfservl_destroy(struct cflayer *layer) } void cfsrvl_init(struct cfsrvl *service, - u8 channel_id, - struct dev_info *dev_info) + u8 channel_id, + struct dev_info *dev_info, + bool supports_flowctrl + ) { caif_assert(offsetof(struct cfsrvl, layer) == 0); service->open = false; @@ -164,6 +173,7 @@ void cfsrvl_init(struct cfsrvl *service, service->layer.ctrlcmd = cfservl_ctrlcmd; service->layer.modemcmd = cfservl_modemcmd; service->dev_info = *dev_info; + service->supports_flowctrl = supports_flowctrl; kref_init(&service->ref); } diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c index 5fd2c9e..ce525ca 100644 --- a/net/caif/cfutill.c +++ b/net/caif/cfutill.c @@ -31,7 +31,7 @@ struct cflayer *cfutill_create(u8 channel_id, struct dev_info *dev_info) } caif_assert(offsetof(struct cfsrvl, layer) == 0); memset(util, 0, sizeof(struct cfsrvl)); - cfsrvl_init(util, channel_id, dev_info); + cfsrvl_init(util, channel_id, dev_info, true); util->layer.receive = cfutill_receive; util->layer.transmit = cfutill_transmit; snprintf(util->layer.name, CAIF_LAYER_NAME_SZ - 1, "util1"); diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c index e04f7d9..637cb0e 100644 --- a/net/caif/cfveil.c +++ b/net/caif/cfveil.c @@ -30,7 +30,7 @@ struct cflayer *cfvei_create(u8 channel_id, struct dev_info *dev_info) } caif_assert(offsetof(struct cfsrvl, layer) == 0); memset(vei, 0, sizeof(struct cfsrvl)); - cfsrvl_init(vei, channel_id, dev_info); + cfsrvl_init(vei, channel_id, dev_info, true); vei->layer.receive = cfvei_receive; vei->layer.transmit = cfvei_transmit; snprintf(vei->layer.name, CAIF_LAYER_NAME_SZ - 1, "vei%d", channel_id); diff --git a/net/caif/cfvidl.c b/net/caif/cfvidl.c index 89ad4ea..ada6ee2 100644 --- a/net/caif/cfvidl.c +++ b/net/caif/cfvidl.c @@ -27,7 +27,7 @@ struct cflayer *cfvidl_create(u8 channel_id, struct dev_info *dev_info) caif_assert(offsetof(struct cfsrvl, layer) == 0); memset(vid, 0, sizeof(struct cfsrvl)); - cfsrvl_init(vid, channel_id, dev_info); + cfsrvl_init(vid, channel_id, dev_info, false); vid->layer.receive = cfvidl_receive; vid->layer.transmit = cfvidl_transmit; snprintf(vid->layer.name, CAIF_LAYER_NAME_SZ - 1, "vid1"); -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation. 2010-06-17 16:55 [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl sjur.brandeland @ 2010-06-17 16:55 ` sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU sjur.brandeland 2010-06-21 3:38 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation David Miller 2010-06-21 3:38 ` [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl David Miller 1 sibling, 2 replies; 8+ messages in thread From: sjur.brandeland @ 2010-06-17 16:55 UTC (permalink / raw) To: sjurbr, netdev, davem; +Cc: linus.walleij, Sjur Braendeland From: Sjur Braendeland <sjur.brandeland@stericsson.com> CAIF Remote File Manager may send or receive more than 4050 bytes. Due to this The CAIF RFM service have to support segmentation. Signed-off-by: Sjur Braendeland@stericsson.com --- include/net/caif/cfsrvl.h | 9 +- net/caif/caif_socket.c | 4 - net/caif/cfcnfg.c | 4 +- net/caif/cfpkt_skbuff.c | 1 - net/caif/cfrfml.c | 314 +++++++++++++++++++++++++++++++++++++-------- net/caif/cfsrvl.c | 13 +- 6 files changed, 278 insertions(+), 67 deletions(-) diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h index 5d921f5..b1fa87e 100644 --- a/include/net/caif/cfsrvl.h +++ b/include/net/caif/cfsrvl.h @@ -17,6 +17,7 @@ struct cfsrvl { bool phy_flow_on; bool modem_flow_on; bool supports_flowctrl; + void (*release)(struct kref *); struct dev_info dev_info; struct kref ref; }; @@ -26,7 +27,8 @@ struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); struct cflayer *cfdgml_create(u8 linkid, struct dev_info *dev_info); struct cflayer *cfutill_create(u8 linkid, struct dev_info *dev_info); struct cflayer *cfvidl_create(u8 linkid, struct dev_info *dev_info); -struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info); +struct cflayer *cfrfml_create(u8 linkid, struct dev_info *dev_info, + int mtu_size); struct cflayer *cfdbgl_create(u8 linkid, struct dev_info *dev_info); bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); void cfservl_destroy(struct cflayer *layer); @@ -52,7 +54,10 @@ static inline void cfsrvl_put(struct cflayer *layr) if (layr == NULL) return; s = container_of(layr, struct cfsrvl, layer); - kref_put(&s->ref, cfsrvl_release); + + WARN_ON(!s->release); + if (s->release) + kref_put(&s->ref, s->release); } #endif /* CFSRVL_H_ */ diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 7912493..848ae75 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -596,10 +596,6 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM; - ret = -EMSGSIZE; - if (buffer_size > CAIF_MAX_PAYLOAD_SIZE) - goto err; - timeo = sock_sndtimeo(sk, noblock); timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), 1, timeo, &ret); diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index 7c81974..cff2dcb 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -22,6 +22,7 @@ #define PHY_NAME_LEN 20 #define container_obj(layr) container_of(layr, struct cfcnfg, layer) +#define RFM_FRAGMENT_SIZE 4030 /* Information about CAIF physical interfaces held by Config Module in order * to manage physical interfaces @@ -328,7 +329,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, servicel = cfdgml_create(channel_id, &phyinfo->dev_info); break; case CFCTRL_SRV_RFM: - servicel = cfrfml_create(channel_id, &phyinfo->dev_info); + servicel = cfrfml_create(channel_id, &phyinfo->dev_info, + RFM_FRAGMENT_SIZE); break; case CFCTRL_SRV_UTIL: servicel = cfutill_create(channel_id, &phyinfo->dev_info); diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index a6fdf89..318b0f4 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -338,7 +338,6 @@ struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, u16 dstlen; u16 createlen; if (unlikely(is_erronous(dstpkt) || is_erronous(addpkt))) { - cfpkt_destroy(addpkt); return dstpkt; } if (expectlen > addlen) diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index 689cbfd..4b04d25 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -7,98 +7,304 @@ #include <linux/stddef.h> #include <linux/spinlock.h> #include <linux/slab.h> +#include <linux/unaligned/le_byteshift.h> #include <net/caif/caif_layer.h> #include <net/caif/cfsrvl.h> #include <net/caif/cfpkt.h> -#define container_obj(layr) container_of(layr, struct cfsrvl, layer) - +#define container_obj(layr) container_of(layr, struct cfrfml, serv.layer) #define RFM_SEGMENTATION_BIT 0x01 -#define RFM_PAYLOAD 0x00 -#define RFM_CMD_BIT 0x80 -#define RFM_FLOW_OFF 0x81 -#define RFM_FLOW_ON 0x80 -#define RFM_SET_PIN 0x82 -#define RFM_CTRL_PKT_SIZE 1 +#define RFM_HEAD_SIZE 7 static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt); static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt); -struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info) +struct cfrfml { + struct cfsrvl serv; + struct cfpkt *incomplete_frm; + int fragment_size; + u8 seghead[6]; + u16 pdu_size; + /* Protects serialized processing of packets */ + spinlock_t sync; +}; + +static void cfrfml_release(struct kref *kref) +{ + struct cfsrvl *srvl = container_of(kref, struct cfsrvl, ref); + struct cfrfml *rfml = container_obj(&srvl->layer); + + if (rfml->incomplete_frm) + cfpkt_destroy(rfml->incomplete_frm); + + kfree(srvl); +} + +struct cflayer *cfrfml_create(u8 channel_id, struct dev_info *dev_info, + int mtu_size) { - struct cfsrvl *rfm = kmalloc(sizeof(struct cfsrvl), GFP_ATOMIC); + int tmp; + struct cfrfml *this = + kzalloc(sizeof(struct cfrfml), GFP_ATOMIC); - if (!rfm) { + if (!this) { pr_warning("CAIF: %s(): Out of memory\n", __func__); return NULL; } - caif_assert(offsetof(struct cfsrvl, layer) == 0); + cfsrvl_init(&this->serv, channel_id, dev_info, false); + this->serv.release = cfrfml_release; + this->serv.layer.receive = cfrfml_receive; + this->serv.layer.transmit = cfrfml_transmit; + + /* Round down to closest multiple of 16 */ + tmp = (mtu_size - RFM_HEAD_SIZE - 6) / 16; + tmp *= 16; + + this->fragment_size = tmp; + spin_lock_init(&this->sync); + snprintf(this->serv.layer.name, CAIF_LAYER_NAME_SZ, + "rfm%d", channel_id); + + return &this->serv.layer; +} + +static struct cfpkt *rfm_append(struct cfrfml *rfml, char *seghead, + struct cfpkt *pkt, int *err) +{ + struct cfpkt *tmppkt; + *err = -EPROTO; + /* n-th but not last segment */ + + if (cfpkt_extr_head(pkt, seghead, 6) < 0) + return NULL; + + /* Verify correct header */ + if (memcmp(seghead, rfml->seghead, 6) != 0) + return NULL; + + tmppkt = cfpkt_append(rfml->incomplete_frm, pkt, + rfml->pdu_size + RFM_HEAD_SIZE); + + /* If cfpkt_append failes input pkts are not freed */ + *err = -ENOMEM; + if (tmppkt == NULL) + return NULL; - memset(rfm, 0, sizeof(struct cfsrvl)); - cfsrvl_init(rfm, channel_id, dev_info, false); - rfm->layer.receive = cfrfml_receive; - rfm->layer.transmit = cfrfml_transmit; - snprintf(rfm->layer.name, CAIF_LAYER_NAME_SZ, "rfm%d", channel_id); - return &rfm->layer; + *err = 0; + return tmppkt; } static int cfrfml_receive(struct cflayer *layr, struct cfpkt *pkt) { u8 tmp; bool segmented; - int ret; + int err; + u8 seghead[6]; + struct cfrfml *rfml; + struct cfpkt *tmppkt = NULL; + caif_assert(layr->up != NULL); caif_assert(layr->receive != NULL); + rfml = container_obj(layr); + spin_lock(&rfml->sync); + + err = -EPROTO; + if (cfpkt_extr_head(pkt, &tmp, 1) < 0) + goto out; + segmented = tmp & RFM_SEGMENTATION_BIT; + + if (segmented) { + if (rfml->incomplete_frm == NULL) { + /* Initial Segment */ + if (cfpkt_peek_head(pkt, rfml->seghead, 6) < 0) + goto out; + + rfml->pdu_size = get_unaligned_le16(rfml->seghead+4); + + if (cfpkt_erroneous(pkt)) + goto out; + rfml->incomplete_frm = pkt; + pkt = NULL; + } else { + + tmppkt = rfm_append(rfml, seghead, pkt, &err); + if (tmppkt == NULL) + goto out; + + if (cfpkt_erroneous(tmppkt)) + goto out; + + rfml->incomplete_frm = tmppkt; + + + if (cfpkt_erroneous(tmppkt)) + goto out; + } + err = 0; + goto out; + } + + if (rfml->incomplete_frm) { + + /* Last Segment */ + tmppkt = rfm_append(rfml, seghead, pkt, &err); + if (tmppkt == NULL) + goto out; + + if (cfpkt_erroneous(tmppkt)) + goto out; + + rfml->incomplete_frm = NULL; + pkt = tmppkt; + tmppkt = NULL; + + /* Verify that length is correct */ + err = EPROTO; + if (rfml->pdu_size != cfpkt_getlen(pkt) - RFM_HEAD_SIZE + 1) + goto out; + } + + err = rfml->serv.layer.up->receive(rfml->serv.layer.up, pkt); + +out: + + if (err != 0) { + if (tmppkt) + cfpkt_destroy(tmppkt); + if (pkt) + cfpkt_destroy(pkt); + if (rfml->incomplete_frm) + cfpkt_destroy(rfml->incomplete_frm); + rfml->incomplete_frm = NULL; + + pr_info("CAIF: %s(): " + "Connection error %d triggered on RFM link\n", + __func__, err); + + /* Trigger connection error upon failure.*/ + layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, + rfml->serv.dev_info.id); + } + spin_unlock(&rfml->sync); + return err; +} + + +static int cfrfml_transmit_segment(struct cfrfml *rfml, struct cfpkt *pkt) +{ + caif_assert(!cfpkt_getlen(pkt) < rfml->fragment_size); + + /* Add info for MUX-layer to route the packet out. */ + cfpkt_info(pkt)->channel_id = rfml->serv.layer.id; /* - * RFM is taking care of segmentation and stripping of - * segmentation bit. + * To optimize alignment, we add up the size of CAIF header before + * payload. */ - if (cfpkt_extr_head(pkt, &tmp, 1) < 0) { - pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); - cfpkt_destroy(pkt); - return -EPROTO; - } - segmented = tmp & RFM_SEGMENTATION_BIT; - caif_assert(!segmented); + cfpkt_info(pkt)->hdr_len = RFM_HEAD_SIZE; + cfpkt_info(pkt)->dev_info = &rfml->serv.dev_info; - ret = layr->up->receive(layr->up, pkt); - return ret; + return rfml->serv.layer.dn->transmit(rfml->serv.layer.dn, pkt); } static int cfrfml_transmit(struct cflayer *layr, struct cfpkt *pkt) { - u8 tmp = 0; - int ret; - struct cfsrvl *service = container_obj(layr); + int err; + u8 seg; + u8 head[6]; + struct cfpkt *rearpkt = NULL; + struct cfpkt *frontpkt = pkt; + struct cfrfml *rfml = container_obj(layr); caif_assert(layr->dn != NULL); caif_assert(layr->dn->transmit != NULL); - if (!cfsrvl_ready(service, &ret)) - return ret; + if (!cfsrvl_ready(&rfml->serv, &err)) + return err; + + err = -EPROTO; + if (cfpkt_getlen(pkt) <= RFM_HEAD_SIZE-1) + goto out; + + err = 0; + if (cfpkt_getlen(pkt) > rfml->fragment_size + RFM_HEAD_SIZE) + err = cfpkt_peek_head(pkt, head, 6); + + if (err < 0) + goto out; + + while (cfpkt_getlen(frontpkt) > rfml->fragment_size + RFM_HEAD_SIZE) { + + seg = 1; + err = -EPROTO; + + if (cfpkt_add_head(frontpkt, &seg, 1) < 0) + goto out; + /* + * On OOM error cfpkt_split returns NULL. + * + * NOTE: Segmented pdu is not correctly aligned. + * This has negative performance impact. + */ + + rearpkt = cfpkt_split(frontpkt, rfml->fragment_size); + if (rearpkt == NULL) + goto out; + + err = cfrfml_transmit_segment(rfml, frontpkt); + + if (err != 0) + goto out; + frontpkt = rearpkt; + rearpkt = NULL; + + err = -ENOMEM; + if (frontpkt == NULL) + goto out; + err = -EPROTO; + if (cfpkt_add_head(frontpkt, head, 6) < 0) + goto out; - if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { - pr_err("CAIF: %s():Packet too large - size=%d\n", - __func__, cfpkt_getlen(pkt)); - return -EOVERFLOW; } - if (cfpkt_add_head(pkt, &tmp, 1) < 0) { - pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); - return -EPROTO; + + seg = 0; + err = -EPROTO; + + if (cfpkt_add_head(frontpkt, &seg, 1) < 0) + goto out; + + err = cfrfml_transmit_segment(rfml, frontpkt); + + frontpkt = NULL; +out: + + if (err != 0) { + pr_info("CAIF: %s(): " + "Connection error %d triggered on RFM link\n", + __func__, err); + /* Trigger connection error upon failure.*/ + + layr->up->ctrlcmd(layr->up, CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, + rfml->serv.dev_info.id); + + if (rearpkt) + cfpkt_destroy(rearpkt); + + if (frontpkt && frontpkt != pkt) { + + cfpkt_destroy(frontpkt); + /* + * Socket layer will free the original packet, + * but this packet may already be sent and + * freed. So we have to return 0 in this case + * to avoid socket layer to re-free this packet. + * The return of shutdown indication will + * cause connection to be invalidated anyhow. + */ + err = 0; + } } - /* Add info for MUX-layer to route the packet out. */ - cfpkt_info(pkt)->channel_id = service->layer.id; - /* - * To optimize alignment, we add up the size of CAIF header before - * payload. - */ - cfpkt_info(pkt)->hdr_len = 1; - cfpkt_info(pkt)->dev_info = &service->dev_info; - ret = layr->dn->transmit(layr->dn, pkt); - if (ret < 0) - cfpkt_extr_head(pkt, &tmp, 1); - return ret; + return err; } diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 7aa1f03..4c9f147 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -159,6 +159,13 @@ void cfservl_destroy(struct cflayer *layer) kfree(layer); } +void cfsrvl_release(struct kref *kref) +{ + struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); + pr_info("CAIF: %s(): enter\n", __func__); + kfree(service); +} + void cfsrvl_init(struct cfsrvl *service, u8 channel_id, struct dev_info *dev_info, @@ -174,14 +181,10 @@ void cfsrvl_init(struct cfsrvl *service, service->layer.modemcmd = cfservl_modemcmd; service->dev_info = *dev_info; service->supports_flowctrl = supports_flowctrl; + service->release = cfsrvl_release; kref_init(&service->ref); } -void cfsrvl_release(struct kref *kref) -{ - struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); - kfree(service); -} bool cfsrvl_ready(struct cfsrvl *service, int *err) { -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU 2010-06-17 16:55 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation sjur.brandeland @ 2010-06-17 16:55 ` sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 4/4] caif: Add debug connection type for CAIF sjur.brandeland 2010-06-21 3:39 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU David Miller 2010-06-21 3:38 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation David Miller 1 sibling, 2 replies; 8+ messages in thread From: sjur.brandeland @ 2010-06-17 16:55 UTC (permalink / raw) To: sjurbr, netdev, davem; +Cc: linus.walleij, Sjur Braendeland From: Sjur Braendeland <sjur.brandeland@stericsson.com> Previously CAIF supported maximum transfer size of ~4050. The transfer size is now calculated dynamically based on the link layers mtu size. Signed-off-by: Sjur Braendeland@stericsson.com --- drivers/net/caif/caif_serial.c | 1 - include/net/caif/caif_dev.h | 8 +++- include/net/caif/caif_layer.h | 6 --- include/net/caif/cfcnfg.h | 16 +++++++-- net/caif/caif_dev.c | 12 +++++-- net/caif/caif_socket.c | 54 +++++++++++++++++++++----------- net/caif/cfcnfg.c | 44 ++++++++++++++++++++++++-- net/caif/cfctrl.c | 6 ++-- net/caif/cfdgml.c | 5 +++ net/caif/cfpkt_skbuff.c | 4 +- net/caif/cfserl.c | 7 ++-- net/caif/cfsrvl.c | 1 - net/caif/cfutill.c | 6 --- net/caif/cfveil.c | 5 --- net/caif/chnl_net.c | 67 ++++++++++++++++++++++++++++++++++------ 15 files changed, 173 insertions(+), 69 deletions(-) diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 3e706f0..3df0c0f 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -403,7 +403,6 @@ static void caifdev_setup(struct net_device *dev) dev->type = ARPHRD_CAIF; dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->mtu = CAIF_MAX_MTU; - dev->hard_header_len = CAIF_NEEDED_HEADROOM; dev->tx_queue_len = 0; dev->destructor = free_netdev; skb_queue_head_init(&serdev->head); diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h index 318ab94..6da573c 100644 --- a/include/net/caif/caif_dev.h +++ b/include/net/caif/caif_dev.h @@ -50,6 +50,9 @@ struct caif_connect_request { * @client_layer: User implementation of client layer. This layer * MUST have receive and control callback functions * implemented. + * @ifindex: Link layer interface index used for this connection. + * @headroom: Head room needed by CAIF protocol. + * @tailroom: Tail room needed by CAIF protocol. * * This function connects a CAIF channel. The Client must implement * the struct cflayer. This layer represents the Client layer and holds @@ -59,8 +62,9 @@ struct caif_connect_request { * E.g. CAIF Socket will call this function for each socket it connects * and have one client_layer instance for each socket. */ -int caif_connect_client(struct caif_connect_request *config, - struct cflayer *client_layer); +int caif_connect_client(struct caif_connect_request *conn_req, + struct cflayer *client_layer, int *ifindex, + int *headroom, int *tailroom); /** * caif_disconnect_client - Disconnects a client from the CAIF stack. diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h index 25c472f..c8b07a9 100644 --- a/include/net/caif/caif_layer.h +++ b/include/net/caif/caif_layer.h @@ -15,14 +15,8 @@ struct cfpktq; struct caif_payload_info; struct caif_packet_funcs; -#define CAIF_MAX_FRAMESIZE 4096 -#define CAIF_MAX_PAYLOAD_SIZE (4096 - 64) -#define CAIF_NEEDED_HEADROOM (10) -#define CAIF_NEEDED_TAILROOM (2) #define CAIF_LAYER_NAME_SZ 16 -#define CAIF_SUCCESS 1 -#define CAIF_FAILURE 0 /** * caif_assert() - Assert function for CAIF. diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h index 9fc2fc2..bd646fa 100644 --- a/include/net/caif/cfcnfg.h +++ b/include/net/caif/cfcnfg.h @@ -7,6 +7,7 @@ #ifndef CFCNFG_H_ #define CFCNFG_H_ #include <linux/spinlock.h> +#include <linux/netdevice.h> #include <net/caif/caif_layer.h> #include <net/caif/cfctrl.h> @@ -73,8 +74,8 @@ void cfcnfg_remove(struct cfcnfg *cfg); void cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, - void *dev, struct cflayer *phy_layer, u16 *phyid, - enum cfcnfg_phy_preference pref, + struct net_device *dev, struct cflayer *phy_layer, + u16 *phyid, enum cfcnfg_phy_preference pref, bool fcs, bool stx); /** @@ -114,11 +115,18 @@ void cfcnfg_release_adap_layer(struct cflayer *adap_layer); * @param: Link setup parameters. * @adap_layer: Specify the adaptation layer; the receive and * flow-control functions MUST be set in the structure. - * + * @ifindex: Link layer interface index used for this connection. + * @proto_head: Protocol head-space needed by CAIF protocol, + * excluding link layer. + * @proto_tail: Protocol tail-space needed by CAIF protocol, + * excluding link layer. */ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, struct cfctrl_link_param *param, - struct cflayer *adap_layer); + struct cflayer *adap_layer, + int *ifindex, + int *proto_head, + int *proto_tail); /** * cfcnfg_get_phyid() - Get physical ID, given type. diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index e2b86f1..0b586e9 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -255,7 +255,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, pref = CFPHYPREF_HIGH_BW; break; } - + dev_hold(dev); cfcnfg_add_phy_layer(get_caif_conf(), phy_type, dev, @@ -285,6 +285,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, caifd->layer.up->ctrlcmd(caifd->layer.up, _CAIF_CTRLCMD_PHYIF_DOWN_IND, caifd->layer.id); + might_sleep(); res = wait_event_interruptible_timeout(caifd->event, atomic_read(&caifd->in_use) == 0, TIMEOUT); @@ -300,6 +301,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, "Unregistering an active CAIF device: %s\n", __func__, dev->name); cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer); + dev_put(dev); atomic_set(&caifd->state, what); break; @@ -326,7 +328,8 @@ struct cfcnfg *get_caif_conf(void) EXPORT_SYMBOL(get_caif_conf); int caif_connect_client(struct caif_connect_request *conn_req, - struct cflayer *client_layer) + struct cflayer *client_layer, int *ifindex, + int *headroom, int *tailroom) { struct cfctrl_link_param param; int ret; @@ -334,8 +337,9 @@ int caif_connect_client(struct caif_connect_request *conn_req, if (ret) return ret; /* Hook up the adaptation layer. */ - return cfcnfg_add_adaptation_layer(get_caif_conf(), - ¶m, client_layer); + return cfcnfg_add_adaptation_layer(get_caif_conf(), ¶m, + client_layer, ifindex, + headroom, tailroom); } EXPORT_SYMBOL(caif_connect_client); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 848ae75..8ce9047 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -28,8 +28,8 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS_NETPROTO(AF_CAIF); -#define CAIF_DEF_SNDBUF (CAIF_MAX_PAYLOAD_SIZE*10) -#define CAIF_DEF_RCVBUF (CAIF_MAX_PAYLOAD_SIZE*100) +#define CAIF_DEF_SNDBUF (4096*10) +#define CAIF_DEF_RCVBUF (4096*100) /* * CAIF state is re-using the TCP socket states. @@ -76,6 +76,7 @@ struct caifsock { struct caif_connect_request conn_req; struct mutex readlock; struct dentry *debugfs_socket_dir; + int headroom, tailroom, maxframe; }; static int rx_flow_is_on(struct caifsock *cf_sk) @@ -594,23 +595,32 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, goto err; noblock = msg->msg_flags & MSG_DONTWAIT; - buffer_size = len + CAIF_NEEDED_HEADROOM + CAIF_NEEDED_TAILROOM; - timeo = sock_sndtimeo(sk, noblock); timeo = caif_wait_for_flow_on(container_of(sk, struct caifsock, sk), 1, timeo, &ret); + if (ret) + goto err; ret = -EPIPE; if (cf_sk->sk.sk_state != CAIF_CONNECTED || sock_flag(sk, SOCK_DEAD) || (sk->sk_shutdown & RCV_SHUTDOWN)) goto err; + /* Error if trying to write more than maximum frame size. */ + ret = -EMSGSIZE; + if (len > cf_sk->maxframe && cf_sk->sk.sk_protocol != CAIFPROTO_RFM) + goto err; + + buffer_size = len + cf_sk->headroom + cf_sk->tailroom; + ret = -ENOMEM; skb = sock_alloc_send_skb(sk, buffer_size, noblock, &ret); - if (!skb) + + if (!skb || skb_tailroom(skb) < buffer_size) goto err; - skb_reserve(skb, CAIF_NEEDED_HEADROOM); + + skb_reserve(skb, cf_sk->headroom); ret = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len); @@ -641,7 +651,6 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, long timeo; err = -EOPNOTSUPP; - if (unlikely(msg->msg_flags&MSG_OOB)) goto out_err; @@ -658,8 +667,8 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, size = len-sent; - if (size > CAIF_MAX_PAYLOAD_SIZE) - size = CAIF_MAX_PAYLOAD_SIZE; + if (size > cf_sk->maxframe) + size = cf_sk->maxframe; /* If size is more than half of sndbuf, chop up message */ if (size > ((sk->sk_sndbuf >> 1) - 64)) @@ -669,14 +678,14 @@ static int caif_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, size = SKB_MAX_ALLOC; skb = sock_alloc_send_skb(sk, - size + CAIF_NEEDED_HEADROOM - + CAIF_NEEDED_TAILROOM, + size + cf_sk->headroom + + cf_sk->tailroom, msg->msg_flags&MSG_DONTWAIT, &err); if (skb == NULL) goto out_err; - skb_reserve(skb, CAIF_NEEDED_HEADROOM); + skb_reserve(skb, cf_sk->headroom); /* * If you pass two values to the sock_alloc_send_skb * it tries to grab the large buffer with GFP_NOFS @@ -817,17 +826,15 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); long timeo; int err; + int ifindex, headroom, tailroom; + struct net_device *dev; + lock_sock(sk); err = -EAFNOSUPPORT; if (uaddr->sa_family != AF_CAIF) goto out; - err = -ESOCKTNOSUPPORT; - if (unlikely(!(sk->sk_type == SOCK_STREAM && - cf_sk->sk.sk_protocol == CAIFPROTO_AT) && - sk->sk_type != SOCK_SEQPACKET)) - goto out; switch (sock->state) { case SS_UNCONNECTED: /* Normal case, a fresh connect */ @@ -883,12 +890,23 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, dbfs_atomic_inc(&cnt.num_connect_req); cf_sk->layer.receive = caif_sktrecv_cb; err = caif_connect_client(&cf_sk->conn_req, - &cf_sk->layer); + &cf_sk->layer, &ifindex, &headroom, &tailroom); if (err < 0) { cf_sk->sk.sk_socket->state = SS_UNCONNECTED; cf_sk->sk.sk_state = CAIF_DISCONNECTED; goto out; } + dev = dev_get_by_index(sock_net(sk), ifindex); + cf_sk->headroom = LL_RESERVED_SPACE_EXTRA(dev, headroom); + cf_sk->tailroom = tailroom; + cf_sk->maxframe = dev->mtu - (headroom + tailroom); + dev_put(dev); + if (cf_sk->maxframe < 1) { + pr_warning("CAIF: %s(): CAIF Interface MTU too small (%d)\n", + __func__, dev->mtu); + err = -ENODEV; + goto out; + } err = -EINPROGRESS; wait_connect: diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index cff2dcb..1c29189 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c @@ -6,6 +6,7 @@ #include <linux/kernel.h> #include <linux/stddef.h> #include <linux/slab.h> +#include <linux/netdevice.h> #include <net/caif/caif_layer.h> #include <net/caif/cfpkt.h> #include <net/caif/cfcnfg.h> @@ -42,6 +43,15 @@ struct cfcnfg_phyinfo { /* Information about the physical device */ struct dev_info dev_info; + + /* Interface index */ + int ifindex; + + /* Use Start of frame extension */ + bool use_stx; + + /* Use Start of frame checksum */ + bool use_fcs; }; struct cfcnfg { @@ -249,9 +259,20 @@ static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) { } +int protohead[CFCTRL_SRV_MASK] = { + [CFCTRL_SRV_VEI] = 4, + [CFCTRL_SRV_DATAGRAM] = 7, + [CFCTRL_SRV_UTIL] = 4, + [CFCTRL_SRV_RFM] = 3, + [CFCTRL_SRV_DBG] = 3, +}; + int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, struct cfctrl_link_param *param, - struct cflayer *adap_layer) + struct cflayer *adap_layer, + int *ifindex, + int *proto_head, + int *proto_tail) { struct cflayer *frml; if (adap_layer == NULL) { @@ -277,6 +298,14 @@ int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, param->phyid); caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id == param->phyid); + + *ifindex = cnfg->phy_layers[param->phyid].ifindex; + *proto_head = + protohead[param->linktype]+ + (cnfg->phy_layers[param->phyid].use_stx ? 1 : 0); + + *proto_tail = 2; + /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ cfctrl_enum_req(cnfg->ctrl, param->phyid); return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); @@ -298,6 +327,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, struct cfcnfg *cnfg = container_obj(layer); struct cflayer *servicel = NULL; struct cfcnfg_phyinfo *phyinfo; + struct net_device *netdev; + if (adapt_layer == NULL) { pr_debug("CAIF: %s(): link setup response " "but no client exist, send linkdown back\n", @@ -329,8 +360,9 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, servicel = cfdgml_create(channel_id, &phyinfo->dev_info); break; case CFCTRL_SRV_RFM: + netdev = phyinfo->dev_info.dev; servicel = cfrfml_create(channel_id, &phyinfo->dev_info, - RFM_FRAGMENT_SIZE); + netdev->mtu); break; case CFCTRL_SRV_UTIL: servicel = cfutill_create(channel_id, &phyinfo->dev_info); @@ -361,8 +393,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, void cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, - void *dev, struct cflayer *phy_layer, u16 *phyid, - enum cfcnfg_phy_preference pref, + struct net_device *dev, struct cflayer *phy_layer, + u16 *phyid, enum cfcnfg_phy_preference pref, bool fcs, bool stx) { struct cflayer *frml; @@ -416,6 +448,10 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, cnfg->phy_layers[*phyid].dev_info.dev = dev; cnfg->phy_layers[*phyid].phy_layer = phy_layer; cnfg->phy_layers[*phyid].phy_ref_count = 0; + cnfg->phy_layers[*phyid].ifindex = dev->ifindex; + cnfg->phy_layers[*phyid].use_stx = stx; + cnfg->phy_layers[*phyid].use_fcs = fcs; + phy_layer->type = phy_type; frml = cffrml_create(*phyid, fcs); if (!frml) { diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 107c4b2..563145f 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -19,7 +19,7 @@ #ifdef CAIF_NO_LOOP static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt){ - return CAIF_FAILURE; + return -1; } #else static int handle_loop(struct cfctrl *ctrl, @@ -395,7 +395,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) cmd = cmdrsp & CFCTRL_CMD_MASK; if (cmd != CFCTRL_CMD_LINK_ERR && CFCTRL_RSP_BIT != (CFCTRL_RSP_BIT & cmdrsp)) { - if (handle_loop(cfctrl, cmd, pkt) == CAIF_FAILURE) + if (handle_loop(cfctrl, cmd, pkt) != 0) cmdrsp |= CFCTRL_ERR_BIT; } @@ -647,6 +647,6 @@ found: default: break; } - return CAIF_SUCCESS; + return 0; } #endif diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c index 32d9f0d..ed9d53a 100644 --- a/net/caif/cfdgml.c +++ b/net/caif/cfdgml.c @@ -17,6 +17,7 @@ #define DGM_FLOW_OFF 0x81 #define DGM_FLOW_ON 0x80 #define DGM_CTRL_PKT_SIZE 1 +#define DGM_MTU 1500 static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt); static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt); @@ -89,6 +90,10 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) if (!cfsrvl_ready(service, &ret)) return ret; + /* STE Modem cannot handle more than 1500 bytes datagrams */ + if (cfpkt_getlen(pkt) > DGM_MTU) + return -EMSGSIZE; + cfpkt_add_head(pkt, &zero, 4); /* Add info for MUX-layer to route the packet out. */ diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index 318b0f4..01f238f 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -9,8 +9,8 @@ #include <linux/hardirq.h> #include <net/caif/cfpkt.h> -#define PKT_PREFIX CAIF_NEEDED_HEADROOM -#define PKT_POSTFIX CAIF_NEEDED_TAILROOM +#define PKT_PREFIX 16 +#define PKT_POSTFIX 2 #define PKT_LEN_WHEN_EXTENDING 128 #define PKT_ERROR(pkt, errmsg) do { \ cfpkt_priv(pkt)->erronous = true; \ diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c index 965c5ba..a11fbd6 100644 --- a/net/caif/cfserl.c +++ b/net/caif/cfserl.c @@ -14,7 +14,8 @@ #define container_obj(layr) ((struct cfserl *) layr) #define CFSERL_STX 0x02 -#define CAIF_MINIUM_PACKET_SIZE 4 +#define SERIAL_MINIUM_PACKET_SIZE 4 +#define SERIAL_MAX_FRAMESIZE 4096 struct cfserl { struct cflayer layer; struct cfpkt *incomplete_frm; @@ -119,8 +120,8 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) /* * Frame error handling */ - if (expectlen < CAIF_MINIUM_PACKET_SIZE - || expectlen > CAIF_MAX_FRAMESIZE) { + if (expectlen < SERIAL_MINIUM_PACKET_SIZE + || expectlen > SERIAL_MAX_FRAMESIZE) { if (!layr->usestx) { if (pkt != NULL) cfpkt_destroy(pkt); diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 4c9f147..f40939a 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -162,7 +162,6 @@ void cfservl_destroy(struct cflayer *layer) void cfsrvl_release(struct kref *kref) { struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); - pr_info("CAIF: %s(): enter\n", __func__); kfree(service); } diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c index ce525ca..02795af 100644 --- a/net/caif/cfutill.c +++ b/net/caif/cfutill.c @@ -90,12 +90,6 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt) if (!cfsrvl_ready(service, &ret)) return ret; - if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { - pr_err("CAIF: %s(): packet too large size=%d\n", - __func__, cfpkt_getlen(pkt)); - return -EOVERFLOW; - } - cfpkt_add_head(pkt, &zero, 1); /* Add info for MUX-layer to route the packet out. */ info = cfpkt_info(pkt); diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c index 637cb0e..77cc09f 100644 --- a/net/caif/cfveil.c +++ b/net/caif/cfveil.c @@ -84,11 +84,6 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) return ret; caif_assert(layr->dn != NULL); caif_assert(layr->dn->transmit != NULL); - if (cfpkt_getlen(pkt) > CAIF_MAX_PAYLOAD_SIZE) { - pr_warning("CAIF: %s(): Packet too large - size=%d\n", - __func__, cfpkt_getlen(pkt)); - return -EOVERFLOW; - } if (cfpkt_add_head(pkt, &tmp, 1) < 0) { pr_err("CAIF: %s(): Packet is erroneous!\n", __func__); diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 610966a..4293e19 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c @@ -23,7 +23,7 @@ #include <net/caif/caif_dev.h> /* GPRS PDP connection has MTU to 1500 */ -#define SIZE_MTU 1500 +#define GPRS_PDP_MTU 1500 /* 5 sec. connect timeout */ #define CONNECT_TIMEOUT (5 * HZ) #define CAIF_NET_DEFAULT_QUEUE_LEN 500 @@ -232,6 +232,8 @@ static int chnl_net_open(struct net_device *dev) { struct chnl_net *priv = NULL; int result = -1; + int llifindex, headroom, tailroom, mtu; + struct net_device *lldev; ASSERT_RTNL(); priv = netdev_priv(dev); if (!priv) { @@ -241,41 +243,88 @@ static int chnl_net_open(struct net_device *dev) if (priv->state != CAIF_CONNECTING) { priv->state = CAIF_CONNECTING; - result = caif_connect_client(&priv->conn_req, &priv->chnl); + result = caif_connect_client(&priv->conn_req, &priv->chnl, + &llifindex, &headroom, &tailroom); if (result != 0) { - priv->state = CAIF_DISCONNECTED; pr_debug("CAIF: %s(): err: " "Unable to register and open device," " Err:%d\n", __func__, result); - return result; + goto error; + } + + lldev = dev_get_by_index(dev_net(dev), llifindex); + + if (lldev == NULL) { + pr_debug("CAIF: %s(): no interface?\n", __func__); + result = -ENODEV; + goto error; + } + + dev->needed_tailroom = tailroom + lldev->needed_tailroom; + dev->hard_header_len = headroom + lldev->hard_header_len + + lldev->needed_tailroom; + + /* + * MTU, head-room etc is not know before we have a + * CAIF link layer device available. MTU calculation may + * override initial RTNL configuration. + * MTU is minimum of current mtu, link layer mtu pluss + * CAIF head and tail, and PDP GPRS contexts max MTU. + */ + mtu = min_t(int, dev->mtu, lldev->mtu - (headroom + tailroom)); + mtu = min_t(int, GPRS_PDP_MTU, mtu); + dev_set_mtu(dev, mtu); + dev_put(lldev); + + if (mtu < 100) { + pr_warning("CAIF: %s(): " + "CAIF Interface MTU too small (%d)\n", + __func__, mtu); + result = -ENODEV; + goto error; } } + rtnl_unlock(); /* Release RTNL lock during connect wait */ + result = wait_event_interruptible_timeout(priv->netmgmt_wq, priv->state != CAIF_CONNECTING, CONNECT_TIMEOUT); + rtnl_lock(); + if (result == -ERESTARTSYS) { pr_debug("CAIF: %s(): wait_event_interruptible" " woken by a signal\n", __func__); - return -ERESTARTSYS; + result = -ERESTARTSYS; + goto error; } + if (result == 0) { pr_debug("CAIF: %s(): connect timeout\n", __func__); caif_disconnect_client(&priv->chnl); priv->state = CAIF_DISCONNECTED; pr_debug("CAIF: %s(): state disconnected\n", __func__); - return -ETIMEDOUT; + result = -ETIMEDOUT; + goto error; } if (priv->state != CAIF_CONNECTED) { pr_debug("CAIF: %s(): connect failed\n", __func__); - return -ECONNREFUSED; + result = -ECONNREFUSED; + goto error; } pr_debug("CAIF: %s(): CAIF Netdevice connected\n", __func__); return 0; + +error: + caif_disconnect_client(&priv->chnl); + priv->state = CAIF_DISCONNECTED; + pr_debug("CAIF: %s(): state disconnected\n", __func__); + return result; + } static int chnl_net_stop(struct net_device *dev) @@ -321,9 +370,7 @@ static void ipcaif_net_setup(struct net_device *dev) dev->destructor = free_netdev; dev->flags |= IFF_NOARP; dev->flags |= IFF_POINTOPOINT; - dev->needed_headroom = CAIF_NEEDED_HEADROOM; - dev->needed_tailroom = CAIF_NEEDED_TAILROOM; - dev->mtu = SIZE_MTU; + dev->mtu = GPRS_PDP_MTU; dev->tx_queue_len = CAIF_NET_DEFAULT_QUEUE_LEN; priv = netdev_priv(dev); -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH net-next-2.6 4/4] caif: Add debug connection type for CAIF. 2010-06-17 16:55 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU sjur.brandeland @ 2010-06-17 16:55 ` sjur.brandeland 2010-06-21 3:39 ` David Miller 2010-06-21 3:39 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU David Miller 1 sibling, 1 reply; 8+ messages in thread From: sjur.brandeland @ 2010-06-17 16:55 UTC (permalink / raw) To: sjurbr, netdev, davem; +Cc: linus.walleij, Sjur Braendeland From: Sjur Braendeland <sjur.brandeland@stericsson.com> Added new CAIF protocol type CAIFPROTO_DEBUG for accessing CAIF debug on the ST Ericsson modems. There are two debug servers on the modem, one for radio related debug (CAIF_RADIO_DEBUG_SERVICE) and the other for communication/application related debug (CAIF_COM_DEBUG_SERVICE). The debug connection can contain trace debug printouts or interactive debug used for debugging and test. Debug connections can be of type STREAM or SEQPACKET. Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com> --- include/linux/caif/caif_socket.h | 34 ++++++++++++++++++++++++++++++++++ net/caif/caif_config_util.c | 5 +++++ 2 files changed, 39 insertions(+), 0 deletions(-) diff --git a/include/linux/caif/caif_socket.h b/include/linux/caif/caif_socket.h index 2a61eb1..d9cb19b 100644 --- a/include/linux/caif/caif_socket.h +++ b/include/linux/caif/caif_socket.h @@ -62,6 +62,7 @@ enum caif_channel_priority { * @CAIFPROTO_DATAGRAM_LOOP: Datagram loopback channel, used for testing. * @CAIFPROTO_UTIL: Utility (Psock) channel. * @CAIFPROTO_RFM: Remote File Manager + * @CAIFPROTO_DEBUG: Debug link * * This enum defines the CAIF Channel type to be used. This defines * the service to connect to on the modem. @@ -72,6 +73,7 @@ enum caif_protocol_type { CAIFPROTO_DATAGRAM_LOOP, CAIFPROTO_UTIL, CAIFPROTO_RFM, + CAIFPROTO_DEBUG, _CAIFPROTO_MAX }; #define CAIFPROTO_MAX _CAIFPROTO_MAX @@ -83,6 +85,28 @@ enum caif_protocol_type { enum caif_at_type { CAIF_ATTYPE_PLAIN = 2 }; + /** + * enum caif_debug_type - Content selection for debug connection + * @CAIF_DEBUG_TRACE_INTERACTIVE: Connection will contain + * both trace and interactive debug. + * @CAIF_DEBUG_TRACE: Connection contains trace only. + * @CAIF_DEBUG_INTERACTIVE: Connection to interactive debug. + */ +enum caif_debug_type { + CAIF_DEBUG_TRACE_INTERACTIVE = 0, + CAIF_DEBUG_TRACE, + CAIF_DEBUG_INTERACTIVE, +}; + +/** + * enum caif_debug_service - Debug Service Endpoint + * @CAIF_RADIO_DEBUG_SERVICE: Debug service on the Radio sub-system + * @CAIF_APP_DEBUG_SERVICE: Debug for the applications sub-system + */ +enum caif_debug_service { + CAIF_RADIO_DEBUG_SERVICE = 1, + CAIF_APP_DEBUG_SERVICE +}; /** * struct sockaddr_caif - the sockaddr structure for CAIF sockets. @@ -109,6 +133,12 @@ enum caif_at_type { * * @u.rfm.volume: Volume to mount. * + * @u.dbg: Applies when family = CAIFPROTO_DEBUG. + * + * @u.dbg.type: Type of debug connection to set up + * (caif_debug_type). + * + * @u.dbg.service: Service sub-system to connect (caif_debug_service * Description: * This structure holds the connect parameters used for setting up a * CAIF Channel. It defines the service to connect to on the modem. @@ -130,6 +160,10 @@ struct sockaddr_caif { __u32 connection_id; char volume[16]; } rfm; /* CAIFPROTO_RFM */ + struct { + __u8 type; /* type:enum caif_debug_type */ + __u8 service; /* service:caif_debug_service */ + } dbg; /* CAIFPROTO_DEBUG */ } u; }; diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c index 6f36580..76ae683 100644 --- a/net/caif/caif_config_util.c +++ b/net/caif/caif_config_util.c @@ -80,6 +80,11 @@ int connect_req_to_link_param(struct cfcnfg *cnfg, l->u.utility.paramlen); break; + case CAIFPROTO_DEBUG: + l->linktype = CFCTRL_SRV_DBG; + l->endpoint = s->sockaddr.u.dbg.service; + l->chtype = s->sockaddr.u.dbg.type; + break; default: return -EINVAL; } -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH net-next-2.6 4/4] caif: Add debug connection type for CAIF. 2010-06-17 16:55 ` [PATCH net-next-2.6 4/4] caif: Add debug connection type for CAIF sjur.brandeland @ 2010-06-21 3:39 ` David Miller 0 siblings, 0 replies; 8+ messages in thread From: David Miller @ 2010-06-21 3:39 UTC (permalink / raw) To: sjur.brandeland; +Cc: sjurbr, netdev, linus.walleij From: sjur.brandeland@stericsson.com Date: Thu, 17 Jun 2010 18:55:41 +0200 > From: Sjur Braendeland <sjur.brandeland@stericsson.com> > > Added new CAIF protocol type CAIFPROTO_DEBUG for accessing > CAIF debug on the ST Ericsson modems. > > There are two debug servers on the modem, one for radio related > debug (CAIF_RADIO_DEBUG_SERVICE) and the other for > communication/application related debug (CAIF_COM_DEBUG_SERVICE). > > The debug connection can contain trace debug printouts or > interactive debug used for debugging and test. > > Debug connections can be of type STREAM or SEQPACKET. > > Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com> Applied. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU 2010-06-17 16:55 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 4/4] caif: Add debug connection type for CAIF sjur.brandeland @ 2010-06-21 3:39 ` David Miller 1 sibling, 0 replies; 8+ messages in thread From: David Miller @ 2010-06-21 3:39 UTC (permalink / raw) To: sjur.brandeland; +Cc: sjurbr, netdev, linus.walleij From: sjur.brandeland@stericsson.com Date: Thu, 17 Jun 2010 18:55:40 +0200 > From: Sjur Braendeland <sjur.brandeland@stericsson.com> > > Previously CAIF supported maximum transfer size of ~4050. > The transfer size is now calculated dynamically based on the > link layers mtu size. > > Signed-off-by: Sjur Braendeland@stericsson.com Applied. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation. 2010-06-17 16:55 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU sjur.brandeland @ 2010-06-21 3:38 ` David Miller 1 sibling, 0 replies; 8+ messages in thread From: David Miller @ 2010-06-21 3:38 UTC (permalink / raw) To: sjur.brandeland; +Cc: sjurbr, netdev, linus.walleij From: sjur.brandeland@stericsson.com Date: Thu, 17 Jun 2010 18:55:39 +0200 > From: Sjur Braendeland <sjur.brandeland@stericsson.com> > > CAIF Remote File Manager may send or receive more than 4050 bytes. > Due to this The CAIF RFM service have to support segmentation. > > Signed-off-by: Sjur Braendeland@stericsson.com Applied. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl. 2010-06-17 16:55 [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation sjur.brandeland @ 2010-06-21 3:38 ` David Miller 1 sibling, 0 replies; 8+ messages in thread From: David Miller @ 2010-06-21 3:38 UTC (permalink / raw) To: sjur.brandeland; +Cc: sjurbr, netdev, linus.walleij From: sjur.brandeland@stericsson.com Date: Thu, 17 Jun 2010 18:55:38 +0200 > From: Sjur Braendeland <sjur.brandeland@stericsson.com> > > Flow control is not used by all CAIF services. > The usage of flow control is now part of the gerneal > initialization function for CAIF Services. > > Signed-off-by: Sjur Braendeland@stericsson.com Applied. ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-06-21 3:38 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-06-17 16:55 [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU sjur.brandeland 2010-06-17 16:55 ` [PATCH net-next-2.6 4/4] caif: Add debug connection type for CAIF sjur.brandeland 2010-06-21 3:39 ` David Miller 2010-06-21 3:39 ` [PATCH net-next-2.6 3/4] caif: Use link layer MTU instead of fixed MTU David Miller 2010-06-21 3:38 ` [PATCH net-next-2.6 2/4] caif: Bugfix - RFM must support segmentation David Miller 2010-06-21 3:38 ` [PATCH net-next-2.6 1/4] caif: Bugfix not all services uses flow-ctrl David Miller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).