Commit 3e65b7a3 authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/disk1/davem/BK/network-2.5

into nuts.ninka.net:/disk1/davem/BK/net-2.5
parents db4cf641 83055835
...@@ -84,12 +84,12 @@ static int act200l_change_speed(struct irda_task *task); ...@@ -84,12 +84,12 @@ static int act200l_change_speed(struct irda_task *task);
#define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */ #define ACT200L_OSCL 0x04 /* oscillator in low power, medium accuracy mode */
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_ACT200L_DONGLE,
IRDA_ACT200L_DONGLE, .open = act200l_open,
act200l_open, .close = act200l_close,
act200l_close, .reset = act200l_reset,
act200l_reset, .change_speed = act200l_change_speed,
act200l_change_speed, .owner = THIS_MODULE,
}; };
int __init act200l_init(void) int __init act200l_init(void)
...@@ -112,8 +112,6 @@ static void act200l_open(dongle_t *self, struct qos_info *qos) ...@@ -112,8 +112,6 @@ static void act200l_open(dongle_t *self, struct qos_info *qos)
/* Set the speeds we can accept */ /* Set the speeds we can accept */
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x03; qos->min_turn_time.bits = 0x03;
MOD_INC_USE_COUNT;
} }
static void act200l_close(dongle_t *self) static void act200l_close(dongle_t *self)
...@@ -122,8 +120,6 @@ static void act200l_close(dongle_t *self) ...@@ -122,8 +120,6 @@ static void act200l_close(dongle_t *self)
/* Power off the dongle */ /* Power off the dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE); self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -64,21 +64,21 @@ static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 }; ...@@ -64,21 +64,21 @@ static __u32 baud_rates[] = { 9600, 19200, 57600, 115200, 38400 };
#define MAX_SPEEDS 5 #define MAX_SPEEDS 5
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_ACTISYS_DONGLE,
IRDA_ACTISYS_DONGLE, .open = actisys_open,
actisys_open, .close = actisys_close,
actisys_close, .reset = actisys_reset,
actisys_reset, .change_speed = actisys_change_speed,
actisys_change_speed, .owner = THIS_MODULE,
}; };
static struct dongle_reg dongle_plus = { static struct dongle_reg dongle_plus = {
Q_NULL, .type = IRDA_ACTISYS_PLUS_DONGLE,
IRDA_ACTISYS_PLUS_DONGLE, .open = actisys_open,
actisys_open, .close = actisys_close,
actisys_close, .reset = actisys_reset,
actisys_reset, .change_speed = actisys_change_speed,
actisys_change_speed, .owner = THIS_MODULE,
}; };
/* /*
...@@ -128,16 +128,12 @@ static void actisys_open(dongle_t *self, struct qos_info *qos) ...@@ -128,16 +128,12 @@ static void actisys_open(dongle_t *self, struct qos_info *qos)
qos->baud_rate.bits &= ~IR_38400; qos->baud_rate.bits &= ~IR_38400;
qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */ qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
MOD_INC_USE_COUNT;
} }
static void actisys_close(dongle_t *self) static void actisys_close(dongle_t *self)
{ {
/* Power off the dongle */ /* Power off the dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE); self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -24,12 +24,12 @@ static int ep7211_ir_change_speed(struct irda_task *task); ...@@ -24,12 +24,12 @@ static int ep7211_ir_change_speed(struct irda_task *task);
static int ep7211_ir_reset(struct irda_task *task); static int ep7211_ir_reset(struct irda_task *task);
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_EP7211_IR,
IRDA_EP7211_IR, .open = ep7211_ir_open,
ep7211_ir_open, .close = ep7211_ir_close,
ep7211_ir_close, .reset = ep7211_ir_reset,
ep7211_ir_reset, .change_speed = ep7211_ir_change_speed,
ep7211_ir_change_speed, .owner = THIS_MODULE,
}; };
static void ep7211_ir_open(dongle_t *self, struct qos_info *qos) static void ep7211_ir_open(dongle_t *self, struct qos_info *qos)
...@@ -47,8 +47,6 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos) ...@@ -47,8 +47,6 @@ static void ep7211_ir_open(dongle_t *self, struct qos_info *qos)
UART (interrupt #14). */ UART (interrupt #14). */
restore_flags(flags); restore_flags(flags);
MOD_INC_USE_COUNT;
} }
static void ep7211_ir_close(dongle_t *self) static void ep7211_ir_close(dongle_t *self)
...@@ -66,8 +64,6 @@ static void ep7211_ir_close(dongle_t *self) ...@@ -66,8 +64,6 @@ static void ep7211_ir_close(dongle_t *self)
reset them back to their original state. */ reset them back to their original state. */
restore_flags(flags); restore_flags(flags);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -44,12 +44,12 @@ static int esi_change_speed(struct irda_task *task); ...@@ -44,12 +44,12 @@ static int esi_change_speed(struct irda_task *task);
static int esi_reset(struct irda_task *task); static int esi_reset(struct irda_task *task);
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_ESI_DONGLE,
IRDA_ESI_DONGLE, .open = esi_open,
esi_open, .close = esi_close,
esi_close, .reset = esi_reset,
esi_reset, .change_speed = esi_change_speed,
esi_change_speed, .owner = THIS_MODULE,
}; };
int __init esi_init(void) int __init esi_init(void)
...@@ -66,16 +66,12 @@ static void esi_open(dongle_t *self, struct qos_info *qos) ...@@ -66,16 +66,12 @@ static void esi_open(dongle_t *self, struct qos_info *qos)
{ {
qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200; qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
MOD_INC_USE_COUNT;
} }
static void esi_close(dongle_t *dongle) static void esi_close(dongle_t *dongle)
{ {
/* Power off dongle */ /* Power off dongle */
dongle->set_dtr_rts(dongle->dev, FALSE, FALSE); dongle->set_dtr_rts(dongle->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -63,12 +63,12 @@ static int girbil_change_speed(struct irda_task *task); ...@@ -63,12 +63,12 @@ static int girbil_change_speed(struct irda_task *task);
#define GIRBIL_LOAD 0x51 /* Load the new baud rate value */ #define GIRBIL_LOAD 0x51 /* Load the new baud rate value */
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_GIRBIL_DONGLE,
IRDA_GIRBIL_DONGLE, .open = girbil_open,
girbil_open, .close = girbil_close,
girbil_close, .reset = girbil_reset,
girbil_reset, .change_speed = girbil_change_speed,
girbil_change_speed, .owner = THIS_MODULE,
}; };
int __init girbil_init(void) int __init girbil_init(void)
...@@ -85,16 +85,12 @@ static void girbil_open(dongle_t *self, struct qos_info *qos) ...@@ -85,16 +85,12 @@ static void girbil_open(dongle_t *self, struct qos_info *qos)
{ {
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x03; qos->min_turn_time.bits = 0x03;
MOD_INC_USE_COUNT;
} }
static void girbil_close(dongle_t *self) static void girbil_close(dongle_t *self)
{ {
/* Power off dongle */ /* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE); self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -48,12 +48,12 @@ static int litelink_reset(struct irda_task *task); ...@@ -48,12 +48,12 @@ static int litelink_reset(struct irda_task *task);
static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 }; static __u32 baud_rates[] = { 115200, 57600, 38400, 19200, 9600 };
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_LITELINK_DONGLE,
IRDA_LITELINK_DONGLE, .open = litelink_open,
litelink_open, .close = litelink_close,
litelink_close, .reset = litelink_reset,
litelink_reset, .change_speed = litelink_change_speed,
litelink_change_speed, .owner = THIS_MODULE,
}; };
int __init litelink_init(void) int __init litelink_init(void)
...@@ -70,16 +70,12 @@ static void litelink_open(dongle_t *self, struct qos_info *qos) ...@@ -70,16 +70,12 @@ static void litelink_open(dongle_t *self, struct qos_info *qos)
{ {
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */ qos->min_turn_time.bits = 0x7f; /* Needs 0.01 ms */
MOD_INC_USE_COUNT;
} }
static void litelink_close(dongle_t *self) static void litelink_close(dongle_t *self)
{ {
/* Power off dongle */ /* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE); self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -74,12 +74,12 @@ static int ma600_reset(struct irda_task *task); ...@@ -74,12 +74,12 @@ static int ma600_reset(struct irda_task *task);
#define MA600_2400 0x08 #define MA600_2400 0x08
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_MA600_DONGLE,
IRDA_MA600_DONGLE, .open = ma600_open,
ma600_open, .close = ma600_close,
ma600_close, .reset = ma600_reset,
ma600_reset, .change_speed = ma600_change_speed,
ma600_change_speed, .owner = THIS_MODULE,
}; };
int __init ma600_init(void) int __init ma600_init(void)
...@@ -115,8 +115,6 @@ static void ma600_open(dongle_t *self, struct qos_info *qos) ...@@ -115,8 +115,6 @@ static void ma600_open(dongle_t *self, struct qos_info *qos)
self->set_dtr_rts(self->dev, TRUE, TRUE); self->set_dtr_rts(self->dev, TRUE, TRUE);
// should wait 1 second // should wait 1 second
MOD_INC_USE_COUNT;
} }
static void ma600_close(dongle_t *self) static void ma600_close(dongle_t *self)
...@@ -125,8 +123,6 @@ static void ma600_close(dongle_t *self) ...@@ -125,8 +123,6 @@ static void ma600_close(dongle_t *self)
/* Power off dongle */ /* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE); self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
static __u8 get_control_byte(__u32 speed) static __u8 get_control_byte(__u32 speed)
......
...@@ -40,12 +40,12 @@ static int mcp2120_change_speed(struct irda_task *task); ...@@ -40,12 +40,12 @@ static int mcp2120_change_speed(struct irda_task *task);
#define MCP2120_COMMIT 0x11 #define MCP2120_COMMIT 0x11
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_MCP2120_DONGLE,
IRDA_MCP2120_DONGLE, .open = mcp2120_open,
mcp2120_open, .close = mcp2120_close,
mcp2120_close, .reset = mcp2120_reset,
mcp2120_reset, .change_speed = mcp2120_change_speed,
mcp2120_change_speed, .owner = THIS_MODULE,
}; };
int __init mcp2120_init(void) int __init mcp2120_init(void)
...@@ -62,8 +62,6 @@ static void mcp2120_open(dongle_t *self, struct qos_info *qos) ...@@ -62,8 +62,6 @@ static void mcp2120_open(dongle_t *self, struct qos_info *qos)
{ {
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01; qos->min_turn_time.bits = 0x01;
MOD_INC_USE_COUNT;
} }
static void mcp2120_close(dongle_t *self) static void mcp2120_close(dongle_t *self)
...@@ -72,8 +70,6 @@ static void mcp2120_close(dongle_t *self) ...@@ -72,8 +70,6 @@ static void mcp2120_close(dongle_t *self)
/* reset and inhibit mcp2120 */ /* reset and inhibit mcp2120 */
self->set_dtr_rts(self->dev, TRUE, TRUE); self->set_dtr_rts(self->dev, TRUE, TRUE);
//self->set_dtr_rts(self->dev, FALSE, FALSE); //self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -74,12 +74,12 @@ static int old_belkin_reset(struct irda_task *task); ...@@ -74,12 +74,12 @@ static int old_belkin_reset(struct irda_task *task);
/* static __u32 baud_rates[] = { 9600 }; */ /* static __u32 baud_rates[] = { 9600 }; */
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_OLD_BELKIN_DONGLE,
IRDA_OLD_BELKIN_DONGLE, .open = old_belkin_open,
old_belkin_open, .close = old_belkin_close,
old_belkin_close, .reset = old_belkin_reset,
old_belkin_reset, .change_speed = old_belkin_change_speed,
old_belkin_change_speed, .owner = THIS_MODULE,
}; };
int __init old_belkin_init(void) int __init old_belkin_init(void)
...@@ -98,16 +98,12 @@ static void old_belkin_open(dongle_t *self, struct qos_info *qos) ...@@ -98,16 +98,12 @@ static void old_belkin_open(dongle_t *self, struct qos_info *qos)
qos->baud_rate.bits &= IR_9600; qos->baud_rate.bits &= IR_9600;
/* Needs at least 10 ms (totally wild guess, can do probably better) */ /* Needs at least 10 ms (totally wild guess, can do probably better) */
qos->min_turn_time.bits = 0x01; qos->min_turn_time.bits = 0x01;
MOD_INC_USE_COUNT;
} }
static void old_belkin_close(dongle_t *self) static void old_belkin_close(dongle_t *self)
{ {
/* Power off dongle */ /* Power off dongle */
self->set_dtr_rts(self->dev, FALSE, FALSE); self->set_dtr_rts(self->dev, FALSE, FALSE);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -44,12 +44,12 @@ static int tekram_reset(struct irda_task *task); ...@@ -44,12 +44,12 @@ static int tekram_reset(struct irda_task *task);
#define TEKRAM_PW 0x10 /* Pulse select bit */ #define TEKRAM_PW 0x10 /* Pulse select bit */
static struct dongle_reg dongle = { static struct dongle_reg dongle = {
Q_NULL, .type = IRDA_TEKRAM_DONGLE,
IRDA_TEKRAM_DONGLE, .open = tekram_open,
tekram_open, .close = tekram_close,
tekram_close, .reset = tekram_reset,
tekram_reset, .change_speed = tekram_change_speed,
tekram_change_speed, .owner = THIS_MODULE,
}; };
int __init tekram_init(void) int __init tekram_init(void)
...@@ -69,8 +69,6 @@ static void tekram_open(dongle_t *self, struct qos_info *qos) ...@@ -69,8 +69,6 @@ static void tekram_open(dongle_t *self, struct qos_info *qos)
qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200; qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */ qos->min_turn_time.bits = 0x01; /* Needs at least 10 ms */
irda_qos_bits_to_value(qos); irda_qos_bits_to_value(qos);
MOD_INC_USE_COUNT;
} }
static void tekram_close(dongle_t *self) static void tekram_close(dongle_t *self)
...@@ -84,8 +82,6 @@ static void tekram_close(dongle_t *self) ...@@ -84,8 +82,6 @@ static void tekram_close(dongle_t *self)
irda_task_delete(self->reset_task); irda_task_delete(self->reset_task);
if (self->speed_task) if (self->speed_task)
irda_task_delete(self->speed_task); irda_task_delete(self->speed_task);
MOD_DEC_USE_COUNT;
} }
/* /*
......
...@@ -1300,12 +1300,9 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) ...@@ -1300,12 +1300,9 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )
switch( cmd ) { switch( cmd ) {
case SIOCDEVGETINSTATS : case SIOCDEVGETINSTATS :
error = verify_area( VERIFY_WRITE, ifr->ifr_data, if (copy_to_user( ifr->ifr_data, &nl->in_stats,
sizeof(struct sbni_in_stats) ); sizeof(struct sbni_in_stats) ))
if( !error ) error = -EFAULT;
if (copy_to_user( ifr->ifr_data, &nl->in_stats,
sizeof(struct sbni_in_stats) ))
return -EFAULT;
break; break;
case SIOCDEVRESINSTATS : case SIOCDEVRESINSTATS :
...@@ -1321,11 +1318,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) ...@@ -1321,11 +1318,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )
flags.rxl = nl->cur_rxl_index; flags.rxl = nl->cur_rxl_index;
flags.fixed_rxl = nl->delta_rxl == 0; flags.fixed_rxl = nl->delta_rxl == 0;
error = verify_area( VERIFY_WRITE, ifr->ifr_data, if (copy_to_user( ifr->ifr_data, &flags, sizeof flags ))
sizeof flags ); error = -EFAULT;
if( !error )
if (copy_to_user( ifr->ifr_data, &flags, sizeof flags ))
return -EFAULT;
break; break;
case SIOCDEVSHWSTATE : case SIOCDEVSHWSTATE :
...@@ -1353,10 +1347,6 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) ...@@ -1353,10 +1347,6 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )
if( current->euid != 0 ) /* root only */ if( current->euid != 0 ) /* root only */
return -EPERM; return -EPERM;
if( (error = verify_area( VERIFY_READ, ifr->ifr_data,
sizeof slave_name )) != 0 )
return error;
if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name )) if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name ))
return -EFAULT; return -EFAULT;
slave_dev = dev_get_by_name( slave_name ); slave_dev = dev_get_by_name( slave_name );
......
...@@ -236,7 +236,7 @@ void sppp_input (struct net_device *dev, struct sk_buff *skb) ...@@ -236,7 +236,7 @@ void sppp_input (struct net_device *dev, struct sk_buff *skb)
sp->ipkts++; sp->ipkts++;
} }
if (skb->len <= PPP_HEADER_LEN) { if (!pskb_may_pull(skb, PPP_HEADER_LEN)) {
/* Too small packet, drop it. */ /* Too small packet, drop it. */
if (sp->pp_flags & PP_DEBUG) if (sp->pp_flags & PP_DEBUG)
printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n", printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n",
...@@ -473,7 +473,7 @@ static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb) ...@@ -473,7 +473,7 @@ static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb)
u8 *p, opt[6]; u8 *p, opt[6];
u32 rmagic; u32 rmagic;
if (len < 4) { if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
if (sp->pp_flags & PP_DEBUG) if (sp->pp_flags & PP_DEBUG)
printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n", printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n",
dev->name, len); dev->name, len);
...@@ -707,7 +707,9 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb) ...@@ -707,7 +707,9 @@ static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
struct cisco_packet *h; struct cisco_packet *h;
struct net_device *dev = sp->pp_if; struct net_device *dev = sp->pp_if;
if (skb->len != CISCO_PACKET_LEN && skb->len != CISCO_BIG_PACKET_LEN) { if (!pskb_may_pull(skb, sizeof(struct cisco_packet))
|| (skb->len != CISCO_PACKET_LEN
&& skb->len != CISCO_BIG_PACKET_LEN)) {
if (sp->pp_flags & PP_DEBUG) if (sp->pp_flags & PP_DEBUG)
printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n", printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n",
dev->name, skb->len); dev->name, skb->len);
...@@ -1211,8 +1213,7 @@ static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb) ...@@ -1211,8 +1213,7 @@ static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb)
struct net_device *dev = sp->pp_if; struct net_device *dev = sp->pp_if;
int len = skb->len; int len = skb->len;
if (len < 4) if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
{
if (sp->pp_flags & PP_DEBUG) if (sp->pp_flags & PP_DEBUG)
printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n", printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n",
dev->name, len); dev->name, len);
......
...@@ -128,6 +128,7 @@ struct dongle_reg { ...@@ -128,6 +128,7 @@ struct dongle_reg {
void (*close)(dongle_t *dongle); void (*close)(dongle_t *dongle);
int (*reset)(struct irda_task *task); int (*reset)(struct irda_task *task);
int (*change_speed)(struct irda_task *task); int (*change_speed)(struct irda_task *task);
struct module *owner;
}; };
/* /*
......
...@@ -85,7 +85,7 @@ static void irda_task_timer_expired(void *data); ...@@ -85,7 +85,7 @@ static void irda_task_timer_expired(void *data);
int __init irda_device_init( void) int __init irda_device_init( void)
{ {
dongles = hashbin_new(HB_LOCK); dongles = hashbin_new(HB_NOLOCK);
if (dongles == NULL) { if (dongles == NULL) {
printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n"); printk(KERN_WARNING "IrDA: Can't allocate dongles hashbin!\n");
return -ENOMEM; return -ENOMEM;
...@@ -109,7 +109,9 @@ void __exit irda_device_cleanup(void) ...@@ -109,7 +109,9 @@ void __exit irda_device_cleanup(void)
IRDA_DEBUG(4, "%s()\n", __FUNCTION__); IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete); hashbin_delete(tasks, (FREE_FUNC) __irda_task_delete);
spin_lock(&dongles->hb_spinlock);
hashbin_delete(dongles, NULL); hashbin_delete(dongles, NULL);
spin_unlock(&dongles->hb_spinlock);
} }
/* /*
...@@ -424,25 +426,34 @@ int irda_device_txqueue_empty(struct net_device *dev) ...@@ -424,25 +426,34 @@ int irda_device_txqueue_empty(struct net_device *dev)
dongle_t *irda_device_dongle_init(struct net_device *dev, int type) dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
{ {
struct dongle_reg *reg; struct dongle_reg *reg;
dongle_t *dongle; dongle_t *dongle = NULL;
ASSERT(dev != NULL, return NULL;); might_sleep();
spin_lock(&dongles->hb_spinlock);
reg = hashbin_find(dongles, type, NULL);
#ifdef CONFIG_KMOD #ifdef CONFIG_KMOD
ASSERT(!in_interrupt(), return NULL;);
/* Try to load the module needed */ /* Try to load the module needed */
request_module("irda-dongle-%d", type); if (!reg && capable(CAP_SYS_MODULE)) {
spin_unlock(&dongles->hb_spinlock);
request_module("irda-dongle-%d", type);
spin_lock(&dongles->hb_spinlock);
reg = hashbin_find(dongles, type, NULL);
}
#endif #endif
if (!(reg = hashbin_lock_find(dongles, type, NULL))) { if (!reg || !try_module_get(reg->owner) ) {
ERROR("IrDA: Unable to find requested dongle\n"); ERROR("IrDA: Unable to find requested dongle type %x\n", type);
return NULL; goto out;
} }
/* Allocate dongle info for this instance */ /* Allocate dongle info for this instance */
dongle = kmalloc(sizeof(dongle_t), GFP_KERNEL); dongle = kmalloc(sizeof(dongle_t), GFP_KERNEL);
if (!dongle) if (!dongle)
return NULL; goto out;
memset(dongle, 0, sizeof(dongle_t)); memset(dongle, 0, sizeof(dongle_t));
...@@ -450,6 +461,8 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type) ...@@ -450,6 +461,8 @@ dongle_t *irda_device_dongle_init(struct net_device *dev, int type)
dongle->issue = reg; dongle->issue = reg;
dongle->dev = dev; dongle->dev = dev;
out:
spin_unlock(&dongles->hb_spinlock);
return dongle; return dongle;
} }
...@@ -461,7 +474,7 @@ int irda_device_dongle_cleanup(dongle_t *dongle) ...@@ -461,7 +474,7 @@ int irda_device_dongle_cleanup(dongle_t *dongle)
ASSERT(dongle != NULL, return -1;); ASSERT(dongle != NULL, return -1;);
dongle->issue->close(dongle); dongle->issue->close(dongle);
module_put(dongle->issue->owner);
kfree(dongle); kfree(dongle);
return 0; return 0;
...@@ -472,14 +485,16 @@ int irda_device_dongle_cleanup(dongle_t *dongle) ...@@ -472,14 +485,16 @@ int irda_device_dongle_cleanup(dongle_t *dongle)
*/ */
int irda_device_register_dongle(struct dongle_reg *new) int irda_device_register_dongle(struct dongle_reg *new)
{ {
spin_lock(&dongles->hb_spinlock);
/* Check if this dongle has been registered before */ /* Check if this dongle has been registered before */
if (hashbin_lock_find(dongles, new->type, NULL)) { if (hashbin_find(dongles, new->type, NULL)) {
MESSAGE("%s: Dongle already registered\n", __FUNCTION__); MESSAGE("%s: Dongle type %x already registered\n",
return 0; __FUNCTION__, new->type);
} } else {
/* Insert IrDA dongle into hashbin */
/* Insert IrDA dongle into hashbin */ hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL);
hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL); }
spin_unlock(&dongles->hb_spinlock);
return 0; return 0;
} }
...@@ -494,11 +509,11 @@ void irda_device_unregister_dongle(struct dongle_reg *dongle) ...@@ -494,11 +509,11 @@ void irda_device_unregister_dongle(struct dongle_reg *dongle)
{ {
struct dongle *node; struct dongle *node;
spin_lock(&dongles->hb_spinlock);
node = hashbin_remove(dongles, dongle->type, NULL); node = hashbin_remove(dongles, dongle->type, NULL);
if (!node) { if (!node)
ERROR("%s: dongle not found!\n", __FUNCTION__); ERROR("%s: dongle not found!\n", __FUNCTION__);
return; spin_unlock(&dongles->hb_spinlock);
}
} }
/* /*
......
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