diff --git a/include/net/caif/cfsrvl.h b/include/net/caif/cfsrvl.h index 6c8279c1ae9a01fb5677723b3eaab437f5baa2c8..0f5905241843ab637126001f69a64b3003c21e0e 100644 --- a/include/net/caif/cfsrvl.h +++ b/include/net/caif/cfsrvl.h @@ -10,6 +10,7 @@ #include #include #include +#include struct cfsrvl { struct cflayer layer; @@ -17,9 +18,11 @@ struct cfsrvl { bool phy_flow_on; bool modem_flow_on; bool supports_flowctrl; - void (*release)(struct kref *); + void (*release)(struct cflayer *layer); struct dev_info dev_info; - struct kref ref; + void (*hold)(struct cflayer *lyr); + void (*put)(struct cflayer *lyr); + struct rcu_head rcu; }; struct cflayer *cfvei_create(u8 linkid, struct dev_info *dev_info); @@ -29,6 +32,10 @@ struct cflayer *cfvidl_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); + +void cfsrvl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, + int phyid); + bool cfsrvl_phyid_match(struct cflayer *layer, int phyid); void cfsrvl_init(struct cfsrvl *service, @@ -40,23 +47,19 @@ u8 cfsrvl_getphyid(struct cflayer *layer); static inline void cfsrvl_get(struct cflayer *layr) { - struct cfsrvl *s; - if (layr == NULL) + struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); + if (layr == NULL || layr->up == NULL || s->hold == NULL) return; - s = container_of(layr, struct cfsrvl, layer); - kref_get(&s->ref); + + s->hold(layr->up); } static inline void cfsrvl_put(struct cflayer *layr) { - struct cfsrvl *s; - if (layr == NULL) + struct cfsrvl *s = container_of(layr, struct cfsrvl, layer); + if (layr == NULL || layr->up == NULL || s->hold == NULL) return; - s = container_of(layr, struct cfsrvl, layer); - WARN_ON(!s->release); - if (s->release) - kref_put(&s->ref, s->release); + s->put(layr->up); } - #endif /* CFSRVL_H_ */ diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index e2fb5fa757951a46e8d6be9326ffc1659f943232..0deabb4400517e9d49205661955b3f06f6f1343c 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c @@ -31,9 +31,9 @@ struct cfrfml { spinlock_t sync; }; -static void cfrfml_release(struct kref *kref) +static void cfrfml_release(struct cflayer *layer) { - struct cfsrvl *srvl = container_of(kref, struct cfsrvl, ref); + struct cfsrvl *srvl = container_of(layer, struct cfsrvl, layer); struct cfrfml *rfml = container_obj(&srvl->layer); if (rfml->incomplete_frm) diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index 24ba392f203bb7f2ba64ae1930081e9c60455d28..535a1e72b366a212e24a4b242cb76c81ceb54301 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -27,8 +28,8 @@ static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, { struct cfsrvl *service = container_obj(layr); - caif_assert(layr->up != NULL); - caif_assert(layr->up->ctrlcmd != NULL); + if (layr->up == NULL || layr->up->ctrlcmd == NULL) + return; switch (ctrl) { case CAIF_CTRLCMD_INIT_RSP: @@ -151,9 +152,9 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) return -EINVAL; } -static void cfsrvl_release(struct kref *kref) +static void cfsrvl_release(struct cflayer *layer) { - struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); + struct cfsrvl *service = container_of(layer, struct cfsrvl, layer); kfree(service); } @@ -173,10 +174,8 @@ void cfsrvl_init(struct cfsrvl *service, service->dev_info = *dev_info; service->supports_flowctrl = supports_flowctrl; service->release = cfsrvl_release; - kref_init(&service->ref); } - bool cfsrvl_ready(struct cfsrvl *service, int *err) { if (service->open && service->modem_flow_on && service->phy_flow_on) @@ -189,6 +188,7 @@ bool cfsrvl_ready(struct cfsrvl *service, int *err) *err = -EAGAIN; return false; } + u8 cfsrvl_getphyid(struct cflayer *layer) { struct cfsrvl *servl = container_obj(layer); @@ -200,3 +200,26 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid) struct cfsrvl *servl = container_obj(layer); return servl->dev_info.id == phyid; } + +void caif_free_client(struct cflayer *adap_layer) +{ + struct cfsrvl *servl; + if (adap_layer == NULL || adap_layer->dn == NULL) + return; + servl = container_obj(adap_layer->dn); + servl->release(&servl->layer); +} +EXPORT_SYMBOL(caif_free_client); + +void caif_client_register_refcnt(struct cflayer *adapt_layer, + void (*hold)(struct cflayer *lyr), + void (*put)(struct cflayer *lyr)) +{ + struct cfsrvl *service; + service = container_of(adapt_layer->dn, struct cfsrvl, layer); + + WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); + service->hold = hold; + service->put = put; +} +EXPORT_SYMBOL(caif_client_register_refcnt);