mirror of
https://github.com/torvalds/linux.git
synced 2026-08-01 03:59:40 +02:00
net: qrtr: Add backup skb pool
Add a pool of SKBs that can be used when the system is in low memory conditions. This pool will be shared between all nodes and replenished by a worker function. Change-Id: I639a9ac76db726dc8ad46b12d3b3d560c674939c Signed-off-by: Jay Jayanna <jayanna@codeaurora.org> Signed-off-by: Chris Lew <quic_clew@quicinc.com>
This commit is contained in:
parent
08de359d99
commit
a34e1c5cea
|
|
@ -127,6 +127,15 @@ static DEFINE_XARRAY_ALLOC(qrtr_ports);
|
|||
u32 qrtr_ports_next = QRTR_MIN_EPH_SOCKET;
|
||||
static DEFINE_SPINLOCK(qrtr_port_lock);
|
||||
|
||||
/* backup buffers */
|
||||
#define QRTR_BACKUP_HI_NUM 5
|
||||
#define QRTR_BACKUP_HI_SIZE SZ_16K
|
||||
#define QRTR_BACKUP_LO_NUM 20
|
||||
#define QRTR_BACKUP_LO_SIZE SZ_1K
|
||||
static struct sk_buff_head qrtr_backup_lo;
|
||||
static struct sk_buff_head qrtr_backup_hi;
|
||||
static struct work_struct qrtr_backup_work;
|
||||
|
||||
/**
|
||||
* struct qrtr_node - endpoint node
|
||||
* @ep_lock: lock for endpoint management and callbacks
|
||||
|
|
@ -552,6 +561,59 @@ int qrtr_peek_pkt_size(const void *data)
|
|||
}
|
||||
EXPORT_SYMBOL(qrtr_peek_pkt_size);
|
||||
|
||||
static void qrtr_alloc_backup(struct work_struct *work)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
int errcode;
|
||||
|
||||
while (skb_queue_len(&qrtr_backup_lo) < QRTR_BACKUP_LO_NUM) {
|
||||
skb = alloc_skb_with_frags(sizeof(struct qrtr_hdr_v1),
|
||||
QRTR_BACKUP_LO_SIZE, 0, &errcode,
|
||||
GFP_KERNEL);
|
||||
if (!skb)
|
||||
break;
|
||||
skb_queue_tail(&qrtr_backup_lo, skb);
|
||||
}
|
||||
while (skb_queue_len(&qrtr_backup_hi) < QRTR_BACKUP_HI_NUM) {
|
||||
skb = alloc_skb_with_frags(sizeof(struct qrtr_hdr_v1),
|
||||
QRTR_BACKUP_HI_SIZE, 0, &errcode,
|
||||
GFP_KERNEL);
|
||||
if (!skb)
|
||||
break;
|
||||
skb_queue_tail(&qrtr_backup_hi, skb);
|
||||
}
|
||||
}
|
||||
|
||||
static struct sk_buff *qrtr_get_backup(size_t len)
|
||||
{
|
||||
struct sk_buff *skb = NULL;
|
||||
|
||||
if (len < QRTR_BACKUP_LO_SIZE)
|
||||
skb = skb_dequeue(&qrtr_backup_lo);
|
||||
else if (len < QRTR_BACKUP_HI_SIZE)
|
||||
skb = skb_dequeue(&qrtr_backup_hi);
|
||||
|
||||
if (skb)
|
||||
queue_work(system_unbound_wq, &qrtr_backup_work);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static void qrtr_backup_init(void)
|
||||
{
|
||||
skb_queue_head_init(&qrtr_backup_lo);
|
||||
skb_queue_head_init(&qrtr_backup_hi);
|
||||
INIT_WORK(&qrtr_backup_work, qrtr_alloc_backup);
|
||||
queue_work(system_unbound_wq, &qrtr_backup_work);
|
||||
}
|
||||
|
||||
static void qrtr_backup_deinit(void)
|
||||
{
|
||||
cancel_work_sync(&qrtr_backup_work);
|
||||
skb_queue_purge(&qrtr_backup_lo);
|
||||
skb_queue_purge(&qrtr_backup_hi);
|
||||
}
|
||||
|
||||
/**
|
||||
* qrtr_endpoint_post() - post incoming data
|
||||
* @ep: endpoint handle
|
||||
|
|
@ -577,8 +639,13 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
|
|||
return -EINVAL;
|
||||
|
||||
skb = alloc_skb_with_frags(sizeof(*v1), len, 0, &errcode, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
if (!skb) {
|
||||
skb = qrtr_get_backup(len);
|
||||
if (!skb) {
|
||||
pr_err("qrtr: Unable to get skb with len:%lu\n", len);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
skb_reserve(skb, sizeof(*v1));
|
||||
cb = (struct qrtr_cb *)skb->cb;
|
||||
|
|
@ -1708,6 +1775,8 @@ static int __init qrtr_proto_init(void)
|
|||
if (rc)
|
||||
goto err_sock;
|
||||
|
||||
qrtr_backup_init();
|
||||
|
||||
return 0;
|
||||
|
||||
err_sock:
|
||||
|
|
@ -1723,6 +1792,8 @@ static void __exit qrtr_proto_fini(void)
|
|||
qrtr_ns_remove();
|
||||
sock_unregister(qrtr_family.family);
|
||||
proto_unregister(&qrtr_proto);
|
||||
|
||||
qrtr_backup_deinit();
|
||||
}
|
||||
module_exit(qrtr_proto_fini);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user