Commit 97ef8f8c authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by David S. Miller

[LLC] use struct sock list members

Now that we don't have anymore the double sock (PF_LLC + core) we can
use struct sock list members.

Also use use rw locks instead of spinlocks in some places.
parent 9950c8fe
...@@ -43,7 +43,7 @@ struct llc_station { ...@@ -43,7 +43,7 @@ struct llc_station {
u8 maximum_retry; u8 maximum_retry;
u8 mac_sa[6]; u8 mac_sa[6];
struct { struct {
spinlock_t lock; rwlock_t lock;
struct list_head list; struct list_head list;
} sap_list; } sap_list;
struct { struct {
......
...@@ -16,30 +16,30 @@ ...@@ -16,30 +16,30 @@
/** /**
* struct llc_sap - Defines the SAP component * struct llc_sap - Defines the SAP component
* *
* @station - station this sap belongs to
* @state - sap state
* @p_bit - only lowest-order bit used * @p_bit - only lowest-order bit used
* @f_bit - only lowest-order bit used * @f_bit - only lowest-order bit used
* @ind - provided by network layer
* @conf - provided by network layer
* @laddr - SAP value in this 'lsap' * @laddr - SAP value in this 'lsap'
* @node - entry in station sap_list * @node - entry in station sap_list
* @sk_list - LLC sockets this one manages * @sk_list - LLC sockets this one manages
* @mac_pdu_q - PDUs ready to send to MAC * @mac_pdu_q - PDUs ready to send to MAC
*/ */
struct llc_sap { struct llc_sap {
struct llc_station *parent_station; struct llc_station *station;
u8 state; u8 state;
u8 p_bit; u8 p_bit;
u8 f_bit; u8 f_bit;
int (*rcv_func)(struct sk_buff *skb, int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev, struct net_device *dev,
struct packet_type *pt); struct packet_type *pt);
struct llc_addr laddr; struct llc_addr laddr;
struct list_head node; struct list_head node;
struct { struct {
spinlock_t lock; rwlock_t lock;
struct list_head list; struct sock *list;
} sk_list; } sk_list;
struct sk_buff_head mac_pdu_q; struct sk_buff_head mac_pdu_q;
}; };
struct llc_sap_state_ev; struct llc_sap_state_ev;
......
...@@ -493,27 +493,21 @@ static int llc_exec_conn_trans_actions(struct sock *sk, ...@@ -493,27 +493,21 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
struct llc_addr *laddr) struct llc_addr *laddr)
{ {
struct sock *rc = NULL; struct sock *rc;
struct list_head *entry;
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) for (rc = sap->sk_list.list; rc; rc = rc->next) {
goto out; struct llc_opt *llc = llc_sk(rc);
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
if (llc->laddr.lsap == laddr->lsap && if (llc->laddr.lsap == laddr->lsap &&
llc->daddr.lsap == daddr->lsap && llc->daddr.lsap == daddr->lsap &&
llc_mac_match(llc->laddr.mac, laddr->mac) && llc_mac_match(llc->laddr.mac, laddr->mac) &&
llc_mac_match(llc->daddr.mac, daddr->mac)) { llc_mac_match(llc->daddr.mac, daddr->mac))
rc = llc->sk;
break; break;
}
} }
if (rc) if (rc)
sock_hold(rc); sock_hold(rc);
out: read_unlock_bh(&sap->sk_list.lock);
spin_unlock_bh(&sap->sk_list.lock);
return rc; return rc;
} }
...@@ -528,25 +522,20 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr, ...@@ -528,25 +522,20 @@ struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
*/ */
struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr) struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr)
{ {
struct sock *rc = NULL; struct sock *rc;
struct list_head *entry;
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) for (rc = sap->sk_list.list; rc; rc = rc->next) {
goto out; struct llc_opt *llc = llc_sk(rc);
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node); if (rc->type == SOCK_STREAM && rc->state == TCP_LISTEN &&
llc->laddr.lsap == laddr->lsap &&
if (llc->sk->type != SOCK_STREAM || llc->sk->state != TCP_LISTEN || llc_mac_match(llc->laddr.mac, laddr->mac))
llc->laddr.lsap != laddr->lsap || break;
!llc_mac_match(llc->laddr.mac, laddr->mac))
continue;
rc = llc->sk;
} }
if (rc) if (rc)
sock_hold(rc); sock_hold(rc);
out: read_unlock_bh(&sap->sk_list.lock);
spin_unlock_bh(&sap->sk_list.lock);
return rc; return rc;
} }
...@@ -560,26 +549,20 @@ struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr) ...@@ -560,26 +549,20 @@ struct sock *llc_lookup_listener(struct llc_sap *sap, struct llc_addr *laddr)
*/ */
struct sock *llc_lookup_dgram(struct llc_sap *sap, struct llc_addr *laddr) struct sock *llc_lookup_dgram(struct llc_sap *sap, struct llc_addr *laddr)
{ {
struct sock *rc = NULL; struct sock *rc;
struct list_head *entry;
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) for (rc = sap->sk_list.list; rc; rc = rc->next) {
goto out; struct llc_opt *llc = llc_sk(rc);
list_for_each(entry, &sap->sk_list.list) {
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
if (llc->sk->type == SOCK_DGRAM && if (rc->type == SOCK_DGRAM &&
llc->laddr.lsap == laddr->lsap && llc->laddr.lsap == laddr->lsap &&
llc_mac_match(llc->laddr.mac, laddr->mac)) { llc_mac_match(llc->laddr.mac, laddr->mac))
rc = llc->sk;
break; break;
}
} }
if (rc) if (rc)
sock_hold(rc); sock_hold(rc);
out: read_unlock_bh(&sap->sk_list.lock);
spin_unlock_bh(&sap->sk_list.lock);
return rc; return rc;
} }
/** /**
......
...@@ -56,8 +56,8 @@ struct llc_sap *llc_sap_open(u8 lsap, int (*func)(struct sk_buff *skb, ...@@ -56,8 +56,8 @@ struct llc_sap *llc_sap_open(u8 lsap, int (*func)(struct sk_buff *skb,
goto err; goto err;
/* allocated a SAP; initialize it and clear out its memory pool */ /* allocated a SAP; initialize it and clear out its memory pool */
sap->laddr.lsap = lsap; sap->laddr.lsap = lsap;
sap->rcv_func = func; sap->rcv_func = func;
sap->parent_station = llc_station_get(); sap->station = llc_station_get();
/* initialized SAP; add it to list of SAPs this station manages */ /* initialized SAP; add it to list of SAPs this station manages */
llc_sap_save(sap); llc_sap_save(sap);
out: out:
......
...@@ -71,7 +71,6 @@ struct llc_sap *llc_sap_alloc(void) ...@@ -71,7 +71,6 @@ struct llc_sap *llc_sap_alloc(void)
sap->state = LLC_SAP_STATE_ACTIVE; sap->state = LLC_SAP_STATE_ACTIVE;
memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN); memcpy(sap->laddr.mac, llc_main_station.mac_sa, ETH_ALEN);
spin_lock_init(&sap->sk_list.lock); spin_lock_init(&sap->sk_list.lock);
INIT_LIST_HEAD(&sap->sk_list.list);
skb_queue_head_init(&sap->mac_pdu_q); skb_queue_head_init(&sap->mac_pdu_q);
} }
return sap; return sap;
...@@ -86,12 +85,10 @@ struct llc_sap *llc_sap_alloc(void) ...@@ -86,12 +85,10 @@ struct llc_sap *llc_sap_alloc(void)
*/ */
void llc_free_sap(struct llc_sap *sap) void llc_free_sap(struct llc_sap *sap)
{ {
struct llc_station *station = sap->parent_station;
llc_rtn_all_conns(sap); llc_rtn_all_conns(sap);
spin_lock_bh(&station->sap_list.lock); write_lock_bh(&sap->station->sap_list.lock);
list_del(&sap->node); list_del(&sap->node);
spin_unlock_bh(&station->sap_list.lock); write_unlock_bh(&sap->station->sap_list.lock);
kfree(sap); kfree(sap);
} }
...@@ -103,9 +100,9 @@ void llc_free_sap(struct llc_sap *sap) ...@@ -103,9 +100,9 @@ void llc_free_sap(struct llc_sap *sap)
*/ */
void llc_sap_save(struct llc_sap *sap) void llc_sap_save(struct llc_sap *sap)
{ {
spin_lock_bh(&llc_main_station.sap_list.lock); write_lock_bh(&llc_main_station.sap_list.lock);
list_add_tail(&sap->node, &llc_main_station.sap_list.list); list_add_tail(&sap->node, &llc_main_station.sap_list.list);
spin_unlock_bh(&llc_main_station.sap_list.lock); write_unlock_bh(&llc_main_station.sap_list.lock);
} }
/** /**
...@@ -120,7 +117,7 @@ struct llc_sap *llc_sap_find(u8 sap_value) ...@@ -120,7 +117,7 @@ struct llc_sap *llc_sap_find(u8 sap_value)
struct llc_sap* sap = NULL; struct llc_sap* sap = NULL;
struct list_head *entry; struct list_head *entry;
spin_lock_bh(&llc_main_station.sap_list.lock); read_lock_bh(&llc_main_station.sap_list.lock);
list_for_each(entry, &llc_main_station.sap_list.list) { list_for_each(entry, &llc_main_station.sap_list.list) {
sap = list_entry(entry, struct llc_sap, node); sap = list_entry(entry, struct llc_sap, node);
if (sap->laddr.lsap == sap_value) if (sap->laddr.lsap == sap_value)
...@@ -128,7 +125,7 @@ struct llc_sap *llc_sap_find(u8 sap_value) ...@@ -128,7 +125,7 @@ struct llc_sap *llc_sap_find(u8 sap_value)
} }
if (entry == &llc_main_station.sap_list.list) /* not found */ if (entry == &llc_main_station.sap_list.list) /* not found */
sap = NULL; sap = NULL;
spin_unlock_bh(&llc_main_station.sap_list.lock); read_unlock_bh(&llc_main_station.sap_list.lock);
return sap; return sap;
} }
...@@ -326,20 +323,18 @@ void llc_sk_reset(struct sock *sk) ...@@ -326,20 +323,18 @@ void llc_sk_reset(struct sock *sk)
static int llc_rtn_all_conns(struct llc_sap *sap) static int llc_rtn_all_conns(struct llc_sap *sap)
{ {
int rc = 0; int rc = 0;
struct list_head *entry, *tmp; struct sock *sk;
spin_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list))
goto out; for (sk = sap->sk_list.list; sk; sk = sk->next) {
list_for_each_safe(entry, tmp, &sap->sk_list.list) { llc_sk(sk)->state = LLC_CONN_STATE_TEMP;
struct llc_opt *llc = list_entry(entry, struct llc_opt, node);
llc->state = LLC_CONN_STATE_TEMP; if (llc_send_disc(sk))
if (llc_send_disc(llc->sk))
rc = 1; rc = 1;
} }
out:
spin_unlock_bh(&sap->sk_list.lock); write_unlock_bh(&sap->sk_list.lock);
return rc; return rc;
} }
...@@ -562,19 +557,19 @@ static char *llc_conn_state_names[] = { ...@@ -562,19 +557,19 @@ static char *llc_conn_state_names[] = {
static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
{ {
struct llc_opt *llc; struct list_head *sap_entry;
struct list_head *sap_entry, *llc_entry; struct sock *sk;
off_t begin = 0, pos = 0; off_t begin = 0, pos = 0;
int len = 0; int len = 0;
spin_lock_bh(&llc_main_station.sap_list.lock); read_lock_bh(&llc_main_station.sap_list.lock);
list_for_each(sap_entry, &llc_main_station.sap_list.list) { list_for_each(sap_entry, &llc_main_station.sap_list.list) {
struct llc_sap *sap = list_entry(sap_entry, struct llc_sap, struct llc_sap *sap = list_entry(sap_entry, struct llc_sap,
node); node);
len += sprintf(bf + len, "lsap=%02X\n", sap->laddr.lsap); len += sprintf(bf + len, "lsap=%02X\n", sap->laddr.lsap);
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
if (list_empty(&sap->sk_list.list)) { if (!sap->sk_list.list) {
len += sprintf(bf + len, "no connections\n"); len += sprintf(bf + len, "no connections\n");
goto unlock; goto unlock;
} }
...@@ -582,8 +577,9 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -582,8 +577,9 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
"dsap state retr txw rxw " "dsap state retr txw rxw "
"pf ff sf df rs cs " "pf ff sf df rs cs "
"tack tpfc trs tbs blog busr\n"); "tack tpfc trs tbs blog busr\n");
list_for_each(llc_entry, &sap->sk_list.list) { for (sk = sap->sk_list.list; sk; sk = sk->next) {
llc = list_entry(llc_entry, struct llc_opt, node); struct llc_opt *llc = llc_sk(sk);
len += sprintf(bf + len, " %02X %-10s %3d %3d %3d " len += sprintf(bf + len, " %02X %-10s %3d %3d %3d "
"%2d %2d %2d " "%2d %2d %2d "
"%2d %2d %2d " "%2d %2d %2d "
...@@ -598,11 +594,10 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -598,11 +594,10 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
timer_pending(&llc->pf_cycle_timer.timer), timer_pending(&llc->pf_cycle_timer.timer),
timer_pending(&llc->rej_sent_timer.timer), timer_pending(&llc->rej_sent_timer.timer),
timer_pending(&llc->busy_state_timer.timer), timer_pending(&llc->busy_state_timer.timer),
!!llc->sk->backlog.tail, !!sk->backlog.tail, sk->lock.users);
llc->sk->lock.users);
} }
unlock: unlock:
spin_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
pos = begin + len; pos = begin + len;
if (pos < offset) { if (pos < offset) {
len = 0; /* Keep dumping into the buffer start */ len = 0; /* Keep dumping into the buffer start */
...@@ -611,7 +606,7 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length) ...@@ -611,7 +606,7 @@ static int llc_proc_get_info(char *bf, char **start, off_t offset, int length)
if (pos > offset + length) /* We have dumped enough */ if (pos > offset + length) /* We have dumped enough */
break; break;
} }
spin_unlock_bh(&llc_main_station.sap_list.lock); read_unlock_bh(&llc_main_station.sap_list.lock);
/* The data in question runs from begin to begin + len */ /* The data in question runs from begin to begin + len */
*start = bf + (offset - begin); /* Start of wanted data */ *start = bf + (offset - begin); /* Start of wanted data */
...@@ -632,8 +627,8 @@ static struct packet_type llc_tr_packet_type = { ...@@ -632,8 +627,8 @@ static struct packet_type llc_tr_packet_type = {
}; };
static char llc_banner[] __initdata = static char llc_banner[] __initdata =
KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001\n" KERN_INFO "LLC 2.0 by Procom, 1997, Arnaldo C. Melo, 2001, 2002\n"
KERN_INFO "NET4.0 IEEE 802.2 extended support\n"; KERN_INFO "NET 4.0 IEEE 802.2 extended support\n";
static char llc_error_msg[] __initdata = static char llc_error_msg[] __initdata =
KERN_ERR "LLC install NOT successful.\n"; KERN_ERR "LLC install NOT successful.\n";
...@@ -693,5 +688,5 @@ module_init(llc_init); ...@@ -693,5 +688,5 @@ module_init(llc_init);
module_exit(llc_exit); module_exit(llc_exit);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001"); MODULE_AUTHOR("Procom, 1997, Arnaldo C. Melo, Jay Schullist, 2001, 2002");
MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support"); MODULE_DESCRIPTION("LLC 2.0, NET4.0 IEEE 802.2 extended support");
...@@ -40,11 +40,15 @@ static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap, ...@@ -40,11 +40,15 @@ static struct llc_sap_state_trans *llc_find_sap_trans(struct llc_sap *sap,
*/ */
void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk) void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
{ {
spin_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
llc_sk(sk)->sap = sap; llc_sk(sk)->sap = sap;
list_add_tail(&llc_sk(sk)->node, &sap->sk_list.list); sk->next = sap->sk_list.list;
if (sk->next)
sap->sk_list.list->pprev = &sk->next;
sap->sk_list.list = sk;
sk->pprev = &sap->sk_list.list;
sock_hold(sk); sock_hold(sk);
spin_unlock_bh(&sap->sk_list.lock); write_unlock_bh(&sap->sk_list.lock);
} }
/** /**
...@@ -56,10 +60,19 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk) ...@@ -56,10 +60,19 @@ void llc_sap_assign_sock(struct llc_sap *sap, struct sock *sk)
*/ */
void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk) void llc_sap_unassign_sock(struct llc_sap *sap, struct sock *sk)
{ {
spin_lock_bh(&sap->sk_list.lock); write_lock_bh(&sap->sk_list.lock);
list_del(&llc_sk(sk)->node); if (sk->pprev) {
sock_put(sk); if (sk->next)
spin_unlock_bh(&sap->sk_list.lock); sk->next->pprev = sk->pprev;
*sk->pprev = sk->next;
sk->pprev = NULL;
/*
* This only makes sense if the socket was inserted on the
* list, if sk->pprev is NULL it wasn't
*/
sock_put(sk);
}
write_unlock_bh(&sap->sk_list.lock);
} }
/** /**
......
...@@ -198,7 +198,7 @@ static int llc_ui_release(struct socket *sock) ...@@ -198,7 +198,7 @@ static int llc_ui_release(struct socket *sock)
if (!sk->zapped) if (!sk->zapped)
llc_sap_unassign_sock(llc->sap, sk); llc_sap_unassign_sock(llc->sap, sk);
release_sock(sk); release_sock(sk);
if (llc->sap && list_empty(&llc->sap->sk_list.list)) if (llc->sap && !llc->sap->sk_list.list)
llc_sap_close(llc->sap); llc_sap_close(llc->sap);
sock_put(sk); sock_put(sk);
llc_sk_free(sk); llc_sk_free(sk);
...@@ -1042,25 +1042,24 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1042,25 +1042,24 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
{ {
off_t pos = 0; off_t pos = 0;
off_t begin = 0; off_t begin = 0;
struct llc_opt *llc;
struct llc_sap *sap; struct llc_sap *sap;
struct list_head *sap_entry, *llc_entry; struct sock *sk;
struct list_head *sap_entry;
struct llc_station *station = llc_station_get(); struct llc_station *station = llc_station_get();
int len = sprintf(buffer, "SKt Mc local_mac_sap " int len = sprintf(buffer, "SKt Mc local_mac_sap "
"remote_mac_sap tx_queue rx_queue st uid " "remote_mac_sap tx_queue rx_queue st uid "
"link\n"); "link\n");
/* Output the LLC socket data for the /proc filesystem */ /* Output the LLC socket data for the /proc filesystem */
spin_lock_bh(&station->sap_list.lock); read_lock_bh(&station->sap_list.lock);
list_for_each(sap_entry, &station->sap_list.list) { list_for_each(sap_entry, &station->sap_list.list) {
sap = list_entry(sap_entry, struct llc_sap, node); sap = list_entry(sap_entry, struct llc_sap, node);
spin_lock_bh(&sap->sk_list.lock); read_lock_bh(&sap->sk_list.lock);
list_for_each(llc_entry, &sap->sk_list.list) { for (sk = sap->sk_list.list; sk; sk = sk->next) {
llc = list_entry(llc_entry, struct llc_opt, node); struct llc_opt *llc = llc_sk(sk);
len += sprintf(buffer + len, "%2X %2X ", len += sprintf(buffer + len, "%2X %2X ", sk->type,
llc->sk->type,
!llc_mac_null(llc->addr.sllc_mmac)); !llc_mac_null(llc->addr.sllc_mmac));
if (llc->dev && llc_mac_null(llc->addr.sllc_mmac)) if (llc->dev && llc_mac_null(llc->addr.sllc_mmac))
llc_ui_format_mac(buffer + len, llc_ui_format_mac(buffer + len,
...@@ -1080,12 +1079,11 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1080,12 +1079,11 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
len += sprintf(buffer + len, len += sprintf(buffer + len,
"@%02X %8d %8d %2d %3d ", "@%02X %8d %8d %2d %3d ",
llc->addr.sllc_dsap, llc->addr.sllc_dsap,
atomic_read(&llc->sk->wmem_alloc), atomic_read(&sk->wmem_alloc),
atomic_read(&llc->sk->rmem_alloc), atomic_read(&sk->rmem_alloc),
llc->sk->state, sk->state,
llc->sk->socket ? sk->socket ?
SOCK_INODE(llc->sk->socket)->i_uid : SOCK_INODE(sk->socket)->i_uid : -1);
-1);
len += sprintf(buffer + len, "%4d\n", llc->link); len += sprintf(buffer + len, "%4d\n", llc->link);
/* Are we still dumping unwanted data then discard the record */ /* Are we still dumping unwanted data then discard the record */
pos = begin + len; pos = begin + len;
...@@ -1097,9 +1095,9 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length) ...@@ -1097,9 +1095,9 @@ static int llc_ui_get_info(char *buffer, char **start, off_t offset, int length)
if (pos > offset + length) /* We have dumped enough */ if (pos > offset + length) /* We have dumped enough */
break; break;
} }
spin_unlock_bh(&sap->sk_list.lock); read_unlock_bh(&sap->sk_list.lock);
} }
spin_unlock_bh(&station->sap_list.lock); read_unlock_bh(&station->sap_list.lock);
/* The data in question runs from begin to begin + len */ /* The data in question runs from begin to begin + len */
*start = buffer + offset - begin; /* Start of wanted data */ *start = buffer + offset - begin; /* Start of wanted data */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment