Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171222
b: refs/heads/master
c: c2315b4
h: refs/heads/master
v: v3
  • Loading branch information
Inaky Perez-Gonzalez committed Oct 19, 2009
1 parent 58295f7 commit ba76beb
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8f90f3ee83dc54e182d6a7548727cbae4b523e6e
refs/heads/master: c2315b4ea9ac9c3f8caf03c3511d86fabe4a5fcd
44 changes: 29 additions & 15 deletions trunk/drivers/net/wimax/i2400m/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,14 +455,15 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)
result = i2400m->bus_dev_start(i2400m);
if (result < 0)
goto error_bus_dev_start;
i2400m->ready = 1;
wmb(); /* see i2400m->ready's documentation */
result = i2400m_firmware_check(i2400m); /* fw versions ok? */
if (result < 0)
goto error_fw_check;
/* At this point is ok to send commands to the device */
result = i2400m_check_mac_addr(i2400m);
if (result < 0)
goto error_check_mac_addr;
i2400m->ready = 1;
wimax_state_change(wimax_dev, WIMAX_ST_UNINITIALIZED);
result = i2400m_dev_initialize(i2400m);
if (result < 0)
Expand All @@ -475,6 +476,9 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)

error_dev_initialize:
error_check_mac_addr:
i2400m->ready = 0;
wmb(); /* see i2400m->ready's documentation */
flush_workqueue(i2400m->work_queue);
error_fw_check:
i2400m->bus_dev_stop(i2400m);
error_bus_dev_start:
Expand All @@ -498,11 +502,15 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)
static
int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags)
{
int result;
int result = 0;
mutex_lock(&i2400m->init_mutex); /* Well, start the device */
result = __i2400m_dev_start(i2400m, bm_flags);
if (result >= 0)
i2400m->updown = 1;
if (i2400m->updown == 0) {
result = __i2400m_dev_start(i2400m, bm_flags);
if (result >= 0) {
i2400m->updown = 1;
wmb(); /* see i2400m->updown's documentation */
}
}
mutex_unlock(&i2400m->init_mutex);
return result;
}
Expand All @@ -529,7 +537,14 @@ void __i2400m_dev_stop(struct i2400m *i2400m)
wimax_state_change(wimax_dev, __WIMAX_ST_QUIESCING);
i2400m_net_wake_stop(i2400m);
i2400m_dev_shutdown(i2400m);
i2400m->ready = 0;
/*
* Make sure no report hooks are running *before* we stop the
* communication infrastructure with the device.
*/
i2400m->ready = 0; /* nobody can queue work anymore */
wmb(); /* see i2400m->ready's documentation */
flush_workqueue(i2400m->work_queue);

i2400m->bus_dev_stop(i2400m);
destroy_workqueue(i2400m->work_queue);
i2400m_rx_release(i2400m);
Expand All @@ -551,6 +566,7 @@ void i2400m_dev_stop(struct i2400m *i2400m)
if (i2400m->updown) {
__i2400m_dev_stop(i2400m);
i2400m->updown = 0;
wmb(); /* see i2400m->updown's documentation */
}
mutex_unlock(&i2400m->init_mutex);
}
Expand Down Expand Up @@ -632,7 +648,6 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)
const char *reason;
struct i2400m *i2400m = iw->i2400m;
struct device *dev = i2400m_dev(i2400m);
enum wimax_st wimax_state;
struct i2400m_reset_ctx *ctx = i2400m->reset_ctx;

if (WARN_ON(iw->pl_size != sizeof(reason)))
Expand All @@ -647,29 +662,28 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)
/* We are still in i2400m_dev_start() [let it fail] or
* i2400m_dev_stop() [we are shutting down anyway, so
* ignore it] or we are resetting somewhere else. */
dev_err(dev, "device rebooted\n");
dev_err(dev, "device rebooted somewhere else?\n");
i2400m_msg_to_dev_cancel_wait(i2400m, -EL3RST);
complete(&i2400m->msg_completion);
goto out;
}
wimax_state = wimax_state_get(&i2400m->wimax_dev);
if (wimax_state < WIMAX_ST_UNINITIALIZED) {
dev_info(dev, "%s: it is down, ignoring\n", reason);
goto out_unlock; /* ifconfig up/down wasn't called */
if (i2400m->updown == 0) {
dev_info(dev, "%s: device is down, doing nothing\n", reason);
goto out_unlock;
}
dev_err(dev, "%s: reinitializing driver\n", reason);
__i2400m_dev_stop(i2400m);
i2400m->updown = 0;
result = __i2400m_dev_start(i2400m,
I2400M_BRI_SOFT | I2400M_BRI_MAC_REINIT);
if (result < 0) {
i2400m->updown = 0;
wmb(); /* see i2400m->updown's documentation */
dev_err(dev, "%s: cannot start the device: %d\n",
reason, result);
result = i2400m->bus_reset(i2400m, I2400M_RT_BUS);
if (result >= 0)
result = -ENODEV;
} else
i2400m->updown = 1;
}
out_unlock:
if (i2400m->reset_ctx) {
ctx->result = result;
Expand Down
23 changes: 22 additions & 1 deletion trunk/drivers/net/wimax/i2400m/i2400m.h
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,27 @@ struct i2400m_barker_db;
* force this to be the first field so that we can get from
* netdev_priv() the right pointer.
*
* @updown: the device is up and ready for transmitting control and
* data packets. This implies @ready (communication infrastructure
* with the device is ready) and the device's firmware has been
* loaded and the device initialized.
*
* Write to it only inside a i2400m->init_mutex protected area
* followed with a wmb(); rmb() before accesing (unless locked
* inside i2400m->init_mutex). Read access can be loose like that
* [just using rmb()] because the paths that use this also do
* other error checks later on.
*
* @ready: Communication infrastructure with the device is ready, data
* frames can start to be passed around (this is lighter than
* using the WiMAX state for certain hot paths).
*
* Write to it only inside a i2400m->init_mutex protected area
* followed with a wmb(); rmb() before accesing (unless locked
* inside i2400m->init_mutex). Read access can be loose like that
* [just using rmb()] because the paths that use this also do
* other error checks later on.
*
* @rx_reorder: 1 if RX reordering is enabled; this can only be
* set at probe time.
*
Expand Down Expand Up @@ -458,7 +479,7 @@ struct i2400m {
unsigned updown:1; /* Network device is up or down */
unsigned boot_mode:1; /* is the device in boot mode? */
unsigned sboot:1; /* signed or unsigned fw boot */
unsigned ready:1; /* all probing steps done */
unsigned ready:1; /* Device comm infrastructure ready */
unsigned rx_reorder:1; /* RX reorder is enabled */
u8 trace_msg_from_user; /* echo rx msgs to 'trace' pipe */
/* typed u8 so /sys/kernel/debug/u8 can tweak */
Expand Down
16 changes: 7 additions & 9 deletions trunk/drivers/net/wimax/i2400m/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,7 @@ void i2400m_report_hook_work(struct work_struct *ws)
struct i2400m_work *iw =
container_of(ws, struct i2400m_work, ws);
struct i2400m_report_hook_args *args = (void *) iw->pl;
if (iw->i2400m->ready)
i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size);
i2400m_report_hook(iw->i2400m, args->l3l4_hdr, args->size);
kfree_skb(args->skb_rx);
i2400m_put(iw->i2400m);
kfree(iw);
Expand Down Expand Up @@ -305,11 +304,12 @@ void i2400m_rx_ctl(struct i2400m *i2400m, struct sk_buff *skb_rx,
.l3l4_hdr = l3l4_hdr,
.size = size
};
if (unlikely(i2400m->ready == 0)) /* only send if up */
return;
skb_get(skb_rx);
i2400m_queue_work(i2400m, i2400m_report_hook_work,
GFP_KERNEL, &args, sizeof(args));
rmb(); /* see i2400m->ready's documentation */
if (likely(i2400m->ready)) { /* only send if up */
skb_get(skb_rx);
i2400m_queue_work(i2400m, i2400m_report_hook_work,
GFP_KERNEL, &args, sizeof(args));
}
if (unlikely(i2400m->trace_msg_from_user))
wimax_msg(&i2400m->wimax_dev, "echo",
l3l4_hdr, size, GFP_KERNEL);
Expand Down Expand Up @@ -363,8 +363,6 @@ void i2400m_rx_trace(struct i2400m *i2400m,
msg_type & I2400M_MT_REPORT_MASK ? "REPORT" : "CMD/SET/GET",
msg_type, size);
d_dump(2, dev, l3l4_hdr, size);
if (unlikely(i2400m->ready == 0)) /* only send if up */
return;
result = wimax_msg(wimax_dev, "trace", l3l4_hdr, size, GFP_KERNEL);
if (result < 0)
dev_err(dev, "error sending trace to userspace: %d\n",
Expand Down
7 changes: 6 additions & 1 deletion trunk/drivers/net/wimax/i2400m/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,10 @@ void i2400mu_disconnect(struct usb_interface *iface)
* So at the end, the three cases require common handling.
*
* If at the time of this call the device's firmware is not loaded,
* nothing has to be done.
* nothing has to be done. Note we can be "loose" about not reading
* i2400m->updown under i2400m->init_mutex. If it happens to change
* inmediately, other parts of the call flow will fail and effectively
* catch it.
*
* If the firmware is loaded, we need to:
*
Expand Down Expand Up @@ -555,6 +558,7 @@ int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
#endif

d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event);
rmb(); /* see i2400m->updown's documentation */
if (i2400m->updown == 0)
goto no_firmware;
if (i2400m->state == I2400M_SS_DATA_PATH_CONNECTED && is_autosuspend) {
Expand Down Expand Up @@ -608,6 +612,7 @@ int i2400mu_resume(struct usb_interface *iface)
struct i2400m *i2400m = &i2400mu->i2400m;

d_fnstart(3, dev, "(iface %p)\n", iface);
rmb(); /* see i2400m->updown's documentation */
if (i2400m->updown == 0) {
d_printf(1, dev, "fw was down, no resume neeed\n");
goto out;
Expand Down
6 changes: 6 additions & 0 deletions trunk/include/net/wimax.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,12 @@
* defining the `struct nla_policy` for each message, it has to have
* an array size of WIMAX_GNL_ATTR_MAX+1.
*
* The op_*() function pointers will not be called if the wimax_dev is
* in a state <= %WIMAX_ST_UNINITIALIZED. The exception is:
*
* - op_reset: can be called at any time after wimax_dev_add() has
* been called.
*
* THE PIPE INTERFACE:
*
* This interface is kept intentionally simple. The driver can send
Expand Down

0 comments on commit ba76beb

Please sign in to comment.