[2.6.31 00/21] WiMAX pull request
Subsystems (2)
This pull requests contains a long set of fixes to bugs and issues found while debugging the SDIO version of the i2400m WiMAX device. Most of them are in the generic part of the i2400m, and thus, apply to both the USB and SDIO versions:
- tweaks and fixes to the firmware loader to ensure it can recover the device from corner cases we can get it into and that it can support more different varities of hardware
- SDIO driver improvements: support bus-level reset, make RX fully IRQ driven (even in firmware load mode)
- misc validation/debug assists
- fix panics caused by some corner cases in the TX code
- miscellaneous small cleanups in code and documentation
- compiler warnings in the sh4 architecture
The following changes since commit 0ed586d075ef65c0268982e5b7f36d0ffaa95547:
Roel Kluin (1):
atl1c: WAKE_MCAST tested twice, not WAKE_UCAST
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax.git linux-2.6.31.y
Patches follow for reviewing convenience.
Cindy H Kao (2):
wimax/i2400m: when bootstrap fails, reinitialize the bootrom wimax/i2400m: use -EL3RST to indicate device reset instead of -ERESTARTSYS
Dirk Brandewie (4):
wimax/i2400m: Change d_printf() level for secure boot messages wimax/i2400m/sdio: Implement I2400M_RT_BUS reset type wimax/i2400m: move boot time poke table out of common driver wimax/i2400m/sdio: Add device specific poke table.
Inaky Perez-Gonzalez (15):
wimax/i2400m: introduce module parameter to disable entering power save wimax/i2400m: don't call netif_start_queue() in _tx_msg_sent() wimax/i2400m: i2400m's work queue should be initialized before RX support wimax/i2400m: i2400m_schedule_work() doesn't need i2400m->work_queue wimax/i2400m: rename misleading I2400M_PL_PAD to I2400M_PL_ALIGN wimax/i2400m: fix panic/warnings caused by missed check on empty TX message wimax/i2400m: fix panic due to missed corner cases on tail_room calculation wimax/i2400m: don't reset device on i2400m_dev_shutdown() wimax/i2400m: fix oops when the TX FIFO fills up due to a missing check wimax/i2400m: if a device reboot happens during probe, handle it wimax/i2400m: Allow bus-specific driver to specify retry count wimax/i2400m: don't reset device when bootrom init retries are exceeded wimax/i2400m/sdio: Move all the RX code to a unified, IRQ based receive routine
wimax: fix warning caused by not checking retval of rfkill_set_hw_state()
wimax: fix gcc warnings in sh4 when calling BUG()
drivers/net/wimax/i2400m/control.c | 24 +++++--- drivers/net/wimax/i2400m/driver.c | 40 ++++++++---- drivers/net/wimax/i2400m/fw.c | 58 ++++++----------- drivers/net/wimax/i2400m/i2400m-sdio.h | 9 +++ drivers/net/wimax/i2400m/i2400m.h | 43 +++++++++++++ drivers/net/wimax/i2400m/op-rfkill.c | 4 +- drivers/net/wimax/i2400m/rx.c | 4 +- drivers/net/wimax/i2400m/sdio-fw.c | 109 ++++++++++++++------------------ drivers/net/wimax/i2400m/sdio-rx.c | 47 +++++++++++--- drivers/net/wimax/i2400m/sdio.c | 50 ++++++++++++--- drivers/net/wimax/i2400m/tx.c | 75 ++++++++++++++++++++-- drivers/net/wimax/i2400m/usb.c | 5 +- include/linux/wimax/i2400m.h | 2 +- net/wimax/op-rfkill.c | 3 +- 14 files changed, 320 insertions(+), 153 deletions(-)
[2.6.31 04/21] wimax/i2400m: i2400m_schedule_work() doesn't need i2400m->work_queue
By mistake, the BUG_ON() check was left in there and it will fail when called if i2400m->work_queue is still not setup.
--- drivers/net/wimax/i2400m/driver.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/net/wimax/i2400m/driver.c +0 -1
@@ -180,7 +180,6 @@ int i2400m_schedule_work(struct i2400m *i2400m,int result;struct i2400m_work *iw; -BUG_ON (i2400m->work_queue ==NULL ); result = -ENOMEM ; iw =kzalloc (sizeof (*iw), gfp_flags);if (iw ==NULL )
Signature · 1 line
1.6.2.3
[2.6.31 01/21] wimax/i2400m: introduce module parameter to disable entering power save
In reply to Inaky Perez-GonzalezThe i2400m driver waits for the device to report being ready for entering power save before asking it to do so. This module parameter allows control of said operation; if disabled, the driver won't ask the device to enter power save mode.
This is useful in setups where power saving is not so important or when the overhead imposed by network reentry after power save is not acceptable; by combining this with parameter 'idle_mode_disabled', the driver will always maintain both the connection and the device in active state.
--- drivers/net/wimax/i2400m/control.c | 11 +++++++++-- drivers/net/wimax/i2400m/driver.c | 8 ++++++++ drivers/net/wimax/i2400m/i2400m.h | 1 + 3 files changed, 18 insertions(+), 2 deletions(-)
drivers/net/wimax/i2400m/control.c +9 -2
@@ -505,8 +505,15 @@ void i2400m_report_hook(struct i2400m *i2400m,* it. */ case I2400M_MT_REPORT_POWERSAVE_READY :/* zzzzz */ if (l3l4_hdr->status ==cpu_to_le16 (I2400M_MS_DONE_OK )) { -d_printf (1 , dev,"ready for powersave, requesting\n" ); -i2400m_cmd_enter_powersave (i2400m); +if (i2400m_power_save_disabled) +d_printf (1 , dev,"ready for powersave, " +"not requesting (disabled by module " +"parameter)\n" ); +else { +d_printf (1 , dev,"ready for powersave, " +"requesting\n" ); +i2400m_cmd_enter_powersave (i2400m); + } }break ; };
drivers/net/wimax/i2400m/driver.c +8 -0
@@ -82,6 +82,14 @@ module_param_named(rx_reorder_disabled, i2400m_rx_reorder_disabled, int, 0644);MODULE_PARM_DESC (rx_reorder_disabled,"If true, RX reordering will be disabled." ); +int i2400m_power_save_disabled;/* 0 (power saving enabled) by default */ +module_param_named (power_save_disabled, i2400m_power_save_disabled, int,0644 ); +MODULE_PARM_DESC (power_save_disabled, +"If true, the driver will not tell the device to enter " +"power saving mode when it reports it is ready for it. " +"False by default (so the device is told to do power " +"saving)." ); +/** * i2400m_queue_work - schedule work on a i2400m's queue *
drivers/net/wimax/i2400m/i2400m.h +1 -0
@@ -709,6 +709,7 @@ static const __le32 i2400m_SBOOT_BARKER[4] = { cpu_to_le32(I2400M_SBOOT_BARKER) }; +extern int i2400m_power_save_disabled;/* * Utility functions
Signature · 1 line
1.6.2.3
[2.6.31 02/21] wimax/i2400m: don't call netif_start_queue() in _tx_msg_sent()
In reply to Inaky Perez-GonzalezReported and fixed by Cindy H Kao.
When the device is stopped __i2400m_dev_stop() stops the network queue.
However, when this is done in the middle of heavy network operation, when the bus-specific subdriver is still wrapping up and it reports a sent TX transaction with _tx_msg_sent() right after the device was stopped, the queue was being started again, which was causing a stream of oopsen and finally a panic.
In any case, said call has no place there. It's a left over from an early implementation that was discarded later on.
--- drivers/net/wimax/i2400m/tx.c | 1 - 1 files changed, 0 insertions(+), 1 deletions(-)
drivers/net/wimax/i2400m/tx.c +0 -1
@@ -773,7 +773,6 @@ void i2400m_tx_msg_sent(struct i2400m *i2400m) n = i2400m->tx_out /I2400M_TX_BUF_SIZE ; i2400m->tx_out %=I2400M_TX_BUF_SIZE ; i2400m->tx_in -= n *I2400M_TX_BUF_SIZE ; -netif_start_queue (i2400m->wimax_dev.net_dev);spin_unlock_irqrestore (&i2400m->tx_lock, flags);d_fnend (3 , dev,"(i2400m %p) = void\n" , i2400m); }
Signature · 1 line
1.6.2.3
[2.6.31 07/21] wimax/i2400m: rename misleading I2400M_PL_PAD to I2400M_PL_ALIGN
In reply to Inaky Perez-GonzalezThe constant is being use as an alignment factor, not as a padding factor; made reading/reviewing the code quite confusing.
--- drivers/net/wimax/i2400m/fw.c | 2 +- drivers/net/wimax/i2400m/rx.c | 4 ++-- drivers/net/wimax/i2400m/tx.c | 4 ++-- include/linux/wimax/i2400m.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-)
drivers/net/wimax/i2400m/fw.c +1 -1
@@ -397,7 +397,7 @@ static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk, unsigned int direct, unsigned int do_csum) { int ret; -size_t chunk_len =ALIGN (__chunk_len,I2400M_PL_PAD ); +size_t chunk_len =ALIGN (__chunk_len,I2400M_PL_ALIGN );struct device *dev =i2400m_dev (i2400m); struct { struct i2400m_bootrom_header cmd;
drivers/net/wimax/i2400m/rx.c +2 -2
@@ -1148,7 +1148,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) num_pls =le16_to_cpu (msg_hdr->num_pls); pl_itr =sizeof (*msg_hdr) +/* Check payload descriptor(s) */ num_pls *sizeof (msg_hdr->pld[0 ]); - pl_itr =ALIGN (pl_itr,I2400M_PL_PAD ); + pl_itr =ALIGN (pl_itr,I2400M_PL_ALIGN );if (pl_itr > skb->len) {/* got all the payload descriptors? */ dev_err(dev, "RX: HW BUG? message too short (%u bytes) for " "%u payload descriptors (%zu each, total %zu)\n",
@@ -1166,7 +1166,7 @@ int i2400m_rx(struct i2400m *i2400m, struct sk_buff *skb) single_last = num_pls ==1 || i == num_pls -1 ;i2400m_rx_payload (i2400m, skb, single_last, &msg_hdr->pld[i], skb->data + pl_itr); - pl_itr +=ALIGN (pl_size,I2400M_PL_PAD ); + pl_itr +=ALIGN (pl_size,I2400M_PL_ALIGN );cond_resched ();/* Don't monopolize */ }kfree_skb (skb);
drivers/net/wimax/i2400m/tx.c +2 -2
@@ -491,7 +491,7 @@ void i2400m_tx_close(struct i2400m *i2400m)*/ hdr_size =sizeof (*tx_msg) +le16_to_cpu (tx_msg->num_pls) *sizeof (tx_msg->pld[0 ]); - hdr_size =ALIGN (hdr_size,I2400M_PL_PAD ); + hdr_size =ALIGN (hdr_size,I2400M_PL_ALIGN ); tx_msg->offset =I2400M_TX_PLD_SIZE - hdr_size; tx_msg_moved = (void *) tx_msg + tx_msg->offset;memmove (tx_msg_moved, tx_msg, hdr_size);
@@ -574,7 +574,7 @@ int i2400m_tx(struct i2400m *i2400m, const void *buf, size_t buf_len,d_fnstart (3 , dev,"(i2400m %p skb %p [%zu bytes] pt %u)\n" , i2400m, buf, buf_len, pl_type); - padded_len =ALIGN (buf_len,I2400M_PL_PAD ); + padded_len =ALIGN (buf_len,I2400M_PL_ALIGN );d_printf (5 , dev,"padded_len %zd buf_len %zd\n" , padded_len, buf_len);/* If there is no current TX message, create one; if the * current one is out of payload slots or we have a singleton,
include/linux/wimax/i2400m.h +1 -1
@@ -266,7 +266,7 @@ enum i2400m_ro_type {/* Misc constants */ enum { -I2400M_PL_PAD =16 ,/* Payload data size alignment */ +I2400M_PL_ALIGN =16 ,/* Payload data size alignment */ I2400M_PL_SIZE_MAX =0x3EFF ,I2400M_MAX_PLS_IN_MSG =60 ,/* protocol barkers: sync sequences; for notifications they
Signature · 1 line
1.6.2.3
[2.6.31 10/21] wimax/i2400m: don't reset device on i2400m_dev_shutdown()
In reply to Inaky Perez-Gonzalezi2400m_dev_shutdown() tried to reset the device to put it in a known state before shutting down.
But that turned out to be pointless. We reach this case in two paths:
1 - when the device resets, to clean up state
2 - when the driver is unloaded, for the same
however, in both cases it is pointless; in (1) the device is already reset, why do it again? in (2) we can't -- the USB stack, for example, doesn't allow communicating with the device when the driver is being unbound and if the device is disconnected, the device is gone already.
So just remove it. Leave the function as a placeholder for future cleanups that will be done from data allocated by the driver during device operation.
--- drivers/net/wimax/i2400m/control.c | 10 +++++----- 1 files changed, 5 insertions(+), 5 deletions(-)
drivers/net/wimax/i2400m/control.c +5 -5
@@ -1396,16 +1396,16 @@ error:* * @i2400m: device descriptor * -* Gracefully stops the device, moving it to the lowest power -* consumption state possible. +* Release resources acquired during the running of the device; in +* theory, should also tell the device to go to sleep, switch off the +* radio, all that, but at this point, in most cases (driver +* disconnection, reset handling) we can't even talk to the device. */ void i2400m_dev_shutdown (struct i2400m *i2400m) { -int result = -ENODEV ;struct device *dev =i2400m_dev (i2400m);d_fnstart (3 , dev,"(i2400m %p)\n" , i2400m); - result = i2400m->bus_reset (i2400m,I2400M_RT_WARM ); -d_fnend (3 , dev,"(i2400m %p) = void [%d]\n" , i2400m, result); +d_fnend (3 , dev,"(i2400m %p) = void\n" , i2400m);return ; }
Signature · 1 line
1.6.2.3
[2.6.31 08/21] wimax/i2400m: fix panic/warnings caused by missed check on empty TX message
In reply to Inaky Perez-GonzalezIn some situations, when a new TX message header is started, there might be no space for data payloads. In this case the message is left with zero payloads and the i2400m_tx_close() function has just to mark it as "to skip". If it tries to go ahead it will overwrite things because there is no space to add padding as defined by the bus-specific layer. This can cause buffer overruns and in some stress cases, panics.
Found and diagnosed by Cindy H. Kao.
--- drivers/net/wimax/i2400m/tx.c | 10 +++++++++- 1 files changed, 9 insertions(+), 1 deletions(-)
drivers/net/wimax/i2400m/tx.c +9 -1
@@ -474,10 +474,18 @@ void i2400m_tx_close(struct i2400m *i2400m)struct i2400m_msg_hdr *tx_msg_moved;size_t aligned_size, padding, hdr_size;void *pad_buf; +unsigned num_pls;if (tx_msg->size &I2400M_TX_SKIP )/* a skipper? nothing to do */ goto out; - + num_pls =le16_to_cpu (tx_msg->num_pls); +/* We can get this situation when a new message was started +* and there was no space to add payloads before hitting the +tail (and taking padding into consideration). */ +if (num_pls ==0 ) { + tx_msg->size |=I2400M_TX_SKIP ; + goto out; + }/* Relocate the message header * * Find the current header size, align it to 16 and if we need
Signature · 1 line
1.6.2.3
[2.6.31 13/21] wimax/i2400m: Allow bus-specific driver to specify retry count
In reply to Inaky Perez-GonzalezThe code that sets up the i2400m (firmware load and general driver setup after it) includes a couple of retry loops.
The SDIO device sometimes can get in more complicated corners than the USB one (due to its interaction with other SDIO functions), that require trying a few more times.
To solve that, without having a failing USB device taking longer to be considered dead, allow the retry counts to be specified by the bus-specific driver, which the general driver takes as a parameter.
--- drivers/net/wimax/i2400m/driver.c | 2 +- drivers/net/wimax/i2400m/fw.c | 2 +- drivers/net/wimax/i2400m/i2400m.h | 14 ++++++++++++++ drivers/net/wimax/i2400m/sdio.c | 3 +++ drivers/net/wimax/i2400m/usb.c | 1 + 5 files changed, 20 insertions(+), 2 deletions(-)
drivers/net/wimax/i2400m/driver.c +1 -1
@@ -399,7 +399,7 @@ int __i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri flags)struct wimax_dev *wimax_dev = &i2400m->wimax_dev;struct net_device *net_dev = wimax_dev->net_dev;struct device *dev =i2400m_dev (i2400m); -int times =3 ; +int times = i2400m->bus_bm_retries;d_fnstart (3 , dev,"(i2400m %p)\n" , i2400m); retry:
drivers/net/wimax/i2400m/fw.c +1 -1
@@ -980,7 +980,7 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf, {int ret =0 ;struct device *dev =i2400m_dev (i2400m); -int count =I2400M_BOOT_RETRIES ; +int count = i2400m->bus_bm_retries;d_fnstart (5 , dev,"(i2400m %p bcf %p size %zu)\n" , i2400m, bcf, bcf_size);
drivers/net/wimax/i2400m/i2400m.h +14 -0
@@ -150,6 +150,7 @@enum {/* Firmware uploading */ I2400M_BOOT_RETRIES =3 , +I3200_BOOT_RETRIES =3 ,/* Size of the Boot Mode Command buffer */ I2400M_BM_CMD_BUF_SIZE =16 *1024 ,I2400M_BM_ACK_BUF_SIZE =256 ,
@@ -224,6 +225,17 @@ struct i2400m_roq;* process, so it cannot rely on common infrastructure being laid * out. * +* @bus_bm_retries: [fill] How many times shall a firmware upload / +* device initialization be retried? Different models of the same +* device might need different values, hence it is set by the +* bus-specific driver. Note this value is used in two places, +* i2400m_fw_dnload() and __i2400m_dev_start(); they won't become +* multiplicative (__i2400m_dev_start() calling N times +* i2400m_fw_dnload() and this trying N times to download the +* firmware), as if __i2400m_dev_start() only retries if the +* firmware crashed while initializing the device (not in a +* general case). +* * @bus_bm_cmd_send: [fill] Function called to send a boot-mode * command. Flags are defined in 'enum i2400m_bm_cmd_flags'. This * is synchronous and has to return 0 if ok or < 0 errno code in
@@ -399,6 +411,8 @@ struct i2400m {size_t bus_tx_block_size;size_t bus_pl_size_max; +unsigned bus_bm_retries; +int (*bus_dev_start)(struct i2400m *);void (*bus_dev_stop)(struct i2400m *);void (*bus_tx_kick)(struct i2400m *);
drivers/net/wimax/i2400m/sdio.c +3 -0
@@ -418,6 +418,9 @@ int i2400ms_probe(struct sdio_func *func, i2400m->bus_dev_stop = i2400ms_bus_dev_stop; i2400m->bus_tx_kick = i2400ms_bus_tx_kick; i2400m->bus_reset = i2400ms_bus_reset; +/* The iwmc3200-wimax sometimes requires the driver to try +* hard when we paint it into a corner. */ + i2400m->bus_bm_retries =I3200_BOOT_RETRIES ; i2400m->bus_bm_cmd_send = i2400ms_bus_bm_cmd_send; i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; i2400m->bus_fw_names = i2400ms_bus_fw_names;
drivers/net/wimax/i2400m/usb.c +1 -0
@@ -399,6 +399,7 @@ int i2400mu_probe(struct usb_interface *iface, i2400m->bus_dev_stop = i2400mu_bus_dev_stop; i2400m->bus_tx_kick = i2400mu_bus_tx_kick; i2400m->bus_reset = i2400mu_bus_reset; + i2400m->bus_bm_retries =I2400M_BOOT_RETRIES ; i2400m->bus_bm_cmd_send = i2400mu_bus_bm_cmd_send; i2400m->bus_bm_wait_for_ack = i2400mu_bus_bm_wait_for_ack; i2400m->bus_fw_names = i2400mu_bus_fw_names;
Signature · 1 line
1.6.2.3
[2.6.31 03/21] wimax/i2400m: i2400m's work queue should be initialized before RX support
In reply to Inaky Perez-GonzalezRX support is the only user of the work-queue, to process reports/notifications from the device. Thus, it needs the work queue to be initialized first.
--- drivers/net/wimax/i2400m/driver.c | 21 ++++++++++++++------- 1 files changed, 14 insertions(+), 7 deletions(-)
drivers/net/wimax/i2400m/driver.c +14 -7
@@ -385,6 +385,11 @@ error:* Uploads firmware and brings up all the resources needed to be able * to communicate with the device. * +* The workqueue has to be setup early, at least before RX handling +* (it's only real user for now) so it can process reports as they +* arrive. We also want to destroy it if we retry, to make sure it is +* flushed...easier like this. +* * TX needs to be setup before the bus-specific code (otherwise on * shutdown, the bus-tx code could try to access it). */
@@ -410,15 +415,15 @@ retry: result =i2400m_rx_setup (i2400m);if (result <0 ) goto error_rx_setup; - result = i2400m->bus_dev_start (i2400m); -if (result <0 ) - goto error_bus_dev_start; i2400m->work_queue =create_singlethread_workqueue (wimax_dev->name);if (i2400m->work_queue ==NULL ) { result = -ENOMEM ;dev_err (dev,"cannot create workqueue\n" ); goto error_create_workqueue; } + result = i2400m->bus_dev_start (i2400m); +if (result <0 ) + goto error_bus_dev_start; result =i2400m_firmware_check (i2400m);/* fw versions ok? */ if (result <0 ) goto error_fw_check;
@@ -440,10 +445,10 @@ retry: error_dev_initialize: error_check_mac_addr: error_fw_check: -destroy_workqueue (i2400m->work_queue); -error_create_workqueue: i2400m->bus_dev_stop (i2400m); error_bus_dev_start: +destroy_workqueue (i2400m->work_queue); +error_create_workqueue:i2400m_rx_release (i2400m); error_rx_setup:i2400m_tx_release (i2400m);
@@ -479,7 +484,9 @@ int i2400m_dev_start(struct i2400m *i2400m, enum i2400m_bri bm_flags)* * Returns: 0 if ok, < 0 errno code on error. * -* Releases all the resources allocated to communicate with the device. +* Releases all the resources allocated to communicate with the +* device. Note we cannot destroy the workqueue earlier as until RX is +* fully destroyed, it could still try to schedule jobs. */ static void __i2400m_dev_stop (struct i2400m *i2400m)
@@ -491,8 +498,8 @@ void __i2400m_dev_stop(struct i2400m *i2400m)wimax_state_change (wimax_dev, __WIMAX_ST_QUIESCING);i2400m_dev_shutdown (i2400m); i2400m->ready =0 ; -destroy_workqueue (i2400m->work_queue); i2400m->bus_dev_stop (i2400m); +destroy_workqueue (i2400m->work_queue);i2400m_rx_release (i2400m);i2400m_tx_release (i2400m);wimax_state_change (wimax_dev,WIMAX_ST_DOWN );
Signature · 1 line
1.6.2.3
[2.6.31 06/21] wimax/i2400m/sdio: Implement I2400M_RT_BUS reset type
In reply to Inaky Perez-GonzalezFrom: Dirk Brandewie <[email protected]>
This reset type causes the WiMAX function to be disabled and re-enabled, which will force the WiMAX device to reset and enter boot mode.
--- drivers/net/wimax/i2400m/i2400m-sdio.h | 2 ++ drivers/net/wimax/i2400m/sdio.c | 20 +++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-)
drivers/net/wimax/i2400m/i2400m-sdio.h +2 -0
@@ -78,6 +78,8 @@ enum {/* The number of ticks to wait for the device to signal that * it is ready */ I2400MS_INIT_SLEEP_INTERVAL =10 , +/* How long to wait for the device to settle after reset */ + I2400MS_SETTLE_TIME = 40, };
drivers/net/wimax/i2400m/sdio.c +17 -3
@@ -255,7 +255,7 @@ error_kzalloc:static int i2400ms_bus_reset (struct i2400m *i2400m,enum i2400m_reset_type rt) { -int result; +int result =0 ;struct i2400ms *i2400ms = container_of(i2400m, struct i2400ms, i2400m);struct device *dev =i2400m_dev (i2400m);
@@ -280,8 +280,22 @@ int i2400ms_bus_reset(struct i2400m *i2400m, enum i2400m_reset_type rt) sizeof(i2400m_COLD_BOOT_BARKER)); else if (rt == I2400M_RT_BUS) { do_bus_reset: -dev_err (dev,"FIXME: SDIO bus reset not implemented\n" ); - result = rt ==I2400M_RT_WARM ? -ENODEV : -ENOSYS ; +/* call netif_tx_disable() before sending IOE disable, +* so that all the tx from network layer are stopped +* while IOE is being reset. Make sure it is called +* only after register_netdev() was issued. +*/ +if (i2400m->wimax_dev.net_dev->reg_state ==NETREG_REGISTERED ) +netif_tx_disable (i2400m->wimax_dev.net_dev); + +sdio_claim_host (i2400ms->func); +sdio_disable_func (i2400ms->func); +sdio_release_host (i2400ms->func); + +/* Wait for the device to settle */ +msleep (40 ); + + result =i2400ms_enable_function (i2400ms->func); } elseBUG ();if (result <0 && rt !=I2400M_RT_BUS ) {
Signature · 1 line
1.6.2.3
[2.6.31 11/21] wimax/i2400m: fix oops when the TX FIFO fills up due to a missing check
In reply to Inaky Perez-GonzalezWhen the TX FIFO filled up and i2400m_tx_new() failed to allocate a new TX message header, a missing check for said condition was causing a kernel oops when trying to dereference a NULL i2400m->tx_msg pointer.
Found and diagnosed by Cindy H. Kao.
--- drivers/net/wimax/i2400m/tx.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
drivers/net/wimax/i2400m/tx.c +2 -0
@@ -653,6 +653,8 @@ try_new:i2400m_tx_close (i2400m);i2400m_tx_new (i2400m); } +if (i2400m->tx_msg ==NULL ) + goto error_tx_new;if (i2400m->tx_msg->size + padded_len >I2400M_TX_BUF_SIZE /2 ) {d_printf (2 , dev,"TX: message too big, going new\n" );i2400m_tx_close (i2400m);
Signature · 1 line
1.6.2.3
[2.6.31 09/21] wimax/i2400m: fix panic due to missed corner cases on tail_room calculation
In reply to Inaky Perez-Gonzalezi2400m_tx_skip_tail() needs to handle the special case of being called when the tail room that is left over in the FIFO is zero.
This happens when a TX message header was opened at the very end of the FIFO (without payloads). The i2400m_tx_close() code already marked said TX message (header) to be skipped and this function should be doing nothing.
It is called anyway because it is part of a common "corner case" path handling which takes care of more cases than only this one.
The tail room computation was also improved to take care of the case when tx_in is at the end of the buffer boundary; tail_room has to be modded (%) to the buffer size. To do that in a single well-documented place, __i2400m_tx_tail_room() is introduced and used.
Treat i2400m->tx_in == 0 as a corner case and handle it accordingly.
Found and diagnosed by Cindy H. Kao.
--- drivers/net/wimax/i2400m/tx.c | 58 +++++++++++++++++++++++++++++++++++++++- 1 files changed, 56 insertions(+), 2 deletions(-)
drivers/net/wimax/i2400m/tx.c +56 -2
@@ -278,6 +278,48 @@ enum {#define TAIL_FULL ((void *)~(unsigned long)NULL)/* +* Calculate how much tail room is available +* +* Note the trick here. This path is ONLY caleed for Case A (see +* i2400m_tx_fifo_push() below), where we have: +* +* Case A +* N ___________ +* | tail room | +* | | +* |<- IN ->| +* | | +* | data | +* | | +* |<- OUT ->| +* | | +* | head room | +* 0 ----------- +* +* When calculating the tail_room, tx_in might get to be zero if +* i2400m->tx_in is right at the end of the buffer (really full +* buffer) if there is no head room. In this case, tail_room would be +* I2400M_TX_BUF_SIZE, although it is actually zero. Hence the final +* mod (%) operation. However, when doing this kind of optimization, +* i2400m->tx_in being zero would fail, so we treat is an a special +* case. +*/ +static inline +size_t __i2400m_tx_tail_room (struct i2400m *i2400m) +{ +size_t tail_room; +size_t tx_in; + +if (unlikely (i2400m->tx_in) ==0 ) +return I2400M_TX_BUF_SIZE ; + tx_in = i2400m->tx_in %I2400M_TX_BUF_SIZE ; + tail_room =I2400M_TX_BUF_SIZE - tx_in; + tail_room %=I2400M_TX_BUF_SIZE ; +return tail_room; +} + + +/* * Allocate @size bytes in the TX fifo, return a pointer to it * * @i2400m: device descriptor
@@ -338,7 +380,7 @@ void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size, size_t padding)return NULL ; }/* Is there space at the tail? */ - tail_room =I2400M_TX_BUF_SIZE - i2400m->tx_in %I2400M_TX_BUF_SIZE ; + tail_room =__i2400m_tx_tail_room (i2400m);if (tail_room < needed_size) {if (i2400m->tx_out %I2400M_TX_BUF_SIZE < i2400m->tx_in %I2400M_TX_BUF_SIZE ) {
@@ -367,17 +409,29 @@ void *i2400m_tx_fifo_push(struct i2400m *i2400m, size_t size, size_t padding)* (I2400M_PL_PAD for the payloads, I2400M_TX_PLD_SIZE for the * header). * +* Tail room can get to be zero if a message was opened when there was +* space only for a header. _tx_close() will mark it as to-skip (as it +* will have no payloads) and there will be no more space to flush, so +* nothing has to be done here. This is probably cheaper than ensuring +* in _tx_new() that there is some space for payloads...as we could +* always possibly hit the same problem if the payload wouldn't fit. +* * Note: * * Assumes i2400m->tx_lock is taken, and we use that as a barrier +* +* This path is only taken for Case A FIFO situations [see +* i2400m_tx_fifo_push()] */ static void i2400m_tx_skip_tail (struct i2400m *i2400m) {struct device *dev =i2400m_dev (i2400m);size_t tx_in = i2400m->tx_in %I2400M_TX_BUF_SIZE ; -size_t tail_room =I2400M_TX_BUF_SIZE - tx_in; +size_t tail_room =__i2400m_tx_tail_room (i2400m);struct i2400m_msg_hdr *msg = i2400m->tx_buf + tx_in; +if (unlikely (tail_room ==0 )) +return ;BUG_ON (tail_room <sizeof (*msg)); msg->size = tail_room |I2400M_TX_SKIP ; d_printf(2, dev, "skip tail: skipping %zu bytes @%zu\n",
Signature · 1 line
1.6.2.3
[2.6.31 16/21] wimax/i2400m: don't reset device when bootrom init retries are exceeded
In reply to Inaky Perez-GonzalezWhen i2400m_bootrom_init() fails to put the device into a state of being ready to accept firmware, the driver was currently trying to reset it if it failed to do so. This is not too useful; as part of trying to put the device in the right state a few resets have already been tried.
At this point, things are probably fried out and an extra reset might do more harm than good (for example causing reseting of other functions in the same composite device).
So it is left up to the callers to determine the error path to take (at the end this is always i2400m_setup(), who depending on how many retries are left, might give up on the device).
Quoted 1 line
From a fix by Cindy H. Kao.
--- drivers/net/wimax/i2400m/fw.c | 3 +-- 1 files changed, 1 insertions(+), 2 deletions(-)
drivers/net/wimax/i2400m/fw.c +1 -2
@@ -696,8 +696,7 @@ error_dev_gone:return result; error_timeout: -dev_err (dev,"Timed out waiting for reboot ack, resetting\n" ); - i2400m->bus_reset (i2400m,I2400M_RT_BUS ); +dev_err (dev,"Timed out waiting for reboot ack\n" ); result = -ETIMEDOUT ; goto exit_timeout; }
Signature · 1 line
1.6.2.3
[2.6.31 12/21] wimax/i2400m: if a device reboot happens during probe, handle it
In reply to Inaky Perez-GonzalezWhen a device reboot happens when we are under probe, with init_mutex taken, make sure we can recover. Have dev_reset_handle set boot mode and i2400m_msg_to_dev() will see it and fail gracefully instead of timing out.
Found and diagnosed by Cindy H. Kao.
--- drivers/net/wimax/i2400m/control.c | 1 + drivers/net/wimax/i2400m/driver.c | 2 ++ drivers/net/wimax/i2400m/fw.c | 2 ++ 3 files changed, 5 insertions(+), 0 deletions(-)
drivers/net/wimax/i2400m/control.c +1 -0
@@ -695,6 +695,7 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m,d_fnstart (3 , dev,"(i2400m %p buf %p len %zu)\n" , i2400m, buf, buf_len); +rmb ();/* Make sure we see what i2400m_dev_reset_handle() */ if (i2400m->boot_mode)return ERR_PTR (-ENODEV );
drivers/net/wimax/i2400m/driver.c +2 -0
@@ -610,6 +610,8 @@ out:*/ int i2400m_dev_reset_handle (struct i2400m *i2400m) { + i2400m->boot_mode =1 ; +wmb ();/* Make sure i2400m_msg_to_dev() sees boot_mode */ return i2400m_schedule_work (i2400m, __i2400m_dev_reset_handle,GFP_ATOMIC ); }
drivers/net/wimax/i2400m/fw.c +2 -0
@@ -985,6 +985,7 @@ int i2400m_fw_dnload(struct i2400m *i2400m, const struct i2400m_bcf_hdr *bcf,d_fnstart (5 , dev,"(i2400m %p bcf %p size %zu)\n" , i2400m, bcf, bcf_size); i2400m->boot_mode =1 ; +wmb ();/* Make sure other readers see it */ hw_reboot:if (count-- ==0 ) { ret = -ERESTARTSYS ;
@@ -1033,6 +1034,7 @@ hw_reboot:d_printf (2 , dev,"fw %s successfully uploaded\n" , i2400m->fw_name); i2400m->boot_mode =0 ; +wmb ();/* Make sure i2400m_msg_to_dev() sees boot_mode */ error_dnload_finalize: error_dnload_bcf: error_dnload_init:
Signature · 1 line
1.6.2.3
[2.6.31 15/21] wimax/i2400m/sdio: Add device specific poke table.
In reply to Inaky Perez-GonzalezFrom: Dirk Brandewie <[email protected]>
Add a poke table for the SDIO device (as it is different than USB).
--- drivers/net/wimax/i2400m/sdio.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-)
drivers/net/wimax/i2400m/sdio.c +9 -0
@@ -78,6 +78,14 @@ static const char *i2400ms_bus_fw_names[] = { }; +static const struct i2400m_poke_table i2400ms_pokes[] = { +I2400M_FW_POKE (0x6BE260 ,0x00000088 ), +I2400M_FW_POKE (0x080550 ,0x00000005 ), +I2400M_FW_POKE (0xAE0000 ,0x00000000 ), +I2400M_FW_POKE (0x000000 ,0x00000000 ),/* MUST be 0 terminated or bad +* things will happen */ +}; +/* * Enable the SDIO function *
@@ -425,6 +433,7 @@ int i2400ms_probe(struct sdio_func *func, i2400m->bus_bm_wait_for_ack = i2400ms_bus_bm_wait_for_ack; i2400m->bus_fw_names = i2400ms_bus_fw_names; i2400m->bus_bm_mac_addr_impaired =1 ; + i2400m->bus_bm_pokes_table = &i2400ms_pokes[0 ];sdio_claim_host (func); result =sdio_set_block_size (func,I2400MS_BLK_SIZE );
Signature · 1 line
1.6.2.3
[2.6.31 20/21] wimax: fix warning caused by not checking retval of rfkill_set_hw_state()
In reply to Inaky Perez-GonzalezCaused by an API update. The return value can be safely ignored, as there is notthing we can do with it.
--- net/wimax/op-rfkill.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
net/wimax/op-rfkill.c +2 -1
@@ -113,7 +113,8 @@ void wimax_report_rfkill_hw(struct wimax_dev *wimax_dev,else wimax_state =WIMAX_ST_RADIO_OFF ; -rfkill_set_hw_state (wimax_dev->rfkill, state ==WIMAX_RF_OFF ); + result =rfkill_set_hw_state (wimax_dev->rfkill, + state ==WIMAX_RF_OFF );__wimax_state_change (wimax_dev, wimax_state); }
Signature · 1 line
1.6.2.3
[2.6.31 05/21] wimax/i2400m: Change d_printf() level for secure boot messages
In reply to Inaky Perez-GonzalezFrom: Dirk Brandewie <[email protected]>
Changing debug level of print out to support validation engineers getting the messages they need.
--- drivers/net/wimax/i2400m/fw.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/wimax/i2400m/fw.c +2 -2
@@ -532,14 +532,14 @@ int i2400m_dnload_finalize(struct i2400m *i2400m, cmd = (void *) bcf + offset;if (i2400m->sboot ==0 ) {struct i2400m_bootrom_header jump_ack; -d_printf (3 , dev,"unsecure boot, jumping to 0x%08x\n" , +d_printf (1 , dev,"unsecure boot, jumping to 0x%08x\n" ,le32_to_cpu (cmd->target_addr));i2400m_brh_set_opcode (cmd,I2400M_BRH_JUMP ); cmd->data_size =0 ; ret =i2400m_bm_cmd (i2400m, cmd,sizeof (*cmd), &jump_ack,sizeof (jump_ack),0 ); }else { -d_printf (3 , dev,"secure boot, jumping to 0x%08x\n" , +d_printf (1 , dev,"secure boot, jumping to 0x%08x\n" ,le32_to_cpu (cmd->target_addr)); cmd_buf = i2400m->bm_cmd_buf;memcpy (&cmd_buf->cmd, cmd,sizeof (*cmd));
Signature · 1 line
1.6.2.3
[2.6.31 19/21] wimax/i2400m: use -EL3RST to indicate device reset instead of -ERESTARTSYS
In reply to Inaky Perez-GonzalezFrom: Cindy H Kao <[email protected]>
When the i2400m device resets, the driver code will force some functions to return a -ERESTARTSYS error code, which can is used by the caller to determine which recovery actions to take.
However, in certain situations the only thing that can be done is to bubble up said error code to user space, for handling.
However, -ERESTARSYS was a poor choice, as it is supposed to be used by the kernel only.
As such, replace -ERESTARTSYS with -EL3RST; as well, in i2400m_msg_to_dev(), when the device is in boot mode (following a recent reset), return -EL3RST instead of -ENODEV (meaning the device is in bootrom mode after a reset, not that the device was disconnected, and thus, normal commands cannot be executed).
--- drivers/net/wimax/i2400m/control.c | 2 +- drivers/net/wimax/i2400m/driver.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
drivers/net/wimax/i2400m/control.c +1 -1
@@ -697,7 +697,7 @@ struct sk_buff *i2400m_msg_to_dev(struct i2400m *i2400m,rmb ();/* Make sure we see what i2400m_dev_reset_handle() */ if (i2400m->boot_mode) -return ERR_PTR (-ENODEV ); +return ERR_PTR (-EL3RST ); msg_l3l4_hdr = buf;/* Check msg & payload consistency */
drivers/net/wimax/i2400m/driver.c +2 -2
@@ -453,7 +453,7 @@ error_rx_setup:i2400m_tx_release (i2400m); error_tx_setup: error_bootstrap: -if (result == -ERESTARTSYS && times-- >0 ) { +if (result == -EL3RST && times-- >0 ) { flags =I2400M_BRI_SOFT |I2400M_BRI_MAC_REINIT ; goto retry; }
@@ -560,7 +560,7 @@ void __i2400m_dev_reset_handle(struct work_struct *ws)* i2400m_dev_stop() [we are shutting down anyway, so * ignore it] or we are resetting somewhere else. */ dev_err (dev,"device rebooted\n" ); -i2400m_msg_to_dev_cancel_wait (i2400m, -ERESTARTSYS ); +i2400m_msg_to_dev_cancel_wait (i2400m, -EL3RST );complete (&i2400m->msg_completion); goto out; }
Signature · 1 line
1.6.2.3
[2.6.31 18/21] wimax/i2400m: when bootstrap fails, reinitialize the bootrom
In reply to Inaky Perez-GonzalezFrom: Cindy H Kao <[email protected]>
When a device reset happens during firmware load [in i2400m_dev_bootstrap()], __i2400m_dev_start() will retry a number of times. However, for those retries to be able to accomplish anything, the device's bootrom has to be reinitialized.
Thus, on the retry path, pass the I2400M_MAC_REINIT to the firmware load code.
--- drivers/net/wimax/i2400m/driver.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
drivers/net/wimax/i2400m/driver.c +1 -1
@@ -454,7 +454,7 @@ error_rx_setup: error_tx_setup: error_bootstrap:if (result == -ERESTARTSYS && times-- >0 ) { - flags =I2400M_BRI_SOFT ; + flags =I2400M_BRI_SOFT |I2400M_BRI_MAC_REINIT ; goto retry; } d_fnend(3, dev, "(net_dev %p [i2400m %p]) = %d\n",
Signature · 1 line
1.6.2.3
[2.6.31 17/21] wimax/i2400m/sdio: Move all the RX code to a unified, IRQ based receive routine
In reply to Inaky Perez-GonzalezThe current SDIO code was working in polling mode for boot-mode (firmware load) mode. This was causing issues on some hardware.
Moved all the RX code to use a unified IRQ handler that based on the type of data the device is sending can discriminate and decide which is the right destination.
As well, all the reads from the device are made to be at least the block size (256); the driver will ignore the rest when not needed.
--- drivers/net/wimax/i2400m/i2400m-sdio.h | 7 ++ drivers/net/wimax/i2400m/sdio-fw.c | 109 ++++++++++++++------------------ drivers/net/wimax/i2400m/sdio-rx.c | 47 +++++++++++--- drivers/net/wimax/i2400m/sdio.c | 18 +++-- 4 files changed, 101 insertions(+), 80 deletions(-)
drivers/net/wimax/i2400m/i2400m-sdio.h +7 -0
@@ -107,6 +107,10 @@ struct i2400ms {char tx_wq_name[32 ];struct dentry *debugfs_dentry; + +wait_queue_head_t bm_wfa_wq; +int bm_wait_result; +size_t bm_ack_size; };
@@ -131,4 +135,7 @@ extern ssize_t i2400ms_bus_bm_cmd_send(struct i2400m *,extern ssize_t i2400ms_bus_bm_wait_for_ack (struct i2400m *,struct i2400m_bootrom_header *,size_t ); +extern void i2400ms_bus_bm_release (struct i2400m *); +extern int i2400ms_bus_bm_setup (struct i2400m *); +#endif /* #ifndef __I2400M_SDIO_H__ */
drivers/net/wimax/i2400m/sdio-fw.c +47 -62
164 lines not on this page · raw message
drivers/net/wimax/i2400m/sdio-rx.c +36 -11
100 lines not on this page · raw message
drivers/net/wimax/i2400m/sdio.c +11 -7
@@ -156,19 +156,14 @@ int i2400ms_bus_dev_start(struct i2400m *i2400m)d_fnstart (3 , dev,"(i2400m %p)\n" , i2400m);msleep (200 ); - result =i2400ms_rx_setup (i2400ms); -if (result <0 ) - goto error_rx_setup; result =i2400ms_tx_setup (i2400ms);if (result <0 ) goto error_tx_setup;d_fnend (3 , dev,"(i2400m %p) = %d\n" , i2400m, result);return result; -i2400ms_tx_release (i2400ms); error_tx_setup: -i2400ms_rx_release (i2400ms); -error_rx_setup: +i2400ms_tx_release (i2400ms);d_fnend (3 , dev,"(i2400m %p) = void\n" , i2400m);return result; }
@@ -182,7 +177,6 @@ void i2400ms_bus_dev_stop(struct i2400m *i2400m)struct device *dev = &func->dev;d_fnstart (3 , dev,"(i2400m %p)\n" , i2400m); -i2400ms_rx_release (i2400ms);i2400ms_tx_release (i2400ms);d_fnend (3 , dev,"(i2400m %p) = void\n" , i2400m); }
@@ -296,6 +290,7 @@ do_bus_reset:if (i2400m->wimax_dev.net_dev->reg_state ==NETREG_REGISTERED )netif_tx_disable (i2400m->wimax_dev.net_dev); +i2400ms_rx_release (i2400ms);sdio_claim_host (i2400ms->func);sdio_disable_func (i2400ms->func);sdio_release_host (i2400ms->func);
@@ -304,6 +299,8 @@ do_bus_reset:msleep (40 ); result =i2400ms_enable_function (i2400ms->func); +if (result >=0 ) +i2400ms_rx_setup (i2400ms); }else BUG ();if (result <0 && rt !=I2400M_RT_BUS ) {
@@ -449,6 +446,10 @@ int i2400ms_probe(struct sdio_func *func, goto error_func_enable; } + result =i2400ms_rx_setup (i2400ms); +if (result <0 ) + goto error_rx_setup; + result =i2400m_setup (i2400m,I2400M_BRI_NO_REBOOT );if (result <0 ) {dev_err (dev,"cannot setup device: %d\n" , result);
@@ -466,6 +467,8 @@ int i2400ms_probe(struct sdio_func *func, error_debugfs_add:i2400m_release (i2400m); error_setup: +i2400ms_rx_release (i2400ms); +error_rx_setup:sdio_claim_host (func);sdio_disable_func (func);sdio_release_host (func);
@@ -488,6 +491,7 @@ void i2400ms_remove(struct sdio_func *func)d_fnstart (3 , dev,"SDIO func %p\n" , func);debugfs_remove_recursive (i2400ms->debugfs_dentry); +i2400ms_rx_release (i2400ms);i2400m_release (i2400m);sdio_set_drvdata (func,NULL );sdio_claim_host (func);
Signature · 1 line
1.6.2.3
[2.6.31 14/21] wimax/i2400m: move boot time poke table out of common driver
In reply to Inaky Perez-GonzalezFrom: Dirk Brandewie <[email protected]>
This change moves the table of "pokes" performed on the device at boot time to the bus specific portion of the driver.
Different models of the i2400m device supported by this driver require different poke tables, thus having a single table that works for all is impossible. For that, the table is moved to the bus-specific driver, who can decide which table to use based on the specifics of the device and point the generic driver to it.
--- drivers/net/wimax/i2400m/fw.c | 45 ++++++++++-------------------------- drivers/net/wimax/i2400m/i2400m.h | 28 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 32 deletions(-)
drivers/net/wimax/i2400m/fw.c +13 -32
@@ -770,40 +770,21 @@ error_read_mac:static int i2400m_dnload_init_nonsigned (struct i2400m *i2400m) { -#define POKE (a, d) { \ - .address = cpu_to_le32(a), \ - .data = cpu_to_le32(d) \ -} -static const struct { -__le32 address; -__le32 data; - } i2400m_pokes[] = { -POKE (0x081A58 ,0xA7810230 ), -POKE (0x080040 ,0x00000000 ), -POKE (0x080048 ,0x00000082 ), -POKE (0x08004C ,0x0000081F ), -POKE (0x080054 ,0x00000085 ), -POKE (0x080058 ,0x00000180 ), -POKE (0x08005C ,0x00000018 ), -POKE (0x080060 ,0x00000010 ), -POKE (0x080574 ,0x00000001 ), -POKE (0x080550 ,0x00000005 ), -POKE (0xAE0000 ,0x00000000 ), - }; -#undef POKE -unsigned i; -int ret; +unsigned i =0 ; +int ret =0 ;struct device *dev =i2400m_dev (i2400m); - -dev_warn (dev,"WARNING!!! non-signed boot UNTESTED PATH!\n" ); -d_fnstart (5 , dev,"(i2400m %p)\n" , i2400m); -for (i =0 ; i <ARRAY_SIZE (i2400m_pokes); i++) { - ret =i2400m_download_chunk (i2400m, &i2400m_pokes[i].data, -sizeof (i2400m_pokes[i].data), - i2400m_pokes[i].address,1 ,1 ); -if (ret <0 ) -break ; +if (i2400m->bus_bm_pokes_table) { +while (i2400m->bus_bm_pokes_table[i].address) { + ret =i2400m_download_chunk ( + i2400m, + &i2400m->bus_bm_pokes_table[i].data, +sizeof (i2400m->bus_bm_pokes_table[i].data), + i2400m->bus_bm_pokes_table[i].address,1 ,1 ); +if (ret <0 ) +break ; + i++; + } }d_fnend (5 , dev,"(i2400m %p) = %d\n" , i2400m, ret);return ret;
drivers/net/wimax/i2400m/i2400m.h +28 -0
@@ -156,6 +156,27 @@ enum { I2400M_BM_ACK_BUF_SIZE = 256, }; +/** +* struct i2400m_poke_table - Hardware poke table for the Intel 2400m +* +* This structure will be used to create a device specific poke table +* to put the device in a consistant state at boot time. +* +* @address: The device address to poke +* +* @data: The data value to poke to the device address +* +*/ +struct i2400m_poke_table { +__le32 address; +__le32 data; +}; + +#define I2400M_FW_POKE (a, d) { \ + .address = cpu_to_le32(a), \ + .data = cpu_to_le32(d) \ +} +/** * i2400m_reset_type - methods to reset a device
@@ -264,6 +285,12 @@ struct i2400m_roq;* address provided in boot mode is kind of broken and needs to * be re-read later on. * +* @bus_bm_pokes_table: [fill/optional] A table of device addresses +* and values that will be poked at device init time to move the +* device to the correct state for the type of boot/firmware being +* used. This table MUST be terminated with (0x000000, +* 0x00000000) or bad things will happen. +* * * @wimax_dev: WiMAX generic device for linkage into the kernel WiMAX * stack. Due to the way a net_device is allocated, we need to
@@ -424,6 +451,7 @@ struct i2400m { struct i2400m_bootrom_header *, size_t);const char **bus_fw_names; unsigned bus_bm_mac_addr_impaired:1; +const struct i2400m_poke_table *bus_bm_pokes_table;spinlock_t tx_lock;/* protect TX state */ void *tx_buf;
Signature · 1 line
1.6.2.3
[2.6.31 21/21] wimax: fix gcc warnings in sh4 when calling BUG()
In reply to Inaky Perez-GonzalezSH4's BUG() seems to confuse the compiler as it is considered to return; thus, some functions would trigger usage of uninitialized variables or non-void functions returning void.
Work around by initializing/returning.
--- drivers/net/wimax/i2400m/op-rfkill.c | 4 +++- drivers/net/wimax/i2400m/usb.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-)
drivers/net/wimax/i2400m/op-rfkill.c +3 -1
@@ -54,8 +54,10 @@ int i2400m_radio_is(struct i2400m *i2400m, enum wimax_rf_state state)/* state == WIMAX_RF_ON */ return i2400m->state !=I2400M_SS_RF_OFF && i2400m->state !=I2400M_SS_RF_SHUTDOWN ; - else + else {BUG (); +return -EINVAL ;/* shut gcc warnings on certain arches */ + } }
drivers/net/wimax/i2400m/usb.c +3 -1
@@ -254,8 +254,10 @@ do_bus_reset:dev_err (dev,"USB reset failed (%d), giving up!\n" , result); } - }else + }else { + result = -EINVAL ;/* shut gcc up in certain arches */ BUG (); + }if (result <0 && result != -EINVAL /* device is gone */ && rt !=I2400M_RT_BUS ) {
Signature · 1 line
1.6.2.3
David Miller
maintainerFrom: Inaky Perez-Gonzalez <[email protected]>
Date: Thu, 11 Jun 2009 14:35:37 -0700
Quoted 4 lines
This pull requests contains a long set of fixes to bugs and issues found while debugging the SDIO version of the i2400m WiMAX device. Most of them are in the generic part of the i2400m, and thus, apply to both the USB and SDIO versions:
...
Quoted 1 line
git://git.kernel.org/pub/scm/linux/kernel/git/inaky/wimax.gitlinux-2.6.31.y
Pulled, thanks a lot.