Skip to content

Commit

Permalink
caif: Use link layer MTU instead of fixed MTU
Browse files Browse the repository at this point in the history
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
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Sjur Braendeland authored and davem330 committed Jun 21, 2010
1 parent a7da1f5 commit 2aa40ae
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 69 deletions.
1 change: 0 additions & 1 deletion drivers/net/caif/caif_serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
8 changes: 6 additions & 2 deletions include/net/caif/caif_dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
6 changes: 0 additions & 6 deletions include/net/caif/caif_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
16 changes: 12 additions & 4 deletions include/net/caif/cfcnfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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);

/**
Expand Down Expand Up @@ -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.
Expand Down
12 changes: 8 additions & 4 deletions net/caif/caif_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand All @@ -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;

Expand All @@ -326,16 +328,18 @@ 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;
ret = connect_req_to_link_param(get_caif_conf(), conn_req, &param);
if (ret)
return ret;
/* Hook up the adaptation layer. */
return cfcnfg_add_adaptation_layer(get_caif_conf(),
&param, client_layer);
return cfcnfg_add_adaptation_layer(get_caif_conf(), &param,
client_layer, ifindex,
headroom, tailroom);
}
EXPORT_SYMBOL(caif_connect_client);

Expand Down
54 changes: 36 additions & 18 deletions net/caif/caif_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand All @@ -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))
Expand All @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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:
Expand Down
44 changes: 40 additions & 4 deletions net/caif/cfcnfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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",
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions net/caif/cfctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -647,6 +647,6 @@ static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt)
default:
break;
}
return CAIF_SUCCESS;
return 0;
}
#endif

0 comments on commit 2aa40ae

Please sign in to comment.