From 2cf8ee9044d744df57adf8485f205e8f2d4c6f02 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Wed, 2 Apr 2014 12:31:19 -0400 Subject: [PATCH 001/279] HID: sony: Fix cancel_work_sync mismerge Remove redundant cancel_work_sync() call caused by mismerge. Signed-off-by: Frank Praznik Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 69204afea7a483..908de278921944 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1721,8 +1721,6 @@ static void sony_remove(struct hid_device *hdev) if (sc->quirks & SONY_LED_SUPPORT) sony_leds_remove(hdev); - if (sc->worker_initialized) - cancel_work_sync(&sc->state_worker); if (sc->quirks & SONY_BATTERY_SUPPORT) { hid_hw_close(hdev); sony_battery_remove(sc); From 496252f787560df18a65fdc74dc3180f7cd2c723 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 14 Feb 2014 14:18:56 -0600 Subject: [PATCH 002/279] parisc: Replace __get_cpu_var uses for address calculation Convert to the use of this_cpu_ptr(). Cc: "James E.J. Bottomley" Cc: Helge Deller Cc: linux-parisc@vger.kernel.org Signed-off-by: Christoph Lameter Signed-off-by: Helge Deller --- arch/parisc/lib/memcpy.c | 2 +- arch/parisc/mm/fault.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index 413dc176929968..b2b441b32341ac 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -470,7 +470,7 @@ static unsigned long pa_memcpy(void *dstp, const void *srcp, unsigned long len) return 0; /* if a load or store fault occured we can get the faulty addr */ - d = &__get_cpu_var(exception_data); + d = this_cpu_ptr(&exception_data); fault_addr = d->fault_addr; /* error in load or store? */ diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c index 9d08c71a967ed2..747550762f3ca2 100644 --- a/arch/parisc/mm/fault.c +++ b/arch/parisc/mm/fault.c @@ -151,7 +151,7 @@ int fixup_exception(struct pt_regs *regs) fix = search_exception_tables(regs->iaoq[0]); if (fix) { struct exception_data *d; - d = &__get_cpu_var(exception_data); + d = this_cpu_ptr(&exception_data); d->fault_ip = regs->iaoq[0]; d->fault_space = regs->isr; d->fault_addr = regs->ior; From 30f58877bfdaa562d329ec870f948b4d03e1ab03 Mon Sep 17 00:00:00 2001 From: Stephen Chandler Paul Date: Thu, 3 Apr 2014 16:27:55 -0400 Subject: [PATCH 003/279] HID: sensor-hub: add sensor hub quirk for ThinkPad Helix Just like some of the other laptops/tablets on the market with ultrabook sensors, the ThinkPad Helix's sensor hub requires a special quirk in order for it to power on properly. Without it the sensors are detected by the kernel and set up as usual, but they won't output any data. This will also fix the sensors on any other laptops with the same model of sensor hub. Signed-off-by: Stephen Chandler Paul Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 3 ++- drivers/hid/hid-sensor-hub.c | 7 +++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index bd221263c739d6..3312f1b568efbe 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -455,7 +455,8 @@ #define USB_VENDOR_ID_INTEL_0 0x8086 #define USB_VENDOR_ID_INTEL_1 0x8087 -#define USB_DEVICE_ID_INTEL_HID_SENSOR 0x09fa +#define USB_DEVICE_ID_INTEL_HID_SENSOR_0 0x09fa +#define USB_DEVICE_ID_INTEL_HID_SENSOR_1 0x0a04 #define USB_VENDOR_ID_STM_0 0x0483 #define USB_DEVICE_ID_STM_HID_SENSOR 0x91d1 diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 5182031f7b5200..af8244b1c1f428 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -697,10 +697,13 @@ static void sensor_hub_remove(struct hid_device *hdev) static const struct hid_device_id sensor_hub_devices[] = { { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_0, - USB_DEVICE_ID_INTEL_HID_SENSOR), + USB_DEVICE_ID_INTEL_HID_SENSOR_0), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, - USB_DEVICE_ID_INTEL_HID_SENSOR), + USB_DEVICE_ID_INTEL_HID_SENSOR_0), + .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, + { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_INTEL_1, + USB_DEVICE_ID_INTEL_HID_SENSOR_1), .driver_data = HID_SENSOR_HUB_ENUM_QUIRK}, { HID_DEVICE(HID_BUS_ANY, HID_GROUP_SENSOR_HUB, USB_VENDOR_ID_STM_0, USB_DEVICE_ID_STM_HID_SENSOR), From f3b0cbce01cd5c242b420d986b208d306bdc5083 Mon Sep 17 00:00:00 2001 From: Derya Date: Mon, 31 Mar 2014 13:27:09 -0400 Subject: [PATCH 004/279] Revert "HID: microsoft: Add ID's for Surface Type/Touch Cover 2" This reverts commit 117309c51dca42121f70cacec801511b76acf75c. The MS Surface Pro 2 has an USB composite device with 3 interfaces - interface 0 - sensor hub - interface 1 - wacom digitizer - interface 2 - the keyboard cover, if one is attached This USB composite device changes it product id dependent on if and which keyboard cover is attached. Adding the covers to hid_have_special_driver prevents loading the right hid drivers for the other two interfaces, all 3 get loaded with hid-microsoft. We don't even need hid-microsoft for the keyboards. We have to revert this to load the right hid modules for each interface. CC: stable@vger.kernel.org # kernel 3.14 only Signed-off-by: Derya Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 2 -- drivers/hid/hid-ids.h | 2 -- drivers/hid/hid-microsoft.c | 4 ---- 3 files changed, 8 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9e8064205bc792..3f488ff88e0cf8 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1821,8 +1821,6 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2) }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 3312f1b568efbe..c8af7202c28da3 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -630,8 +630,6 @@ #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 #define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c -#define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 -#define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 6fd58175a291bb..8ba17a946f2a39 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -274,10 +274,6 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), .driver_data = MS_DUPLICATE_USAGES }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_2), - .driver_data = 0 }, - { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), - .driver_data = 0 }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, From e24d0d399b2fce71b627043e900ef28283850482 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Mon, 31 Mar 2014 13:27:10 -0400 Subject: [PATCH 005/279] HID: core: do not scan constant input report The Microsoft Surface Type/Touch Cover 2 is a fancy device which advertised itself as a multitouch device but with constant input reports. This way, hid_scan_report() gives the group MULTITOUCH to it, but hid-multitouch can not handle it due to the constant collection ignored by hid-input. To prevent such crap in the future, and while we do not fix this particular device, make the scan_report coherent with hid-input.c, and ignore constant input reports. CC: stable@vger.kernel.org # 3.12+ Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3f488ff88e0cf8..10a2c08664596a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -718,6 +718,9 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) case HID_MAIN_ITEM_TAG_END_COLLECTION: break; case HID_MAIN_ITEM_TAG_INPUT: + /* ignore constant inputs, they will be ignored by hid-input */ + if (data & HID_MAIN_ITEM_CONSTANT) + break; for (i = 0; i < parser->local.usage_index; i++) hid_scan_input_usage(parser, parser->local.usage[i]); break; From 1ca2030563534bc0b057df9fddd30fb6257826cb Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 7 Apr 2014 10:37:44 +0200 Subject: [PATCH 006/279] drm/tegra: dp: Support address-only I2C-over-AUX transactions Certain types of I2C-over-AUX transactions require that only the address is transferred. Detect this by looking at the AUX message's size and set the address-only bit appropriately. Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dpaux.c | 44 ++++++++++++++++++++++++----------- drivers/gpu/drm/tegra/dpaux.h | 1 + 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index d536ed381fbd9e..005c19bd92dfa0 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -99,55 +99,73 @@ static void tegra_dpaux_read_fifo(struct tegra_dpaux *dpaux, u8 *buffer, static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { - unsigned long value = DPAUX_DP_AUXCTL_TRANSACTREQ; unsigned long timeout = msecs_to_jiffies(250); struct tegra_dpaux *dpaux = to_dpaux(aux); unsigned long status; ssize_t ret = 0; + u32 value; - if (msg->size < 1 || msg->size > 16) + /* Tegra has 4x4 byte DP AUX transmit and receive FIFOs. */ + if (msg->size > 16) return -EINVAL; - tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); + /* + * Allow zero-sized messages only for I2C, in which case they specify + * address-only transactions. + */ + if (msg->size < 1) { + switch (msg->request & ~DP_AUX_I2C_MOT) { + case DP_AUX_I2C_WRITE: + case DP_AUX_I2C_READ: + value = DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY; + break; + + default: + return -EINVAL; + } + } else { + /* For non-zero-sized messages, set the CMDLEN field. */ + value = DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1); + } switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_I2C_WRITE: if (msg->request & DP_AUX_I2C_MOT) - value = DPAUX_DP_AUXCTL_CMD_MOT_WR; + value |= DPAUX_DP_AUXCTL_CMD_MOT_WR; else - value = DPAUX_DP_AUXCTL_CMD_I2C_WR; + value |= DPAUX_DP_AUXCTL_CMD_I2C_WR; break; case DP_AUX_I2C_READ: if (msg->request & DP_AUX_I2C_MOT) - value = DPAUX_DP_AUXCTL_CMD_MOT_RD; + value |= DPAUX_DP_AUXCTL_CMD_MOT_RD; else - value = DPAUX_DP_AUXCTL_CMD_I2C_RD; + value |= DPAUX_DP_AUXCTL_CMD_I2C_RD; break; case DP_AUX_I2C_STATUS: if (msg->request & DP_AUX_I2C_MOT) - value = DPAUX_DP_AUXCTL_CMD_MOT_RQ; + value |= DPAUX_DP_AUXCTL_CMD_MOT_RQ; else - value = DPAUX_DP_AUXCTL_CMD_I2C_RQ; + value |= DPAUX_DP_AUXCTL_CMD_I2C_RQ; break; case DP_AUX_NATIVE_WRITE: - value = DPAUX_DP_AUXCTL_CMD_AUX_WR; + value |= DPAUX_DP_AUXCTL_CMD_AUX_WR; break; case DP_AUX_NATIVE_READ: - value = DPAUX_DP_AUXCTL_CMD_AUX_RD; + value |= DPAUX_DP_AUXCTL_CMD_AUX_RD; break; default: return -EINVAL; } - value |= DPAUX_DP_AUXCTL_CMDLEN(msg->size - 1); + tegra_dpaux_writel(dpaux, msg->address, DPAUX_DP_AUXADDR); tegra_dpaux_writel(dpaux, value, DPAUX_DP_AUXCTL); if ((msg->request & DP_AUX_I2C_READ) == 0) { @@ -198,7 +216,7 @@ static ssize_t tegra_dpaux_transfer(struct drm_dp_aux *aux, break; } - if (msg->reply == DP_AUX_NATIVE_REPLY_ACK) { + if ((msg->size > 0) && (msg->reply == DP_AUX_NATIVE_REPLY_ACK)) { if (msg->request & DP_AUX_I2C_READ) { size_t count = value & DPAUX_DP_AUXSTAT_REPLY_MASK; diff --git a/drivers/gpu/drm/tegra/dpaux.h b/drivers/gpu/drm/tegra/dpaux.h index 4f5bf10fdff918..806e245ca7874d 100644 --- a/drivers/gpu/drm/tegra/dpaux.h +++ b/drivers/gpu/drm/tegra/dpaux.h @@ -32,6 +32,7 @@ #define DPAUX_DP_AUXCTL_CMD_I2C_RQ (2 << 12) #define DPAUX_DP_AUXCTL_CMD_I2C_RD (1 << 12) #define DPAUX_DP_AUXCTL_CMD_I2C_WR (0 << 12) +#define DPAUX_DP_AUXCTL_CMD_ADDRESS_ONLY (1 << 8) #define DPAUX_DP_AUXCTL_CMDLEN(x) ((x) & 0xff) #define DPAUX_DP_AUXSTAT 0x31 From a6c8aff022d4d06e4b41455ae9b2a5d3d503bf76 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 7 Apr 2014 12:37:25 +0300 Subject: [PATCH 007/279] drm/i915: support address only i2c-over-aux transactions To support bare address requests used by the drm dp helpers. Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_dp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index a0dad1a2f819f3..d2a55884ad523b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -575,7 +575,8 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, return ret; } -#define HEADER_SIZE 4 +#define BARE_ADDRESS_SIZE 3 +#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) static ssize_t intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { @@ -592,7 +593,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_WRITE: case DP_AUX_I2C_WRITE: - txsize = HEADER_SIZE + msg->size; + txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE; rxsize = 1; if (WARN_ON(txsize > 20)) @@ -611,7 +612,7 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) case DP_AUX_NATIVE_READ: case DP_AUX_I2C_READ: - txsize = HEADER_SIZE; + txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE; rxsize = msg->size + 1; if (WARN_ON(rxsize > 20)) From 25377b921b4078a509f384fdd328b50d46414d9c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 7 Apr 2014 10:33:43 -0400 Subject: [PATCH 008/279] drm/radeon/dp: handle zero sized i2c over aux transactions (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Needed for proper i2c over aux handling for certain monitors and configurations (e.g., dp bridges or adapters). v2: add comments clarifying tx_size setting. Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/atombios_dp.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 8b0ab170cef903..e4483042aee0b9 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -142,7 +142,8 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, return recv_bytes; } -#define HEADER_SIZE 4 +#define BARE_ADDRESS_SIZE 3 +#define HEADER_SIZE (BARE_ADDRESS_SIZE + 1) static ssize_t radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) @@ -160,13 +161,19 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) tx_buf[0] = msg->address & 0xff; tx_buf[1] = msg->address >> 8; tx_buf[2] = msg->request << 4; - tx_buf[3] = msg->size - 1; + tx_buf[3] = msg->size ? (msg->size - 1) : 0; switch (msg->request & ~DP_AUX_I2C_MOT) { case DP_AUX_NATIVE_WRITE: case DP_AUX_I2C_WRITE: + /* tx_size needs to be 4 even for bare address packets since the atom + * table needs the info in tx_buf[3]. + */ tx_size = HEADER_SIZE + msg->size; - tx_buf[3] |= tx_size << 4; + if (msg->size == 0) + tx_buf[3] |= BARE_ADDRESS_SIZE << 4; + else + tx_buf[3] |= tx_size << 4; memcpy(tx_buf + HEADER_SIZE, msg->buffer, msg->size); ret = radeon_process_aux_ch(chan, tx_buf, tx_size, NULL, 0, delay, &ack); @@ -176,8 +183,14 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) break; case DP_AUX_NATIVE_READ: case DP_AUX_I2C_READ: + /* tx_size needs to be 4 even for bare address packets since the atom + * table needs the info in tx_buf[3]. + */ tx_size = HEADER_SIZE; - tx_buf[3] |= tx_size << 4; + if (msg->size == 0) + tx_buf[3] |= BARE_ADDRESS_SIZE << 4; + else + tx_buf[3] |= tx_size << 4; ret = radeon_process_aux_ch(chan, tx_buf, tx_size, msg->buffer, msg->size, delay, &ack); break; @@ -186,7 +199,7 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) break; } - if (ret > 0) + if (ret >= 0) msg->reply = ack >> 4; return ret; From ccdb516e1873d9c69377bfec1e3392f3ed660102 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 7 Apr 2014 10:33:44 -0400 Subject: [PATCH 009/279] drm/dp/i2c: send bare addresses to properly reset i2c connections (v4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need bare address packets at the start and end of each i2c over aux transaction to properly reset the connection between transactions. This mirrors what the existing dp i2c over aux algo currently does. This fixes EDID fetches on certain monitors especially with dp bridges. v2: update as per Ville's comments - Set buffer to NULL for zero sized packets - abort the entre transaction if one of the messages fails v3: drop leftover debugging code v4: integrate Thierry's comments - add comments about address only transactions - switch back to i and j Signed-off-by: Alex Deucher Cc: Ville Syrjälä Cc: Jani Nikula Cc: Thierry Reding Reviewed-by: Ville Syrjälä Signed-off-by: Christian König --- drivers/gpu/drm/drm_dp_helper.c | 51 +++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 27671489477de6..bcfb0d07718e2d 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -665,11 +665,26 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, { struct drm_dp_aux *aux = adapter->algo_data; unsigned int i, j; + struct drm_dp_aux_msg msg; + int err = 0; - for (i = 0; i < num; i++) { - struct drm_dp_aux_msg msg; - int err; + memset(&msg, 0, sizeof(msg)); + for (i = 0; i < num; i++) { + msg.address = msgs[i].addr; + msg.request = (msgs[i].flags & I2C_M_RD) ? + DP_AUX_I2C_READ : + DP_AUX_I2C_WRITE; + msg.request |= DP_AUX_I2C_MOT; + /* Send a bare address packet to start the transaction. + * Zero sized messages specify an address only (bare + * address) transaction. + */ + msg.buffer = NULL; + msg.size = 0; + err = drm_dp_i2c_do_msg(aux, &msg); + if (err < 0) + break; /* * Many hardware implementations support FIFOs larger than a * single byte, but it has been empirically determined that @@ -678,30 +693,28 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, * transferred byte-by-byte. */ for (j = 0; j < msgs[i].len; j++) { - memset(&msg, 0, sizeof(msg)); - msg.address = msgs[i].addr; - - msg.request = (msgs[i].flags & I2C_M_RD) ? - DP_AUX_I2C_READ : - DP_AUX_I2C_WRITE; - - /* - * All messages except the last one are middle-of- - * transfer messages. - */ - if ((i < num - 1) || (j < msgs[i].len - 1)) - msg.request |= DP_AUX_I2C_MOT; - msg.buffer = msgs[i].buf + j; msg.size = 1; err = drm_dp_i2c_do_msg(aux, &msg); if (err < 0) - return err; + break; } + if (err < 0) + break; } + if (err >= 0) + err = num; + /* Send a bare address packet to close out the transaction. + * Zero sized messages specify an address only (bare + * address) transaction. + */ + msg.request &= ~DP_AUX_I2C_MOT; + msg.buffer = NULL; + msg.size = 0; + (void)drm_dp_i2c_do_msg(aux, &msg); - return num; + return err; } static const struct i2c_algorithm drm_dp_i2c_algo = { From 732d50b431dca2f3f78fc21ba9b7ed9d06bb01ce Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 7 Apr 2014 10:33:45 -0400 Subject: [PATCH 010/279] drm/dp/i2c: Update comments about common i2c over dp assumptions (v3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you are using the common dp over i2c functionality, it is asumed that the aux transfer function does not modify the any of the msg structure other than the reply field. Doing so breaks the logic in the common code. v2: update struct drm_dp_aux comments about assumptions v3 (chk): rebased on upstream changes Signed-off-by: Alex Deucher Cc: Ville Syrjälä Cc: Jani Nikula Cc: Thierry Reding Reviewed-by: Ville Syrjälä Signed-off-by: Christian König --- drivers/gpu/drm/drm_dp_helper.c | 4 +++- include/drm/drm_dp_helper.h | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index bcfb0d07718e2d..4b6e6f3ba0a19c 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -577,7 +577,9 @@ static u32 drm_dp_i2c_functionality(struct i2c_adapter *adapter) /* * Transfer a single I2C-over-AUX message and handle various error conditions, - * retrying the transaction as appropriate. + * retrying the transaction as appropriate. It is assumed that the + * aux->transfer function does not modify anything in the msg other than the + * reply field. */ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b4f58914bf7d93..cfcacec5b89db8 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -456,6 +456,10 @@ struct drm_dp_aux_msg { * transactions. The drm_dp_aux_register_i2c_bus() function registers an * I2C adapter that can be passed to drm_probe_ddc(). Upon removal, drivers * should call drm_dp_aux_unregister_i2c_bus() to remove the I2C adapter. + * + * Note that the aux helper code assumes that the .transfer() function + * only modifies the reply field of the drm_dp_aux_msg structure. The + * retry logic and i2c helpers assume this is the case. */ struct drm_dp_aux { const char *name; From 379dfc25e257ffe10eb53b86d2375f7c0f4f33ef Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 7 Apr 2014 10:33:46 -0400 Subject: [PATCH 011/279] drm/radeon/dp: switch to the common i2c over aux code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Provides a nice cleanup in radeon. Signed-off-by: Alex Deucher Signed-off-by: Christian König --- drivers/gpu/drm/radeon/atombios_dp.c | 117 +++------------------ drivers/gpu/drm/radeon/radeon_connectors.c | 44 ++------ drivers/gpu/drm/radeon/radeon_display.c | 11 +- drivers/gpu/drm/radeon/radeon_i2c.c | 60 +++-------- drivers/gpu/drm/radeon/radeon_mode.h | 12 +-- 5 files changed, 44 insertions(+), 200 deletions(-) diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index e4483042aee0b9..15936524f226ca 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -207,98 +207,15 @@ radeon_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) void radeon_dp_aux_init(struct radeon_connector *radeon_connector) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; - - dig_connector->dp_i2c_bus->aux.dev = radeon_connector->base.kdev; - dig_connector->dp_i2c_bus->aux.transfer = radeon_dp_aux_transfer; -} - -int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, - u8 write_byte, u8 *read_byte) -{ - struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; - struct radeon_i2c_chan *auxch = i2c_get_adapdata(adapter); - u16 address = algo_data->address; - u8 msg[5]; - u8 reply[2]; - unsigned retry; - int msg_bytes; - int reply_bytes = 1; int ret; - u8 ack; - - /* Set up the address */ - msg[0] = address; - msg[1] = address >> 8; - - /* Set up the command byte */ - if (mode & MODE_I2C_READ) { - msg[2] = DP_AUX_I2C_READ << 4; - msg_bytes = 4; - msg[3] = msg_bytes << 4; - } else { - msg[2] = DP_AUX_I2C_WRITE << 4; - msg_bytes = 5; - msg[3] = msg_bytes << 4; - msg[4] = write_byte; - } - /* special handling for start/stop */ - if (mode & (MODE_I2C_START | MODE_I2C_STOP)) - msg[3] = 3 << 4; - - /* Set MOT bit for all but stop */ - if ((mode & MODE_I2C_STOP) == 0) - msg[2] |= DP_AUX_I2C_MOT << 4; - - for (retry = 0; retry < 7; retry++) { - ret = radeon_process_aux_ch(auxch, - msg, msg_bytes, reply, reply_bytes, 0, &ack); - if (ret == -EBUSY) - continue; - else if (ret < 0) { - DRM_DEBUG_KMS("aux_ch failed %d\n", ret); - return ret; - } + radeon_connector->ddc_bus->aux.dev = radeon_connector->base.kdev; + radeon_connector->ddc_bus->aux.transfer = radeon_dp_aux_transfer; + ret = drm_dp_aux_register_i2c_bus(&radeon_connector->ddc_bus->aux); + if (!ret) + radeon_connector->ddc_bus->has_aux = true; - switch ((ack >> 4) & DP_AUX_NATIVE_REPLY_MASK) { - case DP_AUX_NATIVE_REPLY_ACK: - /* I2C-over-AUX Reply field is only valid - * when paired with AUX ACK. - */ - break; - case DP_AUX_NATIVE_REPLY_NACK: - DRM_DEBUG_KMS("aux_ch native nack\n"); - return -EREMOTEIO; - case DP_AUX_NATIVE_REPLY_DEFER: - DRM_DEBUG_KMS("aux_ch native defer\n"); - usleep_range(500, 600); - continue; - default: - DRM_ERROR("aux_ch invalid native reply 0x%02x\n", ack); - return -EREMOTEIO; - } - - switch ((ack >> 4) & DP_AUX_I2C_REPLY_MASK) { - case DP_AUX_I2C_REPLY_ACK: - if (mode == MODE_I2C_READ) - *read_byte = reply[0]; - return ret; - case DP_AUX_I2C_REPLY_NACK: - DRM_DEBUG_KMS("aux_i2c nack\n"); - return -EREMOTEIO; - case DP_AUX_I2C_REPLY_DEFER: - DRM_DEBUG_KMS("aux_i2c defer\n"); - usleep_range(400, 500); - break; - default: - DRM_ERROR("aux_i2c invalid reply 0x%02x\n", ack); - return -EREMOTEIO; - } - } - - DRM_DEBUG_KMS("aux i2c too many retries, giving up\n"); - return -EREMOTEIO; + WARN(ret, "drm_dp_aux_register_i2c_bus() failed with error %d\n", ret); } /***** general DP utility functions *****/ @@ -433,12 +350,11 @@ static u8 radeon_dp_encoder_service(struct radeon_device *rdev, u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector) { - struct radeon_connector_atom_dig *dig_connector = radeon_connector->con_priv; struct drm_device *dev = radeon_connector->base.dev; struct radeon_device *rdev = dev->dev_private; return radeon_dp_encoder_service(rdev, ATOM_DP_ACTION_GET_SINK_TYPE, 0, - dig_connector->dp_i2c_bus->rec.i2c_id, 0); + radeon_connector->ddc_bus->rec.i2c_id, 0); } static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) @@ -449,11 +365,11 @@ static void radeon_dp_probe_oui(struct radeon_connector *radeon_connector) if (!(dig_connector->dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) return; - if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_SINK_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_SINK_OUI, buf, 3)) DRM_DEBUG_KMS("Sink OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); - if (drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_BRANCH_OUI, buf, 3)) + if (drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_BRANCH_OUI, buf, 3)) DRM_DEBUG_KMS("Branch OUI: %02hx%02hx%02hx\n", buf[0], buf[1], buf[2]); } @@ -464,7 +380,7 @@ bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector) u8 msg[DP_DPCD_SIZE]; int ret, i; - ret = drm_dp_dpcd_read(&dig_connector->dp_i2c_bus->aux, DP_DPCD_REV, msg, + ret = drm_dp_dpcd_read(&radeon_connector->ddc_bus->aux, DP_DPCD_REV, msg, DP_DPCD_SIZE); if (ret > 0) { memcpy(dig_connector->dpcd, msg, DP_DPCD_SIZE); @@ -502,7 +418,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, if (dp_bridge != ENCODER_OBJECT_ID_NONE) { /* DP bridge chips */ - drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, + drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_EDP_CONFIGURATION_CAP, &tmp); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; @@ -513,7 +429,7 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder, panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { /* eDP */ - drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, + drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_EDP_CONFIGURATION_CAP, &tmp); if (tmp & 1) panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE; @@ -567,7 +483,8 @@ bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector) u8 link_status[DP_LINK_STATUS_SIZE]; struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - if (drm_dp_dpcd_read_link_status(&dig->dp_i2c_bus->aux, link_status) <= 0) + if (drm_dp_dpcd_read_link_status(&radeon_connector->ddc_bus->aux, link_status) + <= 0) return false; if (drm_dp_channel_eq_ok(link_status, dig->dp_lane_count)) return false; @@ -587,7 +504,7 @@ void radeon_dp_set_rx_power_state(struct drm_connector *connector, /* power up/down the sink */ if (dig_connector->dpcd[0] >= 0x11) { - drm_dp_dpcd_writeb(&dig_connector->dp_i2c_bus->aux, + drm_dp_dpcd_writeb(&radeon_connector->ddc_bus->aux, DP_SET_POWER, power_state); usleep_range(1000, 2000); } @@ -891,7 +808,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, else dp_info.enc_id |= ATOM_DP_CONFIG_LINK_A; - drm_dp_dpcd_readb(&dig_connector->dp_i2c_bus->aux, DP_MAX_LANE_COUNT, &tmp); + drm_dp_dpcd_readb(&radeon_connector->ddc_bus->aux, DP_MAX_LANE_COUNT, &tmp); if (ASIC_IS_DCE5(rdev) && (tmp & DP_TPS3_SUPPORTED)) dp_info.tp3_supported = true; else @@ -903,7 +820,7 @@ void radeon_dp_link_train(struct drm_encoder *encoder, dp_info.connector = connector; dp_info.dp_lane_count = dig_connector->dp_lane_count; dp_info.dp_clock = dig_connector->dp_clock; - dp_info.aux = &dig_connector->dp_i2c_bus->aux; + dp_info.aux = &radeon_connector->ddc_bus->aux; if (radeon_dp_link_train_init(&dp_info)) goto done; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index c566b486ca08a7..ea50e0ae7bf7f3 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1261,21 +1261,6 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = { .force = radeon_dvi_force, }; -static void radeon_dp_connector_destroy(struct drm_connector *connector) -{ - struct radeon_connector *radeon_connector = to_radeon_connector(connector); - struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv; - - if (radeon_connector->edid) - kfree(radeon_connector->edid); - if (radeon_dig_connector->dp_i2c_bus) - radeon_i2c_destroy(radeon_dig_connector->dp_i2c_bus); - kfree(radeon_connector->con_priv); - drm_sysfs_connector_remove(connector); - drm_connector_cleanup(connector); - kfree(connector); -} - static int radeon_dp_get_modes(struct drm_connector *connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -1553,7 +1538,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_connector_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1562,7 +1547,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_lvds_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1571,7 +1556,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { .detect = radeon_dp_detect, .fill_modes = drm_helper_probe_single_connector_modes, .set_property = radeon_lvds_set_property, - .destroy = radeon_dp_connector_destroy, + .destroy = radeon_connector_destroy, .force = radeon_dvi_force, }; @@ -1668,17 +1653,10 @@ radeon_add_atom_connector(struct drm_device *dev, radeon_dig_connector->igp_lane_info = igp_lane_info; radeon_connector->con_priv = radeon_dig_connector; if (i2c_bus->valid) { - /* add DP i2c bus */ - if (connector_type == DRM_MODE_CONNECTOR_eDP) - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); - else - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); - if (radeon_dig_connector->dp_i2c_bus) + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (radeon_connector->ddc_bus) has_aux = true; else - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); } switch (connector_type) { @@ -1893,10 +1871,6 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_dp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { - /* add DP i2c bus */ - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch"); - if (!radeon_dig_connector->dp_i2c_bus) - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); if (radeon_connector->ddc_bus) has_aux = true; @@ -1942,14 +1916,10 @@ radeon_add_atom_connector(struct drm_device *dev, drm_connector_init(dev, &radeon_connector->base, &radeon_edp_connector_funcs, connector_type); drm_connector_helper_add(&radeon_connector->base, &radeon_dp_connector_helper_funcs); if (i2c_bus->valid) { - /* add DP i2c bus */ - radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "eDP-auxch"); - if (radeon_dig_connector->dp_i2c_bus) + radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); + if (radeon_connector->ddc_bus) has_aux = true; else - DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n"); - radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus); - if (!radeon_connector->ddc_bus) DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); } drm_object_attach_property(&radeon_connector->base.base, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 386cfa4c194dc4..776e03d6ac81a5 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -759,19 +759,18 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != ENCODER_OBJECT_ID_NONE) { - struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - - if (dig->dp_i2c_bus) + if (radeon_connector->ddc_bus->has_aux) radeon_connector->edid = drm_get_edid(&radeon_connector->base, - &dig->dp_i2c_bus->adapter); + &radeon_connector->ddc_bus->aux.ddc); } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || - dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus) + dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && + radeon_connector->ddc_bus->has_aux) radeon_connector->edid = drm_get_edid(&radeon_connector->base, - &dig->dp_i2c_bus->adapter); + &radeon_connector->ddc_bus->aux.ddc); else if (radeon_connector->ddc_bus && !radeon_connector->edid) radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter); diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index e24ca6ab96decd..7b944142a9fdd4 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -64,8 +64,7 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) radeon_router_select_ddc_port(radeon_connector); if (use_aux) { - struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; - ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); + ret = i2c_transfer(&radeon_connector->ddc_bus->aux.ddc, msgs, 2); } else { ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); } @@ -950,16 +949,16 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, /* set the radeon bit adapter */ snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "Radeon i2c bit bus %s", name); - i2c->adapter.algo_data = &i2c->algo.bit; - i2c->algo.bit.pre_xfer = pre_xfer; - i2c->algo.bit.post_xfer = post_xfer; - i2c->algo.bit.setsda = set_data; - i2c->algo.bit.setscl = set_clock; - i2c->algo.bit.getsda = get_data; - i2c->algo.bit.getscl = get_clock; - i2c->algo.bit.udelay = 10; - i2c->algo.bit.timeout = usecs_to_jiffies(2200); /* from VESA */ - i2c->algo.bit.data = i2c; + i2c->adapter.algo_data = &i2c->bit; + i2c->bit.pre_xfer = pre_xfer; + i2c->bit.post_xfer = post_xfer; + i2c->bit.setsda = set_data; + i2c->bit.setscl = set_clock; + i2c->bit.getsda = get_data; + i2c->bit.getscl = get_clock; + i2c->bit.udelay = 10; + i2c->bit.timeout = usecs_to_jiffies(2200); /* from VESA */ + i2c->bit.data = i2c; ret = i2c_bit_add_bus(&i2c->adapter); if (ret) { DRM_ERROR("Failed to register bit i2c %s\n", name); @@ -974,46 +973,13 @@ struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, } -struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, - struct radeon_i2c_bus_rec *rec, - const char *name) -{ - struct radeon_i2c_chan *i2c; - int ret; - - i2c = kzalloc(sizeof(struct radeon_i2c_chan), GFP_KERNEL); - if (i2c == NULL) - return NULL; - - i2c->rec = *rec; - i2c->adapter.owner = THIS_MODULE; - i2c->adapter.class = I2C_CLASS_DDC; - i2c->adapter.dev.parent = &dev->pdev->dev; - i2c->dev = dev; - snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), - "Radeon aux bus %s", name); - i2c_set_adapdata(&i2c->adapter, i2c); - i2c->adapter.algo_data = &i2c->algo.dp; - i2c->algo.dp.aux_ch = radeon_dp_i2c_aux_ch; - i2c->algo.dp.address = 0; - ret = i2c_dp_aux_add_bus(&i2c->adapter); - if (ret) { - DRM_INFO("Failed to register i2c %s\n", name); - goto out_free; - } - - return i2c; -out_free: - kfree(i2c); - return NULL; - -} - void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) { if (!i2c) return; i2c_del_adapter(&i2c->adapter); + if (i2c->has_aux) + drm_dp_aux_unregister_i2c_bus(&i2c->aux); kfree(i2c); } diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 832d9fa1a4c4ec..6ddf31a2d34e01 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -187,12 +187,10 @@ struct radeon_pll { struct radeon_i2c_chan { struct i2c_adapter adapter; struct drm_device *dev; - union { - struct i2c_algo_bit_data bit; - struct i2c_algo_dp_aux_data dp; - } algo; + struct i2c_algo_bit_data bit; struct radeon_i2c_bus_rec rec; struct drm_dp_aux aux; + bool has_aux; }; /* mostly for macs, but really any system without connector tables */ @@ -440,7 +438,6 @@ struct radeon_encoder { struct radeon_connector_atom_dig { uint32_t igp_lane_info; /* displayport */ - struct radeon_i2c_chan *dp_i2c_bus; u8 dpcd[DP_RECEIVER_CAP_SIZE]; u8 dp_sink_type; int dp_clock; @@ -702,8 +699,6 @@ extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder, uint8_t lane_set); extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder); extern struct drm_encoder *radeon_get_external_encoder(struct drm_encoder *encoder); -extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, - u8 write_byte, u8 *read_byte); void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); extern void radeon_i2c_init(struct radeon_device *rdev); @@ -715,9 +710,6 @@ extern void radeon_i2c_add(struct radeon_device *rdev, const char *name); extern struct radeon_i2c_chan *radeon_i2c_lookup(struct radeon_device *rdev, struct radeon_i2c_bus_rec *i2c_bus); -extern struct radeon_i2c_chan *radeon_i2c_create_dp(struct drm_device *dev, - struct radeon_i2c_bus_rec *rec, - const char *name); extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev, struct radeon_i2c_bus_rec *rec, const char *name); From be0949f5eb9c8133a05cf25f108f09e85e79cd32 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 8 Apr 2014 11:28:54 -0400 Subject: [PATCH 012/279] drm/radeon: fix audio pin counts for DCE6+ (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is actually quite a bit of variance based on the asic. v2: fix typo noticed by Jerome. Signed-off-by: Alex Deucher Signed-off-by: Christian König Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/dce6_afmt.c | 14 ++++++++++---- drivers/gpu/drm/radeon/radeon.h | 5 ++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 94e85875199481..0a65dc7e93e7f8 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -309,11 +309,17 @@ int dce6_audio_init(struct radeon_device *rdev) rdev->audio.enabled = true; - if (ASIC_IS_DCE8(rdev)) + if (ASIC_IS_DCE81(rdev)) /* KV: 4 streams, 7 endpoints */ + rdev->audio.num_pins = 7; + else if (ASIC_IS_DCE83(rdev)) /* KB: 2 streams, 3 endpoints */ + rdev->audio.num_pins = 3; + else if (ASIC_IS_DCE8(rdev)) /* BN/HW: 6 streams, 7 endpoints */ + rdev->audio.num_pins = 7; + else if (ASIC_IS_DCE61(rdev)) /* TN: 4 streams, 6 endpoints */ rdev->audio.num_pins = 6; - else if (ASIC_IS_DCE61(rdev)) - rdev->audio.num_pins = 4; - else + else if (ASIC_IS_DCE64(rdev)) /* OL: 2 streams, 2 endpoints */ + rdev->audio.num_pins = 2; + else /* SI: 6 streams, 6 endpoints */ rdev->audio.num_pins = 6; for (i = 0; i < rdev->audio.num_pins; i++) { diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f21db7a0b34d7d..05b08e16e1f5ed 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -739,7 +739,7 @@ union radeon_irq_stat_regs { struct cik_irq_stat_regs cik; }; -#define RADEON_MAX_HPD_PINS 6 +#define RADEON_MAX_HPD_PINS 7 #define RADEON_MAX_CRTCS 6 #define RADEON_MAX_AFMT_BLOCKS 7 @@ -2631,6 +2631,9 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); #define ASIC_IS_DCE64(rdev) ((rdev->family == CHIP_OLAND)) #define ASIC_IS_NODCE(rdev) ((rdev->family == CHIP_HAINAN)) #define ASIC_IS_DCE8(rdev) ((rdev->family >= CHIP_BONAIRE)) +#define ASIC_IS_DCE81(rdev) ((rdev->family == CHIP_KAVERI)) +#define ASIC_IS_DCE82(rdev) ((rdev->family == CHIP_BONAIRE)) +#define ASIC_IS_DCE83(rdev) ((rdev->family == CHIP_KABINI)) #define ASIC_IS_LOMBOK(rdev) ((rdev->ddev->pdev->device == 0x6849) || \ (rdev->ddev->pdev->device == 0x6850) || \ From 8902e6f2b832e00e10c6f9e9532f6f63feb4972f Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Tue, 8 Apr 2014 13:39:36 +0300 Subject: [PATCH 013/279] drm/radeon: Improve vramlimit module param documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Lauri Kasanen Signed-off-by: Christian König Reviewed-by: Alex Deucher --- drivers/gpu/drm/radeon/radeon_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index d0eba48dd74e1d..cf2721a9124974 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -186,7 +186,7 @@ module_param_named(dynclks, radeon_dynclks, int, 0444); MODULE_PARM_DESC(r4xx_atom, "Enable ATOMBIOS modesetting for R4xx"); module_param_named(r4xx_atom, radeon_r4xx_atom, int, 0444); -MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing"); +MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, radeon_vram_limit, int, 0600); MODULE_PARM_DESC(agpmode, "AGP Mode (-1 == PCI)"); From 115b943a6ea12656088fa1ff6634c0d30815e55b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 27 Mar 2014 15:39:20 +0100 Subject: [PATCH 014/279] mac80211: fix software remain-on-channel implementation Jouni reported that when doing off-channel transmissions mixed with on-channel transmissions, the on-channel ones ended up on the off-channel in some cases. The reason for that is that during the refactoring of the off- channel code, I lost the part that stopped all activity and as a consequence the on-channel frames (including data frames) were no longer queued but would be transmitted on the temporary channel. Fix this by simply restoring the lost activity stop call. Cc: stable@vger.kernel.org Fixes: 2eb278e083549 ("mac80211: unify SW/offload remain-on-channel") Reported-by: Jouni Malinen Signed-off-by: Johannes Berg --- net/mac80211/offchannel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 0c2a29484c07cd..6fb38558a5e6c7 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -355,6 +355,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) struct ieee80211_roc_work *dep; /* start this ROC */ + ieee80211_offchannel_stop_vifs(local); /* switch channel etc */ ieee80211_recalc_idle(local); From 7b8a9cdd1f959c7166611fcc58ac91e8409c10ab Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Mon, 24 Mar 2014 09:55:45 +0200 Subject: [PATCH 015/279] mac80211: Disable SMPS for the monitor interface All antennas should be operational when monitoring to maximize reception. Signed-off-by: Ido Yariv Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index bd1fd8ea5105fe..68bee813dfad08 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -492,6 +492,13 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, rx_chains_static = max(rx_chains_static, needed_static); rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic); } + + /* Disable SMPS for the monitor interface */ + sdata = rcu_dereference(local->monitor_sdata); + if (sdata && + rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf) + rx_chains_dynamic = rx_chains_static = local->rx_chains; + rcu_read_unlock(); if (!local->use_chanctx) { From 9b4816f543ee8d48bb49151718edac480d2080b1 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 4 Apr 2014 13:02:43 +0200 Subject: [PATCH 016/279] mac80211: fix radar_enabled propagation If chandef had non-HT width it was possible for radar_enabled update to not be propagated properly through drv_config(). This happened because ieee80211_hw_conf_chan() would never see different local->hw.conf.chandef and local->_oper_chandef. This wasn't a problem with HT chandefs because _oper_chandef width is reset to non-HT in ieee80211_free_chanctx() making ieee80211_hw_conf_chan() to kick in. This problem led (at least) ath10k to not start CAC if prior CAC was cancelled and both CACs were requested for identical non-HT chandefs. Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/mac80211/chan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 68bee813dfad08..75b5dd2c9267f1 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -249,7 +249,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local, if (!local->use_chanctx) { local->_oper_chandef = *chandef; - ieee80211_hw_config(local, 0); + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); } else { err = drv_add_chanctx(local, ctx); if (err) { @@ -286,7 +286,7 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local, check_single_channel = true; local->hw.conf.radar_enabled = false; - ieee80211_hw_config(local, 0); + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); } else { drv_remove_chanctx(local, ctx); } From 00a9a6d1e2f18c193d28409bfafc890d78adef68 Mon Sep 17 00:00:00 2001 From: Chun-Yeow Yeoh Date: Wed, 2 Apr 2014 12:05:09 +0800 Subject: [PATCH 017/279] mac80211: update last_tx_rate only for data frame Rate controller in firmware may also return the Tx Rate used for management frame that is usually sent as lowest Tx Rate (1Mbps in 2.4GHz). So update the last_tx_rate only if it is data frame. This patch is tested with ath9k_htc. Signed-off-by: Chun-Yeow Yeoh Signed-off-by: Johannes Berg --- net/mac80211/status.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/status.c b/net/mac80211/status.c index e6e574a307c8f3..00ba90b02ab2ab 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -618,6 +618,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) sta, true, acked); if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) && + (ieee80211_is_data(hdr->frame_control)) && (rates_idx != -1)) sta->last_tx_rate = info->status.rates[rates_idx]; From 004f388559a89ac17fa4c81fb8559a6599050a4e Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 7 Apr 2014 23:25:20 +0200 Subject: [PATCH 018/279] drm/mm: Don't WARN if drm_mm_reserve_node Jesse's BIOS fb reconstruction code actually relies on the -ENOSPC return value to detect overlapping framebuffers (which the bios uses always when lighting up more than one screen). All this fanciness happens in intel_alloc_plane_obj in intel_display.c. Since no one else uses this we can safely remove the WARN without repercussions. Reported-by: Ben Widawsky Tested-by: Ben Widawsky Cc: Jesse Barnes Cc: Dave Airlie Signed-off-by: Daniel Vetter Acked-by: Dave Airlie Signed-off-by: Jani Nikula --- drivers/gpu/drm/drm_mm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 71e2d3fcd6ee3c..04a209e2b66d7d 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -207,8 +207,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) return 0; } - WARN(1, "no hole found for node 0x%lx + 0x%lx\n", - node->start, node->size); return -ENOSPC; } EXPORT_SYMBOL(drm_mm_reserve_node); From 2ab1bc9df01dbc19b55b2271100db7407fa6bfdc Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Mon, 7 Apr 2014 08:54:21 +0200 Subject: [PATCH 019/279] drm/i915: Disable self-refresh for untiled fbs on i915gm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently it doesn't work. X-tiled self-refresh works flawlessly otoh. Apparently X still works correctly with linear framebuffers, so might just be an issue with the initial modeset. It's unclear whether this just borked wm setup from our side or a hw restriction, but just disabling gets things going. Note that this regression was only brought to light with commit 3f2dc5ac05714711fc14f2bf0ee5e42d5c08c581 Author: Ville Syrjälä Date: Fri Jan 10 14:06:47 2014 +0200 drm/i915: Fix 915GM self-refresh enable/disable before that self-refresh for i915GM didn't work at all. Kudos to Ville for spotting a little bug in the original patch I've attached to the bug. Cc: Ville Syrjälä Cc: Chris Wilson Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76103 Tested-by: Krzysztof Mazur Cc: Krzysztof Mazur Cc: stable@vger.kernel.org Reviewed-by: Ville Syrjälä Signed-off-by: Daniel Vetter [Jani: rebase on top of drm-next with primary plane support.] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_pm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5874716774a7eb..19e94c3edc1957 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -1545,6 +1545,16 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); + if (IS_I915GM(dev) && enabled) { + struct intel_framebuffer *fb; + + fb = to_intel_framebuffer(enabled->primary->fb); + + /* self-refresh seems busted with untiled */ + if (fb->obj->tiling_mode == I915_TILING_NONE) + enabled = NULL; + } + /* * Overlay gets an aggressive default since video jitter is bad. */ From bf3f043e7bc2581475040348580f4acc786842e7 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Tue, 18 Feb 2014 16:09:02 +0100 Subject: [PATCH 020/279] IB/qib: Use pci_enable_msix_range() instead of pci_enable_msix() As result of the deprecation of the MSI-X/MSI enablement functions pci_enable_msix() and pci_enable_msi_block(), all drivers using these two interfaces need to be updated to use the new pci_enable_msi_range() and pci_enable_msix_range() interfaces. Signed-off-by: Alexander Gordeev Acked-by: Mike Marciniszyn Signed-off-by: Roland Dreier --- drivers/infiniband/hw/qib/qib_pcie.c | 55 ++++++++++++++-------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/drivers/infiniband/hw/qib/qib_pcie.c b/drivers/infiniband/hw/qib/qib_pcie.c index c8d9c4ab142bf4..61a0046efb76ff 100644 --- a/drivers/infiniband/hw/qib/qib_pcie.c +++ b/drivers/infiniband/hw/qib/qib_pcie.c @@ -197,46 +197,47 @@ static void qib_msix_setup(struct qib_devdata *dd, int pos, u32 *msixcnt, struct qib_msix_entry *qib_msix_entry) { int ret; - u32 tabsize = 0; - u16 msix_flags; + int nvec = *msixcnt; struct msix_entry *msix_entry; int i; + ret = pci_msix_vec_count(dd->pcidev); + if (ret < 0) + goto do_intx; + + nvec = min(nvec, ret); + /* We can't pass qib_msix_entry array to qib_msix_setup * so use a dummy msix_entry array and copy the allocated * irq back to the qib_msix_entry array. */ - msix_entry = kmalloc(*msixcnt * sizeof(*msix_entry), GFP_KERNEL); - if (!msix_entry) { - ret = -ENOMEM; + msix_entry = kmalloc(nvec * sizeof(*msix_entry), GFP_KERNEL); + if (!msix_entry) goto do_intx; - } - for (i = 0; i < *msixcnt; i++) + + for (i = 0; i < nvec; i++) msix_entry[i] = qib_msix_entry[i].msix; - pci_read_config_word(dd->pcidev, pos + PCI_MSIX_FLAGS, &msix_flags); - tabsize = 1 + (msix_flags & PCI_MSIX_FLAGS_QSIZE); - if (tabsize > *msixcnt) - tabsize = *msixcnt; - ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); - if (ret > 0) { - tabsize = ret; - ret = pci_enable_msix(dd->pcidev, msix_entry, tabsize); - } -do_intx: - if (ret) { - qib_dev_err(dd, - "pci_enable_msix %d vectors failed: %d, falling back to INTx\n", - tabsize, ret); - tabsize = 0; - } - for (i = 0; i < tabsize; i++) + ret = pci_enable_msix_range(dd->pcidev, msix_entry, 1, nvec); + if (ret < 0) + goto free_msix_entry; + else + nvec = ret; + + for (i = 0; i < nvec; i++) qib_msix_entry[i].msix = msix_entry[i]; + kfree(msix_entry); - *msixcnt = tabsize; + *msixcnt = nvec; + return; - if (ret) - qib_enable_intx(dd->pcidev); +free_msix_entry: + kfree(msix_entry); +do_intx: + qib_dev_err(dd, "pci_enable_msix_range %d vectors failed: %d, " + "falling back to INTx\n", nvec, ret); + *msixcnt = 0; + qib_enable_intx(dd->pcidev); } /** From 9684c2ea6d1f5aab44119533530e4059b4c3e1ff Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Sun, 23 Feb 2014 07:57:05 +0100 Subject: [PATCH 021/279] IB/mthca: Use pci_enable_msix_exact() instead of pci_enable_msix() As result of the deprecation of the MSI-X/MSI enablement functions pci_enable_msix() and pci_enable_msi_block(), all drivers using these two interfaces need to be updated to use the new pci_enable_msi_range() or pci_enable_msi_exact() and pci_enable_msix_range() or pci_enable_msix_exact() interfaces. Signed-off-by: Alexander Gordeev Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mthca/mthca_main.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c index 87897b95666d22..ded76c101dde3d 100644 --- a/drivers/infiniband/hw/mthca/mthca_main.c +++ b/drivers/infiniband/hw/mthca/mthca_main.c @@ -858,13 +858,9 @@ static int mthca_enable_msi_x(struct mthca_dev *mdev) entries[1].entry = 1; entries[2].entry = 2; - err = pci_enable_msix(mdev->pdev, entries, ARRAY_SIZE(entries)); - if (err) { - if (err > 0) - mthca_info(mdev, "Only %d MSI-X vectors available, " - "not using MSI-X\n", err); + err = pci_enable_msix_exact(mdev->pdev, entries, ARRAY_SIZE(entries)); + if (err) return err; - } mdev->eq_table.eq[MTHCA_EQ_COMP ].msi_x_vector = entries[0].vector; mdev->eq_table.eq[MTHCA_EQ_ASYNC].msi_x_vector = entries[1].vector; From f360d88a2efddf2d2a2d01a8ac76fded34d624b4 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Wed, 2 Apr 2014 00:10:16 +0300 Subject: [PATCH 022/279] IB/mlx5: Add block multicast loopback support Add support for the block multicast loopback QP creation flag along the proper firmware API for that. Signed-off-by: Eli Cohen Signed-off-by: Or Gerlitz Signed-off-by: Roland Dreier --- drivers/infiniband/hw/mlx5/main.c | 2 ++ drivers/infiniband/hw/mlx5/qp.c | 12 ++++++++++++ include/linux/mlx5/device.h | 1 + include/linux/mlx5/qp.h | 1 + 4 files changed, 16 insertions(+) diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index fa6dc870adae54..364d4b6937f519 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -282,6 +282,8 @@ static int mlx5_ib_query_device(struct ib_device *ibdev, props->sig_guard_cap = IB_GUARD_T10DIF_CRC | IB_GUARD_T10DIF_CSUM; } + if (flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST) + props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; props->vendor_id = be32_to_cpup((__be32 *)(out_mad->data + 36)) & 0xffffff; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index ae788d27b93f51..dc930ed21eca66 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -807,6 +807,15 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, spin_lock_init(&qp->sq.lock); spin_lock_init(&qp->rq.lock); + if (init_attr->create_flags & IB_QP_CREATE_BLOCK_MULTICAST_LOOPBACK) { + if (!(dev->mdev.caps.flags & MLX5_DEV_CAP_FLAG_BLOCK_MCAST)) { + mlx5_ib_dbg(dev, "block multicast loopback isn't supported\n"); + return -EINVAL; + } else { + qp->flags |= MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK; + } + } + if (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR) qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE; @@ -878,6 +887,9 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd, if (qp->wq_sig) in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_ENABLE_SIG); + if (qp->flags & MLX5_IB_QP_BLOCK_MULTICAST_LOOPBACK) + in->ctx.flags_pd |= cpu_to_be32(MLX5_QP_BLOCK_MCAST); + if (qp->scat_cqe && is_connected(init_attr->qp_type)) { int rcqe_sz; int scqe_sz; diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h index 407bdb67fd4f80..3406cfb1267a9b 100644 --- a/include/linux/mlx5/device.h +++ b/include/linux/mlx5/device.h @@ -179,6 +179,7 @@ enum { MLX5_DEV_CAP_FLAG_BAD_QKEY_CNTR = 1LL << 9, MLX5_DEV_CAP_FLAG_APM = 1LL << 17, MLX5_DEV_CAP_FLAG_ATOMIC = 1LL << 18, + MLX5_DEV_CAP_FLAG_BLOCK_MCAST = 1LL << 23, MLX5_DEV_CAP_FLAG_ON_DMND_PG = 1LL << 24, MLX5_DEV_CAP_FLAG_CQ_MODER = 1LL << 29, MLX5_DEV_CAP_FLAG_RESIZE_CQ = 1LL << 30, diff --git a/include/linux/mlx5/qp.h b/include/linux/mlx5/qp.h index f829ad80ff28fc..9709b30e2d690d 100644 --- a/include/linux/mlx5/qp.h +++ b/include/linux/mlx5/qp.h @@ -146,6 +146,7 @@ enum { enum { MLX5_QP_LAT_SENSITIVE = 1 << 28, + MLX5_QP_BLOCK_MCAST = 1 << 30, MLX5_QP_ENABLE_SIG = 1 << 31, }; From 990baec022ccb97b6bb4185624f4fe7cd6150333 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Wed, 9 Apr 2014 00:08:01 +0200 Subject: [PATCH 023/279] mac80211: suppress BSS info change notifications for AP_VLAN Fixes warnings on tx power changes Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b055f6a55c68e2..4172d4253197a7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -199,7 +199,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, { struct ieee80211_local *local = sdata->local; - if (!changed) + if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN) return; drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed); From 764152ff66f4a8be1f9d7981e542ffdaa5bd7aff Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 10 Apr 2014 15:06:48 +0200 Subject: [PATCH 024/279] mac80211: exclude AP_VLAN interfaces from tx power calculation Their power value is initialized to zero. This patch fixes an issue where the configured power drops to the minimum value when AP_VLAN interfaces are created/removed. Cc: stable@vger.kernel.org Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg --- net/mac80211/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 4172d4253197a7..4c1bf61bc77868 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -148,6 +148,8 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) list_for_each_entry_rcu(sdata, &local->interfaces, list) { if (!rcu_access_pointer(sdata->vif.chanctx_conf)) continue; + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + continue; power = min(power, sdata->vif.bss_conf.txpower); } rcu_read_unlock(); From 60e69eed85bb7b5198ef70643b5895c26ad76ef7 Mon Sep 17 00:00:00 2001 From: Mike Galbraith Date: Mon, 7 Apr 2014 10:55:15 +0200 Subject: [PATCH 025/279] sched/numa: Fix task_numa_free() lockdep splat Sasha reported that lockdep claims that the following commit: made numa_group.lock interrupt unsafe: 156654f491dd ("sched/numa: Move task_numa_free() to __put_task_struct()") While I don't see how that could be, given the commit in question moved task_numa_free() from one irq enabled region to another, the below does make both gripes and lockups upon gripe with numa=fake=4 go away. Reported-by: Sasha Levin Fixes: 156654f491dd ("sched/numa: Move task_numa_free() to __put_task_struct()") Signed-off-by: Mike Galbraith Signed-off-by: Peter Zijlstra Cc: torvalds@linux-foundation.org Cc: mgorman@suse.com Cc: akpm@linux-foundation.org Cc: Dave Jones Link: http://lkml.kernel.org/r/1396860915.5170.5.camel@marge.simpson.net Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 13 +++++++------ kernel/sched/sched.h | 9 +++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 7e9bd0b1fa9ef1..4f14a656a7200e 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1497,7 +1497,7 @@ static void task_numa_placement(struct task_struct *p) /* If the task is part of a group prevent parallel updates to group stats */ if (p->numa_group) { group_lock = &p->numa_group->lock; - spin_lock(group_lock); + spin_lock_irq(group_lock); } /* Find the node with the highest number of faults */ @@ -1572,7 +1572,7 @@ static void task_numa_placement(struct task_struct *p) } } - spin_unlock(group_lock); + spin_unlock_irq(group_lock); } /* Preferred node as the node with the most faults */ @@ -1677,7 +1677,8 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags, if (!join) return; - double_lock(&my_grp->lock, &grp->lock); + BUG_ON(irqs_disabled()); + double_lock_irq(&my_grp->lock, &grp->lock); for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++) { my_grp->faults[i] -= p->numa_faults_memory[i]; @@ -1691,7 +1692,7 @@ static void task_numa_group(struct task_struct *p, int cpupid, int flags, grp->nr_tasks++; spin_unlock(&my_grp->lock); - spin_unlock(&grp->lock); + spin_unlock_irq(&grp->lock); rcu_assign_pointer(p->numa_group, grp); @@ -1710,14 +1711,14 @@ void task_numa_free(struct task_struct *p) void *numa_faults = p->numa_faults_memory; if (grp) { - spin_lock(&grp->lock); + spin_lock_irq(&grp->lock); for (i = 0; i < NR_NUMA_HINT_FAULT_STATS * nr_node_ids; i++) grp->faults[i] -= p->numa_faults_memory[i]; grp->total_faults -= p->total_numa_faults; list_del(&p->numa_entry); grp->nr_tasks--; - spin_unlock(&grp->lock); + spin_unlock_irq(&grp->lock); rcu_assign_pointer(p->numa_group, NULL); put_numa_group(grp); } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index c9007f28d3a222..456e492a3dca37 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1385,6 +1385,15 @@ static inline void double_lock(spinlock_t *l1, spinlock_t *l2) spin_lock_nested(l2, SINGLE_DEPTH_NESTING); } +static inline void double_lock_irq(spinlock_t *l1, spinlock_t *l2) +{ + if (l1 > l2) + swap(l1, l2); + + spin_lock_irq(l1); + spin_lock_nested(l2, SINGLE_DEPTH_NESTING); +} + static inline void double_raw_lock(raw_spinlock_t *l1, raw_spinlock_t *l2) { if (l1 > l2) From 39fbc9c8f6765959b55e0b127dd5c57df5a47d67 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 9 Apr 2014 11:22:06 +0300 Subject: [PATCH 026/279] drm/i915: check VBT for supported backlight type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The only supported types are none and PWM. Other values are obsolete or reserved, don't add them. Tested-by: Kamal Mostafa Tested-by: Martin Tested-by: jrg.otte@gmail.com Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_bios.c | 10 ++++++++++ drivers/gpu/drm/i915/intel_bios.h | 3 +++ 3 files changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0905cd915589a8..d24eba70ca9f10 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1308,6 +1308,7 @@ struct intel_vbt_data { struct { u16 pwm_freq_hz; + bool present; bool active_low_pwm; } backlight; diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4867f4cc0938cb..fa486c5fbb0250 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -287,6 +287,9 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) const struct bdb_lfp_backlight_data *backlight_data; const struct bdb_lfp_backlight_data_entry *entry; + /* Err to enabling backlight if no backlight block. */ + dev_priv->vbt.backlight.present = true; + backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT); if (!backlight_data) return; @@ -299,6 +302,13 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv, struct bdb_header *bdb) entry = &backlight_data->data[panel_type]; + dev_priv->vbt.backlight.present = entry->type == BDB_BACKLIGHT_TYPE_PWM; + if (!dev_priv->vbt.backlight.present) { + DRM_DEBUG_KMS("PWM backlight not present in VBT (type %u)\n", + entry->type); + return; + } + dev_priv->vbt.backlight.pwm_freq_hz = entry->pwm_freq_hz; dev_priv->vbt.backlight.active_low_pwm = entry->active_low_pwm; DRM_DEBUG_KMS("VBT backlight PWM modulation frequency %u Hz, " diff --git a/drivers/gpu/drm/i915/intel_bios.h b/drivers/gpu/drm/i915/intel_bios.h index 83b7629e4367bd..f27f7b282465aa 100644 --- a/drivers/gpu/drm/i915/intel_bios.h +++ b/drivers/gpu/drm/i915/intel_bios.h @@ -374,6 +374,9 @@ struct bdb_lvds_lfp_data { struct bdb_lvds_lfp_data_entry data[16]; } __packed; +#define BDB_BACKLIGHT_TYPE_NONE 0 +#define BDB_BACKLIGHT_TYPE_PWM 2 + struct bdb_lfp_backlight_data_entry { u8 type:2; u8 active_low_pwm:1; From c675949ec58ca50d5a3ae3c757892f1560f6e896 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 9 Apr 2014 11:31:37 +0300 Subject: [PATCH 027/279] drm/i915: do not setup backlight if not available according to VBT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some machines use an external EC for controlling the backlight. Info about this is present in the VBT. Do not setup native backlight control if no PWM backlight is available or supported according to VBT. The acpi_backlight interface appears to work for the EC control. In most cases there has been no harm done, but it looks like there are machines out there that have both an EC and our PWM line connected to the same wire. This, obviously, does not end well. This should fix the regression caused by commit bc0bb9fd1c7810407ab810d204bbaecb255fddde Author: Jani Nikula Date: Thu Nov 14 12:14:29 2013 +0200 drm/i915: remove QUIRK_NO_PCH_PWM_ENABLE AFAICT the quirk removed by the above commit effectively resulted in i915 not driving the backlight PWM output, thus not messing things up. Additionally this should fix the regression caused by commit fbc9fe1b4f222a7c575e3bd8e9defe59c6190a04 Author: Aaron Lu Date: Fri Oct 11 21:27:45 2013 +0800 ACPI / video: Do not register backlight if win8 and native interface exists which left some machines without a functioning backlight interface. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76276 Reference: https://bugzilla.kernel.org/show_bug.cgi?id=47941 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=62281 CC: Aaron Lu CC: Eric Griffith CC: Kent Baxley Tested-by: Kamal Mostafa Tested-by: Martin Tested-by: jrg.otte@gmail.com Reviewed-by: Ville Syrjälä Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/intel_panel.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index cb058408c70ea6..0eead16aeda740 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -1065,6 +1065,11 @@ int intel_panel_setup_backlight(struct drm_connector *connector) unsigned long flags; int ret; + if (!dev_priv->vbt.backlight.present) { + DRM_DEBUG_KMS("native backlight control not available per VBT\n"); + return 0; + } + /* set level and max in panel struct */ spin_lock_irqsave(&dev_priv->backlight_lock, flags); ret = dev_priv->display.setup_backlight(intel_connector); From 691e6415c891b8b2b082a120b896b443531c4d45 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 9 Apr 2014 09:07:36 +0100 Subject: [PATCH 028/279] drm/i915: Always use kref tracking for all contexts. If we always initialize kref for the context, even if we are using fake contexts for hangstats when there is no hw support, we can forgo the dance to dereference the ctx->obj and inspect whether we are permitted to use kref inside i915_gem_context_reference() and _unreference(). My ulterior motive here is to improve the debugging of a use-after-free of ctx->obj. This patch avoids the dereference here and instead forces the assertion checks associated with kref. v2: Refactor the fake contexts to being even more like the real contexts, so that there is much less duplicated and special case code. v3: Tweaks. v4: Tweaks, minor. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76671 Signed-off-by: Chris Wilson Tested-by: lu hua Cc: Ben Widawsky Cc: Mika Kuoppala Reviewed-by: Ben Widawsky [Jani: tiny change to backport to drm-intel-fixes.] Signed-off-by: Jani Nikula --- drivers/gpu/drm/i915/i915_drv.h | 8 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_context.c | 218 +++++++++------------ drivers/gpu/drm/i915/i915_gem_execbuffer.c | 2 +- 4 files changed, 93 insertions(+), 137 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d24eba70ca9f10..ec82f6bff1225d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2432,20 +2432,18 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file); int i915_gem_context_enable(struct drm_i915_private *dev_priv); void i915_gem_context_close(struct drm_device *dev, struct drm_file *file); int i915_switch_context(struct intel_ring_buffer *ring, - struct drm_file *file, struct i915_hw_context *to); + struct i915_hw_context *to); struct i915_hw_context * i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id); void i915_gem_context_free(struct kref *ctx_ref); static inline void i915_gem_context_reference(struct i915_hw_context *ctx) { - if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) - kref_get(&ctx->ref); + kref_get(&ctx->ref); } static inline void i915_gem_context_unreference(struct i915_hw_context *ctx) { - if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev)) - kref_put(&ctx->ref, i915_gem_context_free); + kref_put(&ctx->ref, i915_gem_context_free); } static inline bool i915_gem_context_is_default(const struct i915_hw_context *c) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6370a761d137d9..2871ce75f43864 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2790,7 +2790,7 @@ int i915_gpu_idle(struct drm_device *dev) /* Flush everything onto the inactive list. */ for_each_ring(ring, dev_priv, i) { - ret = i915_switch_context(ring, NULL, ring->default_context); + ret = i915_switch_context(ring, ring->default_context); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 6043062ffce734..d72db15afa02fd 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -96,9 +96,6 @@ #define GEN6_CONTEXT_ALIGN (64<<10) #define GEN7_CONTEXT_ALIGN 4096 -static int do_switch(struct intel_ring_buffer *ring, - struct i915_hw_context *to); - static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt) { struct drm_device *dev = ppgtt->base.dev; @@ -185,13 +182,15 @@ void i915_gem_context_free(struct kref *ctx_ref) typeof(*ctx), ref); struct i915_hw_ppgtt *ppgtt = NULL; - /* We refcount even the aliasing PPGTT to keep the code symmetric */ - if (USES_PPGTT(ctx->obj->base.dev)) - ppgtt = ctx_to_ppgtt(ctx); + if (ctx->obj) { + /* We refcount even the aliasing PPGTT to keep the code symmetric */ + if (USES_PPGTT(ctx->obj->base.dev)) + ppgtt = ctx_to_ppgtt(ctx); - /* XXX: Free up the object before tearing down the address space, in - * case we're bound in the PPGTT */ - drm_gem_object_unreference(&ctx->obj->base); + /* XXX: Free up the object before tearing down the address space, in + * case we're bound in the PPGTT */ + drm_gem_object_unreference(&ctx->obj->base); + } if (ppgtt) kref_put(&ppgtt->ref, ppgtt_release); @@ -232,32 +231,32 @@ __create_hw_context(struct drm_device *dev, return ERR_PTR(-ENOMEM); kref_init(&ctx->ref); - ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); - INIT_LIST_HEAD(&ctx->link); - if (ctx->obj == NULL) { - kfree(ctx); - DRM_DEBUG_DRIVER("Context object allocated failed\n"); - return ERR_PTR(-ENOMEM); - } + list_add_tail(&ctx->link, &dev_priv->context_list); - if (INTEL_INFO(dev)->gen >= 7) { - ret = i915_gem_object_set_cache_level(ctx->obj, - I915_CACHE_L3_LLC); - /* Failure shouldn't ever happen this early */ - if (WARN_ON(ret)) + if (dev_priv->hw_context_size) { + ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size); + if (ctx->obj == NULL) { + ret = -ENOMEM; goto err_out; - } + } - list_add_tail(&ctx->link, &dev_priv->context_list); + if (INTEL_INFO(dev)->gen >= 7) { + ret = i915_gem_object_set_cache_level(ctx->obj, + I915_CACHE_L3_LLC); + /* Failure shouldn't ever happen this early */ + if (WARN_ON(ret)) + goto err_out; + } + } /* Default context will never have a file_priv */ - if (file_priv == NULL) - return ctx; - - ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0, - GFP_KERNEL); - if (ret < 0) - goto err_out; + if (file_priv != NULL) { + ret = idr_alloc(&file_priv->context_idr, ctx, + DEFAULT_CONTEXT_ID, 0, GFP_KERNEL); + if (ret < 0) + goto err_out; + } else + ret = DEFAULT_CONTEXT_ID; ctx->file_priv = file_priv; ctx->id = ret; @@ -294,7 +293,7 @@ i915_gem_create_context(struct drm_device *dev, if (IS_ERR(ctx)) return ctx; - if (is_global_default_ctx) { + if (is_global_default_ctx && ctx->obj) { /* We may need to do things with the shrinker which * require us to immediately switch back to the default * context. This can cause a problem as pinning the @@ -342,7 +341,7 @@ i915_gem_create_context(struct drm_device *dev, return ctx; err_unpin: - if (is_global_default_ctx) + if (is_global_default_ctx && ctx->obj) i915_gem_object_ggtt_unpin(ctx->obj); err_destroy: i915_gem_context_unreference(ctx); @@ -352,32 +351,22 @@ i915_gem_create_context(struct drm_device *dev, void i915_gem_context_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; int i; - if (!HAS_HW_CONTEXTS(dev)) - return; - /* Prevent the hardware from restoring the last context (which hung) on * the next switch */ for (i = 0; i < I915_NUM_RINGS; i++) { - struct i915_hw_context *dctx; - if (!(INTEL_INFO(dev)->ring_mask & (1<ring[i]; + struct i915_hw_context *dctx = ring->default_context; /* Do a fake switch to the default context */ - ring = &dev_priv->ring[i]; - dctx = ring->default_context; - if (WARN_ON(!dctx)) + if (ring->last_context == dctx) continue; if (!ring->last_context) continue; - if (ring->last_context == dctx) - continue; - - if (i == RCS) { + if (dctx->obj && i == RCS) { WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj, get_context_alignment(dev), 0)); /* Fake a finish/inactive */ @@ -394,44 +383,35 @@ void i915_gem_context_reset(struct drm_device *dev) int i915_gem_context_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_ring_buffer *ring; + struct i915_hw_context *ctx; int i; - if (!HAS_HW_CONTEXTS(dev)) - return 0; - /* Init should only be called once per module load. Eventually the * restriction on the context_disabled check can be loosened. */ if (WARN_ON(dev_priv->ring[RCS].default_context)) return 0; - dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); - - if (dev_priv->hw_context_size > (1<<20)) { - DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n"); - return -E2BIG; + if (HAS_HW_CONTEXTS(dev)) { + dev_priv->hw_context_size = round_up(get_context_size(dev), 4096); + if (dev_priv->hw_context_size > (1<<20)) { + DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n", + dev_priv->hw_context_size); + dev_priv->hw_context_size = 0; + } } - dev_priv->ring[RCS].default_context = - i915_gem_create_context(dev, NULL, USES_PPGTT(dev)); - - if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) { - DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n", - PTR_ERR(dev_priv->ring[RCS].default_context)); - return PTR_ERR(dev_priv->ring[RCS].default_context); + ctx = i915_gem_create_context(dev, NULL, USES_PPGTT(dev)); + if (IS_ERR(ctx)) { + DRM_ERROR("Failed to create default global context (error %ld)\n", + PTR_ERR(ctx)); + return PTR_ERR(ctx); } - for (i = RCS + 1; i < I915_NUM_RINGS; i++) { - if (!(INTEL_INFO(dev)->ring_mask & (1<ring[i]; + /* NB: RCS will hold a ref for all rings */ + for (i = 0; i < I915_NUM_RINGS; i++) + dev_priv->ring[i].default_context = ctx; - /* NB: RCS will hold a ref for all rings */ - ring->default_context = dev_priv->ring[RCS].default_context; - } - - DRM_DEBUG_DRIVER("HW context support initialized\n"); + DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->hw_context_size ? "HW" : "fake"); return 0; } @@ -441,33 +421,30 @@ void i915_gem_context_fini(struct drm_device *dev) struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context; int i; - if (!HAS_HW_CONTEXTS(dev)) - return; - - /* The only known way to stop the gpu from accessing the hw context is - * to reset it. Do this as the very last operation to avoid confusing - * other code, leading to spurious errors. */ - intel_gpu_reset(dev); - - /* When default context is created and switched to, base object refcount - * will be 2 (+1 from object creation and +1 from do_switch()). - * i915_gem_context_fini() will be called after gpu_idle() has switched - * to default context. So we need to unreference the base object once - * to offset the do_switch part, so that i915_gem_context_unreference() - * can then free the base object correctly. */ - WARN_ON(!dev_priv->ring[RCS].last_context); - if (dev_priv->ring[RCS].last_context == dctx) { - /* Fake switch to NULL context */ - WARN_ON(dctx->obj->active); - i915_gem_object_ggtt_unpin(dctx->obj); - i915_gem_context_unreference(dctx); - dev_priv->ring[RCS].last_context = NULL; + if (dctx->obj) { + /* The only known way to stop the gpu from accessing the hw context is + * to reset it. Do this as the very last operation to avoid confusing + * other code, leading to spurious errors. */ + intel_gpu_reset(dev); + + /* When default context is created and switched to, base object refcount + * will be 2 (+1 from object creation and +1 from do_switch()). + * i915_gem_context_fini() will be called after gpu_idle() has switched + * to default context. So we need to unreference the base object once + * to offset the do_switch part, so that i915_gem_context_unreference() + * can then free the base object correctly. */ + WARN_ON(!dev_priv->ring[RCS].last_context); + if (dev_priv->ring[RCS].last_context == dctx) { + /* Fake switch to NULL context */ + WARN_ON(dctx->obj->active); + i915_gem_object_ggtt_unpin(dctx->obj); + i915_gem_context_unreference(dctx); + dev_priv->ring[RCS].last_context = NULL; + } } for (i = 0; i < I915_NUM_RINGS; i++) { struct intel_ring_buffer *ring = &dev_priv->ring[i]; - if (!(INTEL_INFO(dev)->ring_mask & (1<last_context) i915_gem_context_unreference(ring->last_context); @@ -478,7 +455,6 @@ void i915_gem_context_fini(struct drm_device *dev) i915_gem_object_ggtt_unpin(dctx->obj); i915_gem_context_unreference(dctx); - dev_priv->mm.aliasing_ppgtt = NULL; } int i915_gem_context_enable(struct drm_i915_private *dev_priv) @@ -486,9 +462,6 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) struct intel_ring_buffer *ring; int ret, i; - if (!HAS_HW_CONTEXTS(dev_priv->dev)) - return 0; - /* This is the only place the aliasing PPGTT gets enabled, which means * it has to happen before we bail on reset */ if (dev_priv->mm.aliasing_ppgtt) { @@ -503,7 +476,7 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) BUG_ON(!dev_priv->ring[RCS].default_context); for_each_ring(ring, dev_priv, i) { - ret = do_switch(ring, ring->default_context); + ret = i915_switch_context(ring, ring->default_context); if (ret) return ret; } @@ -526,19 +499,6 @@ static int context_idr_cleanup(int id, void *p, void *data) int i915_gem_context_open(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - struct drm_i915_private *dev_priv = dev->dev_private; - - if (!HAS_HW_CONTEXTS(dev)) { - /* Cheat for hang stats */ - file_priv->private_default_ctx = - kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL); - - if (file_priv->private_default_ctx == NULL) - return -ENOMEM; - - file_priv->private_default_ctx->vm = &dev_priv->gtt.base; - return 0; - } idr_init(&file_priv->context_idr); @@ -559,14 +519,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file) { struct drm_i915_file_private *file_priv = file->driver_priv; - if (!HAS_HW_CONTEXTS(dev)) { - kfree(file_priv->private_default_ctx); - return; - } - idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL); - i915_gem_context_unreference(file_priv->private_default_ctx); idr_destroy(&file_priv->context_idr); + + i915_gem_context_unreference(file_priv->private_default_ctx); } struct i915_hw_context * @@ -574,9 +530,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id) { struct i915_hw_context *ctx; - if (!HAS_HW_CONTEXTS(file_priv->dev_priv->dev)) - return file_priv->private_default_ctx; - ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id); if (!ctx) return ERR_PTR(-ENOENT); @@ -758,7 +711,6 @@ static int do_switch(struct intel_ring_buffer *ring, /** * i915_switch_context() - perform a GPU context switch. * @ring: ring for which we'll execute the context switch - * @file_priv: file_priv associated with the context, may be NULL * @to: the context to switch to * * The context life cycle is simple. The context refcount is incremented and @@ -767,24 +719,30 @@ static int do_switch(struct intel_ring_buffer *ring, * object while letting the normal object tracking destroy the backing BO. */ int i915_switch_context(struct intel_ring_buffer *ring, - struct drm_file *file, struct i915_hw_context *to) { struct drm_i915_private *dev_priv = ring->dev->dev_private; WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex)); - BUG_ON(file && to == NULL); - - /* We have the fake context */ - if (!HAS_HW_CONTEXTS(ring->dev)) { - ring->last_context = to; + if (to->obj == NULL) { /* We have the fake context */ + if (to != ring->last_context) { + i915_gem_context_reference(to); + if (ring->last_context) + i915_gem_context_unreference(ring->last_context); + ring->last_context = to; + } return 0; } return do_switch(ring, to); } +static bool hw_context_enabled(struct drm_device *dev) +{ + return to_i915(dev)->hw_context_size; +} + int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { @@ -793,7 +751,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, struct i915_hw_context *ctx; int ret; - if (!HAS_HW_CONTEXTS(dev)) + if (!hw_context_enabled(dev)) return -ENODEV; ret = i915_mutex_lock_interruptible(dev); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 7447160155a388..2c9d9cbaf65330 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -1221,7 +1221,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data, if (ret) goto err; - ret = i915_switch_context(ring, file, ctx); + ret = i915_switch_context(ring, ctx); if (ret) goto err; From fa658a98a2d08352c514758b3394caf91360aa44 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:25 -0500 Subject: [PATCH 029/279] RDMA/cxgb4: Use the BAR2/WC path for kernel QPs and T5 devices Signed-off-by: Steve Wise [ Fix cast from u64* to integer. - Roland ] Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/device.c | 41 ++++++++++++++---- drivers/infiniband/hw/cxgb4/iw_cxgb4.h | 2 + drivers/infiniband/hw/cxgb4/qp.c | 57 +++++++++++++++--------- drivers/infiniband/hw/cxgb4/t4.h | 60 ++++++++++++++++++++++++-- 4 files changed, 127 insertions(+), 33 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/device.c b/drivers/infiniband/hw/cxgb4/device.c index 9489a388376cee..f4fa50a609e21f 100644 --- a/drivers/infiniband/hw/cxgb4/device.c +++ b/drivers/infiniband/hw/cxgb4/device.c @@ -682,7 +682,10 @@ static void c4iw_dealloc(struct uld_ctx *ctx) idr_destroy(&ctx->dev->hwtid_idr); idr_destroy(&ctx->dev->stid_idr); idr_destroy(&ctx->dev->atid_idr); - iounmap(ctx->dev->rdev.oc_mw_kva); + if (ctx->dev->rdev.bar2_kva) + iounmap(ctx->dev->rdev.bar2_kva); + if (ctx->dev->rdev.oc_mw_kva) + iounmap(ctx->dev->rdev.oc_mw_kva); ib_dealloc_device(&ctx->dev->ibdev); ctx->dev = NULL; } @@ -722,11 +725,31 @@ static struct c4iw_dev *c4iw_alloc(const struct cxgb4_lld_info *infop) } devp->rdev.lldi = *infop; - devp->rdev.oc_mw_pa = pci_resource_start(devp->rdev.lldi.pdev, 2) + - (pci_resource_len(devp->rdev.lldi.pdev, 2) - - roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size)); - devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa, - devp->rdev.lldi.vr->ocq.size); + /* + * For T5 devices, we map all of BAR2 with WC. + * For T4 devices with onchip qp mem, we map only that part + * of BAR2 with WC. + */ + devp->rdev.bar2_pa = pci_resource_start(devp->rdev.lldi.pdev, 2); + if (is_t5(devp->rdev.lldi.adapter_type)) { + devp->rdev.bar2_kva = ioremap_wc(devp->rdev.bar2_pa, + pci_resource_len(devp->rdev.lldi.pdev, 2)); + if (!devp->rdev.bar2_kva) { + pr_err(MOD "Unable to ioremap BAR2\n"); + return ERR_PTR(-EINVAL); + } + } else if (ocqp_supported(infop)) { + devp->rdev.oc_mw_pa = + pci_resource_start(devp->rdev.lldi.pdev, 2) + + pci_resource_len(devp->rdev.lldi.pdev, 2) - + roundup_pow_of_two(devp->rdev.lldi.vr->ocq.size); + devp->rdev.oc_mw_kva = ioremap_wc(devp->rdev.oc_mw_pa, + devp->rdev.lldi.vr->ocq.size); + if (!devp->rdev.oc_mw_kva) { + pr_err(MOD "Unable to ioremap onchip mem\n"); + return ERR_PTR(-EINVAL); + } + } PDBG(KERN_INFO MOD "ocq memory: " "hw_start 0x%x size %u mw_pa 0x%lx mw_kva %p\n", @@ -1003,9 +1026,11 @@ static int enable_qp_db(int id, void *p, void *data) static void resume_rc_qp(struct c4iw_qp *qp) { spin_lock(&qp->lock); - t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc); + t4_ring_sq_db(&qp->wq, qp->wq.sq.wq_pidx_inc, + is_t5(qp->rhp->rdev.lldi.adapter_type), NULL); qp->wq.sq.wq_pidx_inc = 0; - t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc); + t4_ring_rq_db(&qp->wq, qp->wq.rq.wq_pidx_inc, + is_t5(qp->rhp->rdev.lldi.adapter_type), NULL); qp->wq.rq.wq_pidx_inc = 0; spin_unlock(&qp->lock); } diff --git a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h index e872203c542492..7b8c5806a09d84 100644 --- a/drivers/infiniband/hw/cxgb4/iw_cxgb4.h +++ b/drivers/infiniband/hw/cxgb4/iw_cxgb4.h @@ -149,6 +149,8 @@ struct c4iw_rdev { struct gen_pool *ocqp_pool; u32 flags; struct cxgb4_lld_info lldi; + unsigned long bar2_pa; + void __iomem *bar2_kva; unsigned long oc_mw_pa; void __iomem *oc_mw_kva; struct c4iw_stats stats; diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index cb76eb5eee1fd6..e2fcbf4814f279 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -212,13 +212,23 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, wq->db = rdev->lldi.db_reg; wq->gts = rdev->lldi.gts_reg; - if (user) { - wq->sq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) + - (wq->sq.qid << rdev->qpshift); - wq->sq.udb &= PAGE_MASK; - wq->rq.udb = (u64)pci_resource_start(rdev->lldi.pdev, 2) + - (wq->rq.qid << rdev->qpshift); - wq->rq.udb &= PAGE_MASK; + if (user || is_t5(rdev->lldi.adapter_type)) { + u32 off; + + off = (wq->sq.qid << rdev->qpshift) & PAGE_MASK; + if (user) { + wq->sq.udb = (u64 __iomem *)(rdev->bar2_pa + off); + } else { + off += 128 * (wq->sq.qid & rdev->qpmask) + 8; + wq->sq.udb = (u64 __iomem *)(rdev->bar2_kva + off); + } + off = (wq->rq.qid << rdev->qpshift) & PAGE_MASK; + if (user) { + wq->rq.udb = (u64 __iomem *)(rdev->bar2_pa + off); + } else { + off += 128 * (wq->rq.qid & rdev->qpmask) + 8; + wq->rq.udb = (u64 __iomem *)(rdev->bar2_kva + off); + } } wq->rdev = rdev; wq->rq.msn = 1; @@ -299,9 +309,10 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, if (ret) goto free_dma; - PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%llx rqudb 0x%llx\n", + PDBG("%s sqid 0x%x rqid 0x%x kdb 0x%p squdb 0x%lx rqudb 0x%lx\n", __func__, wq->sq.qid, wq->rq.qid, wq->db, - (unsigned long long)wq->sq.udb, (unsigned long long)wq->rq.udb); + (__force unsigned long) wq->sq.udb, + (__force unsigned long) wq->rq.udb); return 0; free_dma: @@ -650,9 +661,10 @@ static int ring_kernel_sq_db(struct c4iw_qp *qhp, u16 inc) spin_lock_irqsave(&qhp->rhp->lock, flags); spin_lock(&qhp->lock); - if (qhp->rhp->db_state == NORMAL) { - t4_ring_sq_db(&qhp->wq, inc); - } else { + if (qhp->rhp->db_state == NORMAL) + t4_ring_sq_db(&qhp->wq, inc, + is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL); + else { add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry); qhp->wq.sq.wq_pidx_inc += inc; } @@ -667,9 +679,10 @@ static int ring_kernel_rq_db(struct c4iw_qp *qhp, u16 inc) spin_lock_irqsave(&qhp->rhp->lock, flags); spin_lock(&qhp->lock); - if (qhp->rhp->db_state == NORMAL) { - t4_ring_rq_db(&qhp->wq, inc); - } else { + if (qhp->rhp->db_state == NORMAL) + t4_ring_rq_db(&qhp->wq, inc, + is_t5(qhp->rhp->rdev.lldi.adapter_type), NULL); + else { add_to_fc_list(&qhp->rhp->db_fc_list, &qhp->db_fc_entry); qhp->wq.rq.wq_pidx_inc += inc; } @@ -686,7 +699,7 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, enum fw_wr_opcodes fw_opcode = 0; enum fw_ri_wr_flags fw_flags; struct c4iw_qp *qhp; - union t4_wr *wqe; + union t4_wr *wqe = NULL; u32 num_wrs; struct t4_swsqe *swsqe; unsigned long flag; @@ -792,7 +805,8 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, idx += DIV_ROUND_UP(len16*16, T4_EQ_ENTRY_SIZE); } if (!qhp->rhp->rdev.status_page->db_off) { - t4_ring_sq_db(&qhp->wq, idx); + t4_ring_sq_db(&qhp->wq, idx, + is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe); spin_unlock_irqrestore(&qhp->lock, flag); } else { spin_unlock_irqrestore(&qhp->lock, flag); @@ -806,7 +820,7 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, { int err = 0; struct c4iw_qp *qhp; - union t4_recv_wr *wqe; + union t4_recv_wr *wqe = NULL; u32 num_wrs; u8 len16 = 0; unsigned long flag; @@ -858,7 +872,8 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, num_wrs--; } if (!qhp->rhp->rdev.status_page->db_off) { - t4_ring_rq_db(&qhp->wq, idx); + t4_ring_rq_db(&qhp->wq, idx, + is_t5(qhp->rhp->rdev.lldi.adapter_type), wqe); spin_unlock_irqrestore(&qhp->lock, flag); } else { spin_unlock_irqrestore(&qhp->lock, flag); @@ -1677,11 +1692,11 @@ struct ib_qp *c4iw_create_qp(struct ib_pd *pd, struct ib_qp_init_attr *attrs, mm2->len = PAGE_ALIGN(qhp->wq.rq.memsize); insert_mmap(ucontext, mm2); mm3->key = uresp.sq_db_gts_key; - mm3->addr = qhp->wq.sq.udb; + mm3->addr = (__force unsigned long) qhp->wq.sq.udb; mm3->len = PAGE_SIZE; insert_mmap(ucontext, mm3); mm4->key = uresp.rq_db_gts_key; - mm4->addr = qhp->wq.rq.udb; + mm4->addr = (__force unsigned long) qhp->wq.rq.udb; mm4->len = PAGE_SIZE; insert_mmap(ucontext, mm4); if (mm5) { diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index eeca8b1e63764c..931bfd105c4954 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h @@ -292,7 +292,7 @@ struct t4_sq { unsigned long phys_addr; struct t4_swsqe *sw_sq; struct t4_swsqe *oldest_read; - u64 udb; + u64 __iomem *udb; size_t memsize; u32 qid; u16 in_use; @@ -314,7 +314,7 @@ struct t4_rq { dma_addr_t dma_addr; DEFINE_DMA_UNMAP_ADDR(mapping); struct t4_swrqe *sw_rq; - u64 udb; + u64 __iomem *udb; size_t memsize; u32 qid; u32 msn; @@ -435,15 +435,67 @@ static inline u16 t4_sq_wq_size(struct t4_wq *wq) return wq->sq.size * T4_SQ_NUM_SLOTS; } -static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc) +/* This function copies 64 byte coalesced work request to memory + * mapped BAR2 space. For coalesced WRs, the SGE fetches data + * from the FIFO instead of from Host. + */ +static inline void pio_copy(u64 __iomem *dst, u64 *src) +{ + int count = 8; + + while (count) { + writeq(*src, dst); + src++; + dst++; + count--; + } +} + +static inline void t4_ring_sq_db(struct t4_wq *wq, u16 inc, u8 t5, + union t4_wr *wqe) { + + /* Flush host queue memory writes. */ wmb(); + if (t5) { + if (inc == 1 && wqe) { + PDBG("%s: WC wq->sq.pidx = %d\n", + __func__, wq->sq.pidx); + pio_copy(wq->sq.udb + 7, (void *)wqe); + } else { + PDBG("%s: DB wq->sq.pidx = %d\n", + __func__, wq->sq.pidx); + writel(PIDX_T5(inc), wq->sq.udb); + } + + /* Flush user doorbell area writes. */ + wmb(); + return; + } writel(QID(wq->sq.qid) | PIDX(inc), wq->db); } -static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc) +static inline void t4_ring_rq_db(struct t4_wq *wq, u16 inc, u8 t5, + union t4_recv_wr *wqe) { + + /* Flush host queue memory writes. */ wmb(); + if (t5) { + if (inc == 1 && wqe) { + PDBG("%s: WC wq->rq.pidx = %d\n", + __func__, wq->rq.pidx); + pio_copy(wq->rq.udb + 7, (void *)wqe); + } else { + PDBG("%s: DB wq->rq.pidx = %d\n", + __func__, wq->rq.pidx); + writel(PIDX_T5(inc), wq->rq.udb); + } + + /* Flush user doorbell area writes. */ + wmb(); + return; + } writel(QID(wq->rq.qid) | PIDX(inc), wq->db); } From b33bd0cbfa102b8f87702338aa72742fe3c7f220 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:25 -0500 Subject: [PATCH 030/279] RDMA/cxgb4: Endpoint timeout fixes 1) timedout endpoint processing can be starved. If there are continual CPL messages flowing into the driver, the endpoint timeout processing can be starved. This condition exposed the other bugs below. Solution: In process_work(), call process_timedout_eps() after each CPL is processed. 2) Connection events can be processed even though the endpoint is on the timeout list. If the endpoint is scheduled for timeout processing, then we must ignore MPA Start Requests and Replies. Solution: Change stop_ep_timer() to return 1 if the ep has already been queued for timeout processing. All the callers of stop_ep_timer() need to check this and act accordingly. There are just a few cases where the caller needs to do something different if stop_ep_timer() returns 1: 1) in process_mpa_reply(), ignore the reply and process_timeout() will abort the connection. 2) in process_mpa_request, ignore the request and process_timeout() will abort the connection. It is ok for callers of stop_ep_timer() to abort the connection since that will leave the state in ABORTING or DEAD, and process_timeout() now ignores timeouts when the ep is in these states. 3) Double insertion on the timeout list. Since the endpoint timers are used for connection setup and teardown, we need to guard against the possibility that an endpoint is already on the timeout list. This is a rare condition and only seen under heavy load and in the presense of the above 2 bugs. Solution: In ep_timeout(), don't queue the endpoint if it is already on the queue. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cm.c | 89 ++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 02436d5d0dab2a..185452abf32cf3 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -173,12 +173,15 @@ static void start_ep_timer(struct c4iw_ep *ep) add_timer(&ep->timer); } -static void stop_ep_timer(struct c4iw_ep *ep) +static int stop_ep_timer(struct c4iw_ep *ep) { PDBG("%s ep %p stopping\n", __func__, ep); del_timer_sync(&ep->timer); - if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) + if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { c4iw_put_ep(&ep->com); + return 0; + } + return 1; } static int c4iw_l2t_send(struct c4iw_rdev *rdev, struct sk_buff *skb, @@ -1165,12 +1168,11 @@ static void process_mpa_reply(struct c4iw_ep *ep, struct sk_buff *skb) PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); /* - * Stop mpa timer. If it expired, then the state has - * changed and we bail since ep_timeout already aborted - * the connection. + * Stop mpa timer. If it expired, then + * we ignore the MPA reply. process_timeout() + * will abort the connection. */ - stop_ep_timer(ep); - if (ep->com.state != MPA_REQ_SENT) + if (stop_ep_timer(ep)) return; /* @@ -1375,15 +1377,12 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid); - if (ep->com.state != MPA_REQ_WAIT) - return; - /* * If we get more than the supported amount of private data * then we must fail this connection. */ if (ep->mpa_pkt_len + skb->len > sizeof(ep->mpa_pkt)) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1413,13 +1412,13 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) if (mpa->revision > mpa_rev) { printk(KERN_ERR MOD "%s MPA version mismatch. Local = %d," " Received = %d\n", __func__, mpa_rev, mpa->revision); - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } if (memcmp(mpa->key, MPA_KEY_REQ, sizeof(mpa->key))) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1430,7 +1429,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) * Fail if there's too much private data. */ if (plen > MPA_MAX_PRIVATE_DATA) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1439,7 +1438,7 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) * If plen does not account for pkt size */ if (ep->mpa_pkt_len > (sizeof(*mpa) + plen)) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); abort_connection(ep, skb, GFP_KERNEL); return; } @@ -1496,18 +1495,24 @@ static void process_mpa_request(struct c4iw_ep *ep, struct sk_buff *skb) ep->mpa_attr.xmit_marker_enabled, ep->mpa_attr.version, ep->mpa_attr.p2p_type); - __state_set(&ep->com, MPA_REQ_RCVD); - stop_ep_timer(ep); - - /* drive upcall */ - mutex_lock(&ep->parent_ep->com.mutex); - if (ep->parent_ep->com.state != DEAD) { - if (connect_request_upcall(ep)) + /* + * If the endpoint timer already expired, then we ignore + * the start request. process_timeout() will abort + * the connection. + */ + if (!stop_ep_timer(ep)) { + __state_set(&ep->com, MPA_REQ_RCVD); + + /* drive upcall */ + mutex_lock(&ep->parent_ep->com.mutex); + if (ep->parent_ep->com.state != DEAD) { + if (connect_request_upcall(ep)) + abort_connection(ep, skb, GFP_KERNEL); + } else { abort_connection(ep, skb, GFP_KERNEL); - } else { - abort_connection(ep, skb, GFP_KERNEL); + } + mutex_unlock(&ep->parent_ep->com.mutex); } - mutex_unlock(&ep->parent_ep->com.mutex); return; } @@ -2265,7 +2270,7 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb) disconnect = 0; break; case MORIBUND: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); if (ep->com.cm_id && ep->com.qp) { attrs.next_state = C4IW_QP_STATE_IDLE; c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp, @@ -2325,10 +2330,10 @@ static int peer_abort(struct c4iw_dev *dev, struct sk_buff *skb) case CONNECTING: break; case MPA_REQ_WAIT: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); break; case MPA_REQ_SENT: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); if (mpa_rev == 1 || (mpa_rev == 2 && ep->tried_with_mpa_v1)) connect_reply_upcall(ep, -ECONNRESET); else { @@ -2433,7 +2438,7 @@ static int close_con_rpl(struct c4iw_dev *dev, struct sk_buff *skb) __state_set(&ep->com, MORIBUND); break; case MORIBUND: - stop_ep_timer(ep); + (void)stop_ep_timer(ep); if ((ep->com.cm_id) && (ep->com.qp)) { attrs.next_state = C4IW_QP_STATE_IDLE; c4iw_modify_qp(ep->com.qp->rhp, @@ -3028,7 +3033,7 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp) if (!test_and_set_bit(CLOSE_SENT, &ep->com.flags)) { close = 1; if (abrupt) { - stop_ep_timer(ep); + (void)stop_ep_timer(ep); ep->com.state = ABORTING; } else ep->com.state = MORIBUND; @@ -3462,6 +3467,16 @@ static void process_timeout(struct c4iw_ep *ep) __state_set(&ep->com, ABORTING); close_complete_upcall(ep, -ETIMEDOUT); break; + case ABORTING: + case DEAD: + + /* + * These states are expected if the ep timed out at the same + * time as another thread was calling stop_ep_timer(). + * So we silently do nothing for these states. + */ + abort = 0; + break; default: WARN(1, "%s unexpected state ep %p tid %u state %u\n", __func__, ep, ep->hwtid, ep->com.state); @@ -3483,6 +3498,8 @@ static void process_timedout_eps(void) tmp = timeout_list.next; list_del(tmp); + tmp->next = NULL; + tmp->prev = NULL; spin_unlock_irq(&timeout_lock); ep = list_entry(tmp, struct c4iw_ep, entry); process_timeout(ep); @@ -3499,6 +3516,7 @@ static void process_work(struct work_struct *work) unsigned int opcode; int ret; + process_timedout_eps(); while ((skb = skb_dequeue(&rxq))) { rpl = cplhdr(skb); dev = *((struct c4iw_dev **) (skb->cb + sizeof(void *))); @@ -3508,8 +3526,8 @@ static void process_work(struct work_struct *work) ret = work_handlers[opcode](dev, skb); if (!ret) kfree_skb(skb); + process_timedout_eps(); } - process_timedout_eps(); } static DECLARE_WORK(skb_work, process_work); @@ -3521,8 +3539,13 @@ static void ep_timeout(unsigned long arg) spin_lock(&timeout_lock); if (!test_and_set_bit(TIMEOUT, &ep->com.flags)) { - list_add_tail(&ep->entry, &timeout_list); - kickit = 1; + /* + * Only insert if it is not already on the list. + */ + if (!ep->entry.next) { + list_add_tail(&ep->entry, &timeout_list); + kickit = 1; + } } spin_unlock(&timeout_lock); if (kickit) From def4771f4bf428d39c7fe6006a9e1a20ee380d1e Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:26 -0500 Subject: [PATCH 031/279] RDMA/cxgb4: rmb() after reading valid gen bit Some HW platforms can reorder read operations, so we must rmb() after we see a valid gen bit in a CQE but before we read any other fields from the CQE. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/t4.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index 931bfd105c4954..1f329fac980198 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h @@ -620,6 +620,9 @@ static inline int t4_next_hw_cqe(struct t4_cq *cq, struct t4_cqe **cqe) printk(KERN_ERR MOD "cq overflow cqid %u\n", cq->cqid); BUG_ON(1); } else if (t4_valid_cqe(cq, &cq->queue[cq->cidx])) { + + /* Ensure CQE is flushed to memory */ + rmb(); *cqe = &cq->queue[cq->cidx]; ret = 0; } else From b4e2901c52cc79f287e2b25804e029880e5e4b07 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:26 -0500 Subject: [PATCH 032/279] RDMA/cxgb4: SQ flush fix There is a race when moving a QP from RTS->CLOSING where a SQ work request could be posted after the FW receives the RDMA_RI/FINI WR. The SQ work request will never get processed, and should be completed with FLUSHED status. Function c4iw_flush_sq(), however was dropping the oldest SQ work request when in CLOSING or IDLE states, instead of completing the pending work request. If that oldest pending work request was actually complete and has a CQE in the CQ, then when that CQE is proceessed in poll_cq, we'll BUG_ON() due to the inconsistent SQ/CQ state. This is a very small timing hole and has only been hit once so far. The fix is two-fold: 1) c4iw_flush_sq() MUST always flush all non-completed WRs with FLUSHED status regardless of the QP state. 2) In c4iw_modify_rc_qp(), always set the "in error" bit on the queue before moving the state out of RTS. This ensures that the state transition will not happen while another thread is in post_rc_send(), because set_state() and post_rc_send() both aquire the qp spinlock. Also, once we transition the state out of RTS, subsequent calls to post_rc_send() will fail because the "in error" bit is set. I don't think this fully closes the race where the FW can get a FINI followed a SQ work request being posted (because they are posted to differente EQs), but the #1 fix will handle the issue by flushing the SQ work request. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cq.c | 22 ++++++++-------------- drivers/infiniband/hw/cxgb4/qp.c | 6 +++--- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index ce468e54242881..e17b155b3758c4 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -235,27 +235,21 @@ int c4iw_flush_sq(struct c4iw_qp *qhp) struct t4_cq *cq = &chp->cq; int idx; struct t4_swsqe *swsqe; - int error = (qhp->attr.state != C4IW_QP_STATE_CLOSING && - qhp->attr.state != C4IW_QP_STATE_IDLE); if (wq->sq.flush_cidx == -1) wq->sq.flush_cidx = wq->sq.cidx; idx = wq->sq.flush_cidx; BUG_ON(idx >= wq->sq.size); while (idx != wq->sq.pidx) { - if (error) { - swsqe = &wq->sq.sw_sq[idx]; - BUG_ON(swsqe->flushed); - swsqe->flushed = 1; - insert_sq_cqe(wq, cq, swsqe); - if (wq->sq.oldest_read == swsqe) { - BUG_ON(swsqe->opcode != FW_RI_READ_REQ); - advance_oldest_read(wq); - } - flushed++; - } else { - t4_sq_consume(wq); + swsqe = &wq->sq.sw_sq[idx]; + BUG_ON(swsqe->flushed); + swsqe->flushed = 1; + insert_sq_cqe(wq, cq, swsqe); + if (wq->sq.oldest_read == swsqe) { + BUG_ON(swsqe->opcode != FW_RI_READ_REQ); + advance_oldest_read(wq); } + flushed++; if (++idx == wq->sq.size) idx = 0; } diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index e2fcbf4814f279..9b4a8b88908e51 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1367,6 +1367,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, switch (attrs->next_state) { case C4IW_QP_STATE_CLOSING: BUG_ON(atomic_read(&qhp->ep->com.kref.refcount) < 2); + t4_set_wq_in_error(&qhp->wq); set_state(qhp, C4IW_QP_STATE_CLOSING); ep = qhp->ep; if (!internal) { @@ -1374,16 +1375,15 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, disconnect = 1; c4iw_get_ep(&qhp->ep->com); } - t4_set_wq_in_error(&qhp->wq); ret = rdma_fini(rhp, qhp, ep); if (ret) goto err; break; case C4IW_QP_STATE_TERMINATE: + t4_set_wq_in_error(&qhp->wq); set_state(qhp, C4IW_QP_STATE_TERMINATE); qhp->attr.layer_etype = attrs->layer_etype; qhp->attr.ecode = attrs->ecode; - t4_set_wq_in_error(&qhp->wq); ep = qhp->ep; disconnect = 1; if (!internal) @@ -1396,8 +1396,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, c4iw_get_ep(&qhp->ep->com); break; case C4IW_QP_STATE_ERROR: - set_state(qhp, C4IW_QP_STATE_ERROR); t4_set_wq_in_error(&qhp->wq); + set_state(qhp, C4IW_QP_STATE_ERROR); if (!internal) { abort = 1; disconnect = 1; From a03d9f94cc54199bf681729b16ba649d7206369e Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:27 -0500 Subject: [PATCH 033/279] RDMA/cxgb4: Max fastreg depth depends on DSGL support The max depth of a fastreg mr depends on whether the device supports DSGL or not. So compute it dynamically based on the device support and the module use_dsgl option. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/provider.c | 2 +- drivers/infiniband/hw/cxgb4/qp.c | 3 ++- drivers/infiniband/hw/cxgb4/t4.h | 9 ++++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/provider.c b/drivers/infiniband/hw/cxgb4/provider.c index 79429256023a7e..a94a3e12c349b2 100644 --- a/drivers/infiniband/hw/cxgb4/provider.c +++ b/drivers/infiniband/hw/cxgb4/provider.c @@ -328,7 +328,7 @@ static int c4iw_query_device(struct ib_device *ibdev, props->max_mr = c4iw_num_stags(&dev->rdev); props->max_pd = T4_MAX_NUM_PD; props->local_ca_ack_delay = 0; - props->max_fast_reg_page_list_len = T4_MAX_FR_DEPTH; + props->max_fast_reg_page_list_len = t4_max_fr_depth(use_dsgl); return 0; } diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 9b4a8b88908e51..2c037e1746d3d3 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -566,7 +566,8 @@ static int build_fastreg(struct t4_sq *sq, union t4_wr *wqe, int pbllen = roundup(wr->wr.fast_reg.page_list_len * sizeof(u64), 32); int rem; - if (wr->wr.fast_reg.page_list_len > T4_MAX_FR_DEPTH) + if (wr->wr.fast_reg.page_list_len > + t4_max_fr_depth(use_dsgl)) return -EINVAL; wqe->fr.qpbinde_to_dcacpu = 0; diff --git a/drivers/infiniband/hw/cxgb4/t4.h b/drivers/infiniband/hw/cxgb4/t4.h index 1f329fac980198..2178f319841045 100644 --- a/drivers/infiniband/hw/cxgb4/t4.h +++ b/drivers/infiniband/hw/cxgb4/t4.h @@ -84,7 +84,14 @@ struct t4_status_page { sizeof(struct fw_ri_isgl)) / sizeof(struct fw_ri_sge)) #define T4_MAX_FR_IMMD ((T4_SQ_NUM_BYTES - sizeof(struct fw_ri_fr_nsmr_wr) - \ sizeof(struct fw_ri_immd)) & ~31UL) -#define T4_MAX_FR_DEPTH (1024 / sizeof(u64)) +#define T4_MAX_FR_IMMD_DEPTH (T4_MAX_FR_IMMD / sizeof(u64)) +#define T4_MAX_FR_DSGL 1024 +#define T4_MAX_FR_DSGL_DEPTH (T4_MAX_FR_DSGL / sizeof(u64)) + +static inline int t4_max_fr_depth(int use_dsgl) +{ + return use_dsgl ? T4_MAX_FR_DSGL_DEPTH : T4_MAX_FR_IMMD_DEPTH; +} #define T4_RQ_NUM_SLOTS 2 #define T4_RQ_NUM_BYTES (T4_EQ_ENTRY_SIZE * T4_RQ_NUM_SLOTS) From aec844df104f1e45cafd10628481f256908554c4 Mon Sep 17 00:00:00 2001 From: Hariprasad Shenai Date: Wed, 9 Apr 2014 09:38:27 -0500 Subject: [PATCH 034/279] RDMA/cxgb4: Use pr_warn_ratelimited Signed-off-by: Hariprasad Shenai Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/resource.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c index cdef4d7fb6d823..94b5fd9b937916 100644 --- a/drivers/infiniband/hw/cxgb4/resource.c +++ b/drivers/infiniband/hw/cxgb4/resource.c @@ -322,8 +322,8 @@ u32 c4iw_rqtpool_alloc(struct c4iw_rdev *rdev, int size) unsigned long addr = gen_pool_alloc(rdev->rqt_pool, size << 6); PDBG("%s addr 0x%x size %d\n", __func__, (u32)addr, size << 6); if (!addr) - printk_ratelimited(KERN_WARNING MOD "%s: Out of RQT memory\n", - pci_name(rdev->lldi.pdev)); + pr_warn_ratelimited(MOD "%s: Out of RQT memory\n", + pci_name(rdev->lldi.pdev)); mutex_lock(&rdev->stats.lock); if (addr) { rdev->stats.rqt.cur += roundup(size << 6, 1 << MIN_RQT_SHIFT); From c3f98fa29176753a759ade424f18b11f440b19f4 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:27 -0500 Subject: [PATCH 035/279] RDMA/cxgb4: Initialize reserved fields in a FW work request Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/qp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 2c037e1746d3d3..5a7d368aa47a1e 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -436,6 +436,8 @@ static int build_rdma_send(struct t4_sq *sq, union t4_wr *wqe, default: return -EINVAL; } + wqe->send.r3 = 0; + wqe->send.r4 = 0; plen = 0; if (wr->num_sge) { From 98a3e879907644c0b7e2f16436eb5cf24b9cd61f Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:28 -0500 Subject: [PATCH 036/279] RDMA/cxgb4: Add missing debug stats Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/mem.c | 6 +++++- drivers/infiniband/hw/cxgb4/resource.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/cxgb4/mem.c b/drivers/infiniband/hw/cxgb4/mem.c index f9ca072a99ed2d..ec7a2988a70344 100644 --- a/drivers/infiniband/hw/cxgb4/mem.c +++ b/drivers/infiniband/hw/cxgb4/mem.c @@ -259,8 +259,12 @@ static int write_tpt_entry(struct c4iw_rdev *rdev, u32 reset_tpt_entry, if ((!reset_tpt_entry) && (*stag == T4_STAG_UNSET)) { stag_idx = c4iw_get_resource(&rdev->resource.tpt_table); - if (!stag_idx) + if (!stag_idx) { + mutex_lock(&rdev->stats.lock); + rdev->stats.stag.fail++; + mutex_unlock(&rdev->stats.lock); return -ENOMEM; + } mutex_lock(&rdev->stats.lock); rdev->stats.stag.cur += 32; if (rdev->stats.stag.cur > rdev->stats.stag.max) diff --git a/drivers/infiniband/hw/cxgb4/resource.c b/drivers/infiniband/hw/cxgb4/resource.c index 94b5fd9b937916..67df71a7012ea3 100644 --- a/drivers/infiniband/hw/cxgb4/resource.c +++ b/drivers/infiniband/hw/cxgb4/resource.c @@ -179,8 +179,12 @@ u32 c4iw_get_qpid(struct c4iw_rdev *rdev, struct c4iw_dev_ucontext *uctx) kfree(entry); } else { qid = c4iw_get_resource(&rdev->resource.qid_table); - if (!qid) + if (!qid) { + mutex_lock(&rdev->stats.lock); + rdev->stats.qid.fail++; + mutex_unlock(&rdev->stats.lock); goto out; + } mutex_lock(&rdev->stats.lock); rdev->stats.qid.cur += rdev->qpmask + 1; mutex_unlock(&rdev->stats.lock); From 97df1c6736f660b58b408a60d0f7f65a64fb9d56 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:38:28 -0500 Subject: [PATCH 037/279] RDMA/cxgb4: Use uninitialized_var() Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/cq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/cq.c b/drivers/infiniband/hw/cxgb4/cq.c index e17b155b3758c4..cfaa56ada18927 100644 --- a/drivers/infiniband/hw/cxgb4/cq.c +++ b/drivers/infiniband/hw/cxgb4/cq.c @@ -672,7 +672,7 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe, static int c4iw_poll_cq_one(struct c4iw_cq *chp, struct ib_wc *wc) { struct c4iw_qp *qhp = NULL; - struct t4_cqe cqe = {0, 0}, *rd_cqe; + struct t4_cqe uninitialized_var(cqe), *rd_cqe; struct t4_wq *wq; u32 credit = 0; u8 cqe_flushed; From 1d1ca9b4fdde07325d263f7a75379527b1281f52 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Wed, 9 Apr 2014 09:40:37 -0500 Subject: [PATCH 038/279] RDMA/cxgb4: Fix over-dereference when terminating Need to get the endpoint reference before calling rdma_fini(), which might fail causing us to not get the reference. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb4/qp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 5a7d368aa47a1e..7b5114cb486f64 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -1389,6 +1389,7 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, qhp->attr.ecode = attrs->ecode; ep = qhp->ep; disconnect = 1; + c4iw_get_ep(&qhp->ep->com); if (!internal) terminate = 1; else { @@ -1396,7 +1397,6 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp, if (ret) goto err; } - c4iw_get_ep(&qhp->ep->com); break; case C4IW_QP_STATE_ERROR: t4_set_wq_in_error(&qhp->wq); From 0229cdafb6f67064a217591d48b0f6abf14e8385 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 19 Mar 2014 18:36:39 +0100 Subject: [PATCH 039/279] iwlwifi: mvm: delay enabling smart FIFO until after beacon RX If we have no beacon data before association, delay smart FIFO enablement until after we have this data. Not doing so can cause association failures in extremely silent environments (usually only a shielded box/room) as beacon RX is not sent to the host immediately, and then the association time event ends without the host receiving any beacon even though it was on the air - it's just stuck on the FIFO. Cc: [3.14] Fixes: 1f3b0ff8ecce ("iwlwifi: mvm: Add Smart FIFO support") Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/mac80211.c | 1 + drivers/net/wireless/iwlwifi/mvm/sf.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 4dd9ff43b8b68e..f0cebf12c7b841 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -1332,6 +1332,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, */ iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); + iwl_mvm_sf_update(mvm, vif, false); WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC)); } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) { diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 8401627c003098..88809b2d165445 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c @@ -274,7 +274,8 @@ int iwl_mvm_sf_update(struct iwl_mvm *mvm, struct ieee80211_vif *changed_vif, return -EINVAL; if (changed_vif->type != NL80211_IFTYPE_STATION) { new_state = SF_UNINIT; - } else if (changed_vif->bss_conf.assoc) { + } else if (changed_vif->bss_conf.assoc && + changed_vif->bss_conf.dtim_period) { mvmvif = iwl_mvm_vif_from_mac80211(changed_vif); sta_id = mvmvif->ap_sta_id; new_state = SF_FULL_ON; From d9088f60425e0acd8a8f05fdfcfdd288d3258641 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Tue, 25 Mar 2014 10:25:44 +0200 Subject: [PATCH 040/279] iwlwifi: mvm: rs: fix mimo delimiter in LQ cmd mimo_delim was always set to 0 instead of pointing to the first SISO entry after MIMO rates. This can cause keep transmitting in MIMO even when we shouldn't. For example when the peer is requesting static SMPS. Cc: [3.14] Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 568abd61b14fb5..dd13629d0187a8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -2547,6 +2547,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, if (is_siso(&rate)) { num_rates = RS_SECONDARY_SISO_NUM_RATES; num_retries = RS_SECONDARY_SISO_RETRIES; + lq_cmd->mimo_delim = index; } else if (is_legacy(&rate)) { num_rates = RS_SECONDARY_LEGACY_NUM_RATES; num_retries = RS_LEGACY_RETRIES_PER_RATE; From fff47eb05a287e1a47836126573a750ff9ed22dd Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 2 Apr 2014 15:29:07 +0300 Subject: [PATCH 041/279] iwlwifi: mvm: BT Coex - send the new LUT upon antenna coupling change I forgot to send the new Look Up Table to the firmware and I also forgot to free the command which is kzalloc'ed. This code is relevant for 7265 device only. Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/coex.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 685f7e8e6943b9..f9c7b302e3dfea 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c @@ -1262,6 +1262,7 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); u32 ant_isolation = le32_to_cpup((void *)pkt->data); u8 __maybe_unused lower_bound, upper_bound; + int ret; u8 lut; struct iwl_bt_coex_cmd *bt_cmd; @@ -1318,5 +1319,8 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm, memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20, sizeof(bt_cmd->bt4_corun_lut40)); - return 0; + ret = iwl_mvm_send_cmd(mvm, &cmd); + + kfree(bt_cmd); + return ret; } From 80f2679e589503bd6cbaaa1f9c1cd9dd7dfae032 Mon Sep 17 00:00:00 2001 From: Oren Givon Date: Wed, 2 Apr 2014 14:04:20 +0300 Subject: [PATCH 042/279] iwlwifi: add new 7265 HW IDs Add 2 new HW IDs for the 7265 series. Cc: [3.13+] Signed-off-by: Oren Givon Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/pcie/drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index edb015c9904931..3d1d57f9f5bc53 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -373,12 +373,14 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = { {IWL_PCI_DEVICE(0x095A, 0x500A, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5200, iwl7265_2n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5002, iwl7265_n_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x5102, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)}, From 431031851ea72a25abb9ad4df56a0f3b997e3026 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Wed, 9 Apr 2014 19:27:25 +0300 Subject: [PATCH 043/279] iwlwifi: 7000: bump API to 9 This will allow to load the new firmware. Cc: [3.14] Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-7000.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 003a546571d477..8425130273f60a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -67,8 +67,8 @@ #include "iwl-agn-hw.h" /* Highest firmware API version supported */ -#define IWL7260_UCODE_API_MAX 8 -#define IWL3160_UCODE_API_MAX 8 +#define IWL7260_UCODE_API_MAX 9 +#define IWL3160_UCODE_API_MAX 9 /* Oldest version we won't warn about */ #define IWL7260_UCODE_API_OK 8 From adeb25905c644350baf1f446bcd856517e58060e Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 9 Apr 2014 10:20:39 +0800 Subject: [PATCH 044/279] iommu/vt-d: fix memory leakage caused by commit ea8ea46 Commit ea8ea46 "iommu/vt-d: Clean up and fix page table clear/free behaviour" introduces possible leakage of DMA page tables due to: for (pte = page_address(pg); !first_pte_in_page(pte); pte++) { if (dma_pte_present(pte) && !dma_pte_superpage(pte)) freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist); } For the first pte in a page, first_pte_in_page(pte) will always be true, thus dma_pte_list_pagetables() will never be called and leak DMA page tables if level is bigger than 1. Signed-off-by: Jiang Liu Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 69fa7da5e48beb..13dc2318e17a3a 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1009,11 +1009,13 @@ static struct page *dma_pte_list_pagetables(struct dmar_domain *domain, if (level == 1) return freelist; - for (pte = page_address(pg); !first_pte_in_page(pte); pte++) { + pte = page_address(pg); + do { if (dma_pte_present(pte) && !dma_pte_superpage(pte)) freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist); - } + pte++; + } while (!first_pte_in_page(pte)); return freelist; } From 0ef36bd2b37815719e31a72d2beecc28ca8ecd26 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Wed, 9 Apr 2014 19:49:28 +0200 Subject: [PATCH 045/279] parisc: change value of SHMLBA from 0x00400000 to PAGE_SIZE On parisc, SHMLBA was defined to 0x00400000 (4MB) to reflect that we need to take care of our caches for shared mappings. But actually, we can map a file at any multiple address of PAGE_SIZE, so let us correct that now with a value of PAGE_SIZE for SHMLBA. Instead we now take care of this cache colouring via the constant SHM_COLOUR while we map shared pages. Signed-off-by: Helge Deller CC: Jeroen Roovers CC: John David Anglin CC: Carlos O'Donell Cc: stable@kernel.org [3.13+] --- arch/parisc/include/asm/shmparam.h | 5 ++--- arch/parisc/kernel/cache.c | 3 ++- arch/parisc/kernel/sys_parisc.c | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/arch/parisc/include/asm/shmparam.h b/arch/parisc/include/asm/shmparam.h index 628ddc22faa892..afe1300ab667fa 100644 --- a/arch/parisc/include/asm/shmparam.h +++ b/arch/parisc/include/asm/shmparam.h @@ -1,8 +1,7 @@ #ifndef _ASMPARISC_SHMPARAM_H #define _ASMPARISC_SHMPARAM_H -#define __ARCH_FORCE_SHMLBA 1 - -#define SHMLBA 0x00400000 /* attach addr needs to be 4 Mb aligned */ +#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */ +#define SHM_COLOUR 0x00400000 /* shared mappings colouring */ #endif /* _ASMPARISC_SHMPARAM_H */ diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index a6ffc775a9f810..f6448c7c62b51f 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -323,7 +323,8 @@ void flush_dcache_page(struct page *page) * specifically accesses it, of course) */ flush_tlb_page(mpnt, addr); - if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) { + if (old_addr == 0 || (old_addr & (SHM_COLOUR - 1)) + != (addr & (SHM_COLOUR - 1))) { __flush_cache_page(mpnt, addr, page_to_phys(page)); if (old_addr) printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? (char *)mpnt->vm_file->f_path.dentry->d_name.name : "(null)"); diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index b7cadc4a06cdf4..31ffa9b5532216 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -45,7 +45,7 @@ static int get_offset(unsigned int last_mmap) { - return (last_mmap & (SHMLBA-1)) >> PAGE_SHIFT; + return (last_mmap & (SHM_COLOUR-1)) >> PAGE_SHIFT; } static unsigned long shared_align_offset(unsigned int last_mmap, @@ -57,8 +57,8 @@ static unsigned long shared_align_offset(unsigned int last_mmap, static inline unsigned long COLOR_ALIGN(unsigned long addr, unsigned int last_mmap, unsigned long pgoff) { - unsigned long base = (addr+SHMLBA-1) & ~(SHMLBA-1); - unsigned long off = (SHMLBA-1) & + unsigned long base = (addr+SHM_COLOUR-1) & ~(SHM_COLOUR-1); + unsigned long off = (SHM_COLOUR-1) & (shared_align_offset(last_mmap, pgoff) << PAGE_SHIFT); return base + off; @@ -101,7 +101,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, if (flags & MAP_FIXED) { if ((flags & MAP_SHARED) && last_mmap && (addr - shared_align_offset(last_mmap, pgoff)) - & (SHMLBA - 1)) + & (SHM_COLOUR - 1)) return -EINVAL; goto found_addr; } @@ -122,7 +122,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, info.length = len; info.low_limit = mm->mmap_legacy_base; info.high_limit = mmap_upper_limit(); - info.align_mask = last_mmap ? (PAGE_MASK & (SHMLBA - 1)) : 0; + info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0; info.align_offset = shared_align_offset(last_mmap, pgoff); addr = vm_unmapped_area(&info); @@ -161,7 +161,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, if (flags & MAP_FIXED) { if ((flags & MAP_SHARED) && last_mmap && (addr - shared_align_offset(last_mmap, pgoff)) - & (SHMLBA - 1)) + & (SHM_COLOUR - 1)) return -EINVAL; goto found_addr; } @@ -182,7 +182,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, info.length = len; info.low_limit = PAGE_SIZE; info.high_limit = mm->mmap_base; - info.align_mask = last_mmap ? (PAGE_MASK & (SHMLBA - 1)) : 0; + info.align_mask = last_mmap ? (PAGE_MASK & (SHM_COLOUR - 1)) : 0; info.align_offset = shared_align_offset(last_mmap, pgoff); addr = vm_unmapped_area(&info); if (!(addr & ~PAGE_MASK)) From ab3e55b119c9653b19ea4edffb86f04db867ac98 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 13 Apr 2014 00:03:55 +0200 Subject: [PATCH 046/279] parisc: fix epoll_pwait syscall on compat kernel This bug was detected with the libio-epoll-perl debian package where the test case IO-Ppoll-compat.t failed. Signed-off-by: Helge Deller CC: stable@kernel.org # 3.0+ --- arch/parisc/kernel/syscall_table.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S index 80e5dd248934e2..83ead0ea127d23 100644 --- a/arch/parisc/kernel/syscall_table.S +++ b/arch/parisc/kernel/syscall_table.S @@ -392,7 +392,7 @@ ENTRY_COMP(vmsplice) ENTRY_COMP(move_pages) /* 295 */ ENTRY_SAME(getcpu) - ENTRY_SAME(epoll_pwait) + ENTRY_COMP(epoll_pwait) ENTRY_COMP(statfs64) ENTRY_COMP(fstatfs64) ENTRY_COMP(kexec_load) /* 300 */ From 08a732f4e4a842f0101e5ea03d79e9d613ffadbe Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Mon, 24 Mar 2014 22:17:15 +0200 Subject: [PATCH 047/279] iwlwifi: add MODULE_FIRMWARE for 7265 It was missing. Cc: [3.13+] Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/iwl-7000.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index 8425130273f60a..4c2d4ef28b220c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -244,3 +244,4 @@ const struct iwl_cfg iwl7265_n_cfg = { MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); +MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); From 198266a3c110e8a68895a24e937003f5da0c5f60 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Mon, 31 Mar 2014 22:37:39 +0300 Subject: [PATCH 048/279] iwlwifi: mvm: rs: use correct max expected throughput figures The selection of the max expected throughput for a column didn't take into account the maximal allowed rate for the current peer. This can cause unnecessary switches during the search cycle to columns which have no chance of beating the current throughput. Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 55 ++++++++++++++++++++------- drivers/net/wireless/iwlwifi/mvm/rs.h | 12 ++++-- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index dd13629d0187a8..cd32ad54384e52 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1186,9 +1186,26 @@ static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy, lq_sta->visited_columns = 0; } +static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta, + const struct rs_tx_column *column) +{ + switch (column->mode) { + case RS_LEGACY: + return lq_sta->max_legacy_rate_idx; + case RS_SISO: + return lq_sta->max_siso_rate_idx; + case RS_MIMO2: + return lq_sta->max_mimo2_rate_idx; + default: + WARN_ON_ONCE(1); + } + + return lq_sta->max_legacy_rate_idx; +} + static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta, - const struct rs_tx_column *column, - u32 bw) + const struct rs_tx_column *column, + u32 bw) { /* Used to choose among HT tables */ const u16 (*ht_tbl_pointer)[IWL_RATE_COUNT]; @@ -1485,14 +1502,14 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, struct ieee80211_sta *sta, struct iwl_scale_tbl_info *tbl) { - int i, j, n; + int i, j, max_rate; enum rs_column next_col_id; const struct rs_tx_column *curr_col = &rs_tx_columns[tbl->column]; const struct rs_tx_column *next_col; allow_column_func_t allow_func; u8 valid_ants = mvm->fw->valid_tx_ant; const u16 *expected_tpt_tbl; - s32 tpt, max_expected_tpt; + u16 tpt, max_expected_tpt; for (i = 0; i < MAX_NEXT_COLUMNS; i++) { next_col_id = curr_col->next_columns[i]; @@ -1535,11 +1552,11 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, if (WARN_ON_ONCE(!expected_tpt_tbl)) continue; - max_expected_tpt = 0; - for (n = 0; n < IWL_RATE_COUNT; n++) - if (expected_tpt_tbl[n] > max_expected_tpt) - max_expected_tpt = expected_tpt_tbl[n]; + max_rate = rs_get_max_allowed_rate(lq_sta, next_col); + if (WARN_ON_ONCE(max_rate == IWL_RATE_INVALID)) + continue; + max_expected_tpt = expected_tpt_tbl[max_rate]; if (tpt >= max_expected_tpt) { IWL_DEBUG_RATE(mvm, "Skip column %d: can't beat current TPT. Max expected %d current %d\n", @@ -1547,14 +1564,15 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm, continue; } + IWL_DEBUG_RATE(mvm, + "Found potential column %d. Max expected %d current %d\n", + next_col_id, max_expected_tpt, tpt); break; } if (i == MAX_NEXT_COLUMNS) return RS_COLUMN_INVALID; - IWL_DEBUG_RATE(mvm, "Found potential column %d\n", next_col_id); - return next_col_id; } @@ -2388,11 +2406,22 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->is_vht = true; } - IWL_DEBUG_RATE(mvm, - "SISO-RATE=%X MIMO2-RATE=%X VHT=%d\n", + lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, + BITS_PER_LONG); + lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, + BITS_PER_LONG); + lq_sta->max_mimo2_rate_idx = find_last_bit(&lq_sta->active_mimo2_rate, + BITS_PER_LONG); + + IWL_DEBUG_RATE(mvm, "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d\n", + lq_sta->active_legacy_rate, lq_sta->active_siso_rate, lq_sta->active_mimo2_rate, lq_sta->is_vht); + IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", + lq_sta->max_legacy_rate_idx, + lq_sta->max_siso_rate_idx, + lq_sta->max_mimo2_rate_idx); /* These values will be overridden later */ lq_sta->lq.single_stream_ant_msk = @@ -2750,7 +2779,7 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, return -ENOMEM; desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); - desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", + desc += sprintf(buff+desc, "failed=%d success=%d rate=0%lX\n", lq_sta->total_failed, lq_sta->total_success, lq_sta->active_legacy_rate); desc += sprintf(buff+desc, "fixed rate 0x%X\n", diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 3332b396011e3c..9892d92d590188 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -314,9 +314,15 @@ struct iwl_lq_sta { enum ieee80211_band band; /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ - u16 active_legacy_rate; - u16 active_siso_rate; - u16 active_mimo2_rate; + unsigned long active_legacy_rate; + unsigned long active_siso_rate; + unsigned long active_mimo2_rate; + + /* Highest rate per Tx mode */ + u8 max_legacy_rate_idx; + u8 max_siso_rate_idx; + u8 max_mimo2_rate_idx; + s8 max_rate_idx; /* Max rate set by user */ u8 missed_rate_counter; From e53839eb9882c99d3781eab0fe1b2d4369a6a2cc Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sun, 6 Apr 2014 02:42:18 +0300 Subject: [PATCH 049/279] iwlwifi: mvm: rs: fix and cleanup rs_get_rate_action Change the down/upscale decision logic a bit to be based on different success ratio thresholds. This fixes the implementation compared to the rate scale algorithm which was planned to yield optimal results. Also fix a case where a lower rate wasn't explored despite being a potential for better throughput. While at it rewrite rs_get_rate_action to be more clear and clean. Cc: [3.14] Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 127 ++++++++++++-------------- drivers/net/wireless/iwlwifi/mvm/rs.h | 1 + 2 files changed, 60 insertions(+), 68 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index cd32ad54384e52..97b8fac214a1ac 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -1658,85 +1658,76 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, { enum rs_action action = RS_ACTION_STAY; - /* Too many failures, decrease rate */ if ((sr <= RS_SR_FORCE_DECREASE) || (current_tpt == 0)) { IWL_DEBUG_RATE(mvm, - "decrease rate because of low SR\n"); - action = RS_ACTION_DOWNSCALE; - /* No throughput measured yet for adjacent rates; try increase. */ - } else if ((low_tpt == IWL_INVALID_VALUE) && - (high_tpt == IWL_INVALID_VALUE)) { - if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) { - IWL_DEBUG_RATE(mvm, - "Good SR and no high rate measurement. " - "Increase rate\n"); - action = RS_ACTION_UPSCALE; - } else if (low != IWL_RATE_INVALID) { - IWL_DEBUG_RATE(mvm, - "Remain in current rate\n"); - action = RS_ACTION_STAY; - } + "Decrease rate because of low SR\n"); + return RS_ACTION_DOWNSCALE; } - /* Both adjacent throughputs are measured, but neither one has better - * throughput; we're using the best rate, don't change it! - */ - else if ((low_tpt != IWL_INVALID_VALUE) && - (high_tpt != IWL_INVALID_VALUE) && - (low_tpt < current_tpt) && - (high_tpt < current_tpt)) { + if ((low_tpt == IWL_INVALID_VALUE) && + (high_tpt == IWL_INVALID_VALUE) && + (high != IWL_RATE_INVALID)) { IWL_DEBUG_RATE(mvm, - "Both high and low are worse. " - "Maintain rate\n"); - action = RS_ACTION_STAY; + "No data about high/low rates. Increase rate\n"); + return RS_ACTION_UPSCALE; } - /* At least one adjacent rate's throughput is measured, - * and may have better performance. - */ - else { - /* Higher adjacent rate's throughput is measured */ - if (high_tpt != IWL_INVALID_VALUE) { - /* Higher rate has better throughput */ - if (high_tpt > current_tpt && - sr >= IWL_RATE_INCREASE_TH) { - IWL_DEBUG_RATE(mvm, - "Higher rate is better and good " - "SR. Increate rate\n"); - action = RS_ACTION_UPSCALE; - } else { - IWL_DEBUG_RATE(mvm, - "Higher rate isn't better OR " - "no good SR. Maintain rate\n"); - action = RS_ACTION_STAY; - } + if ((high_tpt == IWL_INVALID_VALUE) && + (high != IWL_RATE_INVALID) && + (low_tpt != IWL_INVALID_VALUE) && + (low_tpt < current_tpt)) { + IWL_DEBUG_RATE(mvm, + "No data about high rate and low rate is worse. Increase rate\n"); + return RS_ACTION_UPSCALE; + } - /* Lower adjacent rate's throughput is measured */ - } else if (low_tpt != IWL_INVALID_VALUE) { - /* Lower rate has better throughput */ - if (low_tpt > current_tpt) { - IWL_DEBUG_RATE(mvm, - "Lower rate is better. " - "Decrease rate\n"); - action = RS_ACTION_DOWNSCALE; - } else if (sr >= IWL_RATE_INCREASE_TH) { - IWL_DEBUG_RATE(mvm, - "Lower rate isn't better and " - "good SR. Increase rate\n"); - action = RS_ACTION_UPSCALE; - } - } + if ((high_tpt != IWL_INVALID_VALUE) && + (high_tpt > current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Higher rate is better. Increate rate\n"); + return RS_ACTION_UPSCALE; } - /* Sanity check; asked for decrease, but success rate or throughput - * has been good at old rate. Don't change it. - */ - if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID) && - ((sr > IWL_RATE_HIGH_TH) || - (current_tpt > (100 * tbl->expected_tpt[low])))) { + if ((low_tpt != IWL_INVALID_VALUE) && + (high_tpt != IWL_INVALID_VALUE) && + (low_tpt < current_tpt) && + (high_tpt < current_tpt)) { IWL_DEBUG_RATE(mvm, - "Sanity check failed. Maintain rate\n"); - action = RS_ACTION_STAY; + "Both high and low are worse. Maintain rate\n"); + return RS_ACTION_STAY; + } + + if ((low_tpt != IWL_INVALID_VALUE) && + (low_tpt > current_tpt)) { + IWL_DEBUG_RATE(mvm, + "Lower rate is better\n"); + action = RS_ACTION_DOWNSCALE; + goto out; + } + + if ((low_tpt == IWL_INVALID_VALUE) && + (low != IWL_RATE_INVALID)) { + IWL_DEBUG_RATE(mvm, + "No data about lower rate\n"); + action = RS_ACTION_DOWNSCALE; + goto out; + } + + IWL_DEBUG_RATE(mvm, "Maintain rate\n"); + +out: + if ((action == RS_ACTION_DOWNSCALE) && (low != IWL_RATE_INVALID)) { + if (sr >= RS_SR_NO_DECREASE) { + IWL_DEBUG_RATE(mvm, + "SR is above NO DECREASE. Avoid downscale\n"); + action = RS_ACTION_STAY; + } else if (current_tpt > (100 * tbl->expected_tpt[low])) { + IWL_DEBUG_RATE(mvm, + "Current TPT is higher than max expected in low rate. Avoid downscale\n"); + action = RS_ACTION_STAY; + } else { + IWL_DEBUG_RATE(mvm, "Decrease rate\n"); + } } return action; diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index 9892d92d590188..fbb476aadb220f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -156,6 +156,7 @@ enum { #define IWL_RATE_HIGH_TH 10880 /* 85% */ #define IWL_RATE_INCREASE_TH 6400 /* 50% */ #define RS_SR_FORCE_DECREASE 1920 /* 15% */ +#define RS_SR_NO_DECREASE 10880 /* 85% */ #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) From 87d5e4155c0088e6766b4f0193b63fa0eab71220 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sun, 6 Apr 2014 18:13:22 +0300 Subject: [PATCH 050/279] iwlwifi: mvm: rs: reinit rs if no tx for a long time After being idle for a long time (>5sec) the rs statistics will be stale so we prefer to reset rs and start from legacy rates again. This gives better results when the attenuation increased signficantly (e.g. we got further from the AP) and after a while we start Tx Note that the first Tx after the idle period will still go out in the old modulation and rate but this seemed a simpler approach compared to adding a timer or modifying mac80211 for this. The negative impact is negligble as we'll recover quickly. Cc: [3.14] Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 22 +++++++++++++++++++++- drivers/net/wireless/iwlwifi/mvm/rs.h | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 97b8fac214a1ac..0d03dcd2fc3dd6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -59,7 +59,7 @@ /* max allowed rate miss before sync LQ cmd */ #define IWL_MISSED_RATE_MAX 15 #define RS_STAY_IN_COLUMN_TIMEOUT (5*HZ) - +#define RS_IDLE_TIMEOUT (5*HZ) static u8 rs_ht_to_legacy[] = { [IWL_RATE_MCS_0_INDEX] = IWL_RATE_6M_INDEX, @@ -992,6 +992,13 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, return; } +#ifdef CPTCFG_MAC80211_DEBUGFS + /* Disable last tx check if we are debugging with fixed rate */ + if (lq_sta->dbg_fixed_rate) { + IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n"); + return; + } +#endif if (!ieee80211_is_data(hdr->frame_control) || info->flags & IEEE80211_TX_CTL_NO_ACK) return; @@ -1034,6 +1041,18 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband, mac_index++; } + if (time_after(jiffies, + (unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) { + int tid; + IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n"); + for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++) + ieee80211_stop_tx_ba_session(sta, tid); + + iwl_mvm_rs_rate_init(mvm, sta, sband->band, false); + return; + } + lq_sta->last_tx = jiffies; + /* Here we actually compare this rate to the latest LQ command */ if ((mac_index < 0) || (rate.sgi != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || @@ -2354,6 +2373,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]); lq_sta->flush_timer = 0; + lq_sta->last_tx = jiffies; IWL_DEBUG_RATE(mvm, "LQ: *** rate scale station global init for station %d ***\n", diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index fbb476aadb220f..0acfac96a56c6d 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h @@ -311,6 +311,7 @@ struct iwl_lq_sta { u32 visited_columns; /* Bitmask marking which Tx columns were * explored during a search cycle */ + u64 last_tx; bool is_vht; enum ieee80211_band band; From fd7dbee51b3d98402edb11fec0c93d96476e0ae1 Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sun, 6 Apr 2014 04:39:23 +0300 Subject: [PATCH 051/279] iwlwifi: mvm: rs: fallback to legacy Tx columns Allow switching back to legacy Tx columns so we'll stop doing HT/VHT in case we're far from the AP. Stop active aggregation when making a deciding to stay in a legacy column. Despite having low legacy rates in the LQ table lower entries it doesn't help much in case we're doing aggregations as the aggregation was being transmitted in the initial rate of the table. This should help traffic stalls when far from the AP. Cc: [3.14] Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 30 +++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 0d03dcd2fc3dd6..b007db9cf3aa92 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -142,7 +142,7 @@ enum rs_column_mode { RS_MIMO2, }; -#define MAX_NEXT_COLUMNS 5 +#define MAX_NEXT_COLUMNS 7 #define MAX_COLUMN_CHECKS 3 typedef bool (*allow_column_func_t) (struct iwl_mvm *mvm, @@ -214,6 +214,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, }, }, [RS_COLUMN_LEGACY_ANT_B] = { @@ -225,6 +227,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, }, }, [RS_COLUMN_SISO_ANT_A] = { @@ -236,6 +240,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_MIMO2_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, @@ -250,6 +256,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_MIMO2_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, @@ -265,6 +273,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, @@ -281,6 +291,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_MIMO2, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_siso_allow, @@ -296,6 +308,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_MIMO2_SGI, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, @@ -311,6 +325,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, RS_COLUMN_MIMO2, + RS_COLUMN_LEGACY_ANT_A, + RS_COLUMN_LEGACY_ANT_B, }, .checks = { rs_mimo_allow, @@ -2070,8 +2086,18 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, * stay with best antenna legacy modulation for a while * before next round of mode comparisons. */ tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); - if (is_legacy(&tbl1->rate) && !sta->ht_cap.ht_supported) { + if (is_legacy(&tbl1->rate)) { IWL_DEBUG_RATE(mvm, "LQ: STAY in legacy table\n"); + + if (tid != IWL_MAX_TID_COUNT) { + tid_data = &sta_priv->tid_data[tid]; + if (tid_data->state != IWL_AGG_OFF) { + IWL_DEBUG_RATE(mvm, + "Stop aggregation on tid %d\n", + tid); + ieee80211_stop_tx_ba_session(sta, tid); + } + } rs_set_stay_in_table(mvm, 1, lq_sta); } else { /* If we're in an HT mode, and all 3 mode switch actions From d8fff919ecd7820084675c2814913445e95640ac Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sun, 6 Apr 2014 05:27:36 +0300 Subject: [PATCH 052/279] iwlwifi: mvm: avoid searching unnecessary columns Don't search columns which are unlikely to succeed as previous columns searched with less aggressive modulation failed. Cc: [3.14] Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index b007db9cf3aa92..5cab26ecc17ad9 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -212,8 +212,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_B, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, - RS_COLUMN_MIMO2, - RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, }, @@ -225,8 +225,8 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_SISO_ANT_A, RS_COLUMN_SISO_ANT_B, - RS_COLUMN_MIMO2, - RS_COLUMN_MIMO2_SGI, + RS_COLUMN_INVALID, + RS_COLUMN_INVALID, RS_COLUMN_INVALID, RS_COLUMN_INVALID, }, @@ -239,9 +239,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_A_SGI, RS_COLUMN_SISO_ANT_B_SGI, - RS_COLUMN_MIMO2_SGI, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, }, .checks = { rs_siso_allow, @@ -255,9 +255,9 @@ static const struct rs_tx_column rs_tx_columns[] = { RS_COLUMN_MIMO2, RS_COLUMN_SISO_ANT_B_SGI, RS_COLUMN_SISO_ANT_A_SGI, - RS_COLUMN_MIMO2_SGI, RS_COLUMN_LEGACY_ANT_A, RS_COLUMN_LEGACY_ANT_B, + RS_COLUMN_INVALID, }, .checks = { rs_siso_allow, From b804eeb6649d75caeccbeae9f5623fc7b8bdfdfa Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Sun, 6 Apr 2014 04:27:06 +0300 Subject: [PATCH 053/279] iwlwifi: mvm: rs: clear per rate stats when aggregation changes The per rate stats should be cleared when aggregation state changes to avoid making rate scale decisions based on throughput figures which were collected prior to the aggregation state change and are now stale. While at it make sure any clearing of the per rate stats will get logged. Cc: [3.14] Signed-off-by: Eyal Shapira Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/rs.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 5cab26ecc17ad9..9f52c5b3f0ec0e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c @@ -519,10 +519,12 @@ static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) window->average_tpt = IWL_INVALID_VALUE; } -static void rs_rate_scale_clear_tbl_windows(struct iwl_scale_tbl_info *tbl) +static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm, + struct iwl_scale_tbl_info *tbl) { int i; + IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&tbl->win[i]); } @@ -1490,7 +1492,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) IWL_DEBUG_RATE(mvm, "LQ: stay in table clear win\n"); - rs_rate_scale_clear_tbl_windows(tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); } } @@ -1498,8 +1500,7 @@ static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search) * bitmaps and stats in active table (this will become the new * "search" table). */ if (lq_sta->rs_state == RS_STATE_SEARCH_CYCLE_STARTED) { - IWL_DEBUG_RATE(mvm, "Clearing up window stats\n"); - rs_rate_scale_clear_tbl_windows(tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); } } } @@ -1836,6 +1837,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, "Aggregation changed: prev %d current %d. Update expected TPT table\n", prev_agg, lq_sta->is_agg); rs_set_expected_tpt_table(lq_sta, tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); } /* current tx rate */ @@ -2065,7 +2067,7 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm, if (lq_sta->search_better_tbl) { /* Access the "search" table, clear its history. */ tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - rs_rate_scale_clear_tbl_windows(tbl); + rs_rate_scale_clear_tbl_windows(mvm, tbl); /* Use new "search" start rate */ index = tbl->rate.index; @@ -2396,7 +2398,7 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, lq_sta->lq.sta_id = sta_priv->sta_id; for (j = 0; j < LQ_SIZE; j++) - rs_rate_scale_clear_tbl_windows(&lq_sta->lq_info[j]); + rs_rate_scale_clear_tbl_windows(mvm, &lq_sta->lq_info[j]); lq_sta->flush_timer = 0; lq_sta->last_tx = jiffies; From a6bc92803e7f765e02c923cf37c8e280e729642a Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 13 Apr 2014 15:51:41 +0300 Subject: [PATCH 054/279] iwlwifi: mvm: BT Coex - fix Look Up Table A few entries were wrong and this caused throughput issues. Cc: [3.13+] Fixes: dac94da8dba3 ("iwlwifi: mvm: new BT Coex API") Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/coex.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index f9c7b302e3dfea..fa858d548d13c0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c @@ -190,7 +190,7 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { cpu_to_le32(0xcc00aaaa), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xc0004000), - cpu_to_le32(0x00000000), + cpu_to_le32(0x00004000), cpu_to_le32(0xf0005000), cpu_to_le32(0xf0005000), }, @@ -213,16 +213,16 @@ static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = { /* Tx Tx disabled */ cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xaaaaaaaa), - cpu_to_le32(0xaaaaaaaa), + cpu_to_le32(0xeeaaaaaa), cpu_to_le32(0xaaaaaaaa), cpu_to_le32(0xcc00ff28), cpu_to_le32(0x0000aaaa), cpu_to_le32(0xcc00aaaa), cpu_to_le32(0x0000aaaa), - cpu_to_le32(0xC0004000), - cpu_to_le32(0xC0004000), - cpu_to_le32(0xF0005000), - cpu_to_le32(0xF0005000), + cpu_to_le32(0xc0004000), + cpu_to_le32(0xc0004000), + cpu_to_le32(0xf0005000), + cpu_to_le32(0xf0005000), }, }; From 5fc68a6cad658e45dca3e0a6607df3a8e5df4ef9 Mon Sep 17 00:00:00 2001 From: Sekhar Nori Date: Wed, 19 Mar 2014 11:25:50 +0530 Subject: [PATCH 055/279] dma: edma: fix incorrect SG list handling The code to handle any length SG lists calls edma_resume() even before edma_start() is called. This is incorrect because edma_resume() enables edma events on the channel after which CPU (in edma_start) cannot clear posted events by writing to ECR (per the EDMA user's guide). Because of this EDMA transfers fail to start if due to some reason there is a pending EDMA event registered even before EDMA transfers are started. This can happen if an EDMA event is a byproduct of device initialization. Fix this by calling edma_resume() only if it is not the first batch of MAX_NR_SG elements. Without this patch, MMC/SD fails to function on DA850 EVM with DMA. The behaviour is triggered by specific IP and this can explain why the issue was not reported before (example with MMC/SD on AM335x). Tested on DA850 EVM and AM335x EVM-SK using MMC/SD card. Cc: stable@vger.kernel.org # v3.12.x+ Cc: Joel Fernandes Acked-by: Joel Fernandes Tested-by: Jon Ringle Tested-by: Alexander Holler Reported-by: Jon Ringle Signed-off-by: Sekhar Nori Signed-off-by: Vinod Koul --- drivers/dma/edma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index cd04eb7b182e33..926360c2db6abc 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -182,11 +182,13 @@ static void edma_execute(struct edma_chan *echan) echan->ecc->dummy_slot); } - edma_resume(echan->ch_num); - if (edesc->processed <= MAX_NR_SG) { dev_dbg(dev, "first transfer starting %d\n", echan->ch_num); edma_start(echan->ch_num); + } else { + dev_dbg(dev, "chan: %d: completed %d elements, resuming\n", + echan->ch_num, edesc->processed); + edma_resume(echan->ch_num); } /* From 4ab9ed578e82851645f3dd69d36d91ae77564d6c Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 14 Apr 2014 18:11:58 +1000 Subject: [PATCH 056/279] xfs: kill buffers over failed write ranges properly When a write fails, if we don't clear the delalloc flags from the buffers over the failed range, they can persist beyond EOF and cause problems. writeback will see the pages in the page cache, see they are dirty and continually retry the write, assuming that the page beyond EOF is just racing with a truncate. The page will eventually be released due to some other operation (e.g. direct IO), and it will not pass through invalidation because it is dirty. Hence it will be released with buffer_delay set on it, and trigger warnings in xfs_vm_releasepage() and assert fail in xfs_file_aio_write_direct because invalidation failed and we didn't write the corect amount. This causes failures on block size < page size filesystems in fsx and fsstress workloads run by xfstests. Fix it by completely trashing any state on the buffer that could be used to imply that it contains valid data when the delalloc range over the buffer is punched out during the failed write handling. Signed-off-by: Dave Chinner Tested-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_aops.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 75df77d09f757d..282c726d04d070 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1566,6 +1566,16 @@ xfs_vm_write_failed( xfs_vm_kill_delalloc_range(inode, block_offset, block_offset + bh->b_size); + + /* + * This buffer does not contain data anymore. make sure anyone + * who finds it knows that for certain. + */ + clear_buffer_delay(bh); + clear_buffer_uptodate(bh); + clear_buffer_mapped(bh); + clear_buffer_new(bh); + clear_buffer_dirty(bh); } } From 72ab70a19b4ebb19dbe2a79faaa6a4ccead58e70 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 14 Apr 2014 18:13:29 +1000 Subject: [PATCH 057/279] xfs: write failure beyond EOF truncates too much data If we fail a write beyond EOF and have to handle it in xfs_vm_write_begin(), we truncate the inode back to the current inode size. This doesn't take into account the fact that we may have already made successful writes to the same page (in the case of block size < page size) and hence we can truncate the page cache away from blocks with valid data in them. If these blocks are delayed allocation blocks, we now have a mismatch between the page cache and the extent tree, and this will trigger - at minimum - a delayed block count mismatch assert when the inode is evicted from the cache. We can also trip over it when block mapping for direct IO - this is the most common symptom seen from fsx and fsstress when run from xfstests. Fix it by only truncating away the exact range we are updating state for in this write_begin call. Signed-off-by: Dave Chinner Tested-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_aops.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 282c726d04d070..5f296934879ff6 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1609,12 +1609,21 @@ xfs_vm_write_begin( status = __block_write_begin(page, pos, len, xfs_get_blocks); if (unlikely(status)) { struct inode *inode = mapping->host; + size_t isize = i_size_read(inode); xfs_vm_write_failed(inode, page, pos, len); unlock_page(page); - if (pos + len > i_size_read(inode)) - truncate_pagecache(inode, i_size_read(inode)); + /* + * If the write is beyond EOF, we only want to kill blocks + * allocated in this write, not blocks that were previously + * written successfully. + */ + if (pos + len > isize) { + ssize_t start = max_t(ssize_t, pos, isize); + + truncate_pagecache_range(inode, start, pos + len); + } page_cache_release(page); page = NULL; From aad3f3755e7f043789b772856d1a2935f2b41a4b Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 14 Apr 2014 18:14:11 +1000 Subject: [PATCH 058/279] xfs: xfs_vm_write_end truncates too much on failure Similar to the write_begin problem, xfs-vm_write_end will truncate back to the old EOF, potentially removing page cache from over the top of delalloc blocks with valid data in them. Fix this by truncating back to just the start of the failed write. Signed-off-by: Dave Chinner Tested-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_aops.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 5f296934879ff6..e0a793113ea9b6 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1634,9 +1634,12 @@ xfs_vm_write_begin( } /* - * On failure, we only need to kill delalloc blocks beyond EOF because they - * will never be written. For blocks within EOF, generic_write_end() zeros them - * so they are safe to leave alone and be written with all the other valid data. + * On failure, we only need to kill delalloc blocks beyond EOF in the range of + * this specific write because they will never be written. Previous writes + * beyond EOF where block allocation succeeded do not need to be trashed, so + * only new blocks from this write should be trashed. For blocks within + * EOF, generic_write_end() zeros them so they are safe to leave alone and be + * written with all the other valid data. */ STATIC int xfs_vm_write_end( @@ -1659,8 +1662,11 @@ xfs_vm_write_end( loff_t to = pos + len; if (to > isize) { - truncate_pagecache(inode, isize); + /* only kill blocks in this write beyond EOF */ + if (pos > isize) + isize = pos; xfs_vm_kill_delalloc_range(inode, isize, to); + truncate_pagecache_range(inode, isize, to); } } return ret; From 897b73b6a2ee5d3c06648b601beb1724f7fbd678 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Mon, 14 Apr 2014 18:15:11 +1000 Subject: [PATCH 059/279] xfs: zeroing space needs to punch delalloc blocks When we are zeroing space andit is covered by a delalloc range, we need to punch the delalloc range out before we truncate the page cache. Failing to do so leaves and inconsistency between the page cache and the extent tree, which we later trip over when doing direct IO over the same range. Signed-off-by: Dave Chinner Tested-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_bmap_util.c | 13 ++++++++++++- fs/xfs/xfs_trace.h | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 01f6a646caa121..296160b8e78c69 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1418,6 +1418,8 @@ xfs_zero_file_space( xfs_off_t end_boundary; int error; + trace_xfs_zero_file_space(ip); + granularity = max_t(uint, 1 << mp->m_sb.sb_blocklog, PAGE_CACHE_SIZE); /* @@ -1432,9 +1434,18 @@ xfs_zero_file_space( ASSERT(end_boundary <= offset + len); if (start_boundary < end_boundary - 1) { - /* punch out the page cache over the conversion range */ + /* + * punch out delayed allocation blocks and the page cache over + * the conversion range + */ + xfs_ilock(ip, XFS_ILOCK_EXCL); + error = xfs_bmap_punch_delalloc_range(ip, + XFS_B_TO_FSBT(mp, start_boundary), + XFS_B_TO_FSB(mp, end_boundary - start_boundary)); + xfs_iunlock(ip, XFS_ILOCK_EXCL); truncate_pagecache_range(VFS_I(ip), start_boundary, end_boundary - 1); + /* convert the blocks */ error = xfs_alloc_file_space(ip, start_boundary, end_boundary - start_boundary - 1, diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index a4ae41c179a8a6..65d8c793a25cb1 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -603,6 +603,7 @@ DEFINE_INODE_EVENT(xfs_readlink); DEFINE_INODE_EVENT(xfs_inactive_symlink); DEFINE_INODE_EVENT(xfs_alloc_file_space); DEFINE_INODE_EVENT(xfs_free_file_space); +DEFINE_INODE_EVENT(xfs_zero_file_space); DEFINE_INODE_EVENT(xfs_collapse_file_space); DEFINE_INODE_EVENT(xfs_readdir); #ifdef CONFIG_XFS_POSIX_ACL From 7c66593286bcd153e4868383e675673a27071bd5 Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Mon, 14 Apr 2014 15:09:44 +0800 Subject: [PATCH 060/279] ALSA: hda/realtek - Add support of ALC288 codec Signed-off-by: Kailang Yang Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 14ae979a92eac7..f7766febaebe62 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4912,6 +4912,7 @@ static int patch_alc269(struct hda_codec *codec) spec->codec_variant = ALC269_TYPE_ALC285; break; case 0x10ec0286: + case 0x10ec0288: spec->codec_variant = ALC269_TYPE_ALC286; break; case 0x10ec0255: @@ -5781,6 +5782,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 }, { .id = 0x10ec0285, .name = "ALC285", .patch = patch_alc269 }, { .id = 0x10ec0286, .name = "ALC286", .patch = patch_alc269 }, + { .id = 0x10ec0288, .name = "ALC288", .patch = patch_alc269 }, { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, { .id = 0x10ec0293, .name = "ALC293", .patch = patch_alc269 }, From 2ec8e3787ae6957f738bb133e755213b9d7c066e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Apr 2014 11:37:06 +0300 Subject: [PATCH 061/279] drm/omap: fix output enable/disable sequence At the moment it's quite easy to get the following errors when the HDMI output is enabled or disabled: [drm:omap_crtc_error_irq] *ERROR* tv: errors: 00008000 The reason for the errors is that the omapdrm driver doesn't properly handle the sync-lost irqs that happen when enabling the DIGIT crtc, which is used for HDMI and analog TV. The driver does disable the sync-lost irq properly, but it fails to wait until the output has been fully enabled (i.e. the first vsync), so the sync-lost errors are still seen occasionally. This patch makes the omapdrm act the same way as the omapfb does: - When enabling a display, we'll wait for the first vsync. - When disabling a display, we'll wait for framedone if available, or odd and even vsyncs. These changes make sure the output is fully enabled or disabled at the end of the function. Signed-off-by: Tomi Valkeinen Reported-by: Sanjay Singh Rawat Reviewed-by: Rob Clark --- drivers/gpu/drm/omapdrm/omap_crtc.c | 46 +++++++++++++++++------------ 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 355157e4f78dd3..0acbe62901d9bb 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -528,38 +528,46 @@ static void set_enabled(struct drm_crtc *crtc, bool enable) struct drm_device *dev = crtc->dev; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); enum omap_channel channel = omap_crtc->channel; - struct omap_irq_wait *wait = NULL; + struct omap_irq_wait *wait; + u32 framedone_irq, vsync_irq; + int ret; if (dispc_mgr_is_enabled(channel) == enable) return; - /* ignore sync-lost irqs during enable/disable */ + /* + * Digit output produces some sync lost interrupts during the first + * frame when enabling, so we need to ignore those. + */ omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); - if (dispc_mgr_get_framedone_irq(channel)) { - if (!enable) { - wait = omap_irq_wait_init(dev, - dispc_mgr_get_framedone_irq(channel), 1); - } + framedone_irq = dispc_mgr_get_framedone_irq(channel); + vsync_irq = dispc_mgr_get_vsync_irq(channel); + + if (enable) { + wait = omap_irq_wait_init(dev, vsync_irq, 1); } else { /* - * When we disable digit output, we need to wait until fields - * are done. Otherwise the DSS is still working, and turning - * off the clocks prevents DSS from going to OFF mode. And when - * enabling, we need to wait for the extra sync losts + * When we disable the digit output, we need to wait for + * FRAMEDONE to know that DISPC has finished with the output. + * + * OMAP2/3 does not have FRAMEDONE irq for digit output, and in + * that case we need to use vsync interrupt, and wait for both + * even and odd frames. */ - wait = omap_irq_wait_init(dev, - dispc_mgr_get_vsync_irq(channel), 2); + + if (framedone_irq) + wait = omap_irq_wait_init(dev, framedone_irq, 1); + else + wait = omap_irq_wait_init(dev, vsync_irq, 2); } dispc_mgr_enable(channel, enable); - if (wait) { - int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); - if (ret) { - dev_err(dev->dev, "%s: timeout waiting for %s\n", - omap_crtc->name, enable ? "enable" : "disable"); - } + ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); + if (ret) { + dev_err(dev->dev, "%s: timeout waiting for %s\n", + omap_crtc->name, enable ? "enable" : "disable"); } omap_irq_register(crtc->dev, &omap_crtc->error_irq); From 707cf58a0a847f60f849b44bfb9b85dcc17c599d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Apr 2014 13:47:43 +0300 Subject: [PATCH 062/279] drm/omap: fix uninit order in pdev_remove() When unloading omapdrm driver, the omapdrm platform device is uninitialized last, after the displays have been disconnected omap_crtc callbacks have been removed. As the omapdrm pdev uninitialization needs the features uninitialized in earlier steps, a crash is guaranteed. This patch fixes the uninitialize order so that the omapdrm pdev is removed first. Signed-off-by: Tomi Valkeinen Reviewed-by: Rob Clark --- drivers/gpu/drm/omapdrm/omap_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index bf39fcc49e0f18..df3e66416a3059 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -696,10 +696,11 @@ static int pdev_remove(struct platform_device *device) { DBG(""); + drm_put_dev(platform_get_drvdata(device)); + omap_disconnect_dssdevs(); omap_crtc_pre_uninit(); - drm_put_dev(platform_get_drvdata(device)); return 0; } From ea7e3a662814447cd329390feddd04b9ec0a4b82 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Apr 2014 14:31:50 +0300 Subject: [PATCH 063/279] drm/omap: fix DMM driver (un)registration At the moment the DMM driver is never unregistered, even if it's registered in the omapdrm module's init function. This means we'll get errors when reloading the omapdrm module. Fix this by unregistering the DMM driver properly, and also change the module init to fail if DMM driver cannot be registered, simplifying the unregister path as we don't need to keep the state whether we registered the DMM driver or not. Signed-off-by: Tomi Valkeinen Reviewed-by: Rob Clark --- drivers/gpu/drm/omapdrm/omap_drv.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index df3e66416a3059..f16a07d1668def 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -727,18 +727,33 @@ static struct platform_driver pdev = { static int __init omap_drm_init(void) { + int r; + DBG("init"); - if (platform_driver_register(&omap_dmm_driver)) { - /* we can continue on without DMM.. so not fatal */ - dev_err(NULL, "DMM registration failed\n"); + + r = platform_driver_register(&omap_dmm_driver); + if (r) { + pr_err("DMM driver registration failed\n"); + return r; } - return platform_driver_register(&pdev); + + r = platform_driver_register(&pdev); + if (r) { + pr_err("omapdrm driver registration failed\n"); + platform_driver_unregister(&omap_dmm_driver); + return r; + } + + return 0; } static void __exit omap_drm_fini(void) { DBG("fini"); + platform_driver_unregister(&pdev); + + platform_driver_unregister(&omap_dmm_driver); } /* need late_initcall() so we load after dss_driver's are loaded */ From e2f8fd74ec1bf15cb2abc1b11f7d9fa09581024e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 2 Apr 2014 14:31:57 +0300 Subject: [PATCH 064/279] drm/omap: fix race issue when unloading omapdrm At module unload, omap_fbdev_free() gets called which releases the framebuffers. However, the framebuffers are still used by crtcs, and will be released only later at vsync. The driver doesn't wait for this, and goes on to release the rest of the resources, which often causes a crash. This patchs adds a omap_crtc_flush() function which waits until the crtc has finished with its apply queue and page flips. The function utilizes a simple polling while-loop, as the performance is not an issue here. Signed-off-by: Tomi Valkeinen Reviewed-by: Rob Clark --- drivers/gpu/drm/omapdrm/omap_crtc.c | 19 +++++++++++++++++++ drivers/gpu/drm/omapdrm/omap_drv.c | 6 ++++++ drivers/gpu/drm/omapdrm/omap_drv.h | 1 + 3 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 0acbe62901d9bb..161a74a3ac5ed7 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -621,6 +621,25 @@ static void omap_crtc_post_apply(struct omap_drm_apply *apply) /* nothing needed for post-apply */ } +void omap_crtc_flush(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + int loops = 0; + + while (!list_empty(&omap_crtc->pending_applies) || + !list_empty(&omap_crtc->queued_applies) || + omap_crtc->event || omap_crtc->old_fb) { + + if (++loops > 10) { + dev_err(crtc->dev->dev, + "omap_crtc_flush() timeout\n"); + break; + } + + schedule_timeout_uninterruptible(msecs_to_jiffies(20)); + } +} + static const char *channel_names[] = { [OMAP_DSS_CHANNEL_LCD] = "lcd", [OMAP_DSS_CHANNEL_DIGIT] = "tv", diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index f16a07d1668def..c8270e4b26f3f7 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -513,12 +513,18 @@ static int dev_load(struct drm_device *dev, unsigned long flags) static int dev_unload(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; + int i; DBG("unload: dev=%p", dev); drm_kms_helper_poll_fini(dev); omap_fbdev_free(dev); + + /* flush crtcs so the fbs get released */ + for (i = 0; i < priv->num_crtcs; i++) + omap_crtc_flush(priv->crtcs[i]); + omap_modeset_free(dev); omap_gem_deinit(dev); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 428b2981fd685f..284b80fc3c54fc 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -163,6 +163,7 @@ void omap_crtc_pre_init(void); void omap_crtc_pre_uninit(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id); +void omap_crtc_flush(struct drm_crtc *crtc); struct drm_plane *omap_plane_init(struct drm_device *dev, int plane_id, bool private_plane); From c7aef12f344459961eb1e0ba10d184816ed42d99 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Apr 2014 16:30:03 +0300 Subject: [PATCH 065/279] drm/omap: fix missing disable for unused encoder When an encoder is no longer connected to a crtc, the driver will leave the encoder enabled. This patch adds code to track the encoder used for a crtc, and when the encoder changes, the old one is disabled. Signed-off-by: Tomi Valkeinen Reviewed-by: Rob Clark --- drivers/gpu/drm/omapdrm/omap_crtc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 161a74a3ac5ed7..61d1c4897a4598 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -33,6 +33,7 @@ struct omap_crtc { int pipe; enum omap_channel channel; struct omap_overlay_manager_info info; + struct drm_encoder *current_encoder; /* * Temporary: eventually this will go away, but it is needed @@ -594,6 +595,11 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) } } + if (omap_crtc->current_encoder && encoder != omap_crtc->current_encoder) + omap_encoder_set_enabled(omap_crtc->current_encoder, false); + + omap_crtc->current_encoder = encoder; + if (!omap_crtc->enabled) { set_enabled(&omap_crtc->base, false); if (encoder) From 506096a113832239ce763d20fab8e94f76d56266 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 3 Apr 2014 13:11:54 +0300 Subject: [PATCH 066/279] drm/omap: fix enabling/disabling of video pipeline At the moment the omap_crtc_pre_apply() handles the enabling, disabling and configuring of encoders and panels separately from the CRTC (i.e. the overlay manager). However, this doesn't work correctly. The encoder driver has to be in control of its video input (i.e. the crtc) for correct operation. This problem causes bugs with (at least) HDMI: the HDMI encoder supplies pixel clock for DISPC, and DISPC supplies video stream for HDMI. The current code first enables the HDMI encoder, and CRTC after that. However, the encoder expects the video stream to start during the encoder's enable, and if it doesn't, there will be sync lost errors. The encoder enables its video source by calling src->enable(), and this call goes to omapdrm (omap_crtc_enable), but omapdrm doesn't do anything in that function. Similarly for disable, which goes to omap_crtc_disable(). This patch moves the code to setup and enable/disable the crtc to omap_crtc_enable. and omap_crtc_disable(). Signed-off-by: Tomi Valkeinen Reviewed-by: Rob Clark --- drivers/gpu/drm/omapdrm/omap_crtc.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 61d1c4897a4598..f59ef9359e66cf 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -121,13 +121,25 @@ static void omap_crtc_start_update(struct omap_overlay_manager *mgr) { } +static void set_enabled(struct drm_crtc *crtc, bool enable); + static int omap_crtc_enable(struct omap_overlay_manager *mgr) { + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; + + dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); + dispc_mgr_set_timings(omap_crtc->channel, + &omap_crtc->timings); + set_enabled(&omap_crtc->base, true); + return 0; } static void omap_crtc_disable(struct omap_overlay_manager *mgr) { + struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; + + set_enabled(&omap_crtc->base, false); } static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, @@ -601,7 +613,6 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) omap_crtc->current_encoder = encoder; if (!omap_crtc->enabled) { - set_enabled(&omap_crtc->base, false); if (encoder) omap_encoder_set_enabled(encoder, false); } else { @@ -610,13 +621,7 @@ static void omap_crtc_pre_apply(struct omap_drm_apply *apply) omap_encoder_update(encoder, omap_crtc->mgr, &omap_crtc->timings); omap_encoder_set_enabled(encoder, true); - omap_crtc->full_update = false; } - - dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); - dispc_mgr_set_timings(omap_crtc->channel, - &omap_crtc->timings); - set_enabled(&omap_crtc->base, true); } omap_crtc->full_update = false; From d4586604acbd2e58921e0363533b9797b0235275 Mon Sep 17 00:00:00 2001 From: Grazvydas Ignotas Date: Sat, 5 Apr 2014 21:33:51 +0300 Subject: [PATCH 067/279] drm/omap: fix plane rotation Plane rotation with omapdrm is currently broken. It seems omap_plane_mode_set() expects width and height in screen coordinates, so pass it like that. Signed-off-by: Grazvydas Ignotas Reviewed-by: Rob Clark Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_plane.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 046d5e660c04c4..df1725247ccaa5 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -246,6 +246,14 @@ static int omap_plane_update(struct drm_plane *plane, drm_framebuffer_reference(fb); + /* omap_plane_mode_set() takes adjusted src */ + switch (omap_plane->win.rotation & 0xf) { + case BIT(DRM_ROTATE_90): + case BIT(DRM_ROTATE_270): + swap(src_w, src_h); + break; + } + return omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h, From 5e19c06d0e570a347669acc2b850c2f730090b60 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Apr 2014 15:25:34 +0300 Subject: [PATCH 068/279] drm/omap: fix missing unref to fb's buf object omap_fbdev_create() takes a reference to the fb's gem object with omap_gem_get_paddr(). However, it never releases it with omap_gem_put_paddr(). This patch adds the missing omap_gem_put_paddr() to omap_fbdev_free(). Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_fbdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 002988d09021da..1388ca7f87e84f 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -371,6 +371,9 @@ void omap_fbdev_free(struct drm_device *dev) fbdev = to_omap_fbdev(priv->fbdev); + /* release the ref taken in omap_fbdev_create() */ + omap_gem_put_paddr(fbdev->bo); + /* this will free the backing object */ if (fbdev->fb) { drm_framebuffer_unregister_private(fbdev->fb); From 5e0c1879919195b79a0b19feda9aafcb7a3e77e7 Mon Sep 17 00:00:00 2001 From: "Li, Zhen-Hua" Date: Mon, 14 Apr 2014 17:41:32 +0800 Subject: [PATCH 069/279] ALSA: es18xx driver should use udelay error udelay with more than 20000 may cause __bad_udelay. Use mdelay for instead. [fixed a typo spotted by Clemens -- tiwai] Signed-off-by: Li, Zhen-Hua Signed-off-by: Takashi Iwai --- sound/isa/es18xx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index 1c16830af3d8cf..6faaac60161a8b 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -520,7 +520,7 @@ static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip, snd_es18xx_mixer_write(chip, 0x78, 0x93); #ifdef AVOID_POPS /* Avoid pops */ - udelay(100000); + mdelay(100); if (chip->caps & ES18XX_PCM2) /* Restore Audio 2 volume */ snd_es18xx_mixer_write(chip, 0x7C, chip->audio2_vol); @@ -537,7 +537,7 @@ static int snd_es18xx_playback1_trigger(struct snd_es18xx *chip, /* Stop DMA */ snd_es18xx_mixer_write(chip, 0x78, 0x00); #ifdef AVOID_POPS - udelay(25000); + mdelay(25); if (chip->caps & ES18XX_PCM2) /* Set Audio 2 volume to 0 */ snd_es18xx_mixer_write(chip, 0x7C, 0); @@ -596,7 +596,7 @@ static int snd_es18xx_capture_prepare(struct snd_pcm_substream *substream) snd_es18xx_write(chip, 0xA5, count >> 8); #ifdef AVOID_POPS - udelay(100000); + mdelay(100); #endif /* Set format */ @@ -691,7 +691,7 @@ static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip, snd_es18xx_write(chip, 0xB8, 0x05); #ifdef AVOID_POPS /* Avoid pops */ - udelay(100000); + mdelay(100); /* Enable Audio 1 */ snd_es18xx_dsp_command(chip, 0xD1); #endif @@ -705,7 +705,7 @@ static int snd_es18xx_playback2_trigger(struct snd_es18xx *chip, snd_es18xx_write(chip, 0xB8, 0x00); #ifdef AVOID_POPS /* Avoid pops */ - udelay(25000); + mdelay(25); /* Disable Audio 1 */ snd_es18xx_dsp_command(chip, 0xD3); #endif From cc253d7cebb9a1b43f47409acd8b7942e125ea61 Mon Sep 17 00:00:00 2001 From: Javier Martinez Canillas Date: Thu, 24 Oct 2013 22:40:19 +0200 Subject: [PATCH 070/279] of: add vendor prefix for ISEE 2007 S.L. This trivial patch adds ISEE 2007 S.L. to the list of devicetree vendor prefixes. Acked-by: Kumar Gala Signed-off-by: Javier Martinez Canillas Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 0f01c9bf19c8fa..04eed97e45c50c 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -58,6 +58,7 @@ idt Integrated Device Technologies, Inc. img Imagination Technologies Ltd. intel Intel Corporation intercontrol Inter Control Group +isee ISEE 2007 S.L. isl Intersil karo Ka-Ro electronics GmbH lacie LaCie From a438311b715b76d9683a6d0dfccea6603b08083f Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Thu, 3 Apr 2014 10:33:49 +0200 Subject: [PATCH 071/279] of: add vendor prefix for I2SE GmbH Add i2se to the list of DT vendor prefixes. Signed-off-by: Stefan Wahren Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 04eed97e45c50c..233a4957fd189f 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -53,6 +53,7 @@ haoyu Haoyu Microelectronic Co. Ltd. hisilicon Hisilicon Limited. honeywell Honeywell hp Hewlett Packard +i2se I2SE GmbH ibm International Business Machines (IBM) idt Integrated Device Technologies, Inc. img Imagination Technologies Ltd. From e7d2e3af864cf1ac2548b8f3deb2956395a8abd3 Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Wed, 2 Apr 2014 21:52:07 -0500 Subject: [PATCH 072/279] dt-bindings: add vendor-prefix for Newhaven Display Newhaven Display provides the worldwide marketplace with cost effective high quality display devices ranging from OLED and LCD Displays to VFD Displays. Signed-off-by: Dinh Nguyen Reviewed-by: Pavel Machek Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 233a4957fd189f..5cfb6c102fcc2c 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -75,6 +75,7 @@ moxa Moxa national National Semiconductor neonode Neonode Inc. netgear NETGEAR +newhaven Newhaven Display International nintendo Nintendo nokia Nokia nvidia NVIDIA From 401a97d2c0f20a0b6cfe6d035b638fe2b6e8e97c Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 22 Mar 2014 13:45:57 +0100 Subject: [PATCH 073/279] DT: bindings: add missing Marvell Kirkwood SoC documentation Marvell Kirkwood SoC binding have not yet been documented. Add the documentation including the supported SoCs and boards. Signed-off-by: Andrew Lunn Acked-by: Jason Cooper Signed-off-by: Rob Herring --- .../bindings/arm/marvell,kirkwood.txt | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 Documentation/devicetree/bindings/arm/marvell,kirkwood.txt diff --git a/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt b/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt new file mode 100644 index 00000000000000..925ecbf6e7b7af --- /dev/null +++ b/Documentation/devicetree/bindings/arm/marvell,kirkwood.txt @@ -0,0 +1,97 @@ +Marvell Kirkwood SoC Family Device Tree Bindings +------------------------------------------------ + +Boards with a SoC of the Marvell Kirkwook family, eg 88f6281 + +* Required root node properties: +compatible: must contain "marvell,kirkwood" + +In addition, the above compatible shall be extended with the specific +SoC. Currently known SoC compatibles are: + +"marvell,kirkwood-88f6192" +"marvell,kirkwood-88f6281" +"marvell,kirkwood-88f6282" +"marvell,kirkwood-88f6283" +"marvell,kirkwood-88f6702" +"marvell,kirkwood-98DX4122" + +And in addition, the compatible shall be extended with the specific +board. Currently known boards are: + +"buffalo,lschlv2" +"buffalo,lsxhl" +"buffalo,lsxl" +"dlink,dns-320" +"dlink,dns-320-a1" +"dlink,dns-325" +"dlink,dns-325-a1" +"dlink,dns-kirkwood" +"excito,b3" +"globalscale,dreamplug-003-ds2001" +"globalscale,guruplug" +"globalscale,guruplug-server-plus" +"globalscale,sheevaplug" +"globalscale,sheevaplug" +"globalscale,sheevaplug-esata" +"globalscale,sheevaplug-esata-rev13" +"iom,iconnect" +"iom,iconnect-1.1" +"iom,ix2-200" +"keymile,km_kirkwood" +"lacie,cloudbox" +"lacie,inetspace_v2" +"lacie,laplug" +"lacie,netspace_lite_v2" +"lacie,netspace_max_v2" +"lacie,netspace_mini_v2" +"lacie,netspace_v2" +"marvell,db-88f6281-bp" +"marvell,db-88f6282-bp" +"marvell,mv88f6281gtw-ge" +"marvell,rd88f6281" +"marvell,rd88f6281" +"marvell,rd88f6281-a0" +"marvell,rd88f6281-a1" +"mpl,cec4" +"mpl,cec4-10" +"netgear,readynas" +"netgear,readynas" +"netgear,readynas-duo-v2" +"netgear,readynas-nv+-v2" +"plathome,openblocks-a6" +"plathome,openblocks-a7" +"raidsonic,ib-nas6210" +"raidsonic,ib-nas6210-b" +"raidsonic,ib-nas6220" +"raidsonic,ib-nas6220-b" +"raidsonic,ib-nas62x0" +"seagate,dockstar" +"seagate,goflexnet" +"synology,ds109" +"synology,ds110jv10" +"synology,ds110jv20" +"synology,ds110jv30" +"synology,ds111" +"synology,ds209" +"synology,ds210jv10" +"synology,ds210jv20" +"synology,ds212" +"synology,ds212jv10" +"synology,ds212jv20" +"synology,ds212pv10" +"synology,ds409" +"synology,ds409slim" +"synology,ds410j" +"synology,ds411" +"synology,ds411j" +"synology,ds411slim" +"synology,ds413jv10" +"synology,rs212" +"synology,rs409" +"synology,rs411" +"synology,rs812" +"usi,topkick" +"usi,topkick-1281P2" +"zyxel,nsa310" +"zyxel,nsa310a" From 552481aace37a3698a2389bba04ae43fc969803b Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 22 Mar 2014 13:45:56 +0100 Subject: [PATCH 074/279] DT: Vendor: Add prefixes used by Kirkwood devices Add a number of vendor prefixes by kirkwood devices. These are not all stock tickers, but have been in use for a while so changing would not be easy. Signed-off-by: Andrew Lunn Acked-by: Jason Cooper Signed-off-by: Rob Herring --- .../devicetree/bindings/vendor-prefixes.txt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 5cfb6c102fcc2c..36b8530718db47 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -22,6 +22,7 @@ auo AU Optronics Corporation avago Avago Technologies bosch Bosch Sensortec GmbH brcm Broadcom Corporation +buffalo Buffalo, Inc. calxeda Calxeda capella Capella Microsystems, Inc cavium Cavium, Inc. @@ -33,8 +34,8 @@ cortina Cortina Systems, Inc. crystalfontz Crystalfontz America, Inc. dallas Maxim Integrated Products (formerly Dallas Semiconductor) davicom DAVICOM Semiconductor, Inc. -dlink D-Link Systems, Inc. denx Denx Software Engineering +dlink D-Link Corporation dmo Data Modul AG edt Emerging Display Technologies emmicro EM Microelectronic @@ -42,6 +43,7 @@ epfl Ecole Polytechnique Fédérale de Lausanne epson Seiko Epson Corp. est ESTeem Wireless Modems eukrea Eukréa Electromatique +excito Excito fsl Freescale Semiconductor GEFanuc GE Fanuc Intelligent Platforms Embedded Systems, Inc. gef GE Fanuc Intelligent Platforms Embedded Systems, Inc. @@ -56,12 +58,14 @@ hp Hewlett Packard i2se I2SE GmbH ibm International Business Machines (IBM) idt Integrated Device Technologies, Inc. +iom Iomega Corporation img Imagination Technologies Ltd. intel Intel Corporation intercontrol Inter Control Group isee ISEE 2007 S.L. isl Intersil karo Ka-Ro electronics GmbH +keymile Keymile GmbH lacie LaCie lantiq Lantiq Semiconductor lg LG Corporation @@ -72,6 +76,8 @@ maxim Maxim Integrated Products microchip Microchip Technology Inc. mosaixtech Mosaix Technologies, Inc. moxa Moxa +mpl MPL AG +mxicy Macronix International Co., Ltd. national National Semiconductor neonode Neonode Inc. netgear NETGEAR @@ -85,10 +91,12 @@ opencores OpenCores.org panasonic Panasonic Corporation phytec PHYTEC Messtechnik GmbH picochip Picochip Ltd +plathome Plat'Home Co., Ltd. powervr PowerVR (deprecated, use img) qca Qualcomm Atheros, Inc. qcom Qualcomm Technologies, Inc qnap QNAP Systems, Inc. +raidsonic RaidSonic Technology GmbH ralink Mediatek/Ralink Technology Corp. ramtron Ramtron International realtek Realtek Semiconductor Corp. @@ -98,6 +106,7 @@ rockchip Fuzhou Rockchip Electronics Co., Ltd samsung Samsung Semiconductor sbs Smart Battery System schindler Schindler +seagate Seagate Technology PLC sil Silicon Image silabs Silicon Laboratories simtek @@ -114,6 +123,7 @@ ti Texas Instruments tlm Trusted Logic Mobility toshiba Toshiba Corporation toumaz Toumaz +usi Universal Scientifc Industrial Co., Ltd. v3 V3 Semiconductor via VIA Technologies, Inc. voipac Voipac Technologies s.r.o. @@ -122,3 +132,4 @@ wlf Wolfson Microelectronics wm Wondermedia Technologies, Inc. xes Extreme Engineering Solutions (X-ES) xlnx Xilinx +zyxel ZyXEL Communications Corp. From 3443dd19da985da337cd0be20435cc98aa8c7915 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 22 Mar 2014 13:45:59 +0100 Subject: [PATCH 075/279] DT: I2C: Add trivial bindings used by kirkwood boards Add a number of eeproms and temperature sensors/fan controllers used by kirkwood boards. Signed-off-by: Andrew Lunn Acked-by: Jason Cooper Signed-off-by: Rob Herring --- .../devicetree/bindings/i2c/trivial-devices.txt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 71724d026ffacf..bef86e57c3889d 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -13,8 +13,22 @@ ad,ad7414 SMBus/I2C Digital Temperature Sensor in 6-Pin SOT with SMBus Alert an ad,adm9240 ADM9240: Complete System Hardware Monitor for uProcessor-Based Systems adi,adt7461 +/-1C TDM Extended Temp Range I.C adt7461 +/-1C TDM Extended Temp Range I.C +adi,adt7473 +/-1C TDM Extended Temp Range I.C +adi,adt7475 +/-1C TDM Extended Temp Range I.C +adi,adt7476 +/-1C TDM Extended Temp Range I.C +adi,adt7490 +/-1C TDM Extended Temp Range I.C at,24c08 i2c serial eeprom (24cxx) +atmel,24c00 i2c serial eeprom (24cxx) +atmel,24c01 i2c serial eeprom (24cxx) atmel,24c02 i2c serial eeprom (24cxx) +atmel,24c04 i2c serial eeprom (24cxx) +atmel,24c16 i2c serial eeprom (24cxx) +atmel,24c32 i2c serial eeprom (24cxx) +atmel,24c64 i2c serial eeprom (24cxx) +atmel,24c128 i2c serial eeprom (24cxx) +atmel,24c256 i2c serial eeprom (24cxx) +atmel,24c512 i2c serial eeprom (24cxx) +atmel,24c1024 i2c serial eeprom (24cxx) atmel,at97sc3204t i2c trusted platform module (TPM) capella,cm32181 CM32181: Ambient Light Sensor catalyst,24c32 i2c serial eeprom @@ -46,8 +60,10 @@ maxim,ds1050 5 Bit Programmable, Pulse-Width Modulator maxim,max1237 Low-Power, 4-/12-Channel, 2-Wire Serial, 12-Bit ADCs maxim,max6625 9-Bit/12-Bit Temperature Sensors with I²C-Compatible Serial Interface mc,rv3029c2 Real Time Clock Module with I2C-Bus +national,lm63 Temperature sensor with integrated fan control national,lm75 I2C TEMP SENSOR national,lm80 Serial Interface ACPI-Compatible Microprocessor System Hardware Monitor +national,lm85 Temperature sensor with integrated fan control national,lm92 ±0.33°C Accurate, 12-Bit + Sign Temperature Sensor and Thermal Window Comparator with Two-Wire Interface nuvoton,npct501 i2c trusted platform module (TPM) nxp,pca9556 Octal SMBus and I2C registered interface From 42dc102dc3c026267dc2100c27f9e4d5283c3644 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Thu, 3 Apr 2014 19:01:35 +0400 Subject: [PATCH 076/279] of: Add vendor prefix for Digi International Inc. Using "digi" for Digi International Inc. Additionally, this patch keep "dlink" entry sorted alphabetically. Signed-off-by: Alexander Shiyan Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 36b8530718db47..fad44cab68b8b8 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -35,6 +35,7 @@ crystalfontz Crystalfontz America, Inc. dallas Maxim Integrated Products (formerly Dallas Semiconductor) davicom DAVICOM Semiconductor, Inc. denx Denx Software Engineering +digi Digi International Inc. dlink D-Link Corporation dmo Data Modul AG edt Emerging Display Technologies From 5b6241185e2cded07ca3f5f646b55c641928ba4e Mon Sep 17 00:00:00 2001 From: Xiubo Li Date: Tue, 8 Apr 2014 13:48:07 +0800 Subject: [PATCH 077/279] of: Fix the section mismatch warnings. In tag next-20140407, building with CONFIG_DEBUG_SECTION_MISMATCH enabled, the following WARNING is occured: WARNING: drivers/built-in.o(.text.unlikely+0x2220): Section mismatch in reference from the function __reserved_mem_check_root() to the function .init.text:of_get_flat_dt_prop() The function __reserved_mem_check_root() references the function __init of_get_flat_dt_prop(). This is often because __reserved_mem_check_root lacks a __init annotation or the annotation of of_get_flat_dt_prop is wrong. WARNING: vmlinux.o(.text.unlikely+0xb9d0): Section mismatch in reference from the function __reserved_mem_check_root() to the (unknown reference) .init.data:(unknown) The function __reserved_mem_check_root() references the (unknown reference) __initdata (unknown). This is often because __reserved_mem_check_root lacks a __initdata annotation or the annotation of (unknown) is wrong. This is cause by : 'drivers: of: add initialization code for dynamic reserved memory'. Signed-off-by: Xiubo Li Signed-off-by: Rob Herring --- drivers/of/fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index fa16a912a927bb..7a2ef7bb8022b4 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -491,7 +491,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, * in /reserved-memory matches the values supported by the current implementation, * also check if ranges property has been provided */ -static int __reserved_mem_check_root(unsigned long node) +static int __init __reserved_mem_check_root(unsigned long node) { __be32 *prop; From f3afa2259457e46bbb6285bcc1032ecc0f76fdd7 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Mon, 31 Mar 2014 17:36:53 +0200 Subject: [PATCH 078/279] DT: add vendor prefix for EBV Elektronik Add vendor prefix for EBV Elektronik. Signed-off-by: Steffen Trumtrar Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index fad44cab68b8b8..abc308083acb20 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -38,6 +38,7 @@ denx Denx Software Engineering digi Digi International Inc. dlink D-Link Corporation dmo Data Modul AG +ebv EBV Elektronik edt Emerging Display Technologies emmicro EM Microelectronic epfl Ecole Polytechnique Fédérale de Lausanne From af64dc7474a43fb653255ecf8ae879c8227feab2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Sun, 6 Apr 2014 15:30:39 +0200 Subject: [PATCH 079/279] rsi: Add missing initialization of ii MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/net/wireless/rsi/rsi_91x_core.c: In function ‘rsi_core_determine_hal_queue’: drivers/net/wireless/rsi/rsi_91x_core.c:91: warning: ‘ii’ may be used uninitialized in this function Signed-off-by: Geert Uytterhoeven Signed-off-by: John W. Linville --- drivers/net/wireless/rsi/rsi_91x_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_core.c b/drivers/net/wireless/rsi/rsi_91x_core.c index 1a8d3213859363..cf61d6e3eaa7cd 100644 --- a/drivers/net/wireless/rsi/rsi_91x_core.c +++ b/drivers/net/wireless/rsi/rsi_91x_core.c @@ -88,7 +88,7 @@ static u8 rsi_core_determine_hal_queue(struct rsi_common *common) bool recontend_queue = false; u32 q_len = 0; u8 q_num = INVALID_QUEUE; - u8 ii, min = 0; + u8 ii = 0, min = 0; if (skb_queue_len(&common->tx_queue[MGMT_SOFT_Q])) { if (!common->mgmt_q_block) From 98ddcbe03366c19b6da9b75a00f9c8d0a7c2dc6d Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Wed, 9 Apr 2014 21:28:54 +0200 Subject: [PATCH 080/279] rsi: Fix a potential memory leak in rsi_set_channel() Fix a potential memory leak in function rsi_set_channel() that is used to program channel changes. The channel check block for the frequency bands directly exits the function in case of an error, thus leaving an already allocated skb unreferenced. Move the checks above allocating the skb. Detected by Coverity: CID 1195576. Signed-off-by: Christian Engelmayer Signed-off-by: John W. Linville --- drivers/net/wireless/rsi/rsi_91x_mgmt.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 73694295648f19..3a030b9d0fe6c4 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -841,16 +841,6 @@ int rsi_set_channel(struct rsi_common *common, u16 channel) rsi_dbg(MGMT_TX_ZONE, "%s: Sending scan req frame\n", __func__); - skb = dev_alloc_skb(FRAME_DESC_SZ); - if (!skb) { - rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", - __func__); - return -ENOMEM; - } - - memset(skb->data, 0, FRAME_DESC_SZ); - mgmt_frame = (struct rsi_mac_frame *)skb->data; - if (common->band == IEEE80211_BAND_5GHZ) { if ((channel >= 36) && (channel <= 64)) channel = ((channel - 32) / 4); @@ -868,6 +858,16 @@ int rsi_set_channel(struct rsi_common *common, u16 channel) } } + skb = dev_alloc_skb(FRAME_DESC_SZ); + if (!skb) { + rsi_dbg(ERR_ZONE, "%s: Failed in allocation of skb\n", + __func__); + return -ENOMEM; + } + + memset(skb->data, 0, FRAME_DESC_SZ); + mgmt_frame = (struct rsi_mac_frame *)skb->data; + mgmt_frame->desc_word[0] = cpu_to_le16(RSI_WIFI_MGMT_Q << 12); mgmt_frame->desc_word[1] = cpu_to_le16(SCAN_REQUEST); mgmt_frame->desc_word[4] = cpu_to_le16(channel); From 69aa167583a9e6d36ac1957c0bc51136c7a770fa Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 10 Apr 2014 10:01:37 +0300 Subject: [PATCH 081/279] wlcore: ignore dummy packet events in PLT mode Sometimes the firmware sends a dummy packet event while we are in PLT mode. This doesn't make sense, it's a firmware bug. Fix this by ignoring dummy packet events when we're PLT mode. Reported-by: Yegor Yefremov Reported-by: Arik Nemtsov Signed-off-by: Luciano Coelho Signed-off-by: John W. Linville --- drivers/net/wireless/ti/wlcore/event.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 1f9a36031b06d4..16d10281798d76 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c @@ -158,6 +158,11 @@ EXPORT_SYMBOL_GPL(wlcore_event_channel_switch); void wlcore_event_dummy_packet(struct wl1271 *wl) { + if (wl->plt) { + wl1271_info("Got DUMMY_PACKET event in PLT mode. FW bug, ignoring."); + return; + } + wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID"); wl1271_tx_dummy_packet(wl); } From 2004dabaac4104e9aa067e3fe9326d3958b27ca1 Mon Sep 17 00:00:00 2001 From: Frederic Danis Date: Thu, 10 Apr 2014 11:36:38 +0200 Subject: [PATCH 082/279] cw1200: Fix cw1200_debug_link_id This array is used in debug string to display cw1200_link_status defined in drivers/net/wireless/cw1200/cw1200.h. Add missing strings for CW1200_LINK_RESET and CW1200_LINK_RESET_REMAP. Signed-off-by: Frederic Danis Signed-off-by: John W. Linville --- drivers/net/wireless/cw1200/debug.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/cw1200/debug.c b/drivers/net/wireless/cw1200/debug.c index e323b4d54338e4..34f97c31eecf74 100644 --- a/drivers/net/wireless/cw1200/debug.c +++ b/drivers/net/wireless/cw1200/debug.c @@ -41,6 +41,8 @@ static const char * const cw1200_debug_link_id[] = { "REQ", "SOFT", "HARD", + "RESET", + "RESET_REMAP", }; static const char *cw1200_debug_mode(int mode) From 61698b7e222c33e1d38996519b38dd34cbcb8634 Mon Sep 17 00:00:00 2001 From: Christian Engelmayer Date: Thu, 10 Apr 2014 20:37:53 +0200 Subject: [PATCH 083/279] rsi: Fix a potential memory leak in rsi_send_auto_rate_request() Fix a potential memory leak in the error path of function rsi_send_auto_rate_request(). In case memory allocation for array 'selected_rates' fails, the error path exits and leaves the previously allocated skb in place. Detected by Coverity: CID 1195575. Signed-off-by: Christian Engelmayer Signed-off-by: John W. Linville --- drivers/net/wireless/rsi/rsi_91x_mgmt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 3a030b9d0fe6c4..1b28cda6ca8812 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -966,6 +966,7 @@ static int rsi_send_auto_rate_request(struct rsi_common *common) if (!selected_rates) { rsi_dbg(ERR_ZONE, "%s: Failed in allocation of mem\n", __func__); + dev_kfree_skb(skb); return -ENOMEM; } From c0da71ff4d2cbf113465bff9a7c413154be25a89 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 13 Apr 2014 16:33:51 +0300 Subject: [PATCH 084/279] wl18xx: align event mailbox with current fw Some fields are missing from the event mailbox struct definitions, which cause issues when trying to handle some events. Add the missing fields in order to align the struct size (without adding actual support for the new fields). Reported-and-tested-by: Imre Kaloz Cc: stable@vger.kernel.org # 3.14+ Fixes: 028e724 ("wl18xx: move to new firmware (wl18xx-fw-3.bin)") Signed-off-by: Eliad Peller Signed-off-by: John W. Linville --- drivers/net/wireless/ti/wl18xx/event.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/net/wireless/ti/wl18xx/event.h b/drivers/net/wireless/ti/wl18xx/event.h index 398f3d2c0a6cc7..a76e98eb8372a9 100644 --- a/drivers/net/wireless/ti/wl18xx/event.h +++ b/drivers/net/wireless/ti/wl18xx/event.h @@ -68,6 +68,26 @@ struct wl18xx_event_mailbox { /* bitmap of inactive stations (by HLID) */ __le32 inactive_sta_bitmap; + + /* rx BA win size indicated by RX_BA_WIN_SIZE_CHANGE_EVENT_ID */ + u8 rx_ba_role_id; + u8 rx_ba_link_id; + u8 rx_ba_win_size; + u8 padding; + + /* smart config */ + u8 sc_ssid_len; + u8 sc_pwd_len; + u8 sc_token_len; + u8 padding1; + u8 sc_ssid[32]; + u8 sc_pwd[32]; + u8 sc_token[32]; + + /* smart config sync channel */ + u8 sc_sync_channel; + u8 sc_sync_band; + u8 padding2[2]; } __packed; int wl18xx_wait_for_event(struct wl1271 *wl, enum wlcore_wait_event event, From 140ab6452c42174d20e2fdd27ed73b889cd86500 Mon Sep 17 00:00:00 2001 From: Mike Qiu Date: Mon, 14 Apr 2014 16:12:35 -0600 Subject: [PATCH 085/279] powerpc/PCI: Fix NULL dereference in sys_pciconfig_iobase() list traversal 3bc955987fb3 ("powerpc/PCI: Use list_for_each_entry() for bus traversal") caused a NULL pointer dereference because the loop body set the iterator to NULL: Unable to handle kernel paging request for data at address 0x00000000 Faulting instruction address: 0xc000000000041d78 Oops: Kernel access of bad area, sig: 11 [#1] ... NIP [c000000000041d78] .sys_pciconfig_iobase+0x68/0x1f0 LR [c000000000041e0c] .sys_pciconfig_iobase+0xfc/0x1f0 Call Trace: [c0000003b4787db0] [c000000000041e0c] .sys_pciconfig_iobase+0xfc/0x1f0 (unreliable) [c0000003b4787e30] [c000000000009ed8] syscall_exit+0x0/0x98 Fix it by using a temporary variable for the iterator. [bhelgaas: changelog, drop tmp_bus initialization] Fixes: 3bc955987fb3 powerpc/PCI: Use list_for_each_entry() for bus traversal Signed-off-by: Mike Qiu Signed-off-by: Bjorn Helgaas --- arch/powerpc/kernel/pci_64.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 2a4779091a5809..155013da27e05c 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -208,7 +208,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, unsigned long in_devfn) { struct pci_controller* hose; - struct pci_bus *bus = NULL; + struct pci_bus *tmp_bus, *bus = NULL; struct device_node *hose_node; /* Argh ! Please forgive me for that hack, but that's the @@ -229,10 +229,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, * used on pre-domains setup. We return the first match */ - list_for_each_entry(bus, &pci_root_buses, node) { - if (in_bus >= bus->number && in_bus <= bus->busn_res.end) + list_for_each_entry(tmp_bus, &pci_root_buses, node) { + if (in_bus >= tmp_bus->number && + in_bus <= tmp_bus->busn_res.end) { + bus = tmp_bus; break; - bus = NULL; + } } if (bus == NULL || bus->dev.of_node == NULL) return -ENODEV; From 9f05d3fb644bf178c169d9c70dcfe360e3a006ae Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 14 Apr 2014 22:01:30 -0700 Subject: [PATCH 086/279] iommu/vt-d: Fix get_domain_for_dev() handling of upstream PCIe bridges Commit 146922ec79 ("iommu/vt-d: Make get_domain_for_dev() take struct device") introduced new variables bridge_bus and bridge_devfn to identify the upstream PCIe to PCI bridge responsible for the given target device. Leaving the original bus/devfn variables to identify the target device itself, now that it is no longer assumed to be PCI and we can no longer trivially find that information. However, the patch failed to correctly use the new variables in all cases; instead using the as-yet-uninitialised 'bus' and 'devfn' variables. Reported-by: Alex Williamson Signed-off-by: David Woodhouse --- drivers/iommu/intel-iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 13dc2318e17a3a..f256ffc02e29df 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2237,7 +2237,9 @@ static struct dmar_domain *get_domain_for_dev(struct device *dev, int gaw) bridge_devfn = dev_tmp->devfn; } spin_lock_irqsave(&device_domain_lock, flags); - info = dmar_search_domain_by_dev_info(segment, bus, devfn); + info = dmar_search_domain_by_dev_info(segment, + bridge_bus, + bridge_devfn); if (info) { iommu = info->iommu; domain = info->domain; From 5ae0566a0fffa09a77ac5996e3854fe91cd87167 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Tue, 15 Apr 2014 10:35:35 +0800 Subject: [PATCH 087/279] iommu/vt-d: fix bug in matching PCI devices with DRHD/RMRR descriptors Commit "59ce0515cdaf iommu/vt-d: Update DRHD/RMRR/ATSR device scope caches when PCI hotplug happens" introduces a bug, which fails to match PCI devices with DMAR device scope entries if PCI path array in the entry has more than one level. For example, it fails to handle [1D2h 0466 1] Device Scope Entry Type : 01 [1D3h 0467 1] Entry Length : 0A [1D4h 0468 2] Reserved : 0000 [1D6h 0470 1] Enumeration ID : 00 [1D7h 0471 1] PCI Bus Number : 00 [1D8h 0472 2] PCI Path : 1C,04 [1DAh 0474 2] PCI Path : 00,02 And cause DMA failure on HP DL980 as: DMAR:[fault reason 02] Present bit in context entry is clear dmar: DRHD: handling fault status reg 602 dmar: DMAR:[DMA Read] Request device [02:00.2] fault addr 7f61e000 Reported-and-tested-by: Davidlohr Bueso Signed-off-by: Jiang Liu Signed-off-by: David Woodhouse --- drivers/iommu/dmar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index f445c10df8dfd2..39f8b717fe8482 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -152,7 +152,8 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) info->seg = pci_domain_nr(dev->bus); info->level = level; if (event == BUS_NOTIFY_ADD_DEVICE) { - for (tmp = dev, level--; tmp; tmp = tmp->bus->self) { + for (tmp = dev; tmp; tmp = tmp->bus->self) { + level--; info->path[level].device = PCI_SLOT(tmp->devfn); info->path[level].function = PCI_FUNC(tmp->devfn); if (pci_is_root_bus(tmp->bus)) From 5ac96345899be859529e05af42f708ae7bd65782 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 8 Apr 2014 16:18:41 +0300 Subject: [PATCH 088/279] drm/omap: print warning when rotating non-TILER fb Print a warning when the user tries to rotate a non-TILER framebuffer. Also set the rotation to 0, to avoid constant flood of the warnings in case of page flipping. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_fb.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index d2b8c49bfb4ae5..8b019602ffe615 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -218,6 +218,20 @@ void omap_framebuffer_update_scanout(struct drm_framebuffer *fb, info->rotation_type = OMAP_DSS_ROT_TILER; info->screen_width = omap_gem_tiled_stride(plane->bo, orient); } else { + switch (win->rotation & 0xf) { + case 0: + case BIT(DRM_ROTATE_0): + /* OK */ + break; + + default: + dev_warn(fb->dev->dev, + "rotation '%d' ignored for non-tiled fb\n", + win->rotation); + win->rotation = 0; + break; + } + info->paddr = get_linear_addr(plane, format, 0, x, y); info->rotation_type = OMAP_DSS_ROT_DMA; info->screen_width = plane->pitch; From 772cdc9777403f10c4229c49645024a502dfd783 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 9 Apr 2014 14:51:01 +0300 Subject: [PATCH 089/279] drm/omap: remove extra plane->destroy from crtc destroy All the planes, including primary planes, are now destroyed by the drm framework. Thus we no longer need the explicit call to plane->destroy from the crtc's destroy function. This patch removes the call, thus fixing the crash caused by double freeing the plane. remove omap_crtc->plane->funcs->destroy(omap_crtc->plane) Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index f59ef9359e66cf..b3a7529845b952 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -197,7 +197,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) WARN_ON(omap_crtc->apply_irq.registered); omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); - omap_crtc->plane->funcs->destroy(omap_crtc->plane); drm_crtc_cleanup(crtc); kfree(omap_crtc); From b841aedfcfd543d836c856bfde5a17c51cab6b26 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 10 Apr 2014 08:57:55 +0300 Subject: [PATCH 090/279] drm/omap: remove warn from debugfs Patch dfe96ddcfa22b44100814b9435770f6ff1309d37 (omapdrm: simplify locking in the fb debugfs file) removed taking locks when using omapdrm's debugfs to dump fb objects. However, in omap_gem_describe we give a WARN is the lock has not been taken, so that WARN is now seen every time omapdrm debugfs is used. So, presuming the removal of locks is ok, we can also remove the WARN. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_gem.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index c8d972763889d9..70798b9fe63576 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -980,12 +980,9 @@ int omap_gem_resume(struct device *dev) #ifdef CONFIG_DEBUG_FS void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) { - struct drm_device *dev = obj->dev; struct omap_gem_object *omap_obj = to_omap_bo(obj); uint64_t off; - WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - off = drm_vma_node_start(&obj->vma_node); seq_printf(m, "%08x: %2d (%2d) %08llx %08Zx (%2d) %p %4d", From 15ec2ca964d7a52e7e0a452fe0f9c409d2f3eec6 Mon Sep 17 00:00:00 2001 From: Subhajit Paul Date: Fri, 11 Apr 2014 12:53:30 +0530 Subject: [PATCH 091/279] drm/omap: Fix memory leak in omap_gem_op_async In omap_gem_op_async(), if a waiter is not added to the wait list, it needs to be free'd in the function itself. Make sure we free the waiter for this case. Signed-off-by: Subhajit Paul Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_gem.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 70798b9fe63576..9a68e9a284381e 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1226,6 +1226,8 @@ int omap_gem_op_async(struct drm_gem_object *obj, enum omap_gem_op op, } spin_unlock(&sync_lock); + + kfree(waiter); } /* no waiting.. */ From f2cff0f34ff2c51f703880a2b883ea0c9de4a5ac Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 11 Apr 2014 12:53:31 +0530 Subject: [PATCH 092/279] drm/omap: gem sync: wait on correct events A waiter of the type OMAP_GEM_READ should wait for a buffer to be completely written, and only then proceed with reading it. A similar logic applies for waiters with OMAP_GEM_WRITE flag. Currently the function is_waiting() waits on the read_complete/read_target counts in the sync object. This should be the other way round, as a reader should wait for users who are 'writing' to this buffer, and vice versa. Make readers of the buffer(OMAP_GEM_READ) wait on the write counters, and writers to the buffer(OMAP_GEM_WRITE) wait on the read counters in is_waiting() Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_gem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 9a68e9a284381e..95dbce286a4134 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1047,10 +1047,10 @@ static inline bool is_waiting(struct omap_gem_sync_waiter *waiter) { struct omap_gem_object *omap_obj = waiter->omap_obj; if ((waiter->op & OMAP_GEM_READ) && - (omap_obj->sync->read_complete < waiter->read_target)) + (omap_obj->sync->write_complete < waiter->write_target)) return true; if ((waiter->op & OMAP_GEM_WRITE) && - (omap_obj->sync->write_complete < waiter->write_target)) + (omap_obj->sync->read_complete < waiter->read_target)) return true; return false; } From 71b6667765c7019f3fd5ea5e0c02f65f7331f3e1 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 11 Apr 2014 12:53:32 +0530 Subject: [PATCH 093/279] drm/omap: Fix crash when using LCD3 overlay manager The channel_names list didn't have a string populated for LCD3 manager, this results in a crash when the display's output is connected to LCD3. Add an entry for LCD3. Reported-by: Somnath Mukherjee Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index b3a7529845b952..46f8e1e40e88a9 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -654,6 +654,7 @@ static const char *channel_names[] = { [OMAP_DSS_CHANNEL_LCD] = "lcd", [OMAP_DSS_CHANNEL_DIGIT] = "tv", [OMAP_DSS_CHANNEL_LCD2] = "lcd2", + [OMAP_DSS_CHANNEL_LCD3] = "lcd3", }; void omap_crtc_pre_init(void) From bc905aced30e48a39af7c452bf46228d7c6188b9 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 11 Apr 2014 12:53:34 +0530 Subject: [PATCH 094/279] drm/omap: Use old_fb to synchronize between successive page flips omap_crtc->old_fb is used to check whether the previous page flip has completed or not. However, it's never initialized to anything, so it's always NULL. This results in the check to always succeed, and the page_flip to proceed. Initialize old_fb to the fb that we intend to flip to through page_flip, and therefore prevent a future page flip to proceed if the last one didn't complete. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 46f8e1e40e88a9..00798247190bce 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -360,7 +360,7 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, } omap_crtc->event = event; - primary->fb = fb; + omap_crtc->old_fb = primary->fb = fb; /* * Hold a reference temporarily until the crtc is updated From 38e5597a03d2d1499a785230031c4f48e1d9c6b7 Mon Sep 17 00:00:00 2001 From: Archit Taneja Date: Fri, 11 Apr 2014 12:53:35 +0530 Subject: [PATCH 095/279] drm/omap: protect omap_crtc's event with event_lock spinlock The vblank_cb callback and the page_flip ioctl can occur together in different CPU contexts. vblank_cb uses takes tje drm device's event_lock spinlock when sending the vblank event and updating omap_crtc->event and omap_crtc->od_fb. Use the same spinlock in page_flip, to make sure the above omap_crtc parameters are configured sequentially. Signed-off-by: Archit Taneja Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 00798247190bce..e3c47a8005ff14 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -350,11 +350,15 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_plane *primary = crtc->primary; struct drm_gem_object *bo; + unsigned long flags; DBG("%d -> %d (event=%p)", primary->fb ? primary->fb->base.id : -1, fb->base.id, event); + spin_lock_irqsave(&dev->event_lock, flags); + if (omap_crtc->old_fb) { + spin_unlock_irqrestore(&dev->event_lock, flags); dev_err(dev->dev, "already a pending flip\n"); return -EINVAL; } @@ -362,6 +366,8 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, omap_crtc->event = event; omap_crtc->old_fb = primary->fb = fb; + spin_unlock_irqrestore(&dev->event_lock, flags); + /* * Hold a reference temporarily until the crtc is updated * and takes the reference to the bo. This avoids it From 16c50dcfc4c186ed09a4d80fbd511492d024a1c5 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Fri, 28 Feb 2014 15:37:10 +0000 Subject: [PATCH 096/279] iommu/arm-smmu: Return 0 on unmap failure The IOMMU core expects the unmap operation to return the number of bytes that have been unmapped or 0 on failure, a negative return value being treated like a number of bytes. Signed-off-by: Laurent Pinchart Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 8b89e33a89fe99..69d001a71b227a 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1499,7 +1499,7 @@ static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova, ret = arm_smmu_handle_mapping(smmu_domain, iova, 0, size, 0); arm_smmu_tlb_inv_context(&smmu_domain->root_cfg); - return ret ? ret : size; + return ret ? 0 : size; } static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain, From aca1bc4595c5757f01167ab5bfef2a4f8edfcf4f Mon Sep 17 00:00:00 2001 From: Bin Wang Date: Fri, 21 Mar 2014 10:06:07 +0000 Subject: [PATCH 097/279] iommu/arm-smmu: fix panic in arm_smmu_alloc_init_pte MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kernel panic happened when iommu_unmap a buffer larger than 2MB, more than expected pmd entries got “invalidated”, due to a wrong range passed to arm_smmu_alloc_init_pte. it was likely a typo, now we fix it, passing the correct "end" address to arm_smmu_alloc_init_pte. Signed-off-by: Bin Wang Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 69d001a71b227a..647c3c7fd7428f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1381,7 +1381,7 @@ static int arm_smmu_alloc_init_pmd(struct arm_smmu_device *smmu, pud_t *pud, do { next = pmd_addr_end(addr, end); - ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, end, pfn, + ret = arm_smmu_alloc_init_pte(smmu, pmd, addr, next, pfn, prot, stage); phys += next - addr; } while (pmd++, addr = next, addr < end); From f2d022aa421ca903a30f63b04528064b7eceaf5e Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Tue, 15 Apr 2014 16:26:01 +0300 Subject: [PATCH 098/279] drm/omap: fix the handling of fb ref counts With the recent primary-plane changes for drm, the primary plane's framebuffer needs to be ref counted the same way as for non-primary-planes. This was not done by the omapdrm driver, which caused the ref count to drop to 0 too early, causing problems. This patch moves the fb unref and ref from omap_plane_update to omap_plane_mode_set. This way the fb refs are updated for both primary and non-primary cases, as omap_plane_update calls omap_plane_mode_set. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_plane.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index df1725247ccaa5..3cf31ee59aac08 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -225,6 +225,11 @@ int omap_plane_mode_set(struct drm_plane *plane, omap_plane->apply_done_cb.arg = arg; } + if (plane->fb) + drm_framebuffer_unreference(plane->fb); + + drm_framebuffer_reference(fb); + plane->fb = fb; plane->crtc = crtc; @@ -241,11 +246,6 @@ static int omap_plane_update(struct drm_plane *plane, struct omap_plane *omap_plane = to_omap_plane(plane); omap_plane->enabled = true; - if (plane->fb) - drm_framebuffer_unreference(plane->fb); - - drm_framebuffer_reference(fb); - /* omap_plane_mode_set() takes adjusted src */ switch (omap_plane->win.rotation & 0xf) { case BIT(DRM_ROTATE_90): From 4461bbc05bf11fa4251acded60e4645863a4158a Mon Sep 17 00:00:00 2001 From: Boris Ostrovsky Date: Thu, 10 Apr 2014 12:17:09 -0400 Subject: [PATCH 099/279] x86/xen: Fix 32-bit PV guests's usage of kernel_stack Commit 198d208df4371734ac4728f69cb585c284d20a15 ("x86: Keep thread_info on thread stack in x86_32") made 32-bit kernels use kernel_stack to point to thread_info. That change missed a couple of updates needed by Xen's 32-bit PV guests: 1. kernel_stack needs to be initialized for secondary CPUs 2. GET_THREAD_INFO() now uses %fs register which may not be the kernel's version when executing xen_iret(). With respect to the second issue, we don't need GET_THREAD_INFO() anymore: we used it as an intermediate step to get to per_cpu xen_vcpu and avoid referencing %fs. Now that we are going to use %fs anyway we may as well go directly to xen_vcpu. Signed-off-by: Boris Ostrovsky Signed-off-by: David Vrabel --- arch/x86/xen/smp.c | 3 ++- arch/x86/xen/xen-asm_32.S | 25 +++++++++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index a18eadd8bb4039..7005974c3ff308 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -441,10 +441,11 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle) irq_ctx_init(cpu); #else clear_tsk_thread_flag(idle, TIF_FORK); +#endif per_cpu(kernel_stack, cpu) = (unsigned long)task_stack_page(idle) - KERNEL_STACK_OFFSET + THREAD_SIZE; -#endif + xen_setup_runstate_info(cpu); xen_setup_timer(cpu); xen_init_lock_cpu(cpu); diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index 33ca6e42a4caab..fd92a64d748e1c 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -75,6 +75,17 @@ ENDPROC(xen_sysexit) * stack state in whatever form its in, we keep things simple by only * using a single register which is pushed/popped on the stack. */ + +.macro POP_FS +1: + popw %fs +.pushsection .fixup, "ax" +2: movw $0, (%esp) + jmp 1b +.popsection + _ASM_EXTABLE(1b,2b) +.endm + ENTRY(xen_iret) /* test eflags for special cases */ testl $(X86_EFLAGS_VM | XEN_EFLAGS_NMI), 8(%esp) @@ -83,15 +94,13 @@ ENTRY(xen_iret) push %eax ESP_OFFSET=4 # bytes pushed onto stack - /* - * Store vcpu_info pointer for easy access. Do it this way to - * avoid having to reload %fs - */ + /* Store vcpu_info pointer for easy access */ #ifdef CONFIG_SMP - GET_THREAD_INFO(%eax) - movl %ss:TI_cpu(%eax), %eax - movl %ss:__per_cpu_offset(,%eax,4), %eax - mov %ss:xen_vcpu(%eax), %eax + pushw %fs + movl $(__KERNEL_PERCPU), %eax + movl %eax, %fs + movl %fs:xen_vcpu, %eax + POP_FS #else movl %ss:xen_vcpu, %eax #endif From cea37f87519ca3172a4e8ddd3ffcd2b4232b341f Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Tue, 1 Apr 2014 19:15:59 +0900 Subject: [PATCH 100/279] xen: fix memory leak in __xen_pcibk_add_pci_dev() It need to free dev_entry when it failed to assign to a new slot on the virtual PCI bus. smatch says: drivers/xen/xen-pciback/vpci.c:142 __xen_pcibk_add_pci_dev() warn: possible memory leak of 'dev_entry' Signed-off-by: Daeseok Youn Signed-off-by: David Vrabel --- drivers/xen/xen-pciback/vpci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c index 3165ce361b0012..51afff96c515c0 100644 --- a/drivers/xen/xen-pciback/vpci.c +++ b/drivers/xen/xen-pciback/vpci.c @@ -137,6 +137,8 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, /* Publish this device. */ if (!err) err = publish_cb(pdev, 0, 0, PCI_DEVFN(slot, func), devid); + else + kfree(dev_entry); out: return err; From c0914e61660fa7d501ef9394b26f4847ef3dc98e Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 28 Mar 2014 11:24:59 +0300 Subject: [PATCH 101/279] xen-pciback: silence an unwanted debug printk There is a missing curly brace here so we might print some extra debug information. Signed-off-by: Dan Carpenter Signed-off-by: David Vrabel --- drivers/xen/xen-pciback/pciback_ops.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 929dd46bb40c5a..607e41460c0d7e 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -217,7 +217,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, if (result == 0) { for (i = 0; i < op->value; i++) { op->msix_entries[i].entry = entries[i].entry; - if (entries[i].vector) + if (entries[i].vector) { op->msix_entries[i].vector = xen_pirq_from_irq(entries[i].vector); if (unlikely(verbose_request)) @@ -225,6 +225,7 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, "MSI-X[%d]: %d\n", pci_name(dev), i, op->msix_entries[i].vector); + } } } else pr_warn_ratelimited("%s: error enabling MSI-X for guest %u: err %d!\n", From e0fc17a936334c08b2729fff87168c03fdecf5b6 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 4 Apr 2014 14:48:04 -0400 Subject: [PATCH 102/279] xen/spinlock: Don't enable them unconditionally. The git commit a945928ea2709bc0e8e8165d33aed855a0110279 ('xen: Do not enable spinlocks before jump_label_init() has executed') was added to deal with the jump machinery. Earlier the code that turned on the jump label was only called by Xen specific functions. But now that it had been moved to the initcall machinery it gets called on Xen, KVM, and baremetal - ouch!. And the detection machinery to only call it on Xen wasn't remembered in the heat of merge window excitement. This means that the slowpath is enabled on baremetal while it should not be. Reported-by: Waiman Long Acked-by: Steven Rostedt CC: stable@vger.kernel.org CC: Boris Ostrovsky Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: David Vrabel --- arch/x86/xen/spinlock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index 4d3acc34a998e5..0ba5f3b967f004 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -274,7 +274,7 @@ void __init xen_init_spinlocks(void) printk(KERN_DEBUG "xen: PV spinlocks disabled\n"); return; } - + printk(KERN_DEBUG "xen: PV spinlocks enabled\n"); pv_lock_ops.lock_spinning = PV_CALLEE_SAVE(xen_lock_spinning); pv_lock_ops.unlock_kick = xen_unlock_kick; } @@ -290,6 +290,9 @@ static __init int xen_init_spinlocks_jump(void) if (!xen_pvspin) return 0; + if (!xen_domain()) + return 0; + static_key_slow_inc(¶virt_ticketlocks_enabled); return 0; } From 027bd7e89906a076225b23d1ca4b6702c84e72dc Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 4 Apr 2014 14:53:40 -0400 Subject: [PATCH 103/279] xen/xenbus: Avoid synchronous wait on XenBus stalling shutdown/restart. The 'read_reply' works with 'process_msg' to read of a reply in XenBus. 'process_msg' is running from within the 'xenbus' thread. Whenever a message shows up in XenBus it is put on a xs_state.reply_list list and 'read_reply' picks it up. The problem is if the backend domain or the xenstored process is killed. In which case 'xenbus' is still awaiting - and 'read_reply' if called - stuck forever waiting for the reply_list to have some contents. This is normally not a problem - as the backend domain can come back or the xenstored process can be restarted. However if the domain is in process of being powered off/restarted/halted - there is no point of waiting on it coming back - as we are effectively being terminated and should not impede the progress. This patch solves this problem by checking whether the guest is the right domain. If it is an initial domain and hurtling towards death - there is no point of continuing the wait. All other type of guests continue with their behavior (as Xenstore is expected to still be running in another domain). Fixes-Bug: http://bugs.xenproject.org/xen/bug/8 Signed-off-by: Konrad Rzeszutek Wilk Reviewed-by: Boris Ostrovsky Reviewed-by: David Vrabel Signed-off-by: David Vrabel --- drivers/xen/xenbus/xenbus_xs.c | 44 +++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index b6d5fff43d16b9..ba804f3d8278d9 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c @@ -50,6 +50,7 @@ #include #include #include "xenbus_comms.h" +#include "xenbus_probe.h" struct xs_stored_msg { struct list_head list; @@ -139,6 +140,29 @@ static int get_error(const char *errorstring) return xsd_errors[i].errnum; } +static bool xenbus_ok(void) +{ + switch (xen_store_domain_type) { + case XS_LOCAL: + switch (system_state) { + case SYSTEM_POWER_OFF: + case SYSTEM_RESTART: + case SYSTEM_HALT: + return false; + default: + break; + } + return true; + case XS_PV: + case XS_HVM: + /* FIXME: Could check that the remote domain is alive, + * but it is normally initial domain. */ + return true; + default: + break; + } + return false; +} static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) { struct xs_stored_msg *msg; @@ -148,9 +172,20 @@ static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len) while (list_empty(&xs_state.reply_list)) { spin_unlock(&xs_state.reply_lock); - /* XXX FIXME: Avoid synchronous wait for response here. */ - wait_event(xs_state.reply_waitq, - !list_empty(&xs_state.reply_list)); + if (xenbus_ok()) + /* XXX FIXME: Avoid synchronous wait for response here. */ + wait_event_timeout(xs_state.reply_waitq, + !list_empty(&xs_state.reply_list), + msecs_to_jiffies(500)); + else { + /* + * If we are in the process of being shut-down there is + * no point of trying to contact XenBus - it is either + * killed (xenstored application) or the other domain + * has been killed or is unreachable. + */ + return ERR_PTR(-EIO); + } spin_lock(&xs_state.reply_lock); } @@ -215,6 +250,9 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg) mutex_unlock(&xs_state.request_mutex); + if (IS_ERR(ret)) + return ret; + if ((msg->type == XS_TRANSACTION_END) || ((req_msg.type == XS_TRANSACTION_START) && (msg->type == XS_ERROR))) From eb47f71200b7d5b4c8c1f8c75675f592d855aafd Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Fri, 4 Apr 2014 14:53:41 -0400 Subject: [PATCH 104/279] xen/manage: Poweroff forcefully if user-space is not yet up. The user can launch the guest in this sequence: xl create -p /vm.cfg [launch, but pause it] xl shutdown latest [sets control/shutdown=poweroff] xl unpause latest xl console latest [and see that the guest has completely ignored the shutdown request] In reality the guest hasn't ignored it. It registers a watch and gets a notification that there is value. It then calls the shutdown_handler which ends up calling orderly_shutdown. Unfortunately that is so early in the bootup that there are no user-space. Which means that the orderly_shutdown fails. But since the force flag was set to false it continues on without reporting. What we really want to is to use the force when we are in the SYSTEM_BOOTING state and not use the 'force' when SYSTEM_RUNNING. However, if we are in the running state - and the shutdown command has been given before the user-space has been setup, there is nothing we can do. Worst yet, we stop ignoring the 'xl shutdown' requests! As such, the other part of this patch is to only stop ignoring the 'xl shutdown' when we are truly in the power off sequence. That means the user can do multiple 'xl shutdown' and we will try to act on them instead of ignoring them. Fixes-Bug: http://bugs.xenproject.org/xen/bug/6 Reported-by: Alex Bligh Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: David Vrabel --- drivers/xen/manage.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index fc6c94c0b436f5..32f9236c959fd3 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -198,10 +198,32 @@ struct shutdown_handler { void (*cb)(void); }; +static int poweroff_nb(struct notifier_block *cb, unsigned long code, void *unused) +{ + switch (code) { + case SYS_DOWN: + case SYS_HALT: + case SYS_POWER_OFF: + shutting_down = SHUTDOWN_POWEROFF; + default: + break; + } + return NOTIFY_DONE; +} static void do_poweroff(void) { - shutting_down = SHUTDOWN_POWEROFF; - orderly_poweroff(false); + switch (system_state) { + case SYSTEM_BOOTING: + orderly_poweroff(true); + break; + case SYSTEM_RUNNING: + orderly_poweroff(false); + break; + default: + /* Don't do it when we are halting/rebooting. */ + pr_info("Ignoring Xen toolstack shutdown.\n"); + break; + } } static void do_reboot(void) @@ -307,6 +329,10 @@ static struct xenbus_watch shutdown_watch = { .callback = shutdown_handler }; +static struct notifier_block xen_reboot_nb = { + .notifier_call = poweroff_nb, +}; + static int setup_shutdown_watcher(void) { int err; @@ -317,6 +343,7 @@ static int setup_shutdown_watcher(void) return err; } + #ifdef CONFIG_MAGIC_SYSRQ err = register_xenbus_watch(&sysrq_watch); if (err) { @@ -345,6 +372,7 @@ int xen_setup_shutdown_event(void) if (!xen_domain()) return -ENODEV; register_xenstore_notifier(&xenstore_notifier); + register_reboot_notifier(&xen_reboot_nb); return 0; } From 20474129d8bb0e6f113634f4f0f4f1584d0beed2 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 14 Apr 2014 15:31:05 -0700 Subject: [PATCH 105/279] mwifiex: process event before command response During extended scan, SCAN report event is always followed by command response. Sometimes It is observed that command response is processed before SCAN report which leads to a crash, because current command node is cleared while handling the response. This patch makes sure that driver's main thread gives priority to events over command responses. Signed-off-by: Amitkumar Karwar Signed-off-by: Maithili Hinge Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 77db0886c6e2e9..9c771b3e99186f 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -292,6 +292,12 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) mwifiex_handle_rx_packet(adapter, skb); + /* Check for event */ + if (adapter->event_received) { + adapter->event_received = false; + mwifiex_process_event(adapter); + } + /* Check for Cmd Resp */ if (adapter->cmd_resp_received) { adapter->cmd_resp_received = false; @@ -304,12 +310,6 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) } } - /* Check for event */ - if (adapter->event_received) { - adapter->event_received = false; - mwifiex_process_event(adapter); - } - /* Check if we need to confirm Sleep Request received previously */ if (adapter->ps_state == PS_STATE_PRE_SLEEP) { From f8d2b9209ad648a8e9aa973d32fb64aa2ab01d00 Mon Sep 17 00:00:00 2001 From: Amitkumar Karwar Date: Mon, 14 Apr 2014 15:31:06 -0700 Subject: [PATCH 106/279] mwifiex: fix hung task on command timeout Sometimes when command timeout occurs due to a firmware or hardware bug, there may be some synchronous commands in command queue. These commands are never downloaded to firmware causing hung task warnings. This patch replaces wait_event_interruptible call with wait_event_interruptible_timeout to fix the issue. Signed-off-by: Amitkumar Karwar Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_ioctl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 894270611f2cb6..536c14aa71f39c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -60,9 +60,10 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, int status; /* Wait for completion */ - status = wait_event_interruptible(adapter->cmd_wait_q.wait, - *(cmd_queued->condition)); - if (status) { + status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait, + *(cmd_queued->condition), + (12 * HZ)); + if (status <= 0) { dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); mwifiex_cancel_all_pending_cmd(adapter); return status; From 521c42990e9d561ed5ed9f501f07639d0512b3c9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 15 Apr 2014 10:54:37 +0530 Subject: [PATCH 107/279] tick-common: Fix wrong check in tick_check_replacement() tick_check_replacement() returns if a replacement of clock_event_device is possible or not. It does this as the first check: if (tick_check_percpu(curdev, newdev, smp_processor_id())) return false; Thats wrong. tick_check_percpu() returns true when the device is useable. Check for false instead. [ tglx: Massaged changelog ] Signed-off-by: Viresh Kumar Cc: # v3.11+ Cc: linaro-kernel@lists.linaro.org Cc: fweisbec@gmail.com Cc: Arvind.Chauhan@arm.com Cc: linaro-networking@linaro.org Link: http://lkml.kernel.org/r/486a02efe0246635aaba786e24b42d316438bf3b.1397537987.git.viresh.kumar@linaro.org Signed-off-by: Thomas Gleixner --- kernel/time/tick-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index 015661279b682f..0a0608edeb2665 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -276,7 +276,7 @@ static bool tick_check_preferred(struct clock_event_device *curdev, bool tick_check_replacement(struct clock_event_device *curdev, struct clock_event_device *newdev) { - if (tick_check_percpu(curdev, newdev, smp_processor_id())) + if (!tick_check_percpu(curdev, newdev, smp_processor_id())) return false; return tick_check_preferred(curdev, newdev); From 03e6bdc5c4d0fc166bfd5d3cf749a5a0c1b5b1bd Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 15 Apr 2014 10:54:40 +0530 Subject: [PATCH 108/279] tick-sched: Don't call update_wall_time() when delta is lesser than tick_period In tick_do_update_jiffies64() we are processing ticks only if delta is greater than tick_period. This is what we are supposed to do here and it broke a bit with this patch: commit 47a1b796 (tick/timekeeping: Call update_wall_time outside the jiffies lock) With above patch, we might end up calling update_wall_time() even if delta is found to be smaller that tick_period. Fix this by returning when the delta is less than tick period. [ tglx: Made it a 3 liner and massaged changelog ] Signed-off-by: Viresh Kumar Cc: linaro-kernel@lists.linaro.org Cc: fweisbec@gmail.com Cc: Arvind.Chauhan@arm.com Cc: linaro-networking@linaro.org Cc: John Stultz Cc: # v3.14+ Link: http://lkml.kernel.org/r/80afb18a494b0bd9710975bcc4de134ae323c74f.1397537987.git.viresh.kumar@linaro.org Signed-off-by: Thomas Gleixner --- kernel/time/tick-sched.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 9f8af69c67ecb2..e947d968c5b57f 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -84,6 +84,9 @@ static void tick_do_update_jiffies64(ktime_t now) /* Keep the tick_next_period variable up to date */ tick_next_period = ktime_add(last_jiffies_update, tick_period); + } else { + write_sequnlock(&jiffies_lock); + return; } write_sequnlock(&jiffies_lock); update_wall_time(); From 27630532ef5ead28b98cfe28d8f95222ef91c2b7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 15 Apr 2014 10:54:41 +0530 Subject: [PATCH 109/279] tick-sched: Check tick_nohz_enabled in tick_nohz_switch_to_nohz() Since commit d689fe222 (NOHZ: Check for nohz active instead of nohz enabled) the tick_nohz_switch_to_nohz() function returns because it checks for the tick_nohz_active flag. This can't be set, because the function itself sets it. Undo the change in tick_nohz_switch_to_nohz(). Signed-off-by: Viresh Kumar Cc: linaro-kernel@lists.linaro.org Cc: fweisbec@gmail.com Cc: Arvind.Chauhan@arm.com Cc: linaro-networking@linaro.org Cc: # 3.13+ Link: http://lkml.kernel.org/r/40939c05f2d65d781b92b20302b02243d0654224.1397537987.git.viresh.kumar@linaro.org Signed-off-by: Thomas Gleixner --- kernel/time/tick-sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index e947d968c5b57f..6558b7ac112d2e 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -970,7 +970,7 @@ static void tick_nohz_switch_to_nohz(void) struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); ktime_t next; - if (!tick_nohz_active) + if (!tick_nohz_enabled) return; local_irq_disable(); From 29d1e7209e1866a1b6b686107cce9f5a9b886a53 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 21 Mar 2014 00:42:54 +0100 Subject: [PATCH 110/279] staging/rtl8821ae: Fix OOM handling in _rtl_init_deferred_work() alloc_workqueue() can fail, handle this case. Signed-off-by: Richard Weinberger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8821ae/base.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8821ae/base.c b/drivers/staging/rtl8821ae/base.c index e5073fe2477063..a4c9cc437bc6e3 100644 --- a/drivers/staging/rtl8821ae/base.c +++ b/drivers/staging/rtl8821ae/base.c @@ -388,7 +388,7 @@ static void _rtl_init_mac80211(struct ieee80211_hw *hw) } -static void _rtl_init_deferred_work(struct ieee80211_hw *hw) +static int _rtl_init_deferred_work(struct ieee80211_hw *hw) { struct rtl_priv *rtlpriv = rtl_priv(hw); @@ -410,6 +410,9 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) rtlpriv->works.rtl_wq = create_workqueue(rtlpriv->cfg->name); #endif /**/ + if (!rtlpriv->works.rtl_wq) + return -ENOMEM; + INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, (void *)rtl_watchdog_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, @@ -421,6 +424,8 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, (void *)rtl_fwevt_wq_callback); + return 0; + } void rtl_deinit_deferred_work(struct ieee80211_hw *hw) @@ -519,7 +524,8 @@ int rtl_init_core(struct ieee80211_hw *hw) INIT_LIST_HEAD(&rtlpriv->entry_list); /* <6> init deferred work */ - _rtl_init_deferred_work(hw); + if (_rtl_init_deferred_work(hw)) + return 1; /* <7> */ #ifdef VIF_TODO From e7a62df8e8b4a5ecbbf4339b5b3671ae6582e50a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 15 Apr 2014 08:38:17 -0700 Subject: [PATCH 111/279] of: Clean up of_update_property After searching for the old property, bail out with -ENODEV if it was not found. It is unnecessary to check if oldprop is NULL before removing its binary file; the check was already done before. Signed-off-by: Guenter Roeck Signed-off-by: Rob Herring --- drivers/of/base.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/of/base.c b/drivers/of/base.c index f72d19b7e5d299..6d4ee22708c937 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1828,17 +1828,13 @@ int of_update_property(struct device_node *np, struct property *newprop) next = &(*next)->next; } raw_spin_unlock_irqrestore(&devtree_lock, flags); - if (rc) - return rc; + if (!found) + return -ENODEV; /* Update the sysfs attribute */ - if (oldprop) - sysfs_remove_bin_file(&np->kobj, &oldprop->attr); + sysfs_remove_bin_file(&np->kobj, &oldprop->attr); __of_add_property_sysfs(np, newprop); - if (!found) - return -ENODEV; - return 0; } From ec03ab77cc2c39d115118fcd4fc11a5801cbb70e Mon Sep 17 00:00:00 2001 From: Wilfried Klaebe Date: Tue, 25 Mar 2014 17:59:39 +0000 Subject: [PATCH 112/279] staging: rtl8188eu: remove spaces, correct counts to unbreak P2P ioctls staging: rtl8188eu: remove spaces, correct counts to unbreak P2P ioctls It looks like someone did a search-and-replace on that driver, putting spaces before "=" characters, without checking this is OK everywhere. Also, in some places, there's memcpm()s/strncmp()s checking for some different length than the fixed string argument. These things result in code not working as intended. Fix that. Signed-off-by: Wilfried Klaebe Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8188eu/os_dep/ioctl_linux.c | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c index 2636e7f3dbb8c5..cf30a08912d176 100644 --- a/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8188eu/os_dep/ioctl_linux.c @@ -359,7 +359,7 @@ static char *translate_scan(struct adapter *padapter, if (wpa_len > 0) { p = buf; _rtw_memset(buf, 0, MAX_WPA_IE_LEN); - p += sprintf(p, "wpa_ie ="); + p += sprintf(p, "wpa_ie="); for (i = 0; i < wpa_len; i++) p += sprintf(p, "%02x", wpa_ie[i]); @@ -376,7 +376,7 @@ static char *translate_scan(struct adapter *padapter, if (rsn_len > 0) { p = buf; _rtw_memset(buf, 0, MAX_WPA_IE_LEN); - p += sprintf(p, "rsn_ie ="); + p += sprintf(p, "rsn_ie="); for (i = 0; i < rsn_len; i++) p += sprintf(p, "%02x", rsn_ie[i]); _rtw_memset(&iwe, 0, sizeof(iwe)); @@ -2899,7 +2899,7 @@ static int rtw_p2p_get_status(struct net_device *dev, /* Commented by Albert 2010/10/12 */ /* Because of the output size limitation, I had removed the "Role" information. */ /* About the "Role" information, we will use the new private IOCTL to get the "Role" information. */ - sprintf(extra, "\n\nStatus =%.2d\n", rtw_p2p_state(pwdinfo)); + sprintf(extra, "\n\nStatus=%.2d\n", rtw_p2p_state(pwdinfo)); wrqu->data.length = strlen(extra); return ret; @@ -2918,7 +2918,7 @@ static int rtw_p2p_get_req_cm(struct net_device *dev, struct adapter *padapter = (struct adapter *)rtw_netdev_priv(dev); struct wifidirect_info *pwdinfo = &(padapter->wdinfo); - sprintf(extra, "\n\nCM =%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req); + sprintf(extra, "\n\nCM=%s\n", pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req); wrqu->data.length = strlen(extra); return ret; } @@ -2935,7 +2935,7 @@ static int rtw_p2p_get_role(struct net_device *dev, pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1], pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3], pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5]); - sprintf(extra, "\n\nRole =%.2d\n", rtw_p2p_role(pwdinfo)); + sprintf(extra, "\n\nRole=%.2d\n", rtw_p2p_role(pwdinfo)); wrqu->data.length = strlen(extra); return ret; } @@ -3022,7 +3022,7 @@ static int rtw_p2p_get_op_ch(struct net_device *dev, DBG_88E("[%s] Op_ch = %02x\n", __func__, pwdinfo->operating_channel); - sprintf(extra, "\n\nOp_ch =%.2d\n", pwdinfo->operating_channel); + sprintf(extra, "\n\nOp_ch=%.2d\n", pwdinfo->operating_channel); wrqu->data.length = strlen(extra); return ret; } @@ -3043,7 +3043,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev, u8 blnMatch = 0; u16 attr_content = 0; uint attr_contentlen = 0; - /* 6 is the string "wpsCM =", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */ + /* 6 is the string "wpsCM=", 17 is the MAC addr, we have to clear it at wrqu->data.pointer */ u8 attr_content_str[6 + 17] = {0x00}; /* Commented by Albert 20110727 */ @@ -3079,7 +3079,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev, rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_CONF_METHOD, (u8 *) &be_tmp, &attr_contentlen); if (attr_contentlen) { attr_content = be16_to_cpu(be_tmp); - sprintf(attr_content_str, "\n\nM =%.4d", attr_content); + sprintf(attr_content_str, "\n\nM=%.4d", attr_content); blnMatch = 1; } } @@ -3091,7 +3091,7 @@ static int rtw_p2p_get_wps_configmethod(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - sprintf(attr_content_str, "\n\nM = 0000"); + sprintf(attr_content_str, "\n\nM=0000"); if (copy_to_user(wrqu->data.pointer, attr_content_str, 6 + 17)) return -EFAULT; @@ -3172,9 +3172,9 @@ static int rtw_p2p_get_go_device_address(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add = NULL"); + snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=NULL"); else - snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add =%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", + snprintf(go_devadd_str, sizeof(go_devadd_str), "\n\ndev_add=%.2X:%.2X:%.2X:%.2X:%.2X:%.2X", attr_content[0], attr_content[1], attr_content[2], attr_content[3], attr_content[4], attr_content[5]); if (copy_to_user(wrqu->data.pointer, go_devadd_str, sizeof(go_devadd_str))) @@ -3198,7 +3198,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev, u8 blnMatch = 0; u8 dev_type[8] = {0x00}; uint dev_type_len = 0; - u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type =", we have to clear it at wrqu->data.pointer */ + u8 dev_type_str[17 + 9] = {0x00}; /* +9 is for the str "dev_type=", we have to clear it at wrqu->data.pointer */ /* Commented by Albert 20121209 */ /* The input data is the MAC address which the application wants to know its device type. */ @@ -3239,7 +3239,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev, memcpy(&be_tmp, dev_type, 2); type = be16_to_cpu(be_tmp); - sprintf(dev_type_str, "\n\nN =%.2d", type); + sprintf(dev_type_str, "\n\nN=%.2d", type); blnMatch = 1; } } @@ -3252,7 +3252,7 @@ static int rtw_p2p_get_device_type(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - sprintf(dev_type_str, "\n\nN = 00"); + sprintf(dev_type_str, "\n\nN=00"); if (copy_to_user(wrqu->data.pointer, dev_type_str, 9 + 17)) { return -EFAULT; @@ -3277,7 +3277,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev, u8 blnMatch = 0; u8 dev_name[WPS_MAX_DEVICE_NAME_LEN] = {0x00}; uint dev_len = 0; - u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN =", we have to clear it at wrqu->data.pointer */ + u8 dev_name_str[WPS_MAX_DEVICE_NAME_LEN + 5] = {0x00}; /* +5 is for the str "devN=", we have to clear it at wrqu->data.pointer */ /* Commented by Albert 20121225 */ /* The input data is the MAC address which the application wants to know its device name. */ @@ -3310,7 +3310,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev, if (wpsie) { rtw_get_wps_attr_content(wpsie, wpsie_len, WPS_ATTR_DEVICE_NAME, dev_name, &dev_len); if (dev_len) { - sprintf(dev_name_str, "\n\nN =%s", dev_name); + sprintf(dev_name_str, "\n\nN=%s", dev_name); blnMatch = 1; } } @@ -3323,7 +3323,7 @@ static int rtw_p2p_get_device_name(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) - sprintf(dev_name_str, "\n\nN = 0000"); + sprintf(dev_name_str, "\n\nN=0000"); if (copy_to_user(wrqu->data.pointer, dev_name_str, 5 + ((dev_len > 17) ? dev_len : 17))) return -EFAULT; @@ -3349,7 +3349,7 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev, u8 attr_content[2] = {0x00}; u8 inv_proc_str[17 + 8] = {0x00}; - /* +8 is for the str "InvProc =", we have to clear it at wrqu->data.pointer */ + /* +8 is for the str "InvProc=", we have to clear it at wrqu->data.pointer */ /* Commented by Ouden 20121226 */ /* The application wants to know P2P initiation procedure is supported or not. */ @@ -3397,12 +3397,12 @@ static int rtw_p2p_get_invitation_procedure(struct net_device *dev, spin_unlock_bh(&pmlmepriv->scanned_queue.lock); if (!blnMatch) { - sprintf(inv_proc_str, "\nIP =-1"); + sprintf(inv_proc_str, "\nIP=-1"); } else { if (attr_content[0] & 0x20) - sprintf(inv_proc_str, "\nIP = 1"); + sprintf(inv_proc_str, "\nIP=1"); else - sprintf(inv_proc_str, "\nIP = 0"); + sprintf(inv_proc_str, "\nIP=0"); } if (copy_to_user(wrqu->data.pointer, inv_proc_str, 8 + 17)) return -EFAULT; @@ -3512,7 +3512,7 @@ static int rtw_p2p_invite_req(struct net_device *dev, /* The input data contains two informations. */ /* 1. First information is the P2P device address which you want to send to. */ /* 2. Second information is the group id which combines with GO's mac address, space and GO's ssid. */ - /* Command line sample: iwpriv wlan0 p2p_set invite ="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */ + /* Command line sample: iwpriv wlan0 p2p_set invite="00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy" */ /* Format: 00:11:22:33:44:55 00:E0:4C:00:00:05 DIRECT-xy */ DBG_88E("[%s] data = %s\n", __func__, extra); @@ -3805,48 +3805,48 @@ static int rtw_p2p_set(struct net_device *dev, #ifdef CONFIG_88EU_P2P DBG_88E("[%s] extra = %s\n", __func__, extra); - if (!memcmp(extra, "enable =", 7)) { + if (!memcmp(extra, "enable=", 7)) { rtw_wext_p2p_enable(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "setDN =", 6)) { + } else if (!memcmp(extra, "setDN=", 6)) { wrqu->data.length -= 6; rtw_p2p_setDN(dev, info, wrqu, &extra[6]); - } else if (!memcmp(extra, "profilefound =", 13)) { + } else if (!memcmp(extra, "profilefound=", 13)) { wrqu->data.length -= 13; rtw_p2p_profilefound(dev, info, wrqu, &extra[13]); - } else if (!memcmp(extra, "prov_disc =", 10)) { + } else if (!memcmp(extra, "prov_disc=", 10)) { wrqu->data.length -= 10; rtw_p2p_prov_disc(dev, info, wrqu, &extra[10]); - } else if (!memcmp(extra, "nego =", 5)) { + } else if (!memcmp(extra, "nego=", 5)) { wrqu->data.length -= 5; rtw_p2p_connect(dev, info, wrqu, &extra[5]); - } else if (!memcmp(extra, "intent =", 7)) { + } else if (!memcmp(extra, "intent=", 7)) { /* Commented by Albert 2011/03/23 */ /* The wrqu->data.length will include the null character */ /* So, we will decrease 7 + 1 */ wrqu->data.length -= 8; rtw_p2p_set_intent(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "ssid =", 5)) { + } else if (!memcmp(extra, "ssid=", 5)) { wrqu->data.length -= 5; rtw_p2p_set_go_nego_ssid(dev, info, wrqu, &extra[5]); - } else if (!memcmp(extra, "got_wpsinfo =", 12)) { + } else if (!memcmp(extra, "got_wpsinfo=", 12)) { wrqu->data.length -= 12; rtw_p2p_got_wpsinfo(dev, info, wrqu, &extra[12]); - } else if (!memcmp(extra, "listen_ch =", 10)) { + } else if (!memcmp(extra, "listen_ch=", 10)) { /* Commented by Albert 2011/05/24 */ /* The wrqu->data.length will include the null character */ /* So, we will decrease (10 + 1) */ wrqu->data.length -= 11; rtw_p2p_set_listen_ch(dev, info, wrqu, &extra[10]); - } else if (!memcmp(extra, "op_ch =", 6)) { + } else if (!memcmp(extra, "op_ch=", 6)) { /* Commented by Albert 2011/05/24 */ /* The wrqu->data.length will include the null character */ /* So, we will decrease (6 + 1) */ wrqu->data.length -= 7; rtw_p2p_set_op_ch(dev, info, wrqu, &extra[6]); - } else if (!memcmp(extra, "invite =", 7)) { + } else if (!memcmp(extra, "invite=", 7)) { wrqu->data.length -= 8; rtw_p2p_invite_req(dev, info, wrqu, &extra[7]); - } else if (!memcmp(extra, "persistent =", 11)) { + } else if (!memcmp(extra, "persistent=", 11)) { wrqu->data.length -= 11; rtw_p2p_set_persistent(dev, info, wrqu, &extra[11]); } @@ -3887,7 +3887,7 @@ static int rtw_p2p_get(struct net_device *dev, "group_id", 8)) { rtw_p2p_get_groupid(dev, info, wrqu, extra); } else if (!memcmp((__force const char *)wrqu->data.pointer, - "peer_deva_inv", 9)) { + "peer_deva_inv", 13)) { /* Get the P2P device address when receiving the P2P Invitation request frame. */ rtw_p2p_get_peer_devaddr_by_invitation(dev, info, wrqu, extra); } else if (!memcmp((__force const char *)wrqu->data.pointer, @@ -6920,7 +6920,7 @@ static int rtw_mp_ctx(struct net_device *dev, DBG_88E("%s: in =%s\n", __func__, extra); - countPkTx = strncmp(extra, "count =", 5); /* strncmp true is 0 */ + countPkTx = strncmp(extra, "count=", 6); /* strncmp true is 0 */ cotuTx = strncmp(extra, "background", 20); CarrSprTx = strncmp(extra, "background, cs", 20); scTx = strncmp(extra, "background, sc", 20); @@ -7044,7 +7044,7 @@ static int rtw_mp_arx(struct net_device *dev, DBG_88E("%s: %s\n", __func__, input); bStartRx = (strncmp(input, "start", 5) == 0) ? 1 : 0; /* strncmp true is 0 */ - bStopRx = (strncmp(input, "stop", 5) == 0) ? 1 : 0; /* strncmp true is 0 */ + bStopRx = (strncmp(input, "stop", 4) == 0) ? 1 : 0; /* strncmp true is 0 */ bQueryPhy = (strncmp(input, "phy", 3) == 0) ? 1 : 0; /* strncmp true is 0 */ if (bStartRx) { From 21c5e8408d105386c54603aed2cae9195143d87d Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 24 Mar 2014 13:45:13 -0600 Subject: [PATCH 113/279] staging/usbip: userspace - fix usbipd SIGSEGV from refresh_exported_devices() refresh_exported_devices() doesn't check udev_device_new_from_syspath() return value and passed in null dev to udev_device_get_driver() resulting in a segmentation fault. Change it to check for null return value from both udev_device_new_from_syspath() and udev_device_get_driver(). Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c index c5bf60b135b904..92caef7474c7d7 100644 --- a/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c +++ b/drivers/staging/usbip/userspace/libsrc/usbip_host_driver.c @@ -118,6 +118,7 @@ static int refresh_exported_devices(void) struct udev_list_entry *devices, *dev_list_entry; struct udev_device *dev; const char *path; + const char *driver; enumerate = udev_enumerate_new(udev_context); udev_enumerate_add_match_subsystem(enumerate, "usb"); @@ -128,10 +129,12 @@ static int refresh_exported_devices(void) udev_list_entry_foreach(dev_list_entry, devices) { path = udev_list_entry_get_name(dev_list_entry); dev = udev_device_new_from_syspath(udev_context, path); + if (dev == NULL) + continue; /* Check whether device uses usbip-host driver. */ - if (!strcmp(udev_device_get_driver(dev), - USBIP_HOST_DRV_NAME)) { + driver = udev_device_get_driver(dev); + if (driver != NULL && !strcmp(driver, USBIP_HOST_DRV_NAME)) { edev = usbip_exported_device_new(path); if (!edev) { dbg("usbip_exported_device_new failed"); From de4734bc651d19ed71ad30222aac9b1416e1bd52 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Tue, 25 Mar 2014 06:47:13 -0600 Subject: [PATCH 114/279] staging/usbip: fix store_attach() sscanf return value check sscanf() parses the input buffer for four input items. However, the return value check is incorrect, as it checks for one input item instead of four which is what it is expecting in the input buffer. As a result, sscanf() will always fail even when the input buffer is correct. Signed-off-by: Shuah Khan Signed-off-by: Greg Kroah-Hartman --- drivers/staging/usbip/vhci_sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/usbip/vhci_sysfs.c b/drivers/staging/usbip/vhci_sysfs.c index 47bddcdde0a621..211f43f67ea25f 100644 --- a/drivers/staging/usbip/vhci_sysfs.c +++ b/drivers/staging/usbip/vhci_sysfs.c @@ -184,7 +184,7 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr, * @devid: unique device identifier in a remote host * @speed: usb device speed in a remote host */ - if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 1) + if (sscanf(buf, "%u %u %u %u", &rhport, &sockfd, &devid, &speed) != 4) return -EINVAL; usbip_dbg_vhci_sysfs("rhport(%u) sockfd(%u) devid(%u) speed(%u)\n", From d06fb58cb63c66ddcc2ac94edf99f505f4919da0 Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 3 Apr 2014 10:32:17 +0200 Subject: [PATCH 115/279] staging: fpgaboot: clean up Makefile This Makefile tries to set the DEBUG macro but it uses an unknown Kconfig macro to do so. Since no code appears to even care about the DEBUG macro this line can safely be removed. Signed-off-by: Paul Bolle Reviewed-by: Insop Song Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/staging/gs_fpgaboot/Makefile b/drivers/staging/gs_fpgaboot/Makefile index 34cb606e0e3db8..d2f0211ba540b3 100644 --- a/drivers/staging/gs_fpgaboot/Makefile +++ b/drivers/staging/gs_fpgaboot/Makefile @@ -1,4 +1,2 @@ gs_fpga-y += gs_fpgaboot.o io.o obj-$(CONFIG_GS_FPGABOOT) += gs_fpga.o - -ccflags-$(CONFIG_GS_FPGA_DEBUG) := -DDEBUG From 1a52489318c16aaff71059b3892a1a2f3bb8ecec Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Wed, 26 Mar 2014 12:01:48 +0900 Subject: [PATCH 116/279] staging: vme: fix memory leak in vme_user_probe() If vme_master_request() returns NULL when it failed, it need to free buffers for master. And also removes unreachable code in vme_user_probe(). Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vme/devices/vme_user.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/staging/vme/devices/vme_user.c b/drivers/staging/vme/devices/vme_user.c index 792792715673fe..ffb4eeefdddb37 100644 --- a/drivers/staging/vme/devices/vme_user.c +++ b/drivers/staging/vme/devices/vme_user.c @@ -776,7 +776,8 @@ static int vme_user_probe(struct vme_dev *vdev) image[i].kern_buf = kmalloc(image[i].size_buf, GFP_KERNEL); if (image[i].kern_buf == NULL) { err = -ENOMEM; - goto err_master_buf; + vme_master_free(image[i].resource); + goto err_master; } } @@ -819,8 +820,6 @@ static int vme_user_probe(struct vme_dev *vdev) return 0; - /* Ensure counter set correcty to destroy all sysfs devices */ - i = VME_DEVS; err_sysfs: while (i > 0) { i--; @@ -830,12 +829,10 @@ static int vme_user_probe(struct vme_dev *vdev) /* Ensure counter set correcty to unalloc all master windows */ i = MASTER_MAX + 1; -err_master_buf: - for (i = MASTER_MINOR; i < (MASTER_MAX + 1); i++) - kfree(image[i].kern_buf); err_master: while (i > MASTER_MINOR) { i--; + kfree(image[i].kern_buf); vme_master_free(image[i].resource); } From 14e6e35d04995c118f41582299f6861ab209bdb3 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 25 Mar 2014 16:48:35 +0100 Subject: [PATCH 117/279] staging: gs_fpgaboot: remove __TIMESTAMP__ macro We specifically build the kernel with -Werror=date-time to detect such macros, which gives us this error: gs_fpgaboot/gs_fpgaboot.c:376:44: error: macro "__TIMESTAMP__" might prevent reproducible builds [-Werror=date-time] pr_info("built at %s UTC\n", __TIMESTAMP__); The obvious fix is to remove the printk output line. Signed-off-by: Arnd Bergmann Signed-off-by: Insop Song Acked-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/staging/gs_fpgaboot/gs_fpgaboot.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c index 89bc84d833e66e..7506900c9b8dec 100644 --- a/drivers/staging/gs_fpgaboot/gs_fpgaboot.c +++ b/drivers/staging/gs_fpgaboot/gs_fpgaboot.c @@ -373,7 +373,6 @@ static int __init gs_fpgaboot_init(void) r = -1; pr_info("FPGA DOWNLOAD --->\n"); - pr_info("built at %s UTC\n", __TIMESTAMP__); pr_info("FPGA image file name: %s\n", file); From f5d197b614d8fbc5c25307e7eff1d663653966fa Mon Sep 17 00:00:00 2001 From: Jes Sorensen Date: Tue, 15 Apr 2014 19:43:20 +0200 Subject: [PATCH 118/279] staging: rtl8723au: Fix buffer overflow in rtw_get_wfd_ie() Add bounds checking to not allow WFD Information Elements larger than 128, and make sure we use the correct buffer size MAX_WFD_IE_LEN instea of hardcoding the size. This also simplifies rtw_get_wfd_ie() by using the cfg80211 infrastructure. Reported-by: Dan Carpenter Signed-off-by: Jes Sorensen Signed-off-by: Greg Kroah-Hartman --- .../staging/rtl8723au/core/rtw_ieee80211.c | 46 +++++-------------- drivers/staging/rtl8723au/core/rtw_mlme_ext.c | 2 +- drivers/staging/rtl8723au/core/rtw_p2p.c | 4 +- .../staging/rtl8723au/core/rtw_wlan_util.c | 2 +- 4 files changed, 16 insertions(+), 38 deletions(-) diff --git a/drivers/staging/rtl8723au/core/rtw_ieee80211.c b/drivers/staging/rtl8723au/core/rtw_ieee80211.c index 780631fd3b6d4a..a48ab25a7d8a25 100644 --- a/drivers/staging/rtl8723au/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8723au/core/rtw_ieee80211.c @@ -1496,45 +1496,23 @@ void rtw_wlan_bssid_ex_remove_p2p_attr23a(struct wlan_bssid_ex *bss_ex, u8 attr_ int rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen) { int match; - uint cnt = 0; - u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A}; + const u8 *ie; - match = false; + match = 0; - if (in_len < 0) { + if (in_len < 0) return match; - } - - while (cnt < in_len) - { - eid = in_ie[cnt]; - if ((eid == _VENDOR_SPECIFIC_IE_) && - !memcmp(&in_ie[cnt+2], wfd_oui, 4)) { - if (wfd_ie != NULL) { - memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2); - - } else { - if (wfd_ielen != NULL) { - *wfd_ielen = 0; - } - } - - if (wfd_ielen != NULL) { - *wfd_ielen = in_ie[cnt + 1] + 2; - } - - cnt += in_ie[cnt + 1] + 2; - - match = true; - break; - } else { - cnt += in_ie[cnt + 1] +2; /* goto next */ - } - } + ie = cfg80211_find_vendor_ie(0x506F9A, 0x0A, in_ie, in_len); + if (ie && (ie[1] <= (MAX_WFD_IE_LEN - 2))) { + if (wfd_ie) { + *wfd_ielen = ie[1] + 2; + memcpy(wfd_ie, ie, ie[1] + 2); + } else + if (wfd_ielen) + *wfd_ielen = 0; - if (match == true) { - match = cnt; + match = 1; } return match; diff --git a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c index 4c753639ea5a64..1f3e8a0aece460 100644 --- a/drivers/staging/rtl8723au/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723au/core/rtw_mlme_ext.c @@ -1281,7 +1281,7 @@ unsigned int OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *prec u8 p2p_status_code = P2P_STATUS_SUCCESS; u8 *p2pie; u32 p2pielen = 0; - u8 wfd_ie[ 128 ] = { 0x00 }; + u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 }; u32 wfd_ielen = 0; #endif /* CONFIG_8723AU_P2P */ diff --git a/drivers/staging/rtl8723au/core/rtw_p2p.c b/drivers/staging/rtl8723au/core/rtw_p2p.c index 27a6cc76973de4..1a961e3f3a5541 100644 --- a/drivers/staging/rtl8723au/core/rtw_p2p.c +++ b/drivers/staging/rtl8723au/core/rtw_p2p.c @@ -2535,7 +2535,7 @@ u8 process_p2p_group_negotation_req23a(struct wifidirect_info *pwdinfo, u8 *pfra u16 wps_devicepassword_id = 0x0000; uint wps_devicepassword_id_len = 0; #ifdef CONFIG_8723AU_P2P - u8 wfd_ie[ 128 ] = { 0x00 }; + u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 }; u32 wfd_ielen = 0; #endif /* CONFIG_8723AU_P2P */ @@ -2741,7 +2741,7 @@ u8 process_p2p_group_negotation_resp23a(struct wifidirect_info *pwdinfo, u8 *pfr u32 ies_len; u8 * p2p_ie; #ifdef CONFIG_8723AU_P2P - u8 wfd_ie[ 128 ] = { 0x00 }; + u8 wfd_ie[MAX_WFD_IE_LEN] = { 0x00 }; u32 wfd_ielen = 0; #endif /* CONFIG_8723AU_P2P */ diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c index 0dfcfbce3b521f..e743b053b8a290 100644 --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c @@ -570,7 +570,7 @@ void flush_all_cam_entry23a(struct rtw_adapter *padapter) int WFD_info_handler(struct rtw_adapter *padapter, struct ndis_802_11_var_ies * pIE) { struct wifidirect_info *pwdinfo; - u8 wfd_ie[128] = {0x00}; + u8 wfd_ie[MAX_WFD_IE_LEN] = {0x00}; u32 wfd_ielen = 0; pwdinfo = &padapter->wdinfo; From 67807ce55f6e5ad5c04a748aa195333d6af05654 Mon Sep 17 00:00:00 2001 From: Hui Wang Date: Wed, 16 Apr 2014 10:09:08 +0800 Subject: [PATCH 119/279] ALSA: hda - add headset mic detect quirk for a Dell laptop When we plug a 3-ring headset on the Dell machine (VID: 0x10ec0255, SID: 0x1028067f), the headset mic can't be detected, after apply this patch, the headset mic can work well. BugLink: https://bugs.launchpad.net/bugs/1297581 Cc: David Henningsson Cc: stable@vger.kernel.org Signed-off-by: Hui Wang Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f7766febaebe62..26895d1bbd91e1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4621,6 +4621,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0667, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0668, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0669, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x067f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cc, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x15cd, "Dell X5 Precision", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2), From 2dda47d1a416750bf69eb11dd9b6607d18287b0c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Apr 2014 11:32:06 +0200 Subject: [PATCH 120/279] platform: Fix timberdale dependencies VIDEO_TIMBERDALE selects TIMB_DMA which itself depends on MFD_TIMBERDALE, so VIDEO_TIMBERDALE should either select or depend on MFD_TIMBERDALE as well. I chose to make it depend on it because I think it makes more sense and it is consistent with what other options are doing. Adding a "|| HAS_IOMEM" to the TIMB_DMA dependencies silenced the kconfig warning about unmet direct dependencies but it was wrong: without MFD_TIMBERDALE, TIMB_DMA is useless as the driver has no device to bind to. Signed-off-by: Jean Delvare Cc: Vinod Koul Cc: Dan Williams Cc: Mauro Carvalho Chehab Signed-off-by: Vinod Koul --- drivers/dma/Kconfig | 2 +- drivers/media/platform/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ba06d1d2f99e39..5c5863842de92b 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -197,7 +197,7 @@ config AMCC_PPC440SPE_ADMA config TIMB_DMA tristate "Timberdale FPGA DMA support" - depends on MFD_TIMBERDALE || HAS_IOMEM + depends on MFD_TIMBERDALE select DMA_ENGINE help Enable support for the Timberdale FPGA DMA engine. diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index c137abfa0c543d..20f1655e6d7595 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -56,7 +56,7 @@ config VIDEO_VIU config VIDEO_TIMBERDALE tristate "Support for timberdale Video In/LogiWIN" - depends on VIDEO_V4L2 && I2C && DMADEVICES + depends on MFD_TIMBERDALE && VIDEO_V4L2 && I2C && DMADEVICES select DMA_ENGINE select TIMB_DMA select VIDEO_ADV7180 From f3817e777ca3a089381a5b2370fbb869c3bcce6f Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 3 Apr 2014 10:29:33 +0300 Subject: [PATCH 121/279] dmaengine: sirf: off by one in of_dma_sirfsoc_xlate() The ">" here should be ">=" or we are one step beyond the end of the sdma->channels[] array. Fixes: 2e041c94628c ('dmaengine: sirf: enable generic dt binding for dma channels') Signed-off-by: Dan Carpenter Acked-by: Barry Song Signed-off-by: Vinod Koul --- drivers/dma/sirf-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index a1bd8298d55f19..03f7820fa333b8 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -666,7 +666,7 @@ static struct dma_chan *of_dma_sirfsoc_xlate(struct of_phandle_args *dma_spec, struct sirfsoc_dma *sdma = ofdma->of_dma_data; unsigned int request = dma_spec->args[0]; - if (request > SIRFSOC_DMA_CHANNELS) + if (request >= SIRFSOC_DMA_CHANNELS) return NULL; return dma_get_slave_channel(&sdma->channels[request].chan); From 8edc51c197b8f409bef7b21755254e6f3ce7ed23 Mon Sep 17 00:00:00 2001 From: Yuan Yao Date: Fri, 4 Apr 2014 12:27:55 +0800 Subject: [PATCH 122/279] dma: fix eDMA driver as a subsys_initcall Because of some driver base on DMA, changed the initcall order as subsys_initcall. Signed-off-by: Yuan Yao Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/dma/fsl-edma.c b/drivers/dma/fsl-edma.c index 381e793184baef..b396a7fb53abb5 100644 --- a/drivers/dma/fsl-edma.c +++ b/drivers/dma/fsl-edma.c @@ -968,7 +968,17 @@ static struct platform_driver fsl_edma_driver = { .remove = fsl_edma_remove, }; -module_platform_driver(fsl_edma_driver); +static int __init fsl_edma_init(void) +{ + return platform_driver_register(&fsl_edma_driver); +} +subsys_initcall(fsl_edma_init); + +static void __exit fsl_edma_exit(void) +{ + platform_driver_unregister(&fsl_edma_driver); +} +module_exit(fsl_edma_exit); MODULE_ALIAS("platform:fsl-edma"); MODULE_DESCRIPTION("Freescale eDMA engine driver"); From 8dc9abb93dde94e7f2bc719032fe16f5713df05c Mon Sep 17 00:00:00 2001 From: Kailang Yang Date: Wed, 16 Apr 2014 15:53:12 +0800 Subject: [PATCH 123/279] ALSA: hda/realtek - Add headset Mic support for Dell machine Signed-off-by: Kailang Yang Cc: Signed-off-by: Takashi Iwai --- sound/pci/hda/patch_realtek.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 26895d1bbd91e1..c643dfc0a82612 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5541,6 +5541,8 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x1028, 0x0628, "Dell", ALC668_FIXUP_AUTO_MUTE), SND_PCI_QUIRK(0x1028, 0x064e, "Dell", ALC668_FIXUP_AUTO_MUTE), + SND_PCI_QUIRK(0x1028, 0x0696, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x1028, 0x0698, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), SND_PCI_QUIRK(0x1043, 0x11cd, "Asus N550", ALC662_FIXUP_BASS_1A), SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_BASS_MODE4_CHMAP), From 22bbd5d949dc7fdd72a4e78e767fa09d8e54b446 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 4 Apr 2014 16:31:05 -0600 Subject: [PATCH 124/279] gpu: host1x: handle the correct # of syncpt regs BIT_WORD() truncates rather than rounds, so the loops in syncpt_thresh_isr() and _host1x_intr_disable_all_syncpt_intrs() use <= rather than < in an attempt to process the correct number of registers when rounding of the conversion of count of bits to count of words is necessary. However, when rounding isn't necessary because the value is already a multiple of the divisor (as is the case for all values of nb_pts the code actually sees), this causes one too many registers to be processed. Solve this by using and explicit DIV_ROUND_UP() call, rather than BIT_WORD(), and comparing with < rather than <=. Fixes: 7ede0b0bf3e2 ("gpu: host1x: Add syncpoint wait and interrupts") Cc: # 3.10 Signed-off-by: Stephen Warren Acked-By: Terje Bergstrom Signed-off-by: Thierry Reding --- drivers/gpu/host1x/hw/intr_hw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index db9017adfe2bb9..498b37e39058a6 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c @@ -47,7 +47,7 @@ static irqreturn_t syncpt_thresh_isr(int irq, void *dev_id) unsigned long reg; int i, id; - for (i = 0; i <= BIT_WORD(host->info->nb_pts); i++) { + for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); i++) { reg = host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(i)); for_each_set_bit(id, ®, BITS_PER_LONG) { @@ -64,7 +64,7 @@ static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host) { u32 i; - for (i = 0; i <= BIT_WORD(host->info->nb_pts); ++i) { + for (i = 0; i < DIV_ROUND_UP(host->info->nb_pts, 32); ++i) { host1x_sync_writel(host, 0xffffffffu, HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(i)); host1x_sync_writel(host, 0xffffffffu, From cbfbbabb89b37f6bad05f478d906a385149f288d Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 9 Apr 2014 14:26:59 +0200 Subject: [PATCH 125/279] drm/tegra: Remove gratuitous pad field The version of the drm_tegra_submit structure that was merged all the way back in 3.10 contains a pad field that was originally intended to properly pad the following __u64 field. Unfortunately it seems like a different field was dropped during review that caused this padding to become unnecessary, but the pad field wasn't removed at that time. One possible side-effect of this is that since the __u64 following the pad is now no longer properly aligned, the compiler may (or may not) introduce padding itself, which results in no predictable ABI. Rectify this by removing the pad field so that all fields are again naturally aligned. Technically this is breaking existing userspace ABI, but given that there aren't any (released) userspace drivers that make use of this yet, the fallout should be minimal. Fixes: d43f81cbaf43 ("drm/tegra: Add gr2d device") Cc: # 3.10 Signed-off-by: Thierry Reding --- include/uapi/drm/tegra_drm.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h index b042b48495d9a6..b75482112428af 100644 --- a/include/uapi/drm/tegra_drm.h +++ b/include/uapi/drm/tegra_drm.h @@ -120,7 +120,6 @@ struct drm_tegra_submit { __u32 num_waitchks; __u32 waitchk_mask; __u32 timeout; - __u32 pad; __u64 syncpts; __u64 cmdbufs; __u64 relocs; From c23fdc7da4853c25509255419bf88ed94cd42a5b Mon Sep 17 00:00:00 2001 From: Mohit Kumar Date: Wed, 16 Apr 2014 10:23:28 -0600 Subject: [PATCH 126/279] PCI: designware: Fix comment for setting number of lanes Corrects comment for setting number of lanes. Signed-off-by: Mohit Kumar Signed-off-by: Bjorn Helgaas Acked-by: Jingoo Han --- drivers/pci/host/pcie-designware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 509a29d8450936..8909e7748e675f 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -764,7 +764,7 @@ void dw_pcie_setup_rc(struct pcie_port *pp) u32 membase; u32 memlimit; - /* set the number of lines as 4 */ + /* set the number of lanes */ dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL, &val); val &= ~PORT_LINK_MODE_MASK; switch (pp->lanes) { From 017fcdc30cdae18c0946eef1ece1f14b4c7897ba Mon Sep 17 00:00:00 2001 From: Mohit Kumar Date: Wed, 16 Apr 2014 10:23:34 -0600 Subject: [PATCH 127/279] PCI: designware: Fix iATU programming for cfg1, io and mem viewport This patch corrects iATU programming for cfg1, io and mem viewport. Enable ATU only after configuring it. Signed-off-by: Mohit Kumar Signed-off-by: Ajay Khandelwal Signed-off-by: Bjorn Helgaas Acked-by: Jingoo Han Cc: stable@vger.kernel.org --- drivers/pci/host/pcie-designware.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 8909e7748e675f..a9a62ce4bf05ca 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -520,13 +520,13 @@ static void dw_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev) dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, PCIE_ATU_VIEWPORT); dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_CFG1, PCIE_ATU_CR1); - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); dw_pcie_writel_rc(pp, pp->cfg1_base, PCIE_ATU_LOWER_BASE); dw_pcie_writel_rc(pp, (pp->cfg1_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->cfg1_base + pp->config.cfg1_size - 1, PCIE_ATU_LIMIT); dw_pcie_writel_rc(pp, busdev, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, 0, PCIE_ATU_UPPER_TARGET); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); } static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) @@ -535,7 +535,6 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX0, PCIE_ATU_VIEWPORT); dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_MEM, PCIE_ATU_CR1); - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); dw_pcie_writel_rc(pp, pp->mem_base, PCIE_ATU_LOWER_BASE); dw_pcie_writel_rc(pp, (pp->mem_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->mem_base + pp->config.mem_size - 1, @@ -543,6 +542,7 @@ static void dw_pcie_prog_viewport_mem_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, pp->config.mem_bus_addr, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, upper_32_bits(pp->config.mem_bus_addr), PCIE_ATU_UPPER_TARGET); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); } static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) @@ -551,7 +551,6 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, PCIE_ATU_REGION_OUTBOUND | PCIE_ATU_REGION_INDEX1, PCIE_ATU_VIEWPORT); dw_pcie_writel_rc(pp, PCIE_ATU_TYPE_IO, PCIE_ATU_CR1); - dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); dw_pcie_writel_rc(pp, pp->io_base, PCIE_ATU_LOWER_BASE); dw_pcie_writel_rc(pp, (pp->io_base >> 32), PCIE_ATU_UPPER_BASE); dw_pcie_writel_rc(pp, pp->io_base + pp->config.io_size - 1, @@ -559,6 +558,7 @@ static void dw_pcie_prog_viewport_io_outbound(struct pcie_port *pp) dw_pcie_writel_rc(pp, pp->config.io_bus_addr, PCIE_ATU_LOWER_TARGET); dw_pcie_writel_rc(pp, upper_32_bits(pp->config.io_bus_addr), PCIE_ATU_UPPER_TARGET); + dw_pcie_writel_rc(pp, PCIE_ATU_ENABLE, PCIE_ATU_CR2); } static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus, From f86b3e392780050e5907f1c0f3cb6c4cc05fd6bb Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 16 Apr 2014 10:23:46 -0600 Subject: [PATCH 128/279] PCI: designware: Use new OF interrupt mapping when possible Use new OF interrupt mapping (of_irq_parse_and_map_pci()) when possible. This is the recommended method of doing the IRQ mapping. For old devicetrees we fall back to the previous practice. This makes INTB, INTC, and INTD work on i.MX. Tested-by: Tim Harvey Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas Reviewed-by: Marek Vasut Acked-by: Arnd Bergmann Acked-by: Jingoo Han --- drivers/pci/host/pcie-designware.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index a9a62ce4bf05ca..c4e373294476a7 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -490,7 +491,7 @@ int __init dw_pcie_host_init(struct pcie_port *pp) dw_pci.nr_controllers = 1; dw_pci.private_data = (void **)&pp; - pci_common_init(&dw_pci); + pci_common_init_dev(pp->dev, &dw_pci); pci_assign_unassigned_resources(); #ifdef CONFIG_PCI_DOMAINS dw_pci.domain++; @@ -723,7 +724,7 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) if (pp) { pp->root_bus_nr = sys->busnr; - bus = pci_scan_root_bus(NULL, sys->busnr, &dw_pcie_ops, + bus = pci_scan_root_bus(pp->dev, sys->busnr, &dw_pcie_ops, sys, &sys->resources); } else { bus = NULL; @@ -736,8 +737,13 @@ static struct pci_bus *dw_pcie_scan_bus(int nr, struct pci_sys_data *sys) static int dw_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct pcie_port *pp = sys_to_pcie(dev->bus->sysdata); + int irq; - return pp->irq; + irq = of_irq_parse_and_map_pci(dev, slot, pin); + if (!irq) + irq = pp->irq; + + return irq; } static void dw_pcie_add_bus(struct pci_bus *bus) From f8f2fe7355fb04dd129d49ac0ad440beb44f0f79 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 16 Apr 2014 10:24:09 -0600 Subject: [PATCH 129/279] PCI: rcar: Use new OF interrupt mapping when possible Use new OF interrupt mapping (of_irq_parse_and_map_pci()) when possible. This is the recommended method of doing the IRQ mapping. For old devicetrees we fall back to the previous practice. This allows interrupts to be remapped across bridges. Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas Acked-by: Simon Horman --- drivers/pci/host/pci-rcar-gen2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pci/host/pci-rcar-gen2.c b/drivers/pci/host/pci-rcar-gen2.c index fd3e3ab5650912..4fe349dcaf5954 100644 --- a/drivers/pci/host/pci-rcar-gen2.c +++ b/drivers/pci/host/pci-rcar-gen2.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -180,8 +181,13 @@ static int rcar_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { struct pci_sys_data *sys = dev->bus->sysdata; struct rcar_pci_priv *priv = sys->private_data; + int irq; + + irq = of_irq_parse_and_map_pci(dev, slot, pin); + if (!irq) + irq = priv->irq; - return priv->irq; + return irq; } #ifdef CONFIG_PCI_DEBUG From f5d3352b2751f8de7e06e23a04ac0b4c474075e9 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 16 Apr 2014 10:24:32 -0600 Subject: [PATCH 130/279] PCI: tegra: Use new OF interrupt mapping when possible Use new OF interrupt mapping (of_irq_parse_and_map_pci()) when possible. This is the recommended method of doing the IRQ mapping. For old devicetrees we fall back to the previous practice. This allows interrupts to be remapped across bridges. Tested-by: Stephen Warren Signed-off-by: Lucas Stach Signed-off-by: Bjorn Helgaas Acked-by: Arnd Bergmann --- drivers/pci/host/pci-tegra.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 330f7e3a32dd9f..083cf37ca04752 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -639,10 +639,15 @@ static int tegra_pcie_setup(int nr, struct pci_sys_data *sys) static int tegra_pcie_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) { struct tegra_pcie *pcie = sys_to_pcie(pdev->bus->sysdata); + int irq; tegra_cpuidle_pcie_irqs_in_use(); - return pcie->irq; + irq = of_irq_parse_and_map_pci(pdev, slot, pin); + if (!irq) + irq = pcie->irq; + + return irq; } static void tegra_pcie_add_bus(struct pci_bus *bus) From e283546c0465dd3026bc94f7b1a9de7f6b8969ec Mon Sep 17 00:00:00 2001 From: Edward Cree Date: Wed, 16 Apr 2014 19:27:48 +0100 Subject: [PATCH 131/279] sfc:On MCDI timeout, issue an FLR (and mark MCDI to fail-fast) When an MCDI command times out (whether or not we find it completed when we poll), call efx_mcdi_abandon(), which tells all subsequent MCDI calls to fail-fast, and queues up an FLR. Because an FLR doesn't lead to receiving any reboot even from the MC (unlike most other types of reset), we have to call efx_ef10_reset_mc_allocations. In efx_start_all(), if a reset (of any kind) is pending, we bail out. Without this, attempts to reconfigure (e.g. change mtu) can cause driver/mc state inconsistency if the first MCDI call triggers an FLR. For similar reasons, on EF10, in efx_reset_down(method=RESET_TYPE_MCDI_TIMEOUT), set the number of active queues to zero before calling efx_stop_all(). And, on farch, in efx_reset_up(method=RESET_TYPE_MCDI_TIMEOUT), set active_queues and flushes pending & outstanding to zero. efx_mcdi_mode_{poll,event}() should not take us out of fail-fast mode. Instead, this is done by efx_mcdi_reset() after the FLR completes. The new FLR reset_type RESET_TYPE_MCDI_TIMEOUT doesn't really fit into the hierarchy of reset 'scopes' whereby efx_reset() decides some resets subsume others. Thus, it uses separate logic. Also, fixed up some inconsistency around RESET_TYPE_MC_BIST, which was in the wrong place in that hierarchy. Signed-off-by: Shradha Shah Signed-off-by: David S. Miller --- drivers/net/ethernet/sfc/ef10.c | 12 +++++- drivers/net/ethernet/sfc/efx.c | 19 +++++++-- drivers/net/ethernet/sfc/enum.h | 23 +++++++---- drivers/net/ethernet/sfc/falcon.c | 4 ++ drivers/net/ethernet/sfc/farch.c | 22 +++++++++++ drivers/net/ethernet/sfc/mcdi.c | 55 +++++++++++++++++++++------ drivers/net/ethernet/sfc/mcdi.h | 13 +++++++ drivers/net/ethernet/sfc/net_driver.h | 4 ++ drivers/net/ethernet/sfc/nic.h | 1 + drivers/net/ethernet/sfc/siena.c | 2 + 10 files changed, 133 insertions(+), 22 deletions(-) diff --git a/drivers/net/ethernet/sfc/ef10.c b/drivers/net/ethernet/sfc/ef10.c index 21c20ea0dad066..b5ed30a3914486 100644 --- a/drivers/net/ethernet/sfc/ef10.c +++ b/drivers/net/ethernet/sfc/ef10.c @@ -738,8 +738,11 @@ static int efx_ef10_reset(struct efx_nic *efx, enum reset_type reset_type) /* If it was a port reset, trigger reallocation of MC resources. * Note that on an MC reset nothing needs to be done now because we'll * detect the MC reset later and handle it then. + * For an FLR, we never get an MC reset event, but the MC has reset all + * resources assigned to us, so we have to trigger reallocation now. */ - if (reset_type == RESET_TYPE_ALL && !rc) + if ((reset_type == RESET_TYPE_ALL || + reset_type == RESET_TYPE_MCDI_TIMEOUT) && !rc) efx_ef10_reset_mc_allocations(efx); return rc; } @@ -2141,6 +2144,11 @@ static int efx_ef10_fini_dmaq(struct efx_nic *efx) return 0; } +static void efx_ef10_prepare_flr(struct efx_nic *efx) +{ + atomic_set(&efx->active_queues, 0); +} + static bool efx_ef10_filter_equal(const struct efx_filter_spec *left, const struct efx_filter_spec *right) { @@ -3603,6 +3611,8 @@ const struct efx_nic_type efx_hunt_a0_nic_type = { .probe_port = efx_mcdi_port_probe, .remove_port = efx_mcdi_port_remove, .fini_dmaq = efx_ef10_fini_dmaq, + .prepare_flr = efx_ef10_prepare_flr, + .finish_flr = efx_port_dummy_op_void, .describe_stats = efx_ef10_describe_stats, .update_stats = efx_ef10_update_stats, .start_stats = efx_mcdi_mac_start_stats, diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 57b971e5e6b242..63d595fd3cc5f5 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -76,6 +76,7 @@ const char *const efx_reset_type_names[] = { [RESET_TYPE_RECOVER_OR_ALL] = "RECOVER_OR_ALL", [RESET_TYPE_WORLD] = "WORLD", [RESET_TYPE_RECOVER_OR_DISABLE] = "RECOVER_OR_DISABLE", + [RESET_TYPE_MC_BIST] = "MC_BIST", [RESET_TYPE_DISABLE] = "DISABLE", [RESET_TYPE_TX_WATCHDOG] = "TX_WATCHDOG", [RESET_TYPE_INT_ERROR] = "INT_ERROR", @@ -83,7 +84,7 @@ const char *const efx_reset_type_names[] = { [RESET_TYPE_DMA_ERROR] = "DMA_ERROR", [RESET_TYPE_TX_SKIP] = "TX_SKIP", [RESET_TYPE_MC_FAILURE] = "MC_FAILURE", - [RESET_TYPE_MC_BIST] = "MC_BIST", + [RESET_TYPE_MCDI_TIMEOUT] = "MCDI_TIMEOUT (FLR)", }; /* Reset workqueue. If any NIC has a hardware failure then a reset will be @@ -1739,7 +1740,8 @@ static void efx_start_all(struct efx_nic *efx) /* Check that it is appropriate to restart the interface. All * of these flags are safe to read under just the rtnl lock */ - if (efx->port_enabled || !netif_running(efx->net_dev)) + if (efx->port_enabled || !netif_running(efx->net_dev) || + efx->reset_pending) return; efx_start_port(efx); @@ -2334,6 +2336,9 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method) { EFX_ASSERT_RESET_SERIALISED(efx); + if (method == RESET_TYPE_MCDI_TIMEOUT) + efx->type->prepare_flr(efx); + efx_stop_all(efx); efx_disable_interrupts(efx); @@ -2354,6 +2359,10 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok) EFX_ASSERT_RESET_SERIALISED(efx); + if (method == RESET_TYPE_MCDI_TIMEOUT) + efx->type->finish_flr(efx); + + /* Ensure that SRAM is initialised even if we're disabling the device */ rc = efx->type->init(efx); if (rc) { netif_err(efx, drv, efx->net_dev, "failed to initialise NIC\n"); @@ -2417,7 +2426,10 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) /* Clear flags for the scopes we covered. We assume the NIC and * driver are now quiescent so that there is no race here. */ - efx->reset_pending &= -(1 << (method + 1)); + if (method < RESET_TYPE_MAX_METHOD) + efx->reset_pending &= -(1 << (method + 1)); + else /* it doesn't fit into the well-ordered scope hierarchy */ + __clear_bit(method, &efx->reset_pending); /* Reinitialise bus-mastering, which may have been turned off before * the reset was scheduled. This is still appropriate, even in the @@ -2546,6 +2558,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type) case RESET_TYPE_DISABLE: case RESET_TYPE_RECOVER_OR_DISABLE: case RESET_TYPE_MC_BIST: + case RESET_TYPE_MCDI_TIMEOUT: method = type; netif_dbg(efx, drv, efx->net_dev, "scheduling %s reset\n", RESET_TYPE(method)); diff --git a/drivers/net/ethernet/sfc/enum.h b/drivers/net/ethernet/sfc/enum.h index 75ef7ef6450b09..d1dbb5fb31bb51 100644 --- a/drivers/net/ethernet/sfc/enum.h +++ b/drivers/net/ethernet/sfc/enum.h @@ -143,6 +143,7 @@ enum efx_loopback_mode { * @RESET_TYPE_WORLD: Reset as much as possible * @RESET_TYPE_RECOVER_OR_DISABLE: Try to recover. Apply RESET_TYPE_DISABLE if * unsuccessful. + * @RESET_TYPE_MC_BIST: MC entering BIST mode. * @RESET_TYPE_DISABLE: Reset datapath, MAC and PHY; leave NIC disabled * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog * @RESET_TYPE_INT_ERROR: reset due to internal error @@ -150,14 +151,16 @@ enum efx_loopback_mode { * @RESET_TYPE_DMA_ERROR: DMA error * @RESET_TYPE_TX_SKIP: hardware completed empty tx descriptors * @RESET_TYPE_MC_FAILURE: MC reboot/assertion + * @RESET_TYPE_MCDI_TIMEOUT: MCDI timeout. */ enum reset_type { - RESET_TYPE_INVISIBLE = 0, - RESET_TYPE_RECOVER_OR_ALL = 1, - RESET_TYPE_ALL = 2, - RESET_TYPE_WORLD = 3, - RESET_TYPE_RECOVER_OR_DISABLE = 4, - RESET_TYPE_DISABLE = 5, + RESET_TYPE_INVISIBLE, + RESET_TYPE_RECOVER_OR_ALL, + RESET_TYPE_ALL, + RESET_TYPE_WORLD, + RESET_TYPE_RECOVER_OR_DISABLE, + RESET_TYPE_MC_BIST, + RESET_TYPE_DISABLE, RESET_TYPE_MAX_METHOD, RESET_TYPE_TX_WATCHDOG, RESET_TYPE_INT_ERROR, @@ -165,7 +168,13 @@ enum reset_type { RESET_TYPE_DMA_ERROR, RESET_TYPE_TX_SKIP, RESET_TYPE_MC_FAILURE, - RESET_TYPE_MC_BIST, + /* RESET_TYPE_MCDI_TIMEOUT is actually a method, not just a reason, but + * it doesn't fit the scope hierarchy (not well-ordered by inclusion). + * We encode this by having its enum value be greater than + * RESET_TYPE_MAX_METHOD. This also prevents issuing it with + * efx_ioctl_reset. + */ + RESET_TYPE_MCDI_TIMEOUT, RESET_TYPE_MAX, }; diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 8ec20b713cc610..fae25a41864797 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2696,6 +2696,8 @@ const struct efx_nic_type falcon_a1_nic_type = { .fini_dmaq = efx_farch_fini_dmaq, .prepare_flush = falcon_prepare_flush, .finish_flush = efx_port_dummy_op_void, + .prepare_flr = efx_port_dummy_op_void, + .finish_flr = efx_farch_finish_flr, .describe_stats = falcon_describe_nic_stats, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, @@ -2790,6 +2792,8 @@ const struct efx_nic_type falcon_b0_nic_type = { .fini_dmaq = efx_farch_fini_dmaq, .prepare_flush = falcon_prepare_flush, .finish_flush = efx_port_dummy_op_void, + .prepare_flr = efx_port_dummy_op_void, + .finish_flr = efx_farch_finish_flr, .describe_stats = falcon_describe_nic_stats, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index a08761360cdf52..0537381cd2f6a4 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -741,6 +741,28 @@ int efx_farch_fini_dmaq(struct efx_nic *efx) return rc; } +/* Reset queue and flush accounting after FLR + * + * One possible cause of FLR recovery is that DMA may be failing (eg. if bus + * mastering was disabled), in which case we don't receive (RXQ) flush + * completion events. This means that efx->rxq_flush_outstanding remained at 4 + * after the FLR; also, efx->active_queues was non-zero (as no flush completion + * events were received, and we didn't go through efx_check_tx_flush_complete()) + * If we don't fix this up, on the next call to efx_realloc_channels() we won't + * flush any RX queues because efx->rxq_flush_outstanding is at the limit of 4 + * for batched flush requests; and the efx->active_queues gets messed up because + * we keep incrementing for the newly initialised queues, but it never went to + * zero previously. Then we get a timeout every time we try to restart the + * queues, as it doesn't go back to zero when we should be flushing the queues. + */ +void efx_farch_finish_flr(struct efx_nic *efx) +{ + atomic_set(&efx->rxq_flush_pending, 0); + atomic_set(&efx->rxq_flush_outstanding, 0); + atomic_set(&efx->active_queues, 0); +} + + /************************************************************************** * * Event queue processing diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 7bd4b14bf3b32f..5239cf9bdc567f 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -52,12 +52,7 @@ static void efx_mcdi_timeout_async(unsigned long context); static int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, bool *was_attached_out); static bool efx_mcdi_poll_once(struct efx_nic *efx); - -static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) -{ - EFX_BUG_ON_PARANOID(!efx->mcdi); - return &efx->mcdi->iface; -} +static void efx_mcdi_abandon(struct efx_nic *efx); int efx_mcdi_init(struct efx_nic *efx) { @@ -558,6 +553,8 @@ static int _efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen, rc = 0; } + efx_mcdi_abandon(efx); + /* Close the race with efx_mcdi_ev_cpl() executing just too late * and completing a request we've just cancelled, by ensuring * that the seqno check therein fails. @@ -672,6 +669,9 @@ int efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd, if (efx->mc_bist_for_other_fn) return -ENETDOWN; + if (mcdi->mode == MCDI_MODE_FAIL) + return -ENETDOWN; + efx_mcdi_acquire_sync(mcdi); efx_mcdi_send_request(efx, cmd, inbuf, inlen); return 0; @@ -812,7 +812,11 @@ void efx_mcdi_mode_poll(struct efx_nic *efx) return; mcdi = efx_mcdi(efx); - if (mcdi->mode == MCDI_MODE_POLL) + /* If already in polling mode, nothing to do. + * If in fail-fast state, don't switch to polled completion. + * FLR recovery will do that later. + */ + if (mcdi->mode == MCDI_MODE_POLL || mcdi->mode == MCDI_MODE_FAIL) return; /* We can switch from event completion to polled completion, because @@ -841,8 +845,8 @@ void efx_mcdi_flush_async(struct efx_nic *efx) mcdi = efx_mcdi(efx); - /* We must be in polling mode so no more requests can be queued */ - BUG_ON(mcdi->mode != MCDI_MODE_POLL); + /* We must be in poll or fail mode so no more requests can be queued */ + BUG_ON(mcdi->mode == MCDI_MODE_EVENTS); del_timer_sync(&mcdi->async_timer); @@ -875,8 +879,11 @@ void efx_mcdi_mode_event(struct efx_nic *efx) return; mcdi = efx_mcdi(efx); - - if (mcdi->mode == MCDI_MODE_EVENTS) + /* If already in event completion mode, nothing to do. + * If in fail-fast state, don't switch to event completion. FLR + * recovery will do that later. + */ + if (mcdi->mode == MCDI_MODE_EVENTS || mcdi->mode == MCDI_MODE_FAIL) return; /* We can't switch from polled to event completion in the middle of a @@ -966,6 +973,19 @@ static void efx_mcdi_ev_bist(struct efx_nic *efx) spin_unlock(&mcdi->iface_lock); } +/* MCDI timeouts seen, so make all MCDI calls fail-fast and issue an FLR to try + * to recover. + */ +static void efx_mcdi_abandon(struct efx_nic *efx) +{ + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); + + if (xchg(&mcdi->mode, MCDI_MODE_FAIL) == MCDI_MODE_FAIL) + return; /* it had already been done */ + netif_dbg(efx, hw, efx->net_dev, "MCDI is timing out; trying to recover\n"); + efx_schedule_reset(efx, RESET_TYPE_MCDI_TIMEOUT); +} + /* Called from falcon_process_eventq for MCDI events */ void efx_mcdi_process_event(struct efx_channel *channel, efx_qword_t *event) @@ -1512,6 +1532,19 @@ int efx_mcdi_reset(struct efx_nic *efx, enum reset_type method) { int rc; + /* If MCDI is down, we can't handle_assertion */ + if (method == RESET_TYPE_MCDI_TIMEOUT) { + rc = pci_reset_function(efx->pci_dev); + if (rc) + return rc; + /* Re-enable polled MCDI completion */ + if (efx->mcdi) { + struct efx_mcdi_iface *mcdi = efx_mcdi(efx); + mcdi->mode = MCDI_MODE_POLL; + } + return 0; + } + /* Recover from a failed assertion pre-reset */ rc = efx_mcdi_handle_assertion(efx); if (rc) diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 52931aebf3c304..56465f7465a22b 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -28,9 +28,16 @@ enum efx_mcdi_state { MCDI_STATE_COMPLETED, }; +/** + * enum efx_mcdi_mode - MCDI transaction mode + * @MCDI_MODE_POLL: poll for MCDI completion, until timeout + * @MCDI_MODE_EVENTS: wait for an mcdi_event. On timeout, poll once + * @MCDI_MODE_FAIL: we think MCDI is dead, so fail-fast all calls + */ enum efx_mcdi_mode { MCDI_MODE_POLL, MCDI_MODE_EVENTS, + MCDI_MODE_FAIL, }; /** @@ -104,6 +111,12 @@ struct efx_mcdi_data { u32 fn_flags; }; +static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx) +{ + EFX_BUG_ON_PARANOID(!efx->mcdi); + return &efx->mcdi->iface; +} + #ifdef CONFIG_SFC_MCDI_MON static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx) { diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 8a400a0595eb8c..5bdae8ed7c5734 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -972,6 +972,8 @@ struct efx_mtd_partition { * (for Falcon architecture) * @finish_flush: Clean up after flushing the DMA queues (for Falcon * architecture) + * @prepare_flr: Prepare for an FLR + * @finish_flr: Clean up after an FLR * @describe_stats: Describe statistics for ethtool * @update_stats: Update statistics not provided by event handling. * Either argument may be %NULL. @@ -1100,6 +1102,8 @@ struct efx_nic_type { int (*fini_dmaq)(struct efx_nic *efx); void (*prepare_flush)(struct efx_nic *efx); void (*finish_flush)(struct efx_nic *efx); + void (*prepare_flr)(struct efx_nic *efx); + void (*finish_flr)(struct efx_nic *efx); size_t (*describe_stats)(struct efx_nic *efx, u8 *names); size_t (*update_stats)(struct efx_nic *efx, u64 *full_stats, struct rtnl_link_stats64 *core_stats); diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index a001fae1a8d786..d3ad8ed8d901a9 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -757,6 +757,7 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx) int efx_nic_flush_queues(struct efx_nic *efx); void siena_prepare_flush(struct efx_nic *efx); int efx_farch_fini_dmaq(struct efx_nic *efx); +void efx_farch_finish_flr(struct efx_nic *efx); void siena_finish_flush(struct efx_nic *efx); void falcon_start_nic_stats(struct efx_nic *efx); void falcon_stop_nic_stats(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 23f3a6f7737a19..50ffefed492c11 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -921,6 +921,8 @@ const struct efx_nic_type siena_a0_nic_type = { .fini_dmaq = efx_farch_fini_dmaq, .prepare_flush = siena_prepare_flush, .finish_flush = siena_finish_flush, + .prepare_flr = efx_port_dummy_op_void, + .finish_flr = efx_farch_finish_flr, .describe_stats = siena_describe_nic_stats, .update_stats = siena_update_nic_stats, .start_stats = efx_mcdi_mac_start_stats, From 5ed0a8e667090003fdf7b750296fcfb248349502 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 16 Apr 2014 11:35:54 -0700 Subject: [PATCH 132/279] staging: delete rtl8187se wireless driver There is a "real" driver for this hardware now in drivers/net/ so remove the staging version as it's not needed anymore. Reported-by: Xose Vazquez Perez Cc: Larry Finger Cc: John W. Linville" Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/rtl8187se/Kconfig | 10 - drivers/staging/rtl8187se/Makefile | 38 - drivers/staging/rtl8187se/Module.symvers | 0 drivers/staging/rtl8187se/TODO | 13 - drivers/staging/rtl8187se/ieee80211/dot11d.c | 189 - drivers/staging/rtl8187se/ieee80211/dot11d.h | 71 - .../staging/rtl8187se/ieee80211/ieee80211.h | 1496 ------- .../rtl8187se/ieee80211/ieee80211_crypt.c | 240 -- .../rtl8187se/ieee80211/ieee80211_crypt.h | 86 - .../ieee80211/ieee80211_crypt_ccmp.c | 455 -- .../ieee80211/ieee80211_crypt_tkip.c | 740 ---- .../rtl8187se/ieee80211/ieee80211_crypt_wep.c | 277 -- .../rtl8187se/ieee80211/ieee80211_module.c | 203 - .../rtl8187se/ieee80211/ieee80211_rx.c | 1486 ------- .../rtl8187se/ieee80211/ieee80211_softmac.c | 2711 ------------ .../ieee80211/ieee80211_softmac_wx.c | 567 --- .../rtl8187se/ieee80211/ieee80211_tx.c | 591 --- .../rtl8187se/ieee80211/ieee80211_wx.c | 713 ---- drivers/staging/rtl8187se/r8180.h | 640 --- drivers/staging/rtl8187se/r8180_93cx6.h | 54 - drivers/staging/rtl8187se/r8180_core.c | 3775 ----------------- drivers/staging/rtl8187se/r8180_dm.c | 1139 ----- drivers/staging/rtl8187se/r8180_dm.h | 23 - drivers/staging/rtl8187se/r8180_hw.h | 588 --- drivers/staging/rtl8187se/r8180_rtl8225.h | 34 - drivers/staging/rtl8187se/r8180_rtl8225z2.c | 811 ---- drivers/staging/rtl8187se/r8180_wx.c | 1409 ------ drivers/staging/rtl8187se/r8180_wx.h | 21 - drivers/staging/rtl8187se/r8185b_init.c | 1464 ------- 31 files changed, 19847 deletions(-) delete mode 100644 drivers/staging/rtl8187se/Kconfig delete mode 100644 drivers/staging/rtl8187se/Makefile delete mode 100644 drivers/staging/rtl8187se/Module.symvers delete mode 100644 drivers/staging/rtl8187se/TODO delete mode 100644 drivers/staging/rtl8187se/ieee80211/dot11d.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/dot11d.h delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211.h delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_module.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c delete mode 100644 drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c delete mode 100644 drivers/staging/rtl8187se/r8180.h delete mode 100644 drivers/staging/rtl8187se/r8180_93cx6.h delete mode 100644 drivers/staging/rtl8187se/r8180_core.c delete mode 100644 drivers/staging/rtl8187se/r8180_dm.c delete mode 100644 drivers/staging/rtl8187se/r8180_dm.h delete mode 100644 drivers/staging/rtl8187se/r8180_hw.h delete mode 100644 drivers/staging/rtl8187se/r8180_rtl8225.h delete mode 100644 drivers/staging/rtl8187se/r8180_rtl8225z2.c delete mode 100644 drivers/staging/rtl8187se/r8180_wx.c delete mode 100644 drivers/staging/rtl8187se/r8180_wx.h delete mode 100644 drivers/staging/rtl8187se/r8185b_init.c diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ea5efb426f75f0..22365f140bec3d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -40,8 +40,6 @@ source "drivers/staging/olpc_dcon/Kconfig" source "drivers/staging/panel/Kconfig" -source "drivers/staging/rtl8187se/Kconfig" - source "drivers/staging/rtl8192u/Kconfig" source "drivers/staging/rtl8192e/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 86e020c2ad0dea..fbe84ed2d048e4 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -12,7 +12,6 @@ obj-$(CONFIG_PRISM2_USB) += wlan-ng/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/ obj-$(CONFIG_PANEL) += panel/ -obj-$(CONFIG_R8187SE) += rtl8187se/ obj-$(CONFIG_RTL8192U) += rtl8192u/ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_R8712U) += rtl8712/ diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig deleted file mode 100644 index ff8d41ebca36a0..00000000000000 --- a/drivers/staging/rtl8187se/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config R8187SE - tristate "RealTek RTL8187SE Wireless LAN NIC driver" - depends on PCI && WLAN - depends on m - select WIRELESS_EXT - select WEXT_PRIV - select EEPROM_93CX6 - select CRYPTO - ---help--- - If built as a module, it will be called r8187se.ko. diff --git a/drivers/staging/rtl8187se/Makefile b/drivers/staging/rtl8187se/Makefile deleted file mode 100644 index 91d1aa2830c90f..00000000000000 --- a/drivers/staging/rtl8187se/Makefile +++ /dev/null @@ -1,38 +0,0 @@ - -#ccflags-y += -DCONFIG_IEEE80211_NOWEP=y -#ccflags-y += -std=gnu89 -#ccflags-y += -O2 -#CC = gcc - -ccflags-y := -DSW_ANTE -ccflags-y += -DTX_TRACK -ccflags-y += -DHIGH_POWER -ccflags-y += -DSW_DIG -ccflags-y += -DRATE_ADAPT - -#enable it for legacy power save, disable it for leisure power save -ccflags-y += -DENABLE_LPS - - -#ccflags-y := -mhard-float -DCONFIG_FORCE_HARD_FLOAT=y - -r8187se-y := \ - r8180_core.o \ - r8180_wx.o \ - r8180_rtl8225z2.o \ - r8185b_init.o \ - r8180_dm.o \ - ieee80211/dot11d.o \ - ieee80211/ieee80211_softmac.o \ - ieee80211/ieee80211_rx.o \ - ieee80211/ieee80211_tx.o \ - ieee80211/ieee80211_wx.o \ - ieee80211/ieee80211_module.o \ - ieee80211/ieee80211_softmac_wx.o \ - ieee80211/ieee80211_crypt.o \ - ieee80211/ieee80211_crypt_tkip.o \ - ieee80211/ieee80211_crypt_ccmp.o \ - ieee80211/ieee80211_crypt_wep.o - -obj-$(CONFIG_R8187SE) += r8187se.o - diff --git a/drivers/staging/rtl8187se/Module.symvers b/drivers/staging/rtl8187se/Module.symvers deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/drivers/staging/rtl8187se/TODO b/drivers/staging/rtl8187se/TODO deleted file mode 100644 index 704949a9da0d9d..00000000000000 --- a/drivers/staging/rtl8187se/TODO +++ /dev/null @@ -1,13 +0,0 @@ -TODO: -- prepare private ieee80211 stack for merge with rtl8192su's version: - - add hwsec_active flag to struct ieee80211_device - - add bHwSec flag to cb_desc structure -- switch to use shared "librtl" instead of private ieee80211 stack -- switch to use LIB80211 -- switch to use MAC80211 -- use kernel coding style -- checkpatch.pl fixes -- sparse fixes -- integrate with drivers/net/wireless/rtl818x - -Please send any patches to Greg Kroah-Hartman . diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.c b/drivers/staging/rtl8187se/ieee80211/dot11d.c deleted file mode 100644 index 4483c2c0307c9a..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.c +++ /dev/null @@ -1,189 +0,0 @@ -#include "dot11d.h" - -void Dot11d_Init(struct ieee80211_device *ieee) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); - - pDot11dInfo->bEnabled = 0; - - pDot11dInfo->State = DOT11D_STATE_NONE; - pDot11dInfo->CountryIeLen = 0; - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - RESET_CIE_WATCHDOG(ieee); - - netdev_info(ieee->dev, "Dot11d_Init()\n"); -} - -/* Reset to the state as we are just entering a regulatory domain. */ -void Dot11d_Reset(struct ieee80211_device *ieee) -{ - u32 i; - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); - - /* Clear old channel map */ - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - /* Set new channel map */ - for (i = 1; i <= 11; i++) - (pDot11dInfo->channel_map)[i] = 1; - - for (i = 12; i <= 14; i++) - (pDot11dInfo->channel_map)[i] = 2; - - pDot11dInfo->State = DOT11D_STATE_NONE; - pDot11dInfo->CountryIeLen = 0; - RESET_CIE_WATCHDOG(ieee); -} - -/* - * Description: - * Update country IE from Beacon or Probe Response and configure PHY for - * operation in the regulatory domain. - * - * TODO: - * Configure Tx power. - * - * Assumption: - * 1. IS_DOT11D_ENABLE() is TRUE. - * 2. Input IE is an valid one. - */ -void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr, - u16 CoutryIeLen, u8 *pCoutryIe) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 i, j, NumTriples, MaxChnlNum; - u8 index, MaxTxPowerInDbm; - PCHNL_TXPOWER_TRIPLE pTriple; - - if ((CoutryIeLen - 3)%3 != 0) { - netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); - Dot11d_Reset(dev); - return; - } - - memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); - memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); - MaxChnlNum = 0; - NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */ - pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); - for (i = 0; i < NumTriples; i++) { - if (MaxChnlNum >= pTriple->FirstChnl) { - /* - * It is not in a monotonically increasing order, - * so stop processing. - */ - netdev_info(dev->dev, - "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); - Dot11d_Reset(dev); - return; - } - if (MAX_CHANNEL_NUMBER < - (pTriple->FirstChnl + pTriple->NumChnls)) { - /* - * It is not a valid set of channel id, - * so stop processing - */ - netdev_info(dev->dev, - "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); - Dot11d_Reset(dev); - return; - } - - for (j = 0; j < pTriple->NumChnls; j++) { - index = pTriple->FirstChnl + j; - pDot11dInfo->channel_map[index] = 1; - MaxTxPowerInDbm = pTriple->MaxTxPowerInDbm; - pDot11dInfo->MaxTxPwrDbmList[index] = MaxTxPowerInDbm; - MaxChnlNum = pTriple->FirstChnl + j; - } - - pTriple = (PCHNL_TXPOWER_TRIPLE)((u8 *)pTriple + 3); - } -#if 1 - netdev_info(dev->dev, "Channel List:"); - for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) - if (pDot11dInfo->channel_map[i] > 0) - netdev_info(dev->dev, " %d", i); - netdev_info(dev->dev, "\n"); -#endif - - UPDATE_CIE_SRC(dev, pTaddr); - - pDot11dInfo->CountryIeLen = CoutryIeLen; - memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen); - pDot11dInfo->State = DOT11D_STATE_LEARNED; -} - -u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 MaxTxPwrInDbm = 255; - - if (MAX_CHANNEL_NUMBER < Channel) { - netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); - return MaxTxPwrInDbm; - } - if (pDot11dInfo->channel_map[Channel]) - MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; - - return MaxTxPwrInDbm; -} - - -void DOT11D_ScanComplete(struct ieee80211_device *dev) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - - switch (pDot11dInfo->State) { - case DOT11D_STATE_LEARNED: - pDot11dInfo->State = DOT11D_STATE_DONE; - break; - - case DOT11D_STATE_DONE: - if (GET_CIE_WATCHDOG(dev) == 0) { - /* Reset country IE if previous one is gone. */ - Dot11d_Reset(dev); - } - break; - case DOT11D_STATE_NONE: - break; - } -} - -int IsLegalChannel(struct ieee80211_device *dev, u8 channel) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - - if (MAX_CHANNEL_NUMBER < channel) { - netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n"); - return 0; - } - if (pDot11dInfo->channel_map[channel] > 0) - return 1; - return 0; -} - -int ToLegalChannel(struct ieee80211_device *dev, u8 channel) -{ - PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); - u8 default_chn = 0; - u32 i = 0; - - for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) { - if (pDot11dInfo->channel_map[i] > 0) { - default_chn = i; - break; - } - } - - if (MAX_CHANNEL_NUMBER < channel) { - netdev_info(dev->dev, "IsLegalChannel(): Invalid Channel\n"); - return default_chn; - } - - if (pDot11dInfo->channel_map[channel] > 0) - return channel; - - return default_chn; -} diff --git a/drivers/staging/rtl8187se/ieee80211/dot11d.h b/drivers/staging/rtl8187se/ieee80211/dot11d.h deleted file mode 100644 index f996691307bf5b..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/dot11d.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef __INC_DOT11D_H -#define __INC_DOT11D_H - -#include "ieee80211.h" - -/* #define ENABLE_DOT11D */ - -/* #define DOT11D_MAX_CHNL_NUM 83 */ - -typedef struct _CHNL_TXPOWER_TRIPLE { - u8 FirstChnl; - u8 NumChnls; - u8 MaxTxPowerInDbm; -} CHNL_TXPOWER_TRIPLE, *PCHNL_TXPOWER_TRIPLE; - -typedef enum _DOT11D_STATE { - DOT11D_STATE_NONE = 0, - DOT11D_STATE_LEARNED, - DOT11D_STATE_DONE, -} DOT11D_STATE; - -typedef struct _RT_DOT11D_INFO { - /* DECLARE_RT_OBJECT(RT_DOT12D_INFO); */ - - bool bEnabled; /* dot11MultiDomainCapabilityEnabled */ - - u16 CountryIeLen; /* > 0 if CountryIeBuf[] contains valid country information element. */ - u8 CountryIeBuf[MAX_IE_LEN]; - u8 CountryIeSrcAddr[6]; /* Source AP of the country IE. */ - u8 CountryIeWatchdog; - - u8 channel_map[MAX_CHANNEL_NUMBER+1]; /* !!!Value 0: Invalid, 1: Valid (active scan), 2: Valid (passive scan) */ - /* u8 ChnlListLen; // #Bytes valid in ChnlList[]. */ - /* u8 ChnlList[DOT11D_MAX_CHNL_NUM]; */ - u8 MaxTxPwrDbmList[MAX_CHANNEL_NUMBER+1]; - - DOT11D_STATE State; -} RT_DOT11D_INFO, *PRT_DOT11D_INFO; - -#define eqMacAddr(a, b) (((a)[0] == (b)[0] && (a)[1] == (b)[1] && (a)[2] == (b)[2] && (a)[3] == (b)[3] && (a)[4] == (b)[4] && (a)[5] == (b)[5]) ? 1:0) -#define cpMacAddr(des, src) ((des)[0] = (src)[0], (des)[1] = (src)[1], (des)[2] = (src)[2], (des)[3] = (src)[3], (des)[4] = (src)[4], (des)[5] = (src)[5]) -#define GET_DOT11D_INFO(__pIeeeDev) ((PRT_DOT11D_INFO)((__pIeeeDev)->pDot11dInfo)) - -#define IS_DOT11D_ENABLE(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->bEnabled -#define IS_COUNTRY_IE_VALID(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen > 0) - -#define IS_EQUAL_CIE_SRC(__pIeeeDev, __pTa) eqMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) -#define UPDATE_CIE_SRC(__pIeeeDev, __pTa) cpMacAddr(GET_DOT11D_INFO(__pIeeeDev)->CountryIeSrcAddr, __pTa) - -#define IS_COUNTRY_IE_CHANGED(__pIeeeDev, __Ie) \ - (((__Ie).Length == 0 || (__Ie).Length != GET_DOT11D_INFO(__pIeeeDev)->CountryIeLen) ? \ - FALSE : \ - (!memcmp(GET_DOT11D_INFO(__pIeeeDev)->CountryIeBuf, (__Ie).Octet, (__Ie).Length))) - -#define CIE_WATCHDOG_TH 1 -#define GET_CIE_WATCHDOG(__pIeeeDev) GET_DOT11D_INFO(__pIeeeDev)->CountryIeWatchdog -#define RESET_CIE_WATCHDOG(__pIeeeDev) GET_CIE_WATCHDOG(__pIeeeDev) = 0 -#define UPDATE_CIE_WATCHDOG(__pIeeeDev) ++GET_CIE_WATCHDOG(__pIeeeDev) - -#define IS_DOT11D_STATE_DONE(__pIeeeDev) (GET_DOT11D_INFO(__pIeeeDev)->State == DOT11D_STATE_DONE) - -void Dot11d_Init(struct ieee80211_device *dev); -void Dot11d_Reset(struct ieee80211_device *dev); -void Dot11d_UpdateCountryIe(struct ieee80211_device *dev, u8 *pTaddr, - u16 CoutryIeLen, u8 *pCoutryIe); -u8 DOT11D_GetMaxTxPwrInDbm(struct ieee80211_device *dev, u8 Channel); -void DOT11D_ScanComplete(struct ieee80211_device *dev); -int IsLegalChannel(struct ieee80211_device *dev, u8 channel); -int ToLegalChannel(struct ieee80211_device *dev, u8 channel); - -#endif /* #ifndef __INC_DOT11D_H */ diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h deleted file mode 100644 index d1763b7b8f271f..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ /dev/null @@ -1,1496 +0,0 @@ -/* - * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 - * remains copyright by the original authors - * - * Portions of the merged code are based on Host AP (software wireless - * LAN access point) driver for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * - * Copyright (c) 2004, Intel Corporation - * - * Modified for Realtek's wi-fi cards by Andrea Merello - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ -#ifndef IEEE80211_H -#define IEEE80211_H -#include /* ETH_ALEN */ -#include /* ARRAY_SIZE */ -#include -#include -#include -#include -#include -#include -#include - -#define KEY_TYPE_NA 0x0 -#define KEY_TYPE_WEP40 0x1 -#define KEY_TYPE_TKIP 0x2 -#define KEY_TYPE_CCMP 0x4 -#define KEY_TYPE_WEP104 0x5 - -#define aSifsTime 10 - -#define MGMT_QUEUE_NUM 5 - - -#define IEEE_CMD_SET_WPA_PARAM 1 -#define IEEE_CMD_SET_WPA_IE 2 -#define IEEE_CMD_SET_ENCRYPTION 3 -#define IEEE_CMD_MLME 4 - -#define IEEE_PARAM_WPA_ENABLED 1 -#define IEEE_PARAM_TKIP_COUNTERMEASURES 2 -#define IEEE_PARAM_DROP_UNENCRYPTED 3 -#define IEEE_PARAM_PRIVACY_INVOKED 4 -#define IEEE_PARAM_AUTH_ALGS 5 -#define IEEE_PARAM_IEEE_802_1X 6 -//It should consistent with the driver_XXX.c -// David, 2006.9.26 -#define IEEE_PARAM_WPAX_SELECT 7 -//Added for notify the encryption type selection -// David, 2006.9.26 -#define IEEE_PROTO_WPA 1 -#define IEEE_PROTO_RSN 2 -//Added for notify the encryption type selection -// David, 2006.9.26 -#define IEEE_WPAX_USEGROUP 0 -#define IEEE_WPAX_WEP40 1 -#define IEEE_WPAX_TKIP 2 -#define IEEE_WPAX_WRAP 3 -#define IEEE_WPAX_CCMP 4 -#define IEEE_WPAX_WEP104 5 - -#define IEEE_KEY_MGMT_IEEE8021X 1 -#define IEEE_KEY_MGMT_PSK 2 - - - -#define IEEE_MLME_STA_DEAUTH 1 -#define IEEE_MLME_STA_DISASSOC 2 - - -#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2 -#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3 -#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5 -#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7 - - -#define IEEE_CRYPT_ALG_NAME_LEN 16 - -extern int ieee80211_crypto_tkip_init(void); -extern void ieee80211_crypto_tkip_exit(void); - -//by amy for ps -typedef struct ieee_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 name; - u32 value; - } wpa_param; - struct { - u32 len; - u8 reserved[32]; - u8 data[0]; - } wpa_ie; - struct{ - int command; - int reason_code; - } mlme; - struct { - u8 alg[IEEE_CRYPT_ALG_NAME_LEN]; - u8 set_tx; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - - } u; -}ieee_param; - - -#define MSECS(t) msecs_to_jiffies(t) -#define msleep_interruptible_rtl msleep_interruptible - -#define IEEE80211_DATA_LEN 2304 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - 6.2.1.1.2. - - The figure in section 7.1.2 suggests a body size of up to 2312 - bytes is allowed, which is a bit confusing, I suspect this - represents the 2304 bytes of real data, plus a possible 8 bytes of - WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ - -#define IEEE80211_3ADDR_LEN 24 -#define IEEE80211_4ADDR_LEN 30 -#define IEEE80211_FCS_LEN 4 -#define IEEE80211_HLEN IEEE80211_4ADDR_LEN -#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) -#define IEEE80211_MGMT_HDR_LEN 24 -#define IEEE80211_DATA_HDR3_LEN 24 -#define IEEE80211_DATA_HDR4_LEN 30 - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* Frame control field constants */ -#define IEEE80211_FCTL_DSTODS 0x0300 //added by david -#define IEEE80211_FCTL_WEP 0x4000 - -/* debug macros */ - -#ifdef CONFIG_IEEE80211_DEBUG -extern u32 ieee80211_debug_level; -#define IEEE80211_DEBUG(level, fmt, args...) \ -do { if (ieee80211_debug_level & (level)) \ - printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) -#else -#define IEEE80211_DEBUG(level, fmt, args...) do {} while (0) -#endif /* CONFIG_IEEE80211_DEBUG */ - -/* - * To use the debug system; - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define IEEE80211_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a IEEE80211_xxxx_DEBUG() macro definition for your - * classification, or use IEEE80211_DEBUG(IEEE80211_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/ipw/debug_level - * - * you simply need to add your entry to the ipw_debug_levels array. - * - * If you do not see debug_level in /proc/net/ipw then you do not have - * CONFIG_IEEE80211_DEBUG defined in your kernel configuration - * - */ - -#define IEEE80211_DL_INFO (1<<0) -#define IEEE80211_DL_WX (1<<1) -#define IEEE80211_DL_SCAN (1<<2) -#define IEEE80211_DL_STATE (1<<3) -#define IEEE80211_DL_MGMT (1<<4) -#define IEEE80211_DL_FRAG (1<<5) -#define IEEE80211_DL_EAP (1<<6) -#define IEEE80211_DL_DROP (1<<7) - -#define IEEE80211_DL_TX (1<<8) -#define IEEE80211_DL_RX (1<<9) - -#define IEEE80211_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) -#define IEEE80211_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) -#define IEEE80211_DEBUG_INFO(f, a...) IEEE80211_DEBUG(IEEE80211_DL_INFO, f, ## a) - -#define IEEE80211_DEBUG_WX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_WX, f, ## a) -#define IEEE80211_DEBUG_SCAN(f, a...) IEEE80211_DEBUG(IEEE80211_DL_SCAN, f, ## a) -//#define IEEE_DEBUG_SCAN IEEE80211_WARNING -#define IEEE80211_DEBUG_STATE(f, a...) IEEE80211_DEBUG(IEEE80211_DL_STATE, f, ## a) -#define IEEE80211_DEBUG_MGMT(f, a...) IEEE80211_DEBUG(IEEE80211_DL_MGMT, f, ## a) -#define IEEE80211_DEBUG_FRAG(f, a...) IEEE80211_DEBUG(IEEE80211_DL_FRAG, f, ## a) -#define IEEE80211_DEBUG_EAP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_EAP, f, ## a) -#define IEEE80211_DEBUG_DROP(f, a...) IEEE80211_DEBUG(IEEE80211_DL_DROP, f, ## a) -#define IEEE80211_DEBUG_TX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_TX, f, ## a) -#define IEEE80211_DEBUG_RX(f, a...) IEEE80211_DEBUG(IEEE80211_DL_RX, f, ## a) -#include -#include /* ARPHRD_ETHER */ - -#ifndef WIRELESS_SPY -#define WIRELESS_SPY // enable iwspy support -#endif -#include // new driver API - -#ifndef ETH_P_PAE -#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ -#endif /* ETH_P_PAE */ - -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW (ETH_P_ECONET + 1) -#endif - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct ieee80211_snap_hdr { - - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ - -} __attribute__ ((packed)); - -#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr) - -#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) -#define WLAN_GET_SEQ_SEQ(seq) ((seq) & IEEE80211_SCTL_SEQ) - -#define WLAN_CAPABILITY_BSS (1<<0) -#define WLAN_CAPABILITY_SHORT_SLOT (1<<10) - -#define IEEE80211_STATMASK_SIGNAL (1<<0) -#define IEEE80211_STATMASK_RSSI (1<<1) -#define IEEE80211_STATMASK_NOISE (1<<2) -#define IEEE80211_STATMASK_RATE (1<<3) -#define IEEE80211_STATMASK_WEMASK 0x7 - - -#define IEEE80211_CCK_MODULATION (1<<0) -#define IEEE80211_OFDM_MODULATION (1<<1) - -#define IEEE80211_24GHZ_BAND (1<<0) -#define IEEE80211_52GHZ_BAND (1<<1) - -#define IEEE80211_CCK_RATE_LEN 4 -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_LEN 8 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - -#define IEEE80211_NUM_OFDM_RATES 8 -#define IEEE80211_NUM_CCK_RATES 4 -#define IEEE80211_OFDM_SHIFT_MASK_A 4 - -/* this is stolen and modified from the madwifi driver*/ -#define IEEE80211_FC0_TYPE_MASK 0x0c -#define IEEE80211_FC0_TYPE_DATA 0x08 -#define IEEE80211_FC0_SUBTYPE_MASK 0xB0 -#define IEEE80211_FC0_SUBTYPE_QOS 0x80 - -#define IEEE80211_QOS_HAS_SEQ(fc) \ - (((fc) & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) == \ - (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)) - -/* this is stolen from ipw2200 driver */ -#define IEEE_IBSS_MAC_HASH_SIZE 31 -struct ieee_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num[17]; - u16 frag_num[17]; - unsigned long packet_time[17]; - struct list_head list; -}; - -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. Not setting these will not cause - * any adverse affects. */ -struct ieee80211_rx_stats { - u32 mac_time[2]; - u8 signalstrength; - s8 rssi; - u8 signal; - u8 noise; - u16 rate; /* in 100 kbps */ - u8 received_channel; - u8 control; - u8 mask; - u8 freq; - u16 len; - u8 nic_type; -}; - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ -#define IEEE80211_FRAG_CACHE_LEN 4 - -struct ieee80211_frag_entry { - unsigned long first_frag_time; - unsigned int seq; - unsigned int last_frag; - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct ieee80211_stats { - unsigned int tx_unicast_frames; - unsigned int tx_multicast_frames; - unsigned int tx_fragments; - unsigned int tx_unicast_octets; - unsigned int tx_multicast_octets; - unsigned int tx_deferred_transmissions; - unsigned int tx_single_retry_frames; - unsigned int tx_multiple_retry_frames; - unsigned int tx_retry_limit_exceeded; - unsigned int tx_discards; - unsigned int rx_unicast_frames; - unsigned int rx_multicast_frames; - unsigned int rx_fragments; - unsigned int rx_unicast_octets; - unsigned int rx_multicast_octets; - unsigned int rx_fcs_errors; - unsigned int rx_discards_no_buffer; - unsigned int tx_discards_wrong_sa; - unsigned int rx_discards_undecryptable; - unsigned int rx_message_in_msg_fragments; - unsigned int rx_message_in_bad_msg_fragments; -}; - -struct ieee80211_device; - -#include "ieee80211_crypt.h" - -#define SEC_KEY_1 (1<<0) -#define SEC_KEY_2 (1<<1) -#define SEC_KEY_3 (1<<2) -#define SEC_KEY_4 (1<<3) -#define SEC_ACTIVE_KEY (1<<4) -#define SEC_AUTH_MODE (1<<5) -#define SEC_UNICAST_GROUP (1<<6) -#define SEC_LEVEL (1<<7) -#define SEC_ENABLED (1<<8) - -#define SEC_LEVEL_0 0 /* None */ -#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ -#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ -#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ -#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ - -#define WEP_KEYS 4 -#define WEP_KEY_LEN 13 - -#define WEP_KEY_LEN_MODIF 32 - -struct ieee80211_security { - u16 active_key:2, - enabled:1, - auth_mode:2, - auth_algo:4, - unicast_uses_group:1; - u8 key_sizes[WEP_KEYS]; - u8 keys[WEP_KEYS][WEP_KEY_LEN_MODIF]; - u8 level; - u16 flags; -} __attribute__ ((packed)); - - -/* - - 802.11 data frame from AP - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `-------------------------------------------------------------------' - -Total: 28-2340 bytes - -*/ - -/* Management Frame Information Element Types */ -enum { - MFIE_TYPE_SSID = 0, - MFIE_TYPE_RATES = 1, - MFIE_TYPE_FH_SET = 2, - MFIE_TYPE_DS_SET = 3, - MFIE_TYPE_CF_SET = 4, - MFIE_TYPE_TIM = 5, - MFIE_TYPE_IBSS_SET = 6, - MFIE_TYPE_COUNTRY = 7, - MFIE_TYPE_CHALLENGE = 16, - MFIE_TYPE_ERP = 42, - MFIE_TYPE_RSN = 48, - MFIE_TYPE_RATES_EX = 50, - MFIE_TYPE_GENERIC = 221, -}; - -struct ieee80211_header_data { - __le16 frame_ctl; - u16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - u16 seq_ctrl; -}; - -struct ieee80211_hdr_4addr { - __le16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; -} __attribute__ ((packed)); - -struct ieee80211_hdr_3addrqos { - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u16 qos_ctl; -} __attribute__ ((packed)); - -struct ieee80211_hdr_4addrqos { - u16 frame_ctl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctl; - u8 addr4[ETH_ALEN]; - u16 qos_ctl; -} __attribute__ ((packed)); - -struct ieee80211_info_element_hdr { - u8 id; - u8 len; -} __attribute__ ((packed)); - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[0]; -} __attribute__ ((packed)); - -struct ieee80211_authentication { - struct ieee80211_header_data header; - u16 algorithm; - u16 transaction; - u16 status; - //struct ieee80211_info_element_hdr info_element; -} __attribute__ ((packed)); - -struct ieee80211_disassoc_frame { - struct ieee80211_hdr_3addr header; - u16 reasoncode; -} __attribute__ ((packed)); - -struct ieee80211_probe_request { - struct ieee80211_header_data header; - /* struct ieee80211_info_element info_element; */ -} __attribute__ ((packed)); - -struct ieee80211_probe_response { - struct ieee80211_header_data header; - u32 time_stamp[2]; - u16 beacon_interval; - u16 capability; - struct ieee80211_info_element info_element; -} __attribute__ ((packed)); - -struct ieee80211_assoc_request_frame { - struct ieee80211_hdr_3addr header; - u16 capability; - u16 listen_interval; - //u8 current_ap[ETH_ALEN]; - struct ieee80211_info_element_hdr info_element; -} __attribute__ ((packed)); - -struct ieee80211_assoc_response_frame { - struct ieee80211_hdr_3addr header; - u16 capability; - u16 status; - u16 aid; - struct ieee80211_info_element info_element; /* supported rates */ -} __attribute__ ((packed)); - -struct ieee80211_txb { - u8 nr_frags; - u8 encrypted; - u16 reserved; - u16 frag_size; - u16 payload_size; - struct sk_buff *fragments[0]; -}; - -/* SWEEP TABLE ENTRIES NUMBER */ -#define MAX_SWEEP_TAB_ENTRIES 42 -#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 - -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... */ -#define MAX_RATES_LENGTH ((u8)12) -#define MAX_RATES_EX_LENGTH ((u8)16) - -#define MAX_NETWORK_COUNT 128 - -#define MAX_CHANNEL_NUMBER 165 - -#define IEEE80211_SOFTMAC_SCAN_TIME 100 /* (HZ / 2) */ -#define IEEE80211_SOFTMAC_ASSOC_RETRY_TIME (HZ * 2) - -#define CRC_LENGTH 4U - -#define MAX_WPA_IE_LEN 64 - -#define NETWORK_EMPTY_ESSID (1 << 0) -#define NETWORK_HAS_OFDM (1 << 1) -#define NETWORK_HAS_CCK (1 << 2) - -struct ieee80211_wmm_ac_param { - u8 ac_aci_acm_aifsn; - u8 ac_ecwmin_ecwmax; - u16 ac_txop_limit; -}; - -struct ieee80211_wmm_ts_info { - u8 ac_dir_tid; - u8 ac_up_psb; - u8 reserved; -} __attribute__ ((packed)); - -struct ieee80211_wmm_tspec_elem { - struct ieee80211_wmm_ts_info ts_info; - u16 norm_msdu_size; - u16 max_msdu_size; - u32 min_serv_inter; - u32 max_serv_inter; - u32 inact_inter; - u32 suspen_inter; - u32 serv_start_time; - u32 min_data_rate; - u32 mean_data_rate; - u32 peak_data_rate; - u32 max_burst_size; - u32 delay_bound; - u32 min_phy_rate; - u16 surp_band_allow; - u16 medium_time; -}__attribute__((packed)); - -enum eap_type { - EAP_PACKET = 0, - EAPOL_START, - EAPOL_LOGOFF, - EAPOL_KEY, - EAPOL_ENCAP_ASF_ALERT -}; - -static const char *eap_types[] = { - [EAP_PACKET] = "EAP-Packet", - [EAPOL_START] = "EAPOL-Start", - [EAPOL_LOGOFF] = "EAPOL-Logoff", - [EAPOL_KEY] = "EAPOL-Key", - [EAPOL_ENCAP_ASF_ALERT] = "EAPOL-Encap-ASF-Alert" -}; - -static inline const char *eap_get_type(int type) -{ - return (type >= ARRAY_SIZE(eap_types)) ? "Unknown" : eap_types[type]; -} - -struct eapol { - u8 snap[6]; - u16 ethertype; - u8 version; - u8 type; - u16 length; -} __attribute__ ((packed)); - -struct ieee80211_softmac_stats { - unsigned int rx_ass_ok; - unsigned int rx_ass_err; - unsigned int rx_probe_rq; - unsigned int tx_probe_rs; - unsigned int tx_beacons; - unsigned int rx_auth_rq; - unsigned int rx_auth_rs_ok; - unsigned int rx_auth_rs_err; - unsigned int tx_auth_rq; - unsigned int no_auth_rs; - unsigned int no_ass_rs; - unsigned int tx_ass_rq; - unsigned int rx_ass_rq; - unsigned int tx_probe_rq; - unsigned int reassoc; - unsigned int swtxstop; - unsigned int swtxawake; -}; - -#define BEACON_PROBE_SSID_ID_POSITION 12 - -/* - * These are the data types that can make up management packets - * - u16 auth_algorithm; - u16 auth_sequence; - u16 beacon_interval; - u16 capability; - u8 current_ap[ETH_ALEN]; - u16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __attribute__ ((packed)); - u32 time_stamp[2]; - u16 reason; - u16 status; -*/ - -#define IEEE80211_DEFAULT_TX_ESSID "Penguin" -#define IEEE80211_DEFAULT_BASIC_RATE 10 - -enum {WMM_all_frame, WMM_two_frame, WMM_four_frame, WMM_six_frame}; -#define MAX_SP_Len (WMM_all_frame << 4) -#define IEEE80211_QOS_TID 0x0f -#define QOS_CTL_NOTCONTAIN_ACK (0x01 << 5) - -#define MAX_IE_LEN 0xFF //+YJ,080625 - -struct rtl8187se_channel_list { - u8 channel[MAX_CHANNEL_NUMBER + 1]; - u8 len; -}; - -//by amy for ps -#define IEEE80211_WATCH_DOG_TIME 2000 -//by amy for ps -//by amy for antenna -#define ANTENNA_DIVERSITY_TIMER_PERIOD 1000 // 1000 m -//by amy for antenna - -#define IEEE80211_DTIM_MBCAST 4 -#define IEEE80211_DTIM_UCAST 2 -#define IEEE80211_DTIM_VALID 1 -#define IEEE80211_DTIM_INVALID 0 - -#define IEEE80211_PS_DISABLED 0 -#define IEEE80211_PS_UNICAST IEEE80211_DTIM_UCAST -#define IEEE80211_PS_MBCAST IEEE80211_DTIM_MBCAST -#define IEEE80211_PS_ENABLE IEEE80211_DTIM_VALID -//added by David for QoS 2006/6/30 -//#define WMM_Hang_8187 -#ifdef WMM_Hang_8187 -#undef WMM_Hang_8187 -#endif - -#define WME_AC_BE 0x00 -#define WME_AC_BK 0x01 -#define WME_AC_VI 0x02 -#define WME_AC_VO 0x03 -#define WME_ACI_MASK 0x03 -#define WME_AIFSN_MASK 0x03 -#define WME_AC_PRAM_LEN 16 - -//UP Mapping to AC, using in MgntQuery_SequenceNumber() and maybe for DSCP -//#define UP2AC(up) ((up<3) ? ((up==0)?1:0) : (up>>1)) -#define UP2AC(up) ( \ - ((up) < 1) ? WME_AC_BE : \ - ((up) < 3) ? WME_AC_BK : \ - ((up) < 4) ? WME_AC_BE : \ - ((up) < 6) ? WME_AC_VI : \ - WME_AC_VO) -//AC Mapping to UP, using in Tx part for selecting the corresponding TX queue -#define AC2UP(_ac) ( \ - ((_ac) == WME_AC_VO) ? 6 : \ - ((_ac) == WME_AC_VI) ? 5 : \ - ((_ac) == WME_AC_BK) ? 1 : \ - 0) - -#define ETHER_ADDR_LEN 6 /* length of an Ethernet address */ -struct ether_header { - u8 ether_dhost[ETHER_ADDR_LEN]; - u8 ether_shost[ETHER_ADDR_LEN]; - u16 ether_type; -} __attribute__((packed)); - -#ifndef ETHERTYPE_PAE -#define ETHERTYPE_PAE 0x888e /* EAPOL PAE/802.1x */ -#endif -#ifndef ETHERTYPE_IP -#define ETHERTYPE_IP 0x0800 /* IP protocol */ -#endif - -struct ieee80211_network { - /* These entries are used to identify a unique network */ - u8 bssid[ETH_ALEN]; - u8 channel; - /* Ensure null-terminated for any debug msgs */ - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - - /* These are network statistics */ - struct ieee80211_rx_stats stats; - u16 capability; - u8 rates[MAX_RATES_LENGTH]; - u8 rates_len; - u8 rates_ex[MAX_RATES_EX_LENGTH]; - u8 rates_ex_len; - unsigned long last_scanned; - u8 mode; - u8 flags; - u32 last_associate; - u32 time_stamp[2]; - u16 beacon_interval; - u16 listen_interval; - u16 atim_window; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - u8 dtim_period; - u8 dtim_data; - u32 last_dtim_sta_time[2]; - struct list_head list; - //appeded for QoS - u8 wmm_info; - struct ieee80211_wmm_ac_param wmm_param[4]; - u8 QoS_Enable; - u8 SignalStrength; -//by amy 080312 - u8 HighestOperaRate; -//by amy 080312 - u8 Turbo_Enable;//enable turbo mode, added by thomas - u16 CountryIeLen; - u8 CountryIeBuf[MAX_IE_LEN]; -}; - -enum ieee80211_state { - - /* the card is not linked at all */ - IEEE80211_NOLINK = 0, - - /* IEEE80211_ASSOCIATING* are for BSS client mode - * the driver shall not perform RX filtering unless - * the state is LINKED. - * The driver shall just check for the state LINKED and - * defaults to NOLINK for ALL the other states (including - * LINKED_SCANNING) - */ - - /* the association procedure will start (wq scheduling)*/ - IEEE80211_ASSOCIATING, - IEEE80211_ASSOCIATING_RETRY, - - /* the association procedure is sending AUTH request*/ - IEEE80211_ASSOCIATING_AUTHENTICATING, - - /* the association procedure has successfully authenticated - * and is sending association request - */ - IEEE80211_ASSOCIATING_AUTHENTICATED, - - /* the link is ok. the card associated to a BSS or linked - * to a ibss cell or acting as an AP and creating the bss - */ - IEEE80211_LINKED, - - /* same as LINKED, but the driver shall apply RX filter - * rules as we are in NO_LINK mode. As the card is still - * logically linked, but it is doing a syncro site survey - * then it will be back to LINKED state. - */ - IEEE80211_LINKED_SCANNING, - -}; - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) -#define DEFAULT_FTS 2346 - -#define CFG_IEEE80211_RESERVE_FCS (1<<0) -#define CFG_IEEE80211_COMPUTE_FCS (1<<1) - -typedef struct tx_pending_t{ - int frag; - struct ieee80211_txb *txb; -}tx_pending_t; - -enum { - COUNTRY_CODE_FCC = 0, - COUNTRY_CODE_IC = 1, - COUNTRY_CODE_ETSI = 2, - COUNTRY_CODE_SPAIN = 3, - COUNTRY_CODE_FRANCE = 4, - COUNTRY_CODE_MKK = 5, - COUNTRY_CODE_MKK1 = 6, - COUNTRY_CODE_ISRAEL = 7, - COUNTRY_CODE_TELEC = 8, - COUNTRY_CODE_GLOBAL_DOMAIN = 9, - COUNTRY_CODE_WORLD_WIDE_13_INDEX = 10 -}; - -struct ieee80211_device { - struct net_device *dev; - - /* Bookkeeping structures */ - struct net_device_stats stats; - struct ieee80211_stats ieee_stats; - struct ieee80211_softmac_stats softmac_stats; - - /* Probe / Beacon management */ - struct list_head network_free_list; - struct list_head network_list; - struct ieee80211_network *networks; - int scans; - int scan_age; - - int iw_mode; /* operating mode (IW_MODE_*) */ - - spinlock_t lock; - spinlock_t wpax_suitlist_lock; - - int tx_headroom; /* Set to size of any additional room needed at front - * of allocated Tx SKBs */ - u32 config; - - /* WEP and other encryption related settings at the device level */ - int open_wep; /* Set to 1 to allow unencrypted frames */ - - int reset_on_keychange; /* Set to 1 if the HW needs to be reset on - * WEP key changes */ - - /* If the host performs {en,de}cryption, then set to 1 */ - int host_encrypt; - int host_decrypt; - int ieee802_1x; /* is IEEE 802.1X used */ - - /* WPA data */ - int wpa_enabled; - int drop_unencrypted; - int tkip_countermeasures; - int privacy_invoked; - size_t wpa_ie_len; - u8 *wpa_ie; - - u8 ap_mac_addr[6]; - u16 pairwise_key_type; - u16 broadcast_key_type; - - struct list_head crypt_deinit_list; - struct ieee80211_crypt_data *crypt[WEP_KEYS]; - int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */ - struct timer_list crypt_deinit_timer; - - int bcrx_sta_key; /* use individual keys to override default keys even - * with RX of broad/multicast frames */ - - /* Fragmentation structures */ - /* each stream contains an entry */ - struct ieee80211_frag_entry frag_cache[17][IEEE80211_FRAG_CACHE_LEN]; - unsigned int frag_next_idx[17]; - u16 fts; /* Fragmentation Threshold */ - - /* This stores infos for the current network. - * Either the network we are associated in INFRASTRUCTURE - * or the network that we are creating in MASTER mode. - * ad-hoc is a mixture ;-). - * Note that in infrastructure mode, even when not associated, - * fields bssid and essid may be valid (if wpa_set and essid_set - * are true) as thy carry the value set by the user via iwconfig - */ - struct ieee80211_network current_network; - - - enum ieee80211_state state; - - int short_slot; - int mode; /* A, B, G */ - int modulation; /* CCK, OFDM */ - int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ - int abg_true; /* ABG flag */ - - /* used for forcing the ibss workqueue to terminate - * without wait for the syncro scan to terminate - */ - short sync_scan_hurryup; - - void * pDot11dInfo; - bool bGlobalDomain; - - // For Liteon Ch12~13 passive scan - u8 MinPassiveChnlNum; - u8 IbssStartChnl; - - int rate; /* current rate */ - int basic_rate; - //FIXME: please callback, see if redundant with softmac_features - short active_scan; - - /* this contains flags for selectively enable softmac support */ - u16 softmac_features; - - /* if the sequence control field is not filled by HW */ - u16 seq_ctrl[5]; - - /* association procedure transaction sequence number */ - u16 associate_seq; - - /* AID for RTXed association responses */ - u16 assoc_id; - - /* power save mode related*/ - short ps; - short sta_sleep; - int ps_timeout; - struct tasklet_struct ps_task; - u32 ps_th; - u32 ps_tl; - - short raw_tx; - /* used if IEEE_SOFTMAC_TX_QUEUE is set */ - short queue_stop; - short scanning; - short proto_started; - - struct semaphore wx_sem; - struct semaphore scan_sem; - - spinlock_t mgmt_tx_lock; - spinlock_t beacon_lock; - - short beacon_txing; - - short wap_set; - short ssid_set; - - u8 wpax_type_set; //{added by David, 2006.9.28} - u32 wpax_type_notify; //{added by David, 2006.9.26} - - /* QoS related flag */ - char init_wmmparam_flag; - - /* for discarding duplicated packets in IBSS */ - struct list_head ibss_mac_hash[IEEE_IBSS_MAC_HASH_SIZE]; - - /* for discarding duplicated packets in BSS */ - u16 last_rxseq_num[17]; /* rx seq previous per-tid */ - u16 last_rxfrag_num[17];/* tx frag previous per-tid */ - unsigned long last_packet_time[17]; - - /* for PS mode */ - unsigned long last_rx_ps_time; - - /* used if IEEE_SOFTMAC_SINGLE_QUEUE is set */ - struct sk_buff *mgmt_queue_ring[MGMT_QUEUE_NUM]; - int mgmt_queue_head; - int mgmt_queue_tail; - - - /* used if IEEE_SOFTMAC_TX_QUEUE is set */ - struct tx_pending_t tx_pending; - - /* used if IEEE_SOFTMAC_ASSOCIATE is set */ - struct timer_list associate_timer; - - /* used if IEEE_SOFTMAC_BEACONS is set */ - struct timer_list beacon_timer; - - struct work_struct associate_complete_wq; -// struct work_struct associate_retry_wq; - struct work_struct associate_procedure_wq; -// struct work_struct softmac_scan_wq; - struct work_struct wx_sync_scan_wq; - struct work_struct wmm_param_update_wq; - struct work_struct ps_request_tx_ack_wq;//for ps -// struct work_struct hw_wakeup_wq; -// struct work_struct hw_sleep_wq; -// struct work_struct watch_dog_wq; - bool bInactivePs; - bool actscanning; - bool beinretry; - u16 ListenInterval; - unsigned long NumRxDataInPeriod; //YJ,add,080828 - unsigned long NumRxBcnInPeriod; //YJ,add,080828 - unsigned long NumRxOkTotal; - unsigned long NumRxUnicast;//YJ,add,080828,for keep alive - bool bHwRadioOff; - struct delayed_work softmac_scan_wq; - struct delayed_work associate_retry_wq; - struct delayed_work hw_wakeup_wq; - struct delayed_work hw_sleep_wq;//+by amy 080324 - struct delayed_work watch_dog_wq; - struct delayed_work sw_antenna_wq; - struct delayed_work start_ibss_wq; -//by amy for rate adaptive 080312 - struct delayed_work rate_adapter_wq; -//by amy for rate adaptive - struct delayed_work hw_dig_wq; - struct delayed_work tx_pw_wq; - -//Added for RF power on power off by lizhaoming 080512 - struct delayed_work GPIOChangeRFWorkItem; - - struct workqueue_struct *wq; - - /* Callback functions */ - void (*set_security)(struct net_device *dev, - struct ieee80211_security *sec); - - /* Used to TX data frame by using txb structs. - * this is not used if in the softmac_features - * is set the flag IEEE_SOFTMAC_TX_QUEUE - */ - int (*hard_start_xmit)(struct ieee80211_txb *txb, - struct net_device *dev); - - int (*reset_port)(struct net_device *dev); - - /* Softmac-generated frames (management) are TXed via this - * callback if the flag IEEE_SOFTMAC_SINGLE_QUEUE is - * not set. As some cards may have different HW queues that - * one might want to use for data and management frames - * the option to have two callbacks might be useful. - * This function can't sleep. - */ - int (*softmac_hard_start_xmit)(struct sk_buff *skb, - struct net_device *dev); - - /* used instead of hard_start_xmit (not softmac_hard_start_xmit) - * if the IEEE_SOFTMAC_TX_QUEUE feature is used to TX data - * frames. If the option IEEE_SOFTMAC_SINGLE_QUEUE is also set - * then also management frames are sent via this callback. - * This function can't sleep. - */ - void (*softmac_data_hard_start_xmit)(struct sk_buff *skb, - struct net_device *dev,int rate); - - /* stops the HW queue for DATA frames. Useful to avoid - * waste time to TX data frame when we are reassociating - * This function can sleep. - */ - void (*data_hard_stop)(struct net_device *dev); - - /* OK this is complementar to data_poll_hard_stop */ - void (*data_hard_resume)(struct net_device *dev); - - /* ask to the driver to retune the radio . - * This function can sleep. the driver should ensure - * the radio has been switched before return. - */ - void (*set_chan)(struct net_device *dev,short ch); - - /* These are not used if the ieee stack takes care of - * scanning (IEEE_SOFTMAC_SCAN feature set). - * In this case only the set_chan is used. - * - * The syncro version is similar to the start_scan but - * does not return until all channels has been scanned. - * this is called in user context and should sleep, - * it is called in a work_queue when switching to ad-hoc mode - * or in behalf of iwlist scan when the card is associated - * and root user ask for a scan. - * the function stop_scan should stop both the syncro and - * background scanning and can sleep. - * The function start_scan should initiate the background - * scanning and can't sleep. - */ - void (*scan_syncro)(struct net_device *dev); - void (*start_scan)(struct net_device *dev); - void (*stop_scan)(struct net_device *dev); - - /* indicate the driver that the link state is changed - * for example it may indicate the card is associated now. - * Driver might be interested in this to apply RX filter - * rules or simply light the LINK led - */ - void (*link_change)(struct net_device *dev); - - /* these two function indicates to the HW when to start - * and stop to send beacons. This is used when the - * IEEE_SOFTMAC_BEACONS is not set. For now the - * stop_send_bacons is NOT guaranteed to be called only - * after start_send_beacons. - */ - void (*start_send_beacons) (struct net_device *dev); - void (*stop_send_beacons) (struct net_device *dev); - - /* power save mode related */ - void (*sta_wake_up) (struct net_device *dev); - void (*ps_request_tx_ack) (struct net_device *dev); - void (*enter_sleep_state) (struct net_device *dev, u32 th, u32 tl); - short (*ps_is_queue_empty) (struct net_device *dev); - - /* QoS related */ - //void (*wmm_param_update) (struct net_device *dev, u8 *ac_param); - //void (*wmm_param_update) (struct ieee80211_device *ieee); - - /* This must be the last item so that it points to the data - * allocated beyond this structure by alloc_ieee80211 */ - u8 priv[0]; -}; - -#define IEEE_A (1<<0) -#define IEEE_B (1<<1) -#define IEEE_G (1<<2) -#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) - -/* Generate a 802.11 header */ - -/* Uses the channel change callback directly - * instead of [start/stop] scan callbacks - */ -#define IEEE_SOFTMAC_SCAN (1<<2) - -/* Perform authentication and association handshake */ -#define IEEE_SOFTMAC_ASSOCIATE (1<<3) - -/* Generate probe requests */ -#define IEEE_SOFTMAC_PROBERQ (1<<4) - -/* Generate response to probe requests */ -#define IEEE_SOFTMAC_PROBERS (1<<5) - -/* The ieee802.11 stack will manages the netif queue - * wake/stop for the driver, taking care of 802.11 - * fragmentation. See softmac.c for details. */ -#define IEEE_SOFTMAC_TX_QUEUE (1<<7) - -/* Uses only the softmac_data_hard_start_xmit - * even for TX management frames. - */ -#define IEEE_SOFTMAC_SINGLE_QUEUE (1<<8) - -/* Generate beacons. The stack will enqueue beacons - * to the card - */ -#define IEEE_SOFTMAC_BEACONS (1<<6) - - - -static inline void *ieee80211_priv(struct net_device *dev) -{ - return ((struct ieee80211_device *)netdev_priv(dev))->priv; -} - -static inline int ieee80211_is_empty_essid(const char *essid, int essid_len) -{ - /* Single white space is for Linksys APs */ - if (essid_len == 1 && essid[0] == ' ') - return 1; - - /* Otherwise, if the entire essid is 0, we assume it is hidden */ - while (essid_len) { - essid_len--; - if (essid[essid_len] != '\0') - return 0; - } - - return 1; -} - -static inline int ieee80211_is_valid_mode(struct ieee80211_device *ieee, - int mode) -{ - /* - * It is possible for both access points and our device to support - * combinations of modes, so as long as there is one valid combination - * of ap/device supported modes, then return success - * - */ - if ((mode & IEEE_A) && - (ieee->modulation & IEEE80211_OFDM_MODULATION) && - (ieee->freq_band & IEEE80211_52GHZ_BAND)) - return 1; - - if ((mode & IEEE_G) && - (ieee->modulation & IEEE80211_OFDM_MODULATION) && - (ieee->freq_band & IEEE80211_24GHZ_BAND)) - return 1; - - if ((mode & IEEE_B) && - (ieee->modulation & IEEE80211_CCK_MODULATION) && - (ieee->freq_band & IEEE80211_24GHZ_BAND)) - return 1; - - return 0; -} - -static inline int ieee80211_get_hdrlen(u16 fc) -{ - int hdrlen = 24; - - switch (WLAN_FC_GET_TYPE(fc)) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = 30; /* Addr4 */ - if(IEEE80211_QOS_HAS_SEQ(fc)) - hdrlen += 2; /* QOS ctrl*/ - break; - case IEEE80211_FTYPE_CTL: - switch (WLAN_FC_GET_STYPE(fc)) { - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = 10; - break; - default: - hdrlen = 16; - break; - } - break; - } - - return hdrlen; -} - - - -/* ieee80211.c */ -extern void free_ieee80211(struct net_device *dev); -extern struct net_device *alloc_ieee80211(int sizeof_priv); - -extern int ieee80211_set_encryption(struct ieee80211_device *ieee); - -/* ieee80211_tx.c */ - -extern int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, - struct sk_buff *frag, int hdr_len); - -extern int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev); -extern void ieee80211_txb_free(struct ieee80211_txb *); - - -/* ieee80211_rx.c */ -extern int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats); -extern void ieee80211_rx_mgt(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *header, - struct ieee80211_rx_stats *stats); - -/* ieee80211_wx.c */ -extern int ieee80211_wx_get_scan(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_set_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_get_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -int ieee80211_wx_set_auth(struct ieee80211_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra); -int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len); -/* ieee80211_softmac.c */ -extern short ieee80211_is_54g(const struct ieee80211_network *net); -extern short ieee80211_is_shortslot(const struct ieee80211_network *net); -extern int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, - struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, - u16 type, u16 stype); -extern void ieee80211_softmac_new_net(struct ieee80211_device *ieee, - struct ieee80211_network *net); - -extern void ieee80211_softmac_xmit(struct ieee80211_txb *txb, - struct ieee80211_device *ieee); -extern void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee); -extern void ieee80211_start_bss(struct ieee80211_device *ieee); -extern void ieee80211_start_master_bss(struct ieee80211_device *ieee); -extern void ieee80211_start_ibss(struct ieee80211_device *ieee); -extern void ieee80211_softmac_init(struct ieee80211_device *ieee); -extern void ieee80211_softmac_free(struct ieee80211_device *ieee); -extern void ieee80211_associate_abort(struct ieee80211_device *ieee); -extern void ieee80211_disassociate(struct ieee80211_device *ieee); -extern void ieee80211_stop_scan(struct ieee80211_device *ieee); -extern void ieee80211_start_scan_syncro(struct ieee80211_device *ieee); -extern void ieee80211_check_all_nets(struct ieee80211_device *ieee); -extern void ieee80211_start_protocol(struct ieee80211_device *ieee); -extern void ieee80211_stop_protocol(struct ieee80211_device *ieee); -extern void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee); -extern void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee); -extern void ieee80211_reset_queue(struct ieee80211_device *ieee); -extern void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee); -extern void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee); -extern struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee); -extern void ieee80211_start_send_beacons(struct ieee80211_device *ieee); -extern void ieee80211_stop_send_beacons(struct ieee80211_device *ieee); -extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, - struct iw_point *p); -extern void notify_wx_assoc_event(struct ieee80211_device *ieee); -extern void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success); -extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, - u8 asRsn); -extern void ieee80211_rtl_start_scan(struct ieee80211_device *ieee); - -//Add for RF power on power off by lizhaoming 080512 -extern void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, - u8 asRsn); - -/* ieee80211_crypt_ccmp&tkip&wep.c */ -extern void ieee80211_tkip_null(void); -extern void ieee80211_wep_null(void); -extern void ieee80211_ccmp_null(void); -/* ieee80211_softmac_wx.c */ - -extern int ieee80211_wx_get_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *ext); - -extern int ieee80211_wx_set_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *awrq, - char *extra); - -extern int ieee80211_wx_get_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_set_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_scan(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_set_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern int ieee80211_wx_get_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b); - -extern void ieee80211_wx_sync_scan_wq(struct work_struct *work); - -extern int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_name(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_set_power(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern int ieee80211_wx_get_power(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -extern void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee); - -extern void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, - short pwr); - -extern const long ieee80211_wlan_frequencies[]; - -extern inline void ieee80211_increment_scans(struct ieee80211_device *ieee) -{ - ieee->scans++; -} - -extern inline int ieee80211_get_scans(struct ieee80211_device *ieee) -{ - return ieee->scans; -} - -static inline const char *escape_essid(const char *essid, u8 essid_len) { - static char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - const char *s = essid; - char *d = escaped; - - if (ieee80211_is_empty_essid(essid, essid_len)) { - memcpy(escaped, "", sizeof("")); - return escaped; - } - - essid_len = min(essid_len, (u8)IW_ESSID_MAX_SIZE); - while (essid_len--) { - if (*s == '\0') { - *d++ = '\\'; - *d++ = '0'; - s++; - } else { - *d++ = *s++; - } - } - *d = '\0'; - return escaped; -} -#endif /* IEEE80211_H */ diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c deleted file mode 100644 index 101f0c0cdb0a56..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Host AP crypto routines - * - * Copyright (c) 2002-2003, Jouni Malinen - * Portions Copyright (C) 2004, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -//#include -#include -#include -#include -#include - -#include "ieee80211.h" - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("HostAP crypto"); -MODULE_LICENSE("GPL"); - -struct ieee80211_crypto_alg { - struct list_head list; - struct ieee80211_crypto_ops *ops; -}; - - -struct ieee80211_crypto { - struct list_head algs; - spinlock_t lock; -}; - -static struct ieee80211_crypto *hcrypt; - -void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee, int force) -{ - struct list_head *ptr, *n; - struct ieee80211_crypt_data *entry; - - for (ptr = ieee->crypt_deinit_list.next, n = ptr->next; - ptr != &ieee->crypt_deinit_list; ptr = n, n = ptr->next) { - entry = list_entry(ptr, struct ieee80211_crypt_data, list); - - if (atomic_read(&entry->refcnt) != 0 && !force) - continue; - - list_del(ptr); - - if (entry->ops) - entry->ops->deinit(entry->priv); - kfree(entry); - } -} - -void ieee80211_crypt_deinit_handler(unsigned long data) -{ - struct ieee80211_device *ieee = (struct ieee80211_device *)data; - unsigned long flags; - - spin_lock_irqsave(&ieee->lock, flags); - ieee80211_crypt_deinit_entries(ieee, 0); - if (!list_empty(&ieee->crypt_deinit_list)) { - pr_debug("entries remaining in delayed crypt deletion list\n"); - ieee->crypt_deinit_timer.expires = jiffies + HZ; - add_timer(&ieee->crypt_deinit_timer); - } - spin_unlock_irqrestore(&ieee->lock, flags); - -} - -void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, - struct ieee80211_crypt_data **crypt) -{ - struct ieee80211_crypt_data *tmp; - unsigned long flags; - - if (*crypt == NULL) - return; - - tmp = *crypt; - *crypt = NULL; - - /* must not run ops->deinit() while there may be pending encrypt or - * decrypt operations. Use a list of delayed deinits to avoid needing - * locking. */ - - spin_lock_irqsave(&ieee->lock, flags); - list_add(&tmp->list, &ieee->crypt_deinit_list); - if (!timer_pending(&ieee->crypt_deinit_timer)) { - ieee->crypt_deinit_timer.expires = jiffies + HZ; - add_timer(&ieee->crypt_deinit_timer); - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops) -{ - unsigned long flags; - struct ieee80211_crypto_alg *alg; - - if (hcrypt == NULL) - return -1; - - alg = kzalloc(sizeof(*alg), GFP_KERNEL); - if (alg == NULL) - return -ENOMEM; - - alg->ops = ops; - - spin_lock_irqsave(&hcrypt->lock, flags); - list_add(&alg->list, &hcrypt->algs); - spin_unlock_irqrestore(&hcrypt->lock, flags); - - pr_debug("registered algorithm '%s'\n", ops->name); - - return 0; -} - -int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops) -{ - unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *del_alg = NULL; - - if (hcrypt == NULL) - return -1; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *) ptr; - if (alg->ops == ops) { - list_del(&alg->list); - del_alg = alg; - break; - } - } - spin_unlock_irqrestore(&hcrypt->lock, flags); - - if (del_alg) { - pr_debug("unregistered algorithm '%s'\n", ops->name); - kfree(del_alg); - } - - return del_alg ? 0 : -1; -} - - -struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name) -{ - unsigned long flags; - struct list_head *ptr; - struct ieee80211_crypto_alg *found_alg = NULL; - - if (hcrypt == NULL) - return NULL; - - spin_lock_irqsave(&hcrypt->lock, flags); - for (ptr = hcrypt->algs.next; ptr != &hcrypt->algs; ptr = ptr->next) { - struct ieee80211_crypto_alg *alg = - (struct ieee80211_crypto_alg *) ptr; - if (strcmp(alg->ops->name, name) == 0) { - found_alg = alg; - break; - } - } - spin_unlock_irqrestore(&hcrypt->lock, flags); - - if (found_alg) - return found_alg->ops; - else - return NULL; -} - - -static void *ieee80211_crypt_null_init(int keyidx) { return (void *) 1; } -static void ieee80211_crypt_null_deinit(void *priv) {} - -static struct ieee80211_crypto_ops ieee80211_crypt_null = { - .name = "NULL", - .init = ieee80211_crypt_null_init, - .deinit = ieee80211_crypt_null_deinit, - .encrypt_mpdu = NULL, - .decrypt_mpdu = NULL, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = NULL, - .get_key = NULL, - .extra_prefix_len = 0, - .extra_postfix_len = 0, - .owner = THIS_MODULE, -}; - - -int ieee80211_crypto_init(void) -{ - int ret = -ENOMEM; - - hcrypt = kzalloc(sizeof(*hcrypt), GFP_KERNEL); - if (!hcrypt) - goto out; - - INIT_LIST_HEAD(&hcrypt->algs); - spin_lock_init(&hcrypt->lock); - - ret = ieee80211_register_crypto_ops(&ieee80211_crypt_null); - if (ret < 0) { - kfree(hcrypt); - hcrypt = NULL; - } -out: - return ret; -} - - -void ieee80211_crypto_deinit(void) -{ - struct list_head *ptr, *n; - struct ieee80211_crypto_alg *alg = NULL; - - if (hcrypt == NULL) - return; - - list_for_each_safe(ptr, n, &hcrypt->algs) { - alg = list_entry(ptr, struct ieee80211_crypto_alg, list); - if (alg) { - list_del(ptr); - pr_debug("unregistered algorithm '%s' (deinit)\n", - alg->ops->name); - kfree(alg); - } - } - kfree(hcrypt); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h deleted file mode 100644 index 0b4ea431982d98..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Original code based on Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * - * - * Copyright (c) 2004, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -/* - * This file defines the interface to the ieee80211 crypto module. - */ -#ifndef IEEE80211_CRYPT_H -#define IEEE80211_CRYPT_H - -#include - -struct ieee80211_crypto_ops { - const char *name; - - /* init new crypto context (e.g., allocate private data space, - * select IV, etc.); returns NULL on failure or pointer to allocated - * private data on success */ - void * (*init)(int keyidx); - - /* deinitialize crypto context and free allocated private data */ - void (*deinit)(void *priv); - - /* encrypt/decrypt return < 0 on error or >= 0 on success. The return - * value from decrypt_mpdu is passed as the keyidx value for - * decrypt_msdu. skb must have enough head and tail room for the - * encryption; if not, error will be returned; these functions are - * called for all MPDUs (i.e., fragments). - */ - int (*encrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); - int (*decrypt_mpdu)(struct sk_buff *skb, int hdr_len, void *priv); - - /* These functions are called for full MSDUs, i.e. full frames. - * These can be NULL if full MSDU operations are not needed. */ - int (*encrypt_msdu)(struct sk_buff *skb, int hdr_len, void *priv); - int (*decrypt_msdu)(struct sk_buff *skb, int keyidx, int hdr_len, - void *priv); - - int (*set_key)(void *key, int len, u8 *seq, void *priv); - int (*get_key)(void *key, int len, u8 *seq, void *priv); - - /* procfs handler for printing out key information and possible - * statistics */ - char * (*print_stats)(char *p, void *priv); - - /* maximum number of bytes added by encryption; encrypt buf is - * allocated with extra_prefix_len bytes, copy of in_buf, and - * extra_postfix_len; encrypt need not use all this space, but - * the result must start at the beginning of the buffer and correct - * length must be returned */ - int extra_prefix_len, extra_postfix_len; - - struct module *owner; -}; - -struct ieee80211_crypt_data { - struct list_head list; /* delayed deletion list */ - struct ieee80211_crypto_ops *ops; - void *priv; - atomic_t refcnt; -}; - -int ieee80211_register_crypto_ops(struct ieee80211_crypto_ops *ops); -int ieee80211_unregister_crypto_ops(struct ieee80211_crypto_ops *ops); -struct ieee80211_crypto_ops *ieee80211_get_crypto_ops(const char *name); -void ieee80211_crypt_deinit_entries(struct ieee80211_device *, int); -void ieee80211_crypt_deinit_handler(unsigned long); -void ieee80211_crypt_delayed_deinit(struct ieee80211_device *ieee, - struct ieee80211_crypt_data **crypt); - -#endif diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c deleted file mode 100644 index 4fe2538186308d..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_ccmp.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Host AP crypt: host-based CCMP encryption implementation for Host AP driver - * - * Copyright (c) 2003-2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ieee80211.h" - -#include -#include - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP crypt: CCMP"); -MODULE_LICENSE("GPL"); - - -#define AES_BLOCK_LEN 16 -#define CCMP_HDR_LEN 8 -#define CCMP_MIC_LEN 8 -#define CCMP_TK_LEN 16 -#define CCMP_PN_LEN 6 - -struct ieee80211_ccmp_data { - u8 key[CCMP_TK_LEN]; - int key_set; - - u8 tx_pn[CCMP_PN_LEN]; - u8 rx_pn[CCMP_PN_LEN]; - - u32 dot11RSNAStatsCCMPFormatErrors; - u32 dot11RSNAStatsCCMPReplays; - u32 dot11RSNAStatsCCMPDecryptErrors; - - int key_idx; - - struct crypto_tfm *tfm; - - /* scratch buffers for virt_to_page() (crypto API) */ - u8 tx_b0[AES_BLOCK_LEN], tx_b[AES_BLOCK_LEN], - tx_e[AES_BLOCK_LEN], tx_s0[AES_BLOCK_LEN]; - u8 rx_b0[AES_BLOCK_LEN], rx_b[AES_BLOCK_LEN], rx_a[AES_BLOCK_LEN]; -}; - -static void ieee80211_ccmp_aes_encrypt(struct crypto_tfm *tfm, - const u8 pt[16], u8 ct[16]) -{ - crypto_cipher_encrypt_one((void *)tfm, ct, pt); -} - -static void *ieee80211_ccmp_init(int key_idx) -{ - struct ieee80211_ccmp_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (priv == NULL) - goto fail; - priv->key_idx = key_idx; - - priv->tfm = (void *)crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tfm)) { - pr_debug("could not allocate crypto API aes\n"); - priv->tfm = NULL; - goto fail; - } - - return priv; - -fail: - if (priv) { - if (priv->tfm) - crypto_free_cipher((void *)priv->tfm); - kfree(priv); - } - - return NULL; -} - - -static void ieee80211_ccmp_deinit(void *priv) -{ - struct ieee80211_ccmp_data *_priv = priv; - - if (_priv && _priv->tfm) - crypto_free_cipher((void *)_priv->tfm); - kfree(priv); -} - - -static inline void xor_block(u8 *b, u8 *a, size_t len) -{ - int i; - for (i = 0; i < len; i++) - b[i] ^= a[i]; -} - -static void ccmp_init_blocks(struct crypto_tfm *tfm, - struct ieee80211_hdr_4addr *hdr, - u8 *pn, size_t dlen, u8 *b0, u8 *auth, - u8 *s0) -{ - u8 *pos, qc = 0; - size_t aad_len; - u16 fc; - int a4_included, qc_included; - u8 aad[2 * AES_BLOCK_LEN]; - - fc = le16_to_cpu(hdr->frame_ctl); - a4_included = ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)); - /* - qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && - (WLAN_FC_GET_STYPE(fc) & 0x08)); - */ - qc_included = ((WLAN_FC_GET_TYPE(fc) == IEEE80211_FTYPE_DATA) && - (WLAN_FC_GET_STYPE(fc) & 0x80)); - aad_len = 22; - if (a4_included) - aad_len += 6; - if (qc_included) { - pos = (u8 *) &hdr->addr4; - if (a4_included) - pos += 6; - qc = *pos & 0x0f; - aad_len += 2; - } - /* CCM Initial Block: - * Flag (Include authentication header, M=3 (8-octet MIC), - * L=1 (2-octet Dlen)) - * Nonce: 0x00 | A2 | PN - * Dlen */ - b0[0] = 0x59; - b0[1] = qc; - memcpy(b0 + 2, hdr->addr2, ETH_ALEN); - memcpy(b0 + 8, pn, CCMP_PN_LEN); - b0[14] = (dlen >> 8) & 0xff; - b0[15] = dlen & 0xff; - - /* AAD: - * FC with bits 4..6 and 11..13 masked to zero; 14 is always one - * A1 | A2 | A3 - * SC with bits 4..15 (seq#) masked to zero - * A4 (if present) - * QC (if present) - */ - pos = (u8 *) hdr; - aad[0] = 0; /* aad_len >> 8 */ - aad[1] = aad_len & 0xff; - aad[2] = pos[0] & 0x8f; - aad[3] = pos[1] & 0xc7; - memcpy(aad + 4, hdr->addr1, 3 * ETH_ALEN); - pos = (u8 *) &hdr->seq_ctl; - aad[22] = pos[0] & 0x0f; - aad[23] = 0; /* all bits masked */ - memset(aad + 24, 0, 8); - if (a4_included) - memcpy(aad + 24, hdr->addr4, ETH_ALEN); - if (qc_included) { - aad[a4_included ? 30 : 24] = qc; - /* rest of QC masked */ - } - - /* Start with the first block and AAD */ - ieee80211_ccmp_aes_encrypt(tfm, b0, auth); - xor_block(auth, aad, AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - xor_block(auth, &aad[AES_BLOCK_LEN], AES_BLOCK_LEN); - ieee80211_ccmp_aes_encrypt(tfm, auth, auth); - b0[0] &= 0x07; - b0[14] = b0[15] = 0; - ieee80211_ccmp_aes_encrypt(tfm, b0, s0); -} - -static int ieee80211_ccmp_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_ccmp_data *key = priv; - int data_len, i; - u8 *pos; - struct ieee80211_hdr_4addr *hdr; - int blocks, last, len; - u8 *mic; - u8 *b0 = key->tx_b0; - u8 *b = key->tx_b; - u8 *e = key->tx_e; - u8 *s0 = key->tx_s0; - - if (skb_headroom(skb) < CCMP_HDR_LEN || - skb_tailroom(skb) < CCMP_MIC_LEN || - skb->len < hdr_len) - return -1; - - data_len = skb->len - hdr_len; - pos = skb_push(skb, CCMP_HDR_LEN); - memmove(pos, pos + CCMP_HDR_LEN, hdr_len); - pos += hdr_len; - - i = CCMP_PN_LEN - 1; - while (i >= 0) { - key->tx_pn[i]++; - if (key->tx_pn[i] != 0) - break; - i--; - } - - *pos++ = key->tx_pn[5]; - *pos++ = key->tx_pn[4]; - *pos++ = 0; - *pos++ = (key->key_idx << 6) | (1 << 5) /* Ext IV included */; - *pos++ = key->tx_pn[3]; - *pos++ = key->tx_pn[2]; - *pos++ = key->tx_pn[1]; - *pos++ = key->tx_pn[0]; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - mic = skb_put(skb, CCMP_MIC_LEN); - - ccmp_init_blocks(key->tfm, hdr, key->tx_pn, data_len, b0, b, s0); - - blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Authentication */ - xor_block(b, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, b, b); - /* Encryption, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, e); - xor_block(pos, e, len); - pos += len; - } - - for (i = 0; i < CCMP_MIC_LEN; i++) - mic[i] = b[i] ^ s0[i]; - - return 0; -} - - -static int ieee80211_ccmp_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_ccmp_data *key = priv; - u8 keyidx, *pos; - struct ieee80211_hdr_4addr *hdr; - u8 pn[6]; - size_t data_len = skb->len - hdr_len - CCMP_HDR_LEN - CCMP_MIC_LEN; - u8 *mic = skb->data + skb->len - CCMP_MIC_LEN; - u8 *b0 = key->rx_b0; - u8 *b = key->rx_b; - u8 *a = key->rx_a; - int i, blocks, last, len; - - if (skb->len < hdr_len + CCMP_HDR_LEN + CCMP_MIC_LEN) { - key->dot11RSNAStatsCCMPFormatErrors++; - return -1; - } - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - pos = skb->data + hdr_len; - keyidx = pos[3]; - if (!(keyidx & (1 << 5))) { - if (net_ratelimit()) { - pr_debug("received packet without ExtIV flag from %pM\n", - hdr->addr2); - } - key->dot11RSNAStatsCCMPFormatErrors++; - return -2; - } - keyidx >>= 6; - if (key->key_idx != keyidx) { - pr_debug("RX tkey->key_idx=%d frame keyidx=%d priv=%p\n", - key->key_idx, keyidx, priv); - return -6; - } - if (!key->key_set) { - if (net_ratelimit()) { - pr_debug("received packet from %pM with keyid=%d that does not have a configured key\n", - hdr->addr2, keyidx); - } - return -3; - } - - pn[0] = pos[7]; - pn[1] = pos[6]; - pn[2] = pos[5]; - pn[3] = pos[4]; - pn[4] = pos[1]; - pn[5] = pos[0]; - pos += 8; - - if (memcmp(pn, key->rx_pn, CCMP_PN_LEN) <= 0) { - if (net_ratelimit()) { - pr_debug("replay detected: STA=%pM previous PN %pm received PN %pm\n", - hdr->addr2, key->rx_pn, pn); - } - key->dot11RSNAStatsCCMPReplays++; - return -4; - } - - ccmp_init_blocks(key->tfm, hdr, pn, data_len, b0, a, b); - xor_block(mic, b, CCMP_MIC_LEN); - - blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN; - last = data_len % AES_BLOCK_LEN; - - for (i = 1; i <= blocks; i++) { - len = (i == blocks && last) ? last : AES_BLOCK_LEN; - /* Decrypt, with counter */ - b0[14] = (i >> 8) & 0xff; - b0[15] = i & 0xff; - ieee80211_ccmp_aes_encrypt(key->tfm, b0, b); - xor_block(pos, b, len); - /* Authentication */ - xor_block(a, pos, len); - ieee80211_ccmp_aes_encrypt(key->tfm, a, a); - pos += len; - } - - if (memcmp(mic, a, CCMP_MIC_LEN) != 0) { - if (net_ratelimit()) - pr_debug("decrypt failed: STA=%pM\n", hdr->addr2); - - key->dot11RSNAStatsCCMPDecryptErrors++; - return -5; - } - - memcpy(key->rx_pn, pn, CCMP_PN_LEN); - - /* Remove hdr and MIC */ - memmove(skb->data + CCMP_HDR_LEN, skb->data, hdr_len); - skb_pull(skb, CCMP_HDR_LEN); - skb_trim(skb, skb->len - CCMP_MIC_LEN); - - return keyidx; -} - - -static int ieee80211_ccmp_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_ccmp_data *data = priv; - int keyidx; - struct crypto_tfm *tfm = data->tfm; - - keyidx = data->key_idx; - memset(data, 0, sizeof(*data)); - data->key_idx = keyidx; - data->tfm = tfm; - if (len == CCMP_TK_LEN) { - memcpy(data->key, key, CCMP_TK_LEN); - data->key_set = 1; - if (seq) { - data->rx_pn[0] = seq[5]; - data->rx_pn[1] = seq[4]; - data->rx_pn[2] = seq[3]; - data->rx_pn[3] = seq[2]; - data->rx_pn[4] = seq[1]; - data->rx_pn[5] = seq[0]; - } - crypto_cipher_setkey((void *)data->tfm, data->key, CCMP_TK_LEN); - } else if (len == 0) - data->key_set = 0; - else - return -1; - - return 0; -} - - -static int ieee80211_ccmp_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_ccmp_data *data = priv; - - if (len < CCMP_TK_LEN) - return -1; - - if (!data->key_set) - return 0; - memcpy(key, data->key, CCMP_TK_LEN); - - if (seq) { - seq[0] = data->tx_pn[5]; - seq[1] = data->tx_pn[4]; - seq[2] = data->tx_pn[3]; - seq[3] = data->tx_pn[2]; - seq[4] = data->tx_pn[1]; - seq[5] = data->tx_pn[0]; - } - - return CCMP_TK_LEN; -} - - -static char *ieee80211_ccmp_print_stats(char *p, void *priv) -{ - struct ieee80211_ccmp_data *ccmp = priv; - p += sprintf(p, - "key[%d] alg=CCMP key_set=%d tx_pn=%pm rx_pn=%pm format_errors=%d replays=%d decrypt_errors=%d\n", - ccmp->key_idx, ccmp->key_set, - ccmp->tx_pn, ccmp->rx_pn, - ccmp->dot11RSNAStatsCCMPFormatErrors, - ccmp->dot11RSNAStatsCCMPReplays, - ccmp->dot11RSNAStatsCCMPDecryptErrors); - - return p; -} - -void ieee80211_ccmp_null(void) -{ - return; -} -static struct ieee80211_crypto_ops ieee80211_crypt_ccmp = { - .name = "CCMP", - .init = ieee80211_ccmp_init, - .deinit = ieee80211_ccmp_deinit, - .encrypt_mpdu = ieee80211_ccmp_encrypt, - .decrypt_mpdu = ieee80211_ccmp_decrypt, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = ieee80211_ccmp_set_key, - .get_key = ieee80211_ccmp_get_key, - .print_stats = ieee80211_ccmp_print_stats, - .extra_prefix_len = CCMP_HDR_LEN, - .extra_postfix_len = CCMP_MIC_LEN, - .owner = THIS_MODULE, -}; - - -int ieee80211_crypto_ccmp_init(void) -{ - return ieee80211_register_crypto_ops(&ieee80211_crypt_ccmp); -} - - -void ieee80211_crypto_ccmp_exit(void) -{ - ieee80211_unregister_crypto_ops(&ieee80211_crypt_ccmp); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c deleted file mode 100644 index 6c1acc5dfba7ee..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_tkip.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * Host AP crypt: host-based TKIP encryption implementation for Host AP driver - * - * Copyright (c) 2003-2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ieee80211.h" - -#include -#include -#include - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP crypt: TKIP"); -MODULE_LICENSE("GPL"); - - -struct ieee80211_tkip_data { -#define TKIP_KEY_LEN 32 - u8 key[TKIP_KEY_LEN]; - int key_set; - - u32 tx_iv32; - u16 tx_iv16; - u16 tx_ttak[5]; - int tx_phase1_done; - - u32 rx_iv32; - u16 rx_iv16; - u16 rx_ttak[5]; - int rx_phase1_done; - u32 rx_iv32_new; - u16 rx_iv16_new; - - u32 dot11RSNAStatsTKIPReplays; - u32 dot11RSNAStatsTKIPICVErrors; - u32 dot11RSNAStatsTKIPLocalMICFailures; - - int key_idx; - - struct crypto_blkcipher *rx_tfm_arc4; - struct crypto_hash *rx_tfm_michael; - struct crypto_blkcipher *tx_tfm_arc4; - struct crypto_hash *tx_tfm_michael; - struct crypto_tfm *tfm_arc4; - struct crypto_tfm *tfm_michael; - - /* scratch buffers for virt_to_page() (crypto API) */ - u8 rx_hdr[16], tx_hdr[16]; -}; - -static void *ieee80211_tkip_init(int key_idx) -{ - struct ieee80211_tkip_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (priv == NULL) - goto fail; - priv->key_idx = key_idx; - - priv->tx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tx_tfm_arc4)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API arc4\n"); - priv->tx_tfm_arc4 = NULL; - goto fail; - } - - priv->tx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tx_tfm_michael)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API michael_mic\n"); - priv->tx_tfm_michael = NULL; - goto fail; - } - - priv->rx_tfm_arc4 = crypto_alloc_blkcipher("ecb(arc4)", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->rx_tfm_arc4)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API arc4\n"); - priv->rx_tfm_arc4 = NULL; - goto fail; - } - - priv->rx_tfm_michael = crypto_alloc_hash("michael_mic", 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->rx_tfm_michael)) { - printk(KERN_DEBUG "ieee80211_crypt_tkip: could not allocate " - "crypto API michael_mic\n"); - priv->rx_tfm_michael = NULL; - goto fail; - } - - return priv; - -fail: - if (priv) { - if (priv->tx_tfm_michael) - crypto_free_hash(priv->tx_tfm_michael); - if (priv->tx_tfm_arc4) - crypto_free_blkcipher(priv->tx_tfm_arc4); - if (priv->rx_tfm_michael) - crypto_free_hash(priv->rx_tfm_michael); - if (priv->rx_tfm_arc4) - crypto_free_blkcipher(priv->rx_tfm_arc4); - kfree(priv); - } - - return NULL; -} - - -static void ieee80211_tkip_deinit(void *priv) -{ - struct ieee80211_tkip_data *_priv = priv; - - if (_priv) { - if (_priv->tx_tfm_michael) - crypto_free_hash(_priv->tx_tfm_michael); - if (_priv->tx_tfm_arc4) - crypto_free_blkcipher(_priv->tx_tfm_arc4); - if (_priv->rx_tfm_michael) - crypto_free_hash(_priv->rx_tfm_michael); - if (_priv->rx_tfm_arc4) - crypto_free_blkcipher(_priv->rx_tfm_arc4); - } - kfree(priv); -} - - -static inline u16 RotR1(u16 val) -{ - return (val >> 1) | (val << 15); -} - - -static inline u8 Lo8(u16 val) -{ - return val & 0xff; -} - - -static inline u8 Hi8(u16 val) -{ - return val >> 8; -} - - -static inline u16 Lo16(u32 val) -{ - return val & 0xffff; -} - - -static inline u16 Hi16(u32 val) -{ - return val >> 16; -} - - -static inline u16 Mk16(u8 hi, u8 lo) -{ - return lo | (((u16) hi) << 8); -} - - -static inline u16 Mk16_le(u16 *v) -{ - return le16_to_cpu(*v); -} - - -static const u16 Sbox[256] = { - 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, - 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, - 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, - 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, - 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, - 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, - 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, - 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, - 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, - 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, - 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, - 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, - 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, - 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, - 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, - 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, - 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, - 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, - 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, - 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, - 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, - 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, - 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, - 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, - 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, - 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, - 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, - 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, - 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, - 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, - 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, - 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, -}; - - -static inline u16 _S_(u16 v) -{ - u16 t = Sbox[Hi8(v)]; - return Sbox[Lo8(v)] ^ ((t << 8) | (t >> 8)); -} - -#define PHASE1_LOOP_COUNT 8 - -static void tkip_mixing_phase1(u16 *TTAK, const u8 *TK, const u8 *TA, u32 IV32) -{ - int i, j; - - /* Initialize the 80-bit TTAK from TSC (IV32) and TA[0..5] */ - TTAK[0] = Lo16(IV32); - TTAK[1] = Hi16(IV32); - TTAK[2] = Mk16(TA[1], TA[0]); - TTAK[3] = Mk16(TA[3], TA[2]); - TTAK[4] = Mk16(TA[5], TA[4]); - - for (i = 0; i < PHASE1_LOOP_COUNT; i++) { - j = 2 * (i & 1); - TTAK[0] += _S_(TTAK[4] ^ Mk16(TK[1 + j], TK[0 + j])); - TTAK[1] += _S_(TTAK[0] ^ Mk16(TK[5 + j], TK[4 + j])); - TTAK[2] += _S_(TTAK[1] ^ Mk16(TK[9 + j], TK[8 + j])); - TTAK[3] += _S_(TTAK[2] ^ Mk16(TK[13 + j], TK[12 + j])); - TTAK[4] += _S_(TTAK[3] ^ Mk16(TK[1 + j], TK[0 + j])) + i; - } -} - - -static void tkip_mixing_phase2(u8 *WEPSeed, const u8 *TK, const u16 *TTAK, - u16 IV16) -{ - /* Make temporary area overlap WEP seed so that the final copy can be - * avoided on little endian hosts. */ - u16 *PPK = (u16 *) &WEPSeed[4]; - - /* Step 1 - make copy of TTAK and bring in TSC */ - PPK[0] = TTAK[0]; - PPK[1] = TTAK[1]; - PPK[2] = TTAK[2]; - PPK[3] = TTAK[3]; - PPK[4] = TTAK[4]; - PPK[5] = TTAK[4] + IV16; - - /* Step 2 - 96-bit bijective mixing using S-box */ - PPK[0] += _S_(PPK[5] ^ Mk16_le((u16 *) &TK[0])); - PPK[1] += _S_(PPK[0] ^ Mk16_le((u16 *) &TK[2])); - PPK[2] += _S_(PPK[1] ^ Mk16_le((u16 *) &TK[4])); - PPK[3] += _S_(PPK[2] ^ Mk16_le((u16 *) &TK[6])); - PPK[4] += _S_(PPK[3] ^ Mk16_le((u16 *) &TK[8])); - PPK[5] += _S_(PPK[4] ^ Mk16_le((u16 *) &TK[10])); - - PPK[0] += RotR1(PPK[5] ^ Mk16_le((u16 *) &TK[12])); - PPK[1] += RotR1(PPK[0] ^ Mk16_le((u16 *) &TK[14])); - PPK[2] += RotR1(PPK[1]); - PPK[3] += RotR1(PPK[2]); - PPK[4] += RotR1(PPK[3]); - PPK[5] += RotR1(PPK[4]); - - /* Step 3 - bring in last of TK bits, assign 24-bit WEP IV value - * WEPSeed[0..2] is transmitted as WEP IV */ - WEPSeed[0] = Hi8(IV16); - WEPSeed[1] = (Hi8(IV16) | 0x20) & 0x7F; - WEPSeed[2] = Lo8(IV16); - WEPSeed[3] = Lo8((PPK[5] ^ Mk16_le((u16 *) &TK[0])) >> 1); - -#ifdef __BIG_ENDIAN - { - int i; - for (i = 0; i < 6; i++) - PPK[i] = (PPK[i] << 8) | (PPK[i] >> 8); - } -#endif -} - -static int ieee80211_tkip_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = {.tfm = tkey->tx_tfm_arc4}; - int len; - u8 *pos; - struct ieee80211_hdr_4addr *hdr; - u8 rc4key[16], *icv; - u32 crc; - struct scatterlist sg; - int ret; - - ret = 0; - if (skb_headroom(skb) < 8 || skb_tailroom(skb) < 4 || - skb->len < hdr_len) - return -1; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - if (!tkey->tx_phase1_done) { - tkip_mixing_phase1(tkey->tx_ttak, tkey->key, hdr->addr2, - tkey->tx_iv32); - tkey->tx_phase1_done = 1; - } - tkip_mixing_phase2(rc4key, tkey->key, tkey->tx_ttak, tkey->tx_iv16); - - len = skb->len - hdr_len; - pos = skb_push(skb, 8); - memmove(pos, pos + 8, hdr_len); - pos += hdr_len; - - *pos++ = rc4key[0]; - *pos++ = rc4key[1]; - *pos++ = rc4key[2]; - *pos++ = (tkey->key_idx << 6) | (1 << 5) /* Ext IV included */; - *pos++ = tkey->tx_iv32 & 0xff; - *pos++ = (tkey->tx_iv32 >> 8) & 0xff; - *pos++ = (tkey->tx_iv32 >> 16) & 0xff; - *pos++ = (tkey->tx_iv32 >> 24) & 0xff; - - icv = skb_put(skb, 4); - crc = ~crc32_le(~0, pos, len); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - crypto_blkcipher_setkey(tkey->tx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, len + 4); - ret = crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); - - tkey->tx_iv16++; - if (tkey->tx_iv16 == 0) { - tkey->tx_phase1_done = 0; - tkey->tx_iv32++; - } - return ret; -} - -static int ieee80211_tkip_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - struct blkcipher_desc desc = { .tfm = tkey->rx_tfm_arc4 }; - u8 keyidx, *pos; - u32 iv32; - u16 iv16; - struct ieee80211_hdr_4addr *hdr; - u8 icv[4]; - u32 crc; - struct scatterlist sg; - u8 rc4key[16]; - int plen; - - if (skb->len < hdr_len + 8 + 4) - return -1; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - pos = skb->data + hdr_len; - keyidx = pos[3]; - if (!(keyidx & (1 << 5))) { - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: received packet without ExtIV" - " flag from %pM\n", hdr->addr2); - } - return -2; - } - keyidx >>= 6; - if (tkey->key_idx != keyidx) { - printk(KERN_DEBUG "TKIP: RX tkey->key_idx=%d frame " - "keyidx=%d priv=%p\n", tkey->key_idx, keyidx, priv); - return -6; - } - if (!tkey->key_set) { - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: received packet from %pM" - " with keyid=%d that does not have a configured" - " key\n", hdr->addr2, keyidx); - } - return -3; - } - iv16 = (pos[0] << 8) | pos[2]; - iv32 = pos[4] | (pos[5] << 8) | (pos[6] << 16) | (pos[7] << 24); - pos += 8; - - if (iv32 < tkey->rx_iv32 || - (iv32 == tkey->rx_iv32 && iv16 <= tkey->rx_iv16)) { - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: replay detected: STA=%pM" - " previous TSC %08x%04x received TSC " - "%08x%04x\n", hdr->addr2, - tkey->rx_iv32, tkey->rx_iv16, iv32, iv16); - } - tkey->dot11RSNAStatsTKIPReplays++; - return -4; - } - - if (iv32 != tkey->rx_iv32 || !tkey->rx_phase1_done) { - tkip_mixing_phase1(tkey->rx_ttak, tkey->key, hdr->addr2, iv32); - tkey->rx_phase1_done = 1; - } - tkip_mixing_phase2(rc4key, tkey->key, tkey->rx_ttak, iv16); - - plen = skb->len - hdr_len - 12; - crypto_blkcipher_setkey(tkey->rx_tfm_arc4, rc4key, 16); - sg_init_one(&sg, pos, plen + 4); - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) { - if (net_ratelimit()) { - printk(KERN_DEBUG ": TKIP: failed to decrypt " - "received packet from %pM\n", - hdr->addr2); - } - return -7; - } - - crc = ~crc32_le(~0, pos, plen); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - if (memcmp(icv, pos + plen, 4) != 0) { - if (iv32 != tkey->rx_iv32) { - /* Previously cached Phase1 result was already lost, so - * it needs to be recalculated for the next packet. */ - tkey->rx_phase1_done = 0; - } - if (net_ratelimit()) { - printk(KERN_DEBUG "TKIP: ICV error detected: STA=" - "%pM\n", hdr->addr2); - } - tkey->dot11RSNAStatsTKIPICVErrors++; - return -5; - } - - /* Update real counters only after Michael MIC verification has - * completed */ - tkey->rx_iv32_new = iv32; - tkey->rx_iv16_new = iv16; - - /* Remove IV and ICV */ - memmove(skb->data + 8, skb->data, hdr_len); - skb_pull(skb, 8); - skb_trim(skb, skb->len - 4); - - return keyidx; -} - -static int michael_mic(struct crypto_hash *tfm_michael, u8 *key, u8 *hdr, - u8 *data, size_t data_len, u8 *mic) -{ - struct hash_desc desc; - struct scatterlist sg[2]; - - if (tfm_michael == NULL) { - printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n"); - return -1; - } - - sg_init_table(sg, 2); - sg_set_buf(&sg[0], hdr, 16); - sg_set_buf(&sg[1], data, data_len); - - if (crypto_hash_setkey(tfm_michael, key, 8)) - return -1; - - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + 16, mic); -} - -static void michael_mic_hdr(struct sk_buff *skb, u8 *hdr) -{ - struct ieee80211_hdr_4addr *hdr11; - - hdr11 = (struct ieee80211_hdr_4addr *)skb->data; - switch (le16_to_cpu(hdr11->frame_ctl) & - (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_TODS: - memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ - break; - case IEEE80211_FCTL_FROMDS: - memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr3, ETH_ALEN); /* SA */ - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - memcpy(hdr, hdr11->addr3, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr4, ETH_ALEN); /* SA */ - break; - case 0: - memcpy(hdr, hdr11->addr1, ETH_ALEN); /* DA */ - memcpy(hdr + ETH_ALEN, hdr11->addr2, ETH_ALEN); /* SA */ - break; - } - - hdr[12] = 0; /* priority */ - - hdr[13] = hdr[14] = hdr[15] = 0; /* reserved */ -} - - -static int ieee80211_michael_mic_add(struct sk_buff *skb, int hdr_len, - void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - u8 *pos; - struct ieee80211_hdr_4addr *hdr; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - if (skb_tailroom(skb) < 8 || skb->len < hdr_len) { - printk(KERN_DEBUG "Invalid packet for Michael MIC add " - "(tailroom=%d hdr_len=%d skb->len=%d)\n", - skb_tailroom(skb), hdr_len, skb->len); - return -1; - } - - michael_mic_hdr(skb, tkey->tx_hdr); - - if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) - tkey->tx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; - - pos = skb_put(skb, 8); - - if (michael_mic(tkey->tx_tfm_michael, &tkey->key[16], tkey->tx_hdr, - skb->data + hdr_len, skb->len - 8 - hdr_len, pos)) - return -1; - - return 0; -} - -static void ieee80211_michael_mic_failure(struct net_device *dev, - struct ieee80211_hdr_4addr *hdr, - int keyidx) -{ - union iwreq_data wrqu; - struct iw_michaelmicfailure ev; - - /* TODO: needed parameters: count, keyid, key type, TSC */ - memset(&ev, 0, sizeof(ev)); - ev.flags = keyidx & IW_MICFAILURE_KEY_ID; - if (hdr->addr1[0] & 0x01) - ev.flags |= IW_MICFAILURE_GROUP; - else - ev.flags |= IW_MICFAILURE_PAIRWISE; - ev.src_addr.sa_family = ARPHRD_ETHER; - memcpy(ev.src_addr.sa_data, hdr->addr2, ETH_ALEN); - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = sizeof(ev); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, (char *) &ev); -} - -static int ieee80211_michael_mic_verify(struct sk_buff *skb, int keyidx, - int hdr_len, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - u8 mic[8]; - struct ieee80211_hdr_4addr *hdr; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - if (!tkey->key_set) - return -1; - - michael_mic_hdr(skb, tkey->rx_hdr); - if (IEEE80211_QOS_HAS_SEQ(le16_to_cpu(hdr->frame_ctl))) - tkey->rx_hdr[12] = *(skb->data + hdr_len - 2) & 0x07; - - if (michael_mic(tkey->rx_tfm_michael, &tkey->key[24], tkey->rx_hdr, - skb->data + hdr_len, skb->len - 8 - hdr_len, mic)) - return -1; - - if (memcmp(mic, skb->data + skb->len - 8, 8) != 0) { - struct ieee80211_hdr_4addr *hdr; - hdr = (struct ieee80211_hdr_4addr *)skb->data; - printk(KERN_DEBUG "%s: Michael MIC verification failed for " - "MSDU from %pM keyidx=%d\n", - skb->dev ? skb->dev->name : "N/A", hdr->addr2, - keyidx); - if (skb->dev) - ieee80211_michael_mic_failure(skb->dev, hdr, keyidx); - tkey->dot11RSNAStatsTKIPLocalMICFailures++; - return -1; - } - - /* Update TSC counters for RX now that the packet verification has - * completed. */ - tkey->rx_iv32 = tkey->rx_iv32_new; - tkey->rx_iv16 = tkey->rx_iv16_new; - - skb_trim(skb, skb->len - 8); - - return 0; -} - - -static int ieee80211_tkip_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - int keyidx; - struct crypto_hash *tfm = tkey->tx_tfm_michael; - struct crypto_blkcipher *tfm2 = tkey->tx_tfm_arc4; - struct crypto_hash *tfm3 = tkey->rx_tfm_michael; - struct crypto_blkcipher *tfm4 = tkey->rx_tfm_arc4; - - keyidx = tkey->key_idx; - memset(tkey, 0, sizeof(*tkey)); - tkey->key_idx = keyidx; - - tkey->tx_tfm_michael = tfm; - tkey->tx_tfm_arc4 = tfm2; - tkey->rx_tfm_michael = tfm3; - tkey->rx_tfm_arc4 = tfm4; - - if (len == TKIP_KEY_LEN) { - memcpy(tkey->key, key, TKIP_KEY_LEN); - tkey->key_set = 1; - tkey->tx_iv16 = 1; /* TSC is initialized to 1 */ - if (seq) { - tkey->rx_iv32 = (seq[5] << 24) | (seq[4] << 16) | - (seq[3] << 8) | seq[2]; - tkey->rx_iv16 = (seq[1] << 8) | seq[0]; - } - } else if (len == 0) - tkey->key_set = 0; - else - return -1; - - return 0; -} - - -static int ieee80211_tkip_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct ieee80211_tkip_data *tkey = priv; - - if (len < TKIP_KEY_LEN) - return -1; - - if (!tkey->key_set) - return 0; - memcpy(key, tkey->key, TKIP_KEY_LEN); - - if (seq) { - /* Return the sequence number of the last transmitted frame. */ - u16 iv16 = tkey->tx_iv16; - u32 iv32 = tkey->tx_iv32; - if (iv16 == 0) - iv32--; - iv16--; - seq[0] = tkey->tx_iv16; - seq[1] = tkey->tx_iv16 >> 8; - seq[2] = tkey->tx_iv32; - seq[3] = tkey->tx_iv32 >> 8; - seq[4] = tkey->tx_iv32 >> 16; - seq[5] = tkey->tx_iv32 >> 24; - } - - return TKIP_KEY_LEN; -} - - -static char *ieee80211_tkip_print_stats(char *p, void *priv) -{ - struct ieee80211_tkip_data *tkip = priv; - p += sprintf(p, "key[%d] alg=TKIP key_set=%d " - "tx_pn=%02x%02x%02x%02x%02x%02x " - "rx_pn=%02x%02x%02x%02x%02x%02x " - "replays=%d icv_errors=%d local_mic_failures=%d\n", - tkip->key_idx, tkip->key_set, - (tkip->tx_iv32 >> 24) & 0xff, - (tkip->tx_iv32 >> 16) & 0xff, - (tkip->tx_iv32 >> 8) & 0xff, - tkip->tx_iv32 & 0xff, - (tkip->tx_iv16 >> 8) & 0xff, - tkip->tx_iv16 & 0xff, - (tkip->rx_iv32 >> 24) & 0xff, - (tkip->rx_iv32 >> 16) & 0xff, - (tkip->rx_iv32 >> 8) & 0xff, - tkip->rx_iv32 & 0xff, - (tkip->rx_iv16 >> 8) & 0xff, - tkip->rx_iv16 & 0xff, - tkip->dot11RSNAStatsTKIPReplays, - tkip->dot11RSNAStatsTKIPICVErrors, - tkip->dot11RSNAStatsTKIPLocalMICFailures); - return p; -} - - -static struct ieee80211_crypto_ops ieee80211_crypt_tkip = { - .name = "TKIP", - .init = ieee80211_tkip_init, - .deinit = ieee80211_tkip_deinit, - .encrypt_mpdu = ieee80211_tkip_encrypt, - .decrypt_mpdu = ieee80211_tkip_decrypt, - .encrypt_msdu = ieee80211_michael_mic_add, - .decrypt_msdu = ieee80211_michael_mic_verify, - .set_key = ieee80211_tkip_set_key, - .get_key = ieee80211_tkip_get_key, - .print_stats = ieee80211_tkip_print_stats, - .extra_prefix_len = 4 + 4, /* IV + ExtIV */ - .extra_postfix_len = 8 + 4, /* MIC + ICV */ - .owner = THIS_MODULE, -}; - - -int ieee80211_crypto_tkip_init(void) -{ - return ieee80211_register_crypto_ops(&ieee80211_crypt_tkip); -} - - -void ieee80211_crypto_tkip_exit(void) -{ - ieee80211_unregister_crypto_ops(&ieee80211_crypt_tkip); -} - - -void ieee80211_tkip_null(void) -{ -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c deleted file mode 100644 index f2536722494147..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt_wep.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Host AP crypt: host-based WEP encryption implementation for Host AP driver - * - * Copyright (c) 2002-2004, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include - -#include "ieee80211.h" - -#include -#include -#include - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP crypt: WEP"); -MODULE_LICENSE("GPL"); - -struct prism2_wep_data { - u32 iv; -#define WEP_KEY_LEN 13 - u8 key[WEP_KEY_LEN + 1]; - u8 key_len; - u8 key_idx; - struct crypto_blkcipher *tx_tfm; - struct crypto_blkcipher *rx_tfm; -}; - -static void *prism2_wep_init(int keyidx) -{ - struct prism2_wep_data *priv; - - priv = kzalloc(sizeof(*priv), GFP_ATOMIC); - if (priv == NULL) - goto fail; - priv->key_idx = keyidx; - priv->tx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->tx_tfm)) { - pr_debug("could not allocate crypto API arc4\n"); - priv->tx_tfm = NULL; - goto fail; - } - priv->rx_tfm = crypto_alloc_blkcipher("ecb(arc4)", 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(priv->rx_tfm)) { - pr_debug("could not allocate crypto API arc4\n"); - priv->rx_tfm = NULL; - goto fail; - } - - /* start WEP IV from a random value */ - get_random_bytes(&priv->iv, 4); - - return priv; - -fail: - if (priv) { - if (priv->tx_tfm) - crypto_free_blkcipher(priv->tx_tfm); - if (priv->rx_tfm) - crypto_free_blkcipher(priv->rx_tfm); - kfree(priv); - } - - return NULL; -} - -static void prism2_wep_deinit(void *priv) -{ - struct prism2_wep_data *_priv = priv; - - if (_priv) { - if (_priv->tx_tfm) - crypto_free_blkcipher(_priv->tx_tfm); - if (_priv->rx_tfm) - crypto_free_blkcipher(_priv->rx_tfm); - } - - kfree(priv); -} - -/* Perform WEP encryption on given skb that has at least 4 bytes of headroom - * for IV and 4 bytes of tailroom for ICV. Both IV and ICV will be transmitted, - * so the payload length increases with 8 bytes. - * - * WEP frame payload: IV + TX key idx, RC4(data), ICV = RC4(CRC32(data)) - */ -static int prism2_wep_encrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct prism2_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->tx_tfm }; - u32 klen, len; - u8 key[WEP_KEY_LEN + 3]; - u8 *pos; - u32 crc; - u8 *icv; - struct scatterlist sg; - - if (skb_headroom(skb) < 4 || skb_tailroom(skb) < 4 || - skb->len < hdr_len) - return -1; - - len = skb->len - hdr_len; - pos = skb_push(skb, 4); - memmove(pos, pos + 4, hdr_len); - pos += hdr_len; - - klen = 3 + wep->key_len; - - wep->iv++; - - /* Fluhrer, Mantin, and Shamir have reported weaknesses in the key - * scheduling algorithm of RC4. At least IVs (KeyByte + 3, 0xff, N) - * can be used to speedup attacks, so avoid using them. */ - if ((wep->iv & 0xff00) == 0xff00) { - u8 B = (wep->iv >> 16) & 0xff; - if (B >= 3 && B < klen) - wep->iv += 0x0100; - } - - /* Prepend 24-bit IV to RC4 key and TX frame */ - *pos++ = key[0] = (wep->iv >> 16) & 0xff; - *pos++ = key[1] = (wep->iv >> 8) & 0xff; - *pos++ = key[2] = wep->iv & 0xff; - *pos++ = wep->key_idx << 6; - - /* Copy rest of the WEP key (the secret part) */ - memcpy(key + 3, wep->key, wep->key_len); - - /* Append little-endian CRC32 and encrypt it to produce ICV */ - crc = ~crc32_le(~0, pos, len); - icv = skb_put(skb, 4); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - - crypto_blkcipher_setkey(wep->tx_tfm, key, klen); - sg_init_one(&sg, pos, len + 4); - - return crypto_blkcipher_encrypt(&desc, &sg, &sg, len + 4); -} - -/* Perform WEP decryption on given buffer. Buffer includes whole WEP part of - * the frame: IV (4 bytes), encrypted payload (including SNAP header), - * ICV (4 bytes). len includes both IV and ICV. - * - * Returns 0 if frame was decrypted successfully and ICV was correct and -1 on - * failure. If frame is OK, IV and ICV will be removed. - */ -static int prism2_wep_decrypt(struct sk_buff *skb, int hdr_len, void *priv) -{ - struct prism2_wep_data *wep = priv; - struct blkcipher_desc desc = { .tfm = wep->rx_tfm }; - u32 klen, plen; - u8 key[WEP_KEY_LEN + 3]; - u8 keyidx, *pos; - u32 crc; - u8 icv[4]; - struct scatterlist sg; - - if (skb->len < hdr_len + 8) - return -1; - - pos = skb->data + hdr_len; - key[0] = *pos++; - key[1] = *pos++; - key[2] = *pos++; - keyidx = *pos++ >> 6; - if (keyidx != wep->key_idx) - return -1; - - klen = 3 + wep->key_len; - - /* Copy rest of the WEP key (the secret part) */ - memcpy(key + 3, wep->key, wep->key_len); - - /* Apply RC4 to data and compute CRC32 over decrypted data */ - plen = skb->len - hdr_len - 8; - - crypto_blkcipher_setkey(wep->rx_tfm, key, klen); - sg_init_one(&sg, pos, plen + 4); - - if (crypto_blkcipher_decrypt(&desc, &sg, &sg, plen + 4)) - return -7; - - crc = ~crc32_le(~0, pos, plen); - icv[0] = crc; - icv[1] = crc >> 8; - icv[2] = crc >> 16; - icv[3] = crc >> 24; - - if (memcmp(icv, pos + plen, 4) != 0) { - /* ICV mismatch - drop frame */ - return -2; - } - - /* Remove IV and ICV */ - memmove(skb->data + 4, skb->data, hdr_len); - skb_pull(skb, 4); - skb_trim(skb, skb->len - 4); - return 0; -} - -static int prism2_wep_set_key(void *key, int len, u8 *seq, void *priv) -{ - struct prism2_wep_data *wep = priv; - - if (len < 0 || len > WEP_KEY_LEN) - return -1; - - memcpy(wep->key, key, len); - wep->key_len = len; - - return 0; -} - -static int prism2_wep_get_key(void *key, int len, u8 *seq, void *priv) -{ - struct prism2_wep_data *wep = priv; - - if (len < wep->key_len) - return -1; - - memcpy(key, wep->key, wep->key_len); - - return wep->key_len; -} - -static char *prism2_wep_print_stats(char *p, void *priv) -{ - struct prism2_wep_data *wep = priv; - p += sprintf(p, "key[%d] alg=WEP len=%d\n", - wep->key_idx, wep->key_len); - return p; -} - -static struct ieee80211_crypto_ops ieee80211_crypt_wep = { - .name = "WEP", - .init = prism2_wep_init, - .deinit = prism2_wep_deinit, - .encrypt_mpdu = prism2_wep_encrypt, - .decrypt_mpdu = prism2_wep_decrypt, - .encrypt_msdu = NULL, - .decrypt_msdu = NULL, - .set_key = prism2_wep_set_key, - .get_key = prism2_wep_get_key, - .print_stats = prism2_wep_print_stats, - .extra_prefix_len = 4, /* IV */ - .extra_postfix_len = 4, /* ICV */ - .owner = THIS_MODULE, -}; - -int ieee80211_crypto_wep_init(void) -{ - return ieee80211_register_crypto_ops(&ieee80211_crypt_wep); -} - -void ieee80211_crypto_wep_exit(void) -{ - ieee80211_unregister_crypto_ops(&ieee80211_crypt_wep); -} - -void ieee80211_wep_null(void) -{ - return; -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c deleted file mode 100644 index 07a1fbb6678e94..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c +++ /dev/null @@ -1,203 +0,0 @@ -/******************************************************************************* - - Copyright(c) 2004 Intel Corporation. All rights reserved. - - Portions of this file are based on the WEP enablement code provided by the - Host AP project hostap-drivers v0.1.3 - Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - - Copyright (c) 2002-2003, Jouni Malinen - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - James P. Ketrenos - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ieee80211.h" - -MODULE_DESCRIPTION("802.11 data/management/control stack"); -MODULE_AUTHOR("Copyright (C) 2004 Intel Corporation "); -MODULE_LICENSE("GPL"); - -#define DRV_NAME "ieee80211" - -static inline int ieee80211_networks_allocate(struct ieee80211_device *ieee) -{ - if (ieee->networks) - return 0; - - ieee->networks = kcalloc( - MAX_NETWORK_COUNT, sizeof(struct ieee80211_network), - GFP_KERNEL); - if (!ieee->networks) - return -ENOMEM; - - return 0; -} - -static inline void ieee80211_networks_free(struct ieee80211_device *ieee) -{ - if (!ieee->networks) - return; - kfree(ieee->networks); - ieee->networks = NULL; -} - -static inline void ieee80211_networks_initialize(struct ieee80211_device *ieee) -{ - int i; - - INIT_LIST_HEAD(&ieee->network_free_list); - INIT_LIST_HEAD(&ieee->network_list); - for (i = 0; i < MAX_NETWORK_COUNT; i++) - list_add_tail(&ieee->networks[i].list, &ieee->network_free_list); -} - - -struct net_device *alloc_ieee80211(int sizeof_priv) -{ - struct ieee80211_device *ieee; - struct net_device *dev; - int i, err; - - IEEE80211_DEBUG_INFO("Initializing...\n"); - - dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv); - if (!dev) { - IEEE80211_ERROR("Unable to network device.\n"); - goto failed; - } - ieee = netdev_priv(dev); - - ieee->dev = dev; - - err = ieee80211_networks_allocate(ieee); - if (err) { - IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", - err); - goto failed; - } - ieee80211_networks_initialize(ieee); - - /* Default fragmentation threshold is maximum payload size */ - ieee->fts = DEFAULT_FTS; - ieee->scan_age = DEFAULT_MAX_SCAN_AGE; - ieee->open_wep = 1; - - /* Default to enabling full open WEP with host based encrypt/decrypt */ - ieee->host_encrypt = 1; - ieee->host_decrypt = 1; - ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ - - INIT_LIST_HEAD(&ieee->crypt_deinit_list); - init_timer(&ieee->crypt_deinit_timer); - ieee->crypt_deinit_timer.data = (unsigned long)ieee; - ieee->crypt_deinit_timer.function = ieee80211_crypt_deinit_handler; - - spin_lock_init(&ieee->lock); - spin_lock_init(&ieee->wpax_suitlist_lock); - - ieee->wpax_type_set = 0; - ieee->wpa_enabled = 0; - ieee->tkip_countermeasures = 0; - ieee->drop_unencrypted = 0; - ieee->privacy_invoked = 0; - ieee->ieee802_1x = 1; - ieee->raw_tx = 0; - - ieee80211_softmac_init(ieee); - - for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) - INIT_LIST_HEAD(&ieee->ibss_mac_hash[i]); - - for (i = 0; i < 17; i++) { - ieee->last_rxseq_num[i] = -1; - ieee->last_rxfrag_num[i] = -1; - ieee->last_packet_time[i] = 0; - } -//These function were added to load crypte module autoly - ieee80211_tkip_null(); - ieee80211_wep_null(); - ieee80211_ccmp_null(); - return dev; - - failed: - if (dev) - free_netdev(dev); - return NULL; -} - - -void free_ieee80211(struct net_device *dev) -{ - struct ieee80211_device *ieee = netdev_priv(dev); - - int i; - struct list_head *p, *q; - - - ieee80211_softmac_free(ieee); - del_timer_sync(&ieee->crypt_deinit_timer); - ieee80211_crypt_deinit_entries(ieee, 1); - - for (i = 0; i < WEP_KEYS; i++) { - struct ieee80211_crypt_data *crypt = ieee->crypt[i]; - if (crypt) { - if (crypt->ops) - crypt->ops->deinit(crypt->priv); - kfree(crypt); - ieee->crypt[i] = NULL; - } - } - - ieee80211_networks_free(ieee); - - for (i = 0; i < IEEE_IBSS_MAC_HASH_SIZE; i++) { - list_for_each_safe(p, q, &ieee->ibss_mac_hash[i]) { - kfree(list_entry(p, struct ieee_ibss_seq, list)); - list_del(p); - } - } - - - free_netdev(dev); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c deleted file mode 100644 index b522b57a26916a..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c +++ /dev/null @@ -1,1486 +0,0 @@ -/* - * Original code based Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3 - hostap.o module, common routines - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen - * Copyright (c) 2004, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - ****************************************************************************** - - Few modifications for Realtek's Wi-Fi drivers by - Andrea Merello - - A special thanks goes to Realtek for their support ! - -******************************************************************************/ - - -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ieee80211.h" -#include "dot11d.h" -static inline void ieee80211_monitor_rx(struct ieee80211_device *ieee, - struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats) -{ - struct ieee80211_hdr_4addr *hdr = - (struct ieee80211_hdr_4addr *)skb->data; - u16 fc = le16_to_cpu(hdr->frame_ctl); - - skb->dev = ieee->dev; - skb_reset_mac_header(skb); - skb_pull(skb, ieee80211_get_hdrlen(fc)); - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = __constant_htons(ETH_P_80211_RAW); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - - -/* Called only as a tasklet (software IRQ) */ -static struct ieee80211_frag_entry * -ieee80211_frag_cache_find(struct ieee80211_device *ieee, unsigned int seq, - unsigned int frag, u8 tid, u8 *src, u8 *dst) -{ - struct ieee80211_frag_entry *entry; - int i; - - for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) { - entry = &ieee->frag_cache[tid][i]; - if (entry->skb != NULL && - time_after(jiffies, entry->first_frag_time + 2 * HZ)) { - IEEE80211_DEBUG_FRAG( - "expiring fragment cache entry " - "seq=%u last_frag=%u\n", - entry->seq, entry->last_frag); - dev_kfree_skb_any(entry->skb); - entry->skb = NULL; - } - - if (entry->skb != NULL && entry->seq == seq && - (entry->last_frag + 1 == frag || frag == -1) && - memcmp(entry->src_addr, src, ETH_ALEN) == 0 && - memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) - return entry; - } - - return NULL; -} - -/* Called only as a tasklet (software IRQ) */ -static struct sk_buff * -ieee80211_frag_cache_get(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *hdr) -{ - struct sk_buff *skb = NULL; - u16 fc = le16_to_cpu(hdr->frame_ctl); - u16 sc = le16_to_cpu(hdr->seq_ctl); - unsigned int frag = WLAN_GET_SEQ_FRAG(sc); - unsigned int seq = WLAN_GET_SEQ_SEQ(sc); - struct ieee80211_frag_entry *entry; - struct ieee80211_hdr_3addrqos *hdr_3addrqos; - struct ieee80211_hdr_4addrqos *hdr_4addrqos; - u8 tid; - - if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else { - tid = 0; - } - - if (frag == 0) { - /* Reserve enough space to fit maximum frame length */ - skb = dev_alloc_skb(ieee->dev->mtu + - sizeof(struct ieee80211_hdr_4addr) + - 8 /* LLC */ + - 2 /* alignment */ + - 8 /* WEP */ + - ETH_ALEN /* WDS */ + - (IEEE80211_QOS_HAS_SEQ(fc) ? 2 : 0) /* QOS Control */); - if (skb == NULL) - return NULL; - - entry = &ieee->frag_cache[tid][ieee->frag_next_idx[tid]]; - ieee->frag_next_idx[tid]++; - if (ieee->frag_next_idx[tid] >= IEEE80211_FRAG_CACHE_LEN) - ieee->frag_next_idx[tid] = 0; - - if (entry->skb != NULL) - dev_kfree_skb_any(entry->skb); - - entry->first_frag_time = jiffies; - entry->seq = seq; - entry->last_frag = frag; - entry->skb = skb; - memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); - memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); - } else { - /* received a fragment of a frame for which the head fragment - * should have already been received */ - entry = ieee80211_frag_cache_find(ieee, seq, frag, tid, hdr->addr2, - hdr->addr1); - if (entry != NULL) { - entry->last_frag = frag; - skb = entry->skb; - } - } - - return skb; -} - - -/* Called only as a tasklet (software IRQ) */ -static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *hdr) -{ - u16 fc = le16_to_cpu(hdr->frame_ctl); - u16 sc = le16_to_cpu(hdr->seq_ctl); - unsigned int seq = WLAN_GET_SEQ_SEQ(sc); - struct ieee80211_frag_entry *entry; - struct ieee80211_hdr_3addrqos *hdr_3addrqos; - struct ieee80211_hdr_4addrqos *hdr_4addrqos; - u8 tid; - - if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)hdr; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else if (IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)hdr; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else { - tid = 0; - } - - entry = ieee80211_frag_cache_find(ieee, seq, -1, tid, hdr->addr2, - hdr->addr1); - - if (entry == NULL) { - IEEE80211_DEBUG_FRAG( - "could not invalidate fragment cache " - "entry (seq=%u)\n", seq); - return -1; - } - - entry->skb = NULL; - return 0; -} - - - -/* ieee80211_rx_frame_mgtmt - * - * Responsible for handling management control frames - * - * Called by ieee80211_rx */ -static inline int -ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, u16 type, - u16 stype) -{ - struct ieee80211_hdr_4addr *hdr; - - // cheat the the hdr type - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - /* On the struct stats definition there is written that - * this is not mandatory.... but seems that the probe - * response parser uses it - */ - rx_stats->len = skb->len; - ieee80211_rx_mgt(ieee, (struct ieee80211_hdr_4addr *)skb->data, - rx_stats); - - if ((ieee->state == IEEE80211_LINKED) && (memcmp(hdr->addr3, ieee->current_network.bssid, ETH_ALEN))) { - dev_kfree_skb_any(skb); - return 0; - } - - ieee80211_rx_frame_softmac(ieee, skb, rx_stats, type, stype); - - dev_kfree_skb_any(skb); - - return 0; - -} - - - -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -/* No encapsulation header if EtherType < 0x600 (=length) */ - -/* Called by ieee80211_rx_frame_decrypt */ -static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, - struct sk_buff *skb, size_t hdrlen) -{ - struct net_device *dev = ieee->dev; - u16 fc, ethertype; - struct ieee80211_hdr_4addr *hdr; - u8 *pos; - - if (skb->len < 24) - return 0; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - fc = le16_to_cpu(hdr->frame_ctl); - - /* check that the frame is unicast frame to us */ - if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_TODS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 && - memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { - /* ToDS frame with own addr BSSID and DA */ - } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_FROMDS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { - /* FromDS frame with own addr as DA */ - } else - return 0; - - if (skb->len < 24 + 8) - return 0; - - /* check for port access entity Ethernet type */ -// pos = skb->data + 24; - pos = skb->data + hdrlen; - ethertype = (pos[6] << 8) | pos[7]; - if (ethertype == ETH_P_PAE) - return 1; - - return 0; -} - -/* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static inline int -ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_crypt_data *crypt) -{ - struct ieee80211_hdr_4addr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) - return 0; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); - -#ifdef CONFIG_IEEE80211_CRYPT_TKIP - if (ieee->tkip_countermeasures && - strcmp(crypt->ops->name, "TKIP") == 0) { - if (net_ratelimit()) { - netdev_dbg(ieee->dev, - "TKIP countermeasures: dropped received packet from %pM\n", - ieee->dev->name, hdr->addr2); - } - return -1; - } -#endif - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - IEEE80211_DEBUG_DROP( - "decryption failed (SA=%pM" - ") res=%d\n", hdr->addr2, res); - if (res == -2) - IEEE80211_DEBUG_DROP("Decryption failed ICV " - "mismatch (key %d)\n", - skb->data[hdrlen + 3] >> 6); - ieee->ieee_stats.rx_discards_undecryptable++; - return -1; - } - - return res; -} - - -/* Called only as a tasklet (software IRQ), by ieee80211_rx */ -static inline int -ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee, - struct sk_buff *skb, int keyidx, - struct ieee80211_crypt_data *crypt) -{ - struct ieee80211_hdr_4addr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) - return 0; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - netdev_dbg(ieee->dev, - "MSDU decryption/MIC verification failed (SA=%pM keyidx=%d)\n", - hdr->addr2, keyidx); - return -1; - } - - return 0; -} - - -/* this function is stolen from ipw2200 driver*/ -#define IEEE_PACKET_RETRY_TIME (5*HZ) -static int is_duplicate_packet(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *header) -{ - u16 fc = le16_to_cpu(header->frame_ctl); - u16 sc = le16_to_cpu(header->seq_ctl); - u16 seq = WLAN_GET_SEQ_SEQ(sc); - u16 frag = WLAN_GET_SEQ_FRAG(sc); - u16 *last_seq, *last_frag; - unsigned long *last_time; - struct ieee80211_hdr_3addrqos *hdr_3addrqos; - struct ieee80211_hdr_4addrqos *hdr_4addrqos; - u8 tid; - - //TO2DS and QoS - if (((fc & IEEE80211_FCTL_DSTODS) == IEEE80211_FCTL_DSTODS) && IEEE80211_QOS_HAS_SEQ(fc)) { - hdr_4addrqos = (struct ieee80211_hdr_4addrqos *)header; - tid = le16_to_cpu(hdr_4addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else if (IEEE80211_QOS_HAS_SEQ(fc)) { //QoS - hdr_3addrqos = (struct ieee80211_hdr_3addrqos *)header; - tid = le16_to_cpu(hdr_3addrqos->qos_ctl) & IEEE80211_QOS_TID; - tid = UP2AC(tid); - tid++; - } else { // no QoS - tid = 0; - } - switch (ieee->iw_mode) { - case IW_MODE_ADHOC: - { - struct list_head *p; - struct ieee_ibss_seq *entry = NULL; - u8 *mac = header->addr2; - int index = mac[5] % IEEE_IBSS_MAC_HASH_SIZE; - - list_for_each(p, &ieee->ibss_mac_hash[index]) { - entry = list_entry(p, struct ieee_ibss_seq, list); - if (!memcmp(entry->mac, mac, ETH_ALEN)) - break; - } - // if (memcmp(entry->mac, mac, ETH_ALEN)){ - if (p == &ieee->ibss_mac_hash[index]) { - entry = kmalloc(sizeof(struct ieee_ibss_seq), GFP_ATOMIC); - if (!entry) - return 0; - - memcpy(entry->mac, mac, ETH_ALEN); - entry->seq_num[tid] = seq; - entry->frag_num[tid] = frag; - entry->packet_time[tid] = jiffies; - list_add(&entry->list, &ieee->ibss_mac_hash[index]); - return 0; - } - last_seq = &entry->seq_num[tid]; - last_frag = &entry->frag_num[tid]; - last_time = &entry->packet_time[tid]; - break; - } - - case IW_MODE_INFRA: - last_seq = &ieee->last_rxseq_num[tid]; - last_frag = &ieee->last_rxfrag_num[tid]; - last_time = &ieee->last_packet_time[tid]; - - break; - default: - return 0; - } - -// if(tid != 0) { -// printk(KERN_WARNING ":)))))))))))%x %x %x, fc(%x)\n", tid, *last_seq, seq, header->frame_ctl); -// } - if ((*last_seq == seq) && - time_after(*last_time + IEEE_PACKET_RETRY_TIME, jiffies)) { - if (*last_frag == frag) { - //printk(KERN_WARNING "[1] go drop!\n"); - goto drop; - - } - if (*last_frag + 1 != frag) - /* out-of-order fragment */ - //printk(KERN_WARNING "[2] go drop!\n"); - goto drop; - } else - *last_seq = seq; - - *last_frag = frag; - *last_time = jiffies; - return 0; - -drop: -// BUG_ON(!(fc & IEEE80211_FCTL_RETRY)); -// printk("DUP\n"); - - return 1; -} - - -/* All received frames are sent to this function. @skb contains the frame in - * IEEE 802.11 format, i.e., in the format it was sent over air. - * This function is called only as a tasklet (software IRQ). */ -int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats) -{ - struct net_device *dev = ieee->dev; - //struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct ieee80211_hdr_4addr *hdr; - - size_t hdrlen; - u16 fc, type, stype, sc; - struct net_device_stats *stats; - unsigned int frag; - u8 *payload; - u16 ethertype; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - struct ieee80211_crypt_data *crypt = NULL; - int keyidx = 0; - - // cheat the the hdr type - hdr = (struct ieee80211_hdr_4addr *)skb->data; - stats = &ieee->stats; - - if (skb->len < 10) { - netdev_info(ieee->dev, "SKB length < 10\n"); - goto rx_dropped; - } - - fc = le16_to_cpu(hdr->frame_ctl); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - sc = le16_to_cpu(hdr->seq_ctl); - - frag = WLAN_GET_SEQ_FRAG(sc); - -//YJ,add,080828,for keep alive - if ((fc & IEEE80211_FCTL_TODS) != IEEE80211_FCTL_TODS) { - if (!memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) - ieee->NumRxUnicast++; - } else { - if (!memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) - ieee->NumRxUnicast++; - } -//YJ,add,080828,for keep alive,end - - hdrlen = ieee80211_get_hdrlen(fc); - - - if (ieee->iw_mode == IW_MODE_MONITOR) { - ieee80211_monitor_rx(ieee, skb, rx_stats); - stats->rx_packets++; - stats->rx_bytes += skb->len; - return 1; - } - - if (ieee->host_decrypt) { - int idx = 0; - if (skb->len >= hdrlen + 3) - idx = skb->data[hdrlen + 3] >> 6; - crypt = ieee->crypt[idx]; - - /* allow NULL decrypt to indicate an station specific override - * for default encryption */ - if (crypt && (crypt->ops == NULL || - crypt->ops->decrypt_mpdu == NULL)) - crypt = NULL; - - if (!crypt && (fc & IEEE80211_FCTL_WEP)) { - /* This seems to be triggered by some (multicast?) - * frames from other than current BSS, so just drop the - * frames silently instead of filling system log with - * these reports. */ - IEEE80211_DEBUG_DROP("Decryption failed (not set)" - " (SA=%pM)\n", - hdr->addr2); - ieee->ieee_stats.rx_discards_undecryptable++; - goto rx_dropped; - } - } - - if (skb->len < IEEE80211_DATA_HDR3_LEN) - goto rx_dropped; - - // if QoS enabled, should check the sequence for each of the AC - if (is_duplicate_packet(ieee, hdr)) - goto rx_dropped; - - - if (type == IEEE80211_FTYPE_MGMT) { - if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) - goto rx_dropped; - else - goto rx_exit; - } - - /* Data frame - extract src/dst addresses */ - switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_FROMDS: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr3, ETH_ALEN); - memcpy(bssid, hdr->addr2, ETH_ALEN); - break; - case IEEE80211_FCTL_TODS: - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - memcpy(bssid, hdr->addr1, ETH_ALEN); - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - if (skb->len < IEEE80211_DATA_HDR4_LEN) - goto rx_dropped; - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr4, ETH_ALEN); - memcpy(bssid, ieee->current_network.bssid, ETH_ALEN); - break; - case 0: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - memcpy(bssid, hdr->addr3, ETH_ALEN); - break; - } - - - dev->last_rx = jiffies; - - - /* Nullfunc frames may have PS-bit set, so they must be passed to - * hostap_handle_sta_rx() before being dropped here. */ - if (stype != IEEE80211_STYPE_DATA && - stype != IEEE80211_STYPE_DATA_CFACK && - stype != IEEE80211_STYPE_DATA_CFPOLL && - stype != IEEE80211_STYPE_DATA_CFACKPOLL && - stype != IEEE80211_STYPE_QOS_DATA//add by David,2006.8.4 - ) { - if (stype != IEEE80211_STYPE_NULLFUNC) - IEEE80211_DEBUG_DROP( - "RX: dropped data frame " - "with no data (type=0x%02x, " - "subtype=0x%02x, len=%d)\n", - type, stype, skb->len); - goto rx_dropped; - } - if (memcmp(bssid, ieee->current_network.bssid, ETH_ALEN)) - goto rx_dropped; - - ieee->NumRxDataInPeriod++; - ieee->NumRxOkTotal++; - /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ - - if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0) - goto rx_dropped; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - - /* skb: hdr + (possibly fragmented) plaintext payload */ - // PR: FIXME: hostap has additional conditions in the "if" below: - // ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - if ((frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { - int flen; - struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr); - IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); - - if (!frag_skb) { - IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG, - "Rx cannot get skb from fragment " - "cache (morefrag=%d seq=%u frag=%u)\n", - (fc & IEEE80211_FCTL_MOREFRAGS) != 0, - WLAN_GET_SEQ_SEQ(sc), frag); - goto rx_dropped; - } - flen = skb->len; - if (frag != 0) - flen -= hdrlen; - - if (frag_skb->tail + flen > frag_skb->end) { - netdev_warn(ieee->dev, - "host decrypted and reassembled frame did not fit skb\n"); - ieee80211_frag_cache_invalidate(ieee, hdr); - goto rx_dropped; - } - - if (frag == 0) { - /* copy first fragment (including full headers) into - * beginning of the fragment cache skb */ - memcpy(skb_put(frag_skb, flen), skb->data, flen); - } else { - /* append frame payload to the end of the fragment - * cache skb */ - memcpy(skb_put(frag_skb, flen), skb->data + hdrlen, - flen); - } - dev_kfree_skb_any(skb); - skb = NULL; - - if (fc & IEEE80211_FCTL_MOREFRAGS) { - /* more fragments expected - leave the skb in fragment - * cache for now; it will be delivered to upper layers - * after all fragments have been received */ - goto rx_exit; - } - - /* this was the last fragment and the frame will be - * delivered, so remove skb from fragment cache */ - skb = frag_skb; - hdr = (struct ieee80211_hdr_4addr *)skb->data; - ieee80211_frag_cache_invalidate(ieee, hdr); - } - - /* skb: hdr + (possible reassembled) full MSDU payload; possibly still - * encrypted/authenticated */ - if (ieee->host_decrypt && (fc & IEEE80211_FCTL_WEP) && - ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) - goto rx_dropped; - - hdr = (struct ieee80211_hdr_4addr *)skb->data; - if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep) { - if (/*ieee->ieee802_1x &&*/ - ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - -#ifdef CONFIG_IEEE80211_DEBUG - /* pass unencrypted EAPOL frames even if encryption is - * configured */ - struct eapol *eap = (struct eapol *)(skb->data + - 24); - IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); -#endif - } else { - IEEE80211_DEBUG_DROP( - "encryption configured, but RX " - "frame not encrypted (SA=%pM)\n", - hdr->addr2); - goto rx_dropped; - } - } - -#ifdef CONFIG_IEEE80211_DEBUG - if (crypt && !(fc & IEEE80211_FCTL_WEP) && - ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - struct eapol *eap = (struct eapol *)(skb->data + - 24); - IEEE80211_DEBUG_EAP("RX: IEEE 802.1X EAPOL frame: %s\n", - eap_get_type(eap->type)); - } -#endif - - if (crypt && !(fc & IEEE80211_FCTL_WEP) && !ieee->open_wep && - !ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - IEEE80211_DEBUG_DROP( - "dropped unencrypted RX data " - "frame from %pM" - " (drop_unencrypted=1)\n", - hdr->addr2); - goto rx_dropped; - } -/* - if(ieee80211_is_eapol_frame(ieee, skb, hdrlen)) { - printk(KERN_WARNING "RX: IEEE802.1X EPAOL frame!\n"); - } -*/ - /* skb: hdr + (possible reassembled) full plaintext payload */ - payload = skb->data + hdrlen; - ethertype = (payload[6] << 8) | payload[7]; - - - /* convert hdr + possible LLC headers into Ethernet header */ - if (skb->len - hdrlen >= 8 && - ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ - skb_pull(skb, hdrlen + SNAP_SIZE); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } else { - u16 len; - /* Leave Ethernet header part of hdr and full payload */ - skb_pull(skb, hdrlen); - len = htons(skb->len); - memcpy(skb_push(skb, 2), &len, 2); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } - - - stats->rx_packets++; - stats->rx_bytes += skb->len; - - if (skb) { - skb->protocol = eth_type_trans(skb, dev); - memset(skb->cb, 0, sizeof(skb->cb)); - skb->dev = dev; - skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ - ieee->last_rx_ps_time = jiffies; - netif_rx(skb); - } - - rx_exit: - return 1; - - rx_dropped: - stats->rx_dropped++; - - /* Returning 0 indicates to caller that we have not handled the SKB-- - * so it is still allocated and can be used again by underlying - * hardware as a DMA target */ - return 0; -} - -#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 - -static inline int ieee80211_is_ofdm_rate(u8 rate) -{ - switch (rate & ~IEEE80211_BASIC_RATE_MASK) { - case IEEE80211_OFDM_RATE_6MB: - case IEEE80211_OFDM_RATE_9MB: - case IEEE80211_OFDM_RATE_12MB: - case IEEE80211_OFDM_RATE_18MB: - case IEEE80211_OFDM_RATE_24MB: - case IEEE80211_OFDM_RATE_36MB: - case IEEE80211_OFDM_RATE_48MB: - case IEEE80211_OFDM_RATE_54MB: - return 1; - } - return 0; -} - -static inline int ieee80211_SignalStrengthTranslate(int CurrSS) -{ - int RetSS; - - // Step 1. Scale mapping. - if (CurrSS >= 71 && CurrSS <= 100) - RetSS = 90 + ((CurrSS - 70) / 3); - else if (CurrSS >= 41 && CurrSS <= 70) - RetSS = 78 + ((CurrSS - 40) / 3); - else if (CurrSS >= 31 && CurrSS <= 40) - RetSS = 66 + (CurrSS - 30); - else if (CurrSS >= 21 && CurrSS <= 30) - RetSS = 54 + (CurrSS - 20); - else if (CurrSS >= 5 && CurrSS <= 20) - RetSS = 42 + (((CurrSS - 5) * 2) / 3); - else if (CurrSS == 4) - RetSS = 36; - else if (CurrSS == 3) - RetSS = 27; - else if (CurrSS == 2) - RetSS = 18; - else if (CurrSS == 1) - RetSS = 9; - else - RetSS = CurrSS; - - //RT_TRACE(COMP_DBG, DBG_LOUD, ("##### After Mapping: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); - - // Step 2. Smoothing. - - //RT_TRACE(COMP_DBG, DBG_LOUD, ("$$$$$ After Smoothing: LastSS: %d, CurrSS: %d, RetSS: %d\n", LastSS, CurrSS, RetSS)); - - return RetSS; -} - -static inline void -ieee80211_extract_country_ie(struct ieee80211_device *ieee, - struct ieee80211_info_element *info_element, - struct ieee80211_network *network, u8 *addr2) -{ - if (IS_DOT11D_ENABLE(ieee)) { - if (info_element->len != 0) { - memcpy(network->CountryIeBuf, info_element->data, info_element->len); - network->CountryIeLen = info_element->len; - - if (!IS_COUNTRY_IE_VALID(ieee)) - Dot11d_UpdateCountryIe(ieee, addr2, info_element->len, info_element->data); - } - - // - // 070305, rcnjko: I update country IE watch dog here because - // some AP (e.g. Cisco 1242) don't include country IE in their - // probe response frame. - // - if (IS_EQUAL_CIE_SRC(ieee, addr2)) - UPDATE_CIE_WATCHDOG(ieee); - } - -} - -/* SignalStrengthIndex is 0-100 */ -static int ieee80211_TranslateToDbm(unsigned char SignalStrengthIndex) -{ - unsigned char SignalPower; // in dBm. - - // Translate to dBm (x=0.5y-95). - SignalPower = (int)SignalStrengthIndex * 7 / 10; - SignalPower -= 95; - - return SignalPower; -} -inline int ieee80211_network_init( - struct ieee80211_device *ieee, - struct ieee80211_probe_response *beacon, - struct ieee80211_network *network, - struct ieee80211_rx_stats *stats) -{ -#ifdef CONFIG_IEEE80211_DEBUG - char rates_str[64]; - char *p; -#endif - struct ieee80211_info_element *info_element; - u16 left; - u8 i; - short offset; - u8 curRate = 0, hOpRate = 0, curRate_ex = 0; - - /* Pull out fixed field data */ - memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); - network->capability = beacon->capability; - network->last_scanned = jiffies; - network->time_stamp[0] = beacon->time_stamp[0]; - network->time_stamp[1] = beacon->time_stamp[1]; - network->beacon_interval = beacon->beacon_interval; - /* Where to pull this? beacon->listen_interval;*/ - network->listen_interval = 0x0A; - network->rates_len = network->rates_ex_len = 0; - network->last_associate = 0; - network->ssid_len = 0; - network->flags = 0; - network->atim_window = 0; - network->QoS_Enable = 0; -//by amy 080312 - network->HighestOperaRate = 0; -//by amy 080312 - network->Turbo_Enable = 0; - network->CountryIeLen = 0; - memset(network->CountryIeBuf, 0, MAX_IE_LEN); - - if (stats->freq == IEEE80211_52GHZ_BAND) { - /* for A band (No DS info) */ - network->channel = stats->received_channel; - } else - network->flags |= NETWORK_HAS_CCK; - - network->wpa_ie_len = 0; - network->rsn_ie_len = 0; - - info_element = &beacon->info_element; - left = stats->len - ((void *)info_element - (void *)beacon); - while (left >= sizeof(struct ieee80211_info_element_hdr)) { - if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) { - IEEE80211_DEBUG_SCAN("SCAN: parse failed: info_element->len + 2 > left : info_element->len+2=%d left=%d.\n", - info_element->len + sizeof(struct ieee80211_info_element), - left); - return 1; - } - - switch (info_element->id) { - case MFIE_TYPE_SSID: - if (ieee80211_is_empty_essid(info_element->data, - info_element->len)) { - network->flags |= NETWORK_EMPTY_ESSID; - break; - } - - network->ssid_len = min(info_element->len, - (u8)IW_ESSID_MAX_SIZE); - memcpy(network->ssid, info_element->data, network->ssid_len); - if (network->ssid_len < IW_ESSID_MAX_SIZE) - memset(network->ssid + network->ssid_len, 0, - IW_ESSID_MAX_SIZE - network->ssid_len); - - IEEE80211_DEBUG_SCAN("MFIE_TYPE_SSID: '%s' len=%d.\n", - network->ssid, network->ssid_len); - break; - - case MFIE_TYPE_RATES: -#ifdef CONFIG_IEEE80211_DEBUG - p = rates_str; -#endif - network->rates_len = min(info_element->len, MAX_RATES_LENGTH); - for (i = 0; i < network->rates_len; i++) { - network->rates[i] = info_element->data[i]; - curRate = network->rates[i] & 0x7f; - if (hOpRate < curRate) - hOpRate = curRate; -#ifdef CONFIG_IEEE80211_DEBUG - p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); -#endif - if (ieee80211_is_ofdm_rate(info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - IEEE80211_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - } - - IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES: '%s' (%d)\n", - rates_str, network->rates_len); - break; - - case MFIE_TYPE_RATES_EX: -#ifdef CONFIG_IEEE80211_DEBUG - p = rates_str; -#endif - network->rates_ex_len = min(info_element->len, MAX_RATES_EX_LENGTH); - for (i = 0; i < network->rates_ex_len; i++) { - network->rates_ex[i] = info_element->data[i]; - curRate_ex = network->rates_ex[i] & 0x7f; - if (hOpRate < curRate_ex) - hOpRate = curRate_ex; -#ifdef CONFIG_IEEE80211_DEBUG - p += snprintf(p, sizeof(rates_str) - (p - rates_str), "%02X ", network->rates[i]); -#endif - if (ieee80211_is_ofdm_rate(info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - IEEE80211_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - } - - IEEE80211_DEBUG_SCAN("MFIE_TYPE_RATES_EX: '%s' (%d)\n", - rates_str, network->rates_ex_len); - break; - - case MFIE_TYPE_DS_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_DS_SET: %d\n", - info_element->data[0]); - if (stats->freq == IEEE80211_24GHZ_BAND) - network->channel = info_element->data[0]; - break; - - case MFIE_TYPE_FH_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_FH_SET: ignored\n"); - break; - - case MFIE_TYPE_CF_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_CF_SET: ignored\n"); - break; - - case MFIE_TYPE_TIM: - - if (info_element->len < 4) - break; - - network->dtim_period = info_element->data[1]; - - if (ieee->state != IEEE80211_LINKED) - break; - - network->last_dtim_sta_time[0] = jiffies; - network->last_dtim_sta_time[1] = stats->mac_time[1]; - - network->dtim_data = IEEE80211_DTIM_VALID; - - if (info_element->data[0] != 0) - break; - - if (info_element->data[2] & 1) - network->dtim_data |= IEEE80211_DTIM_MBCAST; - - offset = (info_element->data[2] >> 1)*2; - - //printk("offset1:%x aid:%x\n",offset, ieee->assoc_id); - - /* add and modified for ps 2008.1.22 */ - if (ieee->assoc_id < 8*offset || - ieee->assoc_id > 8*(offset + info_element->len - 3)) { - break; - } - - offset = (ieee->assoc_id/8) - offset;// + ((aid % 8)? 0 : 1) ; - - // printk("offset:%x data:%x, ucast:%d\n", offset, - // info_element->data[3+offset] , - // info_element->data[3+offset] & (1<<(ieee->assoc_id%8))); - - if (info_element->data[3+offset] & (1<<(ieee->assoc_id%8))) - network->dtim_data |= IEEE80211_DTIM_UCAST; - - break; - - case MFIE_TYPE_IBSS_SET: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_IBSS_SET: ignored\n"); - break; - - case MFIE_TYPE_CHALLENGE: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_CHALLENGE: ignored\n"); - break; - - case MFIE_TYPE_GENERIC: - //nic is 87B - IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", - info_element->len); - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x01) { - network->wpa_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->wpa_ie, info_element, - network->wpa_ie_len); - } - - if (info_element->len == 7 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0xe0 && - info_element->data[2] == 0x4c && - info_element->data[3] == 0x01 && - info_element->data[4] == 0x02) { - network->Turbo_Enable = 1; - } - if (1 == stats->nic_type) //nic 87 - break; - - if (info_element->len >= 5 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x02 && - info_element->data[4] == 0x00) { - //printk(KERN_WARNING "wmm info updated: %x\n", info_element->data[6]); - //WMM Information Element - network->wmm_info = info_element->data[6]; - network->QoS_Enable = 1; - } - - if (info_element->len >= 8 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x02 && - info_element->data[4] == 0x01) { - // Not care about version at present. - //WMM Information Element - //printk(KERN_WARNING "wmm info¶m updated: %x\n", info_element->data[6]); - network->wmm_info = info_element->data[6]; - //WMM Parameter Element - memcpy(network->wmm_param, (u8 *)(info_element->data + 8), (info_element->len - 8)); - network->QoS_Enable = 1; - } - break; - - case MFIE_TYPE_RSN: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_RSN: %d bytes\n", - info_element->len); - network->rsn_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->rsn_ie, info_element, - network->rsn_ie_len); - break; - case MFIE_TYPE_COUNTRY: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_COUNTRY: %d bytes\n", - info_element->len); -// printk("=====>Receive <%s> Country IE\n",network->ssid); - ieee80211_extract_country_ie(ieee, info_element, network, beacon->header.addr2); - break; - default: - IEEE80211_DEBUG_SCAN("unsupported IE %d\n", - info_element->id); - break; - } - - left -= sizeof(struct ieee80211_info_element_hdr) + - info_element->len; - info_element = (struct ieee80211_info_element *) - &info_element->data[info_element->len]; - } -//by amy 080312 - network->HighestOperaRate = hOpRate; -//by amy 080312 - network->mode = 0; - if (stats->freq == IEEE80211_52GHZ_BAND) - network->mode = IEEE_A; - else { - if (network->flags & NETWORK_HAS_OFDM) - network->mode |= IEEE_G; - if (network->flags & NETWORK_HAS_CCK) - network->mode |= IEEE_B; - } - - if (network->mode == 0) { - IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' " - "network.\n", - escape_essid(network->ssid, - network->ssid_len), - network->bssid); - return 1; - } - - if (ieee80211_is_empty_essid(network->ssid, network->ssid_len)) - network->flags |= NETWORK_EMPTY_ESSID; - - stats->signal = ieee80211_TranslateToDbm(stats->signalstrength); - //stats->noise = stats->signal - stats->noise; - stats->noise = ieee80211_TranslateToDbm(100 - stats->signalstrength) - 25; - memcpy(&network->stats, stats, sizeof(network->stats)); - - return 0; -} - -static inline int is_same_network(struct ieee80211_network *src, - struct ieee80211_network *dst, - struct ieee80211_device *ieee) -{ - /* A network is only a duplicate if the channel, BSSID, ESSID - * and the capability field (in particular IBSS and BSS) all match. - * We treat all with the same BSSID and channel - * as one network */ - return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap - //((src->ssid_len == dst->ssid_len) && - (src->channel == dst->channel) && - !memcmp(src->bssid, dst->bssid, ETH_ALEN) && - (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && //YJ,mod,080819,for hidden ap - //!memcmp(src->ssid, dst->ssid, src->ssid_len) && - ((src->capability & WLAN_CAPABILITY_IBSS) == - (dst->capability & WLAN_CAPABILITY_IBSS)) && - ((src->capability & WLAN_CAPABILITY_BSS) == - (dst->capability & WLAN_CAPABILITY_BSS))); -} - -inline void update_network(struct ieee80211_network *dst, - struct ieee80211_network *src) -{ - unsigned char quality = src->stats.signalstrength; - unsigned char signal = 0; - unsigned char noise = 0; - if (dst->stats.signalstrength > 0) - quality = (dst->stats.signalstrength * 5 + src->stats.signalstrength + 5)/6; - signal = ieee80211_TranslateToDbm(quality); - //noise = signal - src->stats.noise; - if (dst->stats.noise > 0) - noise = (dst->stats.noise * 5 + src->stats.noise)/6; - //if(strcmp(dst->ssid, "linksys_lzm000") == 0) -// printk("ssid:%s, quality:%d, signal:%d\n", dst->ssid, quality, signal); - memcpy(&dst->stats, &src->stats, sizeof(struct ieee80211_rx_stats)); - dst->stats.signalstrength = quality; - dst->stats.signal = signal; -// printk("==================>stats.signal is %d\n",dst->stats.signal); - dst->stats.noise = noise; - - - dst->capability = src->capability; - memcpy(dst->rates, src->rates, src->rates_len); - dst->rates_len = src->rates_len; - memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); - dst->rates_ex_len = src->rates_ex_len; - dst->HighestOperaRate = src->HighestOperaRate; - //printk("==========>in %s: src->ssid is %s,chan is %d\n",__func__,src->ssid,src->channel); - - //YJ,add,080819,for hidden ap - if (src->ssid_len > 0) { - //if(src->ssid_len == 13) - // printk("=====================>>>>>>>> Dst ssid: %s Src ssid: %s\n", dst->ssid, src->ssid); - memset(dst->ssid, 0, dst->ssid_len); - dst->ssid_len = src->ssid_len; - memcpy(dst->ssid, src->ssid, src->ssid_len); - } - //YJ,add,080819,for hidden ap,end - - dst->channel = src->channel; - dst->mode = src->mode; - dst->flags = src->flags; - dst->time_stamp[0] = src->time_stamp[0]; - dst->time_stamp[1] = src->time_stamp[1]; - - dst->beacon_interval = src->beacon_interval; - dst->listen_interval = src->listen_interval; - dst->atim_window = src->atim_window; - dst->dtim_period = src->dtim_period; - dst->dtim_data = src->dtim_data; - dst->last_dtim_sta_time[0] = src->last_dtim_sta_time[0]; - dst->last_dtim_sta_time[1] = src->last_dtim_sta_time[1]; -// printk("update:%s, dtim_period:%x, dtim_data:%x\n", src->ssid, src->dtim_period, src->dtim_data); - memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); - dst->wpa_ie_len = src->wpa_ie_len; - memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); - dst->rsn_ie_len = src->rsn_ie_len; - - dst->last_scanned = jiffies; - /* dst->last_associate is not overwritten */ -// disable QoS process now, added by David 2006/7/25 -#if 1 - dst->wmm_info = src->wmm_info; //sure to exist in beacon or probe response frame. -/* - if((dst->wmm_info^src->wmm_info)&0x0f) {//Param Set Count change, update Parameter - memcpy(dst->wmm_param, src->wmm_param, IEEE80211_AC_PRAM_LEN); - } -*/ - if (src->wmm_param[0].ac_aci_acm_aifsn || \ - src->wmm_param[1].ac_aci_acm_aifsn || \ - src->wmm_param[2].ac_aci_acm_aifsn || \ - src->wmm_param[3].ac_aci_acm_aifsn) { - memcpy(dst->wmm_param, src->wmm_param, WME_AC_PRAM_LEN); - } - dst->QoS_Enable = src->QoS_Enable; -#else - dst->QoS_Enable = 1;//for Rtl8187 simulation -#endif - dst->SignalStrength = src->SignalStrength; - dst->Turbo_Enable = src->Turbo_Enable; - dst->CountryIeLen = src->CountryIeLen; - memcpy(dst->CountryIeBuf, src->CountryIeBuf, src->CountryIeLen); -} - - -inline void -ieee80211_process_probe_response(struct ieee80211_device *ieee, - struct ieee80211_probe_response *beacon, - struct ieee80211_rx_stats *stats) -{ - struct ieee80211_network network; - struct ieee80211_network *target; - struct ieee80211_network *oldest = NULL; -#ifdef CONFIG_IEEE80211_DEBUG - struct ieee80211_info_element *info_element = &beacon->info_element; -#endif - unsigned long flags; - short renew; - u8 wmm_info; - u8 is_beacon = (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_BEACON) ? 1 : 0; //YJ,add,080819,for hidden ap - - memset(&network, 0, sizeof(struct ieee80211_network)); - - IEEE80211_DEBUG_SCAN( - "'%s' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", - escape_essid(info_element->data, info_element->len), - beacon->header.addr3, - (beacon->capability & (1<<0xf)) ? '1' : '0', - (beacon->capability & (1<<0xe)) ? '1' : '0', - (beacon->capability & (1<<0xd)) ? '1' : '0', - (beacon->capability & (1<<0xc)) ? '1' : '0', - (beacon->capability & (1<<0xb)) ? '1' : '0', - (beacon->capability & (1<<0xa)) ? '1' : '0', - (beacon->capability & (1<<0x9)) ? '1' : '0', - (beacon->capability & (1<<0x8)) ? '1' : '0', - (beacon->capability & (1<<0x7)) ? '1' : '0', - (beacon->capability & (1<<0x6)) ? '1' : '0', - (beacon->capability & (1<<0x5)) ? '1' : '0', - (beacon->capability & (1<<0x4)) ? '1' : '0', - (beacon->capability & (1<<0x3)) ? '1' : '0', - (beacon->capability & (1<<0x2)) ? '1' : '0', - (beacon->capability & (1<<0x1)) ? '1' : '0', - (beacon->capability & (1<<0x0)) ? '1' : '0'); - - if (ieee80211_network_init(ieee, beacon, &network, stats)) { - IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", - escape_essid(info_element->data, - info_element->len), - beacon->header.addr3, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == - IEEE80211_STYPE_PROBE_RESP ? - "PROBE RESPONSE" : "BEACON"); - return; - } - - // For Asus EeePc request, - // (1) if wireless adapter receive get any 802.11d country code in AP beacon, - // wireless adapter should follow the country code. - // (2) If there is no any country code in beacon, - // then wireless adapter should do active scan from ch1~11 and - // passive scan from ch12~14 - if (ieee->bGlobalDomain) { - if (WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == IEEE80211_STYPE_PROBE_RESP) { - // Case 1: Country code - if (IS_COUNTRY_IE_VALID(ieee)) { - if (!IsLegalChannel(ieee, network.channel)) { - printk("GetScanInfo(): For Country code, filter probe response at channel(%d).\n", network.channel); - return; - } - } - // Case 2: No any country code. - else { - // Filter over channel ch12~14 - if (network.channel > 11) { - printk("GetScanInfo(): For Global Domain, filter probe response at channel(%d).\n", network.channel); - return; - } - } - } else { - // Case 1: Country code - if (IS_COUNTRY_IE_VALID(ieee)) { - if (!IsLegalChannel(ieee, network.channel)) { - printk("GetScanInfo(): For Country code, filter beacon at channel(%d).\n", network.channel); - return; - } - } - // Case 2: No any country code. - else { - // Filter over channel ch12~14 - if (network.channel > 14) { - printk("GetScanInfo(): For Global Domain, filter beacon at channel(%d).\n", network.channel); - return; - } - } - } - } - /* The network parsed correctly -- so now we scan our known networks - * to see if we can find it in our list. - * - * NOTE: This search is definitely not optimized. Once its doing - * the "right thing" we'll optimize it for efficiency if - * necessary */ - - /* Search for this entry in the list and update it if it is - * already there. */ - - spin_lock_irqsave(&ieee->lock, flags); - - if (is_same_network(&ieee->current_network, &network, ieee)) { - wmm_info = ieee->current_network.wmm_info; - //YJ,add,080819,for hidden ap - if (is_beacon == 0) - network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & ieee->current_network.flags); - else if (ieee->state == IEEE80211_LINKED) - ieee->NumRxBcnInPeriod++; - //YJ,add,080819,for hidden ap,end - //printk("====>network.ssid=%s cur_ssid=%s\n", network.ssid, ieee->current_network.ssid); - update_network(&ieee->current_network, &network); - } - - list_for_each_entry(target, &ieee->network_list, list) { - if (is_same_network(target, &network, ieee)) - break; - if ((oldest == NULL) || - (target->last_scanned < oldest->last_scanned)) - oldest = target; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ - if (&target->list == &ieee->network_list) { - if (list_empty(&ieee->network_free_list)) { - /* If there are no more slots, expire the oldest */ - list_del(&oldest->list); - target = oldest; - IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from " - "network list.\n", - escape_essid(target->ssid, - target->ssid_len), - target->bssid); - } else { - /* Otherwise just pull from the free list */ - target = list_entry(ieee->network_free_list.next, - struct ieee80211_network, list); - list_del(ieee->network_free_list.next); - } - - -#ifdef CONFIG_IEEE80211_DEBUG - IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", - escape_essid(network.ssid, - network.ssid_len), - network.bssid, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == - IEEE80211_STYPE_PROBE_RESP ? - "PROBE RESPONSE" : "BEACON"); -#endif - - memcpy(target, &network, sizeof(*target)); - list_add_tail(&target->list, &ieee->network_list); - } else { - IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", - escape_essid(target->ssid, - target->ssid_len), - target->bssid, - WLAN_FC_GET_STYPE(beacon->header.frame_ctl) == - IEEE80211_STYPE_PROBE_RESP ? - "PROBE RESPONSE" : "BEACON"); - - /* we have an entry and we are going to update it. But this entry may - * be already expired. In this case we do the same as we found a new - * net and call the new_net handler - */ - renew = !time_after(target->last_scanned + ieee->scan_age, jiffies); - //YJ,add,080819,for hidden ap - if (is_beacon == 0) - network.flags = (~NETWORK_EMPTY_ESSID & network.flags)|(NETWORK_EMPTY_ESSID & target->flags); - //if(strncmp(network.ssid, "linksys-c",9) == 0) - // printk("====>2 network.ssid=%s FLAG=%d target.ssid=%s FLAG=%d\n", network.ssid, network.flags, target->ssid, target->flags); - if (((network.flags & NETWORK_EMPTY_ESSID) == NETWORK_EMPTY_ESSID) \ - && (((network.ssid_len > 0) && (strncmp(target->ssid, network.ssid, network.ssid_len)))\ - || ((ieee->current_network.ssid_len == network.ssid_len) && (strncmp(ieee->current_network.ssid, network.ssid, network.ssid_len) == 0) && (ieee->state == IEEE80211_NOLINK)))) - renew = 1; - //YJ,add,080819,for hidden ap,end - update_network(target, &network); - } - - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_rx_mgt(struct ieee80211_device *ieee, - struct ieee80211_hdr_4addr *header, - struct ieee80211_rx_stats *stats) -{ - switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { - - case IEEE80211_STYPE_BEACON: - IEEE80211_DEBUG_MGMT("received BEACON (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); - IEEE80211_DEBUG_SCAN("Beacon\n"); - ieee80211_process_probe_response( - ieee, (struct ieee80211_probe_response *)header, stats); - break; - - case IEEE80211_STYPE_PROBE_RESP: - IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); - IEEE80211_DEBUG_SCAN("Probe response\n"); - ieee80211_process_probe_response( - ieee, (struct ieee80211_probe_response *)header, stats); - break; - } -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c deleted file mode 100644 index 03eb164798cd2a..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ /dev/null @@ -1,2711 +0,0 @@ -/* IEEE 802.11 SoftMAC layer - * Copyright (c) 2005 Andrea Merello - * - * Mostly extracted from the rtl8180-sa2400 driver for the - * in-kernel generic ieee802.11 stack. - * - * Few lines might be stolen from other part of the ieee80211 - * stack. Copyright who own it's copyright - * - * WPA code stolen from the ipw2200 driver. - * Copyright who own it's copyright. - * - * released under the GPL - */ - -#include "ieee80211.h" - -#include -#include -#include -#include -#include -#include - -#include "dot11d.h" - -short ieee80211_is_54g(const struct ieee80211_network *net) -{ - return (net->rates_ex_len > 0) || (net->rates_len > 4); -} - -short ieee80211_is_shortslot(const struct ieee80211_network *net) -{ - return net->capability & WLAN_CAPABILITY_SHORT_SLOT; -} - -/* returns the total length needed for placing the RATE MFIE - * tag and the EXTENDED RATE MFIE tag if needed. - * It encludes two bytes per tag for the tag itself and its len - */ -static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee) -{ - unsigned int rate_len = 0; - - if (ieee->modulation & IEEE80211_CCK_MODULATION) - rate_len = IEEE80211_CCK_RATE_LEN + 2; - - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - - rate_len += IEEE80211_OFDM_RATE_LEN + 2; - - return rate_len; -} - -/* place the MFIE rate, tag to the memory (double) poised. - * Then it updates the pointer so that it points after the new MFIE tag added. - */ -static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - *tag++ = MFIE_TYPE_RATES; - *tag++ = 4; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - } - - /* We may add an option for custom rates that specific HW might support */ - *tag_p = tag; -} - -static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - if (ieee->modulation & IEEE80211_OFDM_MODULATION) { - *tag++ = MFIE_TYPE_RATES_EX; - *tag++ = 8; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; - *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; - - } - /* We may add an option for custom rates that specific HW might support */ - *tag_p = tag; -} - -static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - - *tag++ = MFIE_TYPE_GENERIC; /* 0 */ - *tag++ = 7; - *tag++ = 0x00; - *tag++ = 0x50; - *tag++ = 0xf2; - *tag++ = 0x02; /* 5 */ - *tag++ = 0x00; - *tag++ = 0x01; -#ifdef SUPPORT_USPD - if (ieee->current_network.wmm_info & 0x80) - *tag++ = 0x0f|MAX_SP_Len; - else - *tag++ = MAX_SP_Len; -#else - *tag++ = MAX_SP_Len; -#endif - *tag_p = tag; -} - -static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) -{ - u8 *tag = *tag_p; - *tag++ = MFIE_TYPE_GENERIC; /* 0 */ - *tag++ = 7; - *tag++ = 0x00; - *tag++ = 0xe0; - *tag++ = 0x4c; - *tag++ = 0x01; /* 5 */ - *tag++ = 0x02; - *tag++ = 0x11; - *tag++ = 0x00; - *tag_p = tag; - printk(KERN_ALERT "This is enable turbo mode IE process\n"); -} - -static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb) -{ - int nh; - nh = (ieee->mgmt_queue_head + 1) % MGMT_QUEUE_NUM; - - ieee->mgmt_queue_head = nh; - ieee->mgmt_queue_ring[nh] = skb; -} - -static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee) -{ - struct sk_buff *ret; - - if (ieee->mgmt_queue_tail == ieee->mgmt_queue_head) - return NULL; - - ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail]; - - ieee->mgmt_queue_tail = - (ieee->mgmt_queue_tail + 1) % MGMT_QUEUE_NUM; - - return ret; -} - -static void init_mgmt_queue(struct ieee80211_device *ieee) -{ - ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0; -} - -void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl); - -inline void softmac_mgmt_xmit(struct sk_buff *skb, - struct ieee80211_device *ieee) -{ - unsigned long flags; - short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *) skb->data; - - spin_lock_irqsave(&ieee->lock, flags); - - /* called with 2nd param 0, no mgmt lock required */ - ieee80211_sta_wakeup(ieee, 0); - - if (single) { - if (ieee->queue_stop) { - enqueue_mgmt(ieee, skb); - } else { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate); - } - - spin_unlock_irqrestore(&ieee->lock, flags); - } else { - spin_unlock_irqrestore(&ieee->lock, flags); - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); - - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_hard_start_xmit(skb, ieee->dev); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags); - } -} - -inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, - struct ieee80211_device *ieee) -{ - short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *) skb->data; - - if (single) { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate); - } else { - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - /* avoid watchdog triggers */ - ieee->dev->trans_start = jiffies; - ieee->softmac_hard_start_xmit(skb, ieee->dev); - } -} - -inline struct sk_buff * -ieee80211_disassociate_skb(struct ieee80211_network *beacon, - struct ieee80211_device *ieee, u8 asRsn) -{ - struct sk_buff *skb; - struct ieee80211_disassoc_frame *disass; - - skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc_frame)); - if (!skb) - return NULL; - - disass = (struct ieee80211_disassoc_frame *) skb_put(skb, sizeof(struct ieee80211_disassoc_frame)); - disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC); - disass->header.duration_id = 0; - - memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); - memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN); - - disass->reasoncode = asRsn; - return skb; -} - -void SendDisassociation(struct ieee80211_device *ieee, u8 *asSta, u8 asRsn) -{ - struct ieee80211_network *beacon = &ieee->current_network; - struct sk_buff *skb; - skb = ieee80211_disassociate_skb(beacon, ieee, asRsn); - if (skb) - softmac_mgmt_xmit(skb, ieee); -} - -inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) -{ - unsigned int len, rate_len; - u8 *tag; - struct sk_buff *skb; - struct ieee80211_probe_request *req; - - len = ieee->current_network.ssid_len; - - rate_len = ieee80211_MFIE_rate_len(ieee); - - skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + - 2 + len + rate_len); - if (!skb) - return NULL; - - req = (struct ieee80211_probe_request *) skb_put(skb, sizeof(struct ieee80211_probe_request)); - req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - req->header.duration_id = 0; /* FIXME: is this OK ? */ - - memset(req->header.addr1, 0xff, ETH_ALEN); - memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memset(req->header.addr3, 0xff, ETH_ALEN); - - tag = (u8 *) skb_put(skb, len + 2 + rate_len); - - *tag++ = MFIE_TYPE_SSID; - *tag++ = len; - memcpy(tag, ieee->current_network.ssid, len); - tag += len; - ieee80211_MFIE_Brate(ieee, &tag); - ieee80211_MFIE_Grate(ieee, &tag); - - return skb; -} - -struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee); - -static void ieee80211_send_beacon(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - - skb = ieee80211_get_beacon_(ieee); - - if (skb) { - softmac_mgmt_xmit(skb, ieee); - ieee->softmac_stats.tx_beacons++; - dev_kfree_skb_any(skb); - } - - ieee->beacon_timer.expires = jiffies + - (MSECS(ieee->current_network.beacon_interval - 5)); - - if (ieee->beacon_txing) - add_timer(&ieee->beacon_timer); -} - - -static void ieee80211_send_beacon_cb(unsigned long _ieee) -{ - struct ieee80211_device *ieee = - (struct ieee80211_device *) _ieee; - unsigned long flags; - - spin_lock_irqsave(&ieee->beacon_lock, flags); - ieee80211_send_beacon(ieee); - spin_unlock_irqrestore(&ieee->beacon_lock, flags); -} - -static void ieee80211_send_probe(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - - skb = ieee80211_probe_req(ieee); - if (skb) { - softmac_mgmt_xmit(skb, ieee); - ieee->softmac_stats.tx_probe_rq++; - } -} - -static void ieee80211_send_probe_requests(struct ieee80211_device *ieee) -{ - if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) { - ieee80211_send_probe(ieee); - ieee80211_send_probe(ieee); - } -} - -/* this performs syncro scan blocking the caller until all channels - * in the allowed channel map has been checked. - */ -static void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee) -{ - short ch = 0; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); - down(&ieee->scan_sem); - - while (1) { - do { - ch++; - if (ch > MAX_CHANNEL_NUMBER) - goto out; /* scan completed */ - - } while (!channel_map[ch]); - /* this function can be called in two situations - * 1- We have switched to ad-hoc mode and we are - * performing a complete syncro scan before conclude - * there are no interesting cell and to create a - * new one. In this case the link state is - * IEEE80211_NOLINK until we found an interesting cell. - * If so the ieee8021_new_net, called by the RX path - * will set the state to IEEE80211_LINKED, so we stop - * scanning - * 2- We are linked and the root uses run iwlist scan. - * So we switch to IEEE80211_LINKED_SCANNING to remember - * that we are still logically linked (not interested in - * new network events, despite for updating the net list, - * but we are temporarily 'unlinked' as the driver shall - * not filter RX frames and the channel is changing. - * So the only situation in witch are interested is to check - * if the state become LINKED because of the #1 situation - */ - - if (ieee->state == IEEE80211_LINKED) - goto out; - - ieee->set_chan(ieee->dev, ch); - if (channel_map[ch] == 1) - ieee80211_send_probe_requests(ieee); - - /* this prevent excessive time wait when we - * need to wait for a syncro scan to end.. - */ - if (ieee->sync_scan_hurryup) - goto out; - - msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME); - } -out: - ieee->sync_scan_hurryup = 0; - up(&ieee->scan_sem); - if (IS_DOT11D_ENABLE(ieee)) - DOT11D_ScanComplete(ieee); -} - -void ieee80211_softmac_ips_scan_syncro(struct ieee80211_device *ieee) -{ - int ch; - unsigned int watch_dog = 0; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); - down(&ieee->scan_sem); - ch = ieee->current_network.channel; - - while (1) { - /* this function can be called in two situations - * 1- We have switched to ad-hoc mode and we are - * performing a complete syncro scan before conclude - * there are no interesting cell and to create a - * new one. In this case the link state is - * IEEE80211_NOLINK until we found an interesting cell. - * If so the ieee8021_new_net, called by the RX path - * will set the state to IEEE80211_LINKED, so we stop - * scanning - * 2- We are linked and the root uses run iwlist scan. - * So we switch to IEEE80211_LINKED_SCANNING to remember - * that we are still logically linked (not interested in - * new network events, despite for updating the net list, - * but we are temporarily 'unlinked' as the driver shall - * not filter RX frames and the channel is changing. - * So the only situation in witch are interested is to check - * if the state become LINKED because of the #1 situation - */ - if (ieee->state == IEEE80211_LINKED) - goto out; - - if (channel_map[ieee->current_network.channel] > 0) - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - if (channel_map[ieee->current_network.channel] == 1) - ieee80211_send_probe_requests(ieee); - - msleep_interruptible_rtl(IEEE80211_SOFTMAC_SCAN_TIME); - - do { - if (watch_dog++ >= MAX_CHANNEL_NUMBER) - goto out; /* scan completed */ - - ieee->current_network.channel = (ieee->current_network.channel + 1)%MAX_CHANNEL_NUMBER; - } while (!channel_map[ieee->current_network.channel]); - } -out: - ieee->actscanning = false; - up(&ieee->scan_sem); - if (IS_DOT11D_ENABLE(ieee)) - DOT11D_ScanComplete(ieee); -} - -static void ieee80211_softmac_scan_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq); - static short watchdog; - u8 channel_map[MAX_CHANNEL_NUMBER+1]; - memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); - down(&ieee->scan_sem); - - do { - ieee->current_network.channel = - (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; - if (watchdog++ > MAX_CHANNEL_NUMBER) - goto out; /* no good chans */ - } while (!channel_map[ieee->current_network.channel]); - - if (ieee->scanning == 0) { - printk("error out, scanning = 0\n"); - goto out; - } - ieee->set_chan(ieee->dev, ieee->current_network.channel); - if (channel_map[ieee->current_network.channel] == 1) - ieee80211_send_probe_requests(ieee); - - queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME); - up(&ieee->scan_sem); - return; -out: - ieee->actscanning = false; - watchdog = 0; - ieee->scanning = 0; - up(&ieee->scan_sem); - - if (IS_DOT11D_ENABLE(ieee)) - DOT11D_ScanComplete(ieee); - return; -} - -static void ieee80211_beacons_start(struct ieee80211_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->beacon_lock, flags); - - ieee->beacon_txing = 1; - ieee80211_send_beacon(ieee); - - spin_unlock_irqrestore(&ieee->beacon_lock, flags); -} - -static void ieee80211_beacons_stop(struct ieee80211_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->beacon_lock, flags); - - ieee->beacon_txing = 0; - del_timer_sync(&ieee->beacon_timer); - - spin_unlock_irqrestore(&ieee->beacon_lock, flags); -} - -void ieee80211_stop_send_beacons(struct ieee80211_device *ieee) -{ - if (ieee->stop_send_beacons) - ieee->stop_send_beacons(ieee->dev); - if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) - ieee80211_beacons_stop(ieee); -} - -void ieee80211_start_send_beacons(struct ieee80211_device *ieee) -{ - if (ieee->start_send_beacons) - ieee->start_send_beacons(ieee->dev); - if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) - ieee80211_beacons_start(ieee); -} - -static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee) -{ - down(&ieee->scan_sem); - - if (ieee->scanning == 1) { - ieee->scanning = 0; - cancel_delayed_work(&ieee->softmac_scan_wq); - } - - up(&ieee->scan_sem); -} - -void ieee80211_stop_scan(struct ieee80211_device *ieee) -{ - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) - ieee80211_softmac_stop_scan(ieee); - else - ieee->stop_scan(ieee->dev); -} - -/* called with ieee->lock held */ -void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) -{ - if (IS_DOT11D_ENABLE(ieee)) { - if (IS_COUNTRY_IE_VALID(ieee)) - RESET_CIE_WATCHDOG(ieee); - } - - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) { - if (ieee->scanning == 0) { - ieee->scanning = 1; -#if 1 - queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0); -#endif - } - }else - ieee->start_scan(ieee->dev); -} - -/* called with wx_sem held */ -void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) -{ - if (IS_DOT11D_ENABLE(ieee)) { - if (IS_COUNTRY_IE_VALID(ieee)) - RESET_CIE_WATCHDOG(ieee); - } - ieee->sync_scan_hurryup = 0; - - if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) - ieee80211_softmac_scan_syncro(ieee); - else - ieee->scan_syncro(ieee->dev); -} - -inline struct sk_buff * -ieee80211_authentication_req(struct ieee80211_network *beacon, - struct ieee80211_device *ieee, int challengelen) -{ - struct sk_buff *skb; - struct ieee80211_authentication *auth; - - skb = dev_alloc_skb(sizeof(struct ieee80211_authentication) + challengelen); - - if (!skb) - return NULL; - - auth = (struct ieee80211_authentication *) - skb_put(skb, sizeof(struct ieee80211_authentication)); - - auth->header.frame_ctl = IEEE80211_STYPE_AUTH; - if (challengelen) - auth->header.frame_ctl |= IEEE80211_FCTL_WEP; - - auth->header.duration_id = 0x013a; /* FIXME */ - - memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); - memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); - - auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; - - auth->transaction = cpu_to_le16(ieee->associate_seq); - ieee->associate_seq++; - - auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS); - - return skb; -} - -static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, - u8 *dest) -{ - u8 *tag; - int beacon_size; - struct ieee80211_probe_response *beacon_buf; - struct sk_buff *skb; - int encrypt; - int atim_len, erp_len; - struct ieee80211_crypt_data *crypt; - - char *ssid = ieee->current_network.ssid; - int ssid_len = ieee->current_network.ssid_len; - int rate_len = ieee->current_network.rates_len+2; - int rate_ex_len = ieee->current_network.rates_ex_len; - int wpa_ie_len = ieee->wpa_ie_len; - if (rate_ex_len > 0) - rate_ex_len += 2; - - if (ieee->current_network.capability & WLAN_CAPABILITY_IBSS) - atim_len = 4; - else - atim_len = 0; - - if (ieee80211_is_54g(&ieee->current_network)) - erp_len = 3; - else - erp_len = 0; - - beacon_size = sizeof(struct ieee80211_probe_response)+ - ssid_len - +3 /* channel */ - +rate_len - +rate_ex_len - +atim_len - +wpa_ie_len - +erp_len; - - skb = dev_alloc_skb(beacon_size); - - if (!skb) - return NULL; - - beacon_buf = (struct ieee80211_probe_response *) skb_put(skb, beacon_size); - - memcpy(beacon_buf->header.addr1, dest, ETH_ALEN); - memcpy(beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); - - beacon_buf->header.duration_id = 0; /* FIXME */ - beacon_buf->beacon_interval = - cpu_to_le16(ieee->current_network.beacon_interval); - beacon_buf->capability = - cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); - - if (ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) - beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - - crypt = ieee->crypt[ieee->tx_keyidx]; - - encrypt = ieee->host_encrypt && crypt && crypt->ops && - ((0 == strcmp(crypt->ops->name, "WEP")) || wpa_ie_len); - - if (encrypt) - beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - - - beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); - - beacon_buf->info_element.id = MFIE_TYPE_SSID; - beacon_buf->info_element.len = ssid_len; - - tag = (u8 *) beacon_buf->info_element.data; - - memcpy(tag, ssid, ssid_len); - - tag += ssid_len; - - *(tag++) = MFIE_TYPE_RATES; - *(tag++) = rate_len - 2; - memcpy(tag, ieee->current_network.rates, rate_len-2); - tag += rate_len - 2; - - *(tag++) = MFIE_TYPE_DS_SET; - *(tag++) = 1; - *(tag++) = ieee->current_network.channel; - - if (atim_len) { - *(tag++) = MFIE_TYPE_IBSS_SET; - *(tag++) = 2; - *((u16 *)(tag)) = cpu_to_le16(ieee->current_network.atim_window); - tag += 2; - } - - if (erp_len) { - *(tag++) = MFIE_TYPE_ERP; - *(tag++) = 1; - *(tag++) = 0; - } - - if (rate_ex_len) { - *(tag++) = MFIE_TYPE_RATES_EX; - *(tag++) = rate_ex_len-2; - memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2); - tag += rate_ex_len - 2; - } - - if (wpa_ie_len) { - if (ieee->iw_mode == IW_MODE_ADHOC) { - /* as Windows will set pairwise key same as the group - * key which is not allowed in Linux, so set this for - * IOT issue. - */ - memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4); - } - - memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); - } - skb->dev = ieee->dev; - return skb; -} - -static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee, - u8 *dest) -{ - struct sk_buff *skb; - u8 *tag; - - struct ieee80211_crypt_data *crypt; - struct ieee80211_assoc_response_frame *assoc; - short encrypt; - - unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); - int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len; - - skb = dev_alloc_skb(len); - - if (!skb) - return NULL; - - assoc = (struct ieee80211_assoc_response_frame *) - skb_put(skb, sizeof(struct ieee80211_assoc_response_frame)); - - assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); - memcpy(assoc->header.addr1, dest, ETH_ALEN); - memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); - memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? - WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS); - - if (ieee->short_slot) - assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - - if (ieee->host_encrypt) - crypt = ieee->crypt[ieee->tx_keyidx]; - else - crypt = NULL; - - encrypt = (crypt && crypt->ops); - - if (encrypt) - assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - - assoc->status = 0; - assoc->aid = cpu_to_le16(ieee->assoc_id); - if (ieee->assoc_id == 0x2007) - ieee->assoc_id = 0; - else - ieee->assoc_id++; - - tag = (u8 *) skb_put(skb, rate_len); - - ieee80211_MFIE_Brate(ieee, &tag); - ieee80211_MFIE_Grate(ieee, &tag); - - return skb; -} - -static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee, - int status, u8 *dest) -{ - struct sk_buff *skb; - struct ieee80211_authentication *auth; - - skb = dev_alloc_skb(sizeof(struct ieee80211_authentication)+1); - - if (!skb) - return NULL; - - skb->len = sizeof(struct ieee80211_authentication); - - auth = (struct ieee80211_authentication *)skb->data; - - auth->status = cpu_to_le16(status); - auth->transaction = cpu_to_le16(2); - auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN); - - memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); - memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(auth->header.addr1, dest, ETH_ALEN); - auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH); - return skb; -} - -static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee, short pwr) -{ - struct sk_buff *skb; - struct ieee80211_hdr_3addr *hdr; - - skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr)); - - if (!skb) - return NULL; - - hdr = (struct ieee80211_hdr_3addr *)skb_put(skb, sizeof(struct ieee80211_hdr_3addr)); - - memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN); - memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); - - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | - (pwr ? IEEE80211_FCTL_PM:0)); - - return skb; -} - -static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest) -{ - struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest); - - if (buf) { - softmac_mgmt_xmit(buf, ieee); - dev_kfree_skb_any(buf); - } -} - -static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8 *dest) -{ - struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest); - - if (buf) { - softmac_mgmt_xmit(buf, ieee); - dev_kfree_skb_any(buf); - } -} - -static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) -{ - struct sk_buff *buf = ieee80211_probe_resp(ieee, dest); - - if (buf) { - softmac_mgmt_xmit(buf, ieee); - dev_kfree_skb_any(buf); - } -} - -inline struct sk_buff * -ieee80211_association_req(struct ieee80211_network *beacon, - struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - - struct ieee80211_assoc_request_frame *hdr; - u8 *tag; - unsigned int wpa_len = beacon->wpa_ie_len; -#if 1 - /* for testing purpose */ - unsigned int rsn_len = beacon->rsn_ie_len; -#endif - unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); - unsigned int wmm_info_len = beacon->QoS_Enable?9:0; - unsigned int turbo_info_len = beacon->Turbo_Enable?9:0; - - u8 encry_proto = ieee->wpax_type_notify & 0xff; - - int len = 0; - - /* [0] Notify type of encryption: WPA/WPA2 - * [1] pair wise type - * [2] authen type - */ - if (ieee->wpax_type_set) { - if (IEEE_PROTO_WPA == encry_proto) { - rsn_len = 0; - } else if (IEEE_PROTO_RSN == encry_proto) { - wpa_len = 0; - } - } - len = sizeof(struct ieee80211_assoc_request_frame)+ - + beacon->ssid_len /* essid tagged val */ - + rate_len /* rates tagged val */ - + wpa_len - + rsn_len - + wmm_info_len - + turbo_info_len; - - skb = dev_alloc_skb(len); - - if (!skb) - return NULL; - - hdr = (struct ieee80211_assoc_request_frame *) - skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)); - - hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ; - hdr->header.duration_id = 37; /* FIXME */ - memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); - memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); - memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN); - memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN); /* for HW security */ - - hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS); - if (beacon->capability & WLAN_CAPABILITY_PRIVACY) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); - - if (ieee->short_slot) - hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); - - hdr->listen_interval = 0xa; /* FIXME */ - - hdr->info_element.id = MFIE_TYPE_SSID; - - hdr->info_element.len = beacon->ssid_len; - tag = skb_put(skb, beacon->ssid_len); - memcpy(tag, beacon->ssid, beacon->ssid_len); - - tag = skb_put(skb, rate_len); - - ieee80211_MFIE_Brate(ieee, &tag); - ieee80211_MFIE_Grate(ieee, &tag); - - /* add rsn==0 condition for ap's mix security mode(wpa+wpa2) - * choose AES encryption as default algorithm while using mixed mode. - */ - - tag = skb_put(skb, ieee->wpa_ie_len); - memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); - - tag = skb_put(skb, wmm_info_len); - if (wmm_info_len) - ieee80211_WMM_Info(ieee, &tag); - - tag = skb_put(skb, turbo_info_len); - if (turbo_info_len) - ieee80211_TURBO_Info(ieee, &tag); - - return skb; -} - -void ieee80211_associate_abort(struct ieee80211_device *ieee) -{ - unsigned long flags; - spin_lock_irqsave(&ieee->lock, flags); - - ieee->associate_seq++; - - /* don't scan, and avoid to have the RX path possibly - * try again to associate. Even do not react to AUTH or - * ASSOC response. Just wait for the retry wq to be scheduled. - * Here we will check if there are good nets to associate - * with, so we retry or just get back to NO_LINK and scanning - */ - if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING) { - IEEE80211_DEBUG_MGMT("Authentication failed\n"); - ieee->softmac_stats.no_auth_rs++; - } else { - IEEE80211_DEBUG_MGMT("Association failed\n"); - ieee->softmac_stats.no_ass_rs++; - } - - ieee->state = IEEE80211_ASSOCIATING_RETRY; - - queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, IEEE80211_SOFTMAC_ASSOC_RETRY_TIME); - - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static void ieee80211_associate_abort_cb(unsigned long dev) -{ - ieee80211_associate_abort((struct ieee80211_device *) dev); -} - -static void ieee80211_associate_step1(struct ieee80211_device *ieee) -{ - struct ieee80211_network *beacon = &ieee->current_network; - struct sk_buff *skb; - - IEEE80211_DEBUG_MGMT("Stopping scan\n"); - ieee->softmac_stats.tx_auth_rq++; - skb = ieee80211_authentication_req(beacon, ieee, 0); - if (!skb) { - ieee80211_associate_abort(ieee); - } else { - ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING; - IEEE80211_DEBUG_MGMT("Sending authentication request\n"); - softmac_mgmt_xmit(skb, ieee); - /* BUGON when you try to add_timer twice, using mod_timer may - * be better. - */ - if (!timer_pending(&ieee->associate_timer)) { - ieee->associate_timer.expires = jiffies + (HZ / 2); - add_timer(&ieee->associate_timer); - } - /* If call dev_kfree_skb_any,a warning will ocur.... - * KERNEL: assertion (!atomic_read(&skb->users)) failed at - * net/core/dev.c (1708) - */ - } -} - -static void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, - int chlen) -{ - u8 *c; - struct sk_buff *skb; - struct ieee80211_network *beacon = &ieee->current_network; - del_timer_sync(&ieee->associate_timer); - ieee->associate_seq++; - ieee->softmac_stats.tx_auth_rq++; - - skb = ieee80211_authentication_req(beacon, ieee, chlen+2); - if (!skb) - ieee80211_associate_abort(ieee); - else { - c = skb_put(skb, chlen+2); - *(c++) = MFIE_TYPE_CHALLENGE; - *(c++) = chlen; - memcpy(c, challenge, chlen); - - IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n"); - - ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr)); - - softmac_mgmt_xmit(skb, ieee); - if (!timer_pending(&ieee->associate_timer)) { - ieee->associate_timer.expires = jiffies + (HZ / 2); - add_timer(&ieee->associate_timer); - } - dev_kfree_skb_any(skb); - } - kfree(challenge); -} - -static void ieee80211_associate_step2(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - struct ieee80211_network *beacon = &ieee->current_network; - - del_timer_sync(&ieee->associate_timer); - - IEEE80211_DEBUG_MGMT("Sending association request\n"); - ieee->softmac_stats.tx_ass_rq++; - skb = ieee80211_association_req(beacon, ieee); - if (!skb) - ieee80211_associate_abort(ieee); - else { - softmac_mgmt_xmit(skb, ieee); - if (!timer_pending(&ieee->associate_timer)) { - ieee->associate_timer.expires = jiffies + (HZ / 2); - add_timer(&ieee->associate_timer); - } - } -} - -static void ieee80211_associate_complete_wq(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq); - - printk(KERN_INFO "Associated successfully\n"); - if (ieee80211_is_54g(&ieee->current_network) && - (ieee->modulation & IEEE80211_OFDM_MODULATION)) { - ieee->rate = 540; - printk(KERN_INFO"Using G rates\n"); - } else { - ieee->rate = 110; - printk(KERN_INFO"Using B rates\n"); - } - ieee->link_change(ieee->dev); - notify_wx_assoc_event(ieee); - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - netif_carrier_on(ieee->dev); -} - -static void ieee80211_associate_complete(struct ieee80211_device *ieee) -{ - del_timer_sync(&ieee->associate_timer); - - ieee->state = IEEE80211_LINKED; - IEEE80211_DEBUG_MGMT("Successfully associated\n"); - - queue_work(ieee->wq, &ieee->associate_complete_wq); -} - -static void ieee80211_associate_procedure_wq(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq); - - ieee->sync_scan_hurryup = 1; - down(&ieee->wx_sem); - - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); - - ieee80211_stop_scan(ieee); - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - ieee->associate_seq = 1; - ieee80211_associate_step1(ieee); - - up(&ieee->wx_sem); -} - -inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, - struct ieee80211_network *net) -{ - u8 tmp_ssid[IW_ESSID_MAX_SIZE+1]; - int tmp_ssid_len = 0; - - short apset, ssidset, ssidbroad, apmatch, ssidmatch; - - /* we are interested in new new only if we are not associated - * and we are not associating / authenticating - */ - if (ieee->state != IEEE80211_NOLINK) - return; - - if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS)) - return; - - if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS)) - return; - - if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) { - /* if the user specified the AP MAC, we need also the essid - * This could be obtained by beacons or, if the network does not - * broadcast it, it can be put manually. - */ - apset = ieee->wap_set; - ssidset = ieee->ssid_set; - ssidbroad = !(net->ssid_len == 0 || net->ssid[0] == '\0'); - apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN) == 0); - - if (ieee->current_network.ssid_len != net->ssid_len) - ssidmatch = 0; - else - ssidmatch = (0 == strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len)); - - /* if the user set the AP check if match. - * if the network does not broadcast essid we check the user - * supplied ANY essid - * if the network does broadcast and the user does not set essid - * it is OK - * if the network does broadcast and the user did set essid - * chech if essid match - * (apset && apmatch && ((ssidset && ssidbroad && ssidmatch) || - * (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) || - * if the ap is not set, check that the user set the bssid and - * the network does broadcast and that those two bssid matches - * (!apset && ssidset && ssidbroad && ssidmatch) - */ - if ((apset && apmatch && ((ssidset && ssidbroad && ssidmatch) || - (ssidbroad && !ssidset) || (!ssidbroad && ssidset))) || - (!apset && ssidset && ssidbroad && ssidmatch)) { - /* if the essid is hidden replace it with the - * essid provided by the user. - */ - if (!ssidbroad) { - strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE); - tmp_ssid_len = ieee->current_network.ssid_len; - } - memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network)); - - if (!ssidbroad) { - strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE); - ieee->current_network.ssid_len = tmp_ssid_len; - } - printk(KERN_INFO"Linking with %s: channel is %d\n", ieee->current_network.ssid, ieee->current_network.channel); - - if (ieee->iw_mode == IW_MODE_INFRA) { - ieee->state = IEEE80211_ASSOCIATING; - ieee->beinretry = false; - queue_work(ieee->wq, &ieee->associate_procedure_wq); - } else { - if (ieee80211_is_54g(&ieee->current_network) && - (ieee->modulation & IEEE80211_OFDM_MODULATION)) { - ieee->rate = 540; - printk(KERN_INFO"Using G rates\n"); - } else { - ieee->rate = 110; - printk(KERN_INFO"Using B rates\n"); - } - ieee->state = IEEE80211_LINKED; - ieee->beinretry = false; - } - } - } -} - -void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee) -{ - unsigned long flags; - struct ieee80211_network *target; - - spin_lock_irqsave(&ieee->lock, flags); - list_for_each_entry(target, &ieee->network_list, list) { - /* if the state become different that NOLINK means - * we had found what we are searching for - */ - if (ieee->state != IEEE80211_NOLINK) - break; - - if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies)) - ieee80211_softmac_new_net(ieee, target); - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen) -{ - struct ieee80211_authentication *a; - u8 *t; - if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) { - IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); - return 0xcafe; - } - *challenge = NULL; - a = (struct ieee80211_authentication *) skb->data; - if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) { - t = skb->data + sizeof(struct ieee80211_authentication); - - if (*(t++) == MFIE_TYPE_CHALLENGE) { - *chlen = *(t++); - *challenge = kmemdup(t, *chlen, GFP_ATOMIC); - if (!*challenge) - return -ENOMEM; - } - } - return cpu_to_le16(a->status); -} - -static int auth_rq_parse(struct sk_buff *skb, u8 *dest) -{ - struct ieee80211_authentication *a; - - if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) { - IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n", skb->len); - return -1; - } - a = (struct ieee80211_authentication *) skb->data; - - memcpy(dest, a->header.addr2, ETH_ALEN); - - if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN) - return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; - - return WLAN_STATUS_SUCCESS; -} - -static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, - u8 *src) -{ - u8 *tag; - u8 *skbend; - u8 *ssid = NULL; - u8 ssidlen = 0; - - struct ieee80211_hdr_3addr *header = - (struct ieee80211_hdr_3addr *) skb->data; - - if (skb->len < sizeof(struct ieee80211_hdr_3addr)) - return -1; /* corrupted */ - - memcpy(src, header->addr2, ETH_ALEN); - - skbend = (u8 *)skb->data + skb->len; - - tag = skb->data + sizeof(struct ieee80211_hdr_3addr); - - while (tag+1 < skbend) { - if (*tag == 0) { - ssid = tag+2; - ssidlen = *(tag+1); - break; - } - tag++; /* point to the len field */ - tag = tag + *(tag); /* point to the last data byte of the tag */ - tag++; /* point to the next tag */ - } - - if (ssidlen == 0) - return 1; - - if (!ssid) - return 1; /* ssid not found in tagged param */ - - return (!strncmp(ssid, ieee->current_network.ssid, ssidlen)); - -} - -static int assoc_rq_parse(struct sk_buff *skb, u8 *dest) -{ - struct ieee80211_assoc_request_frame *a; - - if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) - - sizeof(struct ieee80211_info_element))) { - - IEEE80211_DEBUG_MGMT("invalid len in auth request:%d\n", skb->len); - return -1; - } - - a = (struct ieee80211_assoc_request_frame *) skb->data; - - memcpy(dest, a->header.addr2, ETH_ALEN); - - return 0; -} - -static inline u16 assoc_parse(struct sk_buff *skb, int *aid) -{ - struct ieee80211_assoc_response_frame *a; - if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) { - IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); - return 0xcafe; - } - - a = (struct ieee80211_assoc_response_frame *) skb->data; - *aid = le16_to_cpu(a->aid) & 0x3fff; - return le16_to_cpu(a->status); -} - -static inline void ieee80211_rx_probe_rq(struct ieee80211_device *ieee, - struct sk_buff *skb) -{ - u8 dest[ETH_ALEN]; - - ieee->softmac_stats.rx_probe_rq++; - if (probe_rq_parse(ieee, skb, dest)) { - ieee->softmac_stats.tx_probe_rs++; - ieee80211_resp_to_probe(ieee, dest); - } -} - -inline void ieee80211_rx_auth_rq(struct ieee80211_device *ieee, - struct sk_buff *skb) -{ - u8 dest[ETH_ALEN]; - int status; - ieee->softmac_stats.rx_auth_rq++; - - status = auth_rq_parse(skb, dest); - if (status != -1) - ieee80211_resp_to_auth(ieee, status, dest); -} - -inline void -ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb) -{ - - u8 dest[ETH_ALEN]; - - ieee->softmac_stats.rx_ass_rq++; - if (assoc_rq_parse(skb, dest) != -1) - ieee80211_resp_to_assoc_rq(ieee, dest); - - - printk(KERN_INFO"New client associated: %pM\n", dest); -} - -void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr) -{ - struct sk_buff *buf = ieee80211_null_func(ieee, pwr); - - if (buf) - softmac_ps_mgmt_xmit(buf, ieee); -} - -static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, - u32 *time_l) -{ - int timeout = 0; - - u8 dtim; - dtim = ieee->current_network.dtim_data; - - if (!(dtim & IEEE80211_DTIM_VALID)) - return 0; - else - timeout = ieee->current_network.beacon_interval; - - ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID; - - if (dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST) & ieee->ps)) - return 2; - - if (!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))) - return 0; - - if (!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))) - return 0; - - if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) && - (ieee->mgmt_queue_tail != ieee->mgmt_queue_head)) - return 0; - - if (time_l) { - *time_l = ieee->current_network.last_dtim_sta_time[0] - + MSECS((ieee->current_network.beacon_interval)); - } - - if (time_h) { - *time_h = ieee->current_network.last_dtim_sta_time[1]; - if (time_l && *time_l < ieee->current_network.last_dtim_sta_time[0]) - *time_h += 1; - } - - return 1; -} - -static inline void ieee80211_sta_ps(struct ieee80211_device *ieee) -{ - - u32 th, tl; - short sleep; - - unsigned long flags, flags2; - - spin_lock_irqsave(&ieee->lock, flags); - - if ((ieee->ps == IEEE80211_PS_DISABLED || - ieee->iw_mode != IW_MODE_INFRA || - ieee->state != IEEE80211_LINKED)) { - - /* #warning CHECK_LOCK_HERE */ - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - - ieee80211_sta_wakeup(ieee, 1); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - - sleep = ieee80211_sta_ps_sleep(ieee, &th, &tl); - /* 2 wake, 1 sleep, 0 do nothing */ - if (sleep == 0) - goto out; - - if (sleep == 1) { - if (ieee->sta_sleep == 1) - ieee->enter_sleep_state(ieee->dev, th, tl); - - else if (ieee->sta_sleep == 0) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - if (ieee->ps_is_queue_empty(ieee->dev)) { - ieee->sta_sleep = 2; - - ieee->ps_request_tx_ack(ieee->dev); - - ieee80211_sta_ps_send_null_frame(ieee, 1); - - ieee->ps_th = th; - ieee->ps_tl = tl; - } - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - } else if (sleep == 2) { - /* #warning CHECK_LOCK_HERE */ - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - - ieee80211_sta_wakeup(ieee, 1); - - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } -out: - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl) -{ - if (ieee->sta_sleep == 0) { - if (nl) { - ieee->ps_request_tx_ack(ieee->dev); - ieee80211_sta_ps_send_null_frame(ieee, 0); - } - return; - } - - if (ieee->sta_sleep == 1) - ieee->sta_wake_up(ieee->dev); - - ieee->sta_sleep = 0; - - if (nl) { - ieee->ps_request_tx_ack(ieee->dev); - ieee80211_sta_ps_send_null_frame(ieee, 0); - } -} - -void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success) -{ - unsigned long flags, flags2; - - spin_lock_irqsave(&ieee->lock, flags); - if (ieee->sta_sleep == 2) { - /* Null frame with PS bit set */ - if (success) { - ieee->sta_sleep = 1; - ieee->enter_sleep_state(ieee->dev, ieee->ps_th, ieee->ps_tl); - } - /* if the card report not success we can't be sure the AP - * has not RXed so we can't assume the AP believe us awake - */ - } else { - if ((ieee->sta_sleep == 0) && !success) { - spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); - ieee80211_sta_ps_send_null_frame(ieee, 0); - spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); - } - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -inline int ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, - struct sk_buff *skb, - struct ieee80211_rx_stats *rx_stats, - u16 type, u16 stype) -{ - struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data; - u16 errcode; - u8 *challenge = NULL; - int chlen = 0; - int aid = 0; - struct ieee80211_assoc_response_frame *assoc_resp; - struct ieee80211_info_element *info_element; - - if (!ieee->proto_started) - return 0; - - if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED && - ieee->iw_mode == IW_MODE_INFRA && - ieee->state == IEEE80211_LINKED)) - - tasklet_schedule(&ieee->ps_task); - - if (WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_PROBE_RESP && - WLAN_FC_GET_STYPE(header->frame_control) != IEEE80211_STYPE_BEACON) - ieee->last_rx_ps_time = jiffies; - - switch (WLAN_FC_GET_STYPE(header->frame_control)) { - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP: - IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(header->frame_ctl)); - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && - ieee->iw_mode == IW_MODE_INFRA) { - errcode = assoc_parse(skb, &aid); - if (0 == errcode) { - u16 left; - - ieee->state = IEEE80211_LINKED; - ieee->assoc_id = aid; - ieee->softmac_stats.rx_ass_ok++; - /* card type is 8187 */ - if (1 == rx_stats->nic_type) - goto associate_complete; - - assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data; - info_element = &assoc_resp->info_element; - left = skb->len - ((void *)info_element - (void *)assoc_resp); - - while (left >= sizeof(struct ieee80211_info_element_hdr)) { - if (sizeof(struct ieee80211_info_element_hdr) + info_element->len > left) { - printk(KERN_WARNING "[re]associate response error!"); - return 1; - } - switch (info_element->id) { - case MFIE_TYPE_GENERIC: - IEEE80211_DEBUG_SCAN("MFIE_TYPE_GENERIC: %d bytes\n", info_element->len); - if (info_element->len >= 8 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x02 && - info_element->data[4] == 0x01) { - /* Not care about version at present. - * WMM Parameter Element. - */ - memcpy(ieee->current_network.wmm_param, (u8 *)(info_element->data\ - + 8), (info_element->len - 8)); - - if (((ieee->current_network.wmm_info^info_element->data[6])& \ - 0x0f) || (!ieee->init_wmmparam_flag)) { - /* refresh parameter element for current network - * update the register parameter for hardware. - */ - ieee->init_wmmparam_flag = 1; - queue_work(ieee->wq, &ieee->wmm_param_update_wq); - } - /* update info_element for current network */ - ieee->current_network.wmm_info = info_element->data[6]; - } - break; - default: - /* nothing to do at present!!! */ - break; - } - - left -= sizeof(struct ieee80211_info_element_hdr) + - info_element->len; - info_element = (struct ieee80211_info_element *) - &info_element->data[info_element->len]; - } - /* legacy AP, reset the AC_xx_param register */ - if (!ieee->init_wmmparam_flag) { - queue_work(ieee->wq, &ieee->wmm_param_update_wq); - ieee->init_wmmparam_flag = 1; /* indicate AC_xx_param upated since last associate */ - } -associate_complete: - ieee80211_associate_complete(ieee); - } else { - ieee->softmac_stats.rx_ass_err++; - IEEE80211_DEBUG_MGMT( - "Association response status code 0x%x\n", - errcode); - ieee80211_associate_abort(ieee); - } - } - break; - case IEEE80211_STYPE_ASSOC_REQ: - case IEEE80211_STYPE_REASSOC_REQ: - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - ieee->iw_mode == IW_MODE_MASTER) - - ieee80211_rx_assoc_rq(ieee, skb); - break; - case IEEE80211_STYPE_AUTH: - if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) { - if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING && - ieee->iw_mode == IW_MODE_INFRA){ - IEEE80211_DEBUG_MGMT("Received authentication response"); - - errcode = auth_parse(skb, &challenge, &chlen); - if (0 == errcode) { - if (ieee->open_wep || !challenge) { - ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED; - ieee->softmac_stats.rx_auth_rs_ok++; - - ieee80211_associate_step2(ieee); - } else { - ieee80211_rtl_auth_challenge(ieee, challenge, chlen); - } - } else { - ieee->softmac_stats.rx_auth_rs_err++; - IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x", errcode); - ieee80211_associate_abort(ieee); - } - - } else if (ieee->iw_mode == IW_MODE_MASTER) { - ieee80211_rx_auth_rq(ieee, skb); - } - } - break; - case IEEE80211_STYPE_PROBE_REQ: - if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && - ((ieee->iw_mode == IW_MODE_ADHOC || - ieee->iw_mode == IW_MODE_MASTER) && - ieee->state == IEEE80211_LINKED)) - - ieee80211_rx_probe_rq(ieee, skb); - break; - case IEEE80211_STYPE_DISASSOC: - case IEEE80211_STYPE_DEAUTH: - /* FIXME for now repeat all the association procedure - * both for disassociation and deauthentication - */ - if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && - (ieee->state == IEEE80211_LINKED) && - (ieee->iw_mode == IW_MODE_INFRA) && - (!memcmp(header->addr2, ieee->current_network.bssid, ETH_ALEN))) { - ieee->state = IEEE80211_ASSOCIATING; - ieee->softmac_stats.reassoc++; - - queue_work(ieee->wq, &ieee->associate_procedure_wq); - } - break; - default: - return -1; - break; - } - return 0; -} - -/* following are for a simpler TX queue management. - * Instead of using netif_[stop/wake]_queue the driver - * will uses these two function (plus a reset one), that - * will internally uses the kernel netif_* and takes - * care of the ieee802.11 fragmentation. - * So the driver receives a fragment per time and might - * call the stop function when it want without take care - * to have enough room to TX an entire packet. - * This might be useful if each fragment need it's own - * descriptor, thus just keep a total free memory > than - * the max fragmentation threshold is not enough.. If the - * ieee802.11 stack passed a TXB struct then you needed - * to keep N free descriptors where - * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD - * In this way you need just one and the 802.11 stack - * will take care of buffering fragments and pass them to - * to the driver later, when it wakes the queue. - */ - -void ieee80211_softmac_xmit(struct ieee80211_txb *txb, - struct ieee80211_device *ieee) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&ieee->lock, flags); - - /* called with 2nd parm 0, no tx mgmt lock required */ - ieee80211_sta_wakeup(ieee, 0); - - for (i = 0; i < txb->nr_frags; i++) { - if (ieee->queue_stop) { - ieee->tx_pending.txb = txb; - ieee->tx_pending.frag = i; - goto exit; - } else { - ieee->softmac_data_hard_start_xmit( - txb->fragments[i], - ieee->dev, ieee->rate); - ieee->stats.tx_packets++; - ieee->stats.tx_bytes += txb->fragments[i]->len; - ieee->dev->trans_start = jiffies; - } - } - - ieee80211_txb_free(txb); - - exit: - spin_unlock_irqrestore(&ieee->lock, flags); -} - -/* called with ieee->lock acquired */ -static void ieee80211_resume_tx(struct ieee80211_device *ieee) -{ - int i; - for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) { - - if (ieee->queue_stop) { - ieee->tx_pending.frag = i; - return; - } else { - ieee->softmac_data_hard_start_xmit( - ieee->tx_pending.txb->fragments[i], - ieee->dev, ieee->rate); - ieee->stats.tx_packets++; - ieee->dev->trans_start = jiffies; - } - } - - ieee80211_txb_free(ieee->tx_pending.txb); - ieee->tx_pending.txb = NULL; -} - -void ieee80211_reset_queue(struct ieee80211_device *ieee) -{ - unsigned long flags; - - spin_lock_irqsave(&ieee->lock, flags); - init_mgmt_queue(ieee); - if (ieee->tx_pending.txb) { - ieee80211_txb_free(ieee->tx_pending.txb); - ieee->tx_pending.txb = NULL; - } - ieee->queue_stop = 0; - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) -{ - unsigned long flags; - struct sk_buff *skb; - struct ieee80211_hdr_3addr *header; - - spin_lock_irqsave(&ieee->lock, flags); - if (!ieee->queue_stop) - goto exit; - - ieee->queue_stop = 0; - - if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) { - while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) { - header = (struct ieee80211_hdr_3addr *) skb->data; - - header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate); - dev_kfree_skb_any(skb); - } - } - if (!ieee->queue_stop && ieee->tx_pending.txb) - ieee80211_resume_tx(ieee); - - if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) { - ieee->softmac_stats.swtxawake++; - netif_wake_queue(ieee->dev); - } -exit: - spin_unlock_irqrestore(&ieee->lock, flags); -} - -void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) -{ - if (!netif_queue_stopped(ieee->dev)) { - netif_stop_queue(ieee->dev); - ieee->softmac_stats.swtxstop++; - } - ieee->queue_stop = 1; -} - -inline void ieee80211_randomize_cell(struct ieee80211_device *ieee) -{ - random_ether_addr(ieee->current_network.bssid); -} - -/* called in user context only */ -void ieee80211_start_master_bss(struct ieee80211_device *ieee) -{ - ieee->assoc_id = 1; - - if (ieee->current_network.ssid_len == 0) { - strncpy(ieee->current_network.ssid, - IEEE80211_DEFAULT_TX_ESSID, - IW_ESSID_MAX_SIZE); - - ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); - ieee->ssid_set = 1; - } - - memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN); - - ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->state = IEEE80211_LINKED; - ieee->link_change(ieee->dev); - notify_wx_assoc_event(ieee); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); -} - -static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee) -{ - if (ieee->raw_tx) { - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); - } -} - -static void ieee80211_start_ibss_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq); - - /* iwconfig mode ad-hoc will schedule this and return - * on the other hand this will block further iwconfig SET - * operations because of the wx_sem hold. - * Anyway some most set operations set a flag to speed-up - * (abort) this wq (when syncro scanning) before sleeping - * on the semaphore - */ - - down(&ieee->wx_sem); - - if (ieee->current_network.ssid_len == 0) { - strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID); - ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); - ieee->ssid_set = 1; - } - - /* check if we have this cell in our network list */ - ieee80211_softmac_check_all_nets(ieee); - - if (ieee->state == IEEE80211_NOLINK) - ieee->current_network.channel = 10; - /* if not then the state is not linked. Maybe the user switched to - * ad-hoc mode just after being in monitor mode, or just after - * being very few time in managed mode (so the card have had no - * time to scan all the chans..) or we have just run up the iface - * after setting ad-hoc mode. So we have to give another try.. - * Here, in ibss mode, should be safe to do this without extra care - * (in bss mode we had to make sure no-one tried to associate when - * we had just checked the ieee->state and we was going to start the - * scan) because in ibss mode the ieee80211_new_net function, when - * finds a good net, just set the ieee->state to IEEE80211_LINKED, - * so, at worst, we waste a bit of time to initiate an unneeded syncro - * scan, that will stop at the first round because it sees the state - * associated. - */ - if (ieee->state == IEEE80211_NOLINK) - ieee80211_start_scan_syncro(ieee); - - /* the network definitively is not here.. create a new cell */ - if (ieee->state == IEEE80211_NOLINK) { - printk("creating new IBSS cell\n"); - if (!ieee->wap_set) - ieee80211_randomize_cell(ieee); - - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - ieee->current_network.rates_len = 4; - - ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - - } else - ieee->current_network.rates_len = 0; - - if (ieee->modulation & IEEE80211_OFDM_MODULATION) { - ieee->current_network.rates_ex_len = 8; - - ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; - ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; - ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; - ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; - ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; - ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; - ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; - ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; - - ieee->rate = 540; - } else { - ieee->current_network.rates_ex_len = 0; - ieee->rate = 110; - } - - /* By default, WMM function will be disabled in IBSS mode */ - ieee->current_network.QoS_Enable = 0; - - ieee->current_network.atim_window = 0; - ieee->current_network.capability = WLAN_CAPABILITY_IBSS; - if (ieee->short_slot) - ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT; - } - - ieee->state = IEEE80211_LINKED; - ieee->set_chan(ieee->dev, ieee->current_network.channel); - ieee->link_change(ieee->dev); - - notify_wx_assoc_event(ieee); - - ieee80211_start_send_beacons(ieee); - printk(KERN_WARNING "after sending beacon packet!\n"); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); - - up(&ieee->wx_sem); -} - -inline void ieee80211_start_ibss(struct ieee80211_device *ieee) -{ - queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 100); -} - -/* this is called only in user context, with wx_sem held */ -void ieee80211_start_bss(struct ieee80211_device *ieee) -{ - unsigned long flags; - /* Ref: 802.11d 11.1.3.3 - * STA shall not start a BSS unless properly formed Beacon frame - * including a Country IE. - */ - if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) { - if (!ieee->bGlobalDomain) - return; - } - /* check if we have already found the net we are interested in (if any). - * if not (we are disassociated and we are not - * in associating / authenticating phase) start the background scanning. - */ - ieee80211_softmac_check_all_nets(ieee); - - /* ensure no-one start an associating process (thus setting - * the ieee->state to ieee80211_ASSOCIATING) while we - * have just cheked it and we are going to enable scan. - * The ieee80211_new_net function is always called with - * lock held (from both ieee80211_softmac_check_all_nets and - * the rx path), so we cannot be in the middle of such function - */ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->state == IEEE80211_NOLINK) { - ieee->actscanning = true; - ieee80211_rtl_start_scan(ieee); - } - spin_unlock_irqrestore(&ieee->lock, flags); -} - -/* called only in userspace context */ -void ieee80211_disassociate(struct ieee80211_device *ieee) -{ - netif_carrier_off(ieee->dev); - - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) - ieee80211_reset_queue(ieee); - - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); - - if (IS_DOT11D_ENABLE(ieee)) - Dot11d_Reset(ieee); - - ieee->link_change(ieee->dev); - if (ieee->state == IEEE80211_LINKED) - notify_wx_assoc_event(ieee); - ieee->state = IEEE80211_NOLINK; - -} -static void ieee80211_associate_retry_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq); - unsigned long flags; - down(&ieee->wx_sem); - if (!ieee->proto_started) - goto exit; - if (ieee->state != IEEE80211_ASSOCIATING_RETRY) - goto exit; - /* until we do not set the state to IEEE80211_NOLINK - * there are no possibility to have someone else trying - * to start an association procedure (we get here with - * ieee->state = IEEE80211_ASSOCIATING). - * When we set the state to IEEE80211_NOLINK it is possible - * that the RX path run an attempt to associate, but - * both ieee80211_softmac_check_all_nets and the - * RX path works with ieee->lock held so there are no - * problems. If we are still disassociated then start a scan. - * the lock here is necessary to ensure no one try to start - * an association procedure when we have just checked the - * state and we are going to start the scan. - */ - ieee->state = IEEE80211_NOLINK; - ieee->beinretry = true; - ieee80211_softmac_check_all_nets(ieee); - - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->state == IEEE80211_NOLINK) { - ieee->beinretry = false; - ieee->actscanning = true; - ieee80211_rtl_start_scan(ieee); - } - if (ieee->state == IEEE80211_NOLINK) - notify_wx_assoc_event(ieee); - spin_unlock_irqrestore(&ieee->lock, flags); - -exit: - up(&ieee->wx_sem); -} - -struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee) -{ - u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - struct sk_buff *skb = NULL; - struct ieee80211_probe_response *b; - - skb = ieee80211_probe_resp(ieee, broadcast_addr); - if (!skb) - return NULL; - - b = (struct ieee80211_probe_response *) skb->data; - b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON); - - return skb; -} - -struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee) -{ - struct sk_buff *skb; - struct ieee80211_probe_response *b; - - skb = ieee80211_get_beacon_(ieee); - if (!skb) - return NULL; - - b = (struct ieee80211_probe_response *) skb->data; - b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4); - - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - - return skb; -} - -void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee) -{ - ieee->sync_scan_hurryup = 1; - down(&ieee->wx_sem); - ieee80211_stop_protocol(ieee); - up(&ieee->wx_sem); -} - -void ieee80211_stop_protocol(struct ieee80211_device *ieee) -{ - if (!ieee->proto_started) - return; - - ieee->proto_started = 0; - - ieee80211_stop_send_beacons(ieee); - if ((ieee->iw_mode == IW_MODE_INFRA) && (ieee->state == IEEE80211_LINKED)) - SendDisassociation(ieee, NULL, WLAN_REASON_DISASSOC_STA_HAS_LEFT); - - del_timer_sync(&ieee->associate_timer); - cancel_delayed_work(&ieee->associate_retry_wq); - cancel_delayed_work(&ieee->start_ibss_wq); - ieee80211_stop_scan(ieee); - - ieee80211_disassociate(ieee); -} - -void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee) -{ - ieee->sync_scan_hurryup = 0; - down(&ieee->wx_sem); - ieee80211_start_protocol(ieee); - up(&ieee->wx_sem); -} - -void ieee80211_start_protocol(struct ieee80211_device *ieee) -{ - short ch = 0; - int i = 0; - - if (ieee->proto_started) - return; - - ieee->proto_started = 1; - - if (ieee->current_network.channel == 0) { - do { - ch++; - if (ch > MAX_CHANNEL_NUMBER) - return; /* no channel found */ - - } while (!GET_DOT11D_INFO(ieee)->channel_map[ch]); - - ieee->current_network.channel = ch; - } - - if (ieee->current_network.beacon_interval == 0) - ieee->current_network.beacon_interval = 100; - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - for (i = 0; i < 17; i++) { - ieee->last_rxseq_num[i] = -1; - ieee->last_rxfrag_num[i] = -1; - ieee->last_packet_time[i] = 0; - } - - ieee->init_wmmparam_flag = 0; /* reinitialize AC_xx_PARAM registers. */ - - /* if the user set the MAC of the ad-hoc cell and then - * switch to managed mode, shall we make sure that association - * attempts does not fail just because the user provide the essid - * and the nic is still checking for the AP MAC ?? - */ - switch (ieee->iw_mode) { - case IW_MODE_AUTO: - ieee->iw_mode = IW_MODE_INFRA; - /* not set break here intentionly */ - case IW_MODE_INFRA: - ieee80211_start_bss(ieee); - break; - - case IW_MODE_ADHOC: - ieee80211_start_ibss(ieee); - break; - - case IW_MODE_MASTER: - ieee80211_start_master_bss(ieee); - break; - - case IW_MODE_MONITOR: - ieee80211_start_monitor_mode(ieee); - break; - - default: - ieee->iw_mode = IW_MODE_INFRA; - ieee80211_start_bss(ieee); - break; - } -} - -#define DRV_NAME "Ieee80211" -void ieee80211_softmac_init(struct ieee80211_device *ieee) -{ - int i; - memset(&ieee->current_network, 0, sizeof(struct ieee80211_network)); - - ieee->state = IEEE80211_NOLINK; - ieee->sync_scan_hurryup = 0; - for (i = 0; i < 5; i++) - ieee->seq_ctrl[i] = 0; - - ieee->assoc_id = 0; - ieee->queue_stop = 0; - ieee->scanning = 0; - ieee->softmac_features = 0; /* so IEEE2100-like driver are happy */ - ieee->wap_set = 0; - ieee->ssid_set = 0; - ieee->proto_started = 0; - ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE; - ieee->rate = 3; - ieee->ps = IEEE80211_PS_MBCAST|IEEE80211_PS_UNICAST; - ieee->sta_sleep = 0; - ieee->bInactivePs = false; - ieee->actscanning = false; - ieee->ListenInterval = 2; - ieee->NumRxDataInPeriod = 0; - ieee->NumRxBcnInPeriod = 0; - ieee->NumRxOkTotal = 0; - ieee->NumRxUnicast = 0; /* for keep alive */ - ieee->beinretry = false; - ieee->bHwRadioOff = false; - - init_mgmt_queue(ieee); - - ieee->tx_pending.txb = NULL; - - init_timer(&ieee->associate_timer); - ieee->associate_timer.data = (unsigned long)ieee; - ieee->associate_timer.function = ieee80211_associate_abort_cb; - - init_timer(&ieee->beacon_timer); - ieee->beacon_timer.data = (unsigned long) ieee; - ieee->beacon_timer.function = ieee80211_send_beacon_cb; - - ieee->wq = create_workqueue(DRV_NAME); - - INIT_DELAYED_WORK(&ieee->start_ibss_wq, (void *) ieee80211_start_ibss_wq); - INIT_WORK(&ieee->associate_complete_wq, (void *) ieee80211_associate_complete_wq); - INIT_WORK(&ieee->associate_procedure_wq, (void *) ieee80211_associate_procedure_wq); - INIT_DELAYED_WORK(&ieee->softmac_scan_wq, (void *) ieee80211_softmac_scan_wq); - INIT_DELAYED_WORK(&ieee->associate_retry_wq, (void *) ieee80211_associate_retry_wq); - INIT_WORK(&ieee->wx_sync_scan_wq, (void *) ieee80211_wx_sync_scan_wq); - - sema_init(&ieee->wx_sem, 1); - sema_init(&ieee->scan_sem, 1); - - spin_lock_init(&ieee->mgmt_tx_lock); - spin_lock_init(&ieee->beacon_lock); - - tasklet_init(&ieee->ps_task, - (void(*)(unsigned long)) ieee80211_sta_ps, - (unsigned long)ieee); - ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC); -} - -void ieee80211_softmac_free(struct ieee80211_device *ieee) -{ - down(&ieee->wx_sem); - - del_timer_sync(&ieee->associate_timer); - cancel_delayed_work(&ieee->associate_retry_wq); - - /* add for RF power on power of */ - cancel_delayed_work(&ieee->GPIOChangeRFWorkItem); - - destroy_workqueue(ieee->wq); - kfree(ieee->pDot11dInfo); - up(&ieee->wx_sem); -} - -/* Start of WPA code. This is stolen from the ipw2200 driver */ -static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value) -{ - /* This is called when wpa_supplicant loads and closes the driver - * interface. */ - printk("%s WPA\n", value ? "enabling" : "disabling"); - ieee->wpa_enabled = value; - return 0; -} - -static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, - int wpa_ie_len) -{ - /* make sure WPA is enabled */ - ieee80211_wpa_enable(ieee, 1); - - ieee80211_disassociate(ieee); -} - -static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, - int reason) -{ - int ret = 0; - - switch (command) { - case IEEE_MLME_STA_DEAUTH: - /* silently ignore */ - break; - - case IEEE_MLME_STA_DISASSOC: - ieee80211_disassociate(ieee); - break; - - default: - printk("Unknown MLME request: %d\n", command); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee, - struct ieee_param *param, int plen) -{ - u8 *buf; - - if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || - (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) - return -EINVAL; - - if (param->u.wpa_ie.len) { - buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len, - GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = param->u.wpa_ie.len; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - } - - ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len); - return 0; -} - -#define AUTH_ALG_OPEN_SYSTEM 0x1 -#define AUTH_ALG_SHARED_KEY 0x2 - -static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value) -{ - struct ieee80211_security sec = { - .flags = SEC_AUTH_MODE, - }; - int ret = 0; - - if (value & AUTH_ALG_SHARED_KEY) { - sec.auth_mode = WLAN_AUTH_SHARED_KEY; - ieee->open_wep = 0; - } else { - sec.auth_mode = WLAN_AUTH_OPEN; - ieee->open_wep = 1; - } - - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - else - ret = -EOPNOTSUPP; - - return ret; -} - -static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, - u32 value) -{ - int ret = 0; - unsigned long flags; - - switch (name) { - case IEEE_PARAM_WPA_ENABLED: - ret = ieee80211_wpa_enable(ieee, value); - break; - - case IEEE_PARAM_TKIP_COUNTERMEASURES: - ieee->tkip_countermeasures = value; - break; - - case IEEE_PARAM_DROP_UNENCRYPTED: { - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - struct ieee80211_security sec = { - .flags = SEC_ENABLED, - .enabled = value, - }; - ieee->drop_unencrypted = value; - /* We only change SEC_LEVEL for open mode. Others - * are set by ipw_wpa_set_encryption. - */ - if (!value) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_0; - } else { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - break; - } - - case IEEE_PARAM_PRIVACY_INVOKED: - ieee->privacy_invoked = value; - break; - case IEEE_PARAM_AUTH_ALGS: - ret = ieee80211_wpa_set_auth_algs(ieee, value); - break; - case IEEE_PARAM_IEEE_802_1X: - ieee->ieee802_1x = value; - break; - case IEEE_PARAM_WPAX_SELECT: - spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags); - ieee->wpax_type_set = 1; - ieee->wpax_type_notify = value; - spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags); - break; - default: - printk("Unknown WPA param: %d\n", name); - ret = -EOPNOTSUPP; - } - - return ret; -} - -/* implementation borrowed from hostap driver */ - -static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, - struct ieee_param *param, int param_len) -{ - int ret = 0; - - struct ieee80211_crypto_ops *ops; - struct ieee80211_crypt_data **crypt; - - struct ieee80211_security sec = { - .flags = 0, - }; - - param->u.crypt.err = 0; - param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - if (param_len != - (int) ((char *) param->u.crypt.key - (char *) param) + - param->u.crypt.key_len) { - printk("Len mismatch %d, %d\n", param_len, - param->u.crypt.key_len); - return -EINVAL; - } - if (is_broadcast_ether_addr(param->sta_addr)) { - if (param->u.crypt.idx >= WEP_KEYS) - return -EINVAL; - crypt = &ieee->crypt[param->u.crypt.idx]; - } else { - return -EINVAL; - } - - if (strcmp(param->u.crypt.alg, "none") == 0) { - if (crypt) { - sec.enabled = 0; - /* FIXME FIXME */ - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL; - ieee80211_crypt_delayed_deinit(ieee, crypt); - } - goto done; - } - sec.enabled = 1; - /* FIXME FIXME */ - sec.flags |= SEC_ENABLED; - - /* IPW HW cannot build TKIP MIC, host decryption still needed. */ - if (!(ieee->host_encrypt || ieee->host_decrypt) && - strcmp(param->u.crypt.alg, "TKIP")) - goto skip_host_crypt; - - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) - ops = ieee80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL) { - printk("unknown crypto alg '%s'\n", param->u.crypt.alg); - param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; - ret = -EINVAL; - goto done; - } - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct ieee80211_crypt_data *new_crypt; - - ieee80211_crypt_delayed_deinit(ieee, crypt); - - new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); - new_crypt->ops = ops; - if (new_crypt->ops) - new_crypt->priv = - new_crypt->ops->init(param->u.crypt.idx); - - if (new_crypt->priv == NULL) { - kfree(new_crypt); - param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED; - ret = -EINVAL; - goto done; - } - - *crypt = new_crypt; - } - - if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(param->u.crypt.key, - param->u.crypt.key_len, param->u.crypt.seq, - (*crypt)->priv) < 0) { - printk("key setting failed\n"); - param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED; - ret = -EINVAL; - goto done; - } - - skip_host_crypt: - if (param->u.crypt.set_tx) { - ieee->tx_keyidx = param->u.crypt.idx; - sec.active_key = param->u.crypt.idx; - sec.flags |= SEC_ACTIVE_KEY; - } else - sec.flags &= ~SEC_ACTIVE_KEY; - - if (param->u.crypt.alg != NULL) { - memcpy(sec.keys[param->u.crypt.idx], - param->u.crypt.key, - param->u.crypt.key_len); - sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; - sec.flags |= (1 << param->u.crypt.idx); - - if (strcmp(param->u.crypt.alg, "WEP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_2; - } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_3; - } - } - done: - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - - /* Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && - ieee->reset_port(ieee->dev)) { - printk("reset_port failed\n"); - param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED; - return -EINVAL; - } - - return ret; -} - -int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, - struct iw_point *p) -{ - struct ieee_param *param; - int ret = 0; - - down(&ieee->wx_sem); - - if (p->length < sizeof(struct ieee_param) || !p->pointer) { - ret = -EINVAL; - goto out; - } - - param = memdup_user(p->pointer, p->length); - if (IS_ERR(param)) { - ret = PTR_ERR(param); - goto out; - } - - switch (param->cmd) { - case IEEE_CMD_SET_WPA_PARAM: - ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name, - param->u.wpa_param.value); - break; - case IEEE_CMD_SET_WPA_IE: - ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length); - break; - case IEEE_CMD_SET_ENCRYPTION: - ret = ieee80211_wpa_set_encryption(ieee, param, p->length); - break; - case IEEE_CMD_MLME: - ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command, - param->u.mlme.reason_code); - break; - default: - printk("Unknown WPA supplicant request: %d\n", param->cmd); - ret = -EOPNOTSUPP; - break; - } - - if (ret == 0 && copy_to_user(p->pointer, param, p->length)) - ret = -EFAULT; - - kfree(param); -out: - up(&ieee->wx_sem); - - return ret; -} - -void notify_wx_assoc_event(struct ieee80211_device *ieee) -{ - union iwreq_data wrqu; - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - if (ieee->state == IEEE80211_LINKED) - memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN); - else - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL); -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c deleted file mode 100644 index 46f35644126c3a..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac_wx.c +++ /dev/null @@ -1,567 +0,0 @@ -/* IEEE 802.11 SoftMAC layer - * Copyright (c) 2005 Andrea Merello - * - * Mostly extracted from the rtl8180-sa2400 driver for the - * in-kernel generic ieee802.11 stack. - * - * Some pieces of code might be stolen from ipw2100 driver - * copyright of who own it's copyright ;-) - * - * PS wx handler mostly stolen from hostap, copyright who - * own it's copyright ;-) - * - * released under the GPL - */ - - -#include - -#include "ieee80211.h" - -/* FIXME: add A freqs */ - -const long ieee80211_wlan_frequencies[] = { - 2412, 2417, 2422, 2427, - 2432, 2437, 2442, 2447, - 2452, 2457, 2462, 2467, - 2472, 2484 -}; - - -int ieee80211_wx_set_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - int ret; - struct iw_freq *fwrq = &wrqu->freq; -// printk("in %s\n",__func__); - down(&ieee->wx_sem); - - if (ieee->iw_mode == IW_MODE_INFRA) { - ret = -EOPNOTSUPP; - goto out; - } - - /* if setting by freq convert to channel */ - if (fwrq->e == 1) { - if ((fwrq->m >= (int) 2.412e8 && - fwrq->m <= (int) 2.487e8)) { - int f = fwrq->m / 100000; - int c = 0; - - while ((c < 14) && (f != ieee80211_wlan_frequencies[c])) - c++; - - /* hack to fall through */ - fwrq->e = 0; - fwrq->m = c + 1; - } - } - - if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1) { - ret = -EOPNOTSUPP; - goto out; - - } else { /* Set the channel */ - - - ieee->current_network.channel = fwrq->m; - ieee->set_chan(ieee->dev, ieee->current_network.channel); - - if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) - if (ieee->state == IEEE80211_LINKED) { - ieee80211_stop_send_beacons(ieee); - ieee80211_start_send_beacons(ieee); - } - } - - ret = 0; -out: - up(&ieee->wx_sem); - return ret; -} - - -int ieee80211_wx_get_freq(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - struct iw_freq *fwrq = &wrqu->freq; - - if (ieee->current_network.channel == 0) - return -1; - - fwrq->m = ieee->current_network.channel; - fwrq->e = 0; - - return 0; -} - -int ieee80211_wx_get_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - unsigned long flags; - - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - /* We want avoid to give to the user inconsistent infos*/ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->state != IEEE80211_LINKED && - ieee->state != IEEE80211_LINKED_SCANNING && - ieee->wap_set == 0) - - memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); - else - memcpy(wrqu->ap_addr.sa_data, - ieee->current_network.bssid, ETH_ALEN); - - spin_unlock_irqrestore(&ieee->lock, flags); - - return 0; -} - - -int ieee80211_wx_set_wap(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *awrq, - char *extra) -{ - - int ret = 0; - unsigned long flags; - - short ifup = ieee->proto_started;//dev->flags & IFF_UP; - struct sockaddr *temp = (struct sockaddr *)awrq; - - //printk("=======Set WAP:"); - ieee->sync_scan_hurryup = 1; - - down(&ieee->wx_sem); - /* use ifconfig hw ether */ - if (ieee->iw_mode == IW_MODE_MASTER) { - ret = -1; - goto out; - } - - if (temp->sa_family != ARPHRD_ETHER) { - ret = -EINVAL; - goto out; - } - - if (ifup) - ieee80211_stop_protocol(ieee); - - /* just to avoid to give inconsistent infos in the - * get wx method. not really needed otherwise - */ - spin_lock_irqsave(&ieee->lock, flags); - - memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); - ieee->wap_set = !is_zero_ether_addr(temp->sa_data); - //printk(" %x:%x:%x:%x:%x:%x\n", ieee->current_network.bssid[0],ieee->current_network.bssid[1],ieee->current_network.bssid[2],ieee->current_network.bssid[3],ieee->current_network.bssid[4],ieee->current_network.bssid[5]); - - spin_unlock_irqrestore(&ieee->lock, flags); - - if (ifup) - ieee80211_start_protocol(ieee); - -out: - up(&ieee->wx_sem); - return ret; -} - -int ieee80211_wx_get_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - int len, ret = 0; - unsigned long flags; - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - /* We want avoid to give to the user inconsistent infos*/ - spin_lock_irqsave(&ieee->lock, flags); - - if (ieee->current_network.ssid[0] == '\0' || - ieee->current_network.ssid_len == 0){ - ret = -1; - goto out; - } - - if (ieee->state != IEEE80211_LINKED && - ieee->state != IEEE80211_LINKED_SCANNING && - ieee->ssid_set == 0){ - ret = -1; - goto out; - } - len = ieee->current_network.ssid_len; - wrqu->essid.length = len; - strncpy(b, ieee->current_network.ssid, len); - wrqu->essid.flags = 1; - -out: - spin_unlock_irqrestore(&ieee->lock, flags); - - return ret; - -} - -int ieee80211_wx_set_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - - u32 target_rate = wrqu->bitrate.value; - - //added by lizhaoming for auto mode - if (target_rate == -1) - ieee->rate = 110; - else - ieee->rate = target_rate/100000; - - //FIXME: we might want to limit rate also in management protocols. - return 0; -} - - - -int ieee80211_wx_get_rate(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - - wrqu->bitrate.value = ieee->rate * 100000; - - return 0; -} - -int ieee80211_wx_set_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - - ieee->sync_scan_hurryup = 1; - - down(&ieee->wx_sem); - - if (wrqu->mode == ieee->iw_mode) - goto out; - - if (wrqu->mode == IW_MODE_MONITOR) - ieee->dev->type = ARPHRD_IEEE80211; - else - ieee->dev->type = ARPHRD_ETHER; - - if (!ieee->proto_started) { - ieee->iw_mode = wrqu->mode; - } else { - ieee80211_stop_protocol(ieee); - ieee->iw_mode = wrqu->mode; - ieee80211_start_protocol(ieee); - } - -out: - up(&ieee->wx_sem); - return 0; -} - - -void ieee80211_wx_sync_scan_wq(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq); - short chan; - - chan = ieee->current_network.channel; - - if (ieee->data_hard_stop) - ieee->data_hard_stop(ieee->dev); - - ieee80211_stop_send_beacons(ieee); - - ieee->state = IEEE80211_LINKED_SCANNING; - ieee->link_change(ieee->dev); - - ieee80211_start_scan_syncro(ieee); - - ieee->set_chan(ieee->dev, chan); - - ieee->state = IEEE80211_LINKED; - ieee->link_change(ieee->dev); - - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - if (ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) - ieee80211_start_send_beacons(ieee); - - //YJ,add,080828, In prevent of lossing ping packet during scanning - //ieee80211_sta_ps_send_null_frame(ieee, false); - //YJ,add,080828,end - - up(&ieee->wx_sem); - -} - -int ieee80211_wx_set_scan(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - int ret = 0; - - down(&ieee->wx_sem); - - if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)) { - ret = -1; - goto out; - } - //YJ,add,080828 - //In prevent of lossing ping packet during scanning - //ieee80211_sta_ps_send_null_frame(ieee, true); - //YJ,add,080828,end - - if (ieee->state == IEEE80211_LINKED) { - queue_work(ieee->wq, &ieee->wx_sync_scan_wq); - /* intentionally forget to up sem */ - return 0; - } - -out: - up(&ieee->wx_sem); - return ret; -} - -int ieee80211_wx_set_essid(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *extra) -{ - - int ret = 0, len; - short proto_started; - unsigned long flags; - - ieee->sync_scan_hurryup = 1; - - down(&ieee->wx_sem); - - proto_started = ieee->proto_started; - - if (wrqu->essid.length > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - goto out; - } - - if (ieee->iw_mode == IW_MODE_MONITOR) { - ret = -1; - goto out; - } - - if (proto_started) - ieee80211_stop_protocol(ieee); - - /* this is just to be sure that the GET wx callback - * has consistent infos. not needed otherwise - */ - spin_lock_irqsave(&ieee->lock, flags); - - if (wrqu->essid.flags && wrqu->essid.length) { -//YJ,modified,080819 - len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length) : IW_ESSID_MAX_SIZE; - memset(ieee->current_network.ssid, 0, ieee->current_network.ssid_len); //YJ,add,080819 - strncpy(ieee->current_network.ssid, extra, len); - ieee->current_network.ssid_len = len; - ieee->ssid_set = 1; -//YJ,modified,080819,end - - //YJ,add,080819,for hidden ap - if (len == 0) { - memset(ieee->current_network.bssid, 0, ETH_ALEN); - ieee->current_network.capability = 0; - } - //YJ,add,080819,for hidden ap,end - } else { - ieee->ssid_set = 0; - ieee->current_network.ssid[0] = '\0'; - ieee->current_network.ssid_len = 0; - } - //printk("==========set essid %s!\n",ieee->current_network.ssid); - spin_unlock_irqrestore(&ieee->lock, flags); - - if (proto_started) - ieee80211_start_protocol(ieee); -out: - up(&ieee->wx_sem); - return ret; -} - -int ieee80211_wx_get_mode(struct ieee80211_device *ieee, - struct iw_request_info *a, union iwreq_data *wrqu, - char *b) -{ - - wrqu->mode = ieee->iw_mode; - return 0; -} - -int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - - int *parms = (int *)extra; - int enable = (parms[0] > 0); - short prev = ieee->raw_tx; - - down(&ieee->wx_sem); - - if (enable) - ieee->raw_tx = 1; - else - ieee->raw_tx = 0; - - netdev_info(ieee->dev, "raw TX is %s\n", - ieee->raw_tx ? "enabled" : "disabled"); - - if (ieee->iw_mode == IW_MODE_MONITOR) { - if (prev == 0 && ieee->raw_tx) { - if (ieee->data_hard_resume) - ieee->data_hard_resume(ieee->dev); - - netif_carrier_on(ieee->dev); - } - - if (prev && ieee->raw_tx == 1) - netif_carrier_off(ieee->dev); - } - - up(&ieee->wx_sem); - - return 0; -} - -int ieee80211_wx_get_name(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - strlcpy(wrqu->name, "802.11", IFNAMSIZ); - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - strlcat(wrqu->name, "b", IFNAMSIZ); - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strlcat(wrqu->name, "/g", IFNAMSIZ); - } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strlcat(wrqu->name, "g", IFNAMSIZ); - - if ((ieee->state == IEEE80211_LINKED) || - (ieee->state == IEEE80211_LINKED_SCANNING)) - strlcat(wrqu->name, " link", IFNAMSIZ); - else if (ieee->state != IEEE80211_NOLINK) - strlcat(wrqu->name, " .....", IFNAMSIZ); - - - return 0; -} - - -/* this is mostly stolen from hostap */ -int ieee80211_wx_set_power(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - int ret = 0; - - if ((!ieee->sta_wake_up) || - (!ieee->ps_request_tx_ack) || - (!ieee->enter_sleep_state) || - (!ieee->ps_is_queue_empty)) { - - printk("ERROR. PS mode tried to be use but driver missed a callback\n\n"); - - return -1; - } - - down(&ieee->wx_sem); - - if (wrqu->power.disabled) { - ieee->ps = IEEE80211_PS_DISABLED; - - goto exit; - } - switch (wrqu->power.flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - ieee->ps = IEEE80211_PS_UNICAST; - - break; - case IW_POWER_ALL_R: - ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST; - break; - - case IW_POWER_ON: - ieee->ps = IEEE80211_PS_DISABLED; - break; - - default: - ret = -EINVAL; - goto exit; - } - - if (wrqu->power.flags & IW_POWER_TIMEOUT) { - - ieee->ps_timeout = wrqu->power.value / 1000; - printk("Timeout %d\n", ieee->ps_timeout); - } - - if (wrqu->power.flags & IW_POWER_PERIOD) { - - ret = -EOPNOTSUPP; - goto exit; - //wrq->value / 1024; - - } -exit: - up(&ieee->wx_sem); - return ret; - -} - -/* this is stolen from hostap */ -int ieee80211_wx_get_power(struct ieee80211_device *ieee, - struct iw_request_info *info, union iwreq_data *wrqu, - char *extra) -{ - int ret = 0; - - down(&ieee->wx_sem); - - if (ieee->ps == IEEE80211_PS_DISABLED) { - wrqu->power.disabled = 1; - goto exit; - } - - wrqu->power.disabled = 0; - -// if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - wrqu->power.flags = IW_POWER_TIMEOUT; - wrqu->power.value = ieee->ps_timeout * 1000; -// } else { -// ret = -EOPNOTSUPP; -// goto exit; - //wrqu->power.flags = IW_POWER_PERIOD; - //wrqu->power.value = ieee->current_network.dtim_period * - // ieee->current_network.beacon_interval * 1024; -// } - - - if (ieee->ps & IEEE80211_PS_MBCAST) - wrqu->power.flags |= IW_POWER_ALL_R; - else - wrqu->power.flags |= IW_POWER_UNICAST_R; - -exit: - up(&ieee->wx_sem); - return ret; - -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c deleted file mode 100644 index 0dc5ae414270de..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c +++ /dev/null @@ -1,591 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2003 - 2004 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - James P. Ketrenos - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -****************************************************************************** - - Few modifications for Realtek's Wi-Fi drivers by - Andrea Merello - - A special thanks goes to Realtek for their support ! - -******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ieee80211.h" - - -/* - - -802.11 Data Frame - - -802.11 frame_contorl for data frames - 2 bytes - ,-----------------------------------------------------------------------------------------. -bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | - |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| -val | 0 | 0 | 0 | 1 | x | 0 | 0 | 0 | 1 | 0 | x | x | x | x | x | - |----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|-----|------| -desc | ^-ver-^ | ^type-^ | ^-----subtype-----^ | to |from |more |retry| pwr |more |wep | - | | | x=0 data,x=1 data+ack | DS | DS |frag | | mgm |data | | - '-----------------------------------------------------------------------------------------' - /\ - | -802.11 Data Frame | - ,--------- 'ctrl' expands to >-----------' - | - ,--'---,-------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `--------------------------------------------------| |------' -Total: 28 non-data bytes `----.----' - | - .- 'Frame data' expands to <---------------------------' - | - V - ,---------------------------------------------------. -Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | - |------|------|---------|----------|------|---------| -Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | - | DSAP | SSAP | | | | Packet | - | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | - `-----------------------------------------| | -Total: 8 non-data bytes `----.----' - | - .- 'IP Packet' expands, if WEP enabled, to <--' - | - V - ,-----------------------. -Bytes | 4 | 0-2296 | 4 | - |-----|-----------|-----| -Desc. | IV | Encrypted | ICV | - | | IP Packet | | - `-----------------------' -Total: 8 non-data bytes - - -802.3 Ethernet Data Frame - - ,-----------------------------------------. -Bytes | 6 | 6 | 2 | Variable | 4 | - |-------|-------|------|-----------|------| -Desc. | Dest. | Source| Type | IP Packet | fcs | - | MAC | MAC | | | | - `-----------------------------------------' -Total: 18 non-data bytes - -In the event that fragmentation is required, the incoming payload is split into -N parts of size ieee->fts. The first fragment contains the SNAP header and the -remaining packets are just data. - -If encryption is enabled, each fragment payload size is reduced by enough space -to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) -So if you have 1500 bytes of payload with ieee->fts set to 500 without -encryption it will take 3 frames. With WEP it will take 4 frames as the -payload of each frame is reduced to 492 bytes. - -* SKB visualization -* -* ,- skb->data -* | -* | ETHERNET HEADER ,-<-- PAYLOAD -* | | 14 bytes from skb->data -* | 2 bytes for Type --> ,T. | (sizeof ethhdr) -* | | | | -* |,-Dest.--. ,--Src.---. | | | -* | 6 bytes| | 6 bytes | | | | -* v | | | | | | -* 0 | v 1 | v | v 2 -* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -* ^ | ^ | ^ | -* | | | | | | -* | | | | `T' <---- 2 bytes for Type -* | | | | -* | | '---SNAP--' <-------- 6 bytes for SNAP -* | | -* `-IV--' <-------------------- 4 bytes for IV (WEP) -* -* SNAP HEADER -* -*/ - -static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; -static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; - -static inline int ieee80211_put_snap(u8 *data, u16 h_proto) -{ - struct ieee80211_snap_hdr *snap; - u8 *oui; - - snap = (struct ieee80211_snap_hdr *)data; - snap->dsap = 0xaa; - snap->ssap = 0xaa; - snap->ctrl = 0x03; - - if (h_proto == 0x8137 || h_proto == 0x80f3) - oui = P802_1H_OUI; - else - oui = RFC1042_OUI; - snap->oui[0] = oui[0]; - snap->oui[1] = oui[1]; - snap->oui[2] = oui[2]; - - *(u16 *)(data + SNAP_SIZE) = htons(h_proto); - - return SNAP_SIZE + sizeof(u16); -} - -int ieee80211_encrypt_fragment(struct ieee80211_device *ieee, - struct sk_buff *frag, int hdr_len) -{ - struct ieee80211_crypt_data* crypt = ieee->crypt[ieee->tx_keyidx]; - int res; - - /* - * added to care about null crypt condition, to solve that system hangs - * when shared keys error - */ - if (!crypt || !crypt->ops) - return -1; - -#ifdef CONFIG_IEEE80211_CRYPT_TKIP - struct ieee80211_hdr_4addr *header; - - if (ieee->tkip_countermeasures && - crypt && crypt->ops && strcmp(crypt->ops->name, "TKIP") == 0) { - header = (struct ieee80211_hdr_4addr *)frag->data; - if (net_ratelimit()) { - netdev_dbg(ieee->dev, "TKIP countermeasures: dropped " - "TX packet to %pM\n", header->addr1); - } - return -1; - } -#endif - /* - * To encrypt, frame format is: - * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) - * - * PR: FIXME: Copied from hostap. Check fragmentation/MSDU/MPDU - * encryption. - * - * Host-based IEEE 802.11 fragmentation for TX is not yet supported, so - * call both MSDU and MPDU encryption functions from here. - */ - atomic_inc(&crypt->refcnt); - res = 0; - if (crypt->ops->encrypt_msdu) - res = crypt->ops->encrypt_msdu(frag, hdr_len, crypt->priv); - if (res == 0 && crypt->ops->encrypt_mpdu) - res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); - - atomic_dec(&crypt->refcnt); - if (res < 0) { - netdev_info(ieee->dev, "Encryption failed: len=%d.\n", frag->len); - ieee->ieee_stats.tx_discards++; - return -1; - } - - return 0; -} - - -void ieee80211_txb_free(struct ieee80211_txb *txb) -{ - int i; - if (unlikely(!txb)) - return; - for (i = 0; i < txb->nr_frags; i++) - if (txb->fragments[i]) - dev_kfree_skb_any(txb->fragments[i]); - kfree(txb); -} - -static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size, - gfp_t gfp_mask) -{ - struct ieee80211_txb *txb; - int i; - txb = kmalloc( - sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags), - gfp_mask); - if (!txb) - return NULL; - - memset(txb, 0, sizeof(struct ieee80211_txb)); - txb->nr_frags = nr_frags; - txb->frag_size = txb_size; - - for (i = 0; i < nr_frags; i++) { - txb->fragments[i] = dev_alloc_skb(txb_size); - if (unlikely(!txb->fragments[i])) { - i--; - break; - } - } - if (unlikely(i != nr_frags)) { - while (i >= 0) - dev_kfree_skb_any(txb->fragments[i--]); - kfree(txb); - return NULL; - } - return txb; -} - -/* - * Classify the to-be send data packet - * Need to acquire the sent queue index. - */ -static int ieee80211_classify(struct sk_buff *skb, - struct ieee80211_network *network) -{ - struct ether_header *eh = (struct ether_header *)skb->data; - unsigned int wme_UP = 0; - - if (!network->QoS_Enable) { - skb->priority = 0; - return(wme_UP); - } - - if (eh->ether_type == __constant_htons(ETHERTYPE_IP)) { - const struct iphdr *ih = (struct iphdr *)(skb->data + - sizeof(struct ether_header)); - wme_UP = (ih->tos >> 5)&0x07; - } else if (vlan_tx_tag_present(skb)) {/* vtag packet */ -#ifndef VLAN_PRI_SHIFT -#define VLAN_PRI_SHIFT 13 /* Shift to find VLAN user priority */ -#define VLAN_PRI_MASK 7 /* Mask for user priority bits in VLAN */ -#endif - u32 tag = vlan_tx_tag_get(skb); - wme_UP = (tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; - } else if (ETH_P_PAE == ntohs(((struct ethhdr *)skb->data)->h_proto)) { - wme_UP = 7; - } - - skb->priority = wme_UP; - return(wme_UP); -} - -/* SKBs are added to the ieee->tx_queue. */ -int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct ieee80211_device *ieee = netdev_priv(dev); - struct ieee80211_txb *txb = NULL; - struct ieee80211_hdr_3addrqos *frag_hdr; - int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size; - unsigned long flags; - struct net_device_stats *stats = &ieee->stats; - int ether_type, encrypt; - int bytes, fc, qos_ctl, hdr_len; - struct sk_buff *skb_frag; - struct ieee80211_hdr_3addrqos header = { /* Ensure zero initialized */ - .duration_id = 0, - .seq_ctl = 0, - .qos_ctl = 0 - }; - u8 dest[ETH_ALEN], src[ETH_ALEN]; - - struct ieee80211_crypt_data* crypt; - - spin_lock_irqsave(&ieee->lock, flags); - - /* - * If there is no driver handler to take the TXB, don't bother - * creating it... - */ - if ((!ieee->hard_start_xmit && - !(ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)) || - ((!ieee->softmac_data_hard_start_xmit && - (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)))) { - netdev_warn(ieee->dev, "No xmit handler.\n"); - goto success; - } - - ieee80211_classify(skb,&ieee->current_network); - if (likely(ieee->raw_tx == 0)){ - - if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { - netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len); - goto success; - } - - ether_type = ntohs(((struct ethhdr *)skb->data)->h_proto); - - crypt = ieee->crypt[ieee->tx_keyidx]; - - encrypt = !(ether_type == ETH_P_PAE && ieee->ieee802_1x) && - ieee->host_encrypt && crypt && crypt->ops; - - if (!encrypt && ieee->ieee802_1x && - ieee->drop_unencrypted && ether_type != ETH_P_PAE) { - stats->tx_dropped++; - goto success; - } - - #ifdef CONFIG_IEEE80211_DEBUG - if (crypt && !encrypt && ether_type == ETH_P_PAE) { - struct eapol *eap = (struct eapol *)(skb->data + - sizeof(struct ethhdr) - SNAP_SIZE - sizeof(u16)); - IEEE80211_DEBUG_EAP("TX: IEEE 802.11 EAPOL frame: %s\n", - eap_get_type(eap->type)); - } - #endif - - /* Save source and destination addresses */ - memcpy(&dest, skb->data, ETH_ALEN); - memcpy(&src, skb->data+ETH_ALEN, ETH_ALEN); - - /* Advance the SKB to the start of the payload */ - skb_pull(skb, sizeof(struct ethhdr)); - - /* Determine total amount of storage required for TXB packets */ - bytes = skb->len + SNAP_SIZE + sizeof(u16); - - if (ieee->current_network.QoS_Enable) { - if (encrypt) - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA | - IEEE80211_FCTL_WEP; - else - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; - - } else { - if (encrypt) - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | - IEEE80211_FCTL_WEP; - else - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; - } - - if (ieee->iw_mode == IW_MODE_INFRA) { - fc |= IEEE80211_FCTL_TODS; - /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ - memcpy(&header.addr1, ieee->current_network.bssid, ETH_ALEN); - memcpy(&header.addr2, &src, ETH_ALEN); - memcpy(&header.addr3, &dest, ETH_ALEN); - } else if (ieee->iw_mode == IW_MODE_ADHOC) { - /* - * not From/To DS: Addr1 = DA, Addr2 = SA, - * Addr3 = BSSID - */ - memcpy(&header.addr1, dest, ETH_ALEN); - memcpy(&header.addr2, src, ETH_ALEN); - memcpy(&header.addr3, ieee->current_network.bssid, ETH_ALEN); - } - header.frame_ctl = cpu_to_le16(fc); - - /* - * Determine fragmentation size based on destination (multicast - * and broadcast are not fragmented) - */ - if (is_multicast_ether_addr(header.addr1)) { - frag_size = MAX_FRAG_THRESHOLD; - qos_ctl = QOS_CTL_NOTCONTAIN_ACK; - } else { - /* default:392 */ - frag_size = ieee->fts; - qos_ctl = 0; - } - - if (ieee->current_network.QoS_Enable) { - hdr_len = IEEE80211_3ADDR_LEN + 2; - /* skb->priority is set in the ieee80211_classify() */ - qos_ctl |= skb->priority; - header.qos_ctl = cpu_to_le16(qos_ctl); - } else { - hdr_len = IEEE80211_3ADDR_LEN; - } - - /* - * Determine amount of payload per fragment. Regardless of if - * this stack is providing the full 802.11 header, one will - * eventually be affixed to this fragment -- so we must account - * for it when determining the amount of payload space. - */ - bytes_per_frag = frag_size - hdr_len; - if (ieee->config & - (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) - bytes_per_frag -= IEEE80211_FCS_LEN; - - /* Each fragment may need to have room for encryption pre/postfix */ - if (encrypt) - bytes_per_frag -= crypt->ops->extra_prefix_len + - crypt->ops->extra_postfix_len; - - /* - * Number of fragments is the total bytes_per_frag / - * payload_per_fragment - */ - nr_frags = bytes / bytes_per_frag; - bytes_last_frag = bytes % bytes_per_frag; - if (bytes_last_frag) - nr_frags++; - else - bytes_last_frag = bytes_per_frag; - - /* - * When we allocate the TXB we allocate enough space for the - * reserve and full fragment bytes (bytes_per_frag doesn't - * include prefix, postfix, header, FCS, etc.) - */ - txb = ieee80211_alloc_txb(nr_frags, frag_size, GFP_ATOMIC); - if (unlikely(!txb)) { - netdev_warn(ieee->dev, "Could not allocate TXB\n"); - goto failed; - } - txb->encrypted = encrypt; - txb->payload_size = bytes; - - for (i = 0; i < nr_frags; i++) { - skb_frag = txb->fragments[i]; - skb_frag->priority = UP2AC(skb->priority); - if (encrypt) - skb_reserve(skb_frag, crypt->ops->extra_prefix_len); - - frag_hdr = (struct ieee80211_hdr_3addrqos *)skb_put( - skb_frag, hdr_len); - memcpy(frag_hdr, &header, hdr_len); - - /* - * If this is not the last fragment, then add the MOREFRAGS - * bit to the frame control - */ - if (i != nr_frags - 1) { - frag_hdr->frame_ctl = cpu_to_le16( - fc | IEEE80211_FCTL_MOREFRAGS); - bytes = bytes_per_frag; - - } else { - /* The last fragment takes the remaining length */ - bytes = bytes_last_frag; - } - if (ieee->current_network.QoS_Enable) { - /* - * add 1 only indicate to corresponding seq - * number control 2006/7/12 - */ - frag_hdr->seq_ctl = cpu_to_le16( - ieee->seq_ctrl[UP2AC(skb->priority)+1]<<4 | i); - } else { - frag_hdr->seq_ctl = cpu_to_le16( - ieee->seq_ctrl[0]<<4 | i); - } - - /* Put a SNAP header on the first fragment */ - if (i == 0) { - ieee80211_put_snap( - skb_put(skb_frag, SNAP_SIZE + sizeof(u16)), - ether_type); - bytes -= SNAP_SIZE + sizeof(u16); - } - - memcpy(skb_put(skb_frag, bytes), skb->data, bytes); - - /* Advance the SKB... */ - skb_pull(skb, bytes); - - /* - * Encryption routine will move the header forward in - * order to insert the IV between the header and the - * payload - */ - if (encrypt) - ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len); - if (ieee->config & - (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) - skb_put(skb_frag, 4); - } - /* Advance sequence number in data frame. */ - if (ieee->current_network.QoS_Enable) { - if (ieee->seq_ctrl[UP2AC(skb->priority) + 1] == 0xFFF) - ieee->seq_ctrl[UP2AC(skb->priority) + 1] = 0; - else - ieee->seq_ctrl[UP2AC(skb->priority) + 1]++; - } else { - if (ieee->seq_ctrl[0] == 0xFFF) - ieee->seq_ctrl[0] = 0; - else - ieee->seq_ctrl[0]++; - } - } else { - if (unlikely(skb->len < sizeof(struct ieee80211_hdr_3addr))) { - netdev_warn(ieee->dev, "skb too small (%d).\n", skb->len); - goto success; - } - - txb = ieee80211_alloc_txb(1, skb->len, GFP_ATOMIC); - if (!txb) { - netdev_warn(ieee->dev, "Could not allocate TXB\n"); - goto failed; - } - - txb->encrypted = 0; - txb->payload_size = skb->len; - memcpy(skb_put(txb->fragments[0], skb->len), skb->data, skb->len); - } - - success: - spin_unlock_irqrestore(&ieee->lock, flags); - dev_kfree_skb_any(skb); - if (txb) { - if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) { - ieee80211_softmac_xmit(txb, ieee); - } else { - if ((*ieee->hard_start_xmit)(txb, dev) == 0) { - stats->tx_packets++; - stats->tx_bytes += txb->payload_size; - return NETDEV_TX_OK; - } - ieee80211_txb_free(txb); - } - } - - return NETDEV_TX_OK; - - failed: - spin_unlock_irqrestore(&ieee->lock, flags); - netif_stop_queue(dev); - stats->tx_errors++; - return NETDEV_TX_BUSY; - -} diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c deleted file mode 100644 index 07c3f715a6f597..00000000000000 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c +++ /dev/null @@ -1,713 +0,0 @@ -/* - * Copyright(c) 2004 Intel Corporation. All rights reserved. - * - * Portions of this file are based on the WEP enablement code provided by the - * Host AP project hostap-drivers v0.1.3 - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * James P. Ketrenos - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include -#include -#include -#include -#include - -#include "ieee80211.h" -static const char *ieee80211_modes[] = { - "?", "a", "b", "ab", "g", "ag", "bg", "abg" -}; - -#define MAX_CUSTOM_LEN 64 -static inline char *rtl818x_translate_scan(struct ieee80211_device *ieee, - char *start, char *stop, - struct ieee80211_network *network, - struct iw_request_info *info) -{ - char custom[MAX_CUSTOM_LEN]; - char *p; - struct iw_event iwe; - int i, j; - u8 max_rate, rate; - - /* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - ether_addr_copy(iwe.u.ap_addr.sa_data, network->bssid); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); - - /* Remaining entries will be displayed in the order we provide them */ - - /* Add the ESSID */ - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - if (network->ssid_len == 0) { - iwe.u.data.length = sizeof(""); - start = iwe_stream_add_point(info, start, stop, &iwe, ""); - } else { - iwe.u.data.length = min_t(u8, network->ssid_len, 32); - start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); - } - /* Add the protocol name */ - iwe.cmd = SIOCGIWNAME; - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", ieee80211_modes[network->mode]); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); - - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - if (network->capability & - (WLAN_CAPABILITY_BSS | WLAN_CAPABILITY_IBSS)) { - if (network->capability & WLAN_CAPABILITY_BSS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); - } - - /* Add frequency/channel */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = network->channel; - iwe.u.freq.e = 0; - iwe.u.freq.i = 0; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (network->capability & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, &iwe, network->ssid); - - /* Add basic and extended rates */ - max_rate = 0; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Rates (Mb/s): "); - for (i = 0, j = 0; i < network->rates_len; ) { - if (j < network->rates_ex_len && - ((network->rates_ex[j] & 0x7F) < - (network->rates[i] & 0x7F))) - rate = network->rates_ex[j++] & 0x7F; - else - rate = network->rates[i++] & 0x7F; - if (rate > max_rate) - max_rate = rate; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - } - for (; j < network->rates_ex_len; j++) { - rate = network->rates_ex[j] & 0x7F; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - "%d%s ", rate >> 1, (rate & 1) ? ".5" : ""); - if (rate > max_rate) - max_rate = rate; - } - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.value = max_rate * 500000; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_PARAM_LEN); - - iwe.cmd = IWEVCUSTOM; - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - /* Add quality statistics */ - /* TODO: Fix these values... */ - if (network->stats.signal == 0 || network->stats.rssi == 0) - netdev_info(ieee->dev, "========>signal:%d, rssi:%d\n", - network->stats.signal, network->stats.rssi); - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = network->stats.signalstrength; - iwe.u.qual.level = network->stats.signal; - iwe.u.qual.noise = network->stats.noise; - iwe.u.qual.updated = network->stats.mask & IEEE80211_STATMASK_WEMASK; - if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) - iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; - if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) - iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; - if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) - iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID; - iwe.u.qual.updated = 7; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); - - iwe.cmd = IWEVCUSTOM; - p = custom; - - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - memset(&iwe, 0, sizeof(iwe)); - if (network->wpa_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, network->wpa_ie, network->wpa_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->wpa_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - memset(&iwe, 0, sizeof(iwe)); - if (network->rsn_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, network->rsn_ie, network->rsn_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->rsn_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - /* Add EXTRA: Age to display seconds since last beacon/probe response - * for given network. - */ - iwe.cmd = IWEVCUSTOM; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - " Last beacon: %lums ago", (jiffies - network->last_scanned) / (HZ / 100)); - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - return start; -} - -int ieee80211_wx_get_scan(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ieee80211_network *network; - unsigned long flags; - int err = 0; - char *ev = extra; - char *stop = ev + wrqu->data.length; - int i = 0; - - IEEE80211_DEBUG_WX("Getting scan\n"); - down(&ieee->wx_sem); - spin_lock_irqsave(&ieee->lock, flags); - - if (!ieee->bHwRadioOff) { - list_for_each_entry(network, &ieee->network_list, list) { - i++; - - if ((stop-ev) < 200) { - err = -E2BIG; - break; - } - if (ieee->scan_age == 0 || - time_after(network->last_scanned + ieee->scan_age, jiffies)) { - ev = rtl818x_translate_scan(ieee, ev, stop, network, info); - } else - IEEE80211_DEBUG_SCAN( - "Not showing network '%s (" - "%pM)' due to age (%lums).\n", - escape_essid(network->ssid, - network->ssid_len), - network->bssid, - (jiffies - network->last_scanned) / (HZ / 100)); - } - } - spin_unlock_irqrestore(&ieee->lock, flags); - up(&ieee->wx_sem); - wrqu->data.length = ev - extra; - wrqu->data.flags = 0; - IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i); - - return err; -} - -int ieee80211_wx_set_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &(wrqu->encoding); - struct net_device *dev = ieee->dev; - struct ieee80211_security sec = { - .flags = 0 - }; - int i, key, key_provided, len; - struct ieee80211_crypt_data **crypt; - - IEEE80211_DEBUG_WX("SET_ENCODE\n"); - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - key_provided = 1; - } else { - key_provided = 0; - key = ieee->tx_keyidx; - } - - IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? - "provided" : "default"); - - crypt = &ieee->crypt[key]; - - if (erq->flags & IW_ENCODE_DISABLED) { - if (key_provided && *crypt) { - IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n", - key); - ieee80211_crypt_delayed_deinit(ieee, crypt); - } else - IEEE80211_DEBUG_WX("Disabling encryption.\n"); - - /* Check all the keys to see if any are still configured, - * and if no key index was provided, de-init them all. - */ - for (i = 0; i < WEP_KEYS; i++) { - if (ieee->crypt[i] != NULL) { - if (key_provided) - break; - ieee80211_crypt_delayed_deinit( - ieee, &ieee->crypt[i]); - } - } - - if (i == WEP_KEYS) { - sec.enabled = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL; - } - - goto done; - } - - sec.enabled = 1; - sec.flags |= SEC_ENABLED; - - if (*crypt != NULL && (*crypt)->ops != NULL && - strcmp((*crypt)->ops->name, "WEP") != 0) { - /* changing to use WEP; deinit previously used algorithm - * on this key. - */ - ieee80211_crypt_delayed_deinit(ieee, crypt); - } - - if (*crypt == NULL) { - struct ieee80211_crypt_data *new_crypt; - - /* take WEP into use */ - new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data), - GFP_KERNEL); - if (new_crypt == NULL) - return -ENOMEM; - new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - if (!new_crypt->ops) - new_crypt->ops = ieee80211_get_crypto_ops("WEP"); - - if (new_crypt->ops) - new_crypt->priv = new_crypt->ops->init(key); - - if (!new_crypt->ops || !new_crypt->priv) { - kfree(new_crypt); - new_crypt = NULL; - - netdev_warn(ieee->dev, - "could not initialize WEP: load module ieee80211_crypt_wep\n"); - return -EOPNOTSUPP; - } - *crypt = new_crypt; - } - - /* If a new key was provided, set it up */ - if (erq->length > 0) { - len = erq->length <= 5 ? 5 : 13; - memcpy(sec.keys[key], keybuf, erq->length); - if (len > erq->length) - memset(sec.keys[key] + erq->length, 0, - len - erq->length); - IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", - key, escape_essid(sec.keys[key], len), - erq->length, len); - sec.key_sizes[key] = len; - (*crypt)->ops->set_key(sec.keys[key], len, NULL, - (*crypt)->priv); - sec.flags |= (1 << key); - /* This ensures a key will be activated if no key is - * explicitly set. - */ - if (key == sec.active_key) - sec.flags |= SEC_ACTIVE_KEY; - ieee->tx_keyidx = key; - } else { - len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, - NULL, (*crypt)->priv); - if (len == 0) { - /* Set a default key of all 0 */ - IEEE80211_DEBUG_WX("Setting key %d to all zero.\n", - key); - memset(sec.keys[key], 0, 13); - (*crypt)->ops->set_key(sec.keys[key], 13, NULL, - (*crypt)->priv); - sec.key_sizes[key] = 13; - sec.flags |= (1 << key); - } - - /* No key data - just set the default TX key index */ - if (key_provided) { - IEEE80211_DEBUG_WX( - "Setting key %d to default Tx key.\n", key); - ieee->tx_keyidx = key; - sec.active_key = key; - sec.flags |= SEC_ACTIVE_KEY; - } - } - - done: - ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); - sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; - sec.flags |= SEC_AUTH_MODE; - IEEE80211_DEBUG_WX("Auth: %s\n", sec.auth_mode == WLAN_AUTH_OPEN ? - "OPEN" : "SHARED KEY"); - - /* For now we just support WEP, so only set that security level... - * TODO: When WPA is added this is one place that needs to change - */ - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ - - if (ieee->set_security) - ieee->set_security(dev, &sec); - - /* Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. - */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - netdev_dbg(ieee->dev, "reset_port failed\n"); - return -EINVAL; - } - return 0; -} - -int ieee80211_wx_get_encode(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &(wrqu->encoding); - int len, key; - struct ieee80211_crypt_data *crypt; - - IEEE80211_DEBUG_WX("GET_ENCODE\n"); - - if (ieee->iw_mode == IW_MODE_MONITOR) - return -1; - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - } else - key = ieee->tx_keyidx; - - crypt = ieee->crypt[key]; - erq->flags = key + 1; - - if (crypt == NULL || crypt->ops == NULL) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - - if (strcmp(crypt->ops->name, "WEP") != 0) { - /* only WEP is supported with wireless extensions, so just - * report that encryption is used. - */ - erq->length = 0; - erq->flags |= IW_ENCODE_ENABLED; - return 0; - } - - len = crypt->ops->get_key(keybuf, WEP_KEY_LEN, NULL, crypt->priv); - erq->length = (len >= 0 ? len : 0); - - erq->flags |= IW_ENCODE_ENABLED; - - if (ieee->open_wep) - erq->flags |= IW_ENCODE_OPEN; - else - erq->flags |= IW_ENCODE_RESTRICTED; - - return 0; -} - -int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct net_device *dev = ieee->dev; - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int i, idx, ret = 0; - int group_key = 0; - const char *alg; - struct ieee80211_crypto_ops *ops; - struct ieee80211_crypt_data **crypt; - - struct ieee80211_security sec = { - .flags = 0, - }; - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (idx < 1 || idx > WEP_KEYS) - return -EINVAL; - idx--; - } else - idx = ieee->tx_keyidx; - - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - crypt = &ieee->crypt[idx]; - group_key = 1; - } else { - /* some Cisco APs use idx>0 for unicast in dynamic WEP */ - if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) - return -EINVAL; - if (ieee->iw_mode == IW_MODE_INFRA) - crypt = &ieee->crypt[idx]; - else - return -EINVAL; - } - - sec.flags |= SEC_ENABLED; - if ((encoding->flags & IW_ENCODE_DISABLED) || - ext->alg == IW_ENCODE_ALG_NONE) { - if (*crypt) - ieee80211_crypt_delayed_deinit(ieee, crypt); - - for (i = 0; i < WEP_KEYS; i++) - if (ieee->crypt[i] != NULL) - break; - - if (i == WEP_KEYS) { - sec.enabled = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_LEVEL; - } - goto done; - } - - sec.enabled = 1; - - switch (ext->alg) { - case IW_ENCODE_ALG_WEP: - alg = "WEP"; - break; - case IW_ENCODE_ALG_TKIP: - alg = "TKIP"; - break; - case IW_ENCODE_ALG_CCMP: - alg = "CCMP"; - break; - default: - IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", - dev->name, ext->alg); - ret = -EINVAL; - goto done; - } - - ops = ieee80211_get_crypto_ops(alg); - if (ops == NULL) - ops = ieee80211_get_crypto_ops(alg); - if (ops == NULL) { - IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n", - dev->name, ext->alg); - netdev_err(ieee->dev, "========>unknown crypto alg %d\n", - ext->alg); - ret = -EINVAL; - goto done; - } - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct ieee80211_crypt_data *new_crypt; - - ieee80211_crypt_delayed_deinit(ieee, crypt); - - new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - new_crypt->ops = ops; - if (new_crypt->ops) - new_crypt->priv = new_crypt->ops->init(idx); - if (new_crypt->priv == NULL) { - kfree(new_crypt); - ret = -EINVAL; - goto done; - } - *crypt = new_crypt; - - } - - if (ext->key_len > 0 && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, - (*crypt)->priv) < 0) { - IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name); - netdev_err(ieee->dev, "key setting failed\n"); - ret = -EINVAL; - goto done; - } -#if 1 - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - ieee->tx_keyidx = idx; - sec.active_key = idx; - sec.flags |= SEC_ACTIVE_KEY; - } - - if (ext->alg != IW_ENCODE_ALG_NONE) { - memcpy(sec.keys[idx], ext->key, ext->key_len); - sec.key_sizes[idx] = ext->key_len; - sec.flags |= (1 << idx); - if (ext->alg == IW_ENCODE_ALG_WEP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } else if (ext->alg == IW_ENCODE_ALG_TKIP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_2; - } else if (ext->alg == IW_ENCODE_ALG_CCMP) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_3; - } - /* Don't set sec level for group keys. */ - if (group_key) - sec.flags &= ~SEC_LEVEL; - } -#endif -done: - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name); - return -EINVAL; - } - - return ret; -} - -int ieee80211_wx_set_mlme(struct ieee80211_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_mlme *mlme = (struct iw_mlme *) extra; -#if 1 - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - case IW_MLME_DISASSOC: - ieee80211_disassociate(ieee); - break; - default: - return -EOPNOTSUPP; - } -#endif - return 0; -} - -int ieee80211_wx_set_auth(struct ieee80211_device *ieee, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - switch (data->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - /* need to support wpa2 here */ - break; - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* Host AP driver does not use these parameters and allows - * wpa_supplicant to control them internally. - */ - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - ieee->tkip_countermeasures = data->value; - break; - case IW_AUTH_DROP_UNENCRYPTED: - ieee->drop_unencrypted = data->value; - break; - - case IW_AUTH_80211_AUTH_ALG: - ieee->open_wep = (data->value&IW_AUTH_ALG_OPEN_SYSTEM) ? 1 : 0; - break; - -#if 1 - case IW_AUTH_WPA_ENABLED: - ieee->wpa_enabled = (data->value) ? 1 : 0; - break; - -#endif - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - ieee->ieee802_1x = data->value; - break; - case IW_AUTH_PRIVACY_INVOKED: - ieee->privacy_invoked = data->value; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -#if 1 -int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) -{ - u8 *buf = NULL; - - if (len > MAX_WPA_IE_LEN || (len && ie == NULL)) { - netdev_err(ieee->dev, "return error out, len:%zu\n", len); - return -EINVAL; - } - - if (len) { - if (len != ie[1]+2) { - netdev_err(ieee->dev, "len:%zu, ie:%d\n", len, ie[1]); - return -EINVAL; - } - buf = kmemdup(ie, len, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = len; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - } - - return 0; - -} -#endif diff --git a/drivers/staging/rtl8187se/r8180.h b/drivers/staging/rtl8187se/r8180.h deleted file mode 100644 index 9f931dba1d82fe..00000000000000 --- a/drivers/staging/rtl8187se/r8180.h +++ /dev/null @@ -1,640 +0,0 @@ -/* - * This is part of rtl8180 OpenSource driver. - * Copyright (C) Andrea Merello 2004-2005 - * Released under the terms of GPL (General Public Licence) - * - * Parts of this driver are based on the GPL part of the official realtek driver - * - * Parts of this driver are based on the rtl8180 driver skeleton from Patric - * Schenke & Andres Salomon - * - * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver - * - * We want to thanks the Authors of those projects and the Ndiswrapper project - * Authors. - */ - -#ifndef R8180H -#define R8180H - -#include - -#define RTL8180_MODULE_NAME "r8180" -#define DMESG(x, a...) printk(KERN_INFO RTL8180_MODULE_NAME ": " x "\n", ## a) -#define DMESGW(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": WW:" x "\n", ## a) -#define DMESGE(x, a...) printk(KERN_WARNING RTL8180_MODULE_NAME ": EE:" x "\n", ## a) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for rtnl_lock() */ -#include -#include -#include /* Necessary because we use the proc fs. */ -#include -#include "ieee80211/ieee80211.h" -#include - -#define EPROM_93c46 0 -#define EPROM_93c56 1 - -#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 30) - -#define DEFAULT_FRAG_THRESHOLD 2342U -#define MIN_FRAG_THRESHOLD 256U -#define DEFAULT_RTS_THRESHOLD 2342U -#define MIN_RTS_THRESHOLD 0U -#define MAX_RTS_THRESHOLD 2342U -#define DEFAULT_BEACONINTERVAL 0x64U - -#define DEFAULT_RETRY_RTS 7 -#define DEFAULT_RETRY_DATA 7 - -#define BEACON_QUEUE 6 - -#define aSifsTime 10 - -#define sCrcLng 4 -#define sAckCtsLng 112 /* bits in ACK and CTS frames. */ -/* +by amy 080312. */ -#define RATE_ADAPTIVE_TIMER_PERIOD 300 - -enum wireless_mode { - WIRELESS_MODE_UNKNOWN = 0x00, - WIRELESS_MODE_A = 0x01, - WIRELESS_MODE_B = 0x02, - WIRELESS_MODE_G = 0x04, - WIRELESS_MODE_AUTO = 0x08, -}; - -struct chnl_access_setting { - u16 sifs_timer; - u16 difs_timer; - u16 slot_time_timer; - u16 eifs_timer; - u16 cwmin_index; - u16 cwmax_index; -}; - -enum nic_t { - NIC_8185 = 1, - NIC_8185B -}; - -typedef u32 AC_CODING; -#define AC0_BE 0 /* ACI: 0x00 */ /* Best Effort. */ -#define AC1_BK 1 /* ACI: 0x01 */ /* Background. */ -#define AC2_VI 2 /* ACI: 0x10 */ /* Video. */ -#define AC3_VO 3 /* ACI: 0x11 */ /* Voice. */ -#define AC_MAX 4 /* Max: define total number; Should not to be used as a real - * enum. - */ - -/* - * ECWmin/ECWmax field. - * Ref: WMM spec 2.2.2: WME Parameter Element, p.13. - */ -typedef union _ECW { - u8 charData; - struct { - u8 ECWmin:4; - u8 ECWmax:4; - } f; /* Field */ -} ECW, *PECW; - -/* - * ACI/AIFSN Field. Ref: WMM spec 2.2.2: WME Parameter Element, p.12. - */ -typedef union _ACI_AIFSN { - u8 charData; - - struct { - u8 AIFSN:4; - u8 ACM:1; - u8 ACI:2; - u8 Reserved:1; - } f; /* Field */ -} ACI_AIFSN, *PACI_AIFSN; - -/* - * AC Parameters Record Format. - * Ref: WMM spec 2.2.2: WME Parameter Element, p.12. - */ -typedef union _AC_PARAM { - u32 longData; - u8 charData[4]; - - struct { - ACI_AIFSN AciAifsn; - ECW Ecw; - u16 TXOPLimit; - } f; /* Field */ -} AC_PARAM, *PAC_PARAM; - -struct buffer { - struct buffer *next; - u32 *buf; - dma_addr_t dma; -}; - -/* YJ,modified,080828. */ -struct stats { - unsigned long txrdu; - unsigned long rxrdu; - unsigned long rxnolast; - unsigned long rxnodata; - unsigned long rxnopointer; - unsigned long txnperr; - unsigned long txresumed; - unsigned long rxerr; - unsigned long rxoverflow; - unsigned long rxint; - unsigned long txbkpokint; - unsigned long txbepoking; - unsigned long txbkperr; - unsigned long txbeperr; - unsigned long txnpokint; - unsigned long txhpokint; - unsigned long txhperr; - unsigned long ints; - unsigned long shints; - unsigned long txoverflow; - unsigned long rxdmafail; - unsigned long txbeacon; - unsigned long txbeaconerr; - unsigned long txlpokint; - unsigned long txlperr; - unsigned long txretry; /* retry number tony 20060601 */ - unsigned long rxcrcerrmin; /* crc error (0-500) */ - unsigned long rxcrcerrmid; /* crc error (500-1000) */ - unsigned long rxcrcerrmax; /* crc error (>1000) */ - unsigned long rxicverr; /* ICV error */ -}; - -#define MAX_LD_SLOT_NUM 10 -#define KEEP_ALIVE_INTERVAL 20 /* in seconds. */ -#define CHECK_FOR_HANG_PERIOD 2 /* be equal to watchdog check time. */ -#define DEFAULT_KEEP_ALIVE_LEVEL 1 -#define DEFAULT_SLOT_NUM 2 -#define POWER_PROFILE_AC 0 -#define POWER_PROFILE_BATTERY 1 - -struct link_detect_t { - u32 rx_frame_num[MAX_LD_SLOT_NUM]; /* number of Rx Frame. - * CheckForHang_period to determine - * link status. - */ - u16 slot_num; /* number of CheckForHang period to determine link status, - * default is 2. - */ - u16 slot_index; - u32 num_tx_ok_in_period; /* number of packet transmitted during - * CheckForHang. - */ - u32 num_rx_ok_in_period; /* number of packet received during - * CheckForHang. - */ - u8 idle_count; /* (KEEP_ALIVE_INTERVAL / CHECK_FOR_HANG_PERIOD) */ - u32 last_num_tx_unicast; - u32 last_num_rx_unicast; - - bool b_busy_traffic; /* when it is set to 1, UI cann't scan at will. */ -}; - -/* YJ,modified,080828,end */ - -/* by amy for led - * ========================================================================== - * LED customization. - * ========================================================================== - */ -enum led_strategy_8185 { - SW_LED_MODE0, - SW_LED_MODE1, - HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different - * control modes). */ -}; - -enum rt_rf_power_state { - RF_ON, - RF_SLEEP, - RF_OFF -}; - -enum _ReasonCode { - unspec_reason = 0x1, - auth_not_valid = 0x2, - deauth_lv_ss = 0x3, - inactivity = 0x4, - ap_overload = 0x5, - class2_err = 0x6, - class3_err = 0x7, - disas_lv_ss = 0x8, - asoc_not_auth = 0x9, - - /* ----MIC_CHECK */ - mic_failure = 0xe, - /* ----END MIC_CHECK */ - - /* Reason code defined in 802.11i D10.0 p.28. */ - invalid_IE = 0x0d, - four_way_tmout = 0x0f, - two_way_tmout = 0x10, - IE_dismatch = 0x11, - invalid_Gcipher = 0x12, - invalid_Pcipher = 0x13, - invalid_AKMP = 0x14, - unsup_RSNIEver = 0x15, - invalid_RSNIE = 0x16, - auth_802_1x_fail = 0x17, - ciper_reject = 0x18, - - /* Reason code defined in 7.3.1.7, 802.1e D13.0, p.42. Added by Annie, - * 2005-11-15. - */ - QoS_unspec = 0x20, /* 32 */ - QAP_bandwidth = 0x21, /* 33 */ - poor_condition = 0x22, /* 34 */ - no_facility = 0x23, /* 35 */ - /* Where is 36??? */ - req_declined = 0x25, /* 37 */ - invalid_param = 0x26, /* 38 */ - req_not_honored = 0x27, /* 39 */ - TS_not_created = 0x2F, /* 47 */ - DL_not_allowed = 0x30, /* 48 */ - dest_not_exist = 0x31, /* 49 */ - dest_not_QSTA = 0x32, /* 50 */ -}; - -enum rt_ps_mode { - ACTIVE, /* Active/Continuous access. */ - MAX_PS, /* Max power save mode. */ - FAST_PS /* Fast power save mode. */ -}; - -/* by amy for power save. */ -struct r8180_priv { - struct pci_dev *pdev; - - short epromtype; - int irq; - struct ieee80211_device *ieee80211; - - short plcp_preamble_mode; /* 0:auto 1:short 2:long */ - - spinlock_t irq_th_lock; - spinlock_t tx_lock; - spinlock_t ps_lock; - spinlock_t rf_ps_lock; - - u16 irq_mask; - short irq_enabled; - struct net_device *dev; - short chan; - short sens; - short max_sens; - u8 chtxpwr[15]; /* channels from 1 to 14, 0 not used. */ - u8 chtxpwr_ofdm[15]; /* channels from 1 to 14, 0 not used. */ - u8 channel_plan; /* it's the channel plan index. */ - short up; - short crcmon; /* if 1 allow bad crc frame reception in monitor mode. */ - - struct timer_list scan_timer; - spinlock_t scan_lock; - u8 active_probe; - struct semaphore wx_sem; - short hw_wep; - - short digphy; - short antb; - short diversity; - u32 key0[4]; - short (*rf_set_sens)(struct net_device *dev, short sens); - void (*rf_set_chan)(struct net_device *dev, short ch); - void (*rf_close)(struct net_device *dev); - void (*rf_init)(struct net_device *dev); - void (*rf_sleep)(struct net_device *dev); - void (*rf_wakeup)(struct net_device *dev); - /* short rate; */ - short promisc; - /* stats */ - struct stats stats; - struct link_detect_t link_detect; /* YJ,add,080828 */ - struct iw_statistics wstats; - - /* RX stuff. */ - u32 *rxring; - u32 *rxringtail; - dma_addr_t rxringdma; - struct buffer *rxbuffer; - struct buffer *rxbufferhead; - int rxringcount; - u16 rxbuffersize; - - struct sk_buff *rx_skb; - - short rx_skb_complete; - - u32 rx_prevlen; - - u32 *txmapring; - u32 *txbkpring; - u32 *txbepring; - u32 *txvipring; - u32 *txvopring; - u32 *txhpring; - dma_addr_t txmapringdma; - dma_addr_t txbkpringdma; - dma_addr_t txbepringdma; - dma_addr_t txvipringdma; - dma_addr_t txvopringdma; - dma_addr_t txhpringdma; - u32 *txmapringtail; - u32 *txbkpringtail; - u32 *txbepringtail; - u32 *txvipringtail; - u32 *txvopringtail; - u32 *txhpringtail; - u32 *txmapringhead; - u32 *txbkpringhead; - u32 *txbepringhead; - u32 *txvipringhead; - u32 *txvopringhead; - u32 *txhpringhead; - struct buffer *txmapbufs; - struct buffer *txbkpbufs; - struct buffer *txbepbufs; - struct buffer *txvipbufs; - struct buffer *txvopbufs; - struct buffer *txhpbufs; - struct buffer *txmapbufstail; - struct buffer *txbkpbufstail; - struct buffer *txbepbufstail; - struct buffer *txvipbufstail; - struct buffer *txvopbufstail; - struct buffer *txhpbufstail; - - int txringcount; - int txbuffsize; - struct tasklet_struct irq_rx_tasklet; - u8 dma_poll_mask; - - /* adhoc/master mode stuff. */ - u32 *txbeaconringtail; - dma_addr_t txbeaconringdma; - u32 *txbeaconring; - int txbeaconcount; - struct buffer *txbeaconbufs; - struct buffer *txbeaconbufstail; - - u8 retry_data; - u8 retry_rts; - u16 rts; - - /* by amy for led. */ - enum led_strategy_8185 led_strategy; - /* by amy for led. */ - - /* by amy for power save. */ - struct timer_list watch_dog_timer; - bool bInactivePs; - bool bSwRfProcessing; - enum rt_rf_power_state eInactivePowerState; - enum rt_rf_power_state eRFPowerState; - u32 RfOffReason; - bool RFChangeInProgress; - bool SetRFPowerStateInProgress; - u8 RFProgType; - bool bLeisurePs; - enum rt_ps_mode dot11PowerSaveMode; - u8 TxPollingTimes; - - bool bApBufOurFrame; /* TRUE if AP buffer our unicast data , we will - * keep eAwake until receive data or timeout. - */ - u8 WaitBufDataBcnCount; - u8 WaitBufDataTimeOut; - - /* by amy for power save. */ - /* by amy for antenna. */ - u8 EEPROMSwAntennaDiversity; - bool EEPROMDefaultAntenna1; - u8 RegSwAntennaDiversityMechanism; - bool bSwAntennaDiverity; - u8 RegDefaultAntenna; - bool bDefaultAntenna1; - u8 SignalStrength; - long Stats_SignalStrength; - long LastSignalStrengthInPercent; /* In percentage, used for smoothing, - * e.g. Moving Average. - */ - u8 SignalQuality; /* in 0-100 index. */ - long Stats_SignalQuality; - long RecvSignalPower; /* in dBm. */ - long Stats_RecvSignalPower; - u8 LastRxPktAntenna; /* +by amy 080312 Antenna which received the lasted - * packet. 0: Aux, 1:Main. Added by Roger, - * 2008.01.25. - */ - u32 AdRxOkCnt; - long AdRxSignalStrength; - u8 CurrAntennaIndex; /* Index to current Antenna (both Tx and Rx). */ - u8 AdTickCount; /* Times of SwAntennaDiversityTimer happened. */ - u8 AdCheckPeriod; /* # of period SwAntennaDiversityTimer to check Rx - * signal strength for SW Antenna Diversity. - */ - u8 AdMinCheckPeriod; /* Min value of AdCheckPeriod. */ - u8 AdMaxCheckPeriod; /* Max value of AdCheckPeriod. */ - long AdRxSsThreshold; /* Signal strength threshold to switch antenna. */ - long AdMaxRxSsThreshold; /* Max value of AdRxSsThreshold. */ - bool bAdSwitchedChecking; /* TRUE if we shall shall check Rx signal - * strength for last time switching antenna. - */ - long AdRxSsBeforeSwitched; /* Rx signal strength before we switched - * antenna. - */ - struct timer_list SwAntennaDiversityTimer; - /* by amy for antenna {by amy 080312 */ - - /* Crystal calibration. Added by Roger, 2007.12.11. */ - - bool bXtalCalibration; /* Crystal calibration.*/ - u8 XtalCal_Xin; /* Crystal calibration for Xin. 0~7.5pF */ - u8 XtalCal_Xout; /* Crystal calibration for Xout. 0~7.5pF */ - - /* Tx power tracking with thermal meter indication. - * Added by Roger, 2007.12.11. - */ - - bool bTxPowerTrack; /* Tx Power tracking. */ - u8 ThermalMeter; /* Thermal meter reference indication. */ - - /* Dynamic Initial Gain Adjustment Mechanism. Added by Bruce, - * 2007-02-14. - */ - bool bDigMechanism; /* TRUE if DIG is enabled, FALSE ow. */ - bool bRegHighPowerMechanism; /* For High Power Mechanism. 061010, - * by rcnjko. - */ - u32 FalseAlarmRegValue; - u8 RegDigOfdmFaUpTh; /* Upper threshold of OFDM false alarm, which is - * used in DIG. - */ - u8 DIG_NumberFallbackVote; - u8 DIG_NumberUpgradeVote; - /* For HW antenna diversity, added by Roger, 2008.01.30. */ - u32 AdMainAntennaRxOkCnt; /* Main antenna Rx OK count. */ - u32 AdAuxAntennaRxOkCnt; /* Aux antenna Rx OK count. */ - bool bHWAdSwitched; /* TRUE if we has switched default antenna by HW - * evaluation. - */ - /* RF High Power upper/lower threshold. */ - u8 RegHiPwrUpperTh; - u8 RegHiPwrLowerTh; - /* RF RSSI High Power upper/lower Threshold. */ - u8 RegRSSIHiPwrUpperTh; - u8 RegRSSIHiPwrLowerTh; - /* Current CCK RSSI value to determine CCK high power, asked by SD3 DZ, - * by Bruce, 2007-04-12. - */ - u8 CurCCKRSSI; - bool bCurCCKPkt; - /* High Power Mechanism. Added by amy, 080312. */ - bool bToUpdateTxPwr; - long UndecoratedSmoothedSS; - long UndecoratedSmoothedRxPower; - u8 RSSI; - char RxPower; - u8 InitialGain; - /* For adjust Dig Threshold during Legacy/Leisure Power Save Mode. */ - u32 DozePeriodInPast2Sec; - /* Don't access BB/RF under disable PLL situation. */ - u8 InitialGainBackUp; - u8 RegBModeGainStage; - /* by amy for rate adaptive */ - struct timer_list rateadapter_timer; - u32 RateAdaptivePeriod; - bool bEnhanceTxPwr; - bool bUpdateARFR; - int ForcedDataRate; /* Force Data Rate. 0: Auto, 0x02: 1M ~ 0x6C: 54M.) - */ - u32 NumTxUnicast; /* YJ,add,080828,for keep alive. */ - u8 keepAliveLevel; /*YJ,add,080828,for KeepAlive. */ - unsigned long NumTxOkTotal; - u16 LastRetryCnt; - u16 LastRetryRate; - unsigned long LastTxokCnt; - unsigned long LastRxokCnt; - u16 CurrRetryCnt; - unsigned long LastTxOKBytes; - unsigned long NumTxOkBytesTotal; - u8 LastFailTxRate; - long LastFailTxRateSS; - u8 FailTxRateCount; - u32 LastTxThroughput; - /* for up rate. */ - unsigned short bTryuping; - u8 CurrTxRate; /* the rate before up. */ - u16 CurrRetryRate; - u16 TryupingCount; - u8 TryDownCountLowData; - u8 TryupingCountNoData; - - u8 CurrentOperaRate; - struct work_struct reset_wq; - struct work_struct watch_dog_wq; - short ack_tx_to_ieee; - - u8 dma_poll_stop_mask; - - u16 ShortRetryLimit; - u16 LongRetryLimit; - u16 EarlyRxThreshold; - u32 TransmitConfig; - u32 ReceiveConfig; - u32 IntrMask; - - struct chnl_access_setting ChannelAccessSetting; -}; - -#define MANAGE_PRIORITY 0 -#define BK_PRIORITY 1 -#define BE_PRIORITY 2 -#define VI_PRIORITY 3 -#define VO_PRIORITY 4 -#define HI_PRIORITY 5 -#define BEACON_PRIORITY 6 - -#define LOW_PRIORITY VI_PRIORITY -#define NORM_PRIORITY VO_PRIORITY -/* AC2Queue mapping. */ -#define AC2Q(_ac) (((_ac) == WME_AC_VO) ? VO_PRIORITY : \ - ((_ac) == WME_AC_VI) ? VI_PRIORITY : \ - ((_ac) == WME_AC_BK) ? BK_PRIORITY : \ - BE_PRIORITY) - -short rtl8180_tx(struct net_device *dev, u8 *skbuf, int len, int priority, - bool morefrag, short fragdesc, int rate); - -u8 read_nic_byte(struct net_device *dev, int x); -u32 read_nic_dword(struct net_device *dev, int x); -u16 read_nic_word(struct net_device *dev, int x); -void write_nic_byte(struct net_device *dev, int x, u8 y); -void write_nic_word(struct net_device *dev, int x, u16 y); -void write_nic_dword(struct net_device *dev, int x, u32 y); -void force_pci_posting(struct net_device *dev); - -void rtl8180_rtx_disable(struct net_device *); -void rtl8180_set_anaparam(struct net_device *dev, u32 a); -void rtl8185_set_anaparam2(struct net_device *dev, u32 a); -void rtl8180_set_hw_wep(struct net_device *dev); -void rtl8180_no_hw_wep(struct net_device *dev); -void rtl8180_update_msr(struct net_device *dev); -void rtl8180_beacon_tx_disable(struct net_device *dev); -void rtl8180_beacon_rx_disable(struct net_device *dev); -int rtl8180_down(struct net_device *dev); -int rtl8180_up(struct net_device *dev); -void rtl8180_commit(struct net_device *dev); -void rtl8180_set_chan(struct net_device *dev, short ch); -void write_phy(struct net_device *dev, u8 adr, u8 data); -void write_phy_cck(struct net_device *dev, u8 adr, u32 data); -void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data); -void rtl8185_tx_antenna(struct net_device *dev, u8 ant); -void rtl8185_rf_pins_enable(struct net_device *dev); -void IPSEnter(struct net_device *dev); -void IPSLeave(struct net_device *dev); -int get_curr_tx_free_desc(struct net_device *dev, int priority); -void UpdateInitialGain(struct net_device *dev); -bool SetAntennaConfig87SE(struct net_device *dev, u8 DefaultAnt, - bool bAntDiversity); - -void rtl8185b_adapter_start(struct net_device *dev); -void rtl8185b_rx_enable(struct net_device *dev); -void rtl8185b_tx_enable(struct net_device *dev); -void rtl8180_reset(struct net_device *dev); -void rtl8185b_irq_enable(struct net_device *dev); -void fix_rx_fifo(struct net_device *dev); -void fix_tx_fifo(struct net_device *dev); -void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch); -void rtl8180_rate_adapter(struct work_struct *work); -bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet, - u32 ChangeSource); - -#endif - -/* fun with the built-in ieee80211 stack... */ -extern int ieee80211_crypto_init(void); -extern void ieee80211_crypto_deinit(void); -extern int ieee80211_crypto_tkip_init(void); -extern void ieee80211_crypto_tkip_exit(void); -extern int ieee80211_crypto_ccmp_init(void); -extern void ieee80211_crypto_ccmp_exit(void); -extern int ieee80211_crypto_wep_init(void); -extern void ieee80211_crypto_wep_exit(void); diff --git a/drivers/staging/rtl8187se/r8180_93cx6.h b/drivers/staging/rtl8187se/r8180_93cx6.h deleted file mode 100644 index b52b5b0610abe5..00000000000000 --- a/drivers/staging/rtl8187se/r8180_93cx6.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - This is part of rtl8180 OpenSource driver - Copyright (C) Andrea Merello 2004-2005 - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part of the official realtek driver - Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon - Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver - - We want to tanks the Authors of such projects and the Ndiswrapper project Authors. -*/ - -/*This files contains card eeprom (93c46 or 93c56) programming routines*/ -/*memory is addressed by WORDS*/ - -#include "r8180.h" -#include "r8180_hw.h" - -#define EPROM_DELAY 10 - -#define EPROM_ANAPARAM_ADDRLWORD 0xd -#define EPROM_ANAPARAM_ADDRHWORD 0xe - -#define RFCHIPID 0x6 -#define RFCHIPID_INTERSIL 1 -#define RFCHIPID_RFMD 2 -#define RFCHIPID_PHILIPS 3 -#define RFCHIPID_MAXIM 4 -#define RFCHIPID_GCT 5 -#define RFCHIPID_RTL8225 9 -#define RF_ZEBRA2 11 -#define EPROM_TXPW_BASE 0x05 -#define RF_ZEBRA4 12 -#define RFCHIPID_RTL8255 0xa -#define RF_PARAM 0x19 -#define RF_PARAM_DIGPHY_SHIFT 0 -#define RF_PARAM_ANTBDEFAULT_SHIFT 1 -#define RF_PARAM_CARRIERSENSE_SHIFT 2 -#define RF_PARAM_CARRIERSENSE_MASK (3<<2) -#define ENERGY_TRESHOLD 0x17 -#define EPROM_VERSION 0x1E -#define MAC_ADR 0x7 - -#define CIS 0x18 - -#define EPROM_TXPW_OFDM_CH1_2 0x20 - -#define EPROM_TXPW_CH1_2 0x30 - -#define RTL818X_EEPROM_CMD_READ (1 << 0) -#define RTL818X_EEPROM_CMD_WRITE (1 << 1) -#define RTL818X_EEPROM_CMD_CK (1 << 2) -#define RTL818X_EEPROM_CMD_CS (1 << 3) - diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c deleted file mode 100644 index a6022d4e7573e2..00000000000000 --- a/drivers/staging/rtl8187se/r8180_core.c +++ /dev/null @@ -1,3775 +0,0 @@ -/* - * This is part of rtl818x pci OpenSource driver - v 0.1 - * Copyright (C) Andrea Merello 2004-2005 - * Released under the terms of GPL (General Public License) - * - * Parts of this driver are based on the GPL part of the official - * Realtek driver. - * - * Parts of this driver are based on the rtl8180 driver skeleton - * from Patric Schenke & Andres Salomon. - * - * Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. - * - * Parts of BB/RF code are derived from David Young rtl8180 netbsd driver. - * - * RSSI calc function from 'The Deuce' - * - * Some ideas borrowed from the 8139too.c driver included in linux kernel. - * - * We (I?) want to thanks the Authors of those projecs and also the - * Ndiswrapper's project Authors. - * - * A big big thanks goes also to Realtek corp. for their help in my attempt to - * add RTL8185 and RTL8225 support, and to David Young also. - * - * Power management interface routines. - * Written by Mariusz Matuszek. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#undef RX_DONT_PASS_UL -#undef DUMMY_RX - -#include -#include -#include -#include -#include -#include - -#include "r8180_hw.h" -#include "r8180.h" -#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */ -#include "r8180_93cx6.h" /* Card EEPROM */ -#include "r8180_wx.h" -#include "r8180_dm.h" - -#include "ieee80211/dot11d.h" - -static struct pci_device_id rtl8180_pci_id_tbl[] = { - { - .vendor = PCI_VENDOR_ID_REALTEK, - .device = 0x8199, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, - .driver_data = 0, - }, - { - .vendor = 0, - .device = 0, - .subvendor = 0, - .subdevice = 0, - .driver_data = 0, - } -}; - -static char ifname[IFNAMSIZ] = "wlan%d"; -static int hwwep; - -MODULE_LICENSE("GPL"); -MODULE_DEVICE_TABLE(pci, rtl8180_pci_id_tbl); -MODULE_AUTHOR("Andrea Merello "); -MODULE_DESCRIPTION("Linux driver for Realtek RTL8187SE WiFi cards"); - -module_param_string(ifname, ifname, sizeof(ifname), S_IRUGO|S_IWUSR); -module_param(hwwep, int, S_IRUGO|S_IWUSR); - -MODULE_PARM_DESC(hwwep, " Try to use hardware WEP support. Still broken and not available on all cards"); - -static int rtl8180_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id); - -static void rtl8180_pci_remove(struct pci_dev *pdev); - -static void rtl8180_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - if (dev->netdev_ops->ndo_stop) - dev->netdev_ops->ndo_stop(dev); - pci_disable_device(pdev); -} - -static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (!netif_running(dev)) - goto out_pci_suspend; - - if (dev->netdev_ops->ndo_stop) - dev->netdev_ops->ndo_stop(dev); - - netif_device_detach(dev); - -out_pci_suspend: - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static int rtl8180_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - int err; - u32 val; - - pci_set_power_state(pdev, PCI_D0); - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "pci_enable_device failed on resume\n"); - - return err; - } - - pci_restore_state(pdev); - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries - * from interfering with C3 CPU state. pci_restore_state won't help - * here since it only restores the first 64 bytes pci config header. - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - if (!netif_running(dev)) - goto out; - - if (dev->netdev_ops->ndo_open) - dev->netdev_ops->ndo_open(dev); - - netif_device_attach(dev); -out: - return 0; -} - -static struct pci_driver rtl8180_pci_driver = { - .name = RTL8180_MODULE_NAME, - .id_table = rtl8180_pci_id_tbl, - .probe = rtl8180_pci_probe, - .remove = rtl8180_pci_remove, - .suspend = rtl8180_suspend, - .resume = rtl8180_resume, - .shutdown = rtl8180_shutdown, -}; - -u8 read_nic_byte(struct net_device *dev, int x) -{ - return 0xff&readb((u8 __iomem *)dev->mem_start + x); -} - -u32 read_nic_dword(struct net_device *dev, int x) -{ - return readl((u8 __iomem *)dev->mem_start + x); -} - -u16 read_nic_word(struct net_device *dev, int x) -{ - return readw((u8 __iomem *)dev->mem_start + x); -} - -void write_nic_byte(struct net_device *dev, int x, u8 y) -{ - writeb(y, (u8 __iomem *)dev->mem_start + x); - udelay(20); -} - -void write_nic_dword(struct net_device *dev, int x, u32 y) -{ - writel(y, (u8 __iomem *)dev->mem_start + x); - udelay(20); -} - -void write_nic_word(struct net_device *dev, int x, u16 y) -{ - writew(y, (u8 __iomem *)dev->mem_start + x); - udelay(20); -} - -inline void force_pci_posting(struct net_device *dev) -{ - read_nic_byte(dev, EPROM_CMD); - mb(); -} - -static irqreturn_t rtl8180_interrupt(int irq, void *netdev); -void set_nic_rxring(struct net_device *dev); -void set_nic_txring(struct net_device *dev); -static struct net_device_stats *rtl8180_stats(struct net_device *dev); -void rtl8180_commit(struct net_device *dev); -void rtl8180_start_tx_beacon(struct net_device *dev); - -static struct proc_dir_entry *rtl8180_proc; - -static int proc_get_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = 0xff; - - /* This dump the current register page */ - for (n = 0; n <= max;) { - seq_printf(m, "\nD: %2x > ", n); - - for (i = 0; i < 16 && n <= max; i++, n++) - seq_printf(m, "%2x ", read_nic_byte(dev, n)); - } - seq_putc(m, '\n'); - return 0; -} - -int get_curr_tx_free_desc(struct net_device *dev, int priority); - -static int proc_get_stats_hw(struct seq_file *m, void *v) -{ - return 0; -} - -static int proc_get_stats_rx(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - seq_printf(m, - "RX OK: %lu\n" - "RX Retry: %lu\n" - "RX CRC Error(0-500): %lu\n" - "RX CRC Error(500-1000): %lu\n" - "RX CRC Error(>1000): %lu\n" - "RX ICV Error: %lu\n", - priv->stats.rxint, - priv->stats.rxerr, - priv->stats.rxcrcerrmin, - priv->stats.rxcrcerrmid, - priv->stats.rxcrcerrmax, - priv->stats.rxicverr - ); - - return 0; -} - -static int proc_get_stats_tx(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long totalOK; - - totalOK = priv->stats.txnpokint + priv->stats.txhpokint + - priv->stats.txlpokint; - - seq_printf(m, - "TX OK: %lu\n" - "TX Error: %lu\n" - "TX Retry: %lu\n" - "TX beacon OK: %lu\n" - "TX beacon error: %lu\n", - totalOK, - priv->stats.txnperr+priv->stats.txhperr+priv->stats.txlperr, - priv->stats.txretry, - priv->stats.txbeacon, - priv->stats.txbeaconerr - ); - - return 0; -} - -static void rtl8180_proc_module_init(void) -{ - DMESG("Initializing proc filesystem"); - rtl8180_proc = proc_mkdir(RTL8180_MODULE_NAME, init_net.proc_net); -} - -static void rtl8180_proc_module_remove(void) -{ - remove_proc_entry(RTL8180_MODULE_NAME, init_net.proc_net); -} - -static void rtl8180_proc_remove_one(struct net_device *dev) -{ - remove_proc_subtree(dev->name, rtl8180_proc); -} - -/* - * seq_file wrappers for procfile show routines. - */ -static int rtl8180_proc_open(struct inode *inode, struct file *file) -{ - struct net_device *dev = proc_get_parent_data(inode); - int (*show)(struct seq_file *, void *) = PDE_DATA(inode); - - return single_open(file, show, dev); -} - -static const struct file_operations rtl8180_proc_fops = { - .open = rtl8180_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * Table of proc files we need to create. - */ -struct rtl8180_proc_file { - char name[12]; - int (*show)(struct seq_file *, void *); -}; - -static const struct rtl8180_proc_file rtl8180_proc_files[] = { - { "stats-hw", &proc_get_stats_hw }, - { "stats-rx", &proc_get_stats_rx }, - { "stats-tx", &proc_get_stats_tx }, - { "registers", &proc_get_registers }, - { "" } -}; - -static void rtl8180_proc_init_one(struct net_device *dev) -{ - const struct rtl8180_proc_file *f; - struct proc_dir_entry *dir; - - dir = proc_mkdir_data(dev->name, 0, rtl8180_proc, dev); - if (!dir) { - DMESGE("Unable to initialize /proc/net/r8180/%s\n", dev->name); - return; - } - - for (f = rtl8180_proc_files; f->name[0]; f++) { - if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, - &rtl8180_proc_fops, f->show)) { - DMESGE("Unable to initialize /proc/net/r8180/%s/%s\n", - dev->name, f->name); - return; - } - } -} - -/* - * FIXME: check if we can use some standard already-existent - * data type+functions in kernel. - */ - -static short buffer_add(struct buffer **buffer, u32 *buf, dma_addr_t dma, - struct buffer **bufferhead) -{ - struct buffer *tmp; - - if (!*buffer) { - - *buffer = kmalloc(sizeof(struct buffer), GFP_KERNEL); - - if (*buffer == NULL) { - DMESGE("Failed to kmalloc head of TX/RX struct"); - return -1; - } - (*buffer)->next = *buffer; - (*buffer)->buf = buf; - (*buffer)->dma = dma; - if (bufferhead != NULL) - (*bufferhead) = (*buffer); - return 0; - } - tmp = *buffer; - - while (tmp->next != (*buffer)) - tmp = tmp->next; - tmp->next = kmalloc(sizeof(struct buffer), GFP_KERNEL); - if (tmp->next == NULL) { - DMESGE("Failed to kmalloc TX/RX struct"); - return -1; - } - tmp->next->buf = buf; - tmp->next->dma = dma; - tmp->next->next = *buffer; - - return 0; -} - -static void buffer_free(struct net_device *dev, struct buffer **buffer, int len, - short consistent) -{ - - struct buffer *tmp, *next; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - - if (!*buffer) - return; - - tmp = *buffer; - - do { - next = tmp->next; - if (consistent) { - pci_free_consistent(pdev, len, - tmp->buf, tmp->dma); - } else { - pci_unmap_single(pdev, tmp->dma, - len, PCI_DMA_FROMDEVICE); - kfree(tmp->buf); - } - kfree(tmp); - tmp = next; - } while (next != *buffer); - - *buffer = NULL; -} - -int get_curr_tx_free_desc(struct net_device *dev, int priority) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u32 *tail; - u32 *head; - int ret; - - switch (priority) { - case MANAGE_PRIORITY: - head = priv->txmapringhead; - tail = priv->txmapringtail; - break; - case BK_PRIORITY: - head = priv->txbkpringhead; - tail = priv->txbkpringtail; - break; - case BE_PRIORITY: - head = priv->txbepringhead; - tail = priv->txbepringtail; - break; - case VI_PRIORITY: - head = priv->txvipringhead; - tail = priv->txvipringtail; - break; - case VO_PRIORITY: - head = priv->txvopringhead; - tail = priv->txvopringtail; - break; - case HI_PRIORITY: - head = priv->txhpringhead; - tail = priv->txhpringtail; - break; - default: - return -1; - } - - if (head <= tail) - ret = priv->txringcount - (tail - head)/8; - else - ret = (head - tail)/8; - - if (ret > priv->txringcount) - DMESG("BUG"); - - return ret; -} - -static short check_nic_enought_desc(struct net_device *dev, int priority) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = netdev_priv(dev); - int requiredbyte; - int required; - - requiredbyte = priv->ieee80211->fts + - sizeof(struct ieee80211_header_data); - - if (ieee->current_network.QoS_Enable) - requiredbyte += 2; - - required = requiredbyte / (priv->txbuffsize-4); - - if (requiredbyte % priv->txbuffsize) - required++; - - /* for now we keep two free descriptor as a safety boundary - * between the tail and the head - */ - - return required + 2 < get_curr_tx_free_desc(dev, priority); -} - -void fix_tx_fifo(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 *tmp; - int i; - - for (tmp = priv->txmapring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txbkpring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txbepring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - for (tmp = priv->txvipring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txvopring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txhpring, i = 0; - i < priv->txringcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - for (tmp = priv->txbeaconring, i = 0; - i < priv->txbeaconcount; - tmp += 8, i++) { - *tmp = *tmp & ~(1<<31); - } - - priv->txmapringtail = priv->txmapring; - priv->txmapringhead = priv->txmapring; - priv->txmapbufstail = priv->txmapbufs; - - priv->txbkpringtail = priv->txbkpring; - priv->txbkpringhead = priv->txbkpring; - priv->txbkpbufstail = priv->txbkpbufs; - - priv->txbepringtail = priv->txbepring; - priv->txbepringhead = priv->txbepring; - priv->txbepbufstail = priv->txbepbufs; - - priv->txvipringtail = priv->txvipring; - priv->txvipringhead = priv->txvipring; - priv->txvipbufstail = priv->txvipbufs; - - priv->txvopringtail = priv->txvopring; - priv->txvopringhead = priv->txvopring; - priv->txvopbufstail = priv->txvopbufs; - - priv->txhpringtail = priv->txhpring; - priv->txhpringhead = priv->txhpring; - priv->txhpbufstail = priv->txhpbufs; - - priv->txbeaconringtail = priv->txbeaconring; - priv->txbeaconbufstail = priv->txbeaconbufs; - set_nic_txring(dev); - - ieee80211_reset_queue(priv->ieee80211); - priv->ack_tx_to_ieee = 0; -} - -void fix_rx_fifo(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 *tmp; - struct buffer *rxbuf; - u8 rx_desc_size; - - rx_desc_size = 8; /* 4*8 = 32 bytes */ - - for (tmp = priv->rxring, rxbuf = priv->rxbufferhead; - (tmp < (priv->rxring)+(priv->rxringcount)*rx_desc_size); - tmp += rx_desc_size, rxbuf = rxbuf->next) { - *(tmp+2) = rxbuf->dma; - *tmp = *tmp & ~0xfff; - *tmp = *tmp | priv->rxbuffersize; - *tmp |= (1<<31); - } - - priv->rxringtail = priv->rxring; - priv->rxbuffer = priv->rxbufferhead; - priv->rx_skb_complete = 1; - set_nic_rxring(dev); -} - -static void rtl8180_irq_disable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - write_nic_dword(dev, IMR, 0); - force_pci_posting(dev); - priv->irq_enabled = 0; -} - -void rtl8180_set_mode(struct net_device *dev, int mode) -{ - u8 ecmd; - - ecmd = read_nic_byte(dev, EPROM_CMD); - ecmd = ecmd & ~EPROM_CMD_OPERATING_MODE_MASK; - ecmd = ecmd | (mode<ieee80211->state == IEEE80211_LINKED) { - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - msr |= (MSR_LINK_ADHOC<ieee80211->iw_mode == IW_MODE_MASTER) - msr |= (MSR_LINK_MASTER<ieee80211->iw_mode == IW_MODE_INFRA) - msr |= (MSR_LINK_MANAGED< 14) || (ch < 1)) { - netdev_err(dev, "In %s: Invalid channel %d\n", __func__, ch); - return; - } - - priv->chan = ch; - priv->rf_set_chan(dev, priv->chan); -} - -void set_nic_txring(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - write_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR, priv->txmapringdma); - write_nic_dword(dev, TX_BKPRIORITY_RING_ADDR, priv->txbkpringdma); - write_nic_dword(dev, TX_BEPRIORITY_RING_ADDR, priv->txbepringdma); - write_nic_dword(dev, TX_VIPRIORITY_RING_ADDR, priv->txvipringdma); - write_nic_dword(dev, TX_VOPRIORITY_RING_ADDR, priv->txvopringdma); - write_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR, priv->txhpringdma); - write_nic_dword(dev, TX_BEACON_RING_ADDR, priv->txbeaconringdma); -} - -void rtl8180_beacon_tx_enable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_BQ); - write_nic_byte(dev, TPPollStop, priv->dma_poll_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -void rtl8180_beacon_tx_disable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask |= TPPOLLSTOP_BQ; - write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - -} - -void rtl8180_rtx_disable(struct net_device *dev) -{ - u8 cmd; - struct r8180_priv *priv = ieee80211_priv(dev); - - cmd = read_nic_byte(dev, CMD); - write_nic_byte(dev, CMD, cmd & - ~((1<rx_skb_complete) - dev_kfree_skb_any(priv->rx_skb); -} - -static short alloc_tx_desc_ring(struct net_device *dev, int bufsize, int count, - int addr) -{ - int i; - u32 *desc; - u32 *tmp; - dma_addr_t dma_desc, dma_tmp; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - void *buf; - - if ((bufsize & 0xfff) != bufsize) { - DMESGE("TX buffer allocation too large"); - return 0; - } - desc = (u32 *)pci_alloc_consistent(pdev, - sizeof(u32)*8*count+256, &dma_desc); - if (desc == NULL) - return -1; - - if (dma_desc & 0xff) - /* - * descriptor's buffer must be 256 byte aligned - * we shouldn't be here, since we set DMA mask ! - */ - WARN(1, "DMA buffer is not aligned\n"); - - tmp = desc; - - for (i = 0; i < count; i++) { - buf = (void *)pci_alloc_consistent(pdev, bufsize, &dma_tmp); - if (buf == NULL) - return -ENOMEM; - - switch (addr) { - case TX_MANAGEPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txmapbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer NP"); - return -ENOMEM; - } - break; - case TX_BKPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txbkpbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer LP"); - return -ENOMEM; - } - break; - case TX_BEPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txbepbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer NP"); - return -ENOMEM; - } - break; - case TX_VIPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txvipbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer LP"); - return -ENOMEM; - } - break; - case TX_VOPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txvopbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer NP"); - return -ENOMEM; - } - break; - case TX_HIGHPRIORITY_RING_ADDR: - if (-1 == buffer_add(&priv->txhpbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer HP"); - return -ENOMEM; - } - break; - case TX_BEACON_RING_ADDR: - if (-1 == buffer_add(&priv->txbeaconbufs, - buf, dma_tmp, NULL)) { - DMESGE("Unable to allocate mem for buffer BP"); - return -ENOMEM; - } - break; - } - *tmp = *tmp & ~(1<<31); /* descriptor empty, owned by the drv */ - *(tmp+2) = (u32)dma_tmp; - *(tmp+3) = bufsize; - - if (i+1 < count) - *(tmp+4) = (u32)dma_desc+((i+1)*8*4); - else - *(tmp+4) = (u32)dma_desc; - - tmp = tmp+8; - } - - switch (addr) { - case TX_MANAGEPRIORITY_RING_ADDR: - priv->txmapringdma = dma_desc; - priv->txmapring = desc; - break; - case TX_BKPRIORITY_RING_ADDR: - priv->txbkpringdma = dma_desc; - priv->txbkpring = desc; - break; - case TX_BEPRIORITY_RING_ADDR: - priv->txbepringdma = dma_desc; - priv->txbepring = desc; - break; - case TX_VIPRIORITY_RING_ADDR: - priv->txvipringdma = dma_desc; - priv->txvipring = desc; - break; - case TX_VOPRIORITY_RING_ADDR: - priv->txvopringdma = dma_desc; - priv->txvopring = desc; - break; - case TX_HIGHPRIORITY_RING_ADDR: - priv->txhpringdma = dma_desc; - priv->txhpring = desc; - break; - case TX_BEACON_RING_ADDR: - priv->txbeaconringdma = dma_desc; - priv->txbeaconring = desc; - break; - - } - - return 0; -} - -static void free_tx_desc_rings(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - int count = priv->txringcount; - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txmapring, priv->txmapringdma); - buffer_free(dev, &(priv->txmapbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txbkpring, priv->txbkpringdma); - buffer_free(dev, &(priv->txbkpbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txbepring, priv->txbepringdma); - buffer_free(dev, &(priv->txbepbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txvipring, priv->txvipringdma); - buffer_free(dev, &(priv->txvipbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txvopring, priv->txvopringdma); - buffer_free(dev, &(priv->txvopbufs), priv->txbuffsize, 1); - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txhpring, priv->txhpringdma); - buffer_free(dev, &(priv->txhpbufs), priv->txbuffsize, 1); - - count = priv->txbeaconcount; - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->txbeaconring, priv->txbeaconringdma); - buffer_free(dev, &(priv->txbeaconbufs), priv->txbuffsize, 1); -} - -static void free_rx_desc_ring(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - int count = priv->rxringcount; - - pci_free_consistent(pdev, sizeof(u32)*8*count+256, - priv->rxring, priv->rxringdma); - - buffer_free(dev, &(priv->rxbuffer), priv->rxbuffersize, 0); -} - -static short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count) -{ - int i; - u32 *desc; - u32 *tmp; - dma_addr_t dma_desc, dma_tmp; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct pci_dev *pdev = priv->pdev; - void *buf; - u8 rx_desc_size; - - rx_desc_size = 8; /* 4*8 = 32 bytes */ - - if ((bufsize & 0xfff) != bufsize) { - DMESGE("RX buffer allocation too large"); - return -1; - } - - desc = (u32 *)pci_alloc_consistent(pdev, - sizeof(u32) * rx_desc_size * count + 256, &dma_desc); - - if (dma_desc & 0xff) - /* - * descriptor's buffer must be 256 byte aligned - * should never happen since we specify the DMA mask - */ - WARN(1, "DMA buffer is not aligned\n"); - - priv->rxring = desc; - priv->rxringdma = dma_desc; - tmp = desc; - - for (i = 0; i < count; i++) { - buf = kmalloc(bufsize * sizeof(u8), GFP_ATOMIC); - if (buf == NULL) { - DMESGE("Failed to kmalloc RX buffer"); - return -1; - } - - dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8), - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(pdev, dma_tmp)) - return -1; - if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp, - &(priv->rxbufferhead))) { - DMESGE("Unable to allocate mem RX buf"); - return -1; - } - *tmp = 0; /* zero pads the header of the descriptor */ - *tmp = *tmp | (bufsize&0xfff); - *(tmp+2) = (u32)dma_tmp; - *tmp = *tmp | (1<<31); /* descriptor void, owned by the NIC */ - - tmp = tmp+rx_desc_size; - } - - /* this is the last descriptor */ - *(tmp - rx_desc_size) = *(tmp - rx_desc_size) | (1 << 30); - - return 0; -} - - -void set_nic_rxring(struct net_device *dev) -{ - u8 pgreg; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - pgreg = read_nic_byte(dev, PGSELECT); - write_nic_byte(dev, PGSELECT, pgreg & ~(1<rxringdma); -} - -void rtl8180_reset(struct net_device *dev) -{ - u8 cr; - - rtl8180_irq_disable(dev); - - cr = read_nic_byte(dev, CMD); - cr = cr & 2; - cr = cr | (1< 12) - return 10; - return rtl_rate[rate]; -} - -inline u8 rtl8180_IsWirelessBMode(u16 rate) -{ - if (((rate <= 110) && (rate != 60) && (rate != 90)) || (rate == 220)) - return 1; - else - return 0; -} - -u16 N_DBPSOfRate(u16 DataRate); - -static u16 ComputeTxTime(u16 FrameLength, u16 DataRate, u8 bManagementFrame, - u8 bShortPreamble) -{ - u16 FrameTime; - u16 N_DBPS; - u16 Ceiling; - - if (rtl8180_IsWirelessBMode(DataRate)) { - if (bManagementFrame || !bShortPreamble || DataRate == 10) - /* long preamble */ - FrameTime = (u16)(144+48+(FrameLength*8/(DataRate/10))); - else - /* short preamble */ - FrameTime = (u16)(72+24+(FrameLength*8/(DataRate/10))); - - if ((FrameLength*8 % (DataRate/10)) != 0) /* get the ceilling */ - FrameTime++; - } else { /* 802.11g DSSS-OFDM PLCP length field calculation. */ - N_DBPS = N_DBPSOfRate(DataRate); - Ceiling = (16 + 8*FrameLength + 6) / N_DBPS - + (((16 + 8*FrameLength + 6) % N_DBPS) ? 1 : 0); - FrameTime = (u16)(16 + 4 + 4*Ceiling + 6); - } - return FrameTime; -} - -u16 N_DBPSOfRate(u16 DataRate) -{ - u16 N_DBPS = 24; - - switch (DataRate) { - case 60: - N_DBPS = 24; - break; - case 90: - N_DBPS = 36; - break; - case 120: - N_DBPS = 48; - break; - case 180: - N_DBPS = 72; - break; - case 240: - N_DBPS = 96; - break; - case 360: - N_DBPS = 144; - break; - case 480: - N_DBPS = 192; - break; - case 540: - N_DBPS = 216; - break; - default: - break; - } - - return N_DBPS; -} - -/* - * For Netgear case, they want good-looking signal strength. - */ -static long NetgearSignalStrengthTranslate(long LastSS, long CurrSS) -{ - long RetSS; - - /* Step 1. Scale mapping. */ - if (CurrSS >= 71 && CurrSS <= 100) - RetSS = 90 + ((CurrSS - 70) / 3); - else if (CurrSS >= 41 && CurrSS <= 70) - RetSS = 78 + ((CurrSS - 40) / 3); - else if (CurrSS >= 31 && CurrSS <= 40) - RetSS = 66 + (CurrSS - 30); - else if (CurrSS >= 21 && CurrSS <= 30) - RetSS = 54 + (CurrSS - 20); - else if (CurrSS >= 5 && CurrSS <= 20) - RetSS = 42 + (((CurrSS - 5) * 2) / 3); - else if (CurrSS == 4) - RetSS = 36; - else if (CurrSS == 3) - RetSS = 27; - else if (CurrSS == 2) - RetSS = 18; - else if (CurrSS == 1) - RetSS = 9; - else - RetSS = CurrSS; - - /* Step 2. Smoothing. */ - if (LastSS > 0) - RetSS = ((LastSS * 5) + (RetSS) + 5) / 6; - - return RetSS; -} - -/* - * Translate 0-100 signal strength index into dBm. - */ -static long TranslateToDbm8185(u8 SignalStrengthIndex) -{ - long SignalPower; - - /* Translate to dBm (x=0.5y-95). */ - SignalPower = (long)((SignalStrengthIndex + 1) >> 1); - SignalPower -= 95; - - return SignalPower; -} - -/* - * Perform signal smoothing for dynamic mechanism. - * This is different with PerformSignalSmoothing8185 in smoothing formula. - * No dramatic adjustment is applied because dynamic mechanism need some - * degree of correctness. Ported from 8187B. - */ -static void PerformUndecoratedSignalSmoothing8185(struct r8180_priv *priv, - bool bCckRate) -{ - long smoothedSS; - long smoothedRx; - - /* Determine the current packet is CCK rate. */ - priv->bCurCCKPkt = bCckRate; - - smoothedSS = priv->SignalStrength * 10; - - if (priv->UndecoratedSmoothedSS >= 0) - smoothedSS = ((priv->UndecoratedSmoothedSS * 5) + - smoothedSS) / 6; - - priv->UndecoratedSmoothedSS = smoothedSS; - - smoothedRx = ((priv->UndecoratedSmoothedRxPower * 50) + - (priv->RxPower * 11)) / 60; - - priv->UndecoratedSmoothedRxPower = smoothedRx; - - if (bCckRate) - priv->CurCCKRSSI = priv->RSSI; - else - priv->CurCCKRSSI = 0; -} - - -/* - * This is rough RX isr handling routine - */ -static void rtl8180_rx(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct sk_buff *tmp_skb; - short first, last; - u32 len; - int lastlen; - unsigned char quality, signal; - u8 rate; - u32 *tmp, *tmp2; - u8 rx_desc_size; - u8 padding; - char rxpower = 0; - u32 RXAGC = 0; - long RxAGC_dBm = 0; - u8 LNA = 0, BB = 0; - u8 LNA_gain[4] = {02, 17, 29, 39}; - u8 Antenna = 0; - struct ieee80211_hdr_4addr *hdr; - u16 fc, type; - u8 bHwError = 0, bCRC = 0, bICV = 0; - bool bCckRate = false; - u8 RSSI = 0; - long SignalStrengthIndex = 0; - struct ieee80211_rx_stats stats = { - .signal = 0, - .noise = -98, - .rate = 0, - .freq = IEEE80211_24GHZ_BAND, - }; - - stats.nic_type = NIC_8185B; - rx_desc_size = 8; - - if ((*(priv->rxringtail)) & (1<<31)) { - /* we have got an RX int, but the descriptor. we are pointing - * is empty. - */ - - priv->stats.rxnodata++; - priv->ieee80211->stats.rx_errors++; - - tmp2 = NULL; - tmp = priv->rxringtail; - do { - if (tmp == priv->rxring) - tmp = priv->rxring + (priv->rxringcount - 1) * - rx_desc_size; - else - tmp -= rx_desc_size; - - if (!(*tmp & (1<<31))) - tmp2 = tmp; - } while (tmp != priv->rxring); - - if (tmp2) - priv->rxringtail = tmp2; - } - - /* while there are filled descriptors */ - while (!(*(priv->rxringtail) & (1<<31))) { - if (*(priv->rxringtail) & (1<<26)) - DMESGW("RX buffer overflow"); - if (*(priv->rxringtail) & (1<<12)) - priv->stats.rxicverr++; - - if (*(priv->rxringtail) & (1<<27)) { - priv->stats.rxdmafail++; - goto drop; - } - - pci_dma_sync_single_for_cpu(priv->pdev, - priv->rxbuffer->dma, - priv->rxbuffersize * sizeof(u8), - PCI_DMA_FROMDEVICE); - - first = *(priv->rxringtail) & (1<<29) ? 1 : 0; - if (first) - priv->rx_prevlen = 0; - - last = *(priv->rxringtail) & (1<<28) ? 1 : 0; - if (last) { - lastlen = ((*priv->rxringtail) & 0xfff); - - /* if the last descriptor (that should tell us the total - * packet len) tell us something less than the - * descriptors len we had until now, then there is some - * problem.. - * workaround to prevent kernel panic - */ - if (lastlen < priv->rx_prevlen) - len = 0; - else - len = lastlen-priv->rx_prevlen; - - if (*(priv->rxringtail) & (1<<13)) { - if ((*(priv->rxringtail) & 0xfff) < 500) - priv->stats.rxcrcerrmin++; - else if ((*(priv->rxringtail) & 0x0fff) > 1000) - priv->stats.rxcrcerrmax++; - else - priv->stats.rxcrcerrmid++; - - } - - } else { - len = priv->rxbuffersize; - } - - if (first && last) { - padding = ((*(priv->rxringtail+3))&(0x04000000))>>26; - } else if (first) { - padding = ((*(priv->rxringtail+3))&(0x04000000))>>26; - if (padding) - len -= 2; - } else { - padding = 0; - } - padding = 0; - priv->rx_prevlen += len; - - if (priv->rx_prevlen > MAX_FRAG_THRESHOLD + 100) { - /* HW is probably passing several buggy frames without - * FD or LD flag set. - * Throw this garbage away to prevent skb memory - * exhausting - */ - if (!priv->rx_skb_complete) - dev_kfree_skb_any(priv->rx_skb); - priv->rx_skb_complete = 1; - } - - signal = (unsigned char)((*(priv->rxringtail + 3) & - 0x00ff0000) >> 16); - signal = (signal & 0xfe) >> 1; - - quality = (unsigned char)((*(priv->rxringtail+3)) & (0xff)); - - stats.mac_time[0] = *(priv->rxringtail+1); - stats.mac_time[1] = *(priv->rxringtail+2); - - rxpower = ((char)((*(priv->rxringtail + 4) & - 0x00ff0000) >> 16)) / 2 - 42; - - RSSI = ((u8)((*(priv->rxringtail + 3) & - 0x0000ff00) >> 8)) & 0x7f; - - rate = ((*(priv->rxringtail)) & - ((1<<23)|(1<<22)|(1<<21)|(1<<20)))>>20; - - stats.rate = rtl8180_rate2rate(rate); - Antenna = (*(priv->rxringtail + 3) & 0x00008000) == 0 ? 0 : 1; - if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */ - RxAGC_dBm = rxpower+1; /* bias */ - } else { /* CCK rate. */ - RxAGC_dBm = signal; /* bit 0 discard */ - - LNA = (u8) (RxAGC_dBm & 0x60) >> 5; /* bit 6~ bit 5 */ - BB = (u8) (RxAGC_dBm & 0x1F); /* bit 4 ~ bit 0 */ - - /* Pin_11b=-(LNA_gain+BB_gain) (dBm) */ - RxAGC_dBm = -(LNA_gain[LNA] + (BB * 2)); - - RxAGC_dBm += 4; /* bias */ - } - - if (RxAGC_dBm & 0x80) /* absolute value */ - RXAGC = ~(RxAGC_dBm)+1; - bCckRate = rtl8180_IsWirelessBMode(stats.rate); - /* Translate RXAGC into 1-100. */ - if (!rtl8180_IsWirelessBMode(stats.rate)) { /* OFDM rate. */ - if (RXAGC > 90) - RXAGC = 90; - else if (RXAGC < 25) - RXAGC = 25; - RXAGC = (90-RXAGC)*100/65; - } else { /* CCK rate. */ - if (RXAGC > 95) - RXAGC = 95; - else if (RXAGC < 30) - RXAGC = 30; - RXAGC = (95-RXAGC)*100/65; - } - priv->SignalStrength = (u8)RXAGC; - priv->RecvSignalPower = RxAGC_dBm; - priv->RxPower = rxpower; - priv->RSSI = RSSI; - /* SQ translation formula is provided by SD3 DZ. 2006.06.27 */ - if (quality >= 127) - /* 0 causes epc to show signal zero, walk around now */ - quality = 1; - else if (quality < 27) - quality = 100; - else - quality = 127 - quality; - priv->SignalQuality = quality; - - stats.signal = (u8) quality; - - stats.signalstrength = RXAGC; - if (stats.signalstrength > 100) - stats.signalstrength = 100; - stats.signalstrength = (stats.signalstrength * 70) / 100 + 30; - stats.rssi = priv->wstats.qual.qual = priv->SignalQuality; - stats.noise = priv->wstats.qual.noise = - 100 - priv->wstats.qual.qual; - bHwError = (((*(priv->rxringtail)) & (0x00000fff)) == 4080) | - (((*(priv->rxringtail)) & (0x04000000)) != 0) | - (((*(priv->rxringtail)) & (0x08000000)) != 0) | - (((~(*(priv->rxringtail))) & (0x10000000)) != 0) | - (((~(*(priv->rxringtail))) & (0x20000000)) != 0); - bCRC = ((*(priv->rxringtail)) & (0x00002000)) >> 13; - bICV = ((*(priv->rxringtail)) & (0x00001000)) >> 12; - hdr = (struct ieee80211_hdr_4addr *)priv->rxbuffer->buf; - fc = le16_to_cpu(hdr->frame_ctl); - type = WLAN_FC_GET_TYPE(fc); - - if (IEEE80211_FTYPE_CTL != type && - !bHwError && !bCRC && !bICV && - eqMacAddr(priv->ieee80211->current_network.bssid, - fc & IEEE80211_FCTL_TODS ? hdr->addr1 : - fc & IEEE80211_FCTL_FROMDS ? hdr->addr2 : - hdr->addr3)) { - - /* Perform signal smoothing for dynamic - * mechanism on demand. This is different - * with PerformSignalSmoothing8185 in smoothing - * fomula. No dramatic adjustion is apply - * because dynamic mechanism need some degree - * of correctness. */ - PerformUndecoratedSignalSmoothing8185(priv, bCckRate); - - /* For good-looking singal strength. */ - SignalStrengthIndex = NetgearSignalStrengthTranslate( - priv->LastSignalStrengthInPercent, - priv->SignalStrength); - - priv->LastSignalStrengthInPercent = SignalStrengthIndex; - priv->Stats_SignalStrength = - TranslateToDbm8185((u8)SignalStrengthIndex); - - /* - * We need more correct power of received packets and - * the "SignalStrength" of RxStats is beautified, so we - * record the correct power here. - */ - - priv->Stats_SignalQuality = (long)( - priv->Stats_SignalQuality * 5 + - (long)priv->SignalQuality + 5) / 6; - - priv->Stats_RecvSignalPower = (long)( - priv->Stats_RecvSignalPower * 5 + - priv->RecvSignalPower - 1) / 6; - - /* - * Figure out which antenna received the last packet. - * 0: aux, 1: main - */ - priv->LastRxPktAntenna = Antenna ? 1 : 0; - SwAntennaDiversityRxOk8185(dev, priv->SignalStrength); - } - - if (first) { - if (!priv->rx_skb_complete) { - /* seems that HW sometimes fails to receive and - * doesn't provide the last descriptor. - */ - dev_kfree_skb_any(priv->rx_skb); - priv->stats.rxnolast++; - } - priv->rx_skb = dev_alloc_skb(len+2); - if (!priv->rx_skb) - goto drop; - - priv->rx_skb_complete = 0; - priv->rx_skb->dev = dev; - } else { - /* if we are here we should have already RXed the first - * frame. - * If we get here and the skb is not allocated then - * we have just throw out garbage (skb not allocated) - * and we are still rxing garbage.... - */ - if (!priv->rx_skb_complete) { - - tmp_skb = dev_alloc_skb( - priv->rx_skb->len + len + 2); - - if (!tmp_skb) - goto drop; - - tmp_skb->dev = dev; - - memcpy(skb_put(tmp_skb, priv->rx_skb->len), - priv->rx_skb->data, - priv->rx_skb->len); - - dev_kfree_skb_any(priv->rx_skb); - - priv->rx_skb = tmp_skb; - } - } - - if (!priv->rx_skb_complete) { - memcpy(skb_put(priv->rx_skb, len), ((unsigned char *) - priv->rxbuffer->buf) + (padding ? 2 : 0), len); - } - - if (last && !priv->rx_skb_complete) { - if (priv->rx_skb->len > 4) - skb_trim(priv->rx_skb, priv->rx_skb->len-4); - if (!ieee80211_rtl_rx(priv->ieee80211, - priv->rx_skb, &stats)) - dev_kfree_skb_any(priv->rx_skb); - priv->rx_skb_complete = 1; - } - - pci_dma_sync_single_for_device(priv->pdev, - priv->rxbuffer->dma, - priv->rxbuffersize * sizeof(u8), - PCI_DMA_FROMDEVICE); - -drop: /* this is used when we have not enough mem */ - /* restore the descriptor */ - *(priv->rxringtail+2) = priv->rxbuffer->dma; - *(priv->rxringtail) = *(priv->rxringtail) & ~0xfff; - *(priv->rxringtail) = - *(priv->rxringtail) | priv->rxbuffersize; - - *(priv->rxringtail) = - *(priv->rxringtail) | (1<<31); - - priv->rxringtail += rx_desc_size; - if (priv->rxringtail >= - (priv->rxring)+(priv->rxringcount)*rx_desc_size) - priv->rxringtail = priv->rxring; - - priv->rxbuffer = (priv->rxbuffer->next); - } -} - - -static void rtl8180_dma_kick(struct net_device *dev, int priority) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - write_nic_byte(dev, TX_DMA_POLLING, - (1 << (priority + 1)) | priv->dma_poll_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - force_pci_posting(dev); -} - -static void rtl8180_data_hard_stop(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask |= TPPOLLSTOP_AC_VIQ; - write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -static void rtl8180_data_hard_resume(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - priv->dma_poll_stop_mask &= ~(TPPOLLSTOP_AC_VIQ); - write_nic_byte(dev, TPPollStop, priv->dma_poll_stop_mask); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); -} - -/* - * This function TX data frames when the ieee80211 stack requires this. - * It checks also if we need to stop the ieee tx queue, eventually do it - */ -static void rtl8180_hard_data_xmit(struct sk_buff *skb, struct net_device *dev, - int rate) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - int mode; - struct ieee80211_hdr_3addr *h = (struct ieee80211_hdr_3addr *)skb->data; - bool morefrag = le16_to_cpu(h->frame_control) & IEEE80211_FCTL_MOREFRAGS; - unsigned long flags; - int priority; - - mode = priv->ieee80211->iw_mode; - - rate = ieeerate2rtlrate(rate); - /* - * This function doesn't require lock because we make sure it's called - * with the tx_lock already acquired. - * This come from the kernel's hard_xmit callback (through the ieee - * stack, or from the try_wake_queue (again through the ieee stack. - */ - priority = AC2Q(skb->priority); - spin_lock_irqsave(&priv->tx_lock, flags); - - if (priv->ieee80211->bHwRadioOff) { - spin_unlock_irqrestore(&priv->tx_lock, flags); - - return; - } - - if (!check_nic_enought_desc(dev, priority)) { - DMESGW("Error: no descriptor left by previous TX (avail %d) ", - get_curr_tx_free_desc(dev, priority)); - ieee80211_rtl_stop_queue(priv->ieee80211); - } - rtl8180_tx(dev, skb->data, skb->len, priority, morefrag, 0, rate); - if (!check_nic_enought_desc(dev, priority)) - ieee80211_rtl_stop_queue(priv->ieee80211); - - spin_unlock_irqrestore(&priv->tx_lock, flags); -} - -/* - * This is a rough attempt to TX a frame - * This is called by the ieee 80211 stack to TX management frames. - * If the ring is full packets are dropped (for data frame the queue - * is stopped before this can happen). For this reason it is better - * if the descriptors are larger than the largest management frame - * we intend to TX: i'm unsure what the HW does if it will not find - * the last fragment of a frame because it has been dropped... - * Since queues for Management and Data frames are different we - * might use a different lock than tx_lock (for example mgmt_tx_lock) - */ -/* these function may loop if invoked with 0 descriptors or 0 len buffer */ -static int rtl8180_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long flags; - int priority; - - priority = MANAGE_PRIORITY; - - spin_lock_irqsave(&priv->tx_lock, flags); - - if (priv->ieee80211->bHwRadioOff) { - spin_unlock_irqrestore(&priv->tx_lock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - rtl8180_tx(dev, skb->data, skb->len, priority, - 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate)); - - priv->ieee80211->stats.tx_bytes += skb->len; - priv->ieee80211->stats.tx_packets++; - spin_unlock_irqrestore(&priv->tx_lock, flags); - - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -static void rtl8180_prepare_beacon(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct sk_buff *skb; - - u16 word = read_nic_word(dev, BcnItv); - word &= ~BcnItv_BcnItv; /* clear Bcn_Itv */ - - /* word |= 0x64; */ - word |= cpu_to_le16(priv->ieee80211->current_network.beacon_interval); - - write_nic_word(dev, BcnItv, word); - - skb = ieee80211_get_beacon(priv->ieee80211); - if (skb) { - rtl8180_tx(dev, skb->data, skb->len, BEACON_PRIORITY, - 0, 0, ieeerate2rtlrate(priv->ieee80211->basic_rate)); - dev_kfree_skb_any(skb); - } -} - -/* - * This function do the real dirty work: it enqueues a TX command descriptor in - * the ring buffer, copyes the frame in a TX buffer and kicks the NIC to ensure - * it does the DMA transfer. - */ -short rtl8180_tx(struct net_device *dev, u8 *txbuf, int len, int priority, - bool morefrag, short descfrag, int rate) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u32 *tail, *temp_tail; - u32 *begin; - u32 *buf; - int i; - int remain; - int buflen; - int count; - struct buffer *buflist; - struct ieee80211_hdr_3addr *frag_hdr = - (struct ieee80211_hdr_3addr *)txbuf; - u8 dest[ETH_ALEN]; - u8 bUseShortPreamble = 0; - u8 bCTSEnable = 0; - u8 bRTSEnable = 0; - u16 Duration = 0; - u16 RtsDur = 0; - u16 ThisFrameTime = 0; - u16 TxDescDuration = 0; - bool ownbit_flag = false; - - switch (priority) { - case MANAGE_PRIORITY: - tail = priv->txmapringtail; - begin = priv->txmapring; - buflist = priv->txmapbufstail; - count = priv->txringcount; - break; - case BK_PRIORITY: - tail = priv->txbkpringtail; - begin = priv->txbkpring; - buflist = priv->txbkpbufstail; - count = priv->txringcount; - break; - case BE_PRIORITY: - tail = priv->txbepringtail; - begin = priv->txbepring; - buflist = priv->txbepbufstail; - count = priv->txringcount; - break; - case VI_PRIORITY: - tail = priv->txvipringtail; - begin = priv->txvipring; - buflist = priv->txvipbufstail; - count = priv->txringcount; - break; - case VO_PRIORITY: - tail = priv->txvopringtail; - begin = priv->txvopring; - buflist = priv->txvopbufstail; - count = priv->txringcount; - break; - case HI_PRIORITY: - tail = priv->txhpringtail; - begin = priv->txhpring; - buflist = priv->txhpbufstail; - count = priv->txringcount; - break; - case BEACON_PRIORITY: - tail = priv->txbeaconringtail; - begin = priv->txbeaconring; - buflist = priv->txbeaconbufstail; - count = priv->txbeaconcount; - break; - default: - return -1; - break; - } - - memcpy(&dest, frag_hdr->addr1, ETH_ALEN); - if (is_multicast_ether_addr(dest)) { - Duration = 0; - RtsDur = 0; - bRTSEnable = 0; - bCTSEnable = 0; - - ThisFrameTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, bUseShortPreamble); - TxDescDuration = ThisFrameTime; - } else { /* Unicast packet */ - u16 AckTime; - - /* for Keep alive */ - priv->NumTxUnicast++; - - /* Figure out ACK rate according to BSS basic rate - * and Tx rate. - * AckCTSLng = 14 use 1M bps send - */ - AckTime = ComputeTxTime(14, 10, 0, 0); - - if (((len + sCrcLng) > priv->rts) && priv->rts) { /* RTS/CTS. */ - u16 RtsTime, CtsTime; - bRTSEnable = 1; - bCTSEnable = 0; - - /* Rate and time required for RTS. */ - RtsTime = ComputeTxTime(sAckCtsLng / 8, - priv->ieee80211->basic_rate, 0, 0); - - /* Rate and time required for CTS. - * AckCTSLng = 14 use 1M bps send - */ - CtsTime = ComputeTxTime(14, 10, 0, 0); - - /* Figure out time required to transmit this frame. */ - ThisFrameTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, - bUseShortPreamble); - - /* RTS-CTS-ThisFrame-ACK. */ - RtsDur = CtsTime + ThisFrameTime + - AckTime + 3 * aSifsTime; - - TxDescDuration = RtsTime + RtsDur; - } else { /* Normal case. */ - bCTSEnable = 0; - bRTSEnable = 0; - RtsDur = 0; - - ThisFrameTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, bUseShortPreamble); - TxDescDuration = ThisFrameTime + aSifsTime + AckTime; - } - - if (!(le16_to_cpu(frag_hdr->frame_control) & IEEE80211_FCTL_MOREFRAGS)) { - /* ThisFrame-ACK. */ - Duration = aSifsTime + AckTime; - } else { /* One or more fragments remained. */ - u16 NextFragTime; - - /* pretend following packet length = current packet */ - NextFragTime = ComputeTxTime(len + sCrcLng, - rtl8180_rate2rate(rate), 0, bUseShortPreamble); - - /* ThisFrag-ACk-NextFrag-ACK. */ - Duration = NextFragTime + 3 * aSifsTime + 2 * AckTime; - } - - } /* End of Unicast packet */ - - frag_hdr->duration_id = Duration; - - buflen = priv->txbuffsize; - remain = len; - temp_tail = tail; - - while (remain != 0) { - mb(); - if (!buflist) { - DMESGE("TX buffer error, cannot TX frames. pri %d.", - priority); - return -1; - } - buf = buflist->buf; - - if ((*tail & (1 << 31)) && (priority != BEACON_PRIORITY)) { - DMESGW("No more TX desc, returning %x of %x", - remain, len); - priv->stats.txrdu++; - return remain; - } - - *tail = 0; /* zeroes header */ - *(tail+1) = 0; - *(tail+3) = 0; - *(tail+5) = 0; - *(tail+6) = 0; - *(tail+7) = 0; - - /* FIXME: should be triggered by HW encryption parameters.*/ - *tail |= (1<<15); /* no encrypt */ - - if (remain == len && !descfrag) { - ownbit_flag = false; - *tail = *tail | (1 << 29); /* first segment of packet */ - *tail = *tail | (len); - } else { - ownbit_flag = true; - } - - for (i = 0; i < buflen && remain > 0; i++, remain--) { - /* copy data into descriptor pointed DMAble buffer */ - ((u8 *)buf)[i] = txbuf[i]; - - if (remain == 4 && i+4 >= buflen) - break; - /* ensure the last desc has at least 4 bytes payload */ - } - txbuf = txbuf + i; - *(tail+3) = *(tail+3) & ~0xfff; - *(tail+3) = *(tail+3) | i; /* buffer length */ - - if (bCTSEnable) - *tail |= (1<<18); - - if (bRTSEnable) { /* rts enable */ - /* RTS RATE */ - *tail |= (ieeerate2rtlrate( - priv->ieee80211->basic_rate) << 19); - - *tail |= (1<<23); /* rts enable */ - *(tail+1) |= (RtsDur&0xffff); /* RTS Duration */ - } - *(tail+3) |= ((TxDescDuration&0xffff)<<16); /* DURATION */ - - *(tail + 5) |= (11 << 8); /* retry lim; */ - - *tail = *tail | ((rate&0xf) << 24); - - if (morefrag) - *tail = (*tail) | (1<<17); /* more fragment */ - if (!remain) - *tail = (*tail) | (1<<28); /* last segment of frame */ - - *(tail+5) = *(tail+5)|(2<<27); - *(tail+7) = *(tail+7)|(1<<4); - - wmb(); - if (ownbit_flag) - /* descriptor ready to be txed */ - *tail |= (1 << 31); - - if ((tail - begin)/8 == count-1) - tail = begin; - else - tail = tail+8; - - buflist = buflist->next; - - mb(); - - switch (priority) { - case MANAGE_PRIORITY: - priv->txmapringtail = tail; - priv->txmapbufstail = buflist; - break; - case BK_PRIORITY: - priv->txbkpringtail = tail; - priv->txbkpbufstail = buflist; - break; - case BE_PRIORITY: - priv->txbepringtail = tail; - priv->txbepbufstail = buflist; - break; - case VI_PRIORITY: - priv->txvipringtail = tail; - priv->txvipbufstail = buflist; - break; - case VO_PRIORITY: - priv->txvopringtail = tail; - priv->txvopbufstail = buflist; - break; - case HI_PRIORITY: - priv->txhpringtail = tail; - priv->txhpbufstail = buflist; - break; - case BEACON_PRIORITY: - /* - * The HW seems to be happy with the 1st - * descriptor filled and the 2nd empty... - * So always update descriptor 1 and never - * touch 2nd - */ - break; - } - } - *temp_tail = *temp_tail | (1<<31); /* descriptor ready to be txed */ - rtl8180_dma_kick(dev, priority); - - return 0; -} - -void rtl8180_irq_rx_tasklet(struct r8180_priv *priv); - -static void rtl8180_link_change(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 beacon_interval; - struct ieee80211_network *net = &priv->ieee80211->current_network; - - rtl8180_update_msr(dev); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - - write_nic_dword(dev, BSSID, ((u32 *)net->bssid)[0]); - write_nic_word(dev, BSSID+4, ((u16 *)net->bssid)[2]); - - beacon_interval = read_nic_word(dev, BEACON_INTERVAL); - beacon_interval &= ~BEACON_INTERVAL_MASK; - beacon_interval |= net->beacon_interval; - write_nic_word(dev, BEACON_INTERVAL, beacon_interval); - - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - rtl8180_set_chan(dev, priv->chan); -} - -static void rtl8180_rq_tx_ack(struct net_device *dev) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - - write_nic_byte(dev, CONFIG4, - read_nic_byte(dev, CONFIG4) | CONFIG4_PWRMGT); - priv->ack_tx_to_ieee = 1; -} - -static short rtl8180_is_tx_queue_empty(struct net_device *dev) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - u32 *d; - - for (d = priv->txmapring; - d < priv->txmapring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txbkpring; - d < priv->txbkpring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txbepring; - d < priv->txbepring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txvipring; - d < priv->txvipring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txvopring; - d < priv->txvopring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - - for (d = priv->txhpring; - d < priv->txhpring + priv->txringcount; d += 8) - if (*d & (1<<31)) - return 0; - return 1; -} - -static void rtl8180_hw_wakeup(struct net_device *dev) -{ - unsigned long flags; - struct r8180_priv *priv = ieee80211_priv(dev); - - spin_lock_irqsave(&priv->ps_lock, flags); - write_nic_byte(dev, CONFIG4, - read_nic_byte(dev, CONFIG4) & ~CONFIG4_PWRMGT); - if (priv->rf_wakeup) - priv->rf_wakeup(dev); - spin_unlock_irqrestore(&priv->ps_lock, flags); -} - -static void rtl8180_hw_sleep_down(struct net_device *dev) -{ - unsigned long flags; - struct r8180_priv *priv = ieee80211_priv(dev); - - spin_lock_irqsave(&priv->ps_lock, flags); - if (priv->rf_sleep) - priv->rf_sleep(dev); - spin_unlock_irqrestore(&priv->ps_lock, flags); -} - -static void rtl8180_hw_sleep(struct net_device *dev, u32 th, u32 tl) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u32 rb = jiffies; - unsigned long flags; - - spin_lock_irqsave(&priv->ps_lock, flags); - - /* - * Writing HW register with 0 equals to disable - * the timer, that is not really what we want - */ - tl -= MSECS(4+16+7); - - /* - * If the interval in which we are requested to sleep is too - * short then give up and remain awake - */ - if (((tl >= rb) && (tl-rb) <= MSECS(MIN_SLEEP_TIME)) - || ((rb > tl) && (rb-tl) < MSECS(MIN_SLEEP_TIME))) { - spin_unlock_irqrestore(&priv->ps_lock, flags); - netdev_warn(dev, "too short to sleep\n"); - return; - } - - { - u32 tmp = (tl > rb) ? (tl-rb) : (rb-tl); - - priv->DozePeriodInPast2Sec += jiffies_to_msecs(tmp); - /* as tl may be less than rb */ - queue_delayed_work(priv->ieee80211->wq, - &priv->ieee80211->hw_wakeup_wq, tmp); - } - /* - * If we suspect the TimerInt is gone beyond tl - * while setting it, then give up - */ - - if (((tl > rb) && ((tl-rb) > MSECS(MAX_SLEEP_TIME))) || - ((tl < rb) && ((rb-tl) > MSECS(MAX_SLEEP_TIME)))) { - spin_unlock_irqrestore(&priv->ps_lock, flags); - return; - } - - queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->hw_sleep_wq); - spin_unlock_irqrestore(&priv->ps_lock, flags); -} - -static void rtl8180_wmm_single_param_update(struct net_device *dev, - u8 mode, AC_CODING eACI, PAC_PARAM param) -{ - u8 u1bAIFS; - u32 u4bAcParam; - - /* Retrieve parameters to update. */ - /* Mode G/A: slotTimeTimer = 9; Mode B: 20 */ - u1bAIFS = param->f.AciAifsn.f.AIFSN * ((mode & IEEE_G) == IEEE_G ? - 9 : 20) + aSifsTime; - u4bAcParam = (((u32)param->f.TXOPLimit << AC_PARAM_TXOP_LIMIT_OFFSET) | - ((u32)param->f.Ecw.f.ECWmax << AC_PARAM_ECW_MAX_OFFSET) | - ((u32)param->f.Ecw.f.ECWmin << AC_PARAM_ECW_MIN_OFFSET) | - ((u32)u1bAIFS << AC_PARAM_AIFS_OFFSET)); - - switch (eACI) { - case AC1_BK: - write_nic_dword(dev, AC_BK_PARAM, u4bAcParam); - return; - case AC0_BE: - write_nic_dword(dev, AC_BE_PARAM, u4bAcParam); - return; - case AC2_VI: - write_nic_dword(dev, AC_VI_PARAM, u4bAcParam); - return; - case AC3_VO: - write_nic_dword(dev, AC_VO_PARAM, u4bAcParam); - return; - default: - pr_warn("SetHwReg8185(): invalid ACI: %d!\n", eACI); - return; - } -} - -static void rtl8180_wmm_param_update(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of(work, - struct ieee80211_device, wmm_param_update_wq); - struct net_device *dev = ieee->dev; - u8 *ac_param = (u8 *)(ieee->current_network.wmm_param); - u8 mode = ieee->current_network.mode; - AC_CODING eACI; - AC_PARAM AcParam; - - if (!ieee->current_network.QoS_Enable) { - /* legacy ac_xx_param update */ - AcParam.longData = 0; - AcParam.f.AciAifsn.f.AIFSN = 2; /* Follow 802.11 DIFS. */ - AcParam.f.AciAifsn.f.ACM = 0; - AcParam.f.Ecw.f.ECWmin = 3; /* Follow 802.11 CWmin. */ - AcParam.f.Ecw.f.ECWmax = 7; /* Follow 802.11 CWmax. */ - AcParam.f.TXOPLimit = 0; - - for (eACI = 0; eACI < AC_MAX; eACI++) { - AcParam.f.AciAifsn.f.ACI = (u8)eACI; - - rtl8180_wmm_single_param_update(dev, mode, eACI, - (PAC_PARAM)&AcParam); - } - return; - } - - for (eACI = 0; eACI < AC_MAX; eACI++) { - rtl8180_wmm_single_param_update(dev, mode, - ((PAC_PARAM)ac_param)->f.AciAifsn.f.ACI, - (PAC_PARAM)ac_param); - - ac_param += sizeof(AC_PARAM); - } -} - -void rtl8180_restart_wq(struct work_struct *work); -void rtl8180_watch_dog_wq(struct work_struct *work); -void rtl8180_hw_wakeup_wq(struct work_struct *work); -void rtl8180_hw_sleep_wq(struct work_struct *work); -void rtl8180_sw_antenna_wq(struct work_struct *work); -void rtl8180_watch_dog(struct net_device *dev); - -static void watch_dog_adaptive(unsigned long data) -{ - struct r8180_priv *priv = ieee80211_priv((struct net_device *)data); - - if (!priv->up) { - DMESG("<----watch_dog_adaptive():driver is not up!\n"); - return; - } - - /* Tx High Power Mechanism. */ - if (CheckHighPower((struct net_device *)data)) - queue_work(priv->ieee80211->wq, - (void *)&priv->ieee80211->tx_pw_wq); - - /* Tx Power Tracking on 87SE. */ - if (CheckTxPwrTracking((struct net_device *)data)) - TxPwrTracking87SE((struct net_device *)data); - - /* Perform DIG immediately. */ - if (CheckDig((struct net_device *)data)) - queue_work(priv->ieee80211->wq, - (void *)&priv->ieee80211->hw_dig_wq); - - rtl8180_watch_dog((struct net_device *)data); - - queue_work(priv->ieee80211->wq, - (void *)&priv->ieee80211->GPIOChangeRFWorkItem); - - priv->watch_dog_timer.expires = jiffies + - MSECS(IEEE80211_WATCH_DOG_TIME); - - add_timer(&priv->watch_dog_timer); -} - -static struct rtl8187se_channel_list channel_plan_list[] = { - /* FCC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, - 44, 48, 52, 56, 60, 64}, 19}, - - /* IC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, - - /* ETSI */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* Spain. Change to ETSI. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* France. Change to ETSI. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* MKK */ - {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9}, - - /* MKK1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, - 40, 44, 48, 52, 56, 60, 64}, 22}, - - /* Israel. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, - 44, 48, 52, 56, 60, 64}, 21}, - - /* For 11a , TELEC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17}, - - /* For Global Domain. 1-11 active, 12-14 passive. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, - - /* world wide 13: ch1~ch11 active, ch12~13 passive */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13} -}; - -static void rtl8180_set_channel_map(u8 channel_plan, - struct ieee80211_device *ieee) -{ - int i; - - ieee->MinPassiveChnlNum = MAX_CHANNEL_NUMBER+1; - ieee->IbssStartChnl = 0; - - switch (channel_plan) { - case COUNTRY_CODE_FCC: - case COUNTRY_CODE_IC: - case COUNTRY_CODE_ETSI: - case COUNTRY_CODE_SPAIN: - case COUNTRY_CODE_FRANCE: - case COUNTRY_CODE_MKK: - case COUNTRY_CODE_MKK1: - case COUNTRY_CODE_ISRAEL: - case COUNTRY_CODE_TELEC: - { - Dot11d_Init(ieee); - ieee->bGlobalDomain = false; - if (channel_plan_list[channel_plan].len != 0) { - /* Clear old channel map */ - memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); - /* Set new channel map */ - for (i = 0; i < channel_plan_list[channel_plan].len; i++) { - if (channel_plan_list[channel_plan].channel[i] <= 14) - GET_DOT11D_INFO(ieee)->channel_map[channel_plan_list[channel_plan].channel[i]] = 1; - } - } - break; - } - case COUNTRY_CODE_GLOBAL_DOMAIN: - { - GET_DOT11D_INFO(ieee)->bEnabled = false; - Dot11d_Reset(ieee); - ieee->bGlobalDomain = true; - break; - } - case COUNTRY_CODE_WORLD_WIDE_13_INDEX: - { - ieee->MinPassiveChnlNum = 12; - ieee->IbssStartChnl = 10; - break; - } - default: - { - Dot11d_Init(ieee); - ieee->bGlobalDomain = false; - memset(GET_DOT11D_INFO(ieee)->channel_map, 0, sizeof(GET_DOT11D_INFO(ieee)->channel_map)); - for (i = 1; i <= 14; i++) - GET_DOT11D_INFO(ieee)->channel_map[i] = 1; - break; - } - } -} - -void GPIOChangeRFWorkItemCallBack(struct work_struct *work); - -static void rtl8180_statistics_init(struct stats *pstats) -{ - memset(pstats, 0, sizeof(struct stats)); -} - -static void rtl8180_link_detect_init(struct link_detect_t *plink_detect) -{ - memset(plink_detect, 0, sizeof(struct link_detect_t)); - plink_detect->slot_num = DEFAULT_SLOT_NUM; -} - -static void rtl8187se_eeprom_register_read(struct eeprom_93cx6 *eeprom) -{ - struct net_device *dev = eeprom->data; - u8 reg = read_nic_byte(dev, EPROM_CMD); - - eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; - eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; - eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; - eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; -} - -static void rtl8187se_eeprom_register_write(struct eeprom_93cx6 *eeprom) -{ - struct net_device *dev = eeprom->data; - u8 reg = 2 << 6; - - if (eeprom->reg_data_in) - reg |= RTL818X_EEPROM_CMD_WRITE; - if (eeprom->reg_data_out) - reg |= RTL818X_EEPROM_CMD_READ; - if (eeprom->reg_data_clock) - reg |= RTL818X_EEPROM_CMD_CK; - if (eeprom->reg_chip_select) - reg |= RTL818X_EEPROM_CMD_CS; - - write_nic_byte(dev, EPROM_CMD, reg); - read_nic_byte(dev, EPROM_CMD); - udelay(10); -} - -static short rtl8180_init(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 word; - u16 usValue; - u16 tmpu16; - int i, j; - struct eeprom_93cx6 eeprom; - u16 eeprom_val; - - eeprom.data = dev; - eeprom.register_read = rtl8187se_eeprom_register_read; - eeprom.register_write = rtl8187se_eeprom_register_write; - eeprom.width = PCI_EEPROM_WIDTH_93C46; - - eeprom_93cx6_read(&eeprom, EEPROM_COUNTRY_CODE>>1, &eeprom_val); - priv->channel_plan = eeprom_val & 0xFF; - if (priv->channel_plan > COUNTRY_CODE_GLOBAL_DOMAIN) { - netdev_err(dev, "rtl8180_init: Invalid channel plan! Set to default.\n"); - priv->channel_plan = 0; - } - - DMESG("Channel plan is %d\n", priv->channel_plan); - rtl8180_set_channel_map(priv->channel_plan, priv->ieee80211); - - /* FIXME: these constants are placed in a bad pleace. */ - priv->txbuffsize = 2048; /* 1024; */ - priv->txringcount = 32; /* 32; */ - priv->rxbuffersize = 2048; /* 1024; */ - priv->rxringcount = 64; /* 32; */ - priv->txbeaconcount = 2; - priv->rx_skb_complete = 1; - - priv->RFChangeInProgress = false; - priv->SetRFPowerStateInProgress = false; - priv->RFProgType = 0; - - priv->irq_enabled = 0; - - rtl8180_statistics_init(&priv->stats); - rtl8180_link_detect_init(&priv->link_detect); - - priv->ack_tx_to_ieee = 0; - priv->ieee80211->current_network.beacon_interval = - DEFAULT_BEACONINTERVAL; - priv->ieee80211->iw_mode = IW_MODE_INFRA; - priv->ieee80211->softmac_features = IEEE_SOFTMAC_SCAN | - IEEE_SOFTMAC_ASSOCIATE | IEEE_SOFTMAC_PROBERQ | - IEEE_SOFTMAC_PROBERS | IEEE_SOFTMAC_TX_QUEUE; - priv->ieee80211->active_scan = 1; - priv->ieee80211->rate = 110; /* 11 mbps */ - priv->ieee80211->modulation = IEEE80211_CCK_MODULATION; - priv->ieee80211->host_encrypt = 1; - priv->ieee80211->host_decrypt = 1; - priv->ieee80211->sta_wake_up = rtl8180_hw_wakeup; - priv->ieee80211->ps_request_tx_ack = rtl8180_rq_tx_ack; - priv->ieee80211->enter_sleep_state = rtl8180_hw_sleep; - priv->ieee80211->ps_is_queue_empty = rtl8180_is_tx_queue_empty; - - priv->hw_wep = hwwep; - priv->dev = dev; - priv->retry_rts = DEFAULT_RETRY_RTS; - priv->retry_data = DEFAULT_RETRY_DATA; - priv->RFChangeInProgress = false; - priv->SetRFPowerStateInProgress = false; - priv->RFProgType = 0; - priv->bInactivePs = true; /* false; */ - priv->ieee80211->bInactivePs = priv->bInactivePs; - priv->bSwRfProcessing = false; - priv->eRFPowerState = RF_OFF; - priv->RfOffReason = 0; - priv->led_strategy = SW_LED_MODE0; - priv->TxPollingTimes = 0; - priv->bLeisurePs = true; - priv->dot11PowerSaveMode = ACTIVE; - priv->AdMinCheckPeriod = 5; - priv->AdMaxCheckPeriod = 10; - priv->AdMaxRxSsThreshold = 30; /* 60->30 */ - priv->AdRxSsThreshold = 20; /* 50->20 */ - priv->AdCheckPeriod = priv->AdMinCheckPeriod; - priv->AdTickCount = 0; - priv->AdRxSignalStrength = -1; - priv->RegSwAntennaDiversityMechanism = 0; - priv->RegDefaultAntenna = 0; - priv->SignalStrength = 0; - priv->AdRxOkCnt = 0; - priv->CurrAntennaIndex = 0; - priv->AdRxSsBeforeSwitched = 0; - init_timer(&priv->SwAntennaDiversityTimer); - priv->SwAntennaDiversityTimer.data = (unsigned long)dev; - priv->SwAntennaDiversityTimer.function = - (void *)SwAntennaDiversityTimerCallback; - priv->bDigMechanism = true; - priv->InitialGain = 6; - priv->bXtalCalibration = false; - priv->XtalCal_Xin = 0; - priv->XtalCal_Xout = 0; - priv->bTxPowerTrack = false; - priv->ThermalMeter = 0; - priv->FalseAlarmRegValue = 0; - priv->RegDigOfdmFaUpTh = 0xc; /* Upper threshold of OFDM false alarm, - which is used in DIG. */ - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote = 0; - priv->LastSignalStrengthInPercent = 0; - priv->Stats_SignalStrength = 0; - priv->LastRxPktAntenna = 0; - priv->SignalQuality = 0; /* in 0-100 index. */ - priv->Stats_SignalQuality = 0; - priv->RecvSignalPower = 0; /* in dBm. */ - priv->Stats_RecvSignalPower = 0; - priv->AdMainAntennaRxOkCnt = 0; - priv->AdAuxAntennaRxOkCnt = 0; - priv->bHWAdSwitched = false; - priv->bRegHighPowerMechanism = true; - priv->RegHiPwrUpperTh = 77; - priv->RegHiPwrLowerTh = 75; - priv->RegRSSIHiPwrUpperTh = 70; - priv->RegRSSIHiPwrLowerTh = 20; - priv->bCurCCKPkt = false; - priv->UndecoratedSmoothedSS = -1; - priv->bToUpdateTxPwr = false; - priv->CurCCKRSSI = 0; - priv->RxPower = 0; - priv->RSSI = 0; - priv->NumTxOkTotal = 0; - priv->NumTxUnicast = 0; - priv->keepAliveLevel = DEFAULT_KEEP_ALIVE_LEVEL; - priv->CurrRetryCnt = 0; - priv->LastRetryCnt = 0; - priv->LastTxokCnt = 0; - priv->LastRxokCnt = 0; - priv->LastRetryRate = 0; - priv->bTryuping = 0; - priv->CurrTxRate = 0; - priv->CurrRetryRate = 0; - priv->TryupingCount = 0; - priv->TryupingCountNoData = 0; - priv->TryDownCountLowData = 0; - priv->LastTxOKBytes = 0; - priv->LastFailTxRate = 0; - priv->LastFailTxRateSS = 0; - priv->FailTxRateCount = 0; - priv->LastTxThroughput = 0; - priv->NumTxOkBytesTotal = 0; - priv->ForcedDataRate = 0; - priv->RegBModeGainStage = 1; - - priv->promisc = (dev->flags & IFF_PROMISC) ? 1 : 0; - spin_lock_init(&priv->irq_th_lock); - spin_lock_init(&priv->tx_lock); - spin_lock_init(&priv->ps_lock); - spin_lock_init(&priv->rf_ps_lock); - sema_init(&priv->wx_sem, 1); - INIT_WORK(&priv->reset_wq, (void *)rtl8180_restart_wq); - INIT_DELAYED_WORK(&priv->ieee80211->hw_wakeup_wq, - (void *)rtl8180_hw_wakeup_wq); - INIT_DELAYED_WORK(&priv->ieee80211->hw_sleep_wq, - (void *)rtl8180_hw_sleep_wq); - INIT_WORK(&priv->ieee80211->wmm_param_update_wq, - (void *)rtl8180_wmm_param_update); - INIT_DELAYED_WORK(&priv->ieee80211->rate_adapter_wq, - (void *)rtl8180_rate_adapter); - INIT_DELAYED_WORK(&priv->ieee80211->hw_dig_wq, - (void *)rtl8180_hw_dig_wq); - INIT_DELAYED_WORK(&priv->ieee80211->tx_pw_wq, - (void *)rtl8180_tx_pw_wq); - INIT_DELAYED_WORK(&priv->ieee80211->GPIOChangeRFWorkItem, - (void *) GPIOChangeRFWorkItemCallBack); - tasklet_init(&priv->irq_rx_tasklet, - (void(*)(unsigned long)) rtl8180_irq_rx_tasklet, - (unsigned long)priv); - - init_timer(&priv->watch_dog_timer); - priv->watch_dog_timer.data = (unsigned long)dev; - priv->watch_dog_timer.function = watch_dog_adaptive; - - init_timer(&priv->rateadapter_timer); - priv->rateadapter_timer.data = (unsigned long)dev; - priv->rateadapter_timer.function = timer_rate_adaptive; - priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD; - priv->bEnhanceTxPwr = false; - - priv->ieee80211->softmac_hard_start_xmit = rtl8180_hard_start_xmit; - priv->ieee80211->set_chan = rtl8180_set_chan; - priv->ieee80211->link_change = rtl8180_link_change; - priv->ieee80211->softmac_data_hard_start_xmit = rtl8180_hard_data_xmit; - priv->ieee80211->data_hard_stop = rtl8180_data_hard_stop; - priv->ieee80211->data_hard_resume = rtl8180_data_hard_resume; - - priv->ieee80211->init_wmmparam_flag = 0; - - priv->ieee80211->start_send_beacons = rtl8180_start_tx_beacon; - priv->ieee80211->stop_send_beacons = rtl8180_beacon_tx_disable; - priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; - - priv->ShortRetryLimit = 7; - priv->LongRetryLimit = 7; - priv->EarlyRxThreshold = 7; - - priv->TransmitConfig = (1<ShortRetryLimit<LongRetryLimit<ReceiveConfig = RCR_AMF | RCR_ADF | RCR_ACF | - RCR_AB | RCR_AM | RCR_APM | - (7<EarlyRxThreshold<EarlyRxThreshold == 7 ? - RCR_ONLYERLPKT : 0); - - priv->IntrMask = IMR_TMGDOK | IMR_TBDER | - IMR_THPDER | IMR_THPDOK | - IMR_TVODER | IMR_TVODOK | - IMR_TVIDER | IMR_TVIDOK | - IMR_TBEDER | IMR_TBEDOK | - IMR_TBKDER | IMR_TBKDOK | - IMR_RDU | - IMR_RER | IMR_ROK | - IMR_RQoSOK; - - priv->InitialGain = 6; - - DMESG("MAC controller is a RTL8187SE b/g"); - - priv->ieee80211->modulation |= IEEE80211_OFDM_MODULATION; - priv->ieee80211->short_slot = 1; - - eeprom_93cx6_read(&eeprom, EEPROM_SW_REVD_OFFSET, &usValue); - DMESG("usValue is %#hx\n", usValue); - /* 3Read AntennaDiversity */ - - /* SW Antenna Diversity. */ - priv->EEPROMSwAntennaDiversity = (usValue & EEPROM_SW_AD_MASK) == - EEPROM_SW_AD_ENABLE; - - /* Default Antenna to use. */ - priv->EEPROMDefaultAntenna1 = (usValue & EEPROM_DEF_ANT_MASK) == - EEPROM_DEF_ANT_1; - - if (priv->RegSwAntennaDiversityMechanism == 0) /* Auto */ - /* 0: default from EEPROM. */ - priv->bSwAntennaDiverity = priv->EEPROMSwAntennaDiversity; - else - /* 1:disable antenna diversity, 2: enable antenna diversity. */ - priv->bSwAntennaDiverity = - priv->RegSwAntennaDiversityMechanism == 2; - - if (priv->RegDefaultAntenna == 0) - /* 0: default from EEPROM. */ - priv->bDefaultAntenna1 = priv->EEPROMDefaultAntenna1; - else - /* 1: main, 2: aux. */ - priv->bDefaultAntenna1 = priv->RegDefaultAntenna == 2; - - priv->plcp_preamble_mode = 2; - /* the eeprom type is stored in RCR register bit #6 */ - if (RCR_9356SEL & read_nic_dword(dev, RCR)) - priv->epromtype = EPROM_93c56; - else - priv->epromtype = EPROM_93c46; - - eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *) - dev->dev_addr, 3); - - for (i = 1, j = 0; i < 14; i += 2, j++) { - eeprom_93cx6_read(&eeprom, EPROM_TXPW_CH1_2 + j, &word); - priv->chtxpwr[i] = word & 0xff; - priv->chtxpwr[i+1] = (word & 0xff00)>>8; - } - for (i = 1, j = 0; i < 14; i += 2, j++) { - eeprom_93cx6_read(&eeprom, EPROM_TXPW_OFDM_CH1_2 + j, &word); - priv->chtxpwr_ofdm[i] = word & 0xff; - priv->chtxpwr_ofdm[i+1] = (word & 0xff00) >> 8; - } - - /* 3Read crystal calibration and thermal meter indication on 87SE. */ - eeprom_93cx6_read(&eeprom, EEPROM_RSV>>1, &tmpu16); - - /* Crystal calibration for Xin and Xout resp. */ - priv->XtalCal_Xout = tmpu16 & EEPROM_XTAL_CAL_XOUT_MASK; - priv->XtalCal_Xin = (tmpu16 & EEPROM_XTAL_CAL_XIN_MASK) >> 4; - if ((tmpu16 & EEPROM_XTAL_CAL_ENABLE) >> 12) - priv->bXtalCalibration = true; - - /* Thermal meter reference indication. */ - priv->ThermalMeter = (u8)((tmpu16 & EEPROM_THERMAL_METER_MASK) >> 8); - if ((tmpu16 & EEPROM_THERMAL_METER_ENABLE) >> 13) - priv->bTxPowerTrack = true; - - priv->rf_sleep = rtl8225z4_rf_sleep; - priv->rf_wakeup = rtl8225z4_rf_wakeup; - DMESGW("**PLEASE** REPORT SUCCESSFUL/UNSUCCESSFUL TO Realtek!"); - - priv->rf_close = rtl8225z2_rf_close; - priv->rf_init = rtl8225z2_rf_init; - priv->rf_set_chan = rtl8225z2_rf_set_chan; - priv->rf_set_sens = NULL; - - if (0 != alloc_rx_desc_ring(dev, priv->rxbuffersize, priv->rxringcount)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_MANAGEPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_BKPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_BEPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_VIPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_VOPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txringcount, - TX_HIGHPRIORITY_RING_ADDR)) - return -ENOMEM; - - if (0 != alloc_tx_desc_ring(dev, priv->txbuffsize, priv->txbeaconcount, - TX_BEACON_RING_ADDR)) - return -ENOMEM; - - if (request_irq(dev->irq, rtl8180_interrupt, - IRQF_SHARED, dev->name, dev)) { - DMESGE("Error allocating IRQ %d", dev->irq); - return -1; - } else { - priv->irq = dev->irq; - DMESG("IRQ %d", dev->irq); - } - - return 0; -} - -void rtl8180_no_hw_wep(struct net_device *dev) -{ -} - -void rtl8180_set_hw_wep(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 pgreg; - u8 security; - u32 key0_word4; - - pgreg = read_nic_byte(dev, PGSELECT); - write_nic_byte(dev, PGSELECT, pgreg & ~(1<key0[3] & 0xff; - write_nic_dword(dev, KEY0, (priv->key0[0])); - write_nic_dword(dev, KEY0+4, (priv->key0[1])); - write_nic_dword(dev, KEY0+4+4, (priv->key0[2])); - write_nic_dword(dev, KEY0+4+4+4, (key0_word4)); - - security = read_nic_byte(dev, SECURITY); - security |= (1<> 24)); - write_nic_byte(dev, 0x7e, ((phyw & 0x00ff0000) >> 16)); - write_nic_byte(dev, 0x7d, ((phyw & 0x0000ff00) >> 8)); - write_nic_byte(dev, 0x7c, ((phyw & 0x000000ff))); -} - -inline void write_phy_ofdm(struct net_device *dev, u8 adr, u32 data) -{ - data = data & 0xff; - rtl8185_write_phy(dev, adr, data); -} - -void write_phy_cck(struct net_device *dev, u8 adr, u32 data) -{ - data = data & 0xff; - rtl8185_write_phy(dev, adr, data | 0x10000); -} - -/* - * This configures registers for beacon tx and enables it via - * rtl8180_beacon_tx_enable(). rtl8180_beacon_tx_disable() might - * be used to stop beacon transmission - */ -void rtl8180_start_tx_beacon(struct net_device *dev) -{ - u16 word; - - DMESG("Enabling beacon TX"); - rtl8180_prepare_beacon(dev); - rtl8180_irq_disable(dev); - rtl8180_beacon_tx_enable(dev); - - word = read_nic_word(dev, AtimWnd) & ~AtimWnd_AtimWnd; - write_nic_word(dev, AtimWnd, word); /* word |= */ - - word = read_nic_word(dev, BintrItv); - word &= ~BintrItv_BintrItv; - word |= 1000; /* priv->ieee80211->current_network.beacon_interval * - * ((priv->txbeaconcount > 1)?(priv->txbeaconcount-1):1); - * FIXME: check if correct ^^ worked with 0x3e8; - */ - write_nic_word(dev, BintrItv, word); - - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - rtl8185b_irq_enable(dev); -} - -static struct net_device_stats *rtl8180_stats(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return &priv->ieee80211->stats; -} - -/* - * Change current and default preamble mode. - */ -static bool MgntActSet_802_11_PowerSaveMode(struct r8180_priv *priv, - enum rt_ps_mode rtPsMode) -{ - /* Currently, we do not change power save mode on IBSS mode. */ - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - return false; - - priv->ieee80211->ps = rtPsMode; - - return true; -} - -static void LeisurePSEnter(struct r8180_priv *priv) -{ - if (priv->bLeisurePs) - if (priv->ieee80211->ps == IEEE80211_PS_DISABLED) - /* IEEE80211_PS_ENABLE */ - MgntActSet_802_11_PowerSaveMode(priv, - IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST); -} - -static void LeisurePSLeave(struct r8180_priv *priv) -{ - if (priv->bLeisurePs) - if (priv->ieee80211->ps != IEEE80211_PS_DISABLED) - MgntActSet_802_11_PowerSaveMode( - priv, IEEE80211_PS_DISABLED); -} - -void rtl8180_hw_wakeup_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of( - dwork, struct ieee80211_device, hw_wakeup_wq); - struct net_device *dev = ieee->dev; - - rtl8180_hw_wakeup(dev); -} - -void rtl8180_hw_sleep_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of( - dwork, struct ieee80211_device, hw_sleep_wq); - struct net_device *dev = ieee->dev; - - rtl8180_hw_sleep_down(dev); -} - -static void MgntLinkKeepAlive(struct r8180_priv *priv) -{ - if (priv->keepAliveLevel == 0) - return; - - if (priv->ieee80211->state == IEEE80211_LINKED) { - /* - * Keep-Alive. - */ - - if ((priv->keepAliveLevel == 2) || - (priv->link_detect.last_num_tx_unicast == - priv->NumTxUnicast && - priv->link_detect.last_num_rx_unicast == - priv->ieee80211->NumRxUnicast) - ) { - priv->link_detect.idle_count++; - - /* - * Send a Keep-Alive packet packet to AP if we had - * been idle for a while. - */ - if (priv->link_detect.idle_count >= - KEEP_ALIVE_INTERVAL / - CHECK_FOR_HANG_PERIOD - 1) { - priv->link_detect.idle_count = 0; - ieee80211_sta_ps_send_null_frame( - priv->ieee80211, false); - } - } else { - priv->link_detect.idle_count = 0; - } - priv->link_detect.last_num_tx_unicast = priv->NumTxUnicast; - priv->link_detect.last_num_rx_unicast = - priv->ieee80211->NumRxUnicast; - } -} - -void rtl8180_watch_dog(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - bool bEnterPS = false; - bool bBusyTraffic = false; - u32 TotalRxNum = 0; - u16 SlotIndex = 0; - u16 i = 0; - if (priv->ieee80211->actscanning == false) { - if ((priv->ieee80211->iw_mode != IW_MODE_ADHOC) && - (priv->ieee80211->state == IEEE80211_NOLINK) && - (priv->ieee80211->beinretry == false) && - (priv->eRFPowerState == RF_ON)) - IPSEnter(dev); - } - if ((priv->ieee80211->state == IEEE80211_LINKED) && - (priv->ieee80211->iw_mode == IW_MODE_INFRA)) { - SlotIndex = (priv->link_detect.slot_index++) % - priv->link_detect.slot_num; - - priv->link_detect.rx_frame_num[SlotIndex] = - priv->ieee80211->NumRxDataInPeriod + - priv->ieee80211->NumRxBcnInPeriod; - - for (i = 0; i < priv->link_detect.slot_num; i++) - TotalRxNum += priv->link_detect.rx_frame_num[i]; - - if (TotalRxNum == 0) { - priv->ieee80211->state = IEEE80211_ASSOCIATING; - queue_work(priv->ieee80211->wq, - &priv->ieee80211->associate_procedure_wq); - } - } - - MgntLinkKeepAlive(priv); - - LeisurePSLeave(priv); - - if (priv->ieee80211->state == IEEE80211_LINKED) { - priv->link_detect.num_rx_ok_in_period = - priv->ieee80211->NumRxDataInPeriod; - if (priv->link_detect.num_rx_ok_in_period > 666 || - priv->link_detect.num_tx_ok_in_period > 666) { - bBusyTraffic = true; - } - if ((priv->link_detect.num_rx_ok_in_period + - priv->link_detect.num_tx_ok_in_period > 8) - || (priv->link_detect.num_rx_ok_in_period > 2)) { - bEnterPS = false; - } else - bEnterPS = true; - - if (bEnterPS) - LeisurePSEnter(priv); - else - LeisurePSLeave(priv); - } else - LeisurePSLeave(priv); - priv->link_detect.b_busy_traffic = bBusyTraffic; - priv->link_detect.num_rx_ok_in_period = 0; - priv->link_detect.num_tx_ok_in_period = 0; - priv->ieee80211->NumRxDataInPeriod = 0; - priv->ieee80211->NumRxBcnInPeriod = 0; -} - -static int _rtl8180_up(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - priv->up = 1; - - DMESG("Bringing up iface"); - rtl8185b_adapter_start(dev); - rtl8185b_rx_enable(dev); - rtl8185b_tx_enable(dev); - if (priv->bInactivePs) { - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - IPSLeave(dev); - } - timer_rate_adaptive((unsigned long)dev); - watch_dog_adaptive((unsigned long)dev); - if (priv->bSwAntennaDiverity) - SwAntennaDiversityTimerCallback(dev); - ieee80211_softmac_start_protocol(priv->ieee80211); - return 0; -} - -static int rtl8180_open(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - down(&priv->wx_sem); - ret = rtl8180_up(dev); - up(&priv->wx_sem); - return ret; -} - -int rtl8180_up(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->up == 1) - return -1; - - return _rtl8180_up(dev); -} - -static int rtl8180_close(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - down(&priv->wx_sem); - ret = rtl8180_down(dev); - up(&priv->wx_sem); - - return ret; -} - -int rtl8180_down(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->up == 0) - return -1; - - priv->up = 0; - - ieee80211_softmac_stop_protocol(priv->ieee80211); - /* FIXME */ - if (!netif_queue_stopped(dev)) - netif_stop_queue(dev); - rtl8180_rtx_disable(dev); - rtl8180_irq_disable(dev); - del_timer_sync(&priv->watch_dog_timer); - del_timer_sync(&priv->rateadapter_timer); - cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); - cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq); - cancel_delayed_work(&priv->ieee80211->hw_sleep_wq); - cancel_delayed_work(&priv->ieee80211->hw_dig_wq); - cancel_delayed_work(&priv->ieee80211->tx_pw_wq); - del_timer_sync(&priv->SwAntennaDiversityTimer); - SetZebraRFPowerState8185(dev, RF_OFF); - memset(&priv->ieee80211->current_network, - 0, sizeof(struct ieee80211_network)); - priv->ieee80211->state = IEEE80211_NOLINK; - return 0; -} - -void rtl8180_restart_wq(struct work_struct *work) -{ - struct r8180_priv *priv = container_of( - work, struct r8180_priv, reset_wq); - struct net_device *dev = priv->dev; - - down(&priv->wx_sem); - - rtl8180_commit(dev); - - up(&priv->wx_sem); -} - -static void rtl8180_restart(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - schedule_work(&priv->reset_wq); -} - -void rtl8180_commit(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->up == 0) - return; - - del_timer_sync(&priv->watch_dog_timer); - del_timer_sync(&priv->rateadapter_timer); - cancel_delayed_work(&priv->ieee80211->rate_adapter_wq); - cancel_delayed_work(&priv->ieee80211->hw_wakeup_wq); - cancel_delayed_work(&priv->ieee80211->hw_sleep_wq); - cancel_delayed_work(&priv->ieee80211->hw_dig_wq); - cancel_delayed_work(&priv->ieee80211->tx_pw_wq); - del_timer_sync(&priv->SwAntennaDiversityTimer); - ieee80211_softmac_stop_protocol(priv->ieee80211); - rtl8180_irq_disable(dev); - rtl8180_rtx_disable(dev); - _rtl8180_up(dev); -} - -static void r8180_set_multicast(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - short promisc; - - promisc = (dev->flags & IFF_PROMISC) ? 1 : 0; - - if (promisc != priv->promisc) - rtl8180_restart(dev); - - priv->promisc = promisc; -} - -static int r8180_set_mac_adr(struct net_device *dev, void *mac) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct sockaddr *addr = mac; - - down(&priv->wx_sem); - - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - - if (priv->ieee80211->iw_mode == IW_MODE_MASTER) - memcpy(priv->ieee80211->current_network.bssid, - dev->dev_addr, ETH_ALEN); - - if (priv->up) { - rtl8180_down(dev); - rtl8180_up(dev); - } - - up(&priv->wx_sem); - - return 0; -} - -/* based on ipw2200 driver */ -static int rtl8180_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct iwreq *wrq = (struct iwreq *) rq; - int ret = -1; - - switch (cmd) { - case RTL_IOCTL_WPA_SUPPLICANT: - ret = ieee80211_wpa_supplicant_ioctl( - priv->ieee80211, &wrq->u.data); - return ret; - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} - -static const struct net_device_ops rtl8180_netdev_ops = { - .ndo_open = rtl8180_open, - .ndo_stop = rtl8180_close, - .ndo_get_stats = rtl8180_stats, - .ndo_tx_timeout = rtl8180_restart, - .ndo_do_ioctl = rtl8180_ioctl, - .ndo_set_rx_mode = r8180_set_multicast, - .ndo_set_mac_address = r8180_set_mac_adr, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, - .ndo_start_xmit = ieee80211_rtl_xmit, -}; - -static int rtl8180_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned long ioaddr = 0; - struct net_device *dev = NULL; - struct r8180_priv *priv = NULL; - u8 unit = 0; - int ret = -ENODEV; - - unsigned long pmem_start, pmem_len, pmem_flags; - - DMESG("Configuring chip resources"); - - if (pci_enable_device(pdev)) { - DMESG("Failed to enable PCI device"); - return -EIO; - } - - pci_set_master(pdev); - pci_set_dma_mask(pdev, 0xffffff00ULL); - pci_set_consistent_dma_mask(pdev, 0xffffff00ULL); - dev = alloc_ieee80211(sizeof(struct r8180_priv)); - if (!dev) { - ret = -ENOMEM; - goto fail_free; - } - priv = ieee80211_priv(dev); - priv->ieee80211 = netdev_priv(dev); - - pci_set_drvdata(pdev, dev); - SET_NETDEV_DEV(dev, &pdev->dev); - - priv = ieee80211_priv(dev); - priv->pdev = pdev; - - pmem_start = pci_resource_start(pdev, 1); - pmem_len = pci_resource_len(pdev, 1); - pmem_flags = pci_resource_flags(pdev, 1); - - if (!(pmem_flags & IORESOURCE_MEM)) { - DMESG("region #1 not a MMIO resource, aborting"); - goto fail; - } - - if (!request_mem_region(pmem_start, pmem_len, RTL8180_MODULE_NAME)) { - DMESG("request_mem_region failed!"); - goto fail; - } - - ioaddr = (unsigned long)ioremap_nocache(pmem_start, pmem_len); - if (ioaddr == (unsigned long)NULL) { - DMESG("ioremap failed!"); - goto fail1; - } - - dev->mem_start = ioaddr; /* shared mem start */ - dev->mem_end = ioaddr + pci_resource_len(pdev, 0); /* shared mem end */ - - pci_read_config_byte(pdev, 0x05, &unit); - pci_write_config_byte(pdev, 0x05, unit & (~0x04)); - - dev->irq = pdev->irq; - priv->irq = 0; - - dev->netdev_ops = &rtl8180_netdev_ops; - dev->wireless_handlers = &r8180_wx_handlers_def; - - dev->type = ARPHRD_ETHER; - dev->watchdog_timeo = HZ*3; - - if (dev_alloc_name(dev, ifname) < 0) { - DMESG("Oops: devname already taken! Trying wlan%%d...\n"); - strcpy(ifname, "wlan%d"); - dev_alloc_name(dev, ifname); - } - - if (rtl8180_init(dev) != 0) { - DMESG("Initialization failed"); - goto fail1; - } - - netif_carrier_off(dev); - - if (register_netdev(dev)) - goto fail1; - - rtl8180_proc_init_one(dev); - - DMESG("Driver probe completed\n"); - return 0; -fail1: - if (dev->mem_start != (unsigned long)NULL) { - iounmap((void __iomem *)dev->mem_start); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - } -fail: - if (dev) { - if (priv->irq) { - free_irq(dev->irq, dev); - dev->irq = 0; - } - free_ieee80211(dev); - } - -fail_free: - pci_disable_device(pdev); - - DMESG("wlan driver load failed\n"); - return ret; -} - -static void rtl8180_pci_remove(struct pci_dev *pdev) -{ - struct r8180_priv *priv; - struct net_device *dev = pci_get_drvdata(pdev); - - if (dev) { - unregister_netdev(dev); - - priv = ieee80211_priv(dev); - - rtl8180_proc_remove_one(dev); - rtl8180_down(dev); - priv->rf_close(dev); - rtl8180_reset(dev); - mdelay(10); - - if (priv->irq) { - DMESG("Freeing irq %d", dev->irq); - free_irq(dev->irq, dev); - priv->irq = 0; - } - - free_rx_desc_ring(dev); - free_tx_desc_rings(dev); - - if (dev->mem_start != (unsigned long)NULL) { - iounmap((void __iomem *)dev->mem_start); - release_mem_region(pci_resource_start(pdev, 1), - pci_resource_len(pdev, 1)); - } - - free_ieee80211(dev); - } - pci_disable_device(pdev); - - DMESG("wlan driver removed\n"); -} - -static int __init rtl8180_pci_module_init(void) -{ - int ret; - - ret = ieee80211_crypto_init(); - if (ret) { - pr_err("ieee80211_crypto_init() failed %d\n", ret); - return ret; - } - ret = ieee80211_crypto_tkip_init(); - if (ret) { - pr_err("ieee80211_crypto_tkip_init() failed %d\n", ret); - return ret; - } - ret = ieee80211_crypto_ccmp_init(); - if (ret) { - pr_err("ieee80211_crypto_ccmp_init() failed %d\n", ret); - return ret; - } - ret = ieee80211_crypto_wep_init(); - if (ret) { - pr_err("ieee80211_crypto_wep_init() failed %d\n", ret); - return ret; - } - - pr_info("\nLinux kernel driver for RTL8180 / RTL8185 based WLAN cards\n"); - pr_info("Copyright (c) 2004-2005, Andrea Merello\n"); - DMESG("Initializing module"); - DMESG("Wireless extensions version %d", WIRELESS_EXT); - rtl8180_proc_module_init(); - - if (pci_register_driver(&rtl8180_pci_driver)) { - DMESG("No device found"); - return -ENODEV; - } - return 0; -} - -static void __exit rtl8180_pci_module_exit(void) -{ - pci_unregister_driver(&rtl8180_pci_driver); - rtl8180_proc_module_remove(); - ieee80211_crypto_tkip_exit(); - ieee80211_crypto_ccmp_exit(); - ieee80211_crypto_wep_exit(); - ieee80211_crypto_deinit(); - DMESG("Exiting"); -} - -static void rtl8180_try_wake_queue(struct net_device *dev, int pri) -{ - unsigned long flags; - short enough_desc; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - spin_lock_irqsave(&priv->tx_lock, flags); - enough_desc = check_nic_enought_desc(dev, pri); - spin_unlock_irqrestore(&priv->tx_lock, flags); - - if (enough_desc) - ieee80211_rtl_wake_queue(priv->ieee80211); -} - -static void rtl8180_tx_isr(struct net_device *dev, int pri, short error) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 *tail; /* tail virtual addr */ - u32 *head; /* head virtual addr */ - u32 *begin; /* start of ring virtual addr */ - u32 *nicv; /* nic pointer virtual addr */ - u32 nic; /* nic pointer physical addr */ - u32 nicbegin; /* start of ring physical addr */ - unsigned long flag; - /* physical addr are ok on 32 bits since we set DMA mask */ - int offs; - int j, i; - int hd; - if (error) - priv->stats.txretry++; - spin_lock_irqsave(&priv->tx_lock, flag); - switch (pri) { - case MANAGE_PRIORITY: - tail = priv->txmapringtail; - begin = priv->txmapring; - head = priv->txmapringhead; - nic = read_nic_dword(dev, TX_MANAGEPRIORITY_RING_ADDR); - nicbegin = priv->txmapringdma; - break; - case BK_PRIORITY: - tail = priv->txbkpringtail; - begin = priv->txbkpring; - head = priv->txbkpringhead; - nic = read_nic_dword(dev, TX_BKPRIORITY_RING_ADDR); - nicbegin = priv->txbkpringdma; - break; - case BE_PRIORITY: - tail = priv->txbepringtail; - begin = priv->txbepring; - head = priv->txbepringhead; - nic = read_nic_dword(dev, TX_BEPRIORITY_RING_ADDR); - nicbegin = priv->txbepringdma; - break; - case VI_PRIORITY: - tail = priv->txvipringtail; - begin = priv->txvipring; - head = priv->txvipringhead; - nic = read_nic_dword(dev, TX_VIPRIORITY_RING_ADDR); - nicbegin = priv->txvipringdma; - break; - case VO_PRIORITY: - tail = priv->txvopringtail; - begin = priv->txvopring; - head = priv->txvopringhead; - nic = read_nic_dword(dev, TX_VOPRIORITY_RING_ADDR); - nicbegin = priv->txvopringdma; - break; - case HI_PRIORITY: - tail = priv->txhpringtail; - begin = priv->txhpring; - head = priv->txhpringhead; - nic = read_nic_dword(dev, TX_HIGHPRIORITY_RING_ADDR); - nicbegin = priv->txhpringdma; - break; - - default: - spin_unlock_irqrestore(&priv->tx_lock, flag); - return; - } - - nicv = (u32 *)((nic - nicbegin) + (u8 *)begin); - if ((head <= tail && (nicv > tail || nicv < head)) || - (head > tail && (nicv > tail && nicv < head))) { - DMESGW("nic has lost pointer"); - spin_unlock_irqrestore(&priv->tx_lock, flag); - rtl8180_restart(dev); - return; - } - - /* - * We check all the descriptors between the head and the nic, - * but not the currently pointed by the nic (the next to be txed) - * and the previous of the pointed (might be in process ??) - */ - offs = (nic - nicbegin); - offs = offs / 8 / 4; - hd = (head - begin) / 8; - - if (offs >= hd) - j = offs - hd; - else - j = offs + (priv->txringcount-1-hd); - - j -= 2; - if (j < 0) - j = 0; - - for (i = 0; i < j; i++) { - if ((*head) & (1<<31)) - break; - if (((*head)&(0x10000000)) != 0) { - priv->CurrRetryCnt += (u16)((*head) & (0x000000ff)); - if (!error) - priv->NumTxOkTotal++; - } - - if (!error) - priv->NumTxOkBytesTotal += (*(head+3)) & (0x00000fff); - - *head = *head & ~(1<<31); - - if ((head - begin)/8 == priv->txringcount-1) - head = begin; - else - head += 8; - } - - /* - * The head has been moved to the last certainly TXed - * (or at least processed by the nic) packet. - * The driver take forcefully owning of all these packets - * If the packet previous of the nic pointer has been - * processed this doesn't matter: it will be checked - * here at the next round. Anyway if no more packet are - * TXed no memory leak occur at all. - */ - - switch (pri) { - case MANAGE_PRIORITY: - priv->txmapringhead = head; - - if (priv->ack_tx_to_ieee) { - if (rtl8180_is_tx_queue_empty(dev)) { - priv->ack_tx_to_ieee = 0; - ieee80211_ps_tx_ack(priv->ieee80211, !error); - } - } - break; - case BK_PRIORITY: - priv->txbkpringhead = head; - break; - case BE_PRIORITY: - priv->txbepringhead = head; - break; - case VI_PRIORITY: - priv->txvipringhead = head; - break; - case VO_PRIORITY: - priv->txvopringhead = head; - break; - case HI_PRIORITY: - priv->txhpringhead = head; - break; - } - - spin_unlock_irqrestore(&priv->tx_lock, flag); -} - -static irqreturn_t rtl8180_interrupt(int irq, void *netdev) -{ - struct net_device *dev = (struct net_device *) netdev; - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long flags; - u32 inta; - - /* We should return IRQ_NONE, but for now let me keep this */ - if (priv->irq_enabled == 0) - return IRQ_HANDLED; - - spin_lock_irqsave(&priv->irq_th_lock, flags); - - /* ISR: 4bytes */ - inta = read_nic_dword(dev, ISR); - write_nic_dword(dev, ISR, inta); /* reset int situation */ - - priv->stats.shints++; - - if (!inta) { - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - return IRQ_HANDLED; - /* - * most probably we can safely return IRQ_NONE, - * but for now is better to avoid problems - */ - } - - if (inta == 0xffff) { - /* HW disappeared */ - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - return IRQ_HANDLED; - } - - priv->stats.ints++; - - if (!netif_running(dev)) { - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - return IRQ_HANDLED; - } - - if (inta & ISR_TimeOut) - write_nic_dword(dev, TimerInt, 0); - - if (inta & ISR_TBDOK) - priv->stats.txbeacon++; - - if (inta & ISR_TBDER) - priv->stats.txbeaconerr++; - - if (inta & IMR_TMGDOK) - rtl8180_tx_isr(dev, MANAGE_PRIORITY, 0); - - if (inta & ISR_THPDER) { - priv->stats.txhperr++; - rtl8180_tx_isr(dev, HI_PRIORITY, 1); - priv->ieee80211->stats.tx_errors++; - } - - if (inta & ISR_THPDOK) { /* High priority tx ok */ - priv->link_detect.num_tx_ok_in_period++; - priv->stats.txhpokint++; - rtl8180_tx_isr(dev, HI_PRIORITY, 0); - } - - if (inta & ISR_RER) - priv->stats.rxerr++; - - if (inta & ISR_TBKDER) { /* corresponding to BK_PRIORITY */ - priv->stats.txbkperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, BK_PRIORITY, 1); - rtl8180_try_wake_queue(dev, BK_PRIORITY); - } - - if (inta & ISR_TBEDER) { /* corresponding to BE_PRIORITY */ - priv->stats.txbeperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, BE_PRIORITY, 1); - rtl8180_try_wake_queue(dev, BE_PRIORITY); - } - if (inta & ISR_TNPDER) { /* corresponding to VO_PRIORITY */ - priv->stats.txnperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, NORM_PRIORITY, 1); - rtl8180_try_wake_queue(dev, NORM_PRIORITY); - } - - if (inta & ISR_TLPDER) { /* corresponding to VI_PRIORITY */ - priv->stats.txlperr++; - priv->ieee80211->stats.tx_errors++; - rtl8180_tx_isr(dev, LOW_PRIORITY, 1); - rtl8180_try_wake_queue(dev, LOW_PRIORITY); - } - - if (inta & ISR_ROK) { - priv->stats.rxint++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_RQoSOK) { - priv->stats.rxint++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_BcnInt) - rtl8180_prepare_beacon(dev); - - if (inta & ISR_RDU) { - DMESGW("No RX descriptor available"); - priv->stats.rxrdu++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_RXFOVW) { - priv->stats.rxoverflow++; - tasklet_schedule(&priv->irq_rx_tasklet); - } - - if (inta & ISR_TXFOVW) - priv->stats.txoverflow++; - - if (inta & ISR_TNPDOK) { /* Normal priority tx ok */ - priv->link_detect.num_tx_ok_in_period++; - priv->stats.txnpokint++; - rtl8180_tx_isr(dev, NORM_PRIORITY, 0); - rtl8180_try_wake_queue(dev, NORM_PRIORITY); - } - - if (inta & ISR_TLPDOK) { /* Low priority tx ok */ - priv->link_detect.num_tx_ok_in_period++; - priv->stats.txlpokint++; - rtl8180_tx_isr(dev, LOW_PRIORITY, 0); - rtl8180_try_wake_queue(dev, LOW_PRIORITY); - } - - if (inta & ISR_TBKDOK) { /* corresponding to BK_PRIORITY */ - priv->stats.txbkpokint++; - priv->link_detect.num_tx_ok_in_period++; - rtl8180_tx_isr(dev, BK_PRIORITY, 0); - rtl8180_try_wake_queue(dev, BE_PRIORITY); - } - - if (inta & ISR_TBEDOK) { /* corresponding to BE_PRIORITY */ - priv->stats.txbeperr++; - priv->link_detect.num_tx_ok_in_period++; - rtl8180_tx_isr(dev, BE_PRIORITY, 0); - rtl8180_try_wake_queue(dev, BE_PRIORITY); - } - force_pci_posting(dev); - spin_unlock_irqrestore(&priv->irq_th_lock, flags); - - return IRQ_HANDLED; -} - -void rtl8180_irq_rx_tasklet(struct r8180_priv *priv) -{ - rtl8180_rx(priv->dev); -} - -void GPIOChangeRFWorkItemCallBack(struct work_struct *work) -{ - struct ieee80211_device *ieee = container_of( - work, struct ieee80211_device, GPIOChangeRFWorkItem.work); - struct net_device *dev = ieee->dev; - struct r8180_priv *priv = ieee80211_priv(dev); - u8 btPSR; - u8 btConfig0; - enum rt_rf_power_state eRfPowerStateToSet; - bool bActuallySet = false; - - char *argv[3]; - static char *RadioPowerPath = "/etc/acpi/events/RadioPower.sh"; - static char *envp[] = {"HOME=/", "TERM=linux", - "PATH=/usr/bin:/bin", NULL}; - static int readf_count; - - readf_count = (readf_count+1)%0xffff; - /* We should turn off LED before polling FF51[4]. */ - - /* Turn off LED. */ - btPSR = read_nic_byte(dev, PSR); - write_nic_byte(dev, PSR, (btPSR & ~BIT3)); - - /* It need to delay 4us suggested */ - udelay(4); - - /* HW radio On/Off according to the value of FF51[4](config0) */ - btConfig0 = btPSR = read_nic_byte(dev, CONFIG0); - - eRfPowerStateToSet = (btConfig0 & BIT4) ? RF_ON : RF_OFF; - - /* Turn LED back on when radio enabled */ - if (eRfPowerStateToSet == RF_ON) - write_nic_byte(dev, PSR, btPSR | BIT3); - - if ((priv->ieee80211->bHwRadioOff == true) && - (eRfPowerStateToSet == RF_ON)) { - priv->ieee80211->bHwRadioOff = false; - bActuallySet = true; - } else if ((priv->ieee80211->bHwRadioOff == false) && - (eRfPowerStateToSet == RF_OFF)) { - priv->ieee80211->bHwRadioOff = true; - bActuallySet = true; - } - - if (bActuallySet) { - MgntActSet_RF_State(dev, eRfPowerStateToSet, RF_CHANGE_BY_HW); - - /* To update the UI status for Power status changed */ - if (priv->ieee80211->bHwRadioOff == true) - argv[1] = "RFOFF"; - else - argv[1] = "RFON"; - argv[0] = RadioPowerPath; - argv[2] = NULL; - - call_usermodehelper(RadioPowerPath, argv, envp, UMH_WAIT_PROC); - } -} - -module_init(rtl8180_pci_module_init); -module_exit(rtl8180_pci_module_exit); diff --git a/drivers/staging/rtl8187se/r8180_dm.c b/drivers/staging/rtl8187se/r8180_dm.c deleted file mode 100644 index 8c020e0648694a..00000000000000 --- a/drivers/staging/rtl8187se/r8180_dm.c +++ /dev/null @@ -1,1139 +0,0 @@ -#include "r8180_dm.h" -#include "r8180_hw.h" -#include "r8180_93cx6.h" - - /* Return TRUE if we shall perform High Power Mechanism, FALSE otherwise. */ -#define RATE_ADAPTIVE_TIMER_PERIOD 300 - -bool CheckHighPower(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - if (!priv->bRegHighPowerMechanism) - return false; - - if (ieee->state == IEEE80211_LINKED_SCANNING) - return false; - - return true; -} - -/* - * Description: - * Update Tx power level if necessary. - * See also DoRxHighPower() and SetTxPowerLevel8185() for reference. - * - * Note: - * The reason why we udpate Tx power level here instead of DoRxHighPower() - * is the number of IO to change Tx power is much more than channel TR switch - * and they are related to OFDM and MAC registers. - * So, we don't want to update it so frequently in per-Rx packet base. - */ -static void DoTxHighPower(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 HiPwrUpperTh = 0; - u16 HiPwrLowerTh = 0; - u8 RSSIHiPwrUpperTh; - u8 RSSIHiPwrLowerTh; - u8 u1bTmp; - char OfdmTxPwrIdx, CckTxPwrIdx; - - HiPwrUpperTh = priv->RegHiPwrUpperTh; - HiPwrLowerTh = priv->RegHiPwrLowerTh; - - HiPwrUpperTh = HiPwrUpperTh * 10; - HiPwrLowerTh = HiPwrLowerTh * 10; - RSSIHiPwrUpperTh = priv->RegRSSIHiPwrUpperTh; - RSSIHiPwrLowerTh = priv->RegRSSIHiPwrLowerTh; - - /* lzm add 080826 */ - OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; - CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; - - if ((priv->UndecoratedSmoothedSS > HiPwrUpperTh) || - (priv->bCurCCKPkt && (priv->CurCCKRSSI > RSSIHiPwrUpperTh))) { - /* Stevenl suggested that degrade 8dbm in high power sate. 2007-12-04 Isaiah */ - - priv->bToUpdateTxPwr = true; - u1bTmp = read_nic_byte(dev, CCK_TXAGC); - - /* If it never enter High Power. */ - if (CckTxPwrIdx == u1bTmp) { - u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */ - write_nic_byte(dev, CCK_TXAGC, u1bTmp); - - u1bTmp = read_nic_byte(dev, OFDM_TXAGC); - u1bTmp = (u1bTmp > 16) ? (u1bTmp - 16) : 0; /* 8dbm */ - write_nic_byte(dev, OFDM_TXAGC, u1bTmp); - } - - } else if ((priv->UndecoratedSmoothedSS < HiPwrLowerTh) && - (!priv->bCurCCKPkt || priv->CurCCKRSSI < RSSIHiPwrLowerTh)) { - if (priv->bToUpdateTxPwr) { - priv->bToUpdateTxPwr = false; - /* SD3 required. */ - u1bTmp = read_nic_byte(dev, CCK_TXAGC); - if (u1bTmp < CckTxPwrIdx) { - write_nic_byte(dev, CCK_TXAGC, CckTxPwrIdx); - } - - u1bTmp = read_nic_byte(dev, OFDM_TXAGC); - if (u1bTmp < OfdmTxPwrIdx) { - write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); - } - } - } -} - - -/* - * Description: - * Callback function of UpdateTxPowerWorkItem. - * Because of some event happened, e.g. CCX TPC, High Power Mechanism, - * We update Tx power of current channel again. - */ -void rtl8180_tx_pw_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, tx_pw_wq); - struct net_device *dev = ieee->dev; - - DoTxHighPower(dev); -} - - -/* - * Return TRUE if we shall perform DIG Mechanism, FALSE otherwise. - */ -bool CheckDig(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - if (!priv->bDigMechanism) - return false; - - if (ieee->state != IEEE80211_LINKED) - return false; - - if ((priv->ieee80211->rate / 5) < 36) /* Schedule Dig under all OFDM rates. By Bruce, 2007-06-01. */ - return false; - return true; -} -/* - * Implementation of DIG for Zebra and Zebra2. - */ -static void DIG_Zebra(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u16 CCKFalseAlarm, OFDMFalseAlarm; - u16 OfdmFA1, OfdmFA2; - int InitialGainStep = 7; /* The number of initial gain stages. */ - int LowestGainStage = 4; /* The capable lowest stage of performing dig workitem. */ - u32 AwakePeriodIn2Sec = 0; - - CCKFalseAlarm = (u16)(priv->FalseAlarmRegValue & 0x0000ffff); - OFDMFalseAlarm = (u16)((priv->FalseAlarmRegValue >> 16) & 0x0000ffff); - OfdmFA1 = 0x15; - OfdmFA2 = ((u16)(priv->RegDigOfdmFaUpTh)) << 8; - - /* The number of initial gain steps is different, by Bruce, 2007-04-13. */ - if (priv->InitialGain == 0) { /* autoDIG */ - /* Advised from SD3 DZ */ - priv->InitialGain = 4; /* In 87B, m74dBm means State 4 (m82dBm) */ - } - /* Advised from SD3 DZ */ - OfdmFA1 = 0x20; - -#if 1 /* lzm reserved 080826 */ - AwakePeriodIn2Sec = (2000 - priv->DozePeriodInPast2Sec); - priv->DozePeriodInPast2Sec = 0; - - if (AwakePeriodIn2Sec) { - OfdmFA1 = (u16)((OfdmFA1 * AwakePeriodIn2Sec) / 2000); - OfdmFA2 = (u16)((OfdmFA2 * AwakePeriodIn2Sec) / 2000); - } else { - ; - } -#endif - - InitialGainStep = 8; - LowestGainStage = priv->RegBModeGainStage; /* Lowest gain stage. */ - - if (OFDMFalseAlarm > OfdmFA1) { - if (OFDMFalseAlarm > OfdmFA2) { - priv->DIG_NumberFallbackVote++; - if (priv->DIG_NumberFallbackVote > 1) { - /* serious OFDM False Alarm, need fallback */ - if (priv->InitialGain < InitialGainStep) { - priv->InitialGainBackUp = priv->InitialGain; - - priv->InitialGain = (priv->InitialGain + 1); - UpdateInitialGain(dev); - } - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote = 0; - } - } else { - if (priv->DIG_NumberFallbackVote) - priv->DIG_NumberFallbackVote--; - } - priv->DIG_NumberUpgradeVote = 0; - } else { - if (priv->DIG_NumberFallbackVote) - priv->DIG_NumberFallbackVote--; - priv->DIG_NumberUpgradeVote++; - - if (priv->DIG_NumberUpgradeVote > 9) { - if (priv->InitialGain > LowestGainStage) { /* In 87B, m78dBm means State 4 (m864dBm) */ - priv->InitialGainBackUp = priv->InitialGain; - - priv->InitialGain = (priv->InitialGain - 1); - UpdateInitialGain(dev); - } - priv->DIG_NumberFallbackVote = 0; - priv->DIG_NumberUpgradeVote = 0; - } - } -} - -/* - * Dispatch DIG implementation according to RF. - */ -static void DynamicInitGain(struct net_device *dev) -{ - DIG_Zebra(dev); -} - -void rtl8180_hw_dig_wq(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, hw_dig_wq); - struct net_device *dev = ieee->dev; - struct r8180_priv *priv = ieee80211_priv(dev); - - /* Read CCK and OFDM False Alarm. */ - priv->FalseAlarmRegValue = read_nic_dword(dev, CCK_FALSE_ALARM); - - - /* Adjust Initial Gain dynamically. */ - DynamicInitGain(dev); - -} - -static int IncludedInSupportedRates(struct r8180_priv *priv, u8 TxRate) -{ - u8 rate_len; - u8 rate_ex_len; - u8 RateMask = 0x7F; - u8 idx; - unsigned short Found = 0; - u8 NaiveTxRate = TxRate&RateMask; - - rate_len = priv->ieee80211->current_network.rates_len; - rate_ex_len = priv->ieee80211->current_network.rates_ex_len; - for (idx = 0; idx < rate_len; idx++) { - if ((priv->ieee80211->current_network.rates[idx] & RateMask) == NaiveTxRate) { - Found = 1; - goto found_rate; - } - } - for (idx = 0; idx < rate_ex_len; idx++) { - if ((priv->ieee80211->current_network.rates_ex[idx] & RateMask) == NaiveTxRate) { - Found = 1; - goto found_rate; - } - } - return Found; -found_rate: - return Found; -} - -/* - * Get the Tx rate one degree up form the input rate in the supported rates. - * Return the upgrade rate if it is successed, otherwise return the input rate. - */ -static u8 GetUpgradeTxRate(struct net_device *dev, u8 rate) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 UpRate; - - /* Upgrade 1 degree. */ - switch (rate) { - case 108: /* Up to 54Mbps. */ - UpRate = 108; - break; - - case 96: /* Up to 54Mbps. */ - UpRate = 108; - break; - - case 72: /* Up to 48Mbps. */ - UpRate = 96; - break; - - case 48: /* Up to 36Mbps. */ - UpRate = 72; - break; - - case 36: /* Up to 24Mbps. */ - UpRate = 48; - break; - - case 22: /* Up to 18Mbps. */ - UpRate = 36; - break; - - case 11: /* Up to 11Mbps. */ - UpRate = 22; - break; - - case 4: /* Up to 5.5Mbps. */ - UpRate = 11; - break; - - case 2: /* Up to 2Mbps. */ - UpRate = 4; - break; - - default: - printk("GetUpgradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); - return rate; - } - /* Check if the rate is valid. */ - if (IncludedInSupportedRates(priv, UpRate)) { - return UpRate; - } else { - return rate; - } - return rate; -} -/* - * Get the Tx rate one degree down form the input rate in the supported rates. - * Return the degrade rate if it is successed, otherwise return the input rate. - */ - -static u8 GetDegradeTxRate(struct net_device *dev, u8 rate) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 DownRate; - - /* Upgrade 1 degree. */ - switch (rate) { - case 108: /* Down to 48Mbps. */ - DownRate = 96; - break; - - case 96: /* Down to 36Mbps. */ - DownRate = 72; - break; - - case 72: /* Down to 24Mbps. */ - DownRate = 48; - break; - - case 48: /* Down to 18Mbps. */ - DownRate = 36; - break; - - case 36: /* Down to 11Mbps. */ - DownRate = 22; - break; - - case 22: /* Down to 5.5Mbps. */ - DownRate = 11; - break; - - case 11: /* Down to 2Mbps. */ - DownRate = 4; - break; - - case 4: /* Down to 1Mbps. */ - DownRate = 2; - break; - - case 2: /* Down to 1Mbps. */ - DownRate = 2; - break; - - default: - printk("GetDegradeTxRate(): Input Tx Rate(%d) is undefined!\n", rate); - return rate; - } - /* Check if the rate is valid. */ - if (IncludedInSupportedRates(priv, DownRate)) { - return DownRate; - } else { - return rate; - } - return rate; -} -/* - * Helper function to determine if specified data rate is - * CCK rate. - */ - -static bool MgntIsCckRate(u16 rate) -{ - bool bReturn = false; - - if ((rate <= 22) && (rate != 12) && (rate != 18)) { - bReturn = true; - } - - return bReturn; -} -/* - * Description: - * Tx Power tracking mechanism routine on 87SE. - */ -void TxPwrTracking87SE(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u8 tmpu1Byte, CurrentThermal, Idx; - char CckTxPwrIdx, OfdmTxPwrIdx; - - tmpu1Byte = read_nic_byte(dev, EN_LPF_CAL); - CurrentThermal = (tmpu1Byte & 0xf0) >> 4; /*[ 7:4]: thermal meter indication. */ - CurrentThermal = (CurrentThermal > 0x0c) ? 0x0c : CurrentThermal;/* lzm add 080826 */ - - if (CurrentThermal != priv->ThermalMeter) { - /* Update Tx Power level on each channel. */ - for (Idx = 1; Idx < 15; Idx++) { - CckTxPwrIdx = priv->chtxpwr[Idx]; - OfdmTxPwrIdx = priv->chtxpwr_ofdm[Idx]; - - if (CurrentThermal > priv->ThermalMeter) { - /* higher thermal meter. */ - CckTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; - OfdmTxPwrIdx += (CurrentThermal - priv->ThermalMeter) * 2; - - if (CckTxPwrIdx > 35) - CckTxPwrIdx = 35; /* Force TxPower to maximal index. */ - if (OfdmTxPwrIdx > 35) - OfdmTxPwrIdx = 35; - } else { - /* lower thermal meter. */ - CckTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; - OfdmTxPwrIdx -= (priv->ThermalMeter - CurrentThermal) * 2; - - if (CckTxPwrIdx < 0) - CckTxPwrIdx = 0; - if (OfdmTxPwrIdx < 0) - OfdmTxPwrIdx = 0; - } - - /* Update TxPower level on CCK and OFDM resp. */ - priv->chtxpwr[Idx] = CckTxPwrIdx; - priv->chtxpwr_ofdm[Idx] = OfdmTxPwrIdx; - } - - /* Update TxPower level immediately. */ - rtl8225z2_SetTXPowerLevel(dev, priv->ieee80211->current_network.channel); - } - priv->ThermalMeter = CurrentThermal; -} -static void StaRateAdaptive87SE(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - unsigned long CurrTxokCnt; - u16 CurrRetryCnt; - u16 CurrRetryRate; - unsigned long CurrRxokCnt; - bool bTryUp = false; - bool bTryDown = false; - u8 TryUpTh = 1; - u8 TryDownTh = 2; - u32 TxThroughput; - long CurrSignalStrength; - bool bUpdateInitialGain = false; - u8 u1bOfdm = 0, u1bCck = 0; - char OfdmTxPwrIdx, CckTxPwrIdx; - - priv->RateAdaptivePeriod = RATE_ADAPTIVE_TIMER_PERIOD; - - - CurrRetryCnt = priv->CurrRetryCnt; - CurrTxokCnt = priv->NumTxOkTotal - priv->LastTxokCnt; - CurrRxokCnt = priv->ieee80211->NumRxOkTotal - priv->LastRxokCnt; - CurrSignalStrength = priv->Stats_RecvSignalPower; - TxThroughput = (u32)(priv->NumTxOkBytesTotal - priv->LastTxOKBytes); - priv->LastTxOKBytes = priv->NumTxOkBytesTotal; - priv->CurrentOperaRate = priv->ieee80211->rate / 5; - /* 2 Compute retry ratio. */ - if (CurrTxokCnt > 0) { - CurrRetryRate = (u16)(CurrRetryCnt * 100 / CurrTxokCnt); - } else { - /* It may be serious retry. To distinguish serious retry or no packets modified by Bruce */ - CurrRetryRate = (u16)(CurrRetryCnt * 100 / 1); - } - - priv->LastRetryCnt = priv->CurrRetryCnt; - priv->LastTxokCnt = priv->NumTxOkTotal; - priv->LastRxokCnt = priv->ieee80211->NumRxOkTotal; - priv->CurrRetryCnt = 0; - - /* 2No Tx packets, return to init_rate or not? */ - if (CurrRetryRate == 0 && CurrTxokCnt == 0) { - /* - * After 9 (30*300ms) seconds in this condition, we try to raise rate. - */ - priv->TryupingCountNoData++; - - /* [TRC Dell Lab] Extend raised period from 4.5sec to 9sec, Isaiah 2008-02-15 18:00 */ - if (priv->TryupingCountNoData > 30) { - priv->TryupingCountNoData = 0; - priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); - /* Reset Fail Record */ - priv->LastFailTxRate = 0; - priv->LastFailTxRateSS = -200; - priv->FailTxRateCount = 0; - } - goto SetInitialGain; - } else { - priv->TryupingCountNoData = 0; /*Reset trying up times. */ - } - - - /* - * For Netgear case, I comment out the following signal strength estimation, - * which can results in lower rate to transmit when sample is NOT enough (e.g. PING request). - * - * Restructure rate adaptive as the following main stages: - * (1) Add retry threshold in 54M upgrading condition with signal strength. - * (2) Add the mechanism to degrade to CCK rate according to signal strength - * and retry rate. - * (3) Remove all Initial Gain Updates over OFDM rate. To avoid the complicated - * situation, Initial Gain Update is upon on DIG mechanism except CCK rate. - * (4) Add the mechanism of trying to upgrade tx rate. - * (5) Record the information of upping tx rate to avoid trying upping tx rate constantly. - * - */ - - /* - * 11Mbps or 36Mbps - * Check more times in these rate(key rates). - */ - if (priv->CurrentOperaRate == 22 || priv->CurrentOperaRate == 72) - TryUpTh += 9; - /* - * Let these rates down more difficult. - */ - if (MgntIsCckRate(priv->CurrentOperaRate) || priv->CurrentOperaRate == 36) - TryDownTh += 1; - - /* 1 Adjust Rate. */ - if (priv->bTryuping == true) { - /* 2 For Test Upgrading mechanism - * Note: - * Sometimes the throughput is upon on the capability between the AP and NIC, - * thus the low data rate does not improve the performance. - * We randomly upgrade the data rate and check if the retry rate is improved. - */ - - /* Upgrading rate did not improve the retry rate, fallback to the original rate. */ - if ((CurrRetryRate > 25) && TxThroughput < priv->LastTxThroughput) { - /*Not necessary raising rate, fall back rate. */ - bTryDown = true; - } else { - priv->bTryuping = false; - } - } else if (CurrSignalStrength > -47 && (CurrRetryRate < 50)) { - /* - * 2For High Power - * - * Return to highest data rate, if signal strength is good enough. - * SignalStrength threshold(-50dbm) is for RTL8186. - * Revise SignalStrength threshold to -51dbm. - */ - /* Also need to check retry rate for safety, by Bruce, 2007-06-05. */ - if (priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate) { - bTryUp = true; - /* Upgrade Tx Rate directly. */ - priv->TryupingCount += TryUpTh; - } - - } else if (CurrTxokCnt > 9 && CurrTxokCnt < 100 && CurrRetryRate >= 600) { - /* - *2 For Serious Retry - * - * Traffic is not busy but our Tx retry is serious. - */ - bTryDown = true; - /* Let Rate Mechanism to degrade tx rate directly. */ - priv->TryDownCountLowData += TryDownTh; - } else if (priv->CurrentOperaRate == 108) { - /* 2For 54Mbps */ - /* Air Link */ - if ((CurrRetryRate > 26) && (priv->LastRetryRate > 25)) { - bTryDown = true; - } - /* Cable Link */ - else if ((CurrRetryRate > 17) && (priv->LastRetryRate > 16) && (CurrSignalStrength > -72)) { - bTryDown = true; - } - - if (bTryDown && (CurrSignalStrength < -75)) /* cable link */ - priv->TryDownCountLowData += TryDownTh; - } else if (priv->CurrentOperaRate == 96) { - /* 2For 48Mbps */ - /* Air Link */ - if (((CurrRetryRate > 48) && (priv->LastRetryRate > 47))) { - bTryDown = true; - } else if (((CurrRetryRate > 21) && (priv->LastRetryRate > 20)) && (CurrSignalStrength > -74)) { /* Cable Link */ - /* Down to rate 36Mbps. */ - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 8) && (priv->LastRetryRate < 8)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - - if (bTryDown && (CurrSignalStrength < -75)) { - priv->TryDownCountLowData += TryDownTh; - } - } else if (priv->CurrentOperaRate == 72) { - /* 2For 36Mbps */ - if ((CurrRetryRate > 43) && (priv->LastRetryRate > 41)) { - /* Down to rate 24Mbps. */ - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 15) && (priv->LastRetryRate < 16)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - - if (bTryDown && (CurrSignalStrength < -80)) - priv->TryDownCountLowData += TryDownTh; - - } else if (priv->CurrentOperaRate == 48) { - /* 2For 24Mbps */ - /* Air Link */ - if (((CurrRetryRate > 63) && (priv->LastRetryRate > 62))) { - bTryDown = true; - } else if (((CurrRetryRate > 33) && (priv->LastRetryRate > 32)) && (CurrSignalStrength > -82)) { /* Cable Link */ - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 20) && (priv->LastRetryRate < 21)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - - if (bTryDown && (CurrSignalStrength < -82)) - priv->TryDownCountLowData += TryDownTh; - - } else if (priv->CurrentOperaRate == 36) { - if (((CurrRetryRate > 85) && (priv->LastRetryRate > 86))) { - bTryDown = true; - } else if ((CurrRetryRate > (priv->LastRetryRate + 50)) && (priv->FailTxRateCount > 2)) { - bTryDown = true; - priv->TryDownCountLowData += TryDownTh; - } else if ((CurrRetryRate < 22) && (priv->LastRetryRate < 23)) { /* TO DO: need to consider (RSSI) */ - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 22) { - /* 2For 11Mbps */ - if (CurrRetryRate > 95) { - bTryDown = true; - } else if ((CurrRetryRate < 29) && (priv->LastRetryRate < 30)) { /*TO DO: need to consider (RSSI) */ - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 11) { - /* 2For 5.5Mbps */ - if (CurrRetryRate > 149) { - bTryDown = true; - } else if ((CurrRetryRate < 60) && (priv->LastRetryRate < 65)) { - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 4) { - /* 2For 2 Mbps */ - if ((CurrRetryRate > 99) && (priv->LastRetryRate > 99)) { - bTryDown = true; - } else if ((CurrRetryRate < 65) && (priv->LastRetryRate < 70)) { - bTryUp = true; - } - } else if (priv->CurrentOperaRate == 2) { - /* 2For 1 Mbps */ - if ((CurrRetryRate < 70) && (priv->LastRetryRate < 75)) { - bTryUp = true; - } - } - - if (bTryUp && bTryDown) - printk("StaRateAdaptive87B(): Tx Rate tried upping and downing simultaneously!\n"); - - /* 1 Test Upgrading Tx Rate - * Sometimes the cause of the low throughput (high retry rate) is the compatibility between the AP and NIC. - * To test if the upper rate may cause lower retry rate, this mechanism randomly occurs to test upgrading tx rate. - */ - if (!bTryUp && !bTryDown && (priv->TryupingCount == 0) && (priv->TryDownCountLowData == 0) - && priv->CurrentOperaRate != priv->ieee80211->current_network.HighestOperaRate && priv->FailTxRateCount < 2) { - if (jiffies % (CurrRetryRate + 101) == 0) { - bTryUp = true; - priv->bTryuping = true; - } - } - - /* 1 Rate Mechanism */ - if (bTryUp) { - priv->TryupingCount++; - priv->TryDownCountLowData = 0; - - /* - * Check more times if we need to upgrade indeed. - * Because the largest value of pHalData->TryupingCount is 0xFFFF and - * the largest value of pHalData->FailTxRateCount is 0x14, - * this condition will be satisfied at most every 2 min. - */ - - if ((priv->TryupingCount > (TryUpTh + priv->FailTxRateCount * priv->FailTxRateCount)) || - (CurrSignalStrength > priv->LastFailTxRateSS) || priv->bTryuping) { - priv->TryupingCount = 0; - /* - * When transferring from CCK to OFDM, DIG is an important issue. - */ - if (priv->CurrentOperaRate == 22) - bUpdateInitialGain = true; - - /* - * The difference in throughput between 48Mbps and 36Mbps is 8M. - * So, we must be careful in this rate scale. Isaiah 2008-02-15. - */ - if (((priv->CurrentOperaRate == 72) || (priv->CurrentOperaRate == 48) || (priv->CurrentOperaRate == 36)) && - (priv->FailTxRateCount > 2)) - priv->RateAdaptivePeriod = (RATE_ADAPTIVE_TIMER_PERIOD / 2); - - /* (1)To avoid upgrade frequently to the fail tx rate, add the FailTxRateCount into the threshold. */ - /* (2)If the signal strength is increased, it may be able to upgrade. */ - - priv->CurrentOperaRate = GetUpgradeTxRate(dev, priv->CurrentOperaRate); - - if (priv->CurrentOperaRate == 36) { - priv->bUpdateARFR = true; - write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */ - } else if (priv->bUpdateARFR) { - priv->bUpdateARFR = false; - write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */ - } - - /* Update Fail Tx rate and count. */ - if (priv->LastFailTxRate != priv->CurrentOperaRate) { - priv->LastFailTxRate = priv->CurrentOperaRate; - priv->FailTxRateCount = 0; - priv->LastFailTxRateSS = -200; /* Set lowest power. */ - } - } - } else { - if (priv->TryupingCount > 0) - priv->TryupingCount--; - } - - if (bTryDown) { - priv->TryDownCountLowData++; - priv->TryupingCount = 0; - - /* Check if Tx rate can be degraded or Test trying upgrading should fallback. */ - if (priv->TryDownCountLowData > TryDownTh || priv->bTryuping) { - priv->TryDownCountLowData = 0; - priv->bTryuping = false; - /* Update fail information. */ - if (priv->LastFailTxRate == priv->CurrentOperaRate) { - priv->FailTxRateCount++; - /* Record the Tx fail rate signal strength. */ - if (CurrSignalStrength > priv->LastFailTxRateSS) - priv->LastFailTxRateSS = CurrSignalStrength; - } else { - priv->LastFailTxRate = priv->CurrentOperaRate; - priv->FailTxRateCount = 1; - priv->LastFailTxRateSS = CurrSignalStrength; - } - priv->CurrentOperaRate = GetDegradeTxRate(dev, priv->CurrentOperaRate); - - /* Reduce chariot training time at weak signal strength situation. SD3 ED demand. */ - if ((CurrSignalStrength < -80) && (priv->CurrentOperaRate > 72)) { - priv->CurrentOperaRate = 72; - } - - if (priv->CurrentOperaRate == 36) { - priv->bUpdateARFR = true; - write_nic_word(dev, ARFR, 0x0F8F); /* bypass 12/9/6 */ - } else if (priv->bUpdateARFR) { - priv->bUpdateARFR = false; - write_nic_word(dev, ARFR, 0x0FFF); /* set 1M ~ 54Mbps. */ - } - - /* - * When it is CCK rate, it may need to update initial gain to receive lower power packets. - */ - if (MgntIsCckRate(priv->CurrentOperaRate)) { - bUpdateInitialGain = true; - } - } - } else { - if (priv->TryDownCountLowData > 0) - priv->TryDownCountLowData--; - } - - /* - * Keep the Tx fail rate count to equal to 0x15 at most. - * Reduce the fail count at least to 10 sec if tx rate is tending stable. - */ - if (priv->FailTxRateCount >= 0x15 || - (!bTryUp && !bTryDown && priv->TryDownCountLowData == 0 && priv->TryupingCount && priv->FailTxRateCount > 0x6)) { - priv->FailTxRateCount--; - } - - - OfdmTxPwrIdx = priv->chtxpwr_ofdm[priv->ieee80211->current_network.channel]; - CckTxPwrIdx = priv->chtxpwr[priv->ieee80211->current_network.channel]; - - /* Mac0x9e increase 2 level in 36M~18M situation */ - if ((priv->CurrentOperaRate < 96) && (priv->CurrentOperaRate > 22)) { - u1bCck = read_nic_byte(dev, CCK_TXAGC); - u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); - - /* case 1: Never enter High power */ - if (u1bCck == CckTxPwrIdx) { - if (u1bOfdm != (OfdmTxPwrIdx + 2)) { - priv->bEnhanceTxPwr = true; - u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2); - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - } - } else if (u1bCck < CckTxPwrIdx) { - /* case 2: enter high power */ - if (!priv->bEnhanceTxPwr) { - priv->bEnhanceTxPwr = true; - u1bOfdm = ((u1bOfdm + 2) > 35) ? 35 : (u1bOfdm + 2); - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - } - } - } else if (priv->bEnhanceTxPwr) { /* 54/48/11/5.5/2/1 */ - u1bCck = read_nic_byte(dev, CCK_TXAGC); - u1bOfdm = read_nic_byte(dev, OFDM_TXAGC); - - /* case 1: Never enter High power */ - if (u1bCck == CckTxPwrIdx) { - priv->bEnhanceTxPwr = false; - write_nic_byte(dev, OFDM_TXAGC, OfdmTxPwrIdx); - } - /* case 2: enter high power */ - else if (u1bCck < CckTxPwrIdx) { - priv->bEnhanceTxPwr = false; - u1bOfdm = ((u1bOfdm - 2) > 0) ? (u1bOfdm - 2) : 0; - write_nic_byte(dev, OFDM_TXAGC, u1bOfdm); - } - } - - /* - * We need update initial gain when we set tx rate "from OFDM to CCK" or - * "from CCK to OFDM". - */ -SetInitialGain: - if (bUpdateInitialGain) { - if (MgntIsCckRate(priv->CurrentOperaRate)) { /* CCK */ - if (priv->InitialGain > priv->RegBModeGainStage) { - priv->InitialGainBackUp = priv->InitialGain; - - if (CurrSignalStrength < -85) /* Low power, OFDM [0x17] = 26. */ - /* SD3 SYs suggest that CurrSignalStrength < -65, ofdm 0x17=26. */ - priv->InitialGain = priv->RegBModeGainStage; - - else if (priv->InitialGain > priv->RegBModeGainStage + 1) - priv->InitialGain -= 2; - - else - priv->InitialGain--; - - printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate); - UpdateInitialGain(dev); - } - } else { /* OFDM */ - if (priv->InitialGain < 4) { - priv->InitialGainBackUp = priv->InitialGain; - - priv->InitialGain++; - printk("StaRateAdaptive87SE(): update init_gain to index %d for date rate %d\n", priv->InitialGain, priv->CurrentOperaRate); - UpdateInitialGain(dev); - } - } - } - - /* Record the related info */ - priv->LastRetryRate = CurrRetryRate; - priv->LastTxThroughput = TxThroughput; - priv->ieee80211->rate = priv->CurrentOperaRate * 5; -} - -void rtl8180_rate_adapter(struct work_struct *work) -{ - struct delayed_work *dwork = to_delayed_work(work); - struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, rate_adapter_wq); - struct net_device *dev = ieee->dev; - StaRateAdaptive87SE(dev); -} -void timer_rate_adaptive(unsigned long data) -{ - struct r8180_priv *priv = ieee80211_priv((struct net_device *)data); - if (!priv->up) { - return; - } - if ((priv->ieee80211->iw_mode != IW_MODE_MASTER) - && (priv->ieee80211->state == IEEE80211_LINKED) && - (priv->ForcedDataRate == 0)) { - queue_work(priv->ieee80211->wq, (void *)&priv->ieee80211->rate_adapter_wq); - } - priv->rateadapter_timer.expires = jiffies + MSECS(priv->RateAdaptivePeriod); - add_timer(&priv->rateadapter_timer); -} - -void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - priv->AdRxOkCnt++; - - if (priv->AdRxSignalStrength != -1) { - priv->AdRxSignalStrength = ((priv->AdRxSignalStrength * 7) + (SignalStrength * 3)) / 10; - } else { /* Initialization case. */ - priv->AdRxSignalStrength = SignalStrength; - } - - if (priv->LastRxPktAntenna) /* Main antenna. */ - priv->AdMainAntennaRxOkCnt++; - else /* Aux antenna. */ - priv->AdAuxAntennaRxOkCnt++; -} - /* Change Antenna Switch. */ -bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bAntennaSwitched = false; - - switch (u1bAntennaIndex) { - case 0: - /* Mac register, main antenna */ - write_nic_byte(dev, ANTSEL, 0x03); - /* base band */ - write_phy_cck(dev, 0x11, 0x9b); /* Config CCK RX antenna. */ - write_phy_ofdm(dev, 0x0d, 0x5c); /* Config OFDM RX antenna. */ - - bAntennaSwitched = true; - break; - - case 1: - /* Mac register, aux antenna */ - write_nic_byte(dev, ANTSEL, 0x00); - /* base band */ - write_phy_cck(dev, 0x11, 0xbb); /* Config CCK RX antenna. */ - write_phy_ofdm(dev, 0x0d, 0x54); /* Config OFDM RX antenna. */ - - bAntennaSwitched = true; - - break; - - default: - printk("SetAntenna8185: unknown u1bAntennaIndex(%d)\n", u1bAntennaIndex); - break; - } - - if (bAntennaSwitched) - priv->CurrAntennaIndex = u1bAntennaIndex; - - return bAntennaSwitched; -} - /* Toggle Antenna switch. */ -bool SwitchAntenna(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - bool bResult; - - if (priv->CurrAntennaIndex == 0) { - bResult = SetAntenna8185(dev, 1); - } else { - bResult = SetAntenna8185(dev, 0); - } - - return bResult; -} -/* - * Engine of SW Antenna Diversity mechanism. - * Since 8187 has no Tx part information, - * this implementation is only dependend on Rx part information. - */ -void SwAntennaDiversity(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bSwCheckSS = false; - if (bSwCheckSS) { - priv->AdTickCount++; - - printk("(1) AdTickCount: %d, AdCheckPeriod: %d\n", - priv->AdTickCount, priv->AdCheckPeriod); - printk("(2) AdRxSignalStrength: %ld, AdRxSsThreshold: %ld\n", - priv->AdRxSignalStrength, priv->AdRxSsThreshold); - } - - /* Case 1. No Link. */ - if (priv->ieee80211->state != IEEE80211_LINKED) { - priv->bAdSwitchedChecking = false; - /* I switch antenna here to prevent any one of antenna is broken before link established, 2006.04.18, by rcnjko.. */ - SwitchAntenna(dev); - - /* Case 2. Linked but no packet receive.d */ - } else if (priv->AdRxOkCnt == 0) { - priv->bAdSwitchedChecking = false; - SwitchAntenna(dev); - - /* Case 3. Evaluate last antenna switch action and undo it if necessary. */ - } else if (priv->bAdSwitchedChecking == true) { - priv->bAdSwitchedChecking = false; - - /* Adjust Rx signal strength threshold. */ - priv->AdRxSsThreshold = (priv->AdRxSignalStrength + priv->AdRxSsBeforeSwitched) / 2; - - priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? - priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold; - if (priv->AdRxSignalStrength < priv->AdRxSsBeforeSwitched) { - /* Rx signal strength is not improved after we swtiched antenna. => Swich back. */ - /* Increase Antenna Diversity checking period due to bad decision. */ - priv->AdCheckPeriod *= 2; - /* Increase Antenna Diversity checking period. */ - if (priv->AdCheckPeriod > priv->AdMaxCheckPeriod) - priv->AdCheckPeriod = priv->AdMaxCheckPeriod; - - /* Wrong decision => switch back. */ - SwitchAntenna(dev); - } else { - /* Rx Signal Strength is improved. */ - - /* Reset Antenna Diversity checking period to its min value. */ - priv->AdCheckPeriod = priv->AdMinCheckPeriod; - } - - } - /* Case 4. Evaluate if we shall switch antenna now. */ - /* Cause Table Speed is very fast in TRC Dell Lab, we check it every time. */ - else { - priv->AdTickCount = 0; - - /* - * We evaluate RxOk counts for each antenna first and than - * evaluate signal strength. - * The following operation can overcome the disability of CCA on both two antennas - * When signal strength was extremely low or high. - * 2008.01.30. - */ - - /* - * Evaluate RxOk count from each antenna if we shall switch default antenna now. - */ - if ((priv->AdMainAntennaRxOkCnt < priv->AdAuxAntennaRxOkCnt) - && (priv->CurrAntennaIndex == 0)) { - /* We set Main antenna as default but RxOk count was less than Aux ones. */ - - /* Switch to Aux antenna. */ - SwitchAntenna(dev); - priv->bHWAdSwitched = true; - } else if ((priv->AdAuxAntennaRxOkCnt < priv->AdMainAntennaRxOkCnt) - && (priv->CurrAntennaIndex == 1)) { - /* We set Aux antenna as default but RxOk count was less than Main ones. */ - - /* Switch to Main antenna. */ - SwitchAntenna(dev); - priv->bHWAdSwitched = true; - } else { - /* Default antenna is better. */ - - /* Still need to check current signal strength. */ - priv->bHWAdSwitched = false; - } - /* - * We evaluate Rx signal strength ONLY when default antenna - * didn't change by HW evaluation. - * 2008.02.27. - * - * [TRC Dell Lab] SignalStrength is inaccuracy. Isaiah 2008-03-05 - * For example, Throughput of aux is better than main antenna(about 10M v.s 2M), - * but AdRxSignalStrength is less than main. - * Our guess is that main antenna have lower throughput and get many change - * to receive more CCK packets(ex.Beacon) which have stronger SignalStrength. - */ - if ((!priv->bHWAdSwitched) && (bSwCheckSS)) { - /* Evaluate Rx signal strength if we shall switch antenna now. */ - if (priv->AdRxSignalStrength < priv->AdRxSsThreshold) { - /* Rx signal strength is weak => Switch Antenna. */ - priv->AdRxSsBeforeSwitched = priv->AdRxSignalStrength; - priv->bAdSwitchedChecking = true; - - SwitchAntenna(dev); - } else { - /* Rx signal strength is OK. */ - priv->bAdSwitchedChecking = false; - /* Increase Rx signal strength threshold if necessary. */ - if ((priv->AdRxSignalStrength > (priv->AdRxSsThreshold + 10)) && /* Signal is much stronger than current threshold */ - priv->AdRxSsThreshold <= priv->AdMaxRxSsThreshold) { /* Current threhold is not yet reach upper limit. */ - - priv->AdRxSsThreshold = (priv->AdRxSsThreshold + priv->AdRxSignalStrength) / 2; - priv->AdRxSsThreshold = (priv->AdRxSsThreshold > priv->AdMaxRxSsThreshold) ? - priv->AdMaxRxSsThreshold : priv->AdRxSsThreshold;/* +by amy 080312 */ - } - - /* Reduce Antenna Diversity checking period if possible. */ - if (priv->AdCheckPeriod > priv->AdMinCheckPeriod) - priv->AdCheckPeriod /= 2; - } - } - } - /* Reset antenna diversity Rx related statistics. */ - priv->AdRxOkCnt = 0; - priv->AdMainAntennaRxOkCnt = 0; - priv->AdAuxAntennaRxOkCnt = 0; -} - - /* Return TRUE if we shall perform Tx Power Tracking Mechanism, FALSE otherwise. */ -bool CheckTxPwrTracking(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - if (!priv->bTxPowerTrack) - return false; - - /* if 87SE is in High Power , don't do Tx Power Tracking. asked by SD3 ED. 2008-08-08 Isaiah */ - if (priv->bToUpdateTxPwr) - return false; - - return true; -} - - - /* Timer callback function of SW Antenna Diversity. */ -void SwAntennaDiversityTimerCallback(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - enum rt_rf_power_state rtState; - - /* We do NOT need to switch antenna while RF is off. */ - rtState = priv->eRFPowerState; - do { - if (rtState == RF_OFF) { - break; - } else if (rtState == RF_SLEEP) { - /* Don't access BB/RF under Disable PLL situation. */ - break; - } - SwAntennaDiversity(dev); - - } while (false); - - if (priv->up) { - priv->SwAntennaDiversityTimer.expires = jiffies + MSECS(ANTENNA_DIVERSITY_TIMER_PERIOD); - add_timer(&priv->SwAntennaDiversityTimer); - } -} - diff --git a/drivers/staging/rtl8187se/r8180_dm.h b/drivers/staging/rtl8187se/r8180_dm.h deleted file mode 100644 index cb4046f346efed..00000000000000 --- a/drivers/staging/rtl8187se/r8180_dm.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef R8180_DM_H -#define R8180_DM_H - -#include "r8180.h" -/* #include "r8180_hw.h" */ -/* #include "r8180_93cx6.h" */ -void SwAntennaDiversityRxOk8185(struct net_device *dev, u8 SignalStrength); -bool SetAntenna8185(struct net_device *dev, u8 u1bAntennaIndex); -bool SwitchAntenna(struct net_device *dev); -void SwAntennaDiversity(struct net_device *dev); -void SwAntennaDiversityTimerCallback(struct net_device *dev); -bool CheckDig(struct net_device *dev); -bool CheckHighPower(struct net_device *dev); -void rtl8180_hw_dig_wq(struct work_struct *work); -void rtl8180_tx_pw_wq(struct work_struct *work); -void rtl8180_rate_adapter(struct work_struct *work); -void TxPwrTracking87SE(struct net_device *dev); -bool CheckTxPwrTracking(struct net_device *dev); -void rtl8180_rate_adapter(struct work_struct *work); -void timer_rate_adaptive(unsigned long data); - - -#endif diff --git a/drivers/staging/rtl8187se/r8180_hw.h b/drivers/staging/rtl8187se/r8180_hw.h deleted file mode 100644 index e59d74f8ecfc6a..00000000000000 --- a/drivers/staging/rtl8187se/r8180_hw.h +++ /dev/null @@ -1,588 +0,0 @@ -/* - This is part of rtl8180 OpenSource driver. - Copyright (C) Andrea Merello 2004-2005 - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part of the - official Realtek driver. - Parts of this driver are based on the rtl8180 driver skeleton - from Patric Schenke & Andres Salomon. - Parts of this driver are based on the Intel Pro Wireless - 2100 GPL driver. - - We want to tanks the Authors of those projects - and the Ndiswrapper project Authors. -*/ - -/* Mariusz Matuszek added full registers definition with Realtek's name */ - -/* this file contains register definitions for the rtl8180 MAC controller */ -#ifndef R8180_HW -#define R8180_HW - - -#define BIT0 0x00000001 -#define BIT1 0x00000002 -#define BIT2 0x00000004 -#define BIT3 0x00000008 -#define BIT4 0x00000010 -#define BIT5 0x00000020 -#define BIT6 0x00000040 -#define BIT7 0x00000080 -#define BIT9 0x00000200 -#define BIT11 0x00000800 -#define BIT13 0x00002000 -#define BIT15 0x00008000 -#define BIT20 0x00100000 -#define BIT21 0x00200000 -#define BIT22 0x00400000 -#define BIT23 0x00800000 -#define BIT24 0x01000000 -#define BIT25 0x02000000 -#define BIT26 0x04000000 -#define BIT27 0x08000000 -#define BIT28 0x10000000 -#define BIT29 0x20000000 -#define BIT30 0x40000000 -#define BIT31 0x80000000 - -#define MAX_SLEEP_TIME (10000) -#define MIN_SLEEP_TIME (50) - -#define BB_HOST_BANG_EN (1<<2) -#define BB_HOST_BANG_CLK (1<<1) - -#define MAC0 0 -#define MAC4 4 - -#define CMD 0x37 -#define CMD_RST_SHIFT 4 -#define CMD_RX_ENABLE_SHIFT 3 -#define CMD_TX_ENABLE_SHIFT 2 - -#define EPROM_CMD 0x50 -#define EPROM_CMD_RESERVED_MASK ((1<<5)|(1<<4)) -#define EPROM_CMD_OPERATING_MODE_SHIFT 6 -#define EPROM_CMD_OPERATING_MODE_MASK ((1<<7)|(1<<6)) -#define EPROM_CMD_CONFIG 0x3 -#define EPROM_CMD_NORMAL 0 -#define EPROM_CMD_LOAD 1 -#define EPROM_CMD_PROGRAM 2 -#define EPROM_CS_SHIFT 3 -#define EPROM_CK_SHIFT 2 -#define EPROM_W_SHIFT 1 -#define EPROM_R_SHIFT 0 -#define CONFIG2_DMA_POLLING_MODE_SHIFT 3 - -#define INTA_TXOVERFLOW (1<<15) -#define INTA_TIMEOUT (1<<14) -#define INTA_HIPRIORITYDESCERR (1<<9) -#define INTA_HIPRIORITYDESCOK (1<<8) -#define INTA_NORMPRIORITYDESCERR (1<<7) -#define INTA_NORMPRIORITYDESCOK (1<<6) -#define INTA_RXOVERFLOW (1<<5) -#define INTA_RXDESCERR (1<<4) -#define INTA_LOWPRIORITYDESCERR (1<<3) -#define INTA_LOWPRIORITYDESCOK (1<<2) -#define INTA_RXOK (1) -#define INTA_MASK 0x3c - -#define RXRING_ADDR 0xe4 /* page 0 */ -#define PGSELECT 0x5e -#define PGSELECT_PG_SHIFT 0 -#define RX_CONF 0x44 -#define MAC_FILTER_MASK ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<5) | \ -(1<<12) | (1<<18) | (1<<19) | (1<<20) | (1<<21) | (1<<22) | (1<<23)) -#define RX_CHECK_BSSID_SHIFT 23 -#define ACCEPT_PWR_FRAME_SHIFT 22 -#define ACCEPT_MNG_FRAME_SHIFT 20 -#define ACCEPT_CTL_FRAME_SHIFT 19 -#define ACCEPT_DATA_FRAME_SHIFT 18 -#define ACCEPT_ICVERR_FRAME_SHIFT 12 -#define ACCEPT_CRCERR_FRAME_SHIFT 5 -#define ACCEPT_BCAST_FRAME_SHIFT 3 -#define ACCEPT_MCAST_FRAME_SHIFT 2 -#define ACCEPT_ALLMAC_FRAME_SHIFT 0 -#define ACCEPT_NICMAC_FRAME_SHIFT 1 - -#define RX_FIFO_THRESHOLD_MASK ((1<<13) | (1<<14) | (1<<15)) -#define RX_FIFO_THRESHOLD_SHIFT 13 -#define RX_FIFO_THRESHOLD_NONE 7 -#define RX_AUTORESETPHY_SHIFT 28 - -#define TX_CONF 0x40 -#define TX_CONF_HEADER_AUTOICREMENT_SHIFT 30 -#define TX_LOOPBACK_SHIFT 17 -#define TX_LOOPBACK_NONE 0 -#define TX_LOOPBACK_CONTINUE 3 -#define TX_LOOPBACK_MASK ((1<<17)|(1<<18)) -#define TX_DPRETRY_SHIFT 0 -#define R8180_MAX_RETRY 255 -#define TX_RTSRETRY_SHIFT 8 -#define TX_NOICV_SHIFT 19 -#define TX_NOCRC_SHIFT 16 -#define TX_DMA_POLLING 0xd9 -#define TX_DMA_POLLING_BEACON_SHIFT 7 -#define TX_DMA_POLLING_HIPRIORITY_SHIFT 6 -#define TX_DMA_POLLING_NORMPRIORITY_SHIFT 5 -#define TX_DMA_POLLING_LOWPRIORITY_SHIFT 4 -#define TX_MANAGEPRIORITY_RING_ADDR 0x0C -#define TX_BKPRIORITY_RING_ADDR 0x10 -#define TX_BEPRIORITY_RING_ADDR 0x14 -#define TX_VIPRIORITY_RING_ADDR 0x20 -#define TX_VOPRIORITY_RING_ADDR 0x24 -#define TX_HIGHPRIORITY_RING_ADDR 0x28 -#define MAX_RX_DMA_MASK ((1<<8) | (1<<9) | (1<<10)) -#define MAX_RX_DMA_2048 7 -#define MAX_RX_DMA_1024 6 -#define MAX_RX_DMA_SHIFT 10 -#define INT_TIMEOUT 0x48 -#define CONFIG3_CLKRUN_SHIFT 2 -#define CONFIG3_ANAPARAM_W_SHIFT 6 -#define ANAPARAM 0x54 -#define BEACON_INTERVAL 0x70 -#define BEACON_INTERVAL_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)| \ -(1<<6)|(1<<7)|(1<<8)|(1<<9)) -#define ATIM_MASK ((1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7)| \ -(1<<8)|(1<<9)) -#define ATIM 0x72 -#define EPROM_CS_SHIFT 3 -#define EPROM_CK_SHIFT 2 -#define PHY_ADR 0x7c -#define SECURITY 0x5f /* 1209 this is sth wrong */ -#define SECURITY_WEP_TX_ENABLE_SHIFT 1 -#define SECURITY_WEP_RX_ENABLE_SHIFT 0 -#define SECURITY_ENCRYP_104 1 -#define SECURITY_ENCRYP_SHIFT 4 -#define SECURITY_ENCRYP_MASK ((1<<4)|(1<<5)) -#define KEY0 0x90 /* 1209 this is sth wrong */ -#define CONFIG2_ANTENNA_SHIFT 6 -#define TX_BEACON_RING_ADDR 0x4c -#define CONFIG0_WEP40_SHIFT 7 -#define CONFIG0_WEP104_SHIFT 6 -#define AGCRESET_SHIFT 5 - - - -/* - * Operational registers offsets in PCI (I/O) space. - * RealTek names are used. - */ - -#define TSFTR 0x0018 - -#define TLPDA 0x0020 - -#define BSSID 0x002E - -#define CR 0x0037 - -#define RF_SW_CONFIG 0x8 /* store data which is transmitted to RF for driver */ -#define RF_SW_CFG_SI BIT1 -#define EIFS 0x2D /* Extended InterFrame Space Timer, in unit of 4 us. */ - -#define BRSR 0x34 /* Basic rate set */ - -#define IMR 0x006C -#define ISR 0x003C - -#define TCR 0x0040 - -#define RCR 0x0044 - -#define TimerInt 0x0048 - -#define CR9346 0x0050 - -#define CONFIG0 0x0051 -#define CONFIG2 0x0053 - -#define MSR 0x0058 - -#define CONFIG3 0x0059 -#define CONFIG4 0x005A - /* SD3 szuyitasi: Mac0x57= CC -> B0 Mac0x60= D1 -> C6 */ - /* Mac0x60 = 0x000004C6 power save parameters */ - #define ANAPARM_ASIC_ON 0xB0054D00 - #define ANAPARM2_ASIC_ON 0x000004C6 - - #define ANAPARM_ON ANAPARM_ASIC_ON - #define ANAPARM2_ON ANAPARM2_ASIC_ON - -#define TESTR 0x005B - -#define PSR 0x005E - -#define BcnItv 0x0070 - -#define AtimWnd 0x0072 - -#define BintrItv 0x0074 - -#define PhyAddr 0x007C -#define PhyDataR 0x007E - -/* following are for rtl8185 */ -#define RFPinsOutput 0x80 -#define RFPinsEnable 0x82 -#define RF_TIMING 0x8c -#define RFPinsSelect 0x84 -#define ANAPARAM2 0x60 -#define RF_PARA 0x88 -#define RFPinsInput 0x86 -#define GP_ENABLE 0x90 -#define GPIO 0x91 -#define SW_CONTROL_GPIO 0x400 -#define TX_ANTENNA 0x9f -#define TX_GAIN_OFDM 0x9e -#define TX_GAIN_CCK 0x9d -#define WPA_CONFIG 0xb0 -#define TX_AGC_CTL 0x9c -#define TX_AGC_CTL_PERPACKET_GAIN_SHIFT 0 -#define TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT 1 -#define TX_AGC_CTL_FEEDBACK_ANT 2 -#define RESP_RATE 0x34 -#define SIFS 0xb4 -#define DIFS 0xb5 - -#define SLOT 0xb6 -#define CW_CONF 0xbc -#define CW_CONF_PERPACKET_RETRY_SHIFT 1 -#define CW_CONF_PERPACKET_CW_SHIFT 0 -#define CW_VAL 0xbd -#define MAX_RESP_RATE_SHIFT 4 -#define MIN_RESP_RATE_SHIFT 0 -#define RATE_FALLBACK 0xbe - -#define CONFIG5 0x00D8 - -#define PHYPR 0xDA /* 0xDA - 0x0B PHY Parameter Register. */ - -#define FEMR 0x1D4 /* Function Event Mask register */ - -#define FFER 0x00FC -#define FFER_END 0x00FF - - - -/* - * Bitmasks for specific register functions. - * Names are derived from the register name and function name. - * - * _[] - * - * this leads to some awkward names... - */ - -#define BRSR_BPLCP ((1 << 8)) -#define BRSR_MBR ((1 << 1)|(1 << 0)) -#define BRSR_MBR_8185 ((1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)|(1 << 7)|(1 << 6)|(1 << 5)|(1 << 4)|(1 << 3)|(1 << 2)|(1 << 1)|(1 << 0)) -#define BRSR_MBR0 ((1 << 0)) -#define BRSR_MBR1 ((1 << 1)) - -#define CR_RST ((1 << 4)) -#define CR_RE ((1 << 3)) -#define CR_TE ((1 << 2)) -#define CR_MulRW ((1 << 0)) - -#define IMR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */ -#define IMR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */ -#define IMR_WakeInt ((1 << 23)) /*Wake Up Interrupt */ -#define IMR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */ -#define IMR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */ -#define IMR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */ -#define IMR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */ -#define IMR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */ -#define IMR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */ -#define IMR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */ -#define IMR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */ -#define IMR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */ -#define IMR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */ -#define IMR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */ -#define IMR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */ -#define IMR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */ -#define IMR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */ -#define IMR_RER ((1 << 8)) /*Rx Error Interrupt */ -#define IMR_ROK ((1 << 7)) /*Receive OK Interrupt */ -#define IMR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */ -#define IMR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */ -#define IMR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */ -#define IMR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */ -#define IMR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */ -#define IMR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */ -#define IMR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */ -#define IMR_TMGDOK ((1 << 30)) -#define ISR_Dot11hInt ((1 << 25)) /*802.11h Measurement Interrupt */ -#define ISR_BcnDmaInt ((1 << 24)) /*Beacon DMA Interrupt */ /*What differenct between BcnDmaInt and BcnInt??? */ -#define ISR_WakeInt ((1 << 23)) /*Wake Up Interrupt */ -#define ISR_TXFOVW ((1 << 22)) /*Tx FIFO Overflow Interrupt */ -#define ISR_TimeOut1 ((1 << 21)) /*Time Out Interrupt 1 */ -#define ISR_BcnInt ((1 << 20)) /*Beacon Time out Interrupt */ -#define ISR_ATIMInt ((1 << 19)) /*ATIM Time Out Interrupt */ -#define ISR_TBDER ((1 << 18)) /*Tx Beacon Descriptor Error Interrupt */ -#define ISR_TBDOK ((1 << 17)) /*Tx Beacon Descriptor OK Interrupt */ -#define ISR_THPDER ((1 << 16)) /*Tx High Priority Descriptor Error Interrupt */ -#define ISR_THPDOK ((1 << 15)) /*Tx High Priority Descriptor OK Interrupt */ -#define ISR_TVODER ((1 << 14)) /*Tx AC_VO Descriptor Error Interrupt */ -#define ISR_TVODOK ((1 << 13)) /*Tx AC_VO Descriptor OK Interrupt */ -#define ISR_FOVW ((1 << 12)) /*Rx FIFO Overflow Interrupt */ -#define ISR_RDU ((1 << 11)) /*Rx Descriptor Unavailable Interrupt */ -#define ISR_TVIDER ((1 << 10)) /*Tx AC_VI Descriptor Error Interrupt */ -#define ISR_TVIDOK ((1 << 9)) /*Tx AC_VI Descriptor OK Interrupt */ -#define ISR_RER ((1 << 8)) /*Rx Error Interrupt */ -#define ISR_ROK ((1 << 7)) /*Receive OK Interrupt */ -#define ISR_TBEDER ((1 << 6)) /*Tx AC_BE Descriptor Error Interrupt */ -#define ISR_TBEDOK ((1 << 5)) /*Tx AC_BE Descriptor OK Interrupt */ -#define ISR_TBKDER ((1 << 4)) /*Tx AC_BK Descriptor Error Interrupt */ -#define ISR_TBKDOK ((1 << 3)) /*Tx AC_BK Descriptor OK Interrupt */ -#define ISR_RQoSOK ((1 << 2)) /*Rx QoS OK Interrupt */ -#define ISR_TimeOut2 ((1 << 1)) /*Time Out Interrupt 2 */ -#define ISR_TimeOut3 ((1 << 0)) /*Time Out Interrupt 3 */ - -/* these definition is used for Tx/Rx test temporarily */ -#define ISR_TLPDER ISR_TVIDER -#define ISR_TLPDOK ISR_TVIDOK -#define ISR_TNPDER ISR_TVODER -#define ISR_TNPDOK ISR_TVODOK -#define ISR_TimeOut ISR_TimeOut1 -#define ISR_RXFOVW ISR_FOVW - - -#define HW_VERID_R8180_F 3 -#define HW_VERID_R8180_ABCD 2 -#define HW_VERID_R8185_ABC 4 -#define HW_VERID_R8185_D 5 -#define HW_VERID_R8185B_B 6 - -#define TCR_CWMIN ((1 << 31)) -#define TCR_SWSEQ ((1 << 30)) -#define TCR_HWVERID_MASK ((1 << 27)|(1 << 26)|(1 << 25)) -#define TCR_HWVERID_SHIFT 25 -#define TCR_SAT ((1 << 24)) -#define TCR_PLCP_LEN TCR_SAT /* rtl8180 */ -#define TCR_MXDMA_MASK ((1 << 23)|(1 << 22)|(1 << 21)) -#define TCR_MXDMA_1024 6 -#define TCR_MXDMA_2048 7 -#define TCR_MXDMA_SHIFT 21 -#define TCR_DISCW ((1 << 20)) -#define TCR_ICV ((1 << 19)) -#define TCR_LBK ((1 << 18)|(1 << 17)) -#define TCR_LBK1 ((1 << 18)) -#define TCR_LBK0 ((1 << 17)) -#define TCR_CRC ((1 << 16)) -#define TCR_DPRETRY_MASK ((1 << 15)|(1 << 14)|(1 << 13)|(1 << 12)|(1 << 11)|(1 << 10)|(1 << 9)|(1 << 8)) -#define TCR_RTSRETRY_MASK ((1 << 0)|(1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7)) -#define TCR_PROBE_NOTIMESTAMP_SHIFT 29 /* rtl8185 */ - -#define RCR_ONLYERLPKT ((1 << 31)) -#define RCR_CS_SHIFT 29 -#define RCR_CS_MASK ((1 << 30) | (1 << 29)) -#define RCR_ENMARP ((1 << 28)) -#define RCR_CBSSID ((1 << 23)) -#define RCR_APWRMGT ((1 << 22)) -#define RCR_ADD3 ((1 << 21)) -#define RCR_AMF ((1 << 20)) -#define RCR_ACF ((1 << 19)) -#define RCR_ADF ((1 << 18)) -#define RCR_RXFTH ((1 << 15)|(1 << 14)|(1 << 13)) -#define RCR_RXFTH2 ((1 << 15)) -#define RCR_RXFTH1 ((1 << 14)) -#define RCR_RXFTH0 ((1 << 13)) -#define RCR_AICV ((1 << 12)) -#define RCR_MXDMA ((1 << 10)|(1 << 9)|(1 << 8)) -#define RCR_MXDMA2 ((1 << 10)) -#define RCR_MXDMA1 ((1 << 9)) -#define RCR_MXDMA0 ((1 << 8)) -#define RCR_9356SEL ((1 << 6)) -#define RCR_ACRC32 ((1 << 5)) -#define RCR_AB ((1 << 3)) -#define RCR_AM ((1 << 2)) -#define RCR_APM ((1 << 1)) -#define RCR_AAP ((1 << 0)) - -#define CR9346_EEM ((1 << 7)|(1 << 6)) -#define CR9346_EEM1 ((1 << 7)) -#define CR9346_EEM0 ((1 << 6)) -#define CR9346_EECS ((1 << 3)) -#define CR9346_EESK ((1 << 2)) -#define CR9346_EED1 ((1 << 1)) -#define CR9346_EED0 ((1 << 0)) - -#define CONFIG3_PARM_En ((1 << 6)) -#define CONFIG3_FuncRegEn ((1 << 1)) - -#define CONFIG4_PWRMGT ((1 << 5)) - -#define MSR_LINK_MASK ((1 << 2)|(1 << 3)) -#define MSR_LINK_MANAGED 2 -#define MSR_LINK_NONE 0 -#define MSR_LINK_SHIFT 2 -#define MSR_LINK_ADHOC 1 -#define MSR_LINK_MASTER 3 - -#define BcnItv_BcnItv (0x01FF) - -#define AtimWnd_AtimWnd (0x01FF) - -#define BintrItv_BintrItv (0x01FF) - -#define FEMR_INTR ((1 << 15)) -#define FEMR_WKUP ((1 << 14)) -#define FEMR_GWAKE ((1 << 4)) - -#define FFER_INTR ((1 << 15)) -#define FFER_GWAKE ((1 << 4)) - -/* Three wire mode. */ -#define SW_THREE_WIRE 0 -#define HW_THREE_WIRE 2 -/* RTL8187S by amy */ -#define HW_THREE_WIRE_PI 5 -#define HW_THREE_WIRE_SI 6 -/* by amy */ -#define TCR_LRL_OFFSET 0 -#define TCR_SRL_OFFSET 8 -#define TCR_MXDMA_OFFSET 21 -#define TCR_DISReqQsize_OFFSET 28 -#define TCR_DurProcMode_OFFSET 30 - -#define RCR_MXDMA_OFFSET 8 -#define RCR_FIFO_OFFSET 13 - -#define AckTimeOutReg 0x79 /* ACK timeout register, in unit of 4 us. */ - -#define RFTiming 0x8C - -#define TPPollStop 0x93 - -#define TXAGC_CTL 0x9C /*< RJ_TODO_8185B> TX_AGC_CONTROL (0x9C seems be removed at 8185B, see p37). */ -#define CCK_TXAGC 0x9D -#define OFDM_TXAGC 0x9E -#define ANTSEL 0x9F - -#define ACM_CONTROL 0x00BF /* ACM Control Registe */ - -#define IntMig 0xE2 /* Interrupt Migration (0xE2 ~ 0xE3) */ - -#define TID_AC_MAP 0xE8 /* TID to AC Mapping Register */ - -#define ANAPARAM3 0xEE /* How to use it? */ - -#define AC_VO_PARAM 0xF0 /* AC_VO Parameters Record */ -#define AC_VI_PARAM 0xF4 /* AC_VI Parameters Record */ -#define AC_BE_PARAM 0xF8 /* AC_BE Parameters Record */ -#define AC_BK_PARAM 0xFC /* AC_BK Parameters Record */ - -#define GPIOCtrl 0x16B /*GPIO Control Register. */ -#define ARFR 0x1E0 /* Auto Rate Fallback Register (0x1e0 ~ 0x1e2) */ - -#define RFSW_CTRL 0x272 /* 0x272-0x273. */ -#define SW_3W_DB0 0x274 /* Software 3-wire data buffer bit 31~0. */ -#define SW_3W_DB1 0x278 /* Software 3-wire data buffer bit 63~32. */ -#define SW_3W_CMD0 0x27C /* Software 3-wire Control/Status Register. */ -#define SW_3W_CMD1 0x27D /* Software 3-wire Control/Status Register. */ - -#define PI_DATA_READ 0X360 /* 0x360 - 0x361 Parallel Interface Data Register. */ -#define SI_DATA_READ 0x362 /* 0x362 - 0x363 Serial Interface Data Register. */ - -/* ----------------------------------------------------------------------------- - 8185B TPPollStop bits (offset 0x93, 1 byte) ----------------------------------------------------------------------------- -*/ -#define TPPOLLSTOP_BQ (0x01 << 7) -#define TPPOLLSTOP_AC_VIQ (0x01 << 4) - -#define MSR_LINK_ENEDCA (1<<4) - -/* ----------------------------------------------------------------------------- - 8187B AC_XX_PARAM bits ----------------------------------------------------------------------------- -*/ -#define AC_PARAM_TXOP_LIMIT_OFFSET 16 -#define AC_PARAM_ECW_MAX_OFFSET 12 -#define AC_PARAM_ECW_MIN_OFFSET 8 -#define AC_PARAM_AIFS_OFFSET 0 - -/* ----------------------------------------------------------------------------- - 8187B ACM_CONTROL bits (Offset 0xBF, 1 Byte) ----------------------------------------------------------------------------- -*/ -#define VOQ_ACM_EN (0x01 << 7) /*BIT7 */ -#define VIQ_ACM_EN (0x01 << 6) /*BIT6 */ -#define BEQ_ACM_EN (0x01 << 5) /*BIT5 */ -#define ACM_HW_EN (0x01 << 4) /*BIT4 */ -#define VOQ_ACM_CTL (0x01 << 2) /*BIT2 */ /* Set to 1 when AC_VO used time reaches or exceeds the admitted time */ -#define VIQ_ACM_CTL (0x01 << 1) /*BIT1 */ /* Set to 1 when AC_VI used time reaches or exceeds the admitted time */ -#define BEQ_ACM_CTL (0x01 << 0) /*BIT0 */ /* Set to 1 when AC_BE used time reaches or exceeds the admitted time */ - - -/* ----------------------------------------------------------------------------- - 8185B SW_3W_CMD bits (Offset 0x27C-0x27D, 16bit) ----------------------------------------------------------------------------- -*/ -#define SW_3W_CMD0_HOLD ((1 << 7)) -#define SW_3W_CMD1_RE ((1 << 0)) /* BIT8 */ -#define SW_3W_CMD1_WE ((1 << 1)) /* BIT9 */ -#define SW_3W_CMD1_DONE ((1 << 2)) /* BIT10 */ - -#define BB_HOST_BANG_RW (1 << 3) - -/* ----------------------------------------------------------------------------- - 8185B RATE_FALLBACK_CTL bits (Offset 0xBE, 8bit) ----------------------------------------------------------------------------- -*/ -#define RATE_FALLBACK_CTL_ENABLE ((1 << 7)) -#define RATE_FALLBACK_CTL_ENABLE_RTSCTS ((1 << 6)) -/* Auto rate fallback per 2^n retry. */ -#define RATE_FALLBACK_CTL_AUTO_STEP0 0x00 -#define RATE_FALLBACK_CTL_AUTO_STEP1 0x01 -#define RATE_FALLBACK_CTL_AUTO_STEP2 0x02 -#define RATE_FALLBACK_CTL_AUTO_STEP3 0x03 - - -#define RTL8225z2_ANAPARAM_OFF 0x55480658 -#define RTL8225z2_ANAPARAM2_OFF 0x72003f70 -/* by amy for power save */ -#define RF_CHANGE_BY_HW BIT30 -#define RF_CHANGE_BY_PS BIT29 -#define RF_CHANGE_BY_IPS BIT28 -/* by amy for power save */ -/* by amy for antenna */ -#define EEPROM_SW_REVD_OFFSET 0x3f - -/* BIT[8-9] is for SW Antenna Diversity. - * Only the value EEPROM_SW_AD_ENABLE means enable, other values are disable. - */ -#define EEPROM_SW_AD_MASK 0x0300 -#define EEPROM_SW_AD_ENABLE 0x0100 - -/* BIT[10-11] determine if Antenna 1 is the Default Antenna. - * Only the value EEPROM_DEF_ANT_1 means TRUE, other values are FALSE. - */ -#define EEPROM_DEF_ANT_MASK 0x0C00 -#define EEPROM_DEF_ANT_1 0x0400 -/*by amy for antenna */ -/* {by amy 080312 */ -/* 0x7C, 0x7D Crystal calibration and Tx Power tracking mechanism. Added by Roger. 2007.12.10. */ -#define EEPROM_RSV 0x7C -#define EEPROM_XTAL_CAL_XOUT_MASK 0x0F /* 0x7C[3:0], Crystal calibration for Xout. */ -#define EEPROM_XTAL_CAL_XIN_MASK 0xF0 /* 0x7C[7:4], Crystal calibration for Xin. */ -#define EEPROM_THERMAL_METER_MASK 0x0F00 /* 0x7D[3:0], Thermal meter reference level. */ -#define EEPROM_XTAL_CAL_ENABLE 0x1000 /* 0x7D[4], Crystal calibration enabled/disabled BIT. */ -#define EEPROM_THERMAL_METER_ENABLE 0x2000 /* 0x7D[5], Thermal meter enabled/disabled BIT. */ -#define EN_LPF_CAL 0x238 /* Enable LPF Calibration. */ -#define PWR_METER_EN BIT1 -/* where are false alarm counters in 8185B? */ -#define CCK_FALSE_ALARM 0xD0 -/* by amy 080312} */ - -/* YJ,add for Country IE, 080630 */ -#define EEPROM_COUNTRY_CODE 0x2E -/* YJ,add,080630,end */ - -#endif diff --git a/drivers/staging/rtl8187se/r8180_rtl8225.h b/drivers/staging/rtl8187se/r8180_rtl8225.h deleted file mode 100644 index 7df73927b3ccbf..00000000000000 --- a/drivers/staging/rtl8187se/r8180_rtl8225.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * This is part of the rtl8180-sa2400 driver released under the GPL (See file - * COPYING for details). - * - * Copyright (c) 2005 Andrea Merello - * - * This files contains programming code for the rtl8225 radio frontend. - * - * *Many* thanks to Realtek Corp. for their great support! - */ - -#include "r8180.h" - -#define RTL8225_ANAPARAM_ON 0xa0000b59 -#define RTL8225_ANAPARAM_OFF 0xa00beb59 -#define RTL8225_ANAPARAM2_OFF 0x840dec11 -#define RTL8225_ANAPARAM2_ON 0x860dec11 -#define RTL8225_ANAPARAM_SLEEP 0xa00bab59 -#define RTL8225_ANAPARAM2_SLEEP 0x840dec11 - -void rtl8225z2_rf_init(struct net_device *dev); -void rtl8225z2_rf_set_chan(struct net_device *dev, short ch); -void rtl8225z2_rf_close(struct net_device *dev); - -void RF_WriteReg(struct net_device *dev, u8 offset, u16 data); -u16 RF_ReadReg(struct net_device *dev, u8 offset); - -void rtl8180_set_mode(struct net_device *dev, int mode); -void rtl8180_set_mode(struct net_device *dev, int mode); -bool SetZebraRFPowerState8185(struct net_device *dev, - enum rt_rf_power_state eRFPowerState); -void rtl8225z4_rf_sleep(struct net_device *dev); -void rtl8225z4_rf_wakeup(struct net_device *dev); - diff --git a/drivers/staging/rtl8187se/r8180_rtl8225z2.c b/drivers/staging/rtl8187se/r8180_rtl8225z2.c deleted file mode 100644 index 47104fa05c552e..00000000000000 --- a/drivers/staging/rtl8187se/r8180_rtl8225z2.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - * This is part of the rtl8180-sa2400 driver - * released under the GPL (See file COPYING for details). - * Copyright (c) 2005 Andrea Merello - * - * This files contains programming code for the rtl8225 - * radio frontend. - * - * *Many* thanks to Realtek Corp. for their great support! - */ - -#include "r8180_hw.h" -#include "r8180_rtl8225.h" -#include "r8180_93cx6.h" - -#include "ieee80211/dot11d.h" - -static void write_rtl8225(struct net_device *dev, u8 adr, u16 data) -{ - int i; - u16 out, select; - u8 bit; - u32 bangdata = (data << 4) | (adr & 0xf); - - out = read_nic_word(dev, RFPinsOutput) & 0xfff3; - - write_nic_word(dev, RFPinsEnable, - (read_nic_word(dev, RFPinsEnable) | 0x7)); - - select = read_nic_word(dev, RFPinsSelect); - - write_nic_word(dev, RFPinsSelect, select | 0x7 | - SW_CONTROL_GPIO); - - force_pci_posting(dev); - udelay(10); - - write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); - - force_pci_posting(dev); - udelay(2); - - write_nic_word(dev, RFPinsOutput, out); - - force_pci_posting(dev); - udelay(10); - - for (i = 15; i >= 0; i--) { - bit = (bangdata & (1 << i)) >> i; - - write_nic_word(dev, RFPinsOutput, bit | out); - - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - - i--; - bit = (bangdata & (1 << i)) >> i; - - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - write_nic_word(dev, RFPinsOutput, bit | out | BB_HOST_BANG_CLK); - - write_nic_word(dev, RFPinsOutput, bit | out); - - } - - write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); - - force_pci_posting(dev); - udelay(10); - - write_nic_word(dev, RFPinsOutput, out | BB_HOST_BANG_EN); - - write_nic_word(dev, RFPinsSelect, select | SW_CONTROL_GPIO); - - rtl8185_rf_pins_enable(dev); -} - -static const u8 rtl8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, - 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, - 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, - 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, - 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, - 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, - 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, -}; - -static const u32 rtl8225_chan[] = { - 0, - 0x0080, 0x0100, 0x0180, 0x0200, 0x0280, 0x0300, 0x0380, - 0x0400, 0x0480, 0x0500, 0x0580, 0x0600, 0x0680, 0x074A, -}; - -static const u8 rtl8225z2_gain_bg[] = { - 0x23, 0x15, 0xa5, /* -82-1dBm */ - 0x23, 0x15, 0xb5, /* -82-2dBm */ - 0x23, 0x15, 0xc5, /* -82-3dBm */ - 0x33, 0x15, 0xc5, /* -78dBm */ - 0x43, 0x15, 0xc5, /* -74dBm */ - 0x53, 0x15, 0xc5, /* -70dBm */ - 0x63, 0x15, 0xc5, /* -66dBm */ -}; - -static const u8 rtl8225z2_gain_a[] = { - 0x13, 0x27, 0x5a, /* -82dBm */ - 0x23, 0x23, 0x58, /* -82dBm */ - 0x33, 0x1f, 0x56, /* -82dBm */ - 0x43, 0x1b, 0x54, /* -78dBm */ - 0x53, 0x17, 0x51, /* -74dBm */ - 0x63, 0x24, 0x4f, /* -70dBm */ - 0x73, 0x0f, 0x4c, /* -66dBm */ -}; - -static const u16 rtl8225z2_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb - -}; - -static void rtl8225z2_set_gain(struct net_device *dev, short gain) -{ - const u8 *rtl8225_gain; - struct r8180_priv *priv = ieee80211_priv(dev); - u8 mode = priv->ieee80211->mode; - - if (mode == IEEE_B || mode == IEEE_G) - rtl8225_gain = rtl8225z2_gain_bg; - else - rtl8225_gain = rtl8225z2_gain_a; - - write_phy_ofdm(dev, 0x0b, rtl8225_gain[gain * 3]); - write_phy_ofdm(dev, 0x1b, rtl8225_gain[gain * 3 + 1]); - write_phy_ofdm(dev, 0x1d, rtl8225_gain[gain * 3 + 2]); - write_phy_ofdm(dev, 0x21, 0x37); -} - -static u32 read_rtl8225(struct net_device *dev, u8 adr) -{ - u32 data2Write = ((u32)(adr & 0x1f)) << 27; - u32 dataRead; - u32 mask; - u16 oval, oval2, oval3, tmp; - int i; - short bit, rw; - u8 wLength = 6; - u8 rLength = 12; - u8 low2high = 0; - - oval = read_nic_word(dev, RFPinsOutput); - oval2 = read_nic_word(dev, RFPinsEnable); - oval3 = read_nic_word(dev, RFPinsSelect); - - write_nic_word(dev, RFPinsEnable, (oval2|0xf)); - write_nic_word(dev, RFPinsSelect, (oval3|0xf)); - - dataRead = 0; - - oval &= ~0xf; - - write_nic_word(dev, RFPinsOutput, oval | BB_HOST_BANG_EN); - udelay(4); - - write_nic_word(dev, RFPinsOutput, oval); - udelay(5); - - rw = 0; - - mask = (low2high) ? 0x01 : (((u32)0x01)<<(32-1)); - - for (i = 0; i < wLength/2; i++) { - bit = ((data2Write&mask) != 0) ? 1 : 0; - write_nic_word(dev, RFPinsOutput, bit | oval | rw); - udelay(1); - - write_nic_word(dev, RFPinsOutput, - bit | oval | BB_HOST_BANG_CLK | rw); - udelay(2); - write_nic_word(dev, RFPinsOutput, - bit | oval | BB_HOST_BANG_CLK | rw); - udelay(2); - - mask = (low2high) ? (mask<<1) : (mask>>1); - - if (i == 2) { - rw = BB_HOST_BANG_RW; - write_nic_word(dev, RFPinsOutput, - bit | oval | BB_HOST_BANG_CLK | rw); - udelay(2); - write_nic_word(dev, RFPinsOutput, bit | oval | rw); - udelay(2); - break; - } - - bit = ((data2Write&mask) != 0) ? 1 : 0; - - write_nic_word(dev, RFPinsOutput, - oval | bit | rw | BB_HOST_BANG_CLK); - udelay(2); - write_nic_word(dev, RFPinsOutput, - oval | bit | rw | BB_HOST_BANG_CLK); - udelay(2); - - write_nic_word(dev, RFPinsOutput, oval | bit | rw); - udelay(1); - - mask = (low2high) ? (mask<<1) : (mask>>1); - } - - write_nic_word(dev, RFPinsOutput, rw|oval); - udelay(2); - mask = (low2high) ? 0x01 : (((u32)0x01) << (12-1)); - - /* - * We must set data pin to HW controlled, otherwise RF can't driver it - * and value RF register won't be able to read back properly. - */ - write_nic_word(dev, RFPinsEnable, (oval2 & (~0x01))); - - for (i = 0; i < rLength; i++) { - write_nic_word(dev, RFPinsOutput, rw|oval); udelay(1); - - write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); - udelay(2); - write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); - udelay(2); - write_nic_word(dev, RFPinsOutput, rw|oval|BB_HOST_BANG_CLK); - udelay(2); - tmp = read_nic_word(dev, RFPinsInput); - - dataRead |= (tmp & BB_HOST_BANG_CLK ? mask : 0); - - write_nic_word(dev, RFPinsOutput, (rw|oval)); udelay(2); - - mask = (low2high) ? (mask<<1) : (mask>>1); - } - - write_nic_word(dev, RFPinsOutput, - BB_HOST_BANG_EN | BB_HOST_BANG_RW | oval); - udelay(2); - - write_nic_word(dev, RFPinsEnable, oval2); - write_nic_word(dev, RFPinsSelect, oval3); /* Set To SW Switch */ - write_nic_word(dev, RFPinsOutput, 0x3a0); - - return dataRead; -} - -void rtl8225z2_rf_close(struct net_device *dev) -{ - RF_WriteReg(dev, 0x4, 0x1f); - - force_pci_posting(dev); - mdelay(1); - - rtl8180_set_anaparam(dev, RTL8225z2_ANAPARAM_OFF); - rtl8185_set_anaparam2(dev, RTL8225z2_ANAPARAM2_OFF); -} - -/* - * Map dBm into Tx power index according to current HW model, for example, - * RF and PA, and current wireless mode. - */ -static s8 DbmToTxPwrIdx(struct r8180_priv *priv, - enum wireless_mode mode, s32 PowerInDbm) -{ - bool bUseDefault = true; - s8 TxPwrIdx = 0; - - /* - * OFDM Power in dBm = Index * 0.5 + 0 - * CCK Power in dBm = Index * 0.25 + 13 - */ - s32 tmp = 0; - - if (mode == WIRELESS_MODE_G) { - bUseDefault = false; - tmp = (2 * PowerInDbm); - - if (tmp < 0) - TxPwrIdx = 0; - else if (tmp > 40) /* 40 means 20 dBm. */ - TxPwrIdx = 40; - else - TxPwrIdx = (s8)tmp; - } else if (mode == WIRELESS_MODE_B) { - bUseDefault = false; - tmp = (4 * PowerInDbm) - 52; - - if (tmp < 0) - TxPwrIdx = 0; - else if (tmp > 28) /* 28 means 20 dBm. */ - TxPwrIdx = 28; - else - TxPwrIdx = (s8)tmp; - } - - /* - * TRUE if we want to use a default implementation. - * We shall set it to FALSE when we have exact translation formula - * for target IC. 070622, by rcnjko. - */ - if (bUseDefault) { - if (PowerInDbm < 0) - TxPwrIdx = 0; - else if (PowerInDbm > 35) - TxPwrIdx = 35; - else - TxPwrIdx = (u8)PowerInDbm; - } - - return TxPwrIdx; -} - -void rtl8225z2_SetTXPowerLevel(struct net_device *dev, short ch) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 max_cck_power_level; - u8 max_ofdm_power_level; - u8 min_ofdm_power_level; - char cck_power_level = (char)(0xff & priv->chtxpwr[ch]); - char ofdm_power_level = (char)(0xff & priv->chtxpwr_ofdm[ch]); - - if (IS_DOT11D_ENABLE(priv->ieee80211) && - IS_DOT11D_STATE_DONE(priv->ieee80211)) { - u8 MaxTxPwrInDbm = DOT11D_GetMaxTxPwrInDbm(priv->ieee80211, ch); - u8 CckMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_B, - MaxTxPwrInDbm); - u8 OfdmMaxPwrIdx = DbmToTxPwrIdx(priv, WIRELESS_MODE_G, - MaxTxPwrInDbm); - - if (cck_power_level > CckMaxPwrIdx) - cck_power_level = CckMaxPwrIdx; - if (ofdm_power_level > OfdmMaxPwrIdx) - ofdm_power_level = OfdmMaxPwrIdx; - } - - max_cck_power_level = 15; - max_ofdm_power_level = 25; - min_ofdm_power_level = 10; - - if (cck_power_level > 35) - cck_power_level = 35; - - write_nic_byte(dev, CCK_TXAGC, cck_power_level); - force_pci_posting(dev); - mdelay(1); - - if (ofdm_power_level > 35) - ofdm_power_level = 35; - - if (priv->up == 0) { - write_phy_ofdm(dev, 2, 0x42); - write_phy_ofdm(dev, 5, 0x00); - write_phy_ofdm(dev, 6, 0x40); - write_phy_ofdm(dev, 7, 0x00); - write_phy_ofdm(dev, 8, 0x40); - } - - write_nic_byte(dev, OFDM_TXAGC, ofdm_power_level); - - if (ofdm_power_level <= 11) { - write_phy_ofdm(dev, 0x07, 0x5c); - write_phy_ofdm(dev, 0x09, 0x5c); - } - - if (ofdm_power_level <= 17) { - write_phy_ofdm(dev, 0x07, 0x54); - write_phy_ofdm(dev, 0x09, 0x54); - } else { - write_phy_ofdm(dev, 0x07, 0x50); - write_phy_ofdm(dev, 0x09, 0x50); - } - - force_pci_posting(dev); - mdelay(1); -} - -void rtl8225z2_rf_set_chan(struct net_device *dev, short ch) -{ - rtl8225z2_SetTXPowerLevel(dev, ch); - - RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); - - if ((RF_ReadReg(dev, 0x7) & 0x0F80) != rtl8225_chan[ch]) - RF_WriteReg(dev, 0x7, rtl8225_chan[ch]); - - mdelay(1); - - force_pci_posting(dev); - mdelay(10); -} - -static void rtl8225_host_pci_init(struct net_device *dev) -{ - write_nic_word(dev, RFPinsOutput, 0x480); - - rtl8185_rf_pins_enable(dev); - - write_nic_word(dev, RFPinsSelect, 0x88 | SW_CONTROL_GPIO); - - write_nic_byte(dev, GP_ENABLE, 0); - - force_pci_posting(dev); - mdelay(200); - - /* bit 6 is for RF on/off detection */ - write_nic_word(dev, GP_ENABLE, 0xff & (~(1 << 6))); -} - -void rtl8225z2_rf_init(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int i; - short channel = 1; - u16 brsr; - u32 data; - - priv->chan = channel; - - rtl8225_host_pci_init(dev); - - write_nic_dword(dev, RF_TIMING, 0x000a8008); - - brsr = read_nic_word(dev, BRSR); - - write_nic_word(dev, BRSR, 0xffff); - - write_nic_dword(dev, RF_PARA, 0x100044); - - rtl8180_set_mode(dev, EPROM_CMD_CONFIG); - write_nic_byte(dev, CONFIG3, 0x44); - rtl8180_set_mode(dev, EPROM_CMD_NORMAL); - - rtl8185_rf_pins_enable(dev); - - write_rtl8225(dev, 0x0, 0x2bf); mdelay(1); - write_rtl8225(dev, 0x1, 0xee0); mdelay(1); - write_rtl8225(dev, 0x2, 0x44d); mdelay(1); - write_rtl8225(dev, 0x3, 0x441); mdelay(1); - write_rtl8225(dev, 0x4, 0x8c3); mdelay(1); - write_rtl8225(dev, 0x5, 0xc72); mdelay(1); - write_rtl8225(dev, 0x6, 0xe6); mdelay(1); - write_rtl8225(dev, 0x7, rtl8225_chan[channel]); mdelay(1); - write_rtl8225(dev, 0x8, 0x3f); mdelay(1); - write_rtl8225(dev, 0x9, 0x335); mdelay(1); - write_rtl8225(dev, 0xa, 0x9d4); mdelay(1); - write_rtl8225(dev, 0xb, 0x7bb); mdelay(1); - write_rtl8225(dev, 0xc, 0x850); mdelay(1); - write_rtl8225(dev, 0xd, 0xcdf); mdelay(1); - write_rtl8225(dev, 0xe, 0x2b); mdelay(1); - write_rtl8225(dev, 0xf, 0x114); - - mdelay(100); - - write_rtl8225(dev, 0x0, 0x1b7); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - write_rtl8225(dev, 0x1, i + 1); - write_rtl8225(dev, 0x2, rtl8225z2_rxgain[i]); - } - - write_rtl8225(dev, 0x3, 0x80); - write_rtl8225(dev, 0x5, 0x4); - - write_rtl8225(dev, 0x0, 0xb7); - - write_rtl8225(dev, 0x2, 0xc4d); - - /* FIXME!! rtl8187 we have to check if calibrarion - * is successful and eventually cal. again (repeat - * the two write on reg 2) - */ - data = read_rtl8225(dev, 6); - if (!(data & 0x00000080)) { - write_rtl8225(dev, 0x02, 0x0c4d); - force_pci_posting(dev); mdelay(200); - write_rtl8225(dev, 0x02, 0x044d); - force_pci_posting(dev); mdelay(100); - data = read_rtl8225(dev, 6); - if (!(data & 0x00000080)) - DMESGW("RF Calibration Failed!!!!\n"); - } - - mdelay(200); - - write_rtl8225(dev, 0x0, 0x2bf); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - write_phy_ofdm(dev, 0xb, rtl8225_agc[i]); - mdelay(1); - - /* enable writing AGC table */ - write_phy_ofdm(dev, 0xa, i + 0x80); - mdelay(1); - } - - force_pci_posting(dev); - mdelay(1); - - write_phy_ofdm(dev, 0x00, 0x01); mdelay(1); - write_phy_ofdm(dev, 0x01, 0x02); mdelay(1); - write_phy_ofdm(dev, 0x02, 0x62); mdelay(1); - write_phy_ofdm(dev, 0x03, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x04, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x05, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x06, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x07, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x08, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x09, 0xfe); mdelay(1); - write_phy_ofdm(dev, 0x0a, 0x08); mdelay(1); - write_phy_ofdm(dev, 0x0b, 0x80); mdelay(1); - write_phy_ofdm(dev, 0x0c, 0x01); mdelay(1); - write_phy_ofdm(dev, 0x0d, 0x43); - write_phy_ofdm(dev, 0x0e, 0xd3); mdelay(1); - write_phy_ofdm(dev, 0x0f, 0x38); mdelay(1); - write_phy_ofdm(dev, 0x10, 0x84); mdelay(1); - write_phy_ofdm(dev, 0x11, 0x07); mdelay(1); - write_phy_ofdm(dev, 0x12, 0x20); mdelay(1); - write_phy_ofdm(dev, 0x13, 0x20); mdelay(1); - write_phy_ofdm(dev, 0x14, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x15, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x16, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x17, 0x40); mdelay(1); - write_phy_ofdm(dev, 0x18, 0xef); mdelay(1); - write_phy_ofdm(dev, 0x19, 0x19); mdelay(1); - write_phy_ofdm(dev, 0x1a, 0x20); mdelay(1); - write_phy_ofdm(dev, 0x1b, 0x15); mdelay(1); - write_phy_ofdm(dev, 0x1c, 0x04); mdelay(1); - write_phy_ofdm(dev, 0x1d, 0xc5); mdelay(1); - write_phy_ofdm(dev, 0x1e, 0x95); mdelay(1); - write_phy_ofdm(dev, 0x1f, 0x75); mdelay(1); - write_phy_ofdm(dev, 0x20, 0x1f); mdelay(1); - write_phy_ofdm(dev, 0x21, 0x17); mdelay(1); - write_phy_ofdm(dev, 0x22, 0x16); mdelay(1); - write_phy_ofdm(dev, 0x23, 0x80); mdelay(1); /* FIXME maybe not needed */ - write_phy_ofdm(dev, 0x24, 0x46); mdelay(1); - write_phy_ofdm(dev, 0x25, 0x00); mdelay(1); - write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); - write_phy_ofdm(dev, 0x27, 0x88); mdelay(1); - - rtl8225z2_set_gain(dev, 4); - - write_phy_cck(dev, 0x0, 0x98); mdelay(1); - write_phy_cck(dev, 0x3, 0x20); mdelay(1); - write_phy_cck(dev, 0x4, 0x7e); mdelay(1); - write_phy_cck(dev, 0x5, 0x12); mdelay(1); - write_phy_cck(dev, 0x6, 0xfc); mdelay(1); - write_phy_cck(dev, 0x7, 0x78); mdelay(1); - write_phy_cck(dev, 0x8, 0x2e); mdelay(1); - write_phy_cck(dev, 0x10, 0x93); mdelay(1); - write_phy_cck(dev, 0x11, 0x88); mdelay(1); - write_phy_cck(dev, 0x12, 0x47); mdelay(1); - write_phy_cck(dev, 0x13, 0xd0); - write_phy_cck(dev, 0x19, 0x00); - write_phy_cck(dev, 0x1a, 0xa0); - write_phy_cck(dev, 0x1b, 0x08); - write_phy_cck(dev, 0x40, 0x86); /* CCK Carrier Sense Threshold */ - write_phy_cck(dev, 0x41, 0x8d); mdelay(1); - write_phy_cck(dev, 0x42, 0x15); mdelay(1); - write_phy_cck(dev, 0x43, 0x18); mdelay(1); - write_phy_cck(dev, 0x44, 0x36); mdelay(1); - write_phy_cck(dev, 0x45, 0x35); mdelay(1); - write_phy_cck(dev, 0x46, 0x2e); mdelay(1); - write_phy_cck(dev, 0x47, 0x25); mdelay(1); - write_phy_cck(dev, 0x48, 0x1c); mdelay(1); - write_phy_cck(dev, 0x49, 0x12); mdelay(1); - write_phy_cck(dev, 0x4a, 0x09); mdelay(1); - write_phy_cck(dev, 0x4b, 0x04); mdelay(1); - write_phy_cck(dev, 0x4c, 0x05); mdelay(1); - - write_nic_byte(dev, 0x5b, 0x0d); mdelay(1); - - rtl8225z2_SetTXPowerLevel(dev, channel); - - /* RX antenna default to A */ - write_phy_cck(dev, 0x11, 0x9b); mdelay(1); /* B: 0xDB */ - write_phy_ofdm(dev, 0x26, 0x90); mdelay(1); /* B: 0x10 */ - - rtl8185_tx_antenna(dev, 0x03); /* B: 0x00 */ - - /* switch to high-speed 3-wire - * last digit. 2 for both cck and ofdm - */ - write_nic_dword(dev, 0x94, 0x15c00002); - rtl8185_rf_pins_enable(dev); - - rtl8225z2_rf_set_chan(dev, priv->chan); -} - -#define MAX_DOZE_WAITING_TIMES_85B 20 -#define MAX_POLLING_24F_TIMES_87SE 10 -#define LPS_MAX_SLEEP_WAITING_TIMES_87SE 5 - -bool SetZebraRFPowerState8185(struct net_device *dev, - enum rt_rf_power_state eRFPowerState) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 btCR9346, btConfig3; - bool bActionAllowed = true, bTurnOffBB = true; - u8 u1bTmp; - int i; - bool bResult = true; - u8 QueueID; - - if (priv->SetRFPowerStateInProgress == true) - return false; - - priv->SetRFPowerStateInProgress = true; - - btCR9346 = read_nic_byte(dev, CR9346); - write_nic_byte(dev, CR9346, (btCR9346 | 0xC0)); - - btConfig3 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, (btConfig3 | CONFIG3_PARM_En)); - - switch (eRFPowerState) { - case RF_ON: - write_nic_word(dev, 0x37C, 0x00EC); - - /* turn on AFE */ - write_nic_byte(dev, 0x54, 0x00); - write_nic_byte(dev, 0x62, 0x00); - - /* turn on RF */ - RF_WriteReg(dev, 0x0, 0x009f); udelay(500); - RF_WriteReg(dev, 0x4, 0x0972); udelay(500); - - /* turn on RF again */ - RF_WriteReg(dev, 0x0, 0x009f); udelay(500); - RF_WriteReg(dev, 0x4, 0x0972); udelay(500); - - /* turn on BB */ - write_phy_ofdm(dev, 0x10, 0x40); - write_phy_ofdm(dev, 0x12, 0x40); - - /* Avoid power down at init time. */ - write_nic_byte(dev, CONFIG4, priv->RFProgType); - - u1bTmp = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, (u1bTmp & (~(BIT5 | BIT6)))); - break; - case RF_SLEEP: - for (QueueID = 0, i = 0; QueueID < 6;) { - if (get_curr_tx_free_desc(dev, QueueID) == - priv->txringcount) { - QueueID++; - continue; - } else { - priv->TxPollingTimes++; - if (priv->TxPollingTimes >= - LPS_MAX_SLEEP_WAITING_TIMES_87SE) { - bActionAllowed = false; - break; - } else - udelay(10); - } - } - - if (bActionAllowed) { - /* turn off BB RXIQ matrix to cut off rx signal */ - write_phy_ofdm(dev, 0x10, 0x00); - write_phy_ofdm(dev, 0x12, 0x00); - - /* turn off RF */ - RF_WriteReg(dev, 0x4, 0x0000); - RF_WriteReg(dev, 0x0, 0x0000); - - /* turn off AFE except PLL */ - write_nic_byte(dev, 0x62, 0xff); - write_nic_byte(dev, 0x54, 0xec); - - mdelay(1); - - { - int i = 0; - while (true) { - u8 tmp24F = read_nic_byte(dev, 0x24f); - - if ((tmp24F == 0x01) || - (tmp24F == 0x09)) { - bTurnOffBB = true; - break; - } else { - udelay(10); - i++; - priv->TxPollingTimes++; - - if (priv->TxPollingTimes >= LPS_MAX_SLEEP_WAITING_TIMES_87SE) { - bTurnOffBB = false; - break; - } else - udelay(10); - } - } - } - - if (bTurnOffBB) { - /* turn off BB */ - u1bTmp = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, - (u1bTmp | BIT5 | BIT6)); - - /* turn off AFE PLL */ - write_nic_byte(dev, 0x54, 0xFC); - write_nic_word(dev, 0x37C, 0x00FC); - } - } - break; - case RF_OFF: - for (QueueID = 0, i = 0; QueueID < 6;) { - if (get_curr_tx_free_desc(dev, QueueID) == - priv->txringcount) { - QueueID++; - continue; - } else { - udelay(10); - i++; - } - - if (i >= MAX_DOZE_WAITING_TIMES_85B) - break; - } - - /* turn off BB RXIQ matrix to cut off rx signal */ - write_phy_ofdm(dev, 0x10, 0x00); - write_phy_ofdm(dev, 0x12, 0x00); - - /* turn off RF */ - RF_WriteReg(dev, 0x4, 0x0000); - RF_WriteReg(dev, 0x0, 0x0000); - - /* turn off AFE except PLL */ - write_nic_byte(dev, 0x62, 0xff); - write_nic_byte(dev, 0x54, 0xec); - - mdelay(1); - - { - int i = 0; - - while (true) { - u8 tmp24F = read_nic_byte(dev, 0x24f); - - if ((tmp24F == 0x01) || (tmp24F == 0x09)) { - bTurnOffBB = true; - break; - } else { - bTurnOffBB = false; - udelay(10); - i++; - } - - if (i > MAX_POLLING_24F_TIMES_87SE) - break; - } - } - - if (bTurnOffBB) { - /* turn off BB */ - u1bTmp = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, (u1bTmp | BIT5 | BIT6)); - - /* turn off AFE PLL (80M) */ - write_nic_byte(dev, 0x54, 0xFC); - write_nic_word(dev, 0x37C, 0x00FC); - } - break; - } - - btConfig3 &= ~(CONFIG3_PARM_En); - write_nic_byte(dev, CONFIG3, btConfig3); - - btCR9346 &= ~(0xC0); - write_nic_byte(dev, CR9346, btCR9346); - - if (bResult && bActionAllowed) - priv->eRFPowerState = eRFPowerState; - - priv->SetRFPowerStateInProgress = false; - - return bResult && bActionAllowed; -} - -void rtl8225z4_rf_sleep(struct net_device *dev) -{ - MgntActSet_RF_State(dev, RF_SLEEP, RF_CHANGE_BY_PS); -} - -void rtl8225z4_rf_wakeup(struct net_device *dev) -{ - MgntActSet_RF_State(dev, RF_ON, RF_CHANGE_BY_PS); -} diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c deleted file mode 100644 index b55249170f18b2..00000000000000 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ /dev/null @@ -1,1409 +0,0 @@ -/* - This file contains wireless extension handlers. - - This is part of rtl8180 OpenSource driver. - Copyright (C) Andrea Merello 2004-2005 - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part - of the official realtek driver. - - Parts of this driver are based on the rtl8180 driver skeleton - from Patric Schenke & Andres Salomon. - - Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver. - - We want to thanks the Authors of those projects and the Ndiswrapper - project Authors. -*/ - - -#include "r8180.h" -#include "r8180_hw.h" - -#include -#include "ieee80211/dot11d.h" - -static u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000, - 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000}; - -#define RATE_COUNT ARRAY_SIZE(rtl8180_rates) - -static struct rtl8187se_channel_list default_channel_plan[] = { - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19}, /* FCC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, /* IC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* ETSI */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* Spain. Change to ETSI. */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* France. Change to ETSI. */ - {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9}, /* MKK */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22}, /* MKK1 */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21}, /* Israel */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17}, /* For 11a , TELEC */ - {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14} /* For Global Domain. 1-11:active scan, 12-14 passive scan.*/ /* +YJ, 080626 */ -}; -static int r8180_wx_get_freq(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b); -} - - -static int r8180_wx_set_key(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct iw_point *erq = &(wrqu->encoding); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (erq->length > 0) { - u32 *tkey = (u32 *) key; - priv->key0[0] = tkey[0]; - priv->key0[1] = tkey[1]; - priv->key0[2] = tkey[2]; - priv->key0[3] = tkey[3] & 0xff; - DMESG("Setting wep key to %x %x %x %x", - tkey[0], tkey[1], tkey[2], tkey[3]); - rtl8180_set_hw_wep(dev); - } - return 0; -} - - -static int r8180_wx_set_beaconinterval(struct net_device *dev, - struct iw_request_info *aa, - union iwreq_data *wrqu, char *b) -{ - int *parms = (int *)b; - int bi = parms[0]; - - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - DMESG("setting beacon interval to %x", bi); - - priv->ieee80211->current_network.beacon_interval = bi; - rtl8180_commit(dev); - up(&priv->wx_sem); - - return 0; -} - - - -static int r8180_wx_get_mode(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b); -} - - - -static int r8180_wx_get_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra); -} - - - -static int r8180_wx_set_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; -} - - -static int r8180_wx_set_crcmon(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int *parms = (int *)extra; - int enable = (parms[0] > 0); - short prev = priv->crcmon; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - if (enable) - priv->crcmon = 1; - else - priv->crcmon = 0; - - DMESG("bad CRC in monitor mode are %s", - priv->crcmon ? "accepted" : "rejected"); - - if (prev != priv->crcmon && priv->up) { - rtl8180_down(dev); - rtl8180_up(dev); - } - - up(&priv->wx_sem); - - return 0; -} - - -static int r8180_wx_set_mode(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (priv->bInactivePs) { - if (wrqu->mode == IW_MODE_ADHOC) - IPSLeave(dev); - } - ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - return ret; -} - -/* YJ,add,080819,for hidden ap */ -struct iw_range_with_scan_capa { - /* Informative stuff (to choose between different interface) */ - - __u32 throughput; /* To give an idea... */ - - /* In theory this value should be the maximum benchmarked - * TCP/IP throughput, because with most of these devices the - * bit rate is meaningless (overhead an co) to estimate how - * fast the connection will go and pick the fastest one. - * I suggest people to play with Netperf or any benchmark... - */ - - /* NWID (or domain id) */ - __u32 min_nwid; /* Minimal NWID we are able to set */ - __u32 max_nwid; /* Maximal NWID we are able to set */ - - /* Old Frequency (backward compat - moved lower ) */ - __u16 old_num_channels; - __u8 old_num_frequency; - - /* Scan capabilities */ - __u8 scan_capa; -}; -/* YJ,add,080819,for hidden ap */ - - -static int rtl8180_wx_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - struct r8180_priv *priv = ieee80211_priv(dev); - u16 val; - int i; - - wrqu->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - /* Let's try to keep this struct in the same order as in - * linux/include/wireless.h - */ - - /* TODO: See what values we can set, and remove the ones we can't - * set, or fill them with some default data. - */ - - /* ~5 Mb/s real (802.11b) */ - range->throughput = 5 * 1000 * 1000; - - /* TODO: Not used in 802.11b? */ -/* range->min_nwid; */ /* Minimal NWID we are able to set */ - /* TODO: Not used in 802.11b? */ -/* range->max_nwid; */ /* Maximal NWID we are able to set */ - - /* Old Frequency (backward compat - moved lower ) */ -/* range->old_num_channels; */ -/* range->old_num_frequency; */ -/* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */ - if (priv->rf_set_sens != NULL) - range->sensitivity = priv->max_sens; /* signal level threshold range */ - - range->max_qual.qual = 100; - /* TODO: Find real max RSSI and stick here */ - range->max_qual.level = 0; - range->max_qual.noise = -98; - range->max_qual.updated = 7; /* Updated all three */ - - range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ - range->avg_qual.level = 20 + -98; - range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ - - range->num_bitrates = RATE_COUNT; - - for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) - range->bitrate[i] = rtl8180_rates[i]; - - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->pm_capa = 0; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 16; - - range->num_channels = 14; - - for (i = 0, val = 0; i < 14; i++) { - - /* Include only legal frequencies for some countries */ - if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { - range->freq[val].i = i + 1; - range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; - range->freq[val].e = 1; - val++; - } else { - /* FIXME: do we need to set anything for channels */ - /* we don't use ? */ - } - - if (val == IW_MAX_FREQUENCIES) - break; - } - - range->num_frequency = val; - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - - return 0; -} - - -static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - struct ieee80211_device *ieee = priv->ieee80211; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - struct iw_scan_req *req = (struct iw_scan_req *)b; - if (req->essid_len) { - ieee->current_network.ssid_len = req->essid_len; - memcpy(ieee->current_network.ssid, req->essid, req->essid_len); - } - } - - down(&priv->wx_sem); - if (priv->up) { - priv->ieee80211->actscanning = true; - if (priv->bInactivePs && (priv->ieee80211->state != IEEE80211_LINKED)) { - IPSLeave(dev); - ieee80211_softmac_ips_scan_syncro(priv->ieee80211); - ret = 0; - } else { - /* prevent scan in BusyTraffic */ - /* FIXME: Need to consider last scan time */ - if ((priv->link_detect.b_busy_traffic) && (true)) { - ret = 0; - printk("Now traffic is busy, please try later!\n"); - } else - /* prevent scan in BusyTraffic,end */ - ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b); - } - } else - ret = -1; - - up(&priv->wx_sem); - - return ret; -} - - -static int r8180_wx_get_scan(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - down(&priv->wx_sem); - if (priv->up) - ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b); - else - ret = -1; - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_set_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - int ret; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (priv->bInactivePs) - IPSLeave(dev); - - ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_get_essid(struct net_device *dev, - struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - down(&priv->wx_sem); - - ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - - return ret; -} - - -static int r8180_wx_set_freq(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); -} - -static int r8180_wx_set_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (wrqu->frag.disabled) - priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; - else { - if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) - return -EINVAL; - - priv->ieee80211->fts = wrqu->frag.value & ~0x1; - } - - return 0; -} - - -static int r8180_wx_get_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - wrqu->frag.value = priv->ieee80211->fts; - wrqu->frag.fixed = 0; /* no auto select */ - wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); - - return 0; -} - - -static int r8180_wx_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *awrq, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra); - - up(&priv->wx_sem); - return ret; - -} - - -static int r8180_wx_get_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra); -} - - -static int r8180_wx_set_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); - - if (priv->hw_wep) - ret = r8180_wx_set_key(dev, info, wrqu, key); - else { - DMESG("Setting SW wep key"); - ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key); - } - - up(&priv->wx_sem); - return ret; -} - - -static int r8180_wx_get_enc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); -} - - -static int r8180_wx_set_scan_type(struct net_device *dev, - struct iw_request_info *aa, - union iwreq_data *wrqu, char *p) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - int *parms = (int *)p; - int mode = parms[0]; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - priv->ieee80211->active_scan = mode; - - return 1; -} - -static int r8180_wx_set_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int err = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - if (wrqu->retry.flags & IW_RETRY_LIFETIME || - wrqu->retry.disabled) { - err = -EINVAL; - goto exit; - } - if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { - err = -EINVAL; - goto exit; - } - - if (wrqu->retry.value > R8180_MAX_RETRY) { - err = -EINVAL; - goto exit; - } - if (wrqu->retry.flags & IW_RETRY_MAX) { - priv->retry_rts = wrqu->retry.value; - DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); - - } else { - priv->retry_data = wrqu->retry.value; - DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); - } - - /* FIXME ! - * We might try to write directly the TX config register - * or to restart just the (R)TX process. - * I'm unsure if whole reset is really needed - */ - - rtl8180_commit(dev); -exit: - up(&priv->wx_sem); - - return err; -} - -static int r8180_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - wrqu->retry.disabled = 0; /* can't be disabled */ - - if ((wrqu->retry.flags & IW_RETRY_TYPE) == - IW_RETRY_LIFETIME) - return -EINVAL; - - if (wrqu->retry.flags & IW_RETRY_MAX) { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - wrqu->retry.value = priv->retry_rts; - } else { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; - wrqu->retry.value = priv->retry_data; - } - - return 0; -} - -static int r8180_wx_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - if (priv->rf_set_sens == NULL) - return -1; /* we have not this support for this radio */ - wrqu->sens.value = priv->sens; - return 0; -} - - -static int r8180_wx_set_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - - short err = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (priv->rf_set_sens == NULL) { - err = -1; /* we have not this support for this radio */ - goto exit; - } - if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) - priv->sens = wrqu->sens.value; - else - err = -EINVAL; - -exit: - up(&priv->wx_sem); - - return err; -} - - -static int r8180_wx_set_rawtx(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; - -} - -static int r8180_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - down(&priv->wx_sem); - - ret = ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; -} - -static int r8180_wx_set_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - printk("=>>>>>>>>>>=============================>set power:%d, %d!\n", wrqu->power.disabled, wrqu->power.flags); - if (wrqu->power.disabled == 0) { - wrqu->power.flags |= IW_POWER_ALL_R; - wrqu->power.flags |= IW_POWER_TIMEOUT; - wrqu->power.value = 1000; - } - - ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra); - - up(&priv->wx_sem); - - return ret; -} - -static int r8180_wx_set_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - if (wrqu->rts.disabled) - priv->rts = DEFAULT_RTS_THRESHOLD; - else { - if (wrqu->rts.value < MIN_RTS_THRESHOLD || - wrqu->rts.value > MAX_RTS_THRESHOLD) - return -EINVAL; - - priv->rts = wrqu->rts.value; - } - - return 0; -} -static int r8180_wx_get_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - - wrqu->rts.value = priv->rts; - wrqu->rts.fixed = 0; /* no auto select */ - wrqu->rts.disabled = (wrqu->rts.value == 0); - - return 0; -} -static int dummy(struct net_device *dev, struct iw_request_info *a, - union iwreq_data *wrqu, char *b) -{ - return -1; -} - -static int r8180_wx_get_iwmode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee; - int ret = 0; - - - - down(&priv->wx_sem); - - ieee = priv->ieee80211; - - strcpy(extra, "802.11"); - if (ieee->modulation & IEEE80211_CCK_MODULATION) { - strcat(extra, "b"); - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strcat(extra, "/g"); - } else if (ieee->modulation & IEEE80211_OFDM_MODULATION) - strcat(extra, "g"); - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_set_iwmode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - int *param = (int *)extra; - int ret = 0; - int modulation = 0, mode = 0; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - - if (*param == 1) { - modulation |= IEEE80211_CCK_MODULATION; - mode = IEEE_B; - printk(KERN_INFO "B mode!\n"); - } else if (*param == 2) { - modulation |= IEEE80211_OFDM_MODULATION; - mode = IEEE_G; - printk(KERN_INFO "G mode!\n"); - } else if (*param == 3) { - modulation |= IEEE80211_CCK_MODULATION; - modulation |= IEEE80211_OFDM_MODULATION; - mode = IEEE_B|IEEE_G; - printk(KERN_INFO "B/G mode!\n"); - } - - if (ieee->proto_started) { - ieee80211_stop_protocol(ieee); - ieee->mode = mode; - ieee->modulation = modulation; - ieee80211_start_protocol(ieee); - } else { - ieee->mode = mode; - ieee->modulation = modulation; - } - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_get_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - - down(&priv->wx_sem); - - - - *extra = (char) priv->plcp_preamble_mode; /* 0:auto 1:short 2:long */ - up(&priv->wx_sem); - - return 0; -} -static int r8180_wx_set_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - if (*extra < 0 || *extra > 2) - ret = -1; - else - priv->plcp_preamble_mode = *((short *)extra); - - - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_get_siglevel(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - - - down(&priv->wx_sem); - /* Modify by hikaru 6.5 */ - *((int *)extra) = priv->wstats.qual.level;/*for interface test ,it should be the priv->wstats.qual.level; */ - - - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_get_sigqual(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - - - down(&priv->wx_sem); - /* Modify by hikaru 6.5 */ - *((int *)extra) = priv->wstats.qual.qual;/* for interface test ,it should be the priv->wstats.qual.qual; */ - - - - up(&priv->wx_sem); - - return ret; -} -static int r8180_wx_reset_stats(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - down(&priv->wx_sem); - - priv->stats.txrdu = 0; - priv->stats.rxrdu = 0; - priv->stats.rxnolast = 0; - priv->stats.rxnodata = 0; - priv->stats.rxnopointer = 0; - priv->stats.txnperr = 0; - priv->stats.txresumed = 0; - priv->stats.rxerr = 0; - priv->stats.rxoverflow = 0; - priv->stats.rxint = 0; - - priv->stats.txnpokint = 0; - priv->stats.txhpokint = 0; - priv->stats.txhperr = 0; - priv->stats.ints = 0; - priv->stats.shints = 0; - priv->stats.txoverflow = 0; - priv->stats.rxdmafail = 0; - priv->stats.txbeacon = 0; - priv->stats.txbeaconerr = 0; - priv->stats.txlpokint = 0; - priv->stats.txlperr = 0; - priv->stats.txretry = 0;/* 20060601 */ - priv->stats.rxcrcerrmin = 0 ; - priv->stats.rxcrcerrmid = 0; - priv->stats.rxcrcerrmax = 0; - priv->stats.rxicverr = 0; - - up(&priv->wx_sem); - - return 0; - -} -static int r8180_wx_radio_on(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); - priv->rf_wakeup(dev); - - up(&priv->wx_sem); - - return 0; - -} - -static int r8180_wx_radio_off(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); - priv->rf_sleep(dev); - - up(&priv->wx_sem); - - return 0; - -} -static int r8180_wx_get_channelplan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - - - - down(&priv->wx_sem); - *extra = priv->channel_plan; - - - - up(&priv->wx_sem); - - return 0; -} -static int r8180_wx_set_channelplan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int *val = (int *)extra; - int i; - printk("-----in fun %s\n", __func__); - - if (priv->ieee80211->bHwRadioOff) - return 0; - - /* unsigned long flags; */ - down(&priv->wx_sem); - if (default_channel_plan[*val].len != 0) { - priv->channel_plan = *val; - /* Clear old channel map 8 */ - for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) - GET_DOT11D_INFO(priv->ieee80211)->channel_map[i] = 0; - - /* Set new channel map */ - for (i = 1; i <= default_channel_plan[*val].len; i++) - GET_DOT11D_INFO(priv->ieee80211)->channel_map[default_channel_plan[*val].channel[i-1]] = 1; - - } - up(&priv->wx_sem); - - return 0; -} - -static int r8180_wx_get_version(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - /* struct ieee80211_device *ieee; */ - - down(&priv->wx_sem); - strcpy(extra, "1020.0808"); - up(&priv->wx_sem); - - return 0; -} - -/* added by amy 080818 */ -/*receive datarate from user typing valid rate is from 2 to 108 (1 - 54M), if input 0, return to normal rate adaptive. */ -static int r8180_wx_set_forcerate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - u8 forcerate = *extra; - - down(&priv->wx_sem); - - printk("==============>%s(): forcerate is %d\n", __func__, forcerate); - if ((forcerate == 2) || (forcerate == 4) || (forcerate == 11) || (forcerate == 22) || (forcerate == 12) || - (forcerate == 18) || (forcerate == 24) || (forcerate == 36) || (forcerate == 48) || (forcerate == 72) || - (forcerate == 96) || (forcerate == 108)) { - priv->ForcedDataRate = 1; - priv->ieee80211->rate = forcerate * 5; - } else if (forcerate == 0) { - priv->ForcedDataRate = 0; - printk("OK! return rate adaptive\n"); - } else - printk("ERR: wrong rate\n"); - up(&priv->wx_sem); - return 0; -} - -static int r8180_wx_set_enc_ext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - - struct r8180_priv *priv = ieee80211_priv(dev); - - int ret = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); - up(&priv->wx_sem); - return ret; - -} -static int r8180_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - int ret = 0; - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); - ret = ieee80211_wx_set_auth(priv->ieee80211, info, &wrqu->param, extra); - up(&priv->wx_sem); - return ret; -} - -static int r8180_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - - down(&priv->wx_sem); -#if 1 - ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); -#endif - up(&priv->wx_sem); - return ret; -} -static int r8180_wx_set_gen_ie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int ret = 0; - struct r8180_priv *priv = ieee80211_priv(dev); - - - if (priv->ieee80211->bHwRadioOff) - return 0; - - down(&priv->wx_sem); -#if 1 - ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length); -#endif - up(&priv->wx_sem); - return ret; - - -} - -static const iw_handler r8180_wx_handlers[] = { - IW_HANDLER(SIOCGIWNAME, r8180_wx_get_name), - IW_HANDLER(SIOCSIWNWID, dummy), - IW_HANDLER(SIOCGIWNWID, dummy), - IW_HANDLER(SIOCSIWFREQ, r8180_wx_set_freq), - IW_HANDLER(SIOCGIWFREQ, r8180_wx_get_freq), - IW_HANDLER(SIOCSIWMODE, r8180_wx_set_mode), - IW_HANDLER(SIOCGIWMODE, r8180_wx_get_mode), - IW_HANDLER(SIOCSIWSENS, r8180_wx_set_sens), - IW_HANDLER(SIOCGIWSENS, r8180_wx_get_sens), - IW_HANDLER(SIOCGIWRANGE, rtl8180_wx_get_range), - IW_HANDLER(SIOCSIWSPY, dummy), - IW_HANDLER(SIOCGIWSPY, dummy), - IW_HANDLER(SIOCSIWAP, r8180_wx_set_wap), - IW_HANDLER(SIOCGIWAP, r8180_wx_get_wap), - IW_HANDLER(SIOCSIWMLME, r8180_wx_set_mlme), - IW_HANDLER(SIOCGIWAPLIST, dummy), /* deprecated */ - IW_HANDLER(SIOCSIWSCAN, r8180_wx_set_scan), - IW_HANDLER(SIOCGIWSCAN, r8180_wx_get_scan), - IW_HANDLER(SIOCSIWESSID, r8180_wx_set_essid), - IW_HANDLER(SIOCGIWESSID, r8180_wx_get_essid), - IW_HANDLER(SIOCSIWNICKN, dummy), - IW_HANDLER(SIOCGIWNICKN, dummy), - IW_HANDLER(SIOCSIWRATE, r8180_wx_set_rate), - IW_HANDLER(SIOCGIWRATE, r8180_wx_get_rate), - IW_HANDLER(SIOCSIWRTS, r8180_wx_set_rts), - IW_HANDLER(SIOCGIWRTS, r8180_wx_get_rts), - IW_HANDLER(SIOCSIWFRAG, r8180_wx_set_frag), - IW_HANDLER(SIOCGIWFRAG, r8180_wx_get_frag), - IW_HANDLER(SIOCSIWTXPOW, dummy), - IW_HANDLER(SIOCGIWTXPOW, dummy), - IW_HANDLER(SIOCSIWRETRY, r8180_wx_set_retry), - IW_HANDLER(SIOCGIWRETRY, r8180_wx_get_retry), - IW_HANDLER(SIOCSIWENCODE, r8180_wx_set_enc), - IW_HANDLER(SIOCGIWENCODE, r8180_wx_get_enc), - IW_HANDLER(SIOCSIWPOWER, r8180_wx_set_power), - IW_HANDLER(SIOCGIWPOWER, r8180_wx_get_power), - IW_HANDLER(SIOCSIWGENIE, r8180_wx_set_gen_ie), - IW_HANDLER(SIOCSIWAUTH, r8180_wx_set_auth), - IW_HANDLER(SIOCSIWENCODEEXT, r8180_wx_set_enc_ext), -}; - -static const struct iw_priv_args r8180_private_args[] = { - { - SIOCIWFIRSTPRIV + 0x0, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" - }, - { SIOCIWFIRSTPRIV + 0x1, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x2, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beaconint" - }, - { SIOCIWFIRSTPRIV + 0x3, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x4, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" - - }, - { SIOCIWFIRSTPRIV + 0x5, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x6, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" - - }, - { SIOCIWFIRSTPRIV + 0x7, - 0, 0, "dummy" - - }, - { - SIOCIWFIRSTPRIV + 0x8, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setiwmode" - }, - { - SIOCIWFIRSTPRIV + 0x9, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getiwmode" - }, - { - SIOCIWFIRSTPRIV + 0xA, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpreamble" - }, - { - SIOCIWFIRSTPRIV + 0xB, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpreamble" - }, - { SIOCIWFIRSTPRIV + 0xC, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0xD, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getrssi" - }, - { SIOCIWFIRSTPRIV + 0xE, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0xF, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getlinkqual" - }, - { - SIOCIWFIRSTPRIV + 0x10, - 0, 0, "resetstats" - }, - { - SIOCIWFIRSTPRIV + 0x11, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0x12, - 0, 0, "radioon" - }, - { - SIOCIWFIRSTPRIV + 0x13, - 0, 0, "radiooff" - }, - { - SIOCIWFIRSTPRIV + 0x14, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setchannel" - }, - { - SIOCIWFIRSTPRIV + 0x15, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel" - }, - { - SIOCIWFIRSTPRIV + 0x16, - 0, 0, "dummy" - }, - { - SIOCIWFIRSTPRIV + 0x17, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getversion" - }, - { - SIOCIWFIRSTPRIV + 0x18, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setrate" - }, -}; - - -static iw_handler r8180_private_handler[] = { - r8180_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ - dummy, - r8180_wx_set_beaconinterval, - dummy, - /* r8180_wx_set_monitor_type, */ - r8180_wx_set_scan_type, - dummy, - r8180_wx_set_rawtx, - dummy, - r8180_wx_set_iwmode, - r8180_wx_get_iwmode, - r8180_wx_set_preamble, - r8180_wx_get_preamble, - dummy, - r8180_wx_get_siglevel, - dummy, - r8180_wx_get_sigqual, - r8180_wx_reset_stats, - dummy,/* r8180_wx_get_stats */ - r8180_wx_radio_on, - r8180_wx_radio_off, - r8180_wx_set_channelplan, - r8180_wx_get_channelplan, - dummy, - r8180_wx_get_version, - r8180_wx_set_forcerate, -}; - -static inline int is_same_network(struct ieee80211_network *src, - struct ieee80211_network *dst, - struct ieee80211_device *ieee) -{ - /* A network is only a duplicate if the channel, BSSID, ESSID - * and the capability field (in particular IBSS and BSS) all match. - * We treat all with the same BSSID and channel - * as one network - */ - if (src->channel != dst->channel) - return 0; - - if (memcmp(src->bssid, dst->bssid, ETH_ALEN) != 0) - return 0; - - if (ieee->iw_mode != IW_MODE_INFRA) { - if (src->ssid_len != dst->ssid_len) - return 0; - if (memcmp(src->ssid, dst->ssid, src->ssid_len) != 0) - return 0; - } - - if ((src->capability & WLAN_CAPABILITY_IBSS) != - (dst->capability & WLAN_CAPABILITY_IBSS)) - return 0; - if ((src->capability & WLAN_CAPABILITY_BSS) != - (dst->capability & WLAN_CAPABILITY_BSS)) - return 0; - - return 1; -} - -/* WB modified to show signal to GUI on 18-01-2008 */ -static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - struct iw_statistics *wstats = &priv->wstats; - int tmp_level = 0; - int tmp_qual = 0; - int tmp_noise = 0; - - if (ieee->state < IEEE80211_LINKED) { - wstats->qual.qual = 0; - wstats->qual.level = 0; - wstats->qual.noise = 0; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; - } - - tmp_level = (&ieee->current_network)->stats.signal; - tmp_qual = (&ieee->current_network)->stats.signalstrength; - tmp_noise = (&ieee->current_network)->stats.noise; - - wstats->qual.level = tmp_level; - wstats->qual.qual = tmp_qual; - wstats->qual.noise = tmp_noise; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; -} - -struct iw_handler_def r8180_wx_handlers_def = { - .standard = r8180_wx_handlers, - .num_standard = ARRAY_SIZE(r8180_wx_handlers), - .private = r8180_private_handler, - .num_private = ARRAY_SIZE(r8180_private_handler), - .num_private_args = sizeof(r8180_private_args) / sizeof(struct iw_priv_args), - .get_wireless_stats = r8180_get_wireless_stats, - .private_args = (struct iw_priv_args *)r8180_private_args, -}; - - diff --git a/drivers/staging/rtl8187se/r8180_wx.h b/drivers/staging/rtl8187se/r8180_wx.h deleted file mode 100644 index d471520ac7724f..00000000000000 --- a/drivers/staging/rtl8187se/r8180_wx.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - This is part of rtl8180 OpenSource driver - v 0.3 - Copyright (C) Andrea Merello 2004 - Released under the terms of GPL (General Public Licence) - - Parts of this driver are based on the GPL part of the official realtek driver - Parts of this driver are based on the rtl8180 driver skeleton from Patric Schenke & Andres Salomon - Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver - - We want to thanks the Authors of such projects and the Ndiswrapper project Authors. -*/ - -/* this file (will) contains wireless extension handlers*/ - -#ifndef R8180_WX_H -#define R8180_WX_H -#include -#include "ieee80211/ieee80211.h" -extern struct iw_handler_def r8180_wx_handlers_def; - -#endif diff --git a/drivers/staging/rtl8187se/r8185b_init.c b/drivers/staging/rtl8187se/r8185b_init.c deleted file mode 100644 index cc6f100814f333..00000000000000 --- a/drivers/staging/rtl8187se/r8185b_init.c +++ /dev/null @@ -1,1464 +0,0 @@ -/* - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * Module Name: - * r8185b_init.c - * - * Abstract: - * Hardware Initialization and Hardware IO for RTL8185B - * - * Major Change History: - * When Who What - * ---------- --------------- ------------------------------- - * 2006-11-15 Xiong Created - * - * Notes: - * This file is ported from RTL8185B Windows driver. - * - * - */ - -/*--------------------------Include File------------------------------------*/ -#include -#include "r8180_hw.h" -#include "r8180.h" -#include "r8180_rtl8225.h" /* RTL8225 Radio frontend */ -#include "r8180_93cx6.h" /* Card EEPROM */ -#include "r8180_wx.h" -#include "ieee80211/dot11d.h" -/* #define CONFIG_RTL8180_IO_MAP */ -#define TC_3W_POLL_MAX_TRY_CNT 5 - -static u8 MAC_REG_TABLE[][2] = { - /* - * PAGE 0: - * 0x34(BRSR), 0xBE(RATE_FALLBACK_CTL), 0x1E0(ARFR) would set in - * HwConfigureRTL8185() - * 0x272(RFSW_CTRL), 0x1CE(AESMSK_QC) set in InitializeAdapter8185(). - * 0x1F0~0x1F8 set in MacConfig_85BASIC() - */ - {0x08, 0xae}, {0x0a, 0x72}, {0x5b, 0x42}, - {0x84, 0x88}, {0x85, 0x24}, {0x88, 0x54}, {0x8b, 0xb8}, {0x8c, 0x03}, - {0x8d, 0x40}, {0x8e, 0x00}, {0x8f, 0x00}, {0x5b, 0x18}, {0x91, 0x03}, - {0x94, 0x0F}, {0x95, 0x32}, - {0x96, 0x00}, {0x97, 0x07}, {0xb4, 0x22}, {0xdb, 0x00}, - {0xf0, 0x32}, {0xf1, 0x32}, {0xf2, 0x00}, {0xf3, 0x00}, {0xf4, 0x32}, - {0xf5, 0x43}, {0xf6, 0x00}, {0xf7, 0x00}, {0xf8, 0x46}, {0xf9, 0xa4}, - {0xfa, 0x00}, {0xfb, 0x00}, {0xfc, 0x96}, {0xfd, 0xa4}, {0xfe, 0x00}, - {0xff, 0x00}, - - /* - * PAGE 1: - * For Flextronics system Logo PCIHCT failure: - * 0x1C4~0x1CD set no-zero value to avoid PCI configuration - * space 0x45[7]=1 - */ - {0x5e, 0x01}, - {0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x04}, {0x5b, 0x00}, {0x60, 0x24}, - {0x61, 0x97}, {0x62, 0xF0}, {0x63, 0x09}, {0x80, 0x0F}, {0x81, 0xFF}, - {0x82, 0xFF}, {0x83, 0x03}, - /* lzm add 080826 */ - {0xC4, 0x22}, {0xC5, 0x22}, {0xC6, 0x22}, {0xC7, 0x22}, {0xC8, 0x22}, - /* lzm add 080826 */ - {0xC9, 0x22}, {0xCA, 0x22}, {0xCB, 0x22}, {0xCC, 0x22}, {0xCD, 0x22}, - {0xe2, 0x00}, - - - /* PAGE 2: */ - {0x5e, 0x02}, - {0x0c, 0x04}, {0x4c, 0x30}, {0x4d, 0x08}, {0x50, 0x05}, {0x51, 0xf5}, - {0x52, 0x04}, {0x53, 0xa0}, {0x54, 0xff}, {0x55, 0xff}, {0x56, 0xff}, - {0x57, 0xff}, {0x58, 0x08}, {0x59, 0x08}, {0x5a, 0x08}, {0x5b, 0x08}, - {0x60, 0x08}, {0x61, 0x08}, {0x62, 0x08}, {0x63, 0x08}, {0x64, 0x2f}, - {0x8c, 0x3f}, {0x8d, 0x3f}, {0x8e, 0x3f}, - {0x8f, 0x3f}, {0xc4, 0xff}, {0xc5, 0xff}, {0xc6, 0xff}, {0xc7, 0xff}, - {0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x80}, {0xcb, 0x00}, - - /* PAGE 0: */ - {0x5e, 0x00}, {0x9f, 0x03} - }; - - -static u8 ZEBRA_AGC[] = { - 0, - 0x7E, 0x7E, 0x7E, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78, 0x77, 0x76, - 0x75, 0x74, 0x73, 0x72, 0x71, 0x70, 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, - 0x69, 0x68, 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x48, 0x47, 0x46, 0x45, - 0x44, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x08, 0x07, - 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x17, 0x18, 0x18, - 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1e, 0x1e, - 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x22, 0x22, - 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, - 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F, 0x2F - }; - -static u32 ZEBRA_RF_RX_GAIN_TABLE[] = { - 0x0096, 0x0076, 0x0056, 0x0036, 0x0016, 0x01f6, 0x01d6, 0x01b6, - 0x0196, 0x0176, 0x00F7, 0x00D7, 0x00B7, 0x0097, 0x0077, 0x0057, - 0x0037, 0x00FB, 0x00DB, 0x00BB, 0x00FF, 0x00E3, 0x00C3, 0x00A3, - 0x0083, 0x0063, 0x0043, 0x0023, 0x0003, 0x01E3, 0x01C3, 0x01A3, - 0x0183, 0x0163, 0x0143, 0x0123, 0x0103 - }; - -static u8 OFDM_CONFIG[] = { - /* OFDM reg0x06[7:0]=0xFF: Enable power saving mode in RX */ - /* OFDM reg0x3C[4]=1'b1: Enable RX power saving mode */ - /* ofdm 0x3a = 0x7b ,(original : 0xfb) For ECS shielding room TP test */ - /* 0x00 */ - 0x10, 0x0F, 0x0A, 0x0C, 0x14, 0xFA, 0xFF, 0x50, - 0x00, 0x50, 0x00, 0x00, 0x00, 0x5C, 0x00, 0x00, - /* 0x10 */ - 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xA8, 0x26, - 0x32, 0x33, 0x06, 0xA5, 0x6F, 0x55, 0xC8, 0xBB, - /* 0x20 */ - 0x0A, 0xE1, 0x2C, 0x4A, 0x86, 0x83, 0x34, 0x00, - 0x4F, 0x24, 0x6F, 0xC2, 0x03, 0x40, 0x80, 0x00, - /* 0x30 */ - 0xC0, 0xC1, 0x58, 0xF1, 0x00, 0xC4, 0x90, 0x3e, - 0xD8, 0x3C, 0x7B, 0x10, 0x10 - }; - - /*--------------------------------------------------------------- - * Hardware IO - * the code is ported from Windows source code - *--------------------------------------------------------------- - */ - -static u8 PlatformIORead1Byte(struct net_device *dev, u32 offset) -{ - return read_nic_byte(dev, offset); -} - -static void PlatformIOWrite1Byte(struct net_device *dev, u32 offset, u8 data) -{ - write_nic_byte(dev, offset, data); - /* - * To make sure write operation is completed, - * 2005.11.09, by rcnjko. - */ - read_nic_byte(dev, offset); -} - -static void PlatformIOWrite2Byte(struct net_device *dev, u32 offset, u16 data) -{ - write_nic_word(dev, offset, data); - /* - * To make sure write operation is completed, - * 2005.11.09, by rcnjko. - */ - read_nic_word(dev, offset); -} - -static void PlatformIOWrite4Byte(struct net_device *dev, u32 offset, u32 data) -{ - if (offset == PhyAddr) { - /* For Base Band configuration. */ - unsigned char cmdByte; - unsigned long dataBytes; - unsigned char idx; - u8 u1bTmp; - - cmdByte = (u8)(data & 0x000000ff); - dataBytes = data>>8; - - /* - * 071010, rcnjko: - * The critical section is only BB read/write race - * condition. Assumption: - * 1. We assume NO one will access BB at DIRQL, otherwise, - * system will crash for - * acquiring the spinlock in such context. - * 2. PlatformIOWrite4Byte() MUST NOT be recursive. - */ - /* NdisAcquireSpinLock( &(pDevice->IoSpinLock) ); */ - - for (idx = 0; idx < 30; idx++) { - /* Make sure command bit is clear before access it. */ - u1bTmp = PlatformIORead1Byte(dev, PhyAddr); - if ((u1bTmp & BIT7) == 0) - break; - else - mdelay(10); - } - - for (idx = 0; idx < 3; idx++) - PlatformIOWrite1Byte(dev, offset+1+idx, - ((u8 *)&dataBytes)[idx]); - - write_nic_byte(dev, offset, cmdByte); - - /* NdisReleaseSpinLock( &(pDevice->IoSpinLock) ); */ - } else { - write_nic_dword(dev, offset, data); - /* - * To make sure write operation is completed, 2005.11.09, - * by rcnjko. - */ - read_nic_dword(dev, offset); - } -} - -static void SetOutputEnableOfRfPins(struct net_device *dev) -{ - write_nic_word(dev, RFPinsEnable, 0x1bff); -} - -static bool HwHSSIThreeWire(struct net_device *dev, - u8 *pDataBuf, - bool write) -{ - u8 TryCnt; - u8 u1bTmp; - - /* Check if WE and RE are cleared. */ - for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) { - u1bTmp = read_nic_byte(dev, SW_3W_CMD1); - if ((u1bTmp & (SW_3W_CMD1_RE|SW_3W_CMD1_WE)) == 0) - break; - - udelay(10); - } - if (TryCnt == TC_3W_POLL_MAX_TRY_CNT) { - netdev_err(dev, - "HwThreeWire(): CmdReg: %#X RE|WE bits are not clear!!\n", - u1bTmp); - return false; - } - - /* RTL8187S HSSI Read/Write Function */ - u1bTmp = read_nic_byte(dev, RF_SW_CONFIG); - u1bTmp |= RF_SW_CFG_SI; /* reg08[1]=1 Serial Interface(SI) */ - write_nic_byte(dev, RF_SW_CONFIG, u1bTmp); - - /* jong: HW SI read must set reg84[3]=0. */ - u1bTmp = read_nic_byte(dev, RFPinsSelect); - u1bTmp &= ~BIT3; - write_nic_byte(dev, RFPinsSelect, u1bTmp); - /* Fill up data buffer for write operation. */ - - /* SI - reg274[3:0] : RF register's Address */ - if (write) - write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf)); - else - write_nic_word(dev, SW_3W_DB0, *((u16 *)pDataBuf)); - - /* Set up command: WE or RE. */ - if (write) - write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_WE); - else - write_nic_byte(dev, SW_3W_CMD1, SW_3W_CMD1_RE); - - - /* Check if DONE is set. */ - for (TryCnt = 0; TryCnt < TC_3W_POLL_MAX_TRY_CNT; TryCnt++) { - u1bTmp = read_nic_byte(dev, SW_3W_CMD1); - if (u1bTmp & SW_3W_CMD1_DONE) - break; - - udelay(10); - } - - write_nic_byte(dev, SW_3W_CMD1, 0); - - /* Read back data for read operation. */ - if (!write) { - /* Serial Interface : reg363_362[11:0] */ - *((u16 *)pDataBuf) = read_nic_word(dev, SI_DATA_READ); - *((u16 *)pDataBuf) &= 0x0FFF; - } - - return true; -} - -void RF_WriteReg(struct net_device *dev, u8 offset, u16 data) -{ - u16 reg = (data << 4) | (offset & 0x0f); - HwHSSIThreeWire(dev, (u8 *)®, true); -} - -u16 RF_ReadReg(struct net_device *dev, u8 offset) -{ - u16 reg = offset & 0x0f; - HwHSSIThreeWire(dev, (u8 *)®, false); - return reg; -} - -static u8 ReadBBPortUchar(struct net_device *dev, u32 addr) -{ - PlatformIOWrite4Byte(dev, PhyAddr, addr & 0xffffff7f); - return PlatformIORead1Byte(dev, PhyDataR); -} - -/* by Owen on 04/07/14 for writing BB register successfully */ -static void WriteBBPortUchar(struct net_device *dev, u32 Data) -{ - PlatformIOWrite4Byte(dev, PhyAddr, Data); - ReadBBPortUchar(dev, Data); -} - -/* - * Description: - * Perform Antenna settings with antenna diversity on 87SE. - * Created by Roger, 2008.01.25. - */ -bool SetAntennaConfig87SE(struct net_device *dev, - u8 DefaultAnt, /* 0: Main, 1: Aux. */ - bool bAntDiversity) /* 1:Enable, 0: Disable. */ -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bAntennaSwitched = true; - /* 0x00 = disabled, 0x80 = enabled */ - u8 ant_diversity_offset = 0x00; - - /* - * printk("SetAntennaConfig87SE(): DefaultAnt(%d), bAntDiversity(%d)\n", - * DefaultAnt, bAntDiversity); - */ - - /* Threshold for antenna diversity. */ - write_phy_cck(dev, 0x0c, 0x09); /* Reg0c : 09 */ - - if (bAntDiversity) /* Enable Antenna Diversity. */ - ant_diversity_offset = 0x80; - - if (DefaultAnt == 1) { /* aux Antenna */ - /* Mac register, aux antenna */ - write_nic_byte(dev, ANTSEL, 0x00); - - /* Config CCK RX antenna. */ - write_phy_cck(dev, 0x11, 0xbb); /* Reg11 : bb */ - - /* Reg01 : 47 | ant_diversity_offset */ - write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset); - - /* Config OFDM RX antenna. */ - write_phy_ofdm(dev, 0x0D, 0x54); /* Reg0d : 54 */ - /* Reg18 : 32 */ - write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset); - } else { /* main Antenna */ - /* Mac register, main antenna */ - write_nic_byte(dev, ANTSEL, 0x03); - - /* Config CCK RX antenna. */ - write_phy_cck(dev, 0x11, 0x9b); /* Reg11 : 9b */ - /* Reg01 : 47 */ - write_phy_cck(dev, 0x01, 0x47|ant_diversity_offset); - - /* Config OFDM RX antenna. */ - write_phy_ofdm(dev, 0x0D, 0x5c); /* Reg0d : 5c */ - /*Reg18 : 32 */ - write_phy_ofdm(dev, 0x18, 0x32|ant_diversity_offset); - } - priv->CurrAntennaIndex = DefaultAnt; /* Update default settings. */ - return bAntennaSwitched; -} -/* - *-------------------------------------------------------------- - * Hardware Initialization. - * the code is ported from Windows source code - *-------------------------------------------------------------- - */ - -static void ZEBRA_Config_85BASIC_HardCode(struct net_device *dev) -{ - - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u32 i; - u32 addr, data; - u32 u4bRegOffset, u4bRegValue; - u16 u4bRF23, u4bRF24; - u8 u1b24E; - int d_cut = 0; - - -/* - *=========================================================================== - * 87S_PCIE :: RADIOCFG.TXT - *=========================================================================== - */ - - - /* Page1 : reg16-reg30 */ - RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); /* switch to page1 */ - u4bRF23 = RF_ReadReg(dev, 0x08); mdelay(1); - u4bRF24 = RF_ReadReg(dev, 0x09); mdelay(1); - - if (u4bRF23 == 0x818 && u4bRF24 == 0x70C) { - d_cut = 1; - netdev_info(dev, "card type changed from C- to D-cut\n"); - } - - /* Page0 : reg0-reg15 */ - - RF_WriteReg(dev, 0x00, 0x009f); mdelay(1);/* 1 */ - RF_WriteReg(dev, 0x01, 0x06e0); mdelay(1); - RF_WriteReg(dev, 0x02, 0x004d); mdelay(1);/* 2 */ - RF_WriteReg(dev, 0x03, 0x07f1); mdelay(1);/* 3 */ - RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); - RF_WriteReg(dev, 0x05, 0x0c72); mdelay(1); - RF_WriteReg(dev, 0x06, 0x0ae6); mdelay(1); - RF_WriteReg(dev, 0x07, 0x00ca); mdelay(1); - RF_WriteReg(dev, 0x08, 0x0e1c); mdelay(1); - RF_WriteReg(dev, 0x09, 0x02f0); mdelay(1); - RF_WriteReg(dev, 0x0a, 0x09d0); mdelay(1); - RF_WriteReg(dev, 0x0b, 0x01ba); mdelay(1); - RF_WriteReg(dev, 0x0c, 0x0640); mdelay(1); - RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); - RF_WriteReg(dev, 0x0e, 0x0020); mdelay(1); - RF_WriteReg(dev, 0x0f, 0x0990); mdelay(1); - - /* Page1 : reg16-reg30 */ - RF_WriteReg(dev, 0x00, 0x013f); mdelay(1); - RF_WriteReg(dev, 0x03, 0x0806); mdelay(1); - RF_WriteReg(dev, 0x04, 0x03a7); mdelay(1); - RF_WriteReg(dev, 0x05, 0x059b); mdelay(1); - RF_WriteReg(dev, 0x06, 0x0081); mdelay(1); - RF_WriteReg(dev, 0x07, 0x01A0); mdelay(1); -/* - * Don't write RF23/RF24 to make a difference between 87S C cut and D cut. - * asked by SD3 stevenl. - */ - RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1); - RF_WriteReg(dev, 0x0b, 0x0418); mdelay(1); - - if (d_cut) { - RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1); - RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); - /* RX LO buffer */ - RF_WriteReg(dev, 0x0e, 0x0807); mdelay(1); - } else { - RF_WriteReg(dev, 0x0c, 0x0fbe); mdelay(1); - RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); - /* RX LO buffer */ - RF_WriteReg(dev, 0x0e, 0x0806); mdelay(1); - } - - RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1); - RF_WriteReg(dev, 0x00, 0x01d7); mdelay(1); /* 6 */ - RF_WriteReg(dev, 0x03, 0x0e00); mdelay(1); - RF_WriteReg(dev, 0x04, 0x0e50); mdelay(1); - - for (i = 0; i <= 36; i++) { - RF_WriteReg(dev, 0x01, i); mdelay(1); - RF_WriteReg(dev, 0x02, ZEBRA_RF_RX_GAIN_TABLE[i]); mdelay(1); - } - - RF_WriteReg(dev, 0x05, 0x0203); mdelay(1); /* 203, 343 */ - RF_WriteReg(dev, 0x06, 0x0200); mdelay(1); /* 400 */ - /* switch to reg16-reg30, and HSSI disable 137 */ - RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* Z4 synthesizer loop filter setting, 392 */ - RF_WriteReg(dev, 0x0d, 0x0008); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* switch to reg0-reg15, and HSSI disable */ - RF_WriteReg(dev, 0x00, 0x0037); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* CBC on, Tx Rx disable, High gain */ - RF_WriteReg(dev, 0x04, 0x0160); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* Z4 setted channel 1 */ - RF_WriteReg(dev, 0x07, 0x0080); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - RF_WriteReg(dev, 0x02, 0x088D); mdelay(1); /* LC calibration */ - mdelay(200); /* Deay 200 ms. */ /* 0xfd */ - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - /* switch to reg16-reg30 137, and HSSI disable 137 */ - RF_WriteReg(dev, 0x00, 0x0137); mdelay(1); - mdelay(10); /* Deay 10 ms. */ /* 0xfd */ - - RF_WriteReg(dev, 0x07, 0x0000); mdelay(1); - RF_WriteReg(dev, 0x07, 0x0180); mdelay(1); - RF_WriteReg(dev, 0x07, 0x0220); mdelay(1); - RF_WriteReg(dev, 0x07, 0x03E0); mdelay(1); - - /* DAC calibration off 20070702 */ - RF_WriteReg(dev, 0x06, 0x00c1); mdelay(1); - RF_WriteReg(dev, 0x0a, 0x0001); mdelay(1); - /* For crystal calibration, added by Roger, 2007.12.11. */ - if (priv->bXtalCalibration) { /* reg 30. */ - /* - * enable crystal calibration. - * RF Reg[30], (1)Xin:[12:9], Xout:[8:5], addr[4:0]. - * (2)PA Pwr delay timer[15:14], default: 2.4us, - * set BIT15=0 - * (3)RF signal on/off when calibration[13], default: on, - * set BIT13=0. - * So we should minus 4 BITs offset. - */ - RF_WriteReg(dev, 0x0f, (priv->XtalCal_Xin<<5) | - (priv->XtalCal_Xout<<1) | BIT11 | BIT9); mdelay(1); - netdev_info(dev, "ZEBRA_Config_85BASIC_HardCode(): (%02x)\n", - (priv->XtalCal_Xin<<5) | (priv->XtalCal_Xout<<1) | - BIT11 | BIT9); - } else { - /* using default value. Xin=6, Xout=6. */ - RF_WriteReg(dev, 0x0f, 0x0acc); mdelay(1); - } - /* switch to reg0-reg15, and HSSI enable */ - RF_WriteReg(dev, 0x00, 0x00bf); mdelay(1); - /* Rx BB start calibration, 00c//+edward */ - RF_WriteReg(dev, 0x0d, 0x08df); mdelay(1); - /* temperature meter off */ - RF_WriteReg(dev, 0x02, 0x004d); mdelay(1); - RF_WriteReg(dev, 0x04, 0x0975); mdelay(1); /* Rx mode */ - mdelay(10); /* Deay 10 ms.*/ /* 0xfe */ - mdelay(10); /* Deay 10 ms.*/ /* 0xfe */ - mdelay(10); /* Deay 10 ms.*/ /* 0xfe */ - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x00, 0x0197); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x05, 0x05ab); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x00, 0x009f); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x01, 0x0000); mdelay(1); - /* Rx mode*/ /*+edward */ - RF_WriteReg(dev, 0x02, 0x0000); mdelay(1); - /* power save parameters. */ - u1b24E = read_nic_byte(dev, 0x24E); - write_nic_byte(dev, 0x24E, (u1b24E & (~(BIT5|BIT6)))); - - /*====================================================================== - * - *====================================================================== - * CCKCONF.TXT - *====================================================================== - * - * [POWER SAVE] Power Saving Parameters by jong. 2007-11-27 - * CCK reg0x00[7]=1'b1 :power saving for TX (default) - * CCK reg0x00[6]=1'b1: power saving for RX (default) - * CCK reg0x06[4]=1'b1: turn off channel estimation related - * circuits if not doing channel estimation. - * CCK reg0x06[3]=1'b1: turn off unused circuits before cca = 1 - * CCK reg0x06[2]=1'b1: turn off cck's circuit if macrst =0 - */ - - write_phy_cck(dev, 0x00, 0xc8); - write_phy_cck(dev, 0x06, 0x1c); - write_phy_cck(dev, 0x10, 0x78); - write_phy_cck(dev, 0x2e, 0xd0); - write_phy_cck(dev, 0x2f, 0x06); - write_phy_cck(dev, 0x01, 0x46); - - /* power control */ - write_nic_byte(dev, CCK_TXAGC, 0x10); - write_nic_byte(dev, OFDM_TXAGC, 0x1B); - write_nic_byte(dev, ANTSEL, 0x03); - - - - /* - *====================================================================== - * AGC.txt - *====================================================================== - */ - - write_phy_ofdm(dev, 0x00, 0x12); - - for (i = 0; i < 128; i++) { - - data = ZEBRA_AGC[i+1]; - data = data << 8; - data = data | 0x0000008F; - - addr = i + 0x80; /* enable writing AGC table */ - addr = addr << 8; - addr = addr | 0x0000008E; - - WriteBBPortUchar(dev, data); - WriteBBPortUchar(dev, addr); - WriteBBPortUchar(dev, 0x0000008E); - } - - PlatformIOWrite4Byte(dev, PhyAddr, 0x00001080); /* Annie, 2006-05-05 */ - - /* - *====================================================================== - * - *====================================================================== - * OFDMCONF.TXT - *====================================================================== - */ - - for (i = 0; i < 60; i++) { - u4bRegOffset = i; - u4bRegValue = OFDM_CONFIG[i]; - - WriteBBPortUchar(dev, - (0x00000080 | - (u4bRegOffset & 0x7f) | - ((u4bRegValue & 0xff) << 8))); - } - - /* - *====================================================================== - * by amy for antenna - *====================================================================== - */ - /* - * Config Sw/Hw Combinational Antenna Diversity. Added by Roger, - * 2008.02.26. - */ - SetAntennaConfig87SE(dev, priv->bDefaultAntenna1, - priv->bSwAntennaDiverity); -} - - -void UpdateInitialGain(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - /* lzm add 080826 */ - if (priv->eRFPowerState != RF_ON) { - /* Don't access BB/RF under disable PLL situation. - * RT_TRACE(COMP_DIG, DBG_LOUD, ("UpdateInitialGain - - * pHalData->eRFPowerState!=RF_ON\n")); - * Back to the original state - */ - priv->InitialGain = priv->InitialGainBackUp; - return; - } - - switch (priv->InitialGain) { - case 1: /* m861dBm */ - write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1); - break; - - case 2: /* m862dBm */ - write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1); - break; - - case 3: /* m863dBm */ - write_phy_ofdm(dev, 0x17, 0x36); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1); - break; - - case 4: /* m864dBm */ - write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1); - break; - - case 5: /* m82dBm */ - write_phy_ofdm(dev, 0x17, 0x46); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfb); mdelay(1); - break; - - case 6: /* m78dBm */ - write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x96); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1); - break; - - case 7: /* m74dBm */ - write_phy_ofdm(dev, 0x17, 0x56); mdelay(1); - write_phy_ofdm(dev, 0x24, 0xa6); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1); - break; - - case 8: - write_phy_ofdm(dev, 0x17, 0x66); mdelay(1); - write_phy_ofdm(dev, 0x24, 0xb6); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfc); mdelay(1); - break; - - default: /* MP */ - write_phy_ofdm(dev, 0x17, 0x26); mdelay(1); - write_phy_ofdm(dev, 0x24, 0x86); mdelay(1); - write_phy_ofdm(dev, 0x05, 0xfa); mdelay(1); - break; - } -} -/* - * Description: - * Tx Power tracking mechanism routine on 87SE. - * Created by Roger, 2007.12.11. - */ -static void InitTxPwrTracking87SE(struct net_device *dev) -{ - u32 u4bRfReg; - - u4bRfReg = RF_ReadReg(dev, 0x02); - - /* Enable Thermal meter indication. */ - RF_WriteReg(dev, 0x02, u4bRfReg|PWR_METER_EN); mdelay(1); -} - -static void PhyConfig8185(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - write_nic_dword(dev, RCR, priv->ReceiveConfig); - priv->RFProgType = read_nic_byte(dev, CONFIG4) & 0x03; - /* RF config */ - ZEBRA_Config_85BASIC_HardCode(dev); - /* Set default initial gain state to 4, approved by SD3 DZ, by Bruce, - * 2007-06-06. - */ - if (priv->bDigMechanism) { - if (priv->InitialGain == 0) - priv->InitialGain = 4; - } - - /* - * Enable thermal meter indication to implement TxPower tracking - * on 87SE. We initialize thermal meter here to avoid unsuccessful - * configuration. Added by Roger, 2007.12.11. - */ - if (priv->bTxPowerTrack) - InitTxPwrTracking87SE(dev); - - priv->InitialGainBackUp = priv->InitialGain; - UpdateInitialGain(dev); - - return; -} - -static void HwConfigureRTL8185(struct net_device *dev) -{ - /* - * RTL8185_TODO: Determine Retrylimit, TxAGC, - * AutoRateFallback control. - */ - u8 bUNIVERSAL_CONTROL_RL = 0; - u8 bUNIVERSAL_CONTROL_AGC = 1; - u8 bUNIVERSAL_CONTROL_ANT = 1; - u8 bAUTO_RATE_FALLBACK_CTL = 1; - u8 val8; - write_nic_word(dev, BRSR, 0x0fff); - /* Retry limit */ - val8 = read_nic_byte(dev, CW_CONF); - - if (bUNIVERSAL_CONTROL_RL) - val8 = val8 & 0xfd; - else - val8 = val8 | 0x02; - - write_nic_byte(dev, CW_CONF, val8); - - /* Tx AGC */ - val8 = read_nic_byte(dev, TXAGC_CTL); - if (bUNIVERSAL_CONTROL_AGC) { - write_nic_byte(dev, CCK_TXAGC, 128); - write_nic_byte(dev, OFDM_TXAGC, 128); - val8 = val8 & 0xfe; - } else { - val8 = val8 | 0x01; - } - - - write_nic_byte(dev, TXAGC_CTL, val8); - - /* Tx Antenna including Feedback control */ - val8 = read_nic_byte(dev, TXAGC_CTL); - - if (bUNIVERSAL_CONTROL_ANT) { - write_nic_byte(dev, ANTSEL, 0x00); - val8 = val8 & 0xfd; - } else { - val8 = val8 & (val8|0x02); /* xiong-2006-11-15 */ - } - - write_nic_byte(dev, TXAGC_CTL, val8); - - /* Auto Rate fallback control */ - val8 = read_nic_byte(dev, RATE_FALLBACK); - val8 &= 0x7c; - if (bAUTO_RATE_FALLBACK_CTL) { - val8 |= RATE_FALLBACK_CTL_ENABLE | RATE_FALLBACK_CTL_AUTO_STEP1; - - /* We shall set up the ARFR according - * to user's setting. - */ - PlatformIOWrite2Byte(dev, ARFR, 0x0fff); /* set 1M ~ 54Mbps. */ - } - write_nic_byte(dev, RATE_FALLBACK, val8); -} - -static void MacConfig_85BASIC_HardCode(struct net_device *dev) -{ - /* - *====================================================================== - * MACREG.TXT - *====================================================================== - */ - int nLinesRead = 0; - u32 u4bRegOffset, u4bRegValue, u4bPageIndex = 0; - int i; - - nLinesRead = sizeof(MAC_REG_TABLE)/2; - - for (i = 0; i < nLinesRead; i++) { /* nLinesRead=101 */ - u4bRegOffset = MAC_REG_TABLE[i][0]; - u4bRegValue = MAC_REG_TABLE[i][1]; - - if (u4bRegOffset == 0x5e) - u4bPageIndex = u4bRegValue; - else - u4bRegOffset |= (u4bPageIndex << 8); - - write_nic_byte(dev, u4bRegOffset, (u8)u4bRegValue); - } - /* ================================================================= */ -} - -static void MacConfig_85BASIC(struct net_device *dev) -{ - - u8 u1DA; - MacConfig_85BASIC_HardCode(dev); - - /* ================================================================= */ - - /* Follow TID_AC_MAP of WMac. */ - write_nic_word(dev, TID_AC_MAP, 0xfa50); - - /* Interrupt Migration, Jong suggested we use set 0x0000 first, - * 2005.12.14, by rcnjko. - */ - write_nic_word(dev, IntMig, 0x0000); - - /* Prevent TPC to cause CRC error. Added by Annie, 2006-06-10. */ - PlatformIOWrite4Byte(dev, 0x1F0, 0x00000000); - PlatformIOWrite4Byte(dev, 0x1F4, 0x00000000); - PlatformIOWrite1Byte(dev, 0x1F8, 0x00); - - /* Asked for by SD3 CM Lin, 2006.06.27, by rcnjko. */ - - /* - * power save parameter based on - * "87SE power save parameters 20071127.doc", as follow. - */ - - /* Enable DA10 TX power saving */ - u1DA = read_nic_byte(dev, PHYPR); - write_nic_byte(dev, PHYPR, (u1DA | BIT2)); - - /* POWER: */ - write_nic_word(dev, 0x360, 0x1000); - write_nic_word(dev, 0x362, 0x1000); - - /* AFE. */ - write_nic_word(dev, 0x370, 0x0560); - write_nic_word(dev, 0x372, 0x0560); - write_nic_word(dev, 0x374, 0x0DA4); - write_nic_word(dev, 0x376, 0x0DA4); - write_nic_word(dev, 0x378, 0x0560); - write_nic_word(dev, 0x37A, 0x0560); - write_nic_word(dev, 0x37C, 0x00EC); - write_nic_word(dev, 0x37E, 0x00EC); /* +edward */ - write_nic_byte(dev, 0x24E, 0x01); -} - -static u8 GetSupportedWirelessMode8185(struct net_device *dev) -{ - return WIRELESS_MODE_B | WIRELESS_MODE_G; -} - -static void -ActUpdateChannelAccessSetting(struct net_device *dev, - enum wireless_mode mode, - struct chnl_access_setting *chnl_access_setting) -{ - AC_CODING eACI; - - /* - * - * TODO: We still don't know how to set up these registers, - * just follow WMAC to verify 8185B FPAG. - * - * - * Jong said CWmin/CWmax register are not functional in 8185B, - * so we shall fill channel access realted register into AC - * parameter registers, - * even in nQBss. - */ - - /* Suggested by Jong, 2005.12.08. */ - chnl_access_setting->sifs_timer = 0x22; - chnl_access_setting->difs_timer = 0x1C; /* 2006.06.02, by rcnjko. */ - chnl_access_setting->slot_time_timer = 9; /* 2006.06.02, by rcnjko. */ - /* - * Suggested by wcchu, it is the default value of EIFS register, - * 2005.12.08. - */ - chnl_access_setting->eifs_timer = 0x5B; - chnl_access_setting->cwmin_index = 3; /* 2006.06.02, by rcnjko. */ - chnl_access_setting->cwmax_index = 7; /* 2006.06.02, by rcnjko. */ - - write_nic_byte(dev, SIFS, chnl_access_setting->sifs_timer); - /* - * Rewrited from directly use PlatformEFIOWrite1Byte(), - * by Annie, 2006-03-29. - */ - write_nic_byte(dev, SLOT, chnl_access_setting->slot_time_timer); - - write_nic_byte(dev, EIFS, chnl_access_setting->eifs_timer); - - /* - * Suggested by wcchu, it is the default value of EIFS - * register, 2005.12.08. - */ - write_nic_byte(dev, AckTimeOutReg, 0x5B); - - for (eACI = 0; eACI < AC_MAX; eACI++) - write_nic_byte(dev, ACM_CONTROL, 0); -} - -static void ActSetWirelessMode8185(struct net_device *dev, u8 btWirelessMode) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - u8 btSupportedWirelessMode = GetSupportedWirelessMode8185(dev); - - if ((btWirelessMode & btSupportedWirelessMode) == 0) { - /* - * Don't switch to unsupported wireless mode, 2006.02.15, - * by rcnjko. - */ - DMESGW("ActSetWirelessMode8185(): WirelessMode(%d) is not supported (%d)!\n", - btWirelessMode, btSupportedWirelessMode); - return; - } - - /* 1. Assign wireless mode to switch if necessary. */ - if (btWirelessMode == WIRELESS_MODE_AUTO) { - if ((btSupportedWirelessMode & WIRELESS_MODE_A)) { - btWirelessMode = WIRELESS_MODE_A; - } else if (btSupportedWirelessMode & WIRELESS_MODE_G) { - btWirelessMode = WIRELESS_MODE_G; - - } else if ((btSupportedWirelessMode & WIRELESS_MODE_B)) { - btWirelessMode = WIRELESS_MODE_B; - } else { - DMESGW("ActSetWirelessMode8185(): No valid wireless mode supported, btSupportedWirelessMode(%x)!!!\n", - btSupportedWirelessMode); - btWirelessMode = WIRELESS_MODE_B; - } - } - - /* - * 2. Swtich band: RF or BB specific actions, - * for example, refresh tables in omc8255, or change initial gain if - * necessary. Nothing to do for Zebra to switch band. Update current - * wireless mode if we switch to specified band successfully. - */ - - ieee->mode = (enum wireless_mode)btWirelessMode; - - /* 3. Change related setting. */ - if (ieee->mode == WIRELESS_MODE_A) - DMESG("WIRELESS_MODE_A\n"); - else if (ieee->mode == WIRELESS_MODE_B) - DMESG("WIRELESS_MODE_B\n"); - else if (ieee->mode == WIRELESS_MODE_G) - DMESG("WIRELESS_MODE_G\n"); - - ActUpdateChannelAccessSetting(dev, ieee->mode, - &priv->ChannelAccessSetting); -} - -void rtl8185b_irq_enable(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - priv->irq_enabled = 1; - write_nic_dword(dev, IMR, priv->IntrMask); -} - -static void MgntDisconnectIBSS(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u8 i; - - for (i = 0; i < 6; i++) - priv->ieee80211->current_network.bssid[i] = 0x55; - - - - priv->ieee80211->state = IEEE80211_NOLINK; - /* - * Stop Beacon. - * - * Vista add a Adhoc profile, HW radio off until - * OID_DOT11_RESET_REQUEST Driver would set MSR=NO_LINK, - * then HW Radio ON, MgntQueue Stuck. Because Bcn DMA isn't - * complete, mgnt queue would stuck until Bcn packet send. - * - * Disable Beacon Queue Own bit, suggested by jong - */ - ieee80211_stop_send_beacons(priv->ieee80211); - - priv->ieee80211->link_change(dev); - notify_wx_assoc_event(priv->ieee80211); -} - -static void MlmeDisassociateRequest(struct net_device *dev, u8 *asSta, u8 asRsn) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - u8 i; - - SendDisassociation(priv->ieee80211, asSta, asRsn); - - if (memcmp(priv->ieee80211->current_network.bssid, asSta, 6) == 0) { - /* ShuChen TODO: change media status. */ - - for (i = 0; i < 6; i++) - priv->ieee80211->current_network.bssid[i] = 0x22; - - ieee80211_disassociate(priv->ieee80211); - } -} - -static void MgntDisconnectAP(struct net_device *dev, u8 asRsn) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - /* - * Commented out by rcnjko, 2005.01.27: - * I move SecClearAllKeys() to MgntActSet_802_11_DISASSOCIATE(). - * - * 2004/09/15, kcwu, the key should be cleared, or the new - * handshaking will not success - * - * In WPA WPA2 need to Clear all key ... because new key will set - * after new handshaking. 2004.10.11, by rcnjko. - */ - MlmeDisassociateRequest(dev, priv->ieee80211->current_network.bssid, - asRsn); - - priv->ieee80211->state = IEEE80211_NOLINK; -} - -static bool MgntDisconnect(struct net_device *dev, u8 asRsn) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - /* - * Schedule an workitem to wake up for ps mode, 070109, by rcnjko. - */ - - if (IS_DOT11D_ENABLE(priv->ieee80211)) - Dot11d_Reset(priv->ieee80211); - /* In adhoc mode, update beacon frame. */ - if (priv->ieee80211->state == IEEE80211_LINKED) { - if (priv->ieee80211->iw_mode == IW_MODE_ADHOC) - MgntDisconnectIBSS(dev); - - if (priv->ieee80211->iw_mode == IW_MODE_INFRA) { - /* - * We clear key here instead of MgntDisconnectAP() - * because that MgntActSet_802_11_DISASSOCIATE() - * is an interface called by OS, e.g. - * OID_802_11_DISASSOCIATE in Windows while as - * MgntDisconnectAP() is used to handle - * disassociation related things to AP, e.g. send - * Disassoc frame to AP. 2005.01.27, by rcnjko. - */ - MgntDisconnectAP(dev, asRsn); - } - /* Indicate Disconnect, 2005.02.23, by rcnjko. */ - } - return true; -} -/* - * Description: - * Chang RF Power State. - * Note that, only MgntActSet_RF_State() is allowed to set - * HW_VAR_RF_STATE. - * - * Assumption: - * PASSIVE LEVEL. - */ -static bool SetRFPowerState(struct net_device *dev, - enum rt_rf_power_state eRFPowerState) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bResult = false; - - if (eRFPowerState == priv->eRFPowerState) - return bResult; - - bResult = SetZebraRFPowerState8185(dev, eRFPowerState); - - return bResult; -} - -bool MgntActSet_RF_State(struct net_device *dev, enum rt_rf_power_state StateToSet, - u32 ChangeSource) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - bool bActionAllowed = false; - bool bConnectBySSID = false; - enum rt_rf_power_state rtState; - u16 RFWaitCounter = 0; - unsigned long flag; - /* - * Prevent the race condition of RF state change. By Bruce, - * 2007-11-28. Only one thread can change the RF state at one time, - * and others should wait to be executed. - */ - while (true) { - spin_lock_irqsave(&priv->rf_ps_lock, flag); - if (priv->RFChangeInProgress) { - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - /* Set RF after the previous action is done. */ - while (priv->RFChangeInProgress) { - RFWaitCounter++; - udelay(1000); /* 1 ms */ - - /* - * Wait too long, return FALSE to avoid - * to be stuck here. - */ - if (RFWaitCounter > 1000) { /* 1sec */ - netdev_info(dev, "MgntActSet_RF_State(): Wait too long to set RF\n"); - /* TODO: Reset RF state? */ - return false; - } - } - } else { - priv->RFChangeInProgress = true; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - break; - } - } - rtState = priv->eRFPowerState; - - switch (StateToSet) { - case RF_ON: - /* - * Turn On RF no matter the IPS setting because we need to - * update the RF state to Ndis under Vista, or the Windows - * does not allow the driver to perform site survey any - * more. By Bruce, 2007-10-02. - */ - priv->RfOffReason &= (~ChangeSource); - - if (!priv->RfOffReason) { - priv->RfOffReason = 0; - bActionAllowed = true; - - if (rtState == RF_OFF && - ChangeSource >= RF_CHANGE_BY_HW) - bConnectBySSID = true; - } - break; - - case RF_OFF: - /* 070125, rcnjko: we always keep connected in AP mode. */ - - if (priv->RfOffReason > RF_CHANGE_BY_IPS) { - /* - * 060808, Annie: - * Disconnect to current BSS when radio off. - * Asked by QuanTa. - * - * Calling MgntDisconnect() instead of - * MgntActSet_802_11_DISASSOCIATE(), because - * we do NOT need to set ssid to dummy ones. - */ - MgntDisconnect(dev, disas_lv_ss); - /* - * Clear content of bssDesc[] and bssDesc4Query[] - * to avoid reporting old bss to UI. - */ - } - - priv->RfOffReason |= ChangeSource; - bActionAllowed = true; - break; - case RF_SLEEP: - priv->RfOffReason |= ChangeSource; - bActionAllowed = true; - break; - default: - break; - } - - if (bActionAllowed) { - /* Config HW to the specified mode. */ - SetRFPowerState(dev, StateToSet); - } - - /* Release RF spinlock */ - spin_lock_irqsave(&priv->rf_ps_lock, flag); - priv->RFChangeInProgress = false; - spin_unlock_irqrestore(&priv->rf_ps_lock, flag); - return bActionAllowed; -} - -static void InactivePowerSave(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - /* - * This flag "bSwRfProcessing", indicates the status of IPS - * procedure, should be set if the IPS workitem is really - * scheduled. The old code, sets this flag before scheduling the - * IPS workitem and however, at the same time the previous IPS - * workitem did not end yet, fails to schedule the current - * workitem. Thus, bSwRfProcessing blocks the IPS procedure of - * switching RF. - */ - priv->bSwRfProcessing = true; - - MgntActSet_RF_State(dev, priv->eInactivePowerState, RF_CHANGE_BY_IPS); - - /* - * To solve CAM values miss in RF OFF, rewrite CAM values after - * RF ON. By Bruce, 2007-09-20. - */ - - priv->bSwRfProcessing = false; -} - -/* - * Description: - * Enter the inactive power save mode. RF will be off - */ -void IPSEnter(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - enum rt_rf_power_state rtState; - if (priv->bInactivePs) { - rtState = priv->eRFPowerState; - - /* - * Do not enter IPS in the following conditions: - * (1) RF is already OFF or - * Sleep (2) bSwRfProcessing (indicates the IPS is still - * under going) (3) Connected (only disconnected can - * trigger IPS)(4) IBSS (send Beacon) - * (5) AP mode (send Beacon) - */ - if (rtState == RF_ON && !priv->bSwRfProcessing - && (priv->ieee80211->state != IEEE80211_LINKED)) { - priv->eInactivePowerState = RF_OFF; - InactivePowerSave(dev); - } - } -} -void IPSLeave(struct net_device *dev) -{ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - enum rt_rf_power_state rtState; - if (priv->bInactivePs) { - rtState = priv->eRFPowerState; - if ((rtState == RF_OFF || rtState == RF_SLEEP) && - !priv->bSwRfProcessing - && priv->RfOffReason <= RF_CHANGE_BY_IPS) { - priv->eInactivePowerState = RF_ON; - InactivePowerSave(dev); - } - } -} - -void rtl8185b_adapter_start(struct net_device *dev) -{ - struct r8180_priv *priv = ieee80211_priv(dev); - struct ieee80211_device *ieee = priv->ieee80211; - - u8 SupportedWirelessMode; - u8 InitWirelessMode; - u8 bInvalidWirelessMode = 0; - u8 tmpu8; - u8 btCR9346; - u8 TmpU1b; - u8 btPSR; - - write_nic_byte(dev, 0x24e, (BIT5|BIT6|BIT0)); - rtl8180_reset(dev); - - priv->dma_poll_mask = 0; - priv->dma_poll_stop_mask = 0; - - HwConfigureRTL8185(dev); - write_nic_dword(dev, MAC0, ((u32 *)dev->dev_addr)[0]); - write_nic_word(dev, MAC4, ((u32 *)dev->dev_addr)[1] & 0xffff); - /* default network type to 'No Link' */ - write_nic_byte(dev, MSR, read_nic_byte(dev, MSR) & 0xf3); - write_nic_word(dev, BcnItv, 100); - write_nic_word(dev, AtimWnd, 2); - PlatformIOWrite2Byte(dev, FEMR, 0xFFFF); - write_nic_byte(dev, WPA_CONFIG, 0); - MacConfig_85BASIC(dev); - /* Override the RFSW_CTRL (MAC offset 0x272-0x273), 2006.06.07, - * by rcnjko. - */ - /* BT_DEMO_BOARD type */ - PlatformIOWrite2Byte(dev, RFSW_CTRL, 0x569a); - - /* - *--------------------------------------------------------------------- - * Set up PHY related. - *--------------------------------------------------------------------- - */ - /* Enable Config3.PARAM_En to revise AnaaParm. */ - write_nic_byte(dev, CR9346, 0xc0); /* enable config register write */ - tmpu8 = read_nic_byte(dev, CONFIG3); - write_nic_byte(dev, CONFIG3, (tmpu8 | CONFIG3_PARM_En)); - /* Turn on Analog power. */ - /* Asked for by William, otherwise, MAC 3-wire can't work, - * 2006.06.27, by rcnjko. - */ - write_nic_dword(dev, ANAPARAM2, ANAPARM2_ASIC_ON); - write_nic_dword(dev, ANAPARAM, ANAPARM_ASIC_ON); - write_nic_word(dev, ANAPARAM3, 0x0010); - - write_nic_byte(dev, CONFIG3, tmpu8); - write_nic_byte(dev, CR9346, 0x00); - /* enable EEM0 and EEM1 in 9346CR */ - btCR9346 = read_nic_byte(dev, CR9346); - write_nic_byte(dev, CR9346, (btCR9346 | 0xC0)); - - /* B cut use LED1 to control HW RF on/off */ - TmpU1b = read_nic_byte(dev, CONFIG5); - TmpU1b = TmpU1b & ~BIT3; - write_nic_byte(dev, CONFIG5, TmpU1b); - - /* disable EEM0 and EEM1 in 9346CR */ - btCR9346 &= ~(0xC0); - write_nic_byte(dev, CR9346, btCR9346); - - /* Enable Led (suggested by Jong) */ - /* B-cut RF Radio on/off 5e[3]=0 */ - btPSR = read_nic_byte(dev, PSR); - write_nic_byte(dev, PSR, (btPSR | BIT3)); - /* setup initial timing for RFE. */ - write_nic_word(dev, RFPinsOutput, 0x0480); - SetOutputEnableOfRfPins(dev); - write_nic_word(dev, RFPinsSelect, 0x2488); - - /* PHY config. */ - PhyConfig8185(dev); - - /* - * We assume RegWirelessMode has already been initialized before, - * however, we has to validate the wireless mode here and provide a - * reasonable initialized value if necessary. 2005.01.13, - * by rcnjko. - */ - SupportedWirelessMode = GetSupportedWirelessMode8185(dev); - if ((ieee->mode != WIRELESS_MODE_B) && - (ieee->mode != WIRELESS_MODE_G) && - (ieee->mode != WIRELESS_MODE_A) && - (ieee->mode != WIRELESS_MODE_AUTO)) { - /* It should be one of B, G, A, or AUTO. */ - bInvalidWirelessMode = 1; - } else { - /* One of B, G, A, or AUTO. */ - /* Check if the wireless mode is supported by RF. */ - if ((ieee->mode != WIRELESS_MODE_AUTO) && - (ieee->mode & SupportedWirelessMode) == 0) { - bInvalidWirelessMode = 1; - } - } - - if (bInvalidWirelessMode || ieee->mode == WIRELESS_MODE_AUTO) { - /* Auto or other invalid value. */ - /* Assigne a wireless mode to initialize. */ - if ((SupportedWirelessMode & WIRELESS_MODE_A)) { - InitWirelessMode = WIRELESS_MODE_A; - } else if ((SupportedWirelessMode & WIRELESS_MODE_G)) { - InitWirelessMode = WIRELESS_MODE_G; - } else if ((SupportedWirelessMode & WIRELESS_MODE_B)) { - InitWirelessMode = WIRELESS_MODE_B; - } else { - DMESGW("InitializeAdapter8185(): No valid wireless mode supported, SupportedWirelessMode(%x)!!!\n", - SupportedWirelessMode); - InitWirelessMode = WIRELESS_MODE_B; - } - - /* Initialize RegWirelessMode if it is not a valid one. */ - if (bInvalidWirelessMode) - ieee->mode = (enum wireless_mode)InitWirelessMode; - - } else { - /* One of B, G, A. */ - InitWirelessMode = ieee->mode; - } - priv->eRFPowerState = RF_OFF; - priv->RfOffReason = 0; - { - MgntActSet_RF_State(dev, RF_ON, 0); - } - /* - * If inactive power mode is enabled, disable rf while in - * disconnected state. - */ - if (priv->bInactivePs) - MgntActSet_RF_State(dev , RF_OFF, RF_CHANGE_BY_IPS); - - ActSetWirelessMode8185(dev, (u8)(InitWirelessMode)); - - /* ----------------------------------------------------------------- */ - - rtl8185b_irq_enable(dev); - - netif_start_queue(dev); -} - -void rtl8185b_rx_enable(struct net_device *dev) -{ - u8 cmd; - /* for now we accept data, management & ctl frame*/ - struct r8180_priv *priv = (struct r8180_priv *)ieee80211_priv(dev); - - - if (dev->flags & IFF_PROMISC) - DMESG("NIC in promisc mode"); - - if (priv->ieee80211->iw_mode == IW_MODE_MONITOR || dev->flags & - IFF_PROMISC) { - priv->ReceiveConfig = priv->ReceiveConfig & (~RCR_APM); - priv->ReceiveConfig = priv->ReceiveConfig | RCR_AAP; - } - - if (priv->ieee80211->iw_mode == IW_MODE_MONITOR) - priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACF | - RCR_APWRMGT | RCR_AICV; - - - if (priv->crcmon == 1 && priv->ieee80211->iw_mode == IW_MODE_MONITOR) - priv->ReceiveConfig = priv->ReceiveConfig | RCR_ACRC32; - - write_nic_dword(dev, RCR, priv->ReceiveConfig); - - fix_rx_fifo(dev); - - cmd = read_nic_byte(dev, CMD); - write_nic_byte(dev, CMD, cmd | (1<TransmitConfig); - byte = read_nic_byte(dev, MSR); - byte |= MSR_LINK_ENEDCA; - write_nic_byte(dev, MSR, byte); - - fix_tx_fifo(dev); - - cmd = read_nic_byte(dev, CMD); - write_nic_byte(dev, CMD, cmd | (1< Date: Tue, 15 Apr 2014 15:50:19 +0200 Subject: [PATCH 133/279] net: phy: add minimal support for QSGMII PHY This commit adds the necessary definitions for the PHY layer to recognize "qsgmii" as a valid PHY interface. A QSMII interface, as defined at http://en.wikipedia.org/wiki/Media_Independent_Interface#Quad_Serial_Gigabit_Media_Independent_Interface, is "is a method of combining four SGMII lines into a 5Gbit/s interface. QSGMII, like SGMII, uses LVDS signalling for the TX and RX data and a single LVDS clock signal. QSGMII uses significantly fewer signal lines than four SGMII busses." This type of MAC <-> PHY connection might require special handling on the MAC driver side, so it should be possible to express this type of MAC <-> PHY connection, for example in the Device Tree. Signed-off-by: Thomas Petazzoni Cc: devicetree@vger.kernel.org Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/ethernet.txt | 2 +- include/linux/phy.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/ethernet.txt b/Documentation/devicetree/bindings/net/ethernet.txt index 9ecd43d8792c17..3fc360523bc97c 100644 --- a/Documentation/devicetree/bindings/net/ethernet.txt +++ b/Documentation/devicetree/bindings/net/ethernet.txt @@ -10,7 +10,7 @@ The following properties are common to the Ethernet controllers: - max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than the maximum frame size (there's contradiction in ePAPR). - phy-mode: string, operation mode of the PHY interface; supported values are - "mii", "gmii", "sgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id", + "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii"; this is now a de-facto standard property; - phy-connection-type: the same as "phy-mode" property but described in ePAPR; diff --git a/include/linux/phy.h b/include/linux/phy.h index 24126c4b27b58e..4d0221fd0688df 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -75,6 +75,7 @@ typedef enum { PHY_INTERFACE_MODE_SMII, PHY_INTERFACE_MODE_XGMII, PHY_INTERFACE_MODE_MOCA, + PHY_INTERFACE_MODE_QSGMII, PHY_INTERFACE_MODE_MAX, } phy_interface_t; @@ -116,6 +117,8 @@ static inline const char *phy_modes(phy_interface_t interface) return "xgmii"; case PHY_INTERFACE_MODE_MOCA: return "moca"; + case PHY_INTERFACE_MODE_QSGMII: + return "qsgmii"; default: return "unknown"; } From 3f1dd4bcfe2c19a336e01e32a928fcdb8cc43e5c Mon Sep 17 00:00:00 2001 From: Thomas Petazzoni Date: Tue, 15 Apr 2014 15:50:20 +0200 Subject: [PATCH 134/279] net: mvneta: properly configure the MAC <-> PHY connection in all situations Commit 5445eaf309ff ('mvneta: Try to fix mvneta when compiled as module') fixed the mvneta driver to make it work properly when loaded as a module in SGMII configuration, which was tested successful by the author on the Armada XP OpenBlocks AX3, which uses SGMII. However, some other platforms, namely the Armada XP GP don't use SGMII, but a QSGMII connection between the MAC and the PHY, and this case was not supported by the mvneta driver, which was relying on configuration put in place by the bootloader. While this works when the mvneta driver is built-in (because clocks are not gated), it breaks when mvneta is built as a module, because the clock is gated (all configuration is lost) and then re-enabled when the mvneta driver is loaded. In order to support all of RGMII, SGMII and QSGMII, this commit reworks how the PHY interface configuration is done, and simplifies it: it removes the mvneta_port_sgmii_config() and mvneta_gmac_rgmii_set() functions, which were strange because mvneta_gmac_rgmii_set() was called in all cases, even for SGMII configurations. Also, the mvneta_gmac_rgmii_set() function was taking a boolean as argument, which was always true. Instead, all the PHY interface configuration logic is moved into the mvneta_port_power_up() function, in a much simpler 'switch' construct, with four cases: - QSGMII: the RGMIIEn bit, the PCSEn bit in GMAC_CTRL_2 are set, and the SERDES is configured in QSGMII. Technically speaking, configuring the SERDES of the first port would be sufficient, but it is simpler to do it on all ports. - SGMII: the RGMIIEn bit, the PCSEn bit in GMAC_CTRL_2 are set, and the SERDES is configured as SGMII. - RGMII: the RGMIIEn bit in GMAC_CTRL_2 is set. The PCSEn bit is kept cleared, and no SERDES configuration is done, because RGMII is not using SERDES lanes. - other: an error is returned. For this reason, the mvneta_port_power_up() now returns an int instead of nothing, and the return value is checked by mvneta_probe(). This has been successfully tested on: * Armada XP DB, which has two RGMII and two SGMII connections * Armada XP GP, which uses QSGMII for its four interfaces * Armada 370 Mirabox, which has two RGMII connections Signed-off-by: Thomas Petazzoni Signed-off-by: David S. Miller --- drivers/net/ethernet/marvell/mvneta.c | 73 +++++++++++++-------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index b248bcbdae63f4..14786c8bf99efc 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -89,8 +89,9 @@ #define MVNETA_TX_IN_PRGRS BIT(1) #define MVNETA_TX_FIFO_EMPTY BIT(8) #define MVNETA_RX_MIN_FRAME_SIZE 0x247c -#define MVNETA_SGMII_SERDES_CFG 0x24A0 +#define MVNETA_SERDES_CFG 0x24A0 #define MVNETA_SGMII_SERDES_PROTO 0x0cc7 +#define MVNETA_QSGMII_SERDES_PROTO 0x0667 #define MVNETA_TYPE_PRIO 0x24bc #define MVNETA_FORCE_UNI BIT(21) #define MVNETA_TXQ_CMD_1 0x24e4 @@ -711,35 +712,6 @@ static void mvneta_rxq_bm_disable(struct mvneta_port *pp, mvreg_write(pp, MVNETA_RXQ_CONFIG_REG(rxq->id), val); } - - -/* Sets the RGMII Enable bit (RGMIIEn) in port MAC control register */ -static void mvneta_gmac_rgmii_set(struct mvneta_port *pp, int enable) -{ - u32 val; - - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - - if (enable) - val |= MVNETA_GMAC2_PORT_RGMII; - else - val &= ~MVNETA_GMAC2_PORT_RGMII; - - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); -} - -/* Config SGMII port */ -static void mvneta_port_sgmii_config(struct mvneta_port *pp) -{ - u32 val; - - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - val |= MVNETA_GMAC2_PCS_ENABLE; - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); - - mvreg_write(pp, MVNETA_SGMII_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); -} - /* Start the Ethernet port RX and TX activity */ static void mvneta_port_up(struct mvneta_port *pp) { @@ -2749,26 +2721,44 @@ static void mvneta_conf_mbus_windows(struct mvneta_port *pp, } /* Power up the port */ -static void mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) +static int mvneta_port_power_up(struct mvneta_port *pp, int phy_mode) { - u32 val; + u32 ctrl; /* MAC Cause register should be cleared */ mvreg_write(pp, MVNETA_UNIT_INTR_CAUSE, 0); - if (phy_mode == PHY_INTERFACE_MODE_SGMII) - mvneta_port_sgmii_config(pp); + ctrl = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - mvneta_gmac_rgmii_set(pp, 1); + /* Even though it might look weird, when we're configured in + * SGMII or QSGMII mode, the RGMII bit needs to be set. + */ + switch(phy_mode) { + case PHY_INTERFACE_MODE_QSGMII: + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_QSGMII_SERDES_PROTO); + ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; + break; + case PHY_INTERFACE_MODE_SGMII: + mvreg_write(pp, MVNETA_SERDES_CFG, MVNETA_SGMII_SERDES_PROTO); + ctrl |= MVNETA_GMAC2_PCS_ENABLE | MVNETA_GMAC2_PORT_RGMII; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + ctrl |= MVNETA_GMAC2_PORT_RGMII; + break; + default: + return -EINVAL; + } /* Cancel Port Reset */ - val = mvreg_read(pp, MVNETA_GMAC_CTRL_2); - val &= ~MVNETA_GMAC2_PORT_RESET; - mvreg_write(pp, MVNETA_GMAC_CTRL_2, val); + ctrl &= ~MVNETA_GMAC2_PORT_RESET; + mvreg_write(pp, MVNETA_GMAC_CTRL_2, ctrl); while ((mvreg_read(pp, MVNETA_GMAC_CTRL_2) & MVNETA_GMAC2_PORT_RESET) != 0) continue; + + return 0; } /* Device initialization routine */ @@ -2879,7 +2869,12 @@ static int mvneta_probe(struct platform_device *pdev) dev_err(&pdev->dev, "can't init eth hal\n"); goto err_free_stats; } - mvneta_port_power_up(pp, phy_mode); + + err = mvneta_port_power_up(pp, phy_mode); + if (err < 0) { + dev_err(&pdev->dev, "can't power up port\n"); + goto err_deinit; + } dram_target_info = mv_mbus_dram_info(); if (dram_target_info) From ff8ebe6448e98df59a8c7e7e93876f8f3d6a8b19 Mon Sep 17 00:00:00 2001 From: Tuomas Tynkkynen Date: Tue, 8 Apr 2014 09:15:22 +0300 Subject: [PATCH 135/279] staging: goldfish: Call free_irq in error path If misc_register failed in goldfish_audio_probe, the already requested IRQ wouldn't get freed. Add a call to free_irq() like there is in goldfish_audio_remove(). Signed-off-by: Tuomas Tynkkynen Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/goldfish/goldfish_audio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/goldfish/goldfish_audio.c b/drivers/staging/goldfish/goldfish_audio.c index f96dcec740aedf..7ac2602242f1f4 100644 --- a/drivers/staging/goldfish/goldfish_audio.c +++ b/drivers/staging/goldfish/goldfish_audio.c @@ -334,6 +334,7 @@ static int goldfish_audio_probe(struct platform_device *pdev) return 0; err_misc_register_failed: + free_irq(data->irq, data); err_request_irq_failed: dma_free_coherent(&pdev->dev, COMBINED_BUFFER_SIZE, data->buffer_virt, data->buffer_phys); From ef35a4f44bdc6f8c9f99a561fd1fd318305a4d98 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Wed, 9 Apr 2014 19:45:46 +0900 Subject: [PATCH 136/279] staging: speakup: fix misuse of kstrtol() in handle_goto() A string of goto_buf has a number followed by x or y. e.g. "3x" means move 3 lines down. The kstrtol() returns an error(-EINVAL) with this string so go_pos has unsigned a value of that error. And also "*cp" has not expected value. And fix sparse warnings: drivers/staging/speakup/main.c:1901 handle_goto() warn: unsigned '(speakup_console[vc->vc_num]->go_pos)' is never less than zero. drivers/staging/speakup/main.c:1911 handle_goto() warn: unsigned '(speakup_console[vc->vc_num]->go_pos)' is never less than zero. Signed-off-by: Daeseok Youn Reviewed-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/speakup/main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index ef5933b9359063..3b6e5358c723e0 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -1855,8 +1855,9 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) { static u_char goto_buf[8]; static int num; - int maxlen, go_pos; + int maxlen; char *cp; + if (type == KT_SPKUP && ch == SPEAKUP_GOTO) goto do_goto; if (type == KT_LATIN && ch == '\n') @@ -1891,25 +1892,24 @@ static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) spk_special_handler = NULL; return 1; } - go_pos = kstrtol(goto_buf, 10, (long *)&cp); - goto_pos = (u_long) go_pos; + + goto_pos = simple_strtoul(goto_buf, &cp, 10); + if (*cp == 'x') { if (*goto_buf < '0') goto_pos += spk_x; - else + else if (goto_pos > 0) goto_pos--; - if (goto_pos < 0) - goto_pos = 0; + if (goto_pos >= vc->vc_cols) goto_pos = vc->vc_cols - 1; goto_x = 1; } else { if (*goto_buf < '0') goto_pos += spk_y; - else + else if (goto_pos > 0) goto_pos--; - if (goto_pos < 0) - goto_pos = 0; + if (goto_pos >= vc->vc_rows) goto_pos = vc->vc_rows - 1; goto_x = 0; From d21bb45081484b95fb0c80f1afa492a7275689c2 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 10 Apr 2014 12:36:13 +0300 Subject: [PATCH 137/279] staging: unisys: use after free in error messages We dereference "bus" when we report the error so we have to move the kfree() down a couple lines. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/uislib/uislib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/unisys/uislib/uislib.c b/drivers/staging/unisys/uislib/uislib.c index 8ea9c46e56aef5..3152a2180c456c 100644 --- a/drivers/staging/unisys/uislib/uislib.c +++ b/drivers/staging/unisys/uislib/uislib.c @@ -381,17 +381,17 @@ create_bus(CONTROLVM_MESSAGE *msg, char *buf) cmd.add_vbus.busTypeGuid = msg->cmd.createBus.busDataTypeGuid; cmd.add_vbus.busInstGuid = msg->cmd.createBus.busInstGuid; if (!VirtControlChanFunc) { - kfree(bus); LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci callback not registered."); POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo, POSTCODE_SEVERITY_ERR); + kfree(bus); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_FAILURE; } if (!VirtControlChanFunc(&cmd)) { - kfree(bus); LOGERR("CONTROLVM_BUS_CREATE Failed: virtpci GUEST_ADD_VBUS returned error."); POSTCODE_LINUX_3(BUS_CREATE_FAILURE_PC, bus->busNo, POSTCODE_SEVERITY_ERR); + kfree(bus); return CONTROLVM_RESP_ERROR_VIRTPCI_DRIVER_CALLBACK_ERROR; } From e6b1ea773e0a6dd611278d0d6f81ea6ff9d6938b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 10 Apr 2014 12:45:45 +0300 Subject: [PATCH 138/279] Staging: unisys: use after free in list_for_each() These should be using the _safe version of list_for_each() because we free the current element and it leads to a use after free bug. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman --- drivers/staging/unisys/visorchipset/visorchipset.h | 4 ++-- drivers/staging/unisys/visorchipset/visorchipset_main.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/unisys/visorchipset/visorchipset.h b/drivers/staging/unisys/visorchipset/visorchipset.h index d4bf203cdfdf53..d95825dc541494 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset.h +++ b/drivers/staging/unisys/visorchipset/visorchipset.h @@ -104,9 +104,9 @@ finddevice(struct list_head *list, U32 busNo, U32 devNo) static inline void delbusdevices(struct list_head *list, U32 busNo) { - VISORCHIPSET_DEVICE_INFO *p; + VISORCHIPSET_DEVICE_INFO *p, *tmp; - list_for_each_entry(p, list, entry) { + list_for_each_entry_safe(p, tmp, list, entry) { if (p->busNo == busNo) { list_del(&p->entry); kfree(p); diff --git a/drivers/staging/unisys/visorchipset/visorchipset_main.c b/drivers/staging/unisys/visorchipset/visorchipset_main.c index 257c6e59b4603b..c475e256e34b63 100644 --- a/drivers/staging/unisys/visorchipset/visorchipset_main.c +++ b/drivers/staging/unisys/visorchipset/visorchipset_main.c @@ -605,16 +605,16 @@ EXPORT_SYMBOL_GPL(visorchipset_register_busdev_client); static void cleanup_controlvm_structures(void) { - VISORCHIPSET_BUS_INFO *bi; - VISORCHIPSET_DEVICE_INFO *di; + VISORCHIPSET_BUS_INFO *bi, *tmp_bi; + VISORCHIPSET_DEVICE_INFO *di, *tmp_di; - list_for_each_entry(bi, &BusInfoList, entry) { + list_for_each_entry_safe(bi, tmp_bi, &BusInfoList, entry) { busInfo_clear(bi); list_del(&bi->entry); kfree(bi); } - list_for_each_entry(di, &DevInfoList, entry) { + list_for_each_entry_safe(di, tmp_di, &DevInfoList, entry) { devInfo_clear(di); list_del(&di->entry); kfree(di); From 2c33d7cc3875e75311d24a3bfe8d40ca201da2da Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 10 Apr 2014 19:46:56 +0200 Subject: [PATCH 139/279] staging: r8723au: Add missing initialization of change_inx in sort algorithm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/staging/rtl8723au/core/rtw_wlan_util.c: In function ‘WMMOnAssocRsp23a’: drivers/staging/rtl8723au/core/rtw_wlan_util.c:684: warning: ‘change_inx’ may be used uninitialized in this function Depending on the uninitialized data on the stack, the array may not be sorted correctly. Signed-off-by: Geert Uytterhoeven Acked-by: Larry Finger Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8723au/core/rtw_wlan_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8723au/core/rtw_wlan_util.c b/drivers/staging/rtl8723au/core/rtw_wlan_util.c index e743b053b8a290..99d81e612e7b69 100644 --- a/drivers/staging/rtl8723au/core/rtw_wlan_util.c +++ b/drivers/staging/rtl8723au/core/rtw_wlan_util.c @@ -681,7 +681,7 @@ void WMMOnAssocRsp23a(struct rtw_adapter *padapter) inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3; if (pregpriv->wifi_spec == 1) { - u32 j, tmp, change_inx; + u32 j, tmp, change_inx = false; /* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */ for (i = 0; i < 4; i++) { From b34aa86f12e8848ba453215602c8c50fa63c4cb3 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Thu, 10 Apr 2014 19:41:57 +0100 Subject: [PATCH 140/279] staging: comedi: fix circular locking dependency in comedi_mmap() Mmapping a comedi data buffer with lockdep checking enabled produced the following kernel debug messages: ====================================================== [ INFO: possible circular locking dependency detected ] 3.5.0-rc3-ija1+ #9 Tainted: G C ------------------------------------------------------- comedi_test/4160 is trying to acquire lock: (&dev->mutex#2){+.+.+.}, at: [] comedi_mmap+0x57/0x1d9 [comedi] but task is already holding lock: (&mm->mmap_sem){++++++}, at: [] vm_mmap_pgoff+0x41/0x76 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&mm->mmap_sem){++++++}: [] lock_acquire+0x97/0x105 [] might_fault+0x6d/0x90 [] do_devinfo_ioctl.isra.7+0x11e/0x14c [comedi] [] comedi_unlocked_ioctl+0x256/0xe48 [comedi] [] vfs_ioctl+0x18/0x34 [] do_vfs_ioctl+0x382/0x43c [] sys_ioctl+0x42/0x65 [] system_call_fastpath+0x16/0x1b -> #0 (&dev->mutex#2){+.+.+.}: [] __lock_acquire+0x101d/0x1591 [] lock_acquire+0x97/0x105 [] mutex_lock_nested+0x46/0x2a4 [] comedi_mmap+0x57/0x1d9 [comedi] [] mmap_region+0x281/0x492 [] do_mmap_pgoff+0x26b/0x2a7 [] vm_mmap_pgoff+0x5d/0x76 [] sys_mmap_pgoff+0xc7/0x10d [] sys_mmap+0x16/0x20 [] system_call_fastpath+0x16/0x1b other info that might help us debug this: Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock(&mm->mmap_sem); lock(&dev->mutex#2); lock(&mm->mmap_sem); lock(&dev->mutex#2); *** DEADLOCK *** To avoid the circular dependency, just try to get the lock in `comedi_mmap()` instead of blocking. Since the comedi device's main mutex is heavily used, do a down-read of its `attach_lock` rwsemaphore instead. Trying to down-read `attach_lock` should only fail if some task has down-write locked it, and that is only done while the comedi device is being attached to or detached from a low-level hardware device. Unfortunately, acquiring the `attach_lock` doesn't prevent another task replacing the comedi data buffer we are trying to mmap. The details of the buffer are held in a `struct comedi_buf_map` and pointed to by `s->async->buf_map` where `s` is the comedi subdevice whose buffer we are trying to map. The `struct comedi_buf_map` is already reference counted with a `struct kref`, so we can stop it being freed prematurely. Modify `comedi_mmap()` to call new function `comedi_buf_map_from_subdev_get()` to read the subdevice's current buffer map pointer and increment its reference instead of accessing `async->buf_map` directly. Call `comedi_buf_map_put()` to decrement the reference once the buffer map structure has been dealt with. (Note that `comedi_buf_map_put()` does nothing if passed a NULL pointer.) `comedi_buf_map_from_subdev_get()` checks the subdevice's buffer map pointer has been set and the buffer map has been initialized enough for `comedi_mmap()` to deal with it (specifically, check the `n_pages` member has been set to a non-zero value). If all is well, the buffer map's reference is incremented and a pointer to it is returned. The comedi subdevice's spin-lock is used to protect the checks. Also use the spin-lock in `__comedi_buf_alloc()` and `__comedi_buf_free()` to protect changes to the subdevice's buffer map structure pointer and the buffer map structure's `n_pages` member. (This checking of `n_pages` is a bit clunky and I [Ian Abbott] plan to deal with it in the future.) Signed-off-by: Ian Abbott Cc: # 3.14.x, 3.15.x Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi_buf.c | 37 ++++++++++++++++++++++-- drivers/staging/comedi/comedi_fops.c | 18 +++++++++--- drivers/staging/comedi/comedi_internal.h | 2 ++ 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/drivers/staging/comedi/comedi_buf.c b/drivers/staging/comedi/comedi_buf.c index 924fce977985b2..257595016161cc 100644 --- a/drivers/staging/comedi/comedi_buf.c +++ b/drivers/staging/comedi/comedi_buf.c @@ -61,6 +61,8 @@ static void __comedi_buf_free(struct comedi_device *dev, struct comedi_subdevice *s) { struct comedi_async *async = s->async; + struct comedi_buf_map *bm; + unsigned long flags; if (async->prealloc_buf) { vunmap(async->prealloc_buf); @@ -68,8 +70,11 @@ static void __comedi_buf_free(struct comedi_device *dev, async->prealloc_bufsz = 0; } - comedi_buf_map_put(async->buf_map); + spin_lock_irqsave(&s->spin_lock, flags); + bm = async->buf_map; async->buf_map = NULL; + spin_unlock_irqrestore(&s->spin_lock, flags); + comedi_buf_map_put(bm); } static void __comedi_buf_alloc(struct comedi_device *dev, @@ -80,6 +85,7 @@ static void __comedi_buf_alloc(struct comedi_device *dev, struct page **pages = NULL; struct comedi_buf_map *bm; struct comedi_buf_page *buf; + unsigned long flags; unsigned i; if (!IS_ENABLED(CONFIG_HAS_DMA) && s->async_dma_dir != DMA_NONE) { @@ -92,8 +98,10 @@ static void __comedi_buf_alloc(struct comedi_device *dev, if (!bm) return; - async->buf_map = bm; kref_init(&bm->refcount); + spin_lock_irqsave(&s->spin_lock, flags); + async->buf_map = bm; + spin_unlock_irqrestore(&s->spin_lock, flags); bm->dma_dir = s->async_dma_dir; if (bm->dma_dir != DMA_NONE) /* Need ref to hardware device to free buffer later. */ @@ -127,7 +135,9 @@ static void __comedi_buf_alloc(struct comedi_device *dev, pages[i] = virt_to_page(buf->virt_addr); } + spin_lock_irqsave(&s->spin_lock, flags); bm->n_pages = i; + spin_unlock_irqrestore(&s->spin_lock, flags); /* vmap the prealloc_buf if all the pages were allocated */ if (i == n_pages) @@ -150,6 +160,29 @@ int comedi_buf_map_put(struct comedi_buf_map *bm) return 1; } +/* returns s->async->buf_map and increments its kref refcount */ +struct comedi_buf_map * +comedi_buf_map_from_subdev_get(struct comedi_subdevice *s) +{ + struct comedi_async *async = s->async; + struct comedi_buf_map *bm = NULL; + unsigned long flags; + + if (!async) + return NULL; + + spin_lock_irqsave(&s->spin_lock, flags); + bm = async->buf_map; + /* only want it if buffer pages allocated */ + if (bm && bm->n_pages) + comedi_buf_map_get(bm); + else + bm = NULL; + spin_unlock_irqrestore(&s->spin_lock, flags); + + return bm; +} + bool comedi_buf_is_mmapped(struct comedi_async *async) { struct comedi_buf_map *bm = async->buf_map; diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index ea6dc36d753b0d..acc80197e35ed8 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -1926,14 +1926,21 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) struct comedi_device *dev = file->private_data; struct comedi_subdevice *s; struct comedi_async *async; - struct comedi_buf_map *bm; + struct comedi_buf_map *bm = NULL; unsigned long start = vma->vm_start; unsigned long size; int n_pages; int i; int retval; - mutex_lock(&dev->mutex); + /* + * 'trylock' avoids circular dependency with current->mm->mmap_sem + * and down-reading &dev->attach_lock should normally succeed without + * contention unless the device is in the process of being attached + * or detached. + */ + if (!down_read_trylock(&dev->attach_lock)) + return -EAGAIN; if (!dev->attached) { dev_dbg(dev->class_dev, "no driver attached\n"); @@ -1973,7 +1980,9 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) } n_pages = size >> PAGE_SHIFT; - bm = async->buf_map; + + /* get reference to current buf map (if any) */ + bm = comedi_buf_map_from_subdev_get(s); if (!bm || n_pages > bm->n_pages) { retval = -EINVAL; goto done; @@ -1997,7 +2006,8 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma) retval = 0; done: - mutex_unlock(&dev->mutex); + up_read(&dev->attach_lock); + comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */ return retval; } diff --git a/drivers/staging/comedi/comedi_internal.h b/drivers/staging/comedi/comedi_internal.h index 9a746570f1619a..a492f2d2436e7b 100644 --- a/drivers/staging/comedi/comedi_internal.h +++ b/drivers/staging/comedi/comedi_internal.h @@ -19,6 +19,8 @@ void comedi_buf_reset(struct comedi_async *async); bool comedi_buf_is_mmapped(struct comedi_async *async); void comedi_buf_map_get(struct comedi_buf_map *bm); int comedi_buf_map_put(struct comedi_buf_map *bm); +struct comedi_buf_map *comedi_buf_map_from_subdev_get( + struct comedi_subdevice *s); unsigned int comedi_buf_write_n_allocated(struct comedi_async *async); void comedi_device_cancel_all(struct comedi_device *dev); From 9452bf560273e4de2395ffdd79024debfb0c1290 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 9 Apr 2014 11:12:58 -0500 Subject: [PATCH 141/279] staging: r8188eu: Calling rtw_get_stainfo() with a NULL sta_addr will return NULL This makes the follow-on check for psta != NULL pointless and makes the whole exercise rather pointless. This is another case of why blindly zero-initializing variables when they are declared is bad. Reported-by: Jes Sorensen Signed-off-by: Larry Finger Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 636ec553ae8368..01fcabcc8e5648 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -545,7 +545,7 @@ static struct recv_frame *decryptor(struct adapter *padapter, static struct recv_frame *portctrl(struct adapter *adapter, struct recv_frame *precv_frame) { - u8 *psta_addr = NULL, *ptr; + u8 *psta_addr, *ptr; uint auth_alg; struct recv_frame *pfhdr; struct sta_info *psta; @@ -558,7 +558,6 @@ static struct recv_frame *portctrl(struct adapter *adapter, pstapriv = &adapter->stapriv; - psta = rtw_get_stainfo(pstapriv, psta_addr); auth_alg = adapter->securitypriv.dot11AuthAlgrthm; @@ -566,6 +565,7 @@ static struct recv_frame *portctrl(struct adapter *adapter, pfhdr = precv_frame; pattrib = &pfhdr->attrib; psta_addr = pattrib->ta; + psta = rtw_get_stainfo(pstapriv, psta_addr); prtnframe = NULL; From c11f1df5003d534fd067f0168bfad7befffb3b5c Mon Sep 17 00:00:00 2001 From: Sachin Prabhu Date: Tue, 11 Mar 2014 16:11:47 +0000 Subject: [PATCH 142/279] cifs: Wait for writebacks to complete before attempting write. Problem reported in Red Hat bz 1040329 for strict writes where we cache only when we hold oplock and write direct to the server when we don't. When we receive an oplock break, we first change the oplock value for the inode in cifsInodeInfo->oplock to indicate that we no longer hold the oplock before we enqueue a task to flush changes to the backing device. Once we have completed flushing the changes, we return the oplock to the server. There are 2 ways here where we can have data corruption 1) While we flush changes to the backing device as part of the oplock break, we can have processes write to the file. These writes check for the oplock, find none and attempt to write directly to the server. These direct writes made while we are flushing from cache could be overwritten by data being flushed from the cache causing data corruption. 2) While a thread runs in cifs_strict_writev, the machine could receive and process an oplock break after the thread has checked the oplock and found that it allows us to cache and before we have made changes to the cache. In that case, we end up with a dirty page in cache when we shouldn't have any. This will be flushed later and will overwrite all subsequent writes to the part of the file represented by this page. Before making any writes to the server, we need to confirm that we are not in the process of flushing data to the server and if we are, we should wait until the process is complete before we attempt the write. We should also wait for existing writes to complete before we process an oplock break request which changes oplock values. We add a version specific downgrade_oplock() operation to allow for differences in the oplock values set for the different smb versions. Cc: stable@vger.kernel.org Signed-off-by: Sachin Prabhu Reviewed-by: Jeff Layton Reviewed-by: Pavel Shilovsky Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 14 ++++++++- fs/cifs/cifsglob.h | 8 +++++ fs/cifs/cifsproto.h | 3 ++ fs/cifs/file.c | 31 +++++++++++++++++-- fs/cifs/misc.c | 74 +++++++++++++++++++++++++++++++++++++++++++-- fs/cifs/smb1ops.c | 11 +++++++ fs/cifs/smb2misc.c | 18 +++++++++-- fs/cifs/smb2ops.c | 14 +++++++++ 8 files changed, 164 insertions(+), 9 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index df9c9141c09983..5be1f997ecdeff 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -253,6 +253,11 @@ cifs_alloc_inode(struct super_block *sb) cifs_set_oplock_level(cifs_inode, 0); cifs_inode->delete_pending = false; cifs_inode->invalid_mapping = false; + clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cifs_inode->flags); + clear_bit(CIFS_INODE_PENDING_WRITERS, &cifs_inode->flags); + clear_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cifs_inode->flags); + spin_lock_init(&cifs_inode->writers_lock); + cifs_inode->writers = 0; cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ cifs_inode->server_eof = 0; cifs_inode->uniqueid = 0; @@ -732,19 +737,26 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct inode *inode = file_inode(iocb->ki_filp); + struct cifsInodeInfo *cinode = CIFS_I(inode); ssize_t written; int rc; + written = cifs_get_writer(cinode); + if (written) + return written; + written = generic_file_aio_write(iocb, iov, nr_segs, pos); if (CIFS_CACHE_WRITE(CIFS_I(inode))) - return written; + goto out; rc = filemap_fdatawrite(inode->i_mapping); if (rc) cifs_dbg(FYI, "cifs_file_aio_write: %d rc on %p inode\n", rc, inode); +out: + cifs_put_writer(cinode); return written; } diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index c0f3718b77a83e..30f6e9251a4aed 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -228,6 +228,8 @@ struct smb_version_operations { /* verify the message */ int (*check_message)(char *, unsigned int); bool (*is_oplock_break)(char *, struct TCP_Server_Info *); + void (*downgrade_oplock)(struct TCP_Server_Info *, + struct cifsInodeInfo *, bool); /* process transaction2 response */ bool (*check_trans2)(struct mid_q_entry *, struct TCP_Server_Info *, char *, int); @@ -1113,6 +1115,12 @@ struct cifsInodeInfo { unsigned int epoch; /* used to track lease state changes */ bool delete_pending; /* DELETE_ON_CLOSE is set */ bool invalid_mapping; /* pagecache is invalid */ + unsigned long flags; +#define CIFS_INODE_PENDING_OPLOCK_BREAK (0) /* oplock break in progress */ +#define CIFS_INODE_PENDING_WRITERS (1) /* Writes in progress */ +#define CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2 (2) /* Downgrade oplock to L2 */ + spinlock_t writers_lock; + unsigned int writers; /* Number of writers on this inode */ unsigned long time; /* jiffies of last update of inode */ u64 server_eof; /* current file size on server -- protected by i_lock */ u64 uniqueid; /* server inode number */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index acc4ee8ed0759a..ca7980a1e303b8 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -127,6 +127,9 @@ extern u64 cifs_UnixTimeToNT(struct timespec); extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, int offset); extern void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock); +extern int cifs_get_writer(struct cifsInodeInfo *cinode); +extern void cifs_put_writer(struct cifsInodeInfo *cinode); +extern void cifs_done_oplock_break(struct cifsInodeInfo *cinode); extern int cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, const unsigned int xid); extern int cifs_push_mandatory_locks(struct cifsFileInfo *cfile); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 8add25538a3b83..d8ee76241b649c 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2621,12 +2621,20 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); ssize_t written; + written = cifs_get_writer(cinode); + if (written) + return written; + if (CIFS_CACHE_WRITE(cinode)) { if (cap_unix(tcon->ses) && (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) - && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) - return generic_file_aio_write(iocb, iov, nr_segs, pos); - return cifs_writev(iocb, iov, nr_segs, pos); + && ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) { + written = generic_file_aio_write( + iocb, iov, nr_segs, pos); + goto out; + } + written = cifs_writev(iocb, iov, nr_segs, pos); + goto out; } /* * For non-oplocked files in strict cache mode we need to write the data @@ -2646,6 +2654,8 @@ cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov, inode); cinode->oplock = 0; } +out: + cifs_put_writer(cinode); return written; } @@ -3621,6 +3631,13 @@ static int cifs_launder_page(struct page *page) return rc; } +static int +cifs_pending_writers_wait(void *unused) +{ + schedule(); + return 0; +} + void cifs_oplock_break(struct work_struct *work) { struct cifsFileInfo *cfile = container_of(work, struct cifsFileInfo, @@ -3628,8 +3645,15 @@ void cifs_oplock_break(struct work_struct *work) struct inode *inode = cfile->dentry->d_inode; struct cifsInodeInfo *cinode = CIFS_I(inode); struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); + struct TCP_Server_Info *server = tcon->ses->server; int rc = 0; + wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS, + cifs_pending_writers_wait, TASK_UNINTERRUPTIBLE); + + server->ops->downgrade_oplock(server, cinode, + test_bit(CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, &cinode->flags)); + if (!CIFS_CACHE_WRITE(cinode) && CIFS_CACHE_READ(cinode) && cifs_has_mand_locks(cinode)) { cifs_dbg(FYI, "Reset oplock to None for inode=%p due to mand locks\n", @@ -3666,6 +3690,7 @@ void cifs_oplock_break(struct work_struct *work) cinode); cifs_dbg(FYI, "Oplock release rc = %d\n", rc); } + cifs_done_oplock_break(cinode); } /* diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index 2f9f3790679d91..3b0c62e622da80 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -466,8 +466,22 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) cifs_dbg(FYI, "file id match, oplock break\n"); pCifsInode = CIFS_I(netfile->dentry->d_inode); - cifs_set_oplock_level(pCifsInode, - pSMB->OplockLevel ? OPLOCK_READ : 0); + set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, + &pCifsInode->flags); + + /* + * Set flag if the server downgrades the oplock + * to L2 else clear. + */ + if (pSMB->OplockLevel) + set_bit( + CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, + &pCifsInode->flags); + else + clear_bit( + CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, + &pCifsInode->flags); + queue_work(cifsiod_wq, &netfile->oplock_break); netfile->oplock_break_cancelled = false; @@ -551,6 +565,62 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) cinode->oplock = 0; } +static int +cifs_oplock_break_wait(void *unused) +{ + schedule(); + return signal_pending(current) ? -ERESTARTSYS : 0; +} + +/* + * We wait for oplock breaks to be processed before we attempt to perform + * writes. + */ +int cifs_get_writer(struct cifsInodeInfo *cinode) +{ + int rc; + +start: + rc = wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK, + cifs_oplock_break_wait, TASK_KILLABLE); + if (rc) + return rc; + + spin_lock(&cinode->writers_lock); + if (!cinode->writers) + set_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags); + cinode->writers++; + /* Check to see if we have started servicing an oplock break */ + if (test_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags)) { + cinode->writers--; + if (cinode->writers == 0) { + clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags); + wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS); + } + spin_unlock(&cinode->writers_lock); + goto start; + } + spin_unlock(&cinode->writers_lock); + return 0; +} + +void cifs_put_writer(struct cifsInodeInfo *cinode) +{ + spin_lock(&cinode->writers_lock); + cinode->writers--; + if (cinode->writers == 0) { + clear_bit(CIFS_INODE_PENDING_WRITERS, &cinode->flags); + wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS); + } + spin_unlock(&cinode->writers_lock); +} + +void cifs_done_oplock_break(struct cifsInodeInfo *cinode) +{ + clear_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, &cinode->flags); + wake_up_bit(&cinode->flags, CIFS_INODE_PENDING_OPLOCK_BREAK); +} + bool backup_cred(struct cifs_sb_info *cifs_sb) { diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index 526fb89f92305b..d1fdfa848703d3 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -372,6 +372,16 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr) return 0; } +static void +cifs_downgrade_oplock(struct TCP_Server_Info *server, + struct cifsInodeInfo *cinode, bool set_level2) +{ + if (set_level2) + cifs_set_oplock_level(cinode, OPLOCK_READ); + else + cifs_set_oplock_level(cinode, 0); +} + static bool cifs_check_trans2(struct mid_q_entry *mid, struct TCP_Server_Info *server, char *buf, int malformed) @@ -1019,6 +1029,7 @@ struct smb_version_operations smb1_operations = { .clear_stats = cifs_clear_stats, .print_stats = cifs_print_stats, .is_oplock_break = is_valid_oplock_break, + .downgrade_oplock = cifs_downgrade_oplock, .check_trans2 = cifs_check_trans2, .need_neg = cifs_need_neg, .negotiate = cifs_negotiate, diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index fb3966265b6ef6..b8021fde987dbb 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -575,9 +575,21 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server) else cfile->oplock_break_cancelled = false; - server->ops->set_oplock_level(cinode, - rsp->OplockLevel ? SMB2_OPLOCK_LEVEL_II : 0, - 0, NULL); + set_bit(CIFS_INODE_PENDING_OPLOCK_BREAK, + &cinode->flags); + + /* + * Set flag if the server downgrades the oplock + * to L2 else clear. + */ + if (rsp->OplockLevel) + set_bit( + CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, + &cinode->flags); + else + clear_bit( + CIFS_INODE_DOWNGRADE_OPLOCK_TO_L2, + &cinode->flags); queue_work(cifsiod_wq, &cfile->oplock_break); diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index 192f51a12cf1c6..35ddc3ed119d3b 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -904,6 +904,17 @@ smb2_query_symlink(const unsigned int xid, struct cifs_tcon *tcon, return rc; } +static void +smb2_downgrade_oplock(struct TCP_Server_Info *server, + struct cifsInodeInfo *cinode, bool set_level2) +{ + if (set_level2) + server->ops->set_oplock_level(cinode, SMB2_OPLOCK_LEVEL_II, + 0, NULL); + else + server->ops->set_oplock_level(cinode, 0, 0, NULL); +} + static void smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock, unsigned int epoch, bool *purge_cache) @@ -1110,6 +1121,7 @@ struct smb_version_operations smb20_operations = { .clear_stats = smb2_clear_stats, .print_stats = smb2_print_stats, .is_oplock_break = smb2_is_valid_oplock_break, + .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate, .negotiate_wsize = smb2_negotiate_wsize, @@ -1184,6 +1196,7 @@ struct smb_version_operations smb21_operations = { .clear_stats = smb2_clear_stats, .print_stats = smb2_print_stats, .is_oplock_break = smb2_is_valid_oplock_break, + .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate, .negotiate_wsize = smb2_negotiate_wsize, @@ -1259,6 +1272,7 @@ struct smb_version_operations smb30_operations = { .print_stats = smb2_print_stats, .dump_share_caps = smb2_dump_share_caps, .is_oplock_break = smb2_is_valid_oplock_break, + .downgrade_oplock = smb2_downgrade_oplock, .need_neg = smb2_need_neg, .negotiate = smb2_negotiate, .negotiate_wsize = smb2_negotiate_wsize, From 60977fcc808664f82412bb37da7be17640ba99d9 Mon Sep 17 00:00:00 2001 From: Steve French Date: Tue, 25 Mar 2014 19:46:36 -0500 Subject: [PATCH 143/279] Return correct error on query of xattr on file with empty xattrs xfstest 020 detected a problem with cifs xattr handling. When a file had an empty xattr list, we returned success (with an empty xattr value) on query of particular xattrs rather than returning ENODATA. This patch fixes it so that query of an xattr returns ENODATA when the xattr list is empty for the file. Signed-off-by: Steve French Reviewed-by: Jeff Layton --- fs/cifs/cifssmb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index f3264bd7a83d94..6ce4e0954b986a 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -6197,6 +6197,9 @@ CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon, cifs_dbg(FYI, "ea length %d\n", list_len); if (list_len <= 8) { cifs_dbg(FYI, "empty EA list returned from server\n"); + /* didn't find the named attribute */ + if (ea_name) + rc = -ENODATA; goto QAllEAsOut; } From 8e3ecc87695f4a7e9e217ebd55ca6a39b6a451b8 Mon Sep 17 00:00:00 2001 From: Cyril Roelandt Date: Fri, 4 Apr 2014 00:05:21 +0200 Subject: [PATCH 144/279] fs: cifs: remove unused variable. In SMB2_set_compression(), the "res_key" variable is only initialized to NULL and later kfreed. It is therefore useless and should be removed. Found with the following semantic patch: @@ identifier foo; identifier f; type T; @@ * f(...) { ... * T *foo = NULL; ... when forall when != foo * kfree(foo); ... } Signed-off-by: Cyril Roelandt Signed-off-by: Steve French --- fs/cifs/smb2pdu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 860344701067f4..3802f8c94accdb 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -1352,7 +1352,6 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid, u64 volatile_fid) { int rc; - char *res_key = NULL; struct compress_ioctl fsctl_input; char *ret_data = NULL; @@ -1365,7 +1364,6 @@ SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon, 2 /* in data len */, &ret_data /* out data */, NULL); cifs_dbg(FYI, "set compression rc %d\n", rc); - kfree(res_key); return rc; } From a2a4dc494a7b7135f460e38e788c4a58f65e4ac3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20B=C3=A4chler?= Date: Thu, 3 Apr 2014 21:55:37 +0200 Subject: [PATCH 145/279] fs: Don't return 0 from get_anon_bdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 9e30cc9595303b27b48 removed an internal mount. This has the side-effect that rootfs now has FSID 0. Many userspace utilities assume that st_dev in struct stat is never 0, so this change breaks a number of tools in early userspace. Since we don't know how many userspace programs are affected, make sure that FSID is at least 1. References: http://article.gmane.org/gmane.linux.kernel/1666905 References: http://permalink.gmane.org/gmane.linux.utilities.util-linux-ng/8557 Cc: 3.14 Signed-off-by: Thomas Bächler Acked-by: Tejun Heo Acked-by: H. Peter Anvin Tested-by: Alexandre Demers Signed-off-by: Greg Kroah-Hartman --- fs/super.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/super.c b/fs/super.c index e9dc3c3fe159cc..48377f7463c0d3 100644 --- a/fs/super.c +++ b/fs/super.c @@ -800,7 +800,10 @@ void emergency_remount(void) static DEFINE_IDA(unnamed_dev_ida); static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ -static int unnamed_dev_start = 0; /* don't bother trying below it */ +/* Many userspace utilities consider an FSID of 0 invalid. + * Always return at least 1 from get_anon_bdev. + */ +static int unnamed_dev_start = 1; int get_anon_bdev(dev_t *p) { From 4afddd60a770560d370d6f85c5aef57c16bf7502 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 2 Apr 2014 16:40:52 -0400 Subject: [PATCH 146/279] kernfs: protect lazy kernfs_iattrs allocation with mutex kernfs_iattrs is allocated lazily when operations which require it take place; unfortunately, the lazy allocation and returning weren't properly synchronized and when there are multiple concurrent operations, it might end up returning kernfs_iattrs which hasn't finished initialization yet or different copies to different callers. Fix it by synchronizing with a mutex. This can be smarter with memory barriers but let's go there if it actually turns out to be necessary. Signed-off-by: Tejun Heo Link: http://lkml.kernel.org/g/533ABA32.9080602@oracle.com Reported-by: Sasha Levin Cc: stable@vger.kernel.org # 3.14 Signed-off-by: Greg Kroah-Hartman --- fs/kernfs/inode.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index abb0f1f53d933c..985217626e663f 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c @@ -48,14 +48,18 @@ void __init kernfs_inode_init(void) static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) { + static DEFINE_MUTEX(iattr_mutex); + struct kernfs_iattrs *ret; struct iattr *iattrs; + mutex_lock(&iattr_mutex); + if (kn->iattr) - return kn->iattr; + goto out_unlock; kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL); if (!kn->iattr) - return NULL; + goto out_unlock; iattrs = &kn->iattr->ia_iattr; /* assign default attributes */ @@ -65,8 +69,10 @@ static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) iattrs->ia_atime = iattrs->ia_mtime = iattrs->ia_ctime = CURRENT_TIME; simple_xattrs_init(&kn->iattr->xattrs); - - return kn->iattr; +out_unlock: + ret = kn->iattr; + mutex_unlock(&iattr_mutex); + return ret; } static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) From 33ac1257ff0dee2e9c7f009b1c1914b7990217b2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 10 Jan 2014 08:57:31 -0500 Subject: [PATCH 147/279] sysfs, driver-core: remove unused {sysfs|device}_schedule_callback_owner() All device_schedule_callback_owner() users are converted to use device_remove_file_self(). Remove now unused {sysfs|device}_schedule_callback_owner(). Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 33 --------------- fs/sysfs/file.c | 92 ------------------------------------------ include/linux/device.h | 11 +---- include/linux/sysfs.h | 9 ----- 4 files changed, 1 insertion(+), 144 deletions(-) diff --git a/drivers/base/core.c b/drivers/base/core.c index 0dd65281cc65bb..20da3ad1696b58 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -614,39 +614,6 @@ void device_remove_bin_file(struct device *dev, } EXPORT_SYMBOL_GPL(device_remove_bin_file); -/** - * device_schedule_callback_owner - helper to schedule a callback for a device - * @dev: device. - * @func: callback function to invoke later. - * @owner: module owning the callback routine - * - * Attribute methods must not unregister themselves or their parent device - * (which would amount to the same thing). Attempts to do so will deadlock, - * since unregistration is mutually exclusive with driver callbacks. - * - * Instead methods can call this routine, which will attempt to allocate - * and schedule a workqueue request to call back @func with @dev as its - * argument in the workqueue's process context. @dev will be pinned until - * @func returns. - * - * This routine is usually called via the inline device_schedule_callback(), - * which automatically sets @owner to THIS_MODULE. - * - * Returns 0 if the request was submitted, -ENOMEM if storage could not - * be allocated, -ENODEV if a reference to @owner isn't available. - * - * NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an - * underlying sysfs routine (since it is intended for use by attribute - * methods), and if sysfs isn't available you'll get nothing but -ENOSYS. - */ -int device_schedule_callback_owner(struct device *dev, - void (*func)(struct device *), struct module *owner) -{ - return sysfs_schedule_callback(&dev->kobj, - (void (*)(void *)) func, dev, owner); -} -EXPORT_SYMBOL_GPL(device_schedule_callback_owner); - static void klist_children_get(struct klist_node *n) { struct device_private *p = to_device_private_parent(n); diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 1b8b91b67fdb7a..28cc1acd5439bf 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -453,95 +453,3 @@ void sysfs_remove_bin_file(struct kobject *kobj, kernfs_remove_by_name(kobj->sd, attr->attr.name); } EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); - -struct sysfs_schedule_callback_struct { - struct list_head workq_list; - struct kobject *kobj; - void (*func)(void *); - void *data; - struct module *owner; - struct work_struct work; -}; - -static struct workqueue_struct *sysfs_workqueue; -static DEFINE_MUTEX(sysfs_workq_mutex); -static LIST_HEAD(sysfs_workq); -static void sysfs_schedule_callback_work(struct work_struct *work) -{ - struct sysfs_schedule_callback_struct *ss = container_of(work, - struct sysfs_schedule_callback_struct, work); - - (ss->func)(ss->data); - kobject_put(ss->kobj); - module_put(ss->owner); - mutex_lock(&sysfs_workq_mutex); - list_del(&ss->workq_list); - mutex_unlock(&sysfs_workq_mutex); - kfree(ss); -} - -/** - * sysfs_schedule_callback - helper to schedule a callback for a kobject - * @kobj: object we're acting for. - * @func: callback function to invoke later. - * @data: argument to pass to @func. - * @owner: module owning the callback code - * - * sysfs attribute methods must not unregister themselves or their parent - * kobject (which would amount to the same thing). Attempts to do so will - * deadlock, since unregistration is mutually exclusive with driver - * callbacks. - * - * Instead methods can call this routine, which will attempt to allocate - * and schedule a workqueue request to call back @func with @data as its - * argument in the workqueue's process context. @kobj will be pinned - * until @func returns. - * - * Returns 0 if the request was submitted, -ENOMEM if storage could not - * be allocated, -ENODEV if a reference to @owner isn't available, - * -EAGAIN if a callback has already been scheduled for @kobj. - */ -int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), - void *data, struct module *owner) -{ - struct sysfs_schedule_callback_struct *ss, *tmp; - - if (!try_module_get(owner)) - return -ENODEV; - - mutex_lock(&sysfs_workq_mutex); - list_for_each_entry_safe(ss, tmp, &sysfs_workq, workq_list) - if (ss->kobj == kobj) { - module_put(owner); - mutex_unlock(&sysfs_workq_mutex); - return -EAGAIN; - } - mutex_unlock(&sysfs_workq_mutex); - - if (sysfs_workqueue == NULL) { - sysfs_workqueue = create_singlethread_workqueue("sysfsd"); - if (sysfs_workqueue == NULL) { - module_put(owner); - return -ENOMEM; - } - } - - ss = kmalloc(sizeof(*ss), GFP_KERNEL); - if (!ss) { - module_put(owner); - return -ENOMEM; - } - kobject_get(kobj); - ss->kobj = kobj; - ss->func = func; - ss->data = data; - ss->owner = owner; - INIT_WORK(&ss->work, sysfs_schedule_callback_work); - INIT_LIST_HEAD(&ss->workq_list); - mutex_lock(&sysfs_workq_mutex); - list_add_tail(&ss->workq_list, &sysfs_workq); - mutex_unlock(&sysfs_workq_mutex); - queue_work(sysfs_workqueue, &ss->work); - return 0; -} -EXPORT_SYMBOL_GPL(sysfs_schedule_callback); diff --git a/include/linux/device.h b/include/linux/device.h index 233bbbeb768d6f..d1d1c055b48e2e 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -566,12 +566,6 @@ extern int __must_check device_create_bin_file(struct device *dev, const struct bin_attribute *attr); extern void device_remove_bin_file(struct device *dev, const struct bin_attribute *attr); -extern int device_schedule_callback_owner(struct device *dev, - void (*func)(struct device *dev), struct module *owner); - -/* This is a macro to avoid include problems with THIS_MODULE */ -#define device_schedule_callback(dev, func) \ - device_schedule_callback_owner(dev, func, THIS_MODULE) /* device resource management */ typedef void (*dr_release_t)(struct device *dev, void *res); @@ -932,10 +926,7 @@ extern int device_online(struct device *dev); extern struct device *__root_device_register(const char *name, struct module *owner); -/* - * This is a macro to avoid include problems with THIS_MODULE, - * just as per what is done for device_schedule_callback() above. - */ +/* This is a macro to avoid include problems with THIS_MODULE */ #define root_device_register(name) \ __root_device_register(name, THIS_MODULE) diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 084354b0e81451..5ffaa344371282 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -179,9 +179,6 @@ struct sysfs_ops { #ifdef CONFIG_SYSFS -int sysfs_schedule_callback(struct kobject *kobj, void (*func)(void *), - void *data, struct module *owner); - int __must_check sysfs_create_dir_ns(struct kobject *kobj, const void *ns); void sysfs_remove_dir(struct kobject *kobj); int __must_check sysfs_rename_dir_ns(struct kobject *kobj, const char *new_name, @@ -255,12 +252,6 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) #else /* CONFIG_SYSFS */ -static inline int sysfs_schedule_callback(struct kobject *kobj, - void (*func)(void *), void *data, struct module *owner) -{ - return -ENOSYS; -} - static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) { return 0; From c98235cb8584a72e95786e17d695a8e5fafcd766 Mon Sep 17 00:00:00 2001 From: Chris Mason Date: Tue, 15 Apr 2014 18:09:24 -0400 Subject: [PATCH 148/279] mlx4_en: don't use napi_synchronize inside mlx4_en_netpoll The mlx4 driver is triggering schedules while atomic inside mlx4_en_netpoll: spin_lock_irqsave(&cq->lock, flags); napi_synchronize(&cq->napi); ^^^^^ msleep here mlx4_en_process_rx_cq(dev, cq, 0); spin_unlock_irqrestore(&cq->lock, flags); This was part of a patch by Alexander Guller from Mellanox in 2011, but it still isn't upstream. Signed-off-by: Chris Mason cc: stable@vger.kernel.org Acked-By: Amir Vadai Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlx4/en_cq.c | 1 - drivers/net/ethernet/mellanox/mlx4/en_netdev.c | 6 +----- drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | 1 - 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx4/en_cq.c b/drivers/net/ethernet/mellanox/mlx4/en_cq.c index 70e95324a97d35..c2cd8d31bcad56 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_cq.c @@ -66,7 +66,6 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv, cq->ring = ring; cq->is_tx = mode; - spin_lock_init(&cq->lock); /* Allocate HW buffers on provided NUMA node. * dev->numa_node is used in mtt range allocation flow. diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index f085c2df5e6924..7e4b1720c3d1be 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c @@ -1304,15 +1304,11 @@ static void mlx4_en_netpoll(struct net_device *dev) { struct mlx4_en_priv *priv = netdev_priv(dev); struct mlx4_en_cq *cq; - unsigned long flags; int i; for (i = 0; i < priv->rx_ring_num; i++) { cq = priv->rx_cq[i]; - spin_lock_irqsave(&cq->lock, flags); - napi_synchronize(&cq->napi); - mlx4_en_process_rx_cq(dev, cq, 0); - spin_unlock_irqrestore(&cq->lock, flags); + napi_schedule(&cq->napi); } } #endif diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index 7a733c28774422..04d9b6fe3e8000 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h @@ -319,7 +319,6 @@ struct mlx4_en_cq { struct mlx4_cq mcq; struct mlx4_hwq_resources wqres; int ring; - spinlock_t lock; struct net_device *dev; struct napi_struct napi; int size; From 6a662719c9868b3d6c7d26b3a085f0cd3cc15e64 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 15 Apr 2014 16:25:34 -0700 Subject: [PATCH 149/279] ipv4, fib: pass LOOPBACK_IFINDEX instead of 0 to flowi4_iif MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As suggested by Julian: Simply, flowi4_iif must not contain 0, it does not look logical to ignore all ip rules with specified iif. because in fib_rule_match() we do: if (rule->iifindex && (rule->iifindex != fl->flowi_iif)) goto out; flowi4_iif should be LOOPBACK_IFINDEX by default. We need to move LOOPBACK_IFINDEX to include/net/flow.h: 1) It is mostly used by flowi_iif 2) Fix the following compile error if we use it in flow.h by the patches latter: In file included from include/linux/netfilter.h:277:0, from include/net/netns/netfilter.h:5, from include/net/net_namespace.h:21, from include/linux/netdevice.h:43, from include/linux/icmpv6.h:12, from include/linux/ipv6.h:61, from include/net/ipv6.h:16, from include/linux/sunrpc/clnt.h:27, from include/linux/nfs_fs.h:30, from init/do_mounts.c:32: include/net/flow.h: In function ‘flowi4_init_output’: include/net/flow.h:84:32: error: ‘LOOPBACK_IFINDEX’ undeclared (first use in this function) Cc: Eric Biederman Cc: Julian Anastasov Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- include/net/flow.h | 10 +++++++++- include/net/net_namespace.h | 9 +-------- net/ipv4/fib_frontend.c | 2 +- net/ipv4/fib_semantics.c | 1 + net/ipv4/ipmr.c | 2 +- net/ipv4/netfilter/ipt_rpfilter.c | 5 +---- net/ipv6/ip6mr.c | 2 +- 7 files changed, 15 insertions(+), 16 deletions(-) diff --git a/include/net/flow.h b/include/net/flow.h index 64fd24836650b7..8109a159d1b3ba 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -11,6 +11,14 @@ #include #include +/* + * ifindex generation is per-net namespace, and loopback is + * always the 1st device in ns (see net_dev_init), thus any + * loopback device should get ifindex 1 + */ + +#define LOOPBACK_IFINDEX 1 + struct flowi_common { int flowic_oif; int flowic_iif; @@ -80,7 +88,7 @@ static inline void flowi4_init_output(struct flowi4 *fl4, int oif, __be16 dport, __be16 sport) { fl4->flowi4_oif = oif; - fl4->flowi4_iif = 0; + fl4->flowi4_iif = LOOPBACK_IFINDEX; fl4->flowi4_mark = mark; fl4->flowi4_tos = tos; fl4->flowi4_scope = scope; diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 79387f73f87585..5f9eb260990f65 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -131,14 +132,6 @@ struct net { atomic_t fnhe_genid; }; -/* - * ifindex generation is per-net namespace, and loopback is - * always the 1st device in ns (see net_dev_init), thus any - * loopback device should get ifindex 1 - */ - -#define LOOPBACK_IFINDEX 1 - #include /* Init's network namespace */ diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 1a629f870274de..255aa9946fe785 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -250,7 +250,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, bool dev_match; fl4.flowi4_oif = 0; - fl4.flowi4_iif = oif; + fl4.flowi4_iif = oif ? : LOOPBACK_IFINDEX; fl4.daddr = src; fl4.saddr = dst; fl4.flowi4_tos = tos; diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c index b53f0bf84dcaba..8a043f03c88ecb 100644 --- a/net/ipv4/fib_semantics.c +++ b/net/ipv4/fib_semantics.c @@ -631,6 +631,7 @@ static int fib_check_nh(struct fib_config *cfg, struct fib_info *fi, .daddr = nh->nh_gw, .flowi4_scope = cfg->fc_scope + 1, .flowi4_oif = nh->nh_oif, + .flowi4_iif = LOOPBACK_IFINDEX, }; /* It is not necessary, but requires a bit of thinking */ diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 28863570dd6055..d84dc8d4c916e7 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -455,7 +455,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct net_device *dev) struct mr_table *mrt; struct flowi4 fl4 = { .flowi4_oif = dev->ifindex, - .flowi4_iif = skb->skb_iif, + .flowi4_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, .flowi4_mark = skb->mark, }; int err; diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c index c49dcd0284a06c..4bfaedf9b34e52 100644 --- a/net/ipv4/netfilter/ipt_rpfilter.c +++ b/net/ipv4/netfilter/ipt_rpfilter.c @@ -89,11 +89,8 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) if (ipv4_is_multicast(iph->daddr)) { if (ipv4_is_zeronet(iph->saddr)) return ipv4_is_local_multicast(iph->daddr) ^ invert; - flow.flowi4_iif = 0; - } else { - flow.flowi4_iif = LOOPBACK_IFINDEX; } - + flow.flowi4_iif = LOOPBACK_IFINDEX; flow.daddr = iph->saddr; flow.saddr = rpfilter_get_saddr(iph->daddr); flow.flowi4_oif = 0; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 8737400af0a095..8659067da28e8a 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -700,7 +700,7 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, struct mr6_table *mrt; struct flowi6 fl6 = { .flowi6_oif = dev->ifindex, - .flowi6_iif = skb->skb_iif, + .flowi6_iif = skb->skb_iif ? : LOOPBACK_IFINDEX, .flowi6_mark = skb->mark, }; int err; From 0d5edc68739f1c1e0519acbea1d3f0c1882a15d7 Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Tue, 15 Apr 2014 16:25:35 -0700 Subject: [PATCH 150/279] ipv4, route: pass 0 instead of LOOPBACK_IFINDEX to fib_validate_source() In my special case, when a packet is redirected from veth0 to lo, its skb->dev->ifindex would be LOOPBACK_IFINDEX. Meanwhile we pass the hard-coded LOOPBACK_IFINDEX to fib_validate_source() in ip_route_input_slow(). This would cause the following check in fib_validate_source() fail: (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev)) when rp_filter is disabeld on loopback. As suggested by Julian, the caller should pass 0 here so that we will not end up by calling __fib_validate_source(). Cc: Eric Biederman Cc: Julian Anastasov Cc: David S. Miller Signed-off-by: Cong Wang Signed-off-by: Cong Wang Signed-off-by: David S. Miller --- net/ipv4/route.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 1485aafcad59f3..db1e0da871f40a 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1700,8 +1700,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, if (res.type == RTN_LOCAL) { err = fib_validate_source(skb, saddr, daddr, tos, - LOOPBACK_IFINDEX, - dev, in_dev, &itag); + 0, dev, in_dev, &itag); if (err < 0) goto martian_source_keep_err; goto local_input; From 78cdb079685cd8365acaf9fce896137e7d60e1c1 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 15 Apr 2014 19:16:40 -0700 Subject: [PATCH 151/279] net: mdio-gpio: Use devm_ functions where possible This simplifies error path and deinit/removal functions. Signed-off-by: Guenter Roeck Tested-by: Chris Healy Signed-off-by: David S. Miller --- drivers/net/phy/mdio-gpio.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index e701433bf52f60..e853066c805ad6 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -110,7 +110,7 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, struct mdio_gpio_info *bitbang; int i; - bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL); + bitbang = devm_kzalloc(dev, sizeof(*bitbang), GFP_KERNEL); if (!bitbang) goto out; @@ -121,7 +121,7 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, new_bus = alloc_mdio_bitbang(&bitbang->ctrl); if (!new_bus) - goto out_free_bitbang; + goto out; new_bus->name = "GPIO Bitbanged MDIO", @@ -138,11 +138,11 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, snprintf(new_bus->id, MII_BUS_ID_SIZE, "gpio-%x", bus_id); - if (gpio_request(bitbang->mdc, "mdc")) + if (devm_gpio_request(dev, bitbang->mdc, "mdc")) goto out_free_bus; - if (gpio_request(bitbang->mdio, "mdio")) - goto out_free_mdc; + if (devm_gpio_request(dev, bitbang->mdio, "mdio")) + goto out_free_bus; gpio_direction_output(bitbang->mdc, 0); @@ -150,12 +150,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, return new_bus; -out_free_mdc: - gpio_free(bitbang->mdc); out_free_bus: free_mdio_bitbang(new_bus); -out_free_bitbang: - kfree(bitbang); out: return NULL; } @@ -163,13 +159,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, static void mdio_gpio_bus_deinit(struct device *dev) { struct mii_bus *bus = dev_get_drvdata(dev); - struct mdio_gpio_info *bitbang = bus->priv; - dev_set_drvdata(dev, NULL); - gpio_free(bitbang->mdio); - gpio_free(bitbang->mdc); free_mdio_bitbang(bus); - kfree(bitbang); } static void mdio_gpio_bus_destroy(struct device *dev) From 1d2514818a2c3d94dd250e6027cb928a4e192548 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 15 Apr 2014 19:16:41 -0700 Subject: [PATCH 152/279] net: mdio-gpio: Add support for active low gpio pins Some systems using mdio-gpio may use active-low gpio pins (eg with inverters or FETs connected to all or some of the gpio pins). Signed-off-by: Guenter Roeck Signed-off-by: David S. Miller --- drivers/net/phy/mdio-gpio.c | 19 +++++++++++++------ include/linux/mdio-gpio.h | 3 +++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index e853066c805ad6..fac211a5001e9c 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -33,28 +33,32 @@ struct mdio_gpio_info { struct mdiobb_ctrl ctrl; int mdc, mdio; + int mdc_active_low, mdio_active_low; }; static void *mdio_gpio_of_get_data(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct mdio_gpio_platform_data *pdata; + enum of_gpio_flags flags; int ret; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return NULL; - ret = of_get_gpio(np, 0); + ret = of_get_gpio_flags(np, 0, &flags); if (ret < 0) return NULL; pdata->mdc = ret; + pdata->mdc_active_low = flags & OF_GPIO_ACTIVE_LOW; - ret = of_get_gpio(np, 1); + ret = of_get_gpio_flags(np, 1, &flags); if (ret < 0) return NULL; pdata->mdio = ret; + pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW; return pdata; } @@ -65,7 +69,8 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) container_of(ctrl, struct mdio_gpio_info, ctrl); if (dir) - gpio_direction_output(bitbang->mdio, 1); + gpio_direction_output(bitbang->mdio, + 1 ^ bitbang->mdio_active_low); else gpio_direction_input(bitbang->mdio); } @@ -75,7 +80,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); - return gpio_get_value(bitbang->mdio); + return gpio_get_value(bitbang->mdio) ^ bitbang->mdio_active_low; } static void mdio_set(struct mdiobb_ctrl *ctrl, int what) @@ -83,7 +88,7 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); - gpio_set_value(bitbang->mdio, what); + gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low); } static void mdc_set(struct mdiobb_ctrl *ctrl, int what) @@ -91,7 +96,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); - gpio_set_value(bitbang->mdc, what); + gpio_set_value(bitbang->mdc, what ^ bitbang->mdc_active_low); } static struct mdiobb_ops mdio_gpio_ops = { @@ -117,7 +122,9 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, bitbang->ctrl.ops = &mdio_gpio_ops; bitbang->ctrl.reset = pdata->reset; bitbang->mdc = pdata->mdc; + bitbang->mdc_active_low = pdata->mdc_active_low; bitbang->mdio = pdata->mdio; + bitbang->mdio_active_low = pdata->mdio_active_low; new_bus = alloc_mdio_bitbang(&bitbang->ctrl); if (!new_bus) diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h index 7c9fe3c2be73a7..57e57fe6055c7b 100644 --- a/include/linux/mdio-gpio.h +++ b/include/linux/mdio-gpio.h @@ -18,6 +18,9 @@ struct mdio_gpio_platform_data { unsigned int mdc; unsigned int mdio; + bool mdc_active_low; + bool mdio_active_low; + unsigned int phy_mask; int irqs[PHY_MAX_ADDR]; /* reset callback */ From f1d54c47502f42f5c4b89dacbe845ecd87ca002e Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Tue, 15 Apr 2014 19:16:42 -0700 Subject: [PATCH 153/279] net: mdio-gpio: Add support for separate MDI and MDO gpio pins This is for a system with fixed assignments of input and output pins (various variants of Kontron COMe). Signed-off-by: Guenter Roeck Signed-off-by: David S. Miller --- drivers/net/phy/mdio-gpio.c | 34 +++++++++++++++++++++++++++++++--- include/linux/mdio-gpio.h | 2 ++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index fac211a5001e9c..9c4defdec67b09 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -32,8 +32,8 @@ struct mdio_gpio_info { struct mdiobb_ctrl ctrl; - int mdc, mdio; - int mdc_active_low, mdio_active_low; + int mdc, mdio, mdo; + int mdc_active_low, mdio_active_low, mdo_active_low; }; static void *mdio_gpio_of_get_data(struct platform_device *pdev) @@ -60,6 +60,12 @@ static void *mdio_gpio_of_get_data(struct platform_device *pdev) pdata->mdio = ret; pdata->mdio_active_low = flags & OF_GPIO_ACTIVE_LOW; + ret = of_get_gpio_flags(np, 2, &flags); + if (ret > 0) { + pdata->mdo = ret; + pdata->mdo_active_low = flags & OF_GPIO_ACTIVE_LOW; + } + return pdata; } @@ -68,6 +74,16 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); + if (bitbang->mdo) { + /* Separate output pin. Always set its value to high + * when changing direction. If direction is input, + * assume the pin serves as pull-up. If direction is + * output, the default value is high. + */ + gpio_set_value(bitbang->mdo, 1 ^ bitbang->mdo_active_low); + return; + } + if (dir) gpio_direction_output(bitbang->mdio, 1 ^ bitbang->mdio_active_low); @@ -88,7 +104,10 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what) struct mdio_gpio_info *bitbang = container_of(ctrl, struct mdio_gpio_info, ctrl); - gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low); + if (bitbang->mdo) + gpio_set_value(bitbang->mdo, what ^ bitbang->mdo_active_low); + else + gpio_set_value(bitbang->mdio, what ^ bitbang->mdio_active_low); } static void mdc_set(struct mdiobb_ctrl *ctrl, int what) @@ -125,6 +144,8 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, bitbang->mdc_active_low = pdata->mdc_active_low; bitbang->mdio = pdata->mdio; bitbang->mdio_active_low = pdata->mdio_active_low; + bitbang->mdo = pdata->mdo; + bitbang->mdo_active_low = pdata->mdo_active_low; new_bus = alloc_mdio_bitbang(&bitbang->ctrl); if (!new_bus) @@ -151,6 +172,13 @@ static struct mii_bus *mdio_gpio_bus_init(struct device *dev, if (devm_gpio_request(dev, bitbang->mdio, "mdio")) goto out_free_bus; + if (bitbang->mdo) { + if (devm_gpio_request(dev, bitbang->mdo, "mdo")) + goto out_free_bus; + gpio_direction_output(bitbang->mdo, 1); + gpio_direction_input(bitbang->mdio); + } + gpio_direction_output(bitbang->mdc, 0); dev_set_drvdata(dev, new_bus); diff --git a/include/linux/mdio-gpio.h b/include/linux/mdio-gpio.h index 57e57fe6055c7b..66c30a763b108c 100644 --- a/include/linux/mdio-gpio.h +++ b/include/linux/mdio-gpio.h @@ -17,9 +17,11 @@ struct mdio_gpio_platform_data { /* GPIO numbers for bus pins */ unsigned int mdc; unsigned int mdio; + unsigned int mdo; bool mdc_active_low; bool mdio_active_low; + bool mdo_active_low; unsigned int phy_mask; int irqs[PHY_MAX_ADDR]; From 5c5e0589038537848849fc827f5234a31a10f899 Mon Sep 17 00:00:00 2001 From: Frank Haverkamp Date: Thu, 20 Mar 2014 15:11:02 +0100 Subject: [PATCH 154/279] GenWQE: Enable access to VPD flash area In addition to the two flash partitions we used so far, there is a 3rd one which is enabled for usage by this fix. Signed-off-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_dev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index 2c2c9cc75231d7..0d05ca77c458dd 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -531,7 +531,9 @@ static int do_flash_update(struct genwqe_file *cfile, case '1': cmdopts = 0x1C; break; /* download/erase_first/part_1 */ - case 'v': /* cmdopts = 0x0c (VPD) */ + case 'v': + cmdopts = 0x0C; + break; /* download/erase_first/vpd */ default: return -EINVAL; } @@ -665,6 +667,8 @@ static int do_flash_read(struct genwqe_file *cfile, cmdopts = 0x1A; break; /* upload/part_1 */ case 'v': + cmdopts = 0x0A; + break; /* upload/vpd */ default: return -EINVAL; } From 68fe8acc204c7fbefd4c01b8929fedb244ec283d Mon Sep 17 00:00:00 2001 From: Frank Haverkamp Date: Thu, 20 Mar 2014 15:11:03 +0100 Subject: [PATCH 155/279] GenWQE: Add wmb before DDCB is started Needed to add wmb() before we send the DDCB for execution. Without the syncronizing it failed on System p. Signed-off-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_ddcb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c index 6f1acc0ccf887f..29a1a28be02a1a 100644 --- a/drivers/misc/genwqe/card_ddcb.c +++ b/drivers/misc/genwqe/card_ddcb.c @@ -305,6 +305,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue, break; new = (old | DDCB_NEXT_BE32); + + wmb(); icrc_hsi_shi = cmpxchg(&prev_ddcb->icrc_hsi_shi_32, old, new); if (icrc_hsi_shi == old) @@ -314,6 +316,8 @@ static int enqueue_ddcb(struct genwqe_dev *cd, struct ddcb_queue *queue, /* Queue must be re-started by updating QUEUE_OFFSET */ ddcb_mark_tapped(pddcb); num = (u64)ddcb_no << 8; + + wmb(); __genwqe_writeq(cd, queue->IO_QUEUE_OFFSET, num); /* start queue */ return RET_DDCB_TAPPED; From ebb2c96bb9214ba38c7fe35d5d725f6e7cb3bbc8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Thu, 20 Mar 2014 15:11:04 +0100 Subject: [PATCH 156/279] GenWQE: Ensure rc is not returning an uninitialized value rc is not initialized, so genwqe_finish_queue() either returns -EIO or garbage. Fortunately the return is not being checked by any callers, so this has not yet caused any problems. Even so, it makes sense to fix this small bug in case is is checked in future. Signed-off-by: Colin Ian King Signed-off-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_ddcb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/genwqe/card_ddcb.c b/drivers/misc/genwqe/card_ddcb.c index 29a1a28be02a1a..c8046db2d5a230 100644 --- a/drivers/misc/genwqe/card_ddcb.c +++ b/drivers/misc/genwqe/card_ddcb.c @@ -1310,7 +1310,7 @@ static int queue_wake_up_all(struct genwqe_dev *cd) */ int genwqe_finish_queue(struct genwqe_dev *cd) { - int i, rc, in_flight; + int i, rc = 0, in_flight; int waitmax = genwqe_ddcb_software_timeout; struct pci_dev *pci_dev = cd->pci_dev; struct ddcb_queue *queue = &cd->queue; From 718f762efc454796d02f172a929d051f2d6ec01a Mon Sep 17 00:00:00 2001 From: Frank Haverkamp Date: Thu, 20 Mar 2014 15:11:05 +0100 Subject: [PATCH 157/279] GenWQE: Fix multithreading problems When being used in a multithreaded application there were problems with memory pages/cachelines accessed by multiple threads/cpus at the same time, while doing DMA transfers to/from those. To avoid such situations this fix is creating a copy of the first and the last page if it is not fully used. The data is copied from user-space into those pages and results are copied back when the DDCB-request is successfully finished. Signed-off-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_base.h | 58 +++++++---- drivers/misc/genwqe/card_dev.c | 38 ++----- drivers/misc/genwqe/card_utils.c | 170 +++++++++++++++++++++++-------- 3 files changed, 180 insertions(+), 86 deletions(-) diff --git a/drivers/misc/genwqe/card_base.h b/drivers/misc/genwqe/card_base.h index 5e4dbd21f89ad1..0e608a28860303 100644 --- a/drivers/misc/genwqe/card_base.h +++ b/drivers/misc/genwqe/card_base.h @@ -336,6 +336,44 @@ enum genwqe_requ_state { GENWQE_REQU_STATE_MAX, }; +/** + * struct genwqe_sgl - Scatter gather list describing user-space memory + * @sgl: scatter gather list needs to be 128 byte aligned + * @sgl_dma_addr: dma address of sgl + * @sgl_size: size of area used for sgl + * @user_addr: user-space address of memory area + * @user_size: size of user-space memory area + * @page: buffer for partial pages if needed + * @page_dma_addr: dma address partial pages + */ +struct genwqe_sgl { + dma_addr_t sgl_dma_addr; + struct sg_entry *sgl; + size_t sgl_size; /* size of sgl */ + + void __user *user_addr; /* user-space base-address */ + size_t user_size; /* size of memory area */ + + unsigned long nr_pages; + unsigned long fpage_offs; + size_t fpage_size; + size_t lpage_size; + + void *fpage; + dma_addr_t fpage_dma_addr; + + void *lpage; + dma_addr_t lpage_dma_addr; +}; + +int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + void __user *user_addr, size_t user_size); + +int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + dma_addr_t *dma_list); + +int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl); + /** * struct ddcb_requ - Kernel internal representation of the DDCB request * @cmd: User space representation of the DDCB execution request @@ -347,9 +385,7 @@ struct ddcb_requ { struct ddcb_queue *queue; /* associated queue */ struct dma_mapping dma_mappings[DDCB_FIXUPS]; - struct sg_entry *sgl[DDCB_FIXUPS]; - dma_addr_t sgl_dma_addr[DDCB_FIXUPS]; - size_t sgl_size[DDCB_FIXUPS]; + struct genwqe_sgl sgls[DDCB_FIXUPS]; /* kernel/user shared content */ struct genwqe_ddcb_cmd cmd; /* ddcb_no for this request */ @@ -453,22 +489,6 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, int genwqe_user_vunmap(struct genwqe_dev *cd, struct dma_mapping *m, struct ddcb_requ *req); -struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages, - dma_addr_t *dma_addr, size_t *sgl_size); - -void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list, - dma_addr_t dma_addr, size_t size); - -int genwqe_setup_sgl(struct genwqe_dev *cd, - unsigned long offs, - unsigned long size, - struct sg_entry *sgl, /* genwqe sgl */ - dma_addr_t dma_addr, size_t sgl_size, - dma_addr_t *dma_list, int page_offs, int num_pages); - -int genwqe_check_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list, - int size); - static inline bool dma_mapping_used(struct dma_mapping *m) { if (!m) diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index 0d05ca77c458dd..1d2f163a1906c2 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -840,15 +840,8 @@ static int ddcb_cmd_cleanup(struct genwqe_file *cfile, struct ddcb_requ *req) __genwqe_del_mapping(cfile, dma_map); genwqe_user_vunmap(cd, dma_map, req); } - if (req->sgl[i] != NULL) { - genwqe_free_sgl(cd, req->sgl[i], - req->sgl_dma_addr[i], - req->sgl_size[i]); - req->sgl[i] = NULL; - req->sgl_dma_addr[i] = 0x0; - req->sgl_size[i] = 0; - } - + if (req->sgls[i].sgl != NULL) + genwqe_free_sync_sgl(cd, &req->sgls[i]); } return 0; } @@ -917,7 +910,7 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req) case ATS_TYPE_SGL_RDWR: case ATS_TYPE_SGL_RD: { - int page_offs, nr_pages, offs; + int page_offs; u_addr = be64_to_cpu(*((__be64 *) &cmd->asiv[asiv_offs])); @@ -955,27 +948,18 @@ static int ddcb_cmd_fixups(struct genwqe_file *cfile, struct ddcb_requ *req) page_offs = 0; } - offs = offset_in_page(u_addr); - nr_pages = DIV_ROUND_UP(offs + u_size, PAGE_SIZE); - /* create genwqe style scatter gather list */ - req->sgl[i] = genwqe_alloc_sgl(cd, m->nr_pages, - &req->sgl_dma_addr[i], - &req->sgl_size[i]); - if (req->sgl[i] == NULL) { - rc = -ENOMEM; + rc = genwqe_alloc_sync_sgl(cd, &req->sgls[i], + (void __user *)u_addr, + u_size); + if (rc != 0) goto err_out; - } - genwqe_setup_sgl(cd, offs, u_size, - req->sgl[i], - req->sgl_dma_addr[i], - req->sgl_size[i], - m->dma_list, - page_offs, - nr_pages); + + genwqe_setup_sgl(cd, &req->sgls[i], + &m->dma_list[page_offs]); *((__be64 *)&cmd->asiv[asiv_offs]) = - cpu_to_be64(req->sgl_dma_addr[i]); + cpu_to_be64(req->sgls[i].sgl_dma_addr); break; } diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 6b1a6ef9f1a8c3..d049d271699cac 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -275,67 +275,107 @@ static int genwqe_sgl_size(int num_pages) return roundup(len, PAGE_SIZE); } -struct sg_entry *genwqe_alloc_sgl(struct genwqe_dev *cd, int num_pages, - dma_addr_t *dma_addr, size_t *sgl_size) +/** + * genwqe_alloc_sync_sgl() - Allocate memory for sgl and overlapping pages + * + * Allocates memory for sgl and overlapping pages. Pages which might + * overlap other user-space memory blocks are being cached for DMAs, + * such that we do not run into syncronization issues. Data is copied + * from user-space into the cached pages. + */ +int genwqe_alloc_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + void __user *user_addr, size_t user_size) { + int rc; struct pci_dev *pci_dev = cd->pci_dev; - struct sg_entry *sgl; - *sgl_size = genwqe_sgl_size(num_pages); - if (get_order(*sgl_size) > MAX_ORDER) { + sgl->fpage_offs = offset_in_page((unsigned long)user_addr); + sgl->fpage_size = min_t(size_t, PAGE_SIZE-sgl->fpage_offs, user_size); + sgl->nr_pages = DIV_ROUND_UP(sgl->fpage_offs + user_size, PAGE_SIZE); + sgl->lpage_size = (user_size - sgl->fpage_size) % PAGE_SIZE; + + dev_dbg(&pci_dev->dev, "[%s] uaddr=%p usize=%8ld nr_pages=%ld " + "fpage_offs=%lx fpage_size=%ld lpage_size=%ld\n", + __func__, user_addr, user_size, sgl->nr_pages, + sgl->fpage_offs, sgl->fpage_size, sgl->lpage_size); + + sgl->user_addr = user_addr; + sgl->user_size = user_size; + sgl->sgl_size = genwqe_sgl_size(sgl->nr_pages); + + if (get_order(sgl->sgl_size) > MAX_ORDER) { dev_err(&pci_dev->dev, "[%s] err: too much memory requested!\n", __func__); - return NULL; + return -ENOMEM; } - sgl = __genwqe_alloc_consistent(cd, *sgl_size, dma_addr); - if (sgl == NULL) { + sgl->sgl = __genwqe_alloc_consistent(cd, sgl->sgl_size, + &sgl->sgl_dma_addr); + if (sgl->sgl == NULL) { dev_err(&pci_dev->dev, "[%s] err: no memory available!\n", __func__); - return NULL; + return -ENOMEM; } - return sgl; + /* Only use buffering on incomplete pages */ + if ((sgl->fpage_size != 0) && (sgl->fpage_size != PAGE_SIZE)) { + sgl->fpage = __genwqe_alloc_consistent(cd, PAGE_SIZE, + &sgl->fpage_dma_addr); + if (sgl->fpage == NULL) + goto err_out; + + /* Sync with user memory */ + if (copy_from_user(sgl->fpage + sgl->fpage_offs, + user_addr, sgl->fpage_size)) { + rc = -EFAULT; + goto err_out; + } + } + if (sgl->lpage_size != 0) { + sgl->lpage = __genwqe_alloc_consistent(cd, PAGE_SIZE, + &sgl->lpage_dma_addr); + if (sgl->lpage == NULL) + goto err_out1; + + /* Sync with user memory */ + if (copy_from_user(sgl->lpage, user_addr + user_size - + sgl->lpage_size, sgl->lpage_size)) { + rc = -EFAULT; + goto err_out1; + } + } + return 0; + + err_out1: + __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage, + sgl->fpage_dma_addr); + err_out: + __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl, + sgl->sgl_dma_addr); + return -ENOMEM; } -int genwqe_setup_sgl(struct genwqe_dev *cd, - unsigned long offs, - unsigned long size, - struct sg_entry *sgl, - dma_addr_t dma_addr, size_t sgl_size, - dma_addr_t *dma_list, int page_offs, int num_pages) +int genwqe_setup_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl, + dma_addr_t *dma_list) { int i = 0, j = 0, p; unsigned long dma_offs, map_offs; - struct pci_dev *pci_dev = cd->pci_dev; dma_addr_t prev_daddr = 0; struct sg_entry *s, *last_s = NULL; - - /* sanity checks */ - if (offs > PAGE_SIZE) { - dev_err(&pci_dev->dev, - "[%s] too large start offs %08lx\n", __func__, offs); - return -EFAULT; - } - if (sgl_size < genwqe_sgl_size(num_pages)) { - dev_err(&pci_dev->dev, - "[%s] sgl_size too small %08lx for %d pages\n", - __func__, sgl_size, num_pages); - return -EFAULT; - } + size_t size = sgl->user_size; dma_offs = 128; /* next block if needed/dma_offset */ - map_offs = offs; /* offset in first page */ + map_offs = sgl->fpage_offs; /* offset in first page */ - s = &sgl[0]; /* first set of 8 entries */ + s = &sgl->sgl[0]; /* first set of 8 entries */ p = 0; /* page */ - while (p < num_pages) { + while (p < sgl->nr_pages) { dma_addr_t daddr; unsigned int size_to_map; /* always write the chaining entry, cleanup is done later */ j = 0; - s[j].target_addr = cpu_to_be64(dma_addr + dma_offs); + s[j].target_addr = cpu_to_be64(sgl->sgl_dma_addr + dma_offs); s[j].len = cpu_to_be32(128); s[j].flags = cpu_to_be32(SG_CHAINED); j++; @@ -343,7 +383,17 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, while (j < 8) { /* DMA mapping for requested page, offs, size */ size_to_map = min(size, PAGE_SIZE - map_offs); - daddr = dma_list[page_offs + p] + map_offs; + + if ((p == 0) && (sgl->fpage != NULL)) { + daddr = sgl->fpage_dma_addr + map_offs; + + } else if ((p == sgl->nr_pages - 1) && + (sgl->lpage != NULL)) { + daddr = sgl->lpage_dma_addr; + } else { + daddr = dma_list[p] + map_offs; + } + size -= size_to_map; map_offs = 0; @@ -358,7 +408,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, size_to_map); p++; /* process next page */ - if (p == num_pages) + if (p == sgl->nr_pages) goto fixup; /* nothing to do */ prev_daddr = daddr + size_to_map; @@ -374,7 +424,7 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, j++; p++; /* process next page */ - if (p == num_pages) + if (p == sgl->nr_pages) goto fixup; /* nothing to do */ } dma_offs += 128; @@ -395,10 +445,50 @@ int genwqe_setup_sgl(struct genwqe_dev *cd, return 0; } -void genwqe_free_sgl(struct genwqe_dev *cd, struct sg_entry *sg_list, - dma_addr_t dma_addr, size_t size) +/** + * genwqe_free_sync_sgl() - Free memory for sgl and overlapping pages + * + * After the DMA transfer has been completed we free the memory for + * the sgl and the cached pages. Data is being transfered from cached + * pages into user-space buffers. + */ +int genwqe_free_sync_sgl(struct genwqe_dev *cd, struct genwqe_sgl *sgl) { - __genwqe_free_consistent(cd, size, sg_list, dma_addr); + int rc; + struct pci_dev *pci_dev = cd->pci_dev; + + if (sgl->fpage) { + if (copy_to_user(sgl->user_addr, sgl->fpage + sgl->fpage_offs, + sgl->fpage_size)) { + dev_err(&pci_dev->dev, "[%s] err: copying fpage!\n", + __func__); + rc = -EFAULT; + } + __genwqe_free_consistent(cd, PAGE_SIZE, sgl->fpage, + sgl->fpage_dma_addr); + sgl->fpage = NULL; + sgl->fpage_dma_addr = 0; + } + if (sgl->lpage) { + if (copy_to_user(sgl->user_addr + sgl->user_size - + sgl->lpage_size, sgl->lpage, + sgl->lpage_size)) { + dev_err(&pci_dev->dev, "[%s] err: copying lpage!\n", + __func__); + rc = -EFAULT; + } + __genwqe_free_consistent(cd, PAGE_SIZE, sgl->lpage, + sgl->lpage_dma_addr); + sgl->lpage = NULL; + sgl->lpage_dma_addr = 0; + } + __genwqe_free_consistent(cd, sgl->sgl_size, sgl->sgl, + sgl->sgl_dma_addr); + + sgl->sgl = NULL; + sgl->sgl_dma_addr = 0x0; + sgl->sgl_size = 0; + return rc; } /** From 73590a25ba6f55eecde4ffbbbc53835d7ccf5402 Mon Sep 17 00:00:00 2001 From: Frank Haverkamp Date: Thu, 20 Mar 2014 15:11:06 +0100 Subject: [PATCH 158/279] GenWQE: Increase driver version number Increase genwqe driver version number. Signed-off-by: Frank Haverkamp Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/genwqe_driver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/misc/genwqe/genwqe_driver.h b/drivers/misc/genwqe/genwqe_driver.h index 46e916b36c7089..cd5263163a6e5c 100644 --- a/drivers/misc/genwqe/genwqe_driver.h +++ b/drivers/misc/genwqe/genwqe_driver.h @@ -36,7 +36,7 @@ #include #include -#define DRV_VERS_STRING "2.0.0" +#define DRV_VERS_STRING "2.0.15" /* * Static minor number assignement, until we decide/implement From b7c0ddf5f270b2a3c0af326cb300eb17175d58e3 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Wed, 16 Apr 2014 09:32:48 +0200 Subject: [PATCH 159/279] net: use SYSCALL_DEFINEx for sys_recv Make sys_recv a first class citizen by using the SYSCALL_DEFINEx macro. Besides being cleaner this will also generate meta data for the system call so tracing tools like ftrace or LTTng can resolve this system call. Signed-off-by: Jan Glauber Signed-off-by: David S. Miller --- net/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/socket.c b/net/socket.c index 1b1e7e6a960faa..abf56b2a14f9bc 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1880,8 +1880,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, * Receive a datagram from a socket. */ -asmlinkage long sys_recv(int fd, void __user *ubuf, size_t size, - unsigned int flags) +SYSCALL_DEFINE4(recv, int, fd, void __user *, ubuf, size_t, size, + unsigned int, flags) { return sys_recvfrom(fd, ubuf, size, flags, NULL, NULL); } From 8c923ce219b775cc659a31616590afee239a84e5 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 16 Apr 2014 11:19:32 +0200 Subject: [PATCH 160/279] ip_tunnel: use the right netns in ioctl handler Because the netdevice may be in another netns than the i/o netns, we should use the i/o netns instead of dev_net(dev). The variable 'tunnel' was used only to get 'itn', hence to simplify code I remove it and use 't' instead. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv4/ip_tunnel.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 484d0ce27ef7d1..fa5b7519765f10 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -722,19 +722,18 @@ static void ip_tunnel_update(struct ip_tunnel_net *itn, int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) { int err = 0; - struct ip_tunnel *t; - struct net *net = dev_net(dev); - struct ip_tunnel *tunnel = netdev_priv(dev); - struct ip_tunnel_net *itn = net_generic(net, tunnel->ip_tnl_net_id); + struct ip_tunnel *t = netdev_priv(dev); + struct net *net = t->net; + struct ip_tunnel_net *itn = net_generic(net, t->ip_tnl_net_id); BUG_ON(!itn->fb_tunnel_dev); switch (cmd) { case SIOCGETTUNNEL: - t = NULL; - if (dev == itn->fb_tunnel_dev) + if (dev == itn->fb_tunnel_dev) { t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); - if (t == NULL) - t = netdev_priv(dev); + if (t == NULL) + t = netdev_priv(dev); + } memcpy(p, &t->parms, sizeof(*p)); break; From 9aad77c3b5cc9151d356b66ee8533e85ca7da192 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 16 Apr 2014 11:19:33 +0200 Subject: [PATCH 161/279] sit: use the right netns in ioctl handler Because the netdevice may be in another netns than the i/o netns, we should use the i/o netns instead of dev_net(dev). Note that netdev_priv(dev) cannot bu NULL, hence we can remove these useless checks. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/sit.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 8da8268d65f8e9..e5a453ca302e1e 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1127,8 +1127,8 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) int err = 0; struct ip_tunnel_parm p; struct ip_tunnel_prl prl; - struct ip_tunnel *t; - struct net *net = dev_net(dev); + struct ip_tunnel *t = netdev_priv(dev); + struct net *net = t->net; struct sit_net *sitn = net_generic(net, sit_net_id); #ifdef CONFIG_IPV6_SIT_6RD struct ip_tunnel_6rd ip6rd; @@ -1139,16 +1139,15 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) #ifdef CONFIG_IPV6_SIT_6RD case SIOCGET6RD: #endif - t = NULL; if (dev == sitn->fb_tunnel_dev) { if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { err = -EFAULT; break; } t = ipip6_tunnel_locate(net, &p, 0); + if (t == NULL) + t = netdev_priv(dev); } - if (t == NULL) - t = netdev_priv(dev); err = -EFAULT; if (cmd == SIOCGETTUNNEL) { @@ -1244,9 +1243,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EINVAL; if (dev == sitn->fb_tunnel_dev) goto done; - err = -ENOENT; - if (!(t = netdev_priv(dev))) - goto done; err = ipip6_tunnel_get_prl(t, ifr->ifr_ifru.ifru_data); break; @@ -1262,9 +1258,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) err = -EFAULT; if (copy_from_user(&prl, ifr->ifr_ifru.ifru_data, sizeof(prl))) goto done; - err = -ENOENT; - if (!(t = netdev_priv(dev))) - goto done; switch (cmd) { case SIOCDELPRL: @@ -1292,8 +1285,6 @@ ipip6_tunnel_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd) sizeof(ip6rd))) goto done; - t = netdev_priv(dev); - if (cmd != SIOCDEL6RD) { err = ipip6_tunnel_update_6rd(t, &ip6rd); if (err < 0) From 74462f0d4a734274a04dbbe58099134cbe7a5522 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 16 Apr 2014 11:19:34 +0200 Subject: [PATCH 162/279] ip6_tunnel: use the right netns in ioctl handler Because the netdevice may be in another netns than the i/o netns, we should use the i/o netns instead of dev_net(dev). Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index e1df691d78befc..b05b609f69d1cd 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1340,8 +1340,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) int err = 0; struct ip6_tnl_parm p; struct __ip6_tnl_parm p1; - struct ip6_tnl *t = NULL; - struct net *net = dev_net(dev); + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); switch (cmd) { @@ -1353,11 +1353,11 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } ip6_tnl_parm_from_user(&p1, &p); t = ip6_tnl_locate(net, &p1, 0); + if (t == NULL) + t = netdev_priv(dev); } else { memset(&p, 0, sizeof(p)); } - if (t == NULL) - t = netdev_priv(dev); ip6_tnl_parm_to_user(&p, &t->parms); if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { err = -EFAULT; From b7a314054eb55e3745a9409beaa5d8be5cd2d273 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 16 Apr 2014 14:25:16 +0300 Subject: [PATCH 163/279] isdn: icn: buffer overflow in icn_command() This buffer over was detected using static analysis: drivers/isdn/icn/icn.c:1325 icn_command() error: format string overflow. buf_size: 60 length: 98 The calculation for the length of the string is off because it assumes that the dial[] buffer holds a 50 character string, but actually it is at most 31 characters and NUL. I have removed the dial[] buffer because it isn't needed. The maximum length of the string is actually 79 characters and a NUL. I have made the cbuf[] array large enough to hold it and changed the sprintf() to an snprintf() as a further safety enhancement. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- drivers/isdn/icn/icn.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c index 53d487f0c79ddf..6a7447c304acc3 100644 --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -1155,7 +1155,7 @@ icn_command(isdn_ctrl *c, icn_card *card) ulong a; ulong flags; int i; - char cbuf[60]; + char cbuf[80]; isdn_ctrl cmd; icn_cdef cdef; char __user *arg; @@ -1309,7 +1309,6 @@ icn_command(isdn_ctrl *c, icn_card *card) break; if ((c->arg & 255) < ICN_BCH) { char *p; - char dial[50]; char dcode[4]; a = c->arg; @@ -1321,10 +1320,10 @@ icn_command(isdn_ctrl *c, icn_card *card) } else /* Normal Dial */ strcpy(dcode, "CAL"); - strcpy(dial, p); - sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), - dcode, dial, c->parm.setup.si1, - c->parm.setup.si2, c->parm.setup.eazmsn); + snprintf(cbuf, sizeof(cbuf), + "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), + dcode, p, c->parm.setup.si1, + c->parm.setup.si2, c->parm.setup.eazmsn); i = icn_writecmd(cbuf, strlen(cbuf), 0, card); } break; From 5e6533a6f52f1a8283b2f818f5828be99a417dd6 Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Tue, 25 Mar 2014 21:25:18 +0200 Subject: [PATCH 164/279] mei: me: do not load the driver if the FW doesn't support MEI interface NM and SPS FW types that may run on ME device on server platforms do not have valid MEI/HECI interface and driver should not be bound to it as this might lead to system hung. In practice not all BIOSes effectively hide such devices from the OS and in some cases it is not possible. We determine FW type by examining Host FW status registers in order to unbind the driver. In this patch we are adding check for ME on Cougar Point, Lynx Point Devices Cc: stable # 3.10+ Signed-off-by: Tomas Winkler Tested-by: Nikola Ciprich Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/hw-me-regs.h | 5 +++++ drivers/misc/mei/pci-me.c | 30 +++++++++++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index 66f411a6e8ea50..cabc04383685d4 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -115,6 +115,11 @@ #define MEI_DEV_ID_LPT_HR 0x8CBA /* Lynx Point H Refresh */ #define MEI_DEV_ID_WPT_LP 0x9CBA /* Wildcat Point LP */ + +/* Host Firmware Status Registers in PCI Config Space */ +#define PCI_CFG_HFS_1 0x40 +#define PCI_CFG_HFS_2 0x48 + /* * MEI HW Section */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 1c8fd3a3e135d2..95889e2e31ffd1 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -97,15 +97,31 @@ static bool mei_me_quirk_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { u32 reg; - if (ent->device == MEI_DEV_ID_PBG_1) { - pci_read_config_dword(pdev, 0x48, ®); - /* make sure that bit 9 is up and bit 10 is down */ - if ((reg & 0x600) == 0x200) { - dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); - return false; - } + /* Cougar Point || Patsburg */ + if (ent->device == MEI_DEV_ID_CPT_1 || + ent->device == MEI_DEV_ID_PBG_1) { + pci_read_config_dword(pdev, PCI_CFG_HFS_2, ®); + /* make sure that bit 9 (NM) is up and bit 10 (DM) is down */ + if ((reg & 0x600) == 0x200) + goto no_mei; } + + /* Lynx Point */ + if (ent->device == MEI_DEV_ID_LPT_H || + ent->device == MEI_DEV_ID_LPT_W || + ent->device == MEI_DEV_ID_LPT_HR) { + /* Read ME FW Status check for SPS Firmware */ + pci_read_config_dword(pdev, PCI_CFG_HFS_1, ®); + /* if bits [19:16] = 15, running SPS Firmware */ + if ((reg & 0xf0000) == 0xf0000) + goto no_mei; + } + return true; + +no_mei: + dev_info(&pdev->dev, "Device doesn't have valid ME Interface\n"); + return false; } /** * mei_probe - Device Initialization Routine From 34ec43661fe8f1977dd0f05353302ae2ed10aabb Mon Sep 17 00:00:00 2001 From: Alexander Usyskin Date: Tue, 1 Apr 2014 23:50:41 +0300 Subject: [PATCH 165/279] mei: ignore client writing state during cb completion Ignore client writing state during cb completion to fix a memory leak. When moving cbs to the completion list we should not look at writing_state as this state can be already overwritten by next write, the fact that a cb is on the write waiting list means that it was already written to the HW and we can safely complete it. Same pays for wait in poll handler, we do not have to check the state wake is done after completion list processing. Cc: stable@vger.kernel.org Signed-off-by: Alexander Usyskin Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/interrupt.c | 3 +-- drivers/misc/mei/main.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 29b5af8efb71f3..4e3cba6da3f5cc 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c @@ -455,8 +455,7 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) cl->status = 0; list_del(&cb->list); - if (MEI_WRITING == cl->writing_state && - cb->fop_type == MEI_FOP_WRITE && + if (cb->fop_type == MEI_FOP_WRITE && cl != &dev->iamthif_cl) { cl_dbg(dev, cl, "MEI WRITE COMPLETE\n"); cl->writing_state = MEI_WRITE_COMPLETE; diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index b35594dbf52f49..147413145c97d8 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -644,8 +644,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) goto out; } - if (MEI_WRITE_COMPLETE == cl->writing_state) - mask |= (POLLIN | POLLRDNORM); + mask |= (POLLIN | POLLRDNORM); out: mutex_unlock(&dev->device_lock); From 0acf07d240a84069c4a6651e6030cf35d30c7159 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 16 Apr 2014 10:54:34 -0700 Subject: [PATCH 166/279] seccomp: fix memory leak on filter attach This sets the correct error code when final filter memory is unavailable, and frees the raw filter no matter what. unreferenced object 0xffff8800d6ea4000 (size 512): comm "sshd", pid 278, jiffies 4294898315 (age 46.653s) hex dump (first 32 bytes): 21 00 00 00 04 00 00 00 15 00 01 00 3e 00 00 c0 !...........>... 06 00 00 00 00 00 00 00 21 00 00 00 00 00 00 00 ........!....... backtrace: [] kmemleak_alloc+0x4e/0xb0 [] __kmalloc+0x280/0x320 [] prctl_set_seccomp+0x11e/0x3b0 [] SyS_prctl+0x3bb/0x4a0 [] system_call_fastpath+0x1a/0x1f [] 0xffffffffffffffff Reported-by: Masami Ichikawa Signed-off-by: Kees Cook Tested-by: Masami Ichikawa Acked-by: Daniel Borkmann Signed-off-by: David S. Miller --- kernel/seccomp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 590c37925084d0..b35c21503a36d6 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -255,6 +255,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) goto free_prog; /* Allocate a new seccomp_filter */ + ret = -ENOMEM; filter = kzalloc(sizeof(struct seccomp_filter) + sizeof(struct sock_filter_int) * new_len, GFP_KERNEL|__GFP_NOWARN); @@ -264,6 +265,7 @@ static long seccomp_attach_filter(struct sock_fprog *fprog) ret = sk_convert_filter(fp, fprog->len, filter->insnsi, &new_len); if (ret) goto free_filter; + kfree(fp); atomic_set(&filter->usage, 1); filter->len = new_len; From 7c7352827343b377446bb59b844d387df665e401 Mon Sep 17 00:00:00 2001 From: Christoph Jaeger Date: Fri, 11 Apr 2014 18:40:05 +0200 Subject: [PATCH 167/279] drivers: mcb: fix memory leak in chameleon_parse_cells() error path chameleon_parse_cells() bails out if chameleon descriptor type is invalid but does not free the storage 'header' points to. Signed-off-by: Christoph Jaeger Signed-off-by: Johannes Thumshirn Signed-off-by: Greg Kroah-Hartman --- drivers/mcb/mcb-parse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c index d1278b5f3028db..00492695526354 100644 --- a/drivers/mcb/mcb-parse.c +++ b/drivers/mcb/mcb-parse.c @@ -141,6 +141,7 @@ int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, default: pr_err("Invalid chameleon descriptor type 0x%x\n", dtype); + kfree(header); return -EINVAL; } num_cells++; From a82cb8b91a37b6015f171a90dc4670e4c8e12e12 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Apr 2014 18:55:49 +0200 Subject: [PATCH 168/279] misc: Grammar s/addition/additional/ Signed-off-by: Geert Uytterhoeven Cc: Arnd Bergmann Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 1cb74085e41094..8baff0effc7dfa 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -300,8 +300,8 @@ config SGI_GRU_DEBUG depends on SGI_GRU default n ---help--- - This option enables addition debugging code for the SGI GRU driver. If - you are unsure, say N. + This option enables additional debugging code for the SGI GRU driver. + If you are unsure, say N. config APDS9802ALS tristate "Medfield Avago APDS9802 ALS Sensor module" From f764cd68d9036498f08fe8834deb6a367b5c2542 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 16 Apr 2014 14:49:33 -0500 Subject: [PATCH 169/279] staging: r8712u: Fix case where ethtype was never obtained and always be checked against 0 Zero-initializing ether_type masked that the ether type would never be obtained for 8021x packets and the comparison against eapol_type would always fail. Reported-by: Jes Sorensen Signed-off-by: Larry Finger Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8712/rtl871x_recv.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c index 23ec684b60e1af..274c359279ef38 100644 --- a/drivers/staging/rtl8712/rtl871x_recv.c +++ b/drivers/staging/rtl8712/rtl871x_recv.c @@ -254,7 +254,7 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, struct sta_info *psta; struct sta_priv *pstapriv; union recv_frame *prtnframe; - u16 ether_type = 0; + u16 ether_type; pstapriv = &adapter->stapriv; ptr = get_recvframe_data(precv_frame); @@ -263,15 +263,14 @@ union recv_frame *r8712_portctrl(struct _adapter *adapter, psta = r8712_get_stainfo(pstapriv, psta_addr); auth_alg = adapter->securitypriv.AuthAlgrthm; if (auth_alg == 2) { + /* get ether_type */ + ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; + memcpy(ðer_type, ptr, 2); + ether_type = ntohs((unsigned short)ether_type); + if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked * only accept EAPOL frame */ - prtnframe = precv_frame; - /*get ether_type */ - ptr = ptr + pfhdr->attrib.hdrlen + - pfhdr->attrib.iv_len + LLC_HEADER_SIZE; - memcpy(ðer_type, ptr, 2); - ether_type = ntohs((unsigned short)ether_type); if (ether_type == 0x888e) prtnframe = precv_frame; else { From 33c84bc14c25074ac14644cf7db75a57e9abaf1a Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 16 Apr 2014 14:49:34 -0500 Subject: [PATCH 170/279] staging: r8188eu: Fix case where ethtype was never obtained and always be checked against 0 Zero-initializing ether_type masked that the ether type would never be obtained for 8021x packets and the comparison against eapol_type would always fail. Reported-by: Jes Sorensen Signed-off-by: Larry Finger Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8188eu/core/rtw_recv.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/staging/rtl8188eu/core/rtw_recv.c b/drivers/staging/rtl8188eu/core/rtw_recv.c index 01fcabcc8e5648..e305d43ebd0656 100644 --- a/drivers/staging/rtl8188eu/core/rtw_recv.c +++ b/drivers/staging/rtl8188eu/core/rtw_recv.c @@ -551,10 +551,9 @@ static struct recv_frame *portctrl(struct adapter *adapter, struct sta_info *psta; struct sta_priv *pstapriv; struct recv_frame *prtnframe; - u16 ether_type = 0; + u16 ether_type; u16 eapol_type = 0x888e;/* for Funia BD's WPA issue */ struct rx_pkt_attrib *pattrib; - __be16 be_tmp; pstapriv = &adapter->stapriv; @@ -572,18 +571,16 @@ static struct recv_frame *portctrl(struct adapter *adapter, RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n", adapter->securitypriv.dot11AuthAlgrthm)); if (auth_alg == 2) { + /* get ether_type */ + ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE; + memcpy(ðer_type, ptr, 2); + ether_type = ntohs((unsigned short)ether_type); + if ((psta != NULL) && (psta->ieee8021x_blocked)) { /* blocked */ /* only accept EAPOL frame */ RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked==1\n")); - prtnframe = precv_frame; - - /* get ether_type */ - ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE; - memcpy(&be_tmp, ptr, 2); - ether_type = ntohs(be_tmp); - if (ether_type == eapol_type) { prtnframe = precv_frame; } else { From efe26e16b1d93ac0085e69178cc18811629e8fc5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 31 Mar 2014 10:51:00 +0200 Subject: [PATCH 171/279] USB: serial: ftdi_sio: add id for Brainboxes serial cards Custom VID/PIDs for Brainboxes cards as reported in https://bugzilla.redhat.com/show_bug.cgi?id=1071914 Signed-off-by: Michele Baldessari Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 33 +++++++++++++++++++++++++++ drivers/usb/serial/ftdi_sio_ids.h | 37 +++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 44ab1298680557..7c6e1dedeb0684 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -909,6 +909,39 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, /* Cressi Devices */ { USB_DEVICE(FTDI_VID, FTDI_CRESSI_PID) }, + /* Brainboxes Devices */ + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_001_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_012_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_023_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_VX_034_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_101_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_4_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_5_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_6_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_7_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_160_8_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_257_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_279_4_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_313_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_324_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_346_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_357_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_606_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_701_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_1_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_2_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_3_PID) }, + { USB_DEVICE(BRAINBOXES_VID, BRAINBOXES_US_842_4_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index e599fbfcde5f8f..993c93df687482 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1326,3 +1326,40 @@ * Manufacturer: Cressi */ #define FTDI_CRESSI_PID 0x87d0 + +/* + * Brainboxes devices + */ +#define BRAINBOXES_VID 0x05d1 +#define BRAINBOXES_VX_001_PID 0x1001 /* VX-001 ExpressCard 1 Port RS232 */ +#define BRAINBOXES_VX_012_PID 0x1002 /* VX-012 ExpressCard 2 Port RS232 */ +#define BRAINBOXES_VX_023_PID 0x1003 /* VX-023 ExpressCard 1 Port RS422/485 */ +#define BRAINBOXES_VX_034_PID 0x1004 /* VX-034 ExpressCard 2 Port RS422/485 */ +#define BRAINBOXES_US_101_PID 0x1011 /* US-101 1xRS232 */ +#define BRAINBOXES_US_324_PID 0x1013 /* US-324 1xRS422/485 1Mbaud */ +#define BRAINBOXES_US_606_1_PID 0x2001 /* US-606 6 Port RS232 Serial Port 1 and 2 */ +#define BRAINBOXES_US_606_2_PID 0x2002 /* US-606 6 Port RS232 Serial Port 3 and 4 */ +#define BRAINBOXES_US_606_3_PID 0x2003 /* US-606 6 Port RS232 Serial Port 4 and 6 */ +#define BRAINBOXES_US_701_1_PID 0x2011 /* US-701 4xRS232 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_701_2_PID 0x2012 /* US-701 4xRS422 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_279_1_PID 0x2021 /* US-279 8xRS422 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_279_2_PID 0x2022 /* US-279 8xRS422 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_279_3_PID 0x2023 /* US-279 8xRS422 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_279_4_PID 0x2024 /* US-279 8xRS422 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_346_1_PID 0x3011 /* US-346 4xRS422/485 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_346_2_PID 0x3012 /* US-346 4xRS422/485 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_257_PID 0x5001 /* US-257 2xRS232 1Mbaud */ +#define BRAINBOXES_US_313_PID 0x6001 /* US-313 2xRS422/485 1Mbaud */ +#define BRAINBOXES_US_357_PID 0x7001 /* US_357 1xRS232/422/485 */ +#define BRAINBOXES_US_842_1_PID 0x8001 /* US-842 8xRS422/485 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_842_2_PID 0x8002 /* US-842 8xRS422/485 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_842_3_PID 0x8003 /* US-842 8xRS422/485 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_842_4_PID 0x8004 /* US-842 8xRS422/485 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_160_1_PID 0x9001 /* US-160 16xRS232 1Mbaud Port 1 and 2 */ +#define BRAINBOXES_US_160_2_PID 0x9002 /* US-160 16xRS232 1Mbaud Port 3 and 4 */ +#define BRAINBOXES_US_160_3_PID 0x9003 /* US-160 16xRS232 1Mbaud Port 5 and 6 */ +#define BRAINBOXES_US_160_4_PID 0x9004 /* US-160 16xRS232 1Mbaud Port 7 and 8 */ +#define BRAINBOXES_US_160_5_PID 0x9005 /* US-160 16xRS232 1Mbaud Port 9 and 10 */ +#define BRAINBOXES_US_160_6_PID 0x9006 /* US-160 16xRS232 1Mbaud Port 11 and 12 */ +#define BRAINBOXES_US_160_7_PID 0x9007 /* US-160 16xRS232 1Mbaud Port 13 and 14 */ +#define BRAINBOXES_US_160_8_PID 0x9008 /* US-160 16xRS232 1Mbaud Port 15 and 16 */ From 2e01280d2801c72878cf3a7119eac30077b463d5 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Fri, 28 Mar 2014 18:05:10 +0100 Subject: [PATCH 172/279] Revert "USB: serial: add usbid for dell wwan card to sierra.c" This reverts commit 1ebca9dad5abe8b2ed4dbd186cd657fb47c1f321. This device was erroneously added to the sierra driver even though it's not a Sierra device and was already handled by the option driver. Cc: Richard Farina Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/sierra.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index a9eb6221a8155a..6b192e602ce0a9 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -291,7 +291,6 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, - { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */ { } }; From d6de486bc22255779bd54b0fceb4c240962bf146 Mon Sep 17 00:00:00 2001 From: Daniele Palmas Date: Wed, 2 Apr 2014 11:19:48 +0200 Subject: [PATCH 173/279] usb: option driver, add support for Telit UE910v2 option driver, added VID/PID for Telit UE910v2 modem Signed-off-by: Daniele Palmas Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 68fc9fe65936e7..367c7f08b27c53 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -243,6 +243,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_DUAL 0x1005 #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 +#define TELIT_PRODUCT_UE910_V2 0x1012 #define TELIT_PRODUCT_LE920 0x1200 /* ZTE PRODUCTS */ @@ -1041,6 +1042,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ From 72b3007951010ce1bbf950e23b19d9839fa905a5 Mon Sep 17 00:00:00 2001 From: Tristan Bruns Date: Sun, 13 Apr 2014 23:57:16 +0200 Subject: [PATCH 174/279] USB: cp210x: Add 8281 (Nanotec Plug & Drive) Signed-off-by: Tristan Bruns Cc: stable Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 95fa1217afdd7e..762e4a5f5ae9dd 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -104,6 +104,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */ + { USB_DEVICE(0x10C4, 0x8281) }, /* Nanotec Plug & Drive */ { USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */ { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ From b16c02fbfb963fa2941b7517ebf1f8a21946775e Mon Sep 17 00:00:00 2001 From: Aaron Sanders Date: Mon, 31 Mar 2014 15:54:21 +0200 Subject: [PATCH 175/279] USB: pl2303: add ids for Hewlett-Packard HP POS pole displays Add device ids to pl2303 for the Hewlett-Packard HP POS pole displays: LD960: 03f0:0B39 LCM220: 03f0:3139 LCM960: 03f0:3239 [ Johan: fix indentation and sort PIDs numerically ] Signed-off-by: Aaron Sanders Cc: stable@vger.kernel.org Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/pl2303.c | 3 +++ drivers/usb/serial/pl2303.h | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 2e22fc22c3822f..b3d5a35c0d4b2e 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -83,6 +83,9 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LD960_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LCM220_PRODUCT_ID) }, + { USB_DEVICE(HP_VENDOR_ID, HP_LCM960_PRODUCT_ID) }, { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, { USB_DEVICE(ZEAGLE_VENDOR_ID, ZEAGLE_N2ITION3_PRODUCT_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index c38b8c00c06fdd..42bc082896ac8e 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -121,8 +121,11 @@ #define SUPERIAL_VENDOR_ID 0x5372 #define SUPERIAL_PRODUCT_ID 0x2303 -/* Hewlett-Packard LD220-HP POS Pole Display */ +/* Hewlett-Packard POS Pole Displays */ #define HP_VENDOR_ID 0x03f0 +#define HP_LD960_PRODUCT_ID 0x0b39 +#define HP_LCM220_PRODUCT_ID 0x3139 +#define HP_LCM960_PRODUCT_ID 0x3239 #define HP_LD220_PRODUCT_ID 0x3524 /* Cressi Edy (diving computer) PC interface */ From bd73bd8831696f189a479a0712ae95208e513d7e Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Thu, 3 Apr 2014 13:06:46 +0200 Subject: [PATCH 176/279] USB: usb_wwan: fix handling of missing bulk endpoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix regression introduced by commit 8e493ca1767d ("USB: usb_wwan: fix bulk-urb allocation") by making sure to require both bulk-in and out endpoints during port probe. The original option driver (which usb_wwan is based on) was written under the assumption that either endpoint could be missing, but evidently this cannot have been tested properly. Specifically, it would handle opening a device without bulk-in (but would blow up during resume which was implemented later), but not a missing bulk-out in write() (although it is handled in some places such as write_room()). Fortunately (?), the driver also got the test for missing endpoints wrong so the urbs were in fact always allocated, although they would be initialised using the wrong endpoint address (0) and any submission of such an urb would fail. The commit mentioned above fixed the test for missing endpoints but thereby exposed the other bugs which would now generate null-pointer exceptions rather than failed urb submissions. The regression was introduced in v3.7, but the offending commit was also marked for stable. Reported-by: Rafał Miłecki Cc: stable Signed-off-by: Johan Hovold Tested-by: Rafał Miłecki Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb_wwan.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 640fe017323680..b078440e822f2b 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -466,6 +466,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port) int err; int i; + if (!port->bulk_in_size || !port->bulk_out_size) + return -ENODEV; + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); if (!portdata) return -ENOMEM; @@ -473,9 +476,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port) init_usb_anchor(&portdata->delayed); for (i = 0; i < N_IN_URB; i++) { - if (!port->bulk_in_size) - break; - buffer = (u8 *)__get_free_page(GFP_KERNEL); if (!buffer) goto bail_out_error; @@ -489,9 +489,6 @@ int usb_wwan_port_probe(struct usb_serial_port *port) } for (i = 0; i < N_OUT_URB; i++) { - if (!port->bulk_out_size) - break; - buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL); if (!buffer) goto bail_out_error2; From f9076e28013e448ba2a905ae905ac9b53f8a2e16 Mon Sep 17 00:00:00 2001 From: Peter Chen Date: Wed, 9 Apr 2014 14:48:58 +0800 Subject: [PATCH 177/279] usb: usb-common: fix typo for usb_state_string %s/addresssed/addressed Signed-off-by: Peter Chen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usb-common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/usb-common.c b/drivers/usb/usb-common.c index d771870a819e52..6dfd30a863c797 100644 --- a/drivers/usb/usb-common.c +++ b/drivers/usb/usb-common.c @@ -69,7 +69,7 @@ const char *usb_state_string(enum usb_device_state state) [USB_STATE_RECONNECTING] = "reconnecting", [USB_STATE_UNAUTHENTICATED] = "unauthenticated", [USB_STATE_DEFAULT] = "default", - [USB_STATE_ADDRESS] = "addresssed", + [USB_STATE_ADDRESS] = "addressed", [USB_STATE_CONFIGURED] = "configured", [USB_STATE_SUSPENDED] = "suspended", }; From 070c0b17f6a1ba39dff9be112218127e7e8fd456 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Sat, 12 Apr 2014 02:10:45 +0400 Subject: [PATCH 178/279] USB: cdc-acm: fix double usb_autopm_put_interface() in acm_port_activate() If acm_submit_read_urbs() fails in acm_port_activate(), error handling code calls usb_autopm_put_interface() while it is already called before acm_submit_read_urbs(). The patch reorganizes error handling code to avoid double decrement of USB interface's PM-usage counter. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 900f7ff805eef5..d5d2c922186afb 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -518,13 +518,16 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { dev_err(&acm->control->dev, "%s - usb_submit_urb(ctrl irq) failed\n", __func__); + usb_autopm_put_interface(acm->control); goto error_submit_urb; } acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS; if (acm_set_control(acm, acm->ctrlout) < 0 && - (acm->ctrl_caps & USB_CDC_CAP_LINE)) + (acm->ctrl_caps & USB_CDC_CAP_LINE)) { + usb_autopm_put_interface(acm->control); goto error_set_control; + } usb_autopm_put_interface(acm->control); @@ -549,7 +552,6 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) error_set_control: usb_kill_urb(acm->ctrlurb); error_submit_urb: - usb_autopm_put_interface(acm->control); error_get_interface: disconnected: mutex_unlock(&acm->mutex); From a2ff864b53eac9a0e9b05bfe9d1781ccd6c2af71 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 14 Apr 2014 13:48:47 -0400 Subject: [PATCH 179/279] USB: fix crash during hotplug of PCI USB controller card The code in hcd-pci.c that matches up EHCI controllers with their companion UHCI or OHCI controllers assumes that the private drvdata fields don't get set too early. However, it turns out that this field gets set by usb_create_hcd(), before hcd-pci expects it, and this can result in a crash when two controllers are probed in parallel (as can happen when a new controller card is hotplugged). The companions_rwsem lock was supposed to prevent this sort of thing, but usb_create_hcd() is called outside the scope of the rwsem. A simple solution is to check that the root-hub pointer has been initialized as well as the drvdata field. This doesn't happen until usb_add_hcd() is called; that call and the check are both protected by the rwsem. This patch should be applied to stable kernels from 3.10 onward. Signed-off-by: Alan Stern Reported-by: Stefani Seibold Tested-by: Stefani Seibold CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd-pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index d59d99347d543b..1f02e65fe3056e 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -75,7 +75,7 @@ static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd, PCI_SLOT(companion->devfn) != slot) continue; companion_hcd = pci_get_drvdata(companion); - if (!companion_hcd) + if (!companion_hcd || !companion_hcd->self.root_hub) continue; fn(pdev, hcd, companion, companion_hcd); } From d72175103f25783b0504f864a4f381621a789ca2 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Thu, 10 Apr 2014 15:58:01 +0530 Subject: [PATCH 180/279] usb: ehci-exynos: Return immediately from suspend if ehci_suspend fails Patch 'b8efdaf USB: EHCI: add check for wakeup/suspend race' adds a check for possible race between suspend and wakeup interrupt, and thereby it returns -EBUSY as error code if there's a wakeup interrupt. So the platform host controller should not proceed further with its suspend callback, rather should return immediately to avoid powering down the essential things, like phy. Signed-off-by: Vivek Gautam Acked-by: Jingoo Han Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-exynos.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c index d1d8c47777c589..7f425acd9be5e1 100644 --- a/drivers/usb/host/ehci-exynos.c +++ b/drivers/usb/host/ehci-exynos.c @@ -212,6 +212,8 @@ static int exynos_ehci_suspend(struct device *dev) int rc; rc = ehci_suspend(hcd, do_wakeup); + if (rc) + return rc; if (exynos_ehci->otg) exynos_ehci->otg->set_host(exynos_ehci->otg, &hcd->self); From e155b5b8d2d42455d3a94c2460c287e97184ec61 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Thu, 10 Apr 2014 15:58:02 +0530 Subject: [PATCH 181/279] usb: ehci-platform: Return immediately from suspend if ehci_suspend fails Patch 'b8efdaf USB: EHCI: add check for wakeup/suspend race' adds a check for possible race between suspend and wakeup interrupt, and thereby it returns -EBUSY as error code if there's a wakeup interrupt. So the platform host controller should not proceed further with its suspend callback, rather should return immediately to avoid powering down the essential things, like phy. Signed-off-by: Vivek Gautam Acked-by: Alan Stern Cc: Hauke Mehrtens Cc: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-platform.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index b3a0e11073aae8..c7dd93aad20c59 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -303,6 +303,8 @@ static int ehci_platform_suspend(struct device *dev) int ret; ret = ehci_suspend(hcd, do_wakeup); + if (ret) + return ret; if (pdata->power_suspend) pdata->power_suspend(pdev); From 4f2fe2d27472f4a5dbd875888af4fc5175f3fdc5 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Mon, 14 Apr 2014 15:21:23 -0600 Subject: [PATCH 182/279] USB: EHCI: tegra: set txfill_tuning To avoid memory fetch underflows with larger USB transfers, Tegra SoCs need txfill_tuning's txfifothresh register field set to a non-default value. Add a custom reset override in order to set this up. These values are recommended practice for all Tegra chips. However, I've only noticed practical problems when not setting them this way on systems using Tegra124. Hence, CC: stable only for recent kernels which actually support Tegra124. Cc: # 3.14+ Signed-off-by: Stephen Warren Acked-by: Alan Stern Tested-by: Alexandre Courbot Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-tegra.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 27ac6ad53c3d9e..7ef00ecb0da10e 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -509,8 +509,31 @@ static struct platform_driver tegra_ehci_driver = { } }; +static int tegra_ehci_reset(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + int retval; + int txfifothresh; + + retval = ehci_setup(hcd); + if (retval) + return retval; + + /* + * We should really pull this value out of tegra_ehci_soc_config, but + * to avoid needing access to it, make use of the fact that Tegra20 is + * the only one so far that needs a value of 10, and Tegra20 is the + * only one which doesn't set has_hostpc. + */ + txfifothresh = ehci->has_hostpc ? 0x10 : 10; + ehci_writel(ehci, txfifothresh << 16, &ehci->regs->txfill_tuning); + + return 0; +} + static const struct ehci_driver_overrides tegra_overrides __initconst = { .extra_priv_size = sizeof(struct tegra_ehci_hcd), + .reset = tegra_ehci_reset, }; static int __init ehci_tegra_init(void) From 4d6b5161dba1aa1964e505d2a09bfe4e3a1a7378 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Apr 2014 12:08:13 +0200 Subject: [PATCH 183/279] USB: ohci-jz4740: Fix uninitialized variable warning The ret variable is not initialized in all code paths of the ohci_jz4740_hub_control function. Fix it. Signed-off-by: Laurent Pinchart Acked-by: Lars-Peter Clausen Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-jz4740.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c index af8dc1b92d7550..b34315ca6cffce 100644 --- a/drivers/usb/host/ohci-jz4740.c +++ b/drivers/usb/host/ohci-jz4740.c @@ -82,7 +82,7 @@ static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct jz4740_ohci_hcd *jz4740_ohci = hcd_to_jz4740_hcd(hcd); - int ret; + int ret = 0; switch (typeReq) { case SetHubFeature: From 166cf4aa354c0066cb1903336382772e9e1b7941 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Mon, 14 Apr 2014 12:08:14 +0200 Subject: [PATCH 184/279] USB: ohci-jz4740: FEAT_POWER is a port feature, not a hub feature Power control of hub ports target the CLEAR_FEATURE and SET_FEATURE requests to ports, not to the hub. Fix the hub control function to detect the request correctly. Signed-off-by: Laurent Pinchart Acked-by: Lars-Peter Clausen Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-jz4740.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/ohci-jz4740.c b/drivers/usb/host/ohci-jz4740.c index b34315ca6cffce..c2c221a332eb48 100644 --- a/drivers/usb/host/ohci-jz4740.c +++ b/drivers/usb/host/ohci-jz4740.c @@ -85,11 +85,11 @@ static int ohci_jz4740_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, int ret = 0; switch (typeReq) { - case SetHubFeature: + case SetPortFeature: if (wValue == USB_PORT_FEAT_POWER) ret = ohci_jz4740_set_vbus_power(jz4740_ohci, true); break; - case ClearHubFeature: + case ClearPortFeature: if (wValue == USB_PORT_FEAT_POWER) ret = ohci_jz4740_set_vbus_power(jz4740_ohci, false); break; From 895d240d1db0b2736d779200788e4c4aea28a0c6 Mon Sep 17 00:00:00 2001 From: Michael Ulbricht Date: Tue, 25 Mar 2014 10:34:18 +0100 Subject: [PATCH 185/279] USB: cdc-acm: Remove Motorola/Telit H24 serial interfaces from ACM driver By specifying NO_UNION_NORMAL the ACM driver does only use the first two USB interfaces (modem data & control). The AT Port, Diagnostic and NMEA interfaces are left to the USB serial driver. Signed-off-by: Michael Ulbricht Signed-off-by: Alexander Stein Signed-off-by: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d5d2c922186afb..904efb6035b06d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1654,13 +1654,27 @@ static const struct usb_device_id acm_ids[] = { }, /* Motorola H24 HSPA module: */ { USB_DEVICE(0x22b8, 0x2d91) }, /* modem */ - { USB_DEVICE(0x22b8, 0x2d92) }, /* modem + diagnostics */ - { USB_DEVICE(0x22b8, 0x2d93) }, /* modem + AT port */ - { USB_DEVICE(0x22b8, 0x2d95) }, /* modem + AT port + diagnostics */ - { USB_DEVICE(0x22b8, 0x2d96) }, /* modem + NMEA */ - { USB_DEVICE(0x22b8, 0x2d97) }, /* modem + diagnostics + NMEA */ - { USB_DEVICE(0x22b8, 0x2d99) }, /* modem + AT port + NMEA */ - { USB_DEVICE(0x22b8, 0x2d9a) }, /* modem + AT port + diagnostics + NMEA */ + { USB_DEVICE(0x22b8, 0x2d92), /* modem + diagnostics */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d93), /* modem + AT port */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d95), /* modem + AT port + diagnostics */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d96), /* modem + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d97), /* modem + diagnostics + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d99), /* modem + AT port + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, + { USB_DEVICE(0x22b8, 0x2d9a), /* modem + AT port + diagnostics + NMEA */ + .driver_info = NO_UNION_NORMAL, /* handle only modem interface */ + }, { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ .driver_info = NO_UNION_NORMAL, /* union descriptor misplaced on From f7a87195603ae9db133ddd393169dd6c1d45b4a3 Mon Sep 17 00:00:00 2001 From: Daeseok Youn Date: Wed, 16 Apr 2014 18:48:02 +0900 Subject: [PATCH 186/279] uwb: adds missing error handling There is checking NULL before dereferncing but it need to add "return". Signed-off-by: Daeseok Youn Signed-off-by: Greg Kroah-Hartman --- drivers/uwb/drp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/uwb/drp.c b/drivers/uwb/drp.c index 16ada8341c46de..1a2fd9795367cc 100644 --- a/drivers/uwb/drp.c +++ b/drivers/uwb/drp.c @@ -599,8 +599,11 @@ static void uwb_drp_handle_alien_drp(struct uwb_rc *rc, struct uwb_ie_drp *drp_i /* alloc and initialize new uwb_cnflt_alien */ cnflt = kzalloc(sizeof(struct uwb_cnflt_alien), GFP_KERNEL); - if (!cnflt) + if (!cnflt) { dev_err(dev, "failed to alloc uwb_cnflt_alien struct\n"); + return; + } + INIT_LIST_HEAD(&cnflt->rc_node); init_timer(&cnflt->timer); cnflt->timer.function = uwb_cnflt_timer; From e7eda9329372f5e436e5a9291eb115eab0feae02 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 28 Mar 2014 11:10:30 +0100 Subject: [PATCH 187/279] uas: fix GFP_NOIO under spinlock Quote Dan: The patch e36e64930cff: "uas: Use GFP_NOIO rather then GFP_ATOMIC where possible" from Nov 7, 2013, leads to the following static checker warning: drivers/usb/storage/uas.c:806 uas_eh_task_mgmt() error: scheduling with locks held: 'spin_lock:lock' Some other allocations under spinlock are not caught. The fix essentially reverts e36e64930cffd94e1c37fdb82f35989384aa946b Signed-off-by: Oliver Neukum Reported-by: Dan Carpenter Reviewed-by: Hans de Goede Acked-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index a7ac97cc59495f..8f4222640bd6b7 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -137,7 +137,7 @@ static void uas_do_work(struct work_struct *work) if (!(cmdinfo->state & IS_IN_WORK_LIST)) continue; - err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); if (!err) cmdinfo->state &= ~IS_IN_WORK_LIST; else @@ -803,7 +803,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, devinfo->running_task = 1; memset(&devinfo->response, 0, sizeof(devinfo->response)); - sense_urb = uas_submit_sense_urb(cmnd, GFP_NOIO, + sense_urb = uas_submit_sense_urb(cmnd, GFP_ATOMIC, devinfo->use_streams ? tag : 0); if (!sense_urb) { shost_printk(KERN_INFO, shost, @@ -813,7 +813,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, spin_unlock_irqrestore(&devinfo->lock, flags); return FAILED; } - if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) { + if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) { shost_printk(KERN_INFO, shost, "%s: %s: submit task mgmt urb failed\n", __func__, fname); From c637f1fa7b0452b71eebd35d00906d371c04714e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 28 Mar 2014 11:29:25 +0100 Subject: [PATCH 188/279] uas: fix error handling during scsi_scan() intfdata is set only after scsi_scan(). uas_pre_reset() however needs intfdata to be valid and will follow the NULL pointer killing khubd. intfdata must be preemptively set before the host is registered and undone in the error case. Signed-off-by: Oliver Neukum Reviewed-by: Hans de Goede Acked-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 8f4222640bd6b7..fcab9b79d9fb90 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -1096,16 +1096,17 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) if (result) goto free_streams; + usb_set_intfdata(intf, shost); result = scsi_add_host(shost, &intf->dev); if (result) goto free_streams; scsi_scan_host(shost); - usb_set_intfdata(intf, shost); return result; free_streams: uas_free_streams(devinfo); + usb_set_intfdata(intf, NULL); set_alt0: usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); if (shost) From 94d72f008909610710bb1841d665eeeb010a0be1 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 28 Mar 2014 11:25:50 +0100 Subject: [PATCH 189/279] uas: fix deadlocky memory allocations There are also two allocations with GFP_KERNEL in the pre-/post_reset code paths. That is no good because that is a part of the SCSI error handler. Signed-off-by: Oliver Neukum Reviewed-by: Hans de Goede Acked-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/uas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index fcab9b79d9fb90..511b22953167bd 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -1030,7 +1030,7 @@ static int uas_configure_endpoints(struct uas_dev_info *devinfo) devinfo->use_streams = 0; } else { devinfo->qdepth = usb_alloc_streams(devinfo->intf, eps + 1, - 3, 256, GFP_KERNEL); + 3, 256, GFP_NOIO); if (devinfo->qdepth < 0) return devinfo->qdepth; devinfo->use_streams = 1; @@ -1047,7 +1047,7 @@ static void uas_free_streams(struct uas_dev_info *devinfo) eps[0] = usb_pipe_endpoint(udev, devinfo->status_pipe); eps[1] = usb_pipe_endpoint(udev, devinfo->data_in_pipe); eps[2] = usb_pipe_endpoint(udev, devinfo->data_out_pipe); - usb_free_streams(devinfo->intf, eps, 3, GFP_KERNEL); + usb_free_streams(devinfo->intf, eps, 3, GFP_NOIO); } static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) From 593ceb0c7046c640cf463022189428a45219f595 Mon Sep 17 00:00:00 2001 From: David Fries Date: Tue, 8 Apr 2014 22:37:07 -0500 Subject: [PATCH 190/279] w1: fix netlink refcnt leak on error path If the message type is W1_MASTER_CMD or W1_SLAVE_CMD, then a reference is taken when searching for the slave or master device. If there isn't any following data m->len (mlen is a copy) is 0 and packing up the message for later execution is skipped leaving nothing to decrement the reference counts. Way back when, m->len was checked before the search that increments the reference count, but W1_LIST_MASTERS has no additional data, the check was moved in 9be62e0b2fadaf5ff causing this bug. This change reorders to put the check before the reference count is incremented avoiding the problem. Signed-off-by: David Fries Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1_netlink.c | 44 ++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c index 5234964fe001e9..a02704a593213e 100644 --- a/drivers/w1/w1_netlink.c +++ b/drivers/w1/w1_netlink.c @@ -300,12 +300,6 @@ static int w1_process_command_root(struct cn_msg *msg, struct w1_netlink_msg *w; u32 *id; - if (mcmd->type != W1_LIST_MASTERS) { - printk(KERN_NOTICE "%s: msg: %x.%x, wrong type: %u, len: %u.\n", - __func__, msg->id.idx, msg->id.val, mcmd->type, mcmd->len); - return -EPROTO; - } - cn = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!cn) return -ENOMEM; @@ -441,6 +435,9 @@ static void w1_process_cb(struct w1_master *dev, struct w1_async_cmd *async_cmd) w1_netlink_send_error(&node->block->msg, node->m, cmd, node->block->portid, err); + /* ref taken in w1_search_slave or w1_search_master_id when building + * the block + */ if (sl) w1_unref_slave(sl); else @@ -503,30 +500,42 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) msg_len = msg->len; while (msg_len && !err) { - struct w1_reg_num id; - u16 mlen = m->len; dev = NULL; sl = NULL; - memcpy(&id, m->id.id, sizeof(id)); -#if 0 - printk("%s: %02x.%012llx.%02x: type=%02x, len=%u.\n", - __func__, id.family, (unsigned long long)id.id, id.crc, m->type, m->len); -#endif if (m->len + sizeof(struct w1_netlink_msg) > msg_len) { err = -E2BIG; break; } + /* execute on this thread, no need to process later */ + if (m->type == W1_LIST_MASTERS) { + err = w1_process_command_root(msg, m, nsp->portid); + goto out_cont; + } + + /* All following message types require additional data, + * check here before references are taken. + */ + if (!m->len) { + err = -EPROTO; + goto out_cont; + } + + /* both search calls take reference counts */ if (m->type == W1_MASTER_CMD) { dev = w1_search_master_id(m->id.mst.id); } else if (m->type == W1_SLAVE_CMD) { - sl = w1_search_slave(&id); + sl = w1_search_slave((struct w1_reg_num *)m->id.id); if (sl) dev = sl->master; } else { - err = w1_process_command_root(msg, m, nsp->portid); + printk(KERN_NOTICE + "%s: msg: %x.%x, wrong type: %u, len: %u.\n", + __func__, msg->id.idx, msg->id.val, + m->type, m->len); + err = -EPROTO; goto out_cont; } @@ -536,8 +545,6 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) } err = 0; - if (!mlen) - goto out_cont; atomic_inc(&block->refcnt); node->async.cb = w1_process_cb; @@ -557,7 +564,8 @@ static void w1_cn_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) if (err) w1_netlink_send_error(msg, m, NULL, nsp->portid, err); msg_len -= sizeof(struct w1_netlink_msg) + m->len; - m = (struct w1_netlink_msg *)(((u8 *)m) + sizeof(struct w1_netlink_msg) + m->len); + m = (struct w1_netlink_msg *)(((u8 *)m) + + sizeof(struct w1_netlink_msg) + m->len); /* * Let's allow requests for nonexisting devices. From 18d7f891bcc7e49f2900215f17a861ccec34b138 Mon Sep 17 00:00:00 2001 From: David Fries Date: Wed, 16 Apr 2014 01:21:21 -0500 Subject: [PATCH 191/279] w1: avoid recursive device_add __w1_attach_slave_device calls device_add which calls w1_bus_notify which calls the w1_bq27000 slave driver, which calls platform_device_add and device_add and deadlocks on getting &(&priv->bus_notifier)->rwsem as it is still held in the previous device_add. This avoids the problem by processing the family add/remove outside of the slave device_add call. Commit 47eba33a0997fc7362a introduced this deadlock and added a KOBJ_ADD, as the add was already reported in device_register two add events were being sent. This change suppresses the device_register add so that any slave device sysfs entries are setup before the add goes out. Belisko Marek reported this change fixed the deadlock he was seeing on ARM device tree, while testing on my x86-64 system never saw the deadlock. Reported-by: Belisko Marek Signed-off-by: David Fries Signed-off-by: Greg Kroah-Hartman --- drivers/w1/w1.c | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index b96f61b15dc65e..ff52618cafbeca 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -614,27 +614,11 @@ static int w1_uevent(struct device *dev, struct kobj_uevent_env *env) return err; } -/* - * Handle sysfs file creation and removal here, before userspace is told that - * the device is added / removed from the system - */ -static int w1_bus_notify(struct notifier_block *nb, unsigned long action, - void *data) +static int w1_family_notify(unsigned long action, struct w1_slave *sl) { - struct device *dev = data; - struct w1_slave *sl; struct w1_family_ops *fops; int err; - /* - * Only care about slave devices at the moment. Yes, we should use a - * separate "type" for this, but for now, look at the release function - * to know which type it is... - */ - if (dev->release != w1_slave_release) - return 0; - - sl = dev_to_w1_slave(dev); fops = sl->family->fops; if (!fops) @@ -673,10 +657,6 @@ static int w1_bus_notify(struct notifier_block *nb, unsigned long action, return 0; } -static struct notifier_block w1_bus_nb = { - .notifier_call = w1_bus_notify, -}; - static int __w1_attach_slave_device(struct w1_slave *sl) { int err; @@ -698,6 +678,9 @@ static int __w1_attach_slave_device(struct w1_slave *sl) dev_dbg(&sl->dev, "%s: registering %s as %p.\n", __func__, dev_name(&sl->dev), sl); + /* suppress for w1_family_notify before sending KOBJ_ADD */ + dev_set_uevent_suppress(&sl->dev, true); + err = device_register(&sl->dev); if (err < 0) { dev_err(&sl->dev, @@ -705,7 +688,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl) dev_name(&sl->dev), err); return err; } - + w1_family_notify(BUS_NOTIFY_ADD_DEVICE, sl); dev_set_uevent_suppress(&sl->dev, false); kobject_uevent(&sl->dev.kobj, KOBJ_ADD); @@ -799,6 +782,7 @@ int w1_unref_slave(struct w1_slave *sl) msg.type = W1_SLAVE_REMOVE; w1_netlink_send(sl->master, &msg); + w1_family_notify(BUS_NOTIFY_DEL_DEVICE, sl); device_unregister(&sl->dev); #ifdef DEBUG memset(sl, 0, sizeof(*sl)); @@ -1186,10 +1170,6 @@ static int __init w1_init(void) goto err_out_exit_init; } - retval = bus_register_notifier(&w1_bus_type, &w1_bus_nb); - if (retval) - goto err_out_bus_unregister; - retval = driver_register(&w1_master_driver); if (retval) { printk(KERN_ERR From 098ced8fefe4a4e4240fa47b1ed9b00d65b6cd21 Mon Sep 17 00:00:00 2001 From: Joe Schultz Date: Thu, 3 Apr 2014 14:47:55 -0500 Subject: [PATCH 192/279] vme_tsi148: Fix typo in tsi148_slave_get() This patch corrects a typo where "vme_base" was used instead of "*vme_base". The typo resulted in an incorrect value being returned to userspace (via vme_user). It also removes the following compile warning on some platforms: warning: cast from pointer to integer of different size [asierra: commit title/log rewording] Signed-off-by: Joe Schultz Signed-off-by: Aaron Sierra Signed-off-by: Greg Kroah-Hartman --- drivers/vme/bridges/vme_tsi148.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 06990c6a1a698c..6b03be71500558 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -741,7 +741,7 @@ static int tsi148_slave_get(struct vme_slave_resource *image, int *enabled, reg_join(vme_bound_high, vme_bound_low, &vme_bound); reg_join(pci_offset_high, pci_offset_low, &pci_offset); - *pci_base = (dma_addr_t)vme_base + pci_offset; + *pci_base = (dma_addr_t)(*vme_base + pci_offset); *enabled = 0; *aspace = 0; From 226572b110ab6083cb8c1d6afb191166b4178179 Mon Sep 17 00:00:00 2001 From: Joe Schultz Date: Thu, 3 Apr 2014 14:48:16 -0500 Subject: [PATCH 193/279] vme_tsi148: Fix PCI address mapping assumption Previously, tsi148_master_set() assumed the address contained in its PCI bus resource represented the actual PCI bus address. This is a fine assumption on some platforms. However, on platforms that don't use a 1:1 (CPU:PCI) mapping this results in the tsi148 driver configuring an invalid master window translation. This patch updates the vme_tsi148 driver to first convert the address contained in the PCI bus resource into a PCI bus address before using it. [asierra: account for pcibios_resource_to_bus() prototype change] Signed-off-by: Joe Schultz Signed-off-by: Aaron Sierra Signed-off-by: Greg Kroah-Hartman --- drivers/vme/bridges/vme_tsi148.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index 6b03be71500558..e64e4208de2b7c 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -910,11 +910,15 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, unsigned long long pci_bound, vme_offset, pci_base; struct vme_bridge *tsi148_bridge; struct tsi148_driver *bridge; + struct pci_bus_region region; + struct pci_dev *pdev; tsi148_bridge = image->parent; bridge = tsi148_bridge->driver_priv; + pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + /* Verify input data */ if (vme_base & 0xFFFF) { dev_err(tsi148_bridge->parent, "Invalid VME Window " @@ -949,7 +953,9 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, pci_bound = 0; vme_offset = 0; } else { - pci_base = (unsigned long long)image->bus_resource.start; + pcibios_resource_to_bus(pdev->bus, ®ion, + &image->bus_resource); + pci_base = region.start; /* * Bound address is a valid address for the window, adjust From 177581faf2a5aa71898d223bc47dbc882eeb1488 Mon Sep 17 00:00:00 2001 From: Aaron Sierra Date: Thu, 3 Apr 2014 14:48:27 -0500 Subject: [PATCH 194/279] vme_tsi148: Utilize to_pci_dev() macro Save some characters by using to_pci_dev() instead of container_of(). Signed-off-by: Aaron Sierra Signed-off-by: Greg Kroah-Hartman --- drivers/vme/bridges/vme_tsi148.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/vme/bridges/vme_tsi148.c b/drivers/vme/bridges/vme_tsi148.c index e64e4208de2b7c..61e706c0e00c6f 100644 --- a/drivers/vme/bridges/vme_tsi148.c +++ b/drivers/vme/bridges/vme_tsi148.c @@ -320,7 +320,7 @@ static int tsi148_irq_init(struct vme_bridge *tsi148_bridge) struct pci_dev *pdev; struct tsi148_driver *bridge; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); bridge = tsi148_bridge->driver_priv; @@ -433,9 +433,7 @@ static void tsi148_irq_set(struct vme_bridge *tsi148_bridge, int level, iowrite32be(tmp, bridge->base + TSI148_LCSR_INTEO); if (sync != 0) { - pdev = container_of(tsi148_bridge->parent, - struct pci_dev, dev); - + pdev = to_pci_dev(tsi148_bridge->parent); synchronize_irq(pdev->irq); } } else { @@ -814,7 +812,7 @@ static int tsi148_alloc_resource(struct vme_master_resource *image, tsi148_bridge = image->parent; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); existing_size = (unsigned long long)(image->bus_resource.end - image->bus_resource.start); @@ -917,7 +915,7 @@ static int tsi148_master_set(struct vme_master_resource *image, int enabled, bridge = tsi148_bridge->driver_priv; - pdev = container_of(tsi148_bridge->parent, struct pci_dev, dev); + pdev = to_pci_dev(tsi148_bridge->parent); /* Verify input data */ if (vme_base & 0xFFFF) { @@ -2238,7 +2236,7 @@ static void *tsi148_alloc_consistent(struct device *parent, size_t size, struct pci_dev *pdev; /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); + pdev = to_pci_dev(parent); return pci_alloc_consistent(pdev, size, dma); } @@ -2249,7 +2247,7 @@ static void tsi148_free_consistent(struct device *parent, size_t size, struct pci_dev *pdev; /* Find pci_dev container of dev */ - pdev = container_of(parent, struct pci_dev, dev); + pdev = to_pci_dev(parent); pci_free_consistent(pdev, size, vaddr, dma); } From 314672a2c2780212fb770bb02d2fffaa1019823f Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Wed, 9 Apr 2014 17:24:16 -0700 Subject: [PATCH 195/279] Tools: hv: Handle the case when the target file exists correctly Return the appropriate error code and handle the case when the target file exists correctly. This fixes a bug. Signed-off-by: K. Y. Srinivasan Cc: [3.14] Signed-off-by: Greg Kroah-Hartman --- include/uapi/linux/hyperv.h | 1 + tools/hv/hv_fcopy_daemon.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/hyperv.h b/include/uapi/linux/hyperv.h index 9beb7c991638ad..78e4a86030dd2d 100644 --- a/include/uapi/linux/hyperv.h +++ b/include/uapi/linux/hyperv.h @@ -305,6 +305,7 @@ enum hv_kvp_exchg_pool { #define HV_ERROR_DEVICE_NOT_CONNECTED 0x8007048F #define HV_INVALIDARG 0x80070057 #define HV_GUID_NOTFOUND 0x80041002 +#define HV_ERROR_ALREADY_EXISTS 0x80070050 #define ADDR_FAMILY_NONE 0x00 #define ADDR_FAMILY_IPV4 0x01 diff --git a/tools/hv/hv_fcopy_daemon.c b/tools/hv/hv_fcopy_daemon.c index 4ecc4fd0bc1bd9..fba1c75aa484f6 100644 --- a/tools/hv/hv_fcopy_daemon.c +++ b/tools/hv/hv_fcopy_daemon.c @@ -82,8 +82,10 @@ static int hv_start_fcopy(struct hv_start_fcopy *smsg) if (!access(target_fname, F_OK)) { syslog(LOG_INFO, "File: %s exists", target_fname); - if (!smsg->copy_flags & OVER_WRITE) + if (!(smsg->copy_flags & OVER_WRITE)) { + error = HV_ERROR_ALREADY_EXISTS; goto done; + } } target_fd = open(target_fname, O_RDWR | O_CREAT | O_CLOEXEC, 0744); From 408065998443831d3369c6bfdc8862c1d02a91dd Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Wed, 2 Apr 2014 09:37:08 -0700 Subject: [PATCH 196/279] stable_kernel_rules: spelling/word usage "than" should be "then" Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman --- Documentation/stable_kernel_rules.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index b0714d8f678ac5..cbc2f03056bdef 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -39,7 +39,7 @@ Procedure for submitting patches to the -stable tree: the stable tree without anything else needing to be done by the author or subsystem maintainer. - If the patch requires other patches as prerequisites which can be - cherry-picked than this can be specified in the following format in + cherry-picked, then this can be specified in the following format in the sign-off area: Cc: # 3.3.x: a1f84a3: sched: Check for idle From 06d96c0ff77f20dbf5fc93c8cfa9a2a9690fd67e Mon Sep 17 00:00:00 2001 From: Lin Yongting Date: Wed, 16 Apr 2014 23:25:28 +0800 Subject: [PATCH 197/279] Chinese: add translation of io_ordering.txt This is a Chinese translated version of Documentation/io_ordering.txt Signed-off-by: Lin Yongting Signed-off-by: Greg Kroah-Hartman --- Documentation/zh_CN/io_ordering.txt | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Documentation/zh_CN/io_ordering.txt diff --git a/Documentation/zh_CN/io_ordering.txt b/Documentation/zh_CN/io_ordering.txt new file mode 100644 index 00000000000000..e592daf4e0143b --- /dev/null +++ b/Documentation/zh_CN/io_ordering.txt @@ -0,0 +1,67 @@ +Chinese translated version of Documentation/io_orderings.txt + +If you have any comment or update to the content, please contact the +original document maintainer directly. However, if you have a problem +communicating in English you can also ask the Chinese maintainer for +help. Contact the Chinese maintainer if this translation is outdated +or if there is a problem with the translation. + +Chinese maintainer: Lin Yongting +--------------------------------------------------------------------- +Documentation/io_ordering.txt 的中文翻译 + +如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文 +交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻 +译存在问题,请联系中文版维护者。 + +中文版维护者: 林永听 Lin Yongting +中文版翻译者: 林永听 Lin Yongting +中文版校译者: 林永听 Lin Yongting + + +以下为正文 +--------------------------------------------------------------------- + +在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任 +保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全” +设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作, +而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。 +这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存 +屏障操作,mb(),不过仅适用于I/O)。 + +假设一个设备驱动程的具体例子: + + ... +CPU A: spin_lock_irqsave(&dev_lock, flags) +CPU A: val = readl(my_status); +CPU A: ... +CPU A: writel(newval, ring_ptr); +CPU A: spin_unlock_irqrestore(&dev_lock, flags) + ... +CPU B: spin_lock_irqsave(&dev_lock, flags) +CPU B: val = readl(my_status); +CPU B: ... +CPU B: writel(newval2, ring_ptr); +CPU B: spin_unlock_irqrestore(&dev_lock, flags) + ... + +上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就 +发生了。不过很容易通过下面方法来修复: + + ... +CPU A: spin_lock_irqsave(&dev_lock, flags) +CPU A: val = readl(my_status); +CPU A: ... +CPU A: writel(newval, ring_ptr); +CPU A: (void)readl(safe_register); /* 配置寄存器?*/ +CPU A: spin_unlock_irqrestore(&dev_lock, flags) + ... +CPU B: spin_lock_irqsave(&dev_lock, flags) +CPU B: val = readl(my_status); +CPU B: ... +CPU B: writel(newval2, ring_ptr); +CPU B: (void)readl(safe_register); /* 配置寄存器?*/ +CPU B: spin_unlock_irqrestore(&dev_lock, flags) + +在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作, +再处理后面的读操作,防止引发数据不一致问题。 From 53974e06603977f348ed978d75c426b0532daa67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20Stehl=C3=A9?= Date: Fri, 4 Apr 2014 08:43:18 +0200 Subject: [PATCH 198/279] topology: Fix compilation warning when not in SMP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The topology_##name() macro does not use its argument when CONFIG_SMP is not set, as it ultimately calls the cpu_data() macro. So we avoid maintaining a possibly unused `cpu' variable, to avoid the following compilation warning: drivers/base/topology.c: In function ‘show_physical_package_id’: drivers/base/topology.c:103:118: warning: unused variable ‘cpu’ [-Wunused-variable] define_id_show_func(physical_package_id); drivers/base/topology.c: In function ‘show_core_id’: drivers/base/topology.c:106:106: warning: unused variable ‘cpu’ [-Wunused-variable] define_id_show_func(core_id); This can be seen with e.g. x86 defconfig and CONFIG_SMP not set. Signed-off-by: Vincent Stehlé Cc: Greg Kroah-Hartman Cc: # 3.10.x Cc: # 3.13.x Cc: # 3.14.x Signed-off-by: Greg Kroah-Hartman --- drivers/base/topology.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/base/topology.c b/drivers/base/topology.c index bbcbd3c4392689..be7c1fb7c0c96f 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -39,8 +39,7 @@ static ssize_t show_##name(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ - unsigned int cpu = dev->id; \ - return sprintf(buf, "%d\n", topology_##name(cpu)); \ + return sprintf(buf, "%d\n", topology_##name(dev->id)); \ } #if defined(topology_thread_cpumask) || defined(topology_core_cpumask) || \ From 98b0f811aade1b7c6e7806c86aa0befd5919d65f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 14 Apr 2014 18:52:14 +0200 Subject: [PATCH 199/279] Documentation: Update stable address in Chinese and Japanese translations The English and Korean translations were updated, the Chinese and Japanese weren't. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- Documentation/ja_JP/HOWTO | 2 +- Documentation/ja_JP/stable_kernel_rules.txt | 6 +++--- Documentation/zh_CN/HOWTO | 2 +- Documentation/zh_CN/stable_kernel_rules.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/ja_JP/HOWTO b/Documentation/ja_JP/HOWTO index 0091a8215ac150..b61885c35ce11d 100644 --- a/Documentation/ja_JP/HOWTO +++ b/Documentation/ja_JP/HOWTO @@ -315,7 +315,7 @@ Andrew Morton が Linux-kernel メーリングリストにカーネルリリー もし、3.x.y カーネルが存在しない場合には、番号が一番大きい 3.x が 最新の安定版カーネルです。 -3.x.y は "stable" チーム でメンテされており、必 +3.x.y は "stable" チーム でメンテされており、必 要に応じてリリースされます。通常のリリース期間は 2週間毎ですが、差し迫っ た問題がなければもう少し長くなることもあります。セキュリティ関連の問題 の場合はこれに対してだいたいの場合、すぐにリリースがされます。 diff --git a/Documentation/ja_JP/stable_kernel_rules.txt b/Documentation/ja_JP/stable_kernel_rules.txt index 14265837c4ce34..9dbda9b5d21ed4 100644 --- a/Documentation/ja_JP/stable_kernel_rules.txt +++ b/Documentation/ja_JP/stable_kernel_rules.txt @@ -50,16 +50,16 @@ linux-2.6.29/Documentation/stable_kernel_rules.txt -stable ツリーにパッチを送付する手続き- - - 上記の規則に従っているかを確認した後に、stable@kernel.org にパッチ + - 上記の規則に従っているかを確認した後に、stable@vger.kernel.org にパッチ を送る。 - 送信者はパッチがキューに受け付けられた際には ACK を、却下された場合 には NAK を受け取る。この反応は開発者たちのスケジュールによって、数 日かかる場合がある。 - もし受け取られたら、パッチは他の開発者たちと関連するサブシステムの メンテナーによるレビューのために -stable キューに追加される。 - - パッチに stable@kernel.org のアドレスが付加されているときには、それ + - パッチに stable@vger.kernel.org のアドレスが付加されているときには、それ が Linus のツリーに入る時に自動的に stable チームに email される。 - - セキュリティパッチはこのエイリアス (stable@kernel.org) に送られるべ + - セキュリティパッチはこのエイリアス (stable@vger.kernel.org) に送られるべ きではなく、代わりに security@kernel.org のアドレスに送られる。 レビューサイクル- diff --git a/Documentation/zh_CN/HOWTO b/Documentation/zh_CN/HOWTO index 6c914aa87e7138..54ea24ff63c7ce 100644 --- a/Documentation/zh_CN/HOWTO +++ b/Documentation/zh_CN/HOWTO @@ -237,7 +237,7 @@ kernel.org网站的pub/linux/kernel/v2.6/目录下找到它。它的开发遵循 如果没有2.6.x.y版本内核存在,那么最新的2.6.x版本内核就相当于是当前的稳定 版内核。 -2.6.x.y版本由“稳定版”小组(邮件地址)维护,一般隔周发 +2.6.x.y版本由“稳定版”小组(邮件地址)维护,一般隔周发 布新版本。 内核源码中的Documentation/stable_kernel_rules.txt文件具体描述了可被稳定 diff --git a/Documentation/zh_CN/stable_kernel_rules.txt b/Documentation/zh_CN/stable_kernel_rules.txt index b5b9b0ab02fd5a..26ea5ed7cd9c4c 100644 --- a/Documentation/zh_CN/stable_kernel_rules.txt +++ b/Documentation/zh_CN/stable_kernel_rules.txt @@ -42,7 +42,7 @@ Documentation/stable_kernel_rules.txt 的中文翻译 向稳定版代码树提交补丁的过程: - - 在确认了补丁符合以上的规则后,将补丁发送到stable@kernel.org。 + - 在确认了补丁符合以上的规则后,将补丁发送到stable@vger.kernel.org。 - 如果补丁被接受到队列里,发送者会收到一个ACK回复,如果没有被接受,收 到的是NAK回复。回复需要几天的时间,这取决于开发者的时间安排。 - 被接受的补丁会被加到稳定版本队列里,等待其他开发者的审查。 From 03367ef5ea811475187a0732aada068919e14d61 Mon Sep 17 00:00:00 2001 From: "K. Y. Srinivasan" Date: Thu, 3 Apr 2014 18:02:45 -0700 Subject: [PATCH 200/279] Drivers: hv: vmbus: Negotiate version 3.0 when running on ws2012r2 hosts Only ws2012r2 hosts support the ability to reconnect to the host on VMBUS. This functionality is needed by kexec in Linux. To use this functionality we need to negotiate version 3.0 of the VMBUS protocol. Signed-off-by: K. Y. Srinivasan Cc: [3.9+] Signed-off-by: Greg Kroah-Hartman --- drivers/hv/connection.c | 5 ++++- include/linux/hyperv.h | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index f2d7bf90c9fe5b..2e7801af466e58 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -55,6 +55,9 @@ static __u32 vmbus_get_next_version(__u32 current_version) case (VERSION_WIN8): return VERSION_WIN7; + case (VERSION_WIN8_1): + return VERSION_WIN8; + case (VERSION_WS2008): default: return VERSION_INVAL; @@ -77,7 +80,7 @@ static int vmbus_negotiate_version(struct vmbus_channel_msginfo *msginfo, msg->interrupt_page = virt_to_phys(vmbus_connection.int_page); msg->monitor_page1 = virt_to_phys(vmbus_connection.monitor_pages[0]); msg->monitor_page2 = virt_to_phys(vmbus_connection.monitor_pages[1]); - if (version == VERSION_WIN8) + if (version == VERSION_WIN8_1) msg->target_vcpu = hv_context.vp_index[smp_processor_id()]; /* diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index ab7359fde9879f..2d7b4f139c32fa 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -147,15 +147,17 @@ hv_get_ringbuffer_availbytes(struct hv_ring_buffer_info *rbi, * 0 . 13 (Windows Server 2008) * 1 . 1 (Windows 7) * 2 . 4 (Windows 8) + * 3 . 0 (Windows 8 R2) */ #define VERSION_WS2008 ((0 << 16) | (13)) #define VERSION_WIN7 ((1 << 16) | (1)) #define VERSION_WIN8 ((2 << 16) | (4)) +#define VERSION_WIN8_1 ((3 << 16) | (0)) #define VERSION_INVAL -1 -#define VERSION_CURRENT VERSION_WIN8 +#define VERSION_CURRENT VERSION_WIN8_1 /* Make maximum size of pipe payload of 16K */ #define MAX_PIPE_DATA_PAYLOAD (sizeof(u8) * 16384) From 93a2e470ef3b17495029a89a05e25830aeca1ffb Mon Sep 17 00:00:00 2001 From: Sanjay Singh Rawat Date: Fri, 21 Mar 2014 13:55:10 +0530 Subject: [PATCH 201/279] serial: omap: free the wakeup settings in remove Signed-off-by: Sanjay Singh Rawat Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index dd8b1a5458ff43..ecfafbb3035626 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -1789,6 +1789,7 @@ static int serial_omap_remove(struct platform_device *dev) pm_runtime_disable(up->dev); uart_remove_one_port(&serial_omap_reg, &up->port); pm_qos_remove_request(&up->pm_qos_request); + device_init_wakeup(&dev->dev, false); return 0; } From 4ea8dafd2475e26b3cee3836bc6e6fddbdfb2721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Tue, 25 Mar 2014 15:53:12 +0100 Subject: [PATCH 202/279] serial: efm32: use $vendor,$device scheme for compatible string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wolfram Sang pointed out that "efm32,$device" is non-standard. So use the common scheme and prefix device with "efm32-". The old compatible string is left in place until arch/arm/boot/dts/efm32* is fixed. Reported-by: Wolfram Sang Signed-off-by: Uwe Kleine-König Acked-by: Wolfram Sang Signed-off-by: Greg Kroah-Hartman --- Documentation/devicetree/bindings/serial/efm32-uart.txt | 4 ++-- drivers/tty/serial/efm32-uart.c | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/serial/efm32-uart.txt b/Documentation/devicetree/bindings/serial/efm32-uart.txt index 1984bdfbd545c7..3ca01336b837e7 100644 --- a/Documentation/devicetree/bindings/serial/efm32-uart.txt +++ b/Documentation/devicetree/bindings/serial/efm32-uart.txt @@ -1,7 +1,7 @@ * Energymicro efm32 UART Required properties: -- compatible : Should be "efm32,uart" +- compatible : Should be "energymicro,efm32-uart" - reg : Address and length of the register set - interrupts : Should contain uart interrupt @@ -13,7 +13,7 @@ Optional properties: Example: uart@0x4000c400 { - compatible = "efm32,uart"; + compatible = "energymicro,efm32-uart"; reg = <0x4000c400 0x400>; interrupts = <15>; efm32,location = <0>; diff --git a/drivers/tty/serial/efm32-uart.c b/drivers/tty/serial/efm32-uart.c index 028582e924a5fb..c167a710dc39b5 100644 --- a/drivers/tty/serial/efm32-uart.c +++ b/drivers/tty/serial/efm32-uart.c @@ -798,6 +798,9 @@ static int efm32_uart_remove(struct platform_device *pdev) static const struct of_device_id efm32_uart_dt_ids[] = { { + .compatible = "energymicro,efm32-uart", + }, { + /* doesn't follow the "vendor,device" scheme, don't use */ .compatible = "efm32,uart", }, { /* sentinel */ From 717f3bbab3c7628736ef738fdbf3d9a28578c26c Mon Sep 17 00:00:00 2001 From: Seth Bollinger Date: Tue, 25 Mar 2014 12:55:37 -0500 Subject: [PATCH 203/279] serial_core: Fix conditional start_tx on ring buffer not empty If the serial_core ring buffer empties just as the tty layer receives an XOFF, then start_tx will never be called when the tty layer receives an XON as the serial_core ring buffer is empty. This will possibly leave a few bytes trapped in the fifo for drivers that disable the transmitter when flow controlled. Signed-off-by: Seth Bollinger Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2cf5649a6dc038..dd1a7bef6647bf 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -89,8 +89,7 @@ static void __uart_start(struct tty_struct *tty) struct uart_state *state = tty->driver_data; struct uart_port *port = state->uart_port; - if (!uart_circ_empty(&state->xmit) && state->xmit.buf && - !tty->stopped && !tty->hw_stopped) + if (!tty->stopped && !tty->hw_stopped) port->ops->start_tx(port); } From 2f310b8e418ac5eb3833a9f36791c24a97f1f557 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Thu, 27 Mar 2014 13:38:19 +0400 Subject: [PATCH 204/279] Revert "serial: clps711x: Give a chance to perform useful tasks during wait loop" This reverts commit 63e3ad3252695a2b8c01b6f6c225e4537af08b85, since this not works as expected and produce runtime error: BUG: sleeping function called from invalid context at drivers/tty/serial/clps711x.c:379 in_atomic(): 0, irqs_disabled(): 128, pid: 287, name: mount Signed-off-by: Alexander Shiyan Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/clps711x.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c index 5e6fdb1ea73b32..14aaea0d413107 100644 --- a/drivers/tty/serial/clps711x.c +++ b/drivers/tty/serial/clps711x.c @@ -368,16 +368,12 @@ static const struct uart_ops uart_clps711x_ops = { static void uart_clps711x_console_putchar(struct uart_port *port, int ch) { struct clps711x_port *s = dev_get_drvdata(port->dev); + u32 sysflg = 0; /* Wait for FIFO is not full */ - while (1) { - u32 sysflg = 0; - + do { regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); - if (!(sysflg & SYSFLG_UTXFF)) - break; - cond_resched(); - } + } while (sysflg & SYSFLG_UTXFF); writew(ch, port->membase + UARTDR_OFFSET); } @@ -387,18 +383,14 @@ static void uart_clps711x_console_write(struct console *co, const char *c, { struct uart_port *port = clps711x_uart.state[co->index].uart_port; struct clps711x_port *s = dev_get_drvdata(port->dev); + u32 sysflg = 0; uart_console_write(port, c, n, uart_clps711x_console_putchar); /* Wait for transmitter to become empty */ - while (1) { - u32 sysflg = 0; - + do { regmap_read(s->syscon, SYSFLG_OFFSET, &sysflg); - if (!(sysflg & SYSFLG_UBUSY)) - break; - cond_resched(); - } + } while (sysflg & SYSFLG_UBUSY); } static int uart_clps711x_console_setup(struct console *co, char *options) From c3c00b6f7f79be1dd1aa0969ee0ab7d1f79eda79 Mon Sep 17 00:00:00 2001 From: Daniel Thompson Date: Fri, 28 Mar 2014 10:53:10 +0000 Subject: [PATCH 205/279] serial: st-asc: Fix SysRq char handling This driver, like several others, uses the upper bits of the character to track both real and dummy state. Unfortunately it neglects to mask these bits properly when passing the character data around. This means neither break detection nor sysrq character handling work correctly. This patch adds the requires masking and has been tested to confirm that it correctly handles magic sysrq sequences on ST's B2020 board. Signed-off-by: Daniel Thompson Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/st-asc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c index 21e6e84c0df872..dd3a96e070265d 100644 --- a/drivers/tty/serial/st-asc.c +++ b/drivers/tty/serial/st-asc.c @@ -295,7 +295,7 @@ static void asc_receive_chars(struct uart_port *port) status & ASC_STA_OE) { if (c & ASC_RXBUF_FE) { - if (c == ASC_RXBUF_FE) { + if (c == (ASC_RXBUF_FE | ASC_RXBUF_DUMMY_RX)) { port->icount.brk++; if (uart_handle_break(port)) continue; @@ -325,7 +325,7 @@ static void asc_receive_chars(struct uart_port *port) flag = TTY_FRAME; } - if (uart_handle_sysrq_char(port, c)) + if (uart_handle_sysrq_char(port, c & 0xff)) continue; uart_insert_char(port, c, ASC_RXBUF_DUMMY_OE, c & 0xff, flag); From e55c2a07c4abf65d1915a7507a625c82c72fed5a Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 3 Apr 2014 11:36:22 +0200 Subject: [PATCH 206/279] serial: timberdale: Depend on X86_32 As far as I know the Timberdale chip was only used as a companion for Intel Atom E600 series processors. As such, its drivers are only useful on X86_32. Signed-off-by: Jean Delvare Cc: Greg Kroah-Hartman Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 2e6d8ddc44252b..5d9b01aa54f4c0 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1226,6 +1226,7 @@ config SERIAL_BFIN_SPORT3_UART_CTSRTS config SERIAL_TIMBERDALE tristate "Support for timberdale UART" select SERIAL_CORE + depends on X86_32 || COMPILE_TEST ---help--- Add support for UART controller on timberdale. From b2aeb775f814c9543784b15a5f2d87ea91005f3f Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 12 Apr 2014 19:47:17 +0200 Subject: [PATCH 207/279] serial: pl011: change Rx burst size to half of trigger level The amba-pl011.c driver sets DMA burst size equal to FIFO trigger level. If now exactly DMA burst size bytes are received, the DMAC will retrieve them all and no Rx timeout interrupt will be generated. To fix that set the burst size to half the FIFO trigger level. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index d4eda24aa68ba6..ca0ec600fab6f5 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -318,7 +318,7 @@ static void pl011_dma_probe_initcall(struct device *dev, struct uart_amba_port * .src_addr = uap->port.mapbase + UART01x_DR, .src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE, .direction = DMA_DEV_TO_MEM, - .src_maxburst = uap->fifosize >> 1, + .src_maxburst = uap->fifosize >> 2, .device_fc = false, }; From bf903c0c6ddfedec19ba92626ca30e98bfafbe08 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 27 Mar 2014 11:40:39 +0100 Subject: [PATCH 208/279] serial_core: Fix pm imbalance on unbind When a serial port is closed, uart_close() takes care of shutting down the hardware, and powering it down. When a serial port is unbound while in use, uart_close() bypasses all of this, as this is supposed to be done through uart_hangup() (invoked via tty_vhangup() in uart_remove_one_port()). However, uart_hangup() does not set the hardware's power state, leaving it powered up. This may also lead to unbounded nesting counts in clock and power management, depending on their internal implementation. Make sure to power down the port in uart_hangup(), except when the port is used as a serial console. For serial consoles, this operation must be postponed until after the port becomes completely unused. This case is not fixed yet, as it depends on a (future) fix for the tty->count vs. port->count imbalance on failed uart_open(). After this, the module clock used by the sh-sci driver is disabled on unbind while the serial port is in use. Signed-off-by: Geert Uytterhoeven Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/serial_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index dd1a7bef6647bf..f26834d262b3a8 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1451,6 +1451,8 @@ static void uart_hangup(struct tty_struct *tty) clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags); spin_unlock_irqrestore(&port->lock, flags); tty_port_tty_set(port, NULL); + if (!uart_console(state->uart_port)) + uart_change_pm(state, UART_PM_STATE_OFF); wake_up_interruptible(&port->open_wait); wake_up_interruptible(&port->delta_msr_wait); } From d758c9c1b36b4d9a141c2146c70398d756167ed1 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 25 Mar 2014 11:48:47 -0700 Subject: [PATCH 209/279] serial: omap: Fix missing pm_runtime_resume handling by simplifying code The lack of pm_runtime_resume handling for the device state leads into device wake-up interrupts not working after a while for runtime PM. Also, serial-omap is confused about the use of device_may_wakeup. The checks for device_may_wakeup should only be done for suspend and resume, not for pm_runtime_suspend and pm_runtime_resume. The wake-up events for PM runtime should always be enabled. The lack of pm_runtime_resume handling leads into device wake-up interrupts not working after a while for runtime PM. Rather than try to patch over the issue of adding complex tests to the pm_runtime_resume, let's fix the issues properly: 1. Make serial_omap_enable_wakeup deal with all internal PM state handling so we don't need to test for up->wakeups_enabled elsewhere. Later on once omap3 boots in device tree only mode we can also remove the up->wakeups_enabled flag and rely on the wake-up interrupt enable/disable state alone. 2. Do the device_may_wakeup checks in suspend and resume only, for runtime PM the wake-up events need to be always enabled. 3. Finally just call serial_omap_enable_wakeup and make sure we call it also in pm_runtime_resume. 4. Note that we also have to use disable_irq_nosync as serial_omap_irq calls pm_runtime_get_sync. Fixes: 2a0b965cfb6e (serial: omap: Add support for optional wake-up) Cc: stable@vger.kernel.org # v3.13+ Signed-off-by: Tony Lindgren Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/omap-serial.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index ecfafbb3035626..08b6b9419f0d04 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -225,14 +225,19 @@ static inline void serial_omap_enable_wakeirq(struct uart_omap_port *up, if (enable) enable_irq(up->wakeirq); else - disable_irq(up->wakeirq); + disable_irq_nosync(up->wakeirq); } static void serial_omap_enable_wakeup(struct uart_omap_port *up, bool enable) { struct omap_uart_port_info *pdata = dev_get_platdata(up->dev); + if (enable == up->wakeups_enabled) + return; + serial_omap_enable_wakeirq(up, enable); + up->wakeups_enabled = enable; + if (!pdata || !pdata->enable_wakeup) return; @@ -1495,6 +1500,11 @@ static int serial_omap_suspend(struct device *dev) uart_suspend_port(&serial_omap_reg, &up->port); flush_work(&up->qos_work); + if (device_may_wakeup(dev)) + serial_omap_enable_wakeup(up, true); + else + serial_omap_enable_wakeup(up, false); + return 0; } @@ -1502,6 +1512,9 @@ static int serial_omap_resume(struct device *dev) { struct uart_omap_port *up = dev_get_drvdata(dev); + if (device_may_wakeup(dev)) + serial_omap_enable_wakeup(up, false); + uart_resume_port(&serial_omap_reg, &up->port); return 0; @@ -1878,17 +1891,7 @@ static int serial_omap_runtime_suspend(struct device *dev) up->context_loss_cnt = serial_omap_get_context_loss_count(up); - if (device_may_wakeup(dev)) { - if (!up->wakeups_enabled) { - serial_omap_enable_wakeup(up, true); - up->wakeups_enabled = true; - } - } else { - if (up->wakeups_enabled) { - serial_omap_enable_wakeup(up, false); - up->wakeups_enabled = false; - } - } + serial_omap_enable_wakeup(up, true); up->latency = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE; schedule_work(&up->qos_work); @@ -1902,6 +1905,8 @@ static int serial_omap_runtime_resume(struct device *dev) int loss_cnt = serial_omap_get_context_loss_count(up); + serial_omap_enable_wakeup(up, false); + if (loss_cnt < 0) { dev_dbg(dev, "serial_omap_get_context_loss_count failed : %d\n", loss_cnt); From 3053075cea4e1d385cf0b003ffeb860cc8b378fb Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 31 Mar 2014 14:54:25 +0200 Subject: [PATCH 210/279] Documentation/serial: Delete obsolete driver documentation These serial drivers were removed in kernel v3.1, so we can drop their documentation files and references to their magic numbers and parameters. There are still references to these old drivers in Documentation/devices.txt but I'm afraid they can't be removed. Signed-off-by: Jean Delvare Cc: Greg Kroah-Hartman Cc: Jiri Slaby Cc: Rob Landley Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 13 - Documentation/magic-number.txt | 12 - Documentation/serial/00-INDEX | 8 - Documentation/serial/digiepca.txt | 98 ------- Documentation/serial/riscom8.txt | 36 --- Documentation/serial/specialix.txt | 383 --------------------------- Documentation/serial/sx.txt | 294 -------------------- Documentation/zh_CN/magic-number.txt | 12 - firmware/WHENCE | 10 - 9 files changed, 866 deletions(-) delete mode 100644 Documentation/serial/digiepca.txt delete mode 100644 Documentation/serial/riscom8.txt delete mode 100644 Documentation/serial/specialix.txt delete mode 100644 Documentation/serial/sx.txt diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 03e50b4883a8e9..43842177b771d7 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -804,13 +804,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. dhash_entries= [KNL] Set number of hash buckets for dentry cache. - digi= [HW,SERIAL] - IO parameters + enable/disable command. - - digiepca= [HW,SERIAL] - See drivers/char/README.epca and - Documentation/serial/digiepca.txt. - disable= [IPV6] See Documentation/networking/ipv6.txt. @@ -2939,9 +2932,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. rhash_entries= [KNL,NET] Set number of hash buckets for route cache - riscom8= [HW,SERIAL] - Format: [,[,...]] - ro [KNL] Mount root device read-only on boot root= [KNL] Root filesystem @@ -3083,9 +3073,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted. sonypi.*= [HW] Sony Programmable I/O Control Device driver See Documentation/laptops/sonypi.txt - specialix= [HW,SERIAL] Specialix multi-serial port adapter - See Documentation/serial/specialix.txt. - spia_io_base= [HW,MTD] spia_fio_base= spia_pedr= diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt index 76d80a64bbe1dd..4c8e142db2ef99 100644 --- a/Documentation/magic-number.txt +++ b/Documentation/magic-number.txt @@ -63,8 +63,6 @@ Magic Name Number Structure File PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h CMAGIC 0x0111 user include/linux/a.out.h MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h -RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h -SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c APM_BIOS_MAGIC 0x4101 apm_user arch/x86/kernel/apm_32.c CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h @@ -82,7 +80,6 @@ STRIP_MAGIC 0x5303 strip drivers/net/strip.c X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h -ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h TTY_MAGIC 0x5401 tty_struct include/linux/tty.h MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h @@ -94,13 +91,10 @@ USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h -A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h LSEMAGIC 0x05091998 lse drivers/fc4/fc.c GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h RIEBL_MAGIC 0x09051990 drivers/net/atarilance.c -RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c -SX_MAGIC 0x12345678 gs_port drivers/char/sx.h NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h RED_MAGIC2 0x170fc2a5 (any) mm/slab.c BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c @@ -116,7 +110,6 @@ ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c -STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c @@ -127,10 +120,8 @@ SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h RED_MAGIC1 0x5a2cf071 (any) mm/slab.c -STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h -EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h KV_MAGIC 0x5f4b565f kernel_vars_s arch/mips/include/asm/sn/klkernvars.h I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c @@ -142,17 +133,14 @@ SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h OPROFILE_MAGIC 0x6f70726f super_block drivers/oprofile/oprofilefs.h M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c -STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h -STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h ENI155_MAGIC 0xa54b872d midway_eprom drivers/atm/eni.h SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h CODA_MAGIC 0xC0DAC0DA coda_file_info fs/coda/coda_fs_i.h DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram drivers/scsi/gdth.h -STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c diff --git a/Documentation/serial/00-INDEX b/Documentation/serial/00-INDEX index f9c6b5ed03e7f0..8021a9f29fc59a 100644 --- a/Documentation/serial/00-INDEX +++ b/Documentation/serial/00-INDEX @@ -2,23 +2,15 @@ - this file. README.cycladesZ - info on Cyclades-Z firmware loading. -digiepca.txt - - info on Digi Intl. {PC,PCI,EISA}Xx and Xem series cards. driver - intro to the low level serial driver. moxa-smartio - file with info on installing/using Moxa multiport serial driver. n_gsm.txt - GSM 0710 tty multiplexer howto. -riscom8.txt - - notes on using the RISCom/8 multi-port serial driver. rocket.txt - info on the Comtrol RocketPort multiport serial driver. serial-rs485.txt - info about RS485 structures and support in the kernel. -specialix.txt - - info on hardware/driver for specialix IO8+ multiport serial card. -sx.txt - - info on the Specialix SX/SI multiport serial driver. tty.txt - guide to the locking policies of the tty layer. diff --git a/Documentation/serial/digiepca.txt b/Documentation/serial/digiepca.txt deleted file mode 100644 index f2560e22f2c976..00000000000000 --- a/Documentation/serial/digiepca.txt +++ /dev/null @@ -1,98 +0,0 @@ -NOTE: This driver is obsolete. Digi provides a 2.6 driver (dgdm) at -http://www.digi.com for PCI cards. They no longer maintain this driver, -and have no 2.6 driver for ISA cards. - -This driver requires a number of user-space tools. They can be acquired from -http://www.digi.com, but only works with 2.4 kernels. - - -The Digi Intl. epca driver. ----------------------------- -The Digi Intl. epca driver for Linux supports the following boards: - -Digi PC/Xem, PC/Xr, PC/Xe, PC/Xi, PC/Xeve -Digi EISA/Xem, PCI/Xem, PCI/Xr - -Limitations: ------------- -Currently the driver only autoprobes for supported PCI boards. - -The Linux MAKEDEV command does not support generating the Digiboard -Devices. Users executing digiConfig to setup EISA and PC series cards -will have their device nodes automatically constructed (cud?? for ~CLOCAL, -and ttyD?? for CLOCAL). Users wishing to boot their board from the LILO -prompt, or those users booting PCI cards may use buildDIGI to construct -the necessary nodes. - -Notes: ------- -This driver may be configured via LILO. For users who have already configured -their driver using digiConfig, configuring from LILO will override previous -settings. Multiple boards may be configured by issuing multiple LILO command -lines. For examples see the bottom of this document. - -Device names start at 0 and continue up. Beware of this as previous Digi -drivers started device names with 1. - -PCI boards are auto-detected and configured by the driver. PCI boards will -be allocated device numbers (internally) beginning with the lowest PCI slot -first. In other words a PCI card in slot 3 will always have higher device -nodes than a PCI card in slot 1. - -LILO config examples: ---------------------- -Using LILO's APPEND command, a string of comma separated identifiers or -integers can be used to configure supported boards. The six values in order -are: - - Enable/Disable this card or Override, - Type of card: PC/Xe (AccelePort) (0), PC/Xeve (1), PC/Xem or PC/Xr (2), - EISA/Xem (3), PC/64Xe (4), PC/Xi (5), - Enable/Disable alternate pin arrangement, - Number of ports on this card, - I/O Port where card is configured (in HEX if using string identifiers), - Base of memory window (in HEX if using string identifiers), - -NOTE : PCI boards are auto-detected and configured. Do not attempt to -configure PCI boards with the LILO append command. If you wish to override -previous configuration data (As set by digiConfig), but you do not wish to -configure any specific card (Example if there are PCI cards in the system) -the following override command will accomplish this: --> append="digi=2" - -Samples: - append="digiepca=E,PC/Xe,D,16,200,D0000" - or - append="digi=1,0,0,16,512,851968" - -Supporting Tools: ------------------ -Supporting tools include digiDload, digiConfig, buildPCI, and ditty. See -drivers/char/README.epca for more details. Note, -this driver REQUIRES that digiDload be executed prior to it being used. -Failure to do this will result in an ENODEV error. - -Documentation: --------------- -Complete documentation for this product may be found in the tool package. - -Sources of information and support: ------------------------------------ -Digi Intl. support site for this product: - --> http://www.digi.com - -Acknowledgments: ----------------- -Much of this work (And even text) was derived from a similar document -supporting the original public domain DigiBoard driver Copyright (C) -1994,1995 Troy De Jongh. Many thanks to Christoph Lameter -(christoph@lameter.com) and Mike McLagan (mike.mclagan@linux.org) who authored -and contributed to the original document. - -Changelog: ----------- -10-29-04: Update status of driver, remove dead links in document - James Nelson - -2000 (?) Original Document diff --git a/Documentation/serial/riscom8.txt b/Documentation/serial/riscom8.txt deleted file mode 100644 index 14f61fdad7ca7c..00000000000000 --- a/Documentation/serial/riscom8.txt +++ /dev/null @@ -1,36 +0,0 @@ -* NOTE - this is an unmaintained driver. The original author cannot be located. - -SDL Communications is now SBS Technologies, and does not have any -information on these ancient ISA cards on their website. - -James Nelson - 12-12-2004 - - This is the README for RISCom/8 multi-port serial driver - (C) 1994-1996 D.Gorodchanin - See file LICENSE for terms and conditions. - -NOTE: English is not my native language. - I'm sorry for any mistakes in this text. - -Misc. notes for RISCom/8 serial driver, in no particular order :) - -1) This driver can support up to 4 boards at time. - Use string "riscom8=0xXXX,0xXXX,0xXXX,0xXXX" at LILO prompt, for - setting I/O base addresses for boards. If you compile driver - as module use modprobe options "iobase=0xXXX iobase1=0xXXX iobase2=..." - -2) The driver partially supports famous 'setserial' program, you can use almost - any of its options, excluding port & irq settings. - -3) There are some misc. defines at the beginning of riscom8.c, please read the - comments and try to change some of them in case of problems. - -4) I consider the current state of the driver as BETA. - -5) SDL Communications WWW page is http://www.sdlcomm.com. - -6) You can use the MAKEDEV program to create RISCom/8 /dev/ttyL* entries. - -7) Minor numbers for first board are 0-7, for second 8-15, etc. - -22 Apr 1996. diff --git a/Documentation/serial/specialix.txt b/Documentation/serial/specialix.txt deleted file mode 100644 index 6eb6f3a3331c26..00000000000000 --- a/Documentation/serial/specialix.txt +++ /dev/null @@ -1,383 +0,0 @@ - - specialix.txt -- specialix IO8+ multiport serial driver readme. - - - - Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) - - Specialix pays for the development and support of this driver. - Please DO contact io8-linux@specialix.co.uk if you require - support. - - This driver was developed in the BitWizard linux device - driver service. If you require a linux device driver for your - product, please contact devices@BitWizard.nl for a quote. - - This code is firmly based on the riscom/8 serial driver, - written by Dmitry Gorodchanin. The specialix IO8+ card - programming information was obtained from the CL-CD1865 Data - Book, and Specialix document number 6200059: IO8+ Hardware - Functional Specification, augmented by document number 6200088: - Merak Hardware Functional Specification. (IO8+/PCI is also - called Merak) - - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, - USA. - - -Intro -===== - - -This file contains some random information, that I like to have online -instead of in a manual that can get lost. Ever misplace your Linux -kernel sources? And the manual of one of the boards in your computer? - - -Addresses and interrupts -======================== - -Address dip switch settings: -The dip switch sets bits 2-9 of the IO address. - - 9 8 7 6 5 4 3 2 - +-----------------+ - 0 | X X X X X X X | - | | = IoBase = 0x100 - 1 | X | - +-----------------+ ------ RS232 connectors ----> - - | | | - edge connector - | | | - V V V - -Base address 0x100 caused a conflict in one of my computers once. I -haven't the foggiest why. My Specialix card is now at 0x180. My -other computer runs just fine with the Specialix card at 0x100.... -The card occupies 4 addresses, but actually only two are really used. - -The PCI version doesn't have any dip switches. The BIOS assigns -an IO address. - -The driver now still autoprobes at 0x100, 0x180, 0x250 and 0x260. If -that causes trouble for you, please report that. I'll remove -autoprobing then. - -The driver will tell the card what IRQ to use, so you don't have to -change any jumpers to change the IRQ. Just use a command line -argument (irq=xx) to the insmod program to set the interrupt. - -The BIOS assigns the IRQ on the PCI version. You have no say in what -IRQ to use in that case. - -If your specialix cards are not at the default locations, you can use -the kernel command line argument "specialix=io0,irq0,io1,irq1...". -Here "io0" is the io address for the first card, and "irq0" is the -irq line that the first card should use. And so on. - -Examples. - -You use the driver as a module and have three cards at 0x100, 0x250 -and 0x180. And some way or another you want them detected in that -order. Moreover irq 12 is taken (e.g. by your PS/2 mouse). - - insmod specialix.o iobase=0x100,0x250,0x180 irq=9,11,15 - -The same three cards, but now in the kernel would require you to -add - - specialix=0x100,9,0x250,11,0x180,15 - -to the command line. This would become - - append="specialix=0x100,9,0x250,11,0x180,15" - -in your /etc/lilo.conf file if you use lilo. - -The Specialix driver is slightly odd: It allows you to have the second -or third card detected without having a first card. This has -advantages and disadvantages. A slot that isn't filled by an ISA card, -might be filled if a PCI card is detected. Thus if you have an ISA -card at 0x250 and a PCI card, you would get: - -sx0: specialix IO8+ Board at 0x100 not found. -sx1: specialix IO8+ Board at 0x180 not found. -sx2: specialix IO8+ board detected at 0x250, IRQ 12, CD1865 Rev. B. -sx3: specialix IO8+ Board at 0x260 not found. -sx0: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B. - -This would happen if you don't give any probe hints to the driver. -If you would specify: - - specialix=0x250,11 - -you'd get the following messages: - -sx0: specialix IO8+ board detected at 0x250, IRQ 11, CD1865 Rev. B. -sx1: specialix IO8+ board detected at 0xd800, IRQ 9, CD1865 Rev. B. - -ISA probing is aborted after the IO address you gave is exhausted, and -the PCI card is now detected as the second card. The ISA card is now -also forced to IRQ11.... - - -Baud rates -========== - -The rev 1.2 and below boards use a CL-CD1864. These chips can only -do 64kbit. The rev 1.3 and newer boards use a CL-CD1865. These chips -are officially capable of 115k2. - -The Specialix card uses a 25MHz crystal (in times two mode, which in -fact is a divided by two mode). This is not enough to reach the rated -115k2 on all ports at the same time. With this clock rate you can only -do 37% of this rate. This means that at 115k2 on all ports you are -going to lose characters (The chip cannot handle that many incoming -bits at this clock rate.) (Yes, you read that correctly: there is a -limit to the number of -=bits=- per second that the chip can handle.) - -If you near the "limit" you will first start to see a graceful -degradation in that the chip cannot keep the transmitter busy at all -times. However with a central clock this slow, you can also get it to -miss incoming characters. The driver will print a warning message when -you are outside the official specs. The messages usually show up in -the file /var/log/messages . - -The specialix card cannot reliably do 115k2. If you use it, you have -to do "extensive testing" (*) to verify if it actually works. - -When "mgetty" communicates with my modem at 115k2 it reports: -got: +++[0d]ATQ0V1H0[0d][0d][8a]O[cb][0d][8a] - ^^^^ ^^^^ ^^^^ - -The three characters that have the "^^^" under them have suffered a -bit error in the highest bit. In conclusion: I've tested it, and found -that it simply DOESN'T work for me. I also suspect that this is also -caused by the baud rate being just a little bit out of tune. - -I upgraded the crystal to 66Mhz on one of my Specialix cards. Works -great! Contact me for details. (Voids warranty, requires a steady hand -and more such restrictions....) - - -(*) Cirrus logic CD1864 databook, page 40. - - -Cables for the Specialix IO8+ -============================= - -The pinout of the connectors on the IO8+ is: - - pin short direction long name - name - Pin 1 DCD input Data Carrier Detect - Pin 2 RXD input Receive - Pin 3 DTR/RTS output Data Terminal Ready/Ready To Send - Pin 4 GND - Ground - Pin 5 TXD output Transmit - Pin 6 CTS input Clear To Send - - - -- 6 5 4 3 2 1 -- - | | - | | - | | - | | - +----- -----+ - |__________| - clip - - Front view of an RJ12 connector. Cable moves "into" the paper. - (the plug is ready to plug into your mouth this way...) - - - NULL cable. I don't know who is going to use these except for - testing purposes, but I tested the cards with this cable. (It - took quite a while to figure out, so I'm not going to delete - it. So there! :-) - - - This end goes This end needs - straight into the some twists in - RJ12 plug. the wiring. - IO8+ RJ12 IO8+ RJ12 - 1 DCD white - - - - 1 DCD - 2 RXD black 5 TXD - 3 DTR/RTS red 6 CTS - 4 GND green 4 GND - 5 TXD yellow 2 RXD - 6 CTS blue 3 DTR/RTS - - - Same NULL cable, but now sorted on the second column. - - 1 DCD white - - - - 1 DCD - 5 TXD yellow 2 RXD - 6 CTS blue 3 DTR/RTS - 4 GND green 4 GND - 2 RXD black 5 TXD - 3 DTR/RTS red 6 CTS - - - - This is a modem cable usable for hardware handshaking: - RJ12 DB25 DB9 - 1 DCD white 8 DCD 1 DCD - 2 RXD black 3 RXD 2 RXD - 3 DTR/RTS red 4 RTS 7 RTS - 4 GND green 7 GND 5 GND - 5 TXD yellow 2 TXD 3 TXD - 6 CTS blue 5 CTS 8 CTS - +---- 6 DSR 6 DSR - +---- 20 DTR 4 DTR - - This is a modem cable usable for software handshaking: - It allows you to reset the modem using the DTR ioctls. - I (REW) have never tested this, "but xxxxxxxxxxxxx - says that it works." If you test this, please - tell me and I'll fill in your name on the xxx's. - - RJ12 DB25 DB9 - 1 DCD white 8 DCD 1 DCD - 2 RXD black 3 RXD 2 RXD - 3 DTR/RTS red 20 DTR 4 DTR - 4 GND green 7 GND 5 GND - 5 TXD yellow 2 TXD 3 TXD - 6 CTS blue 5 CTS 8 CTS - +---- 6 DSR 6 DSR - +---- 4 RTS 7 RTS - - I bought a 6 wire flat cable. It was colored as indicated. - Check that yours is the same before you trust me on this. - - -Hardware handshaking issues. -============================ - -The driver can be told to operate in two different ways. The default -behaviour is specialix.sx_rtscts = 0 where the pin behaves as DTR when -hardware handshaking is off. It behaves as the RTS hardware -handshaking signal when hardware handshaking is selected. - -When you use this, you have to use the appropriate cable. The -cable will either be compatible with hardware handshaking or with -software handshaking. So switching on the fly is not really an -option. - -I actually prefer to use the "specialix.sx_rtscts=1" option. -This makes the DTR/RTS pin always an RTS pin, and ioctls to -change DTR are always ignored. I have a cable that is configured -for this. - - -Ports and devices -================= - -Port 0 is the one furthest from the card-edge connector. - -Devices: - -You should make the devices as follows: - -bash -cd /dev -for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \ - 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 -do - echo -n "$i " - mknod /dev/ttyW$i c 75 $i - mknod /dev/cuw$i c 76 $i -done -echo "" - -If your system doesn't come with these devices preinstalled, bug your -linux-vendor about this. They have had ample time to get this -implemented by now. - -You cannot have more than 4 boards in one computer. The card only -supports 4 different interrupts. If you really want this, contact me -about this and I'll give you a few tips (requires soldering iron).... - -If you have enough PCI slots, you can probably use more than 4 PCI -versions of the card though.... - -The PCI version of the card cannot adhere to the mechanical part of -the PCI spec because the 8 serial connectors are simply too large. If -it doesn't fit in your computer, bring back the card. - - ------------------------------------------------------------------------- - - - Fixed bugs and restrictions: - - During initialization, interrupts are blindly turned on. - Having a shadow variable would cause an extra memory - access on every IO instruction. - - The interrupt (on the card) should be disabled when we - don't allocate the Linux end of the interrupt. This allows - a different driver/card to use it while all ports are not in - use..... (a la standard serial port) - == An extra _off variant of the sx_in and sx_out macros are - now available. They don't set the interrupt enable bit. - These are used during initialization. Normal operation uses - the old variant which enables the interrupt line. - - RTS/DTR issue needs to be implemented according to - specialix' spec. - I kind of like the "determinism" of the current - implementation. Compile time flag? - == Ok. Compile time flag! Default is how Specialix likes it. - == Now a config time flag! Gets saved in your config file. Neat! - - Can you set the IO address from the lilo command line? - If you need this, bug me about it, I'll make it. - == Hah! No bugging needed. Fixed! :-) - - Cirrus logic hasn't gotten back to me yet why the CD1865 can - and the CD1864 can't do 115k2. I suspect that this is - because the CD1864 is not rated for 33MHz operation. - Therefore the CD1864 versions of the card can't do 115k2 on - all ports just like the CD1865 versions. The driver does - not block 115k2 on CD1864 cards. - == I called the Cirrus Logic representative here in Holland. - The CD1864 databook is identical to the CD1865 databook, - except for an extra warning at the end. Similar Bit errors - have been observed in testing at 115k2 on both an 1865 and - a 1864 chip. I see no reason why I would prohibit 115k2 on - 1864 chips and not do it on 1865 chips. Actually there is - reason to prohibit it on BOTH chips. I print a warning. - If you use 115k2, you're on your own. - - A spiky CD may send spurious HUPs. Also in CLOCAL??? - -- A fix for this turned out to be counter productive. - Different fix? Current behaviour is acceptable? - -- Maybe the current implementation is correct. If anybody - gets bitten by this, please report, and it will get fixed. - - -- Testing revealed that when in CLOCAL, the problem doesn't - occur. As warned for in the CD1865 manual, the chip may - send modem intr's on a spike. We could filter those out, - but that would be a cludge anyway (You'd still risk getting - a spurious HUP when two spikes occur.)..... - - - - Bugs & restrictions: - - This is a difficult card to autoprobe. - You have to WRITE to the address register to even - read-probe a CD186x register. Disable autodetection? - -- Specialix: any suggestions? - - diff --git a/Documentation/serial/sx.txt b/Documentation/serial/sx.txt deleted file mode 100644 index cb4efa0fb5cc31..00000000000000 --- a/Documentation/serial/sx.txt +++ /dev/null @@ -1,294 +0,0 @@ - - sx.txt -- specialix SX/SI multiport serial driver readme. - - - - Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl) - - Specialix pays for the development and support of this driver. - Please DO contact support@specialix.co.uk if you require - support. - - This driver was developed in the BitWizard linux device - driver service. If you require a linux device driver for your - product, please contact devices@BitWizard.nl for a quote. - - (History) - There used to be an SI driver by Simon Allan. This is a complete - rewrite from scratch. Just a few lines-of-code have been snatched. - - (Sources) - Specialix document number 6210028: SX Host Card and Download Code - Software Functional Specification. - - (Copying) - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be - useful, but WITHOUT ANY WARRANTY; without even the implied - warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR - PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, - USA. - - (Addendum) - I'd appreciate it that if you have fixes, that you send them - to me first. - - -Introduction -============ - -This file contains some random information, that I like to have online -instead of in a manual that can get lost. Ever misplace your Linux -kernel sources? And the manual of one of the boards in your computer? - - -Theory of operation -=================== - -An important thing to know is that the driver itself doesn't have the -firmware for the card. This means that you need the separate package -"sx_firmware". For now you can get the source at - - ftp://ftp.bitwizard.nl/specialix/sx_firmware_.tgz - -The firmware load needs a "misc" device, so you'll need to enable the -"Support for user misc device modules" in your kernel configuration. -The misc device needs to be called "/dev/specialix_sxctl". It needs -misc major 10, and minor number 167 (assigned by HPA). The section -on creating device files below also creates this device. - -After loading the sx.o module into your kernel, the driver will report -the number of cards detected, but because it doesn't have any -firmware, it will not be able to determine the number of ports. Only -when you then run "sx_firmware" will the firmware be downloaded and -the rest of the driver initialized. At that time the sx_firmware -program will report the number of ports installed. - -In contrast with many other multi port serial cards, some of the data -structures are only allocated when the card knows the number of ports -that are connected. This means we won't waste memory for 120 port -descriptor structures when you only have 8 ports. If you experience -problems due to this, please report them: I haven't seen any. - - -Interrupts -========== - -A multi port serial card, would generate a horrendous amount of -interrupts if it would interrupt the CPU for every received -character. Even more than 10 years ago, the trick not to use -interrupts but to poll the serial cards was invented. - -The SX card allow us to do this two ways. First the card limits its -own interrupt rate to a rate that won't overwhelm the CPU. Secondly, -we could forget about the cards interrupt completely and use the -internal timer for this purpose. - -Polling the card can take up to a few percent of your CPU. Using the -interrupts would be better if you have most of the ports idle. Using -timer-based polling is better if your card almost always has work to -do. You save the separate interrupt in that case. - -In any case, it doesn't really matter all that much. - -The most common problem with interrupts is that for ISA cards in a PCI -system the BIOS has to be told to configure that interrupt as "legacy -ISA". Otherwise the card can pull on the interrupt line all it wants -but the CPU won't see this. - -If you can't get the interrupt to work, remember that polling mode is -more efficient (provided you actually use the card intensively). - - -Allowed Configurations -====================== - -Some configurations are disallowed. Even though at a glance they might -seem to work, they are known to lockup the bus between the host card -and the device concentrators. You should respect the drivers decision -not to support certain configurations. It's there for a reason. - -Warning: Seriously technical stuff ahead. Executive summary: Don't use -SX cards except configured at a 64k boundary. Skip the next paragraph. - -The SX cards can theoretically be placed at a 32k boundary. So for -instance you can put an SX card at 0xc8000-0xd7fff. This is not a -"recommended configuration". ISA cards have to tell the bus controller -how they like their timing. Due to timing issues they have to do this -based on which 64k window the address falls into. This means that the -32k window below and above the SX card have to use exactly the same -timing as the SX card. That reportedly works for other SX cards. But -you're still left with two useless 32k windows that should not be used -by anybody else. - - -Configuring the driver -====================== - -PCI cards are always detected. The driver auto-probes for ISA cards at -some sensible addresses. Please report if the auto-probe causes trouble -in your system, or when a card isn't detected. - -I'm afraid I haven't implemented "kernel command line parameters" yet. -This means that if the default doesn't work for you, you shouldn't use -the compiled-into-the-kernel version of the driver. Use a module -instead. If you convince me that you need this, I'll make it for -you. Deal? - -I'm afraid that the module parameters are a bit clumsy. If you have a -better idea, please tell me. - -You can specify several parameters: - - sx_poll: number of jiffies between timer-based polls. - - Set this to "0" to disable timer based polls. - Initialization of cards without a working interrupt - will fail. - - Set this to "1" if you want a polling driver. - (on Intel: 100 polls per second). If you don't use - fast baud rates, you might consider a value like "5". - (If you don't know how to do the math, use 1). - - sx_slowpoll: Number of jiffies between timer-based polls. - Set this to "100" to poll once a second. - This should get the card out of a stall if the driver - ever misses an interrupt. I've never seen this happen, - and if it does, that's a bug. Tell me. - - sx_maxints: Number of interrupts to request from the card. - The card normally limits interrupts to about 100 per - second to offload the host CPU. You can increase this - number to reduce latency on the card a little. - Note that if you give a very high number you can overload - your CPU as well as the CPU on the host card. This setting - is inaccurate and not recommended for SI cards (But it - works). - - sx_irqmask: The mask of allowable IRQs to use. I suggest you set - this to 0 (disable IRQs all together) and use polling if - the assignment of IRQs becomes problematic. This is defined - as the sum of (1 << irq) 's that you want to allow. So - sx_irqmask of 8 (1 << 3) specifies that only irq 3 may - be used by the SX driver. If you want to specify to the - driver: "Either irq 11 or 12 is ok for you to use", then - specify (1 << 11) | (1 << 12) = 0x1800 . - - sx_debug: You can enable different sorts of debug traces with this. - At "-1" all debugging traces are active. You'll get several - times more debugging output than you'll get characters - transmitted. - - -Baud rates -========== - -Theoretically new SXDCs should be capable of more than 460k -baud. However the line drivers usually give up before that. Also the -CPU on the card may not be able to handle 8 channels going at full -blast at that speed. Moreover, the buffers are not large enough to -allow operation with 100 interrupts per second. You'll have to realize -that the card has a 256 byte buffer, so you'll have to increase the -number of interrupts per second if you have more than 256*100 bytes -per second to transmit. If you do any performance testing in this -area, I'd be glad to hear from you... - -(Psst Linux users..... I think the Linux driver is more efficient than -the driver for other OSes. If you can and want to benchmark them -against each other, be my guest, and report your findings...... :-) - - -Ports and devices -================= - -Port 0 is the top connector on the module closest to the host -card. Oh, the ports on the SXDCs and TAs are labelled from 1 to 8 -instead of from 0 to 7, as they are numbered by linux. I'm stubborn in -this: I know for sure that I wouldn't be able to calculate which port -is which anymore if I would change that.... - - -Devices: - -You should make the device files as follows: - -#!/bin/sh -# (I recommend that you cut-and-paste this into a file and run that) -cd /dev -t=0 -mknod specialix_sxctl c 10 167 -while [ $t -lt 64 ] - do - echo -n "$t " - mknod ttyX$t c 32 $t - mknod cux$t c 33 $t - t=`expr $t + 1` -done -echo "" -rm /etc/psdevtab -ps > /dev/null - - -This creates 64 devices. If you have more, increase the constant on -the line with "while". The devices start at 0, as is customary on -Linux. Specialix seems to like starting the numbering at 1. - -If your system doesn't come with these devices pre-installed, bug your -linux-vendor about this. They should have these devices -"pre-installed" before the new millennium. The "ps" stuff at the end -is to "tell" ps that the new devices exist. - -Officially the maximum number of cards per computer is 4. This driver -however supports as many cards in one machine as you want. You'll run -out of interrupts after a few, but you can switch to polled operation -then. At about 256 ports (More than 8 cards), we run out of minor -device numbers. Sorry. I suggest you buy a second computer.... (Or -switch to RIO). - ------------------------------------------------------------------------- - - - Fixed bugs and restrictions: - - Hangup processing. - -- Done. - - - the write path in generic_serial (lockup / oops). - -- Done (Ugly: not the way I want it. Copied from serial.c). - - - write buffer isn't flushed at close. - -- Done. I still seem to lose a few chars at close. - Sorry. I think that this is a firmware issue. (-> Specialix) - - - drain hardware before changing termios - - Change debug on the fly. - - ISA free irq -1. (no firmware loaded). - - adding c8000 as a probe address. Added warning. - - Add a RAMtest for the RAM on the card.c - - Crash when opening a port "way" of the number of allowed ports. - (for example opening port 60 when there are only 24 ports attached) - - Sometimes the use-count strays a bit. After a few hours of - testing the use count is sometimes "3". If you are not like - me and can remember what you did to get it that way, I'd - appreciate an Email. Possibly fixed. Tell me if anyone still - sees this. - - TAs don't work right if you don't connect all the modem control - signals. SXDCs do. T225 firmware problem -> Specialix. - (Mostly fixed now, I think. Tell me if you encounter this!) - - Bugs & restrictions: - - - Arbitrary baud rates. Requires firmware update. (-> Specialix) - - - Low latency (mostly firmware, -> Specialix) - - - diff --git a/Documentation/zh_CN/magic-number.txt b/Documentation/zh_CN/magic-number.txt index 2ebe539f5450a4..dfb72a5c63e9ba 100644 --- a/Documentation/zh_CN/magic-number.txt +++ b/Documentation/zh_CN/magic-number.txt @@ -63,8 +63,6 @@ struct tty_ldisc { PG_MAGIC 'P' pg_{read,write}_hdr include/linux/pg.h CMAGIC 0x0111 user include/linux/a.out.h MKISS_DRIVER_MAGIC 0x04bf mkiss_channel drivers/net/mkiss.h -RISCOM8_MAGIC 0x0907 riscom_port drivers/char/riscom8.h -SPECIALIX_MAGIC 0x0907 specialix_port drivers/char/specialix_io8.h HDLC_MAGIC 0x239e n_hdlc drivers/char/n_hdlc.c APM_BIOS_MAGIC 0x4101 apm_user arch/x86/kernel/apm_32.c CYCLADES_MAGIC 0x4359 cyclades_port include/linux/cyclades.h @@ -82,7 +80,6 @@ STRIP_MAGIC 0x5303 strip drivers/net/strip.c X25_ASY_MAGIC 0x5303 x25_asy drivers/net/x25_asy.h SIXPACK_MAGIC 0x5304 sixpack drivers/net/hamradio/6pack.h AX25_MAGIC 0x5316 ax_disp drivers/net/mkiss.h -ESP_MAGIC 0x53ee esp_struct drivers/char/esp.h TTY_MAGIC 0x5401 tty_struct include/linux/tty.h MGSL_MAGIC 0x5401 mgsl_info drivers/char/synclink.c TTY_DRIVER_MAGIC 0x5402 tty_driver include/linux/tty_driver.h @@ -94,13 +91,10 @@ USB_BLUETOOTH_MAGIC 0x6d02 usb_bluetooth drivers/usb/class/bluetty.c RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h -A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h LSEMAGIC 0x05091998 lse drivers/fc4/fc.c GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h RIEBL_MAGIC 0x09051990 drivers/net/atarilance.c -RIO_MAGIC 0x12345678 gs_port drivers/char/rio/rio_linux.c -SX_MAGIC 0x12345678 gs_port drivers/char/sx.h NBD_REQUEST_MAGIC 0x12560953 nbd_request include/linux/nbd.h RED_MAGIC2 0x170fc2a5 (any) mm/slab.c BAYCOM_MAGIC 0x19730510 baycom_state drivers/net/baycom_epp.c @@ -116,7 +110,6 @@ ISDN_ASYNC_MAGIC 0x49344C01 modem_info include/linux/isdn.h CTC_ASYNC_MAGIC 0x49344C01 ctc_tty_info drivers/s390/net/ctctty.c ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_lib.h SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c -STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c @@ -127,10 +120,8 @@ SCC_MAGIC 0x52696368 gs_port drivers/char/scc.h SAVEKMSG_MAGIC1 0x53415645 savekmsg arch/*/amiga/config.c GDA_MAGIC 0x58464552 gda arch/mips/include/asm/sn/gda.h RED_MAGIC1 0x5a2cf071 (any) mm/slab.c -STL_PORTMAGIC 0x5a7182c9 stlport include/linux/stallion.h EEPROM_MAGIC_VALUE 0x5ab478d2 lanai_dev drivers/atm/lanai.c HDLCDRV_MAGIC 0x5ac6e778 hdlcdrv_state include/linux/hdlcdrv.h -EPCA_MAGIC 0x5c6df104 channel include/linux/epca.h PCXX_MAGIC 0x5c6df104 channel drivers/char/pcxx.h KV_MAGIC 0x5f4b565f kernel_vars_s arch/mips/include/asm/sn/klkernvars.h I810_STATE_MAGIC 0x63657373 i810_state sound/oss/i810_audio.c @@ -142,17 +133,14 @@ SLOT_MAGIC 0x67267322 slot drivers/hotplug/acpiphp.h LO_MAGIC 0x68797548 nbd_device include/linux/nbd.h OPROFILE_MAGIC 0x6f70726f super_block drivers/oprofile/oprofilefs.h M3_STATE_MAGIC 0x734d724d m3_state sound/oss/maestro3.c -STL_PANELMAGIC 0x7ef621a1 stlpanel include/linux/stallion.h VMALLOC_MAGIC 0x87654320 snd_alloc_track sound/core/memory.c KMALLOC_MAGIC 0x87654321 snd_alloc_track sound/core/memory.c PWC_MAGIC 0x89DC10AB pwc_device drivers/usb/media/pwc.h NBD_REPLY_MAGIC 0x96744668 nbd_reply include/linux/nbd.h -STL_BOARDMAGIC 0xa2267f52 stlbrd include/linux/stallion.h ENI155_MAGIC 0xa54b872d midway_eprom drivers/atm/eni.h SCI_MAGIC 0xbabeface gs_port drivers/char/sh-sci.h CODA_MAGIC 0xC0DAC0DA coda_file_info include/linux/coda_fs_i.h DPMEM_MAGIC 0xc0ffee11 gdt_pci_sram drivers/scsi/gdth.h -STLI_PORTMAGIC 0xe671c7a1 stliport include/linux/istallion.h YAM_MAGIC 0xF10A7654 yam_port drivers/net/hamradio/yam.c CCB_MAGIC 0xf2691ad2 ccb drivers/scsi/ncr53c8xx.c QUEUE_MAGIC_FREE 0xf7e1c9a3 queue_entry drivers/scsi/arm/queue.c diff --git a/firmware/WHENCE b/firmware/WHENCE index 8388f02de2bde4..0c4d96dee9b632 100644 --- a/firmware/WHENCE +++ b/firmware/WHENCE @@ -273,16 +273,6 @@ Converted from Intel HEX files, used in our binary representation of ihex. -------------------------------------------------------------------------- -Driver: ip2 -- Computone IntelliPort Plus serial device - -File: intelliport2.bin - -Licence: Unknown - -Found in hex form in kernel source. - --------------------------------------------------------------------------- - Driver: CPiA2 -- cameras based on Vision's CPiA2 File: cpia2/stv0672_vp4.bin From f4f653e9875e573860e783fecbebde284a8626f5 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 1 Apr 2014 13:37:00 +0200 Subject: [PATCH 211/279] serial: 8250, disable "too much work" messages The 8250 driver now reports many of these: serial8250: too much work for irq4 These messages turned out to be common these days with a use of virtualization. I tried to increase the limit of processed characters in commit e7328ae1848966181a7ac47e8ae6cddbd2cf55f3 (serial: 8250, increase PASS_LIMIT) in 2011. It was raised from 256 to 512, but it is still not enough, apparently. So disable the warning unless somebody turns on DEBUG (or DYNAMIC_DEBUG _and_ the message). Signed-off-by: Jiri Slaby Reported-by: Martin Pluskal Reported-by: Takashi Iwai Tested-by: Takashi Iwai References: https://bugzilla.novell.com/show_bug.cgi?id=868394 Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 81f909c2101f61..139ab1997e062f 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1601,8 +1601,7 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) l = l->next; if (l == i->head && pass_counter++ > PASS_LIMIT) { - /* If we hit this, we're dead. */ - printk_ratelimited(KERN_ERR + pr_debug_ratelimited( "serial8250: too much work for irq%d\n", irq); break; } From 7d1c2858c49095ab748f55354b89dbd6b18d28b9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 Apr 2014 14:45:21 +0200 Subject: [PATCH 212/279] ttyprintk: Fix wrong tty_unregister_driver() call in the error path ttyprintk driver calls tty_unregister_driver() wrongly in the error path of tty_register_driver(). Also, setting ttyprintk_driver to NULL is utterly superfluous, so let's get rid of it, too. Reported-by: Jean Delvare Reviewed-by: Jean Delvare Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- drivers/char/ttyprintk.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index daea84c4174321..2a39c579036445 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -210,10 +210,8 @@ static int __init ttyprintk_init(void) return 0; error: - tty_unregister_driver(ttyprintk_driver); put_tty_driver(ttyprintk_driver); tty_port_destroy(&tpk_port.port); - ttyprintk_driver = NULL; return ret; } device_initcall(ttyprintk_init); From b24313a82cf24e90170671ea74360b3e6ef3a91f Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 2 Apr 2014 14:45:22 +0200 Subject: [PATCH 213/279] ttyprintk: Allow built as a module The driver is well written to be used as a module, just the exit call is missing. Reviewed-by: Jean Delvare Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- drivers/char/Kconfig | 2 +- drivers/char/ttyprintk.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index fbae63e3d30435..6e9f74a5c09503 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -40,7 +40,7 @@ config SGI_MBCS source "drivers/tty/serial/Kconfig" config TTY_PRINTK - bool "TTY driver to output user messages via printk" + tristate "TTY driver to output user messages via printk" depends on EXPERT && TTY default n ---help--- diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 2a39c579036445..a15ce4ef39cd97 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include struct ttyprintk_port { struct tty_port port; @@ -214,4 +214,15 @@ static int __init ttyprintk_init(void) tty_port_destroy(&tpk_port.port); return ret; } + +static void __exit ttyprintk_exit(void) +{ + tty_unregister_driver(ttyprintk_driver); + put_tty_driver(ttyprintk_driver); + tty_port_destroy(&tpk_port.port); +} + device_initcall(ttyprintk_init); +module_exit(ttyprintk_exit); + +MODULE_LICENSE("GPL"); From c70dbb1e79a1ac2802b4b7b6de7456b230fbbbeb Mon Sep 17 00:00:00 2001 From: Chen Tingjie Date: Tue, 15 Apr 2014 11:52:51 +0800 Subject: [PATCH 214/279] tty: fix memleak in alloc_pid There is memleak in alloc_pid: ------------------------------ unreferenced object 0xd3453a80 (size 64): comm "adbd", pid 1730, jiffies 66363 (age 6586.950s) hex dump (first 32 bytes): 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00 00 00 00 40 c2 f6 d5 00 d3 25 c1 59 28 00 00 ....@.....%.Y(.. backtrace: [] kmemleak_alloc+0x3c/0xa0 [] kmem_cache_alloc+0xc6/0x190 [] alloc_pid+0x1e/0x400 [] copy_process.part.39+0xad4/0x1120 [] do_fork+0x99/0x330 [] sys_fork+0x28/0x30 [] syscall_call+0x7/0xb [] 0xffffffff the leak is due to unreleased pid->count, which execute in function: get_pid()(pid->count++) and put_pid()(pid->count--). The race condition as following: task[dumpsys] task[adbd] in disassociate_ctty() in tty_signal_session_leader() ----------------------- ------------------------- tty = get_current_tty(); // tty is not NULL ... spin_lock_irq(¤t->sighand->siglock); put_pid(current->signal->tty_old_pgrp); current->signal->tty_old_pgrp = NULL; spin_unlock_irq(¤t->sighand->siglock); spin_lock_irq(&p->sighand->siglock); ... p->signal->tty = NULL; ... spin_unlock_irq(&p->sighand->siglock); tty = get_current_tty(); // tty NULL, goto else branch by accident. if (tty) { ... put_pid(tty_session); put_pid(tty_pgrp); ... } else { print msg } in task[dumpsys], in disassociate_ctty(), tty is set NULL by task[adbd], tty_signal_session_leader(), then it goto else branch and lack of put_pid(), cause memleak. move spin_unlock(sighand->siglock) after get_current_tty() can avoid the race and fix the memleak. Signed-off-by: Zhang Jun Signed-off-by: Chen Tingjie Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index d3448a90f0f9fe..34110719fe0377 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -878,9 +878,8 @@ void disassociate_ctty(int on_exit) spin_lock_irq(¤t->sighand->siglock); put_pid(current->signal->tty_old_pgrp); current->signal->tty_old_pgrp = NULL; - spin_unlock_irq(¤t->sighand->siglock); - tty = get_current_tty(); + tty = tty_kref_get(current->signal->tty); if (tty) { unsigned long flags; spin_lock_irqsave(&tty->ctrl_lock, flags); @@ -897,6 +896,7 @@ void disassociate_ctty(int on_exit) #endif } + spin_unlock_irq(¤t->sighand->siglock); /* Now clear signal->tty under the lock */ read_lock(&tasklist_lock); session_clear_tty(task_session(current)); From 9ca83fd2d5805a5e4608a901ffa802697adc638b Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 14 Apr 2014 18:32:13 +0200 Subject: [PATCH 215/279] tty: Fix help text of SYNCLINK_CS Enabling SYNCLINK_CS as a module builds synclink_cs, not synclinkmp. Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman --- drivers/char/pcmcia/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/pcmcia/Kconfig b/drivers/char/pcmcia/Kconfig index b27f5342fe7615..8d3dfb0c8a2625 100644 --- a/drivers/char/pcmcia/Kconfig +++ b/drivers/char/pcmcia/Kconfig @@ -15,7 +15,7 @@ config SYNCLINK_CS This driver may be built as a module ( = code which can be inserted in and removed from the running kernel whenever you want). - The module will be called synclinkmp. If you want to do that, say M + The module will be called synclink_cs. If you want to do that, say M here. config CARDMAN_4000 From 1e7da0530423a232747d64c2113ace55b01e5754 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Sat, 5 Apr 2014 16:31:08 +0200 Subject: [PATCH 216/279] serial: amba-pl011: fix regression, causing an Oops on rmmod A recent commit ef2889f7ffee67f0aed49e854c72be63f1466759 "serial: pl011: Move uart_register_driver call to device probe" introduced a regression, causing the pl011 driver to Oops if more than 1 port have been probed. Fix the Oops by only calling uart_unregister_driver() once after the last port has been removed. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/amba-pl011.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index ca0ec600fab6f5..dacf0a09ab248c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2176,6 +2176,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) static int pl011_remove(struct amba_device *dev) { struct uart_amba_port *uap = amba_get_drvdata(dev); + bool busy = false; int i; uart_remove_one_port(&amba_reg, &uap->port); @@ -2183,9 +2184,12 @@ static int pl011_remove(struct amba_device *dev) for (i = 0; i < ARRAY_SIZE(amba_ports); i++) if (amba_ports[i] == uap) amba_ports[i] = NULL; + else if (amba_ports[i]) + busy = true; pl011_dma_remove(uap); - uart_unregister_driver(&amba_reg); + if (!busy) + uart_unregister_driver(&amba_reg); return 0; } From 0e1f789d0dc38db79dfc4ddfd9cf541a8c198b7a Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 17 Apr 2014 08:15:19 +1000 Subject: [PATCH 217/279] xfs: don't map ranges that span EOF for direct IO Al Viro tracked down the problem that has caused generic/263 to fail on XFS since the test was introduced. If is caused by xfs_get_blocks() mapping a single extent that spans EOF without marking it as buffer-new() so that the direct IO code does not zero the tail of the block at the new EOF. This is a long standing bug that has been around for many, many years. Because xfs_get_blocks() starts the map before EOF, it can't set buffer_new(), because that causes he direct IO code to also zero unaligned sectors at the head of the IO. This would overwrite valid data with zeros, and hence we cannot validly return a single extent that spans EOF to direct IO. Fix this by detecting a mapping that spans EOF and truncate it down to EOF. This results in the the direct IO code doing the right thing for unaligned data blocks before EOF, and then returning to get another mapping for the region beyond EOF which XFS treats correctly by setting buffer_new() on it. This makes direct Io behave correctly w.r.t. tail block zeroing beyond EOF, and fsx is happy about that. Again, thanks to Al Viro for finding what I couldn't. [ dchinner: Fix for __divdi3 build error: Reported-by: Paul Gortmaker Tested-by: Paul Gortmaker Signed-off-by: Mark Tinguely Reviewed-by: Eric Sandeen ] Signed-off-by: Dave Chinner Tested-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_aops.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index e0a793113ea9b6..0479c32c5eb170 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1344,6 +1344,14 @@ __xfs_get_blocks( /* * If this is O_DIRECT or the mpage code calling tell them how large * the mapping is, so that we can avoid repeated get_blocks calls. + * + * If the mapping spans EOF, then we have to break the mapping up as the + * mapping for blocks beyond EOF must be marked new so that sub block + * regions can be correctly zeroed. We can't do this for mappings within + * EOF unless the mapping was just allocated or is unwritten, otherwise + * the callers would overwrite existing data with zeros. Hence we have + * to split the mapping into a range up to and including EOF, and a + * second mapping for beyond EOF. */ if (direct || size > (1 << inode->i_blkbits)) { xfs_off_t mapping_size; @@ -1354,6 +1362,12 @@ __xfs_get_blocks( ASSERT(mapping_size > 0); if (mapping_size > size) mapping_size = size; + if (offset < i_size_read(inode) && + offset + mapping_size >= i_size_read(inode)) { + /* limit mapping to block that spans EOF */ + mapping_size = roundup_64(i_size_read(inode) - offset, + 1 << inode->i_blkbits); + } if (mapping_size > LONG_MAX) mapping_size = LONG_MAX; From d39a2ced0fa0172faa46df0866fc22419b876e2a Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 17 Apr 2014 08:15:25 +1000 Subject: [PATCH 218/279] xfs: collapse range is delalloc challenged FSX has been detecting data corruption after to collapse range calls. The key observation is that the offset of the last extent in the file was not being shifted, and hence when the file size was adjusted it was truncating away data because the extents handled been correctly shifted. Tracing indicated that before the collapse, the extent list looked like: .... ino 0x5788 state idx 6 offset 26 block 195904 count 10 flag 0 ino 0x5788 state idx 7 offset 39 block 195917 count 35 flag 0 ino 0x5788 state idx 8 offset 86 block 195964 count 32 flag 0 and after the shift of 2 blocks: ino 0x5788 state idx 6 offset 24 block 195904 count 10 flag 0 ino 0x5788 state idx 7 offset 37 block 195917 count 35 flag 0 ino 0x5788 state idx 8 offset 86 block 195964 count 32 flag 0 Note that the last extent did not change offset. After the changing of the file size: ino 0x5788 state idx 6 offset 24 block 195904 count 10 flag 0 ino 0x5788 state idx 7 offset 37 block 195917 count 35 flag 0 ino 0x5788 state idx 8 offset 86 block 195964 count 30 flag 0 You can see that the last extent had it's length truncated, indicating that we've lost data. The reason for this is that the xfs_bmap_shift_extents() loop uses XFS_IFORK_NEXTENTS() to determine how many extents are in the inode. This, unfortunately, doesn't take into account delayed allocation extents - it's a count of physically allocated extents - and hence when the file being collapsed has a delalloc extent like this one does prior to the range being collapsed: .... ino 0x5788 state idx 4 offset 11 block 4503599627239429 count 1 flag 0 .... it gets the count wrong and terminates the shift loop early. Fix it by using the in-memory extent array size that includes delayed allocation extents to determine the number of extents on the inode. Signed-off-by: Dave Chinner Tested-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_bmap.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 5b6092ef51efa9..f0efc7e970ef10 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c @@ -5413,6 +5413,7 @@ xfs_bmap_shift_extents( int whichfork = XFS_DATA_FORK; int logflags; xfs_filblks_t blockcount = 0; + int total_extents; if (unlikely(XFS_TEST_ERROR( (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && @@ -5429,7 +5430,6 @@ xfs_bmap_shift_extents( ASSERT(current_ext != NULL); ifp = XFS_IFORK_PTR(ip, whichfork); - if (!(ifp->if_flags & XFS_IFEXTENTS)) { /* Read in all the extents */ error = xfs_iread_extents(tp, ip, whichfork); @@ -5456,7 +5456,6 @@ xfs_bmap_shift_extents( /* We are going to change core inode */ logflags = XFS_ILOG_CORE; - if (ifp->if_flags & XFS_IFBROOT) { cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; @@ -5467,8 +5466,14 @@ xfs_bmap_shift_extents( logflags |= XFS_ILOG_DEXT; } - while (nexts++ < num_exts && - *current_ext < XFS_IFORK_NEXTENTS(ip, whichfork)) { + /* + * There may be delalloc extents in the data fork before the range we + * are collapsing out, so we cannot + * use the count of real extents here. Instead we have to calculate it + * from the incore fork. + */ + total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); + while (nexts++ < num_exts && *current_ext < total_extents) { gotp = xfs_iext_get_ext(ifp, *current_ext); xfs_bmbt_get_all(gotp, &got); @@ -5556,10 +5561,11 @@ xfs_bmap_shift_extents( } (*current_ext)++; + total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t); } /* Check if we are done */ - if (*current_ext == XFS_IFORK_NEXTENTS(ip, whichfork)) + if (*current_ext == total_extents) *done = 1; del_cursor: @@ -5568,6 +5574,5 @@ xfs_bmap_shift_extents( error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); xfs_trans_log_inode(tp, ip, logflags); - return error; } From 9c23eccc1e746f64b18fab070a37189b4422e44a Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 17 Apr 2014 08:15:26 +1000 Subject: [PATCH 219/279] xfs: unmount does not wait for shutdown during unmount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And interesting situation can occur if a log IO error occurs during the unmount of a filesystem. The cases reported have the same signature - the update of the superblock counters fails due to a log write IO error: XFS (dm-16): xfs_do_force_shutdown(0x2) called from line 1170 of file fs/xfs/xfs_log.c. Return address = 0xffffffffa08a44a1 XFS (dm-16): Log I/O Error Detected. Shutting down filesystem XFS (dm-16): Unable to update superblock counters. Freespace may not be correct on next mount. XFS (dm-16): xfs_log_force: error 5 returned. XFS (¿-¿¿¿): Please umount the filesystem and rectify the problem(s) It can be seen that the last line of output contains a corrupt device name - this is because the log and xfs_mount structures have already been freed by the time this message is printed. A kernel oops closely follows. The issue is that the shutdown is occurring in a separate IO completion thread to the unmount. Once the shutdown processing has started and all the iclogs are marked with XLOG_STATE_IOERROR, the log shutdown code wakes anyone waiting on a log force so they can process the shutdown error. This wakes up the unmount code that is doing a synchronous transaction to update the superblock counters. The unmount path now sees all the iclogs are marked with XLOG_STATE_IOERROR and so never waits on them again, knowing that if it does, there will not be a wakeup trigger for it and we will hang the unmount if we do. Hence the unmount runs through all the remaining code and frees all the filesystem structures while the xlog_iodone() is still processing the shutdown. When the log shutdown processing completes, xfs_do_force_shutdown() emits the "Please umount the filesystem and rectify the problem(s)" message, and xlog_iodone() then aborts all the objects attached to the iclog. An iclog that has already been freed.... The real issue here is that there is no serialisation point between the log IO and the unmount. We have serialisations points for log writes, log forces, reservations, etc, but we don't actually have any code that wakes for log IO to fully complete. We do that for all other types of object, so why not iclogbufs? Well, it turns out that we can easily do this. We've got xfs_buf handles, and that's what everyone else uses for IO serialisation. i.e. bp->b_sema. So, lets hold iclogbufs locked over IO, and only release the lock in xlog_iodone() when we are finished with the buffer. That way before we tear down the iclog, we can lock and unlock the buffer to ensure IO completion has finished completely before we tear it down. Signed-off-by: Dave Chinner Tested-by: Mike Snitzer Tested-by: Bob Mastors Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_log.c | 53 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 8497a00e399d0b..08624dc6731718 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -1181,11 +1181,14 @@ xlog_iodone(xfs_buf_t *bp) /* log I/O is always issued ASYNC */ ASSERT(XFS_BUF_ISASYNC(bp)); xlog_state_done_syncing(iclog, aborted); + /* - * do not reference the buffer (bp) here as we could race - * with it being freed after writing the unmount record to the - * log. + * drop the buffer lock now that we are done. Nothing references + * the buffer after this, so an unmount waiting on this lock can now + * tear it down safely. As such, it is unsafe to reference the buffer + * (bp) after the unlock as we could race with it being freed. */ + xfs_buf_unlock(bp); } /* @@ -1368,8 +1371,16 @@ xlog_alloc_log( bp = xfs_buf_alloc(mp->m_logdev_targp, 0, BTOBB(log->l_iclog_size), 0); if (!bp) goto out_free_log; - bp->b_iodone = xlog_iodone; + + /* + * The iclogbuf buffer locks are held over IO but we are not going to do + * IO yet. Hence unlock the buffer so that the log IO path can grab it + * when appropriately. + */ ASSERT(xfs_buf_islocked(bp)); + xfs_buf_unlock(bp); + + bp->b_iodone = xlog_iodone; log->l_xbuf = bp; spin_lock_init(&log->l_icloglock); @@ -1398,6 +1409,9 @@ xlog_alloc_log( if (!bp) goto out_free_iclog; + ASSERT(xfs_buf_islocked(bp)); + xfs_buf_unlock(bp); + bp->b_iodone = xlog_iodone; iclog->ic_bp = bp; iclog->ic_data = bp->b_addr; @@ -1422,7 +1436,6 @@ xlog_alloc_log( iclog->ic_callback_tail = &(iclog->ic_callback); iclog->ic_datap = (char *)iclog->ic_data + log->l_iclog_hsize; - ASSERT(xfs_buf_islocked(iclog->ic_bp)); init_waitqueue_head(&iclog->ic_force_wait); init_waitqueue_head(&iclog->ic_write_wait); @@ -1631,6 +1644,12 @@ xlog_cksum( * we transition the iclogs to IOERROR state *after* flushing all existing * iclogs to disk. This is because we don't want anymore new transactions to be * started or completed afterwards. + * + * We lock the iclogbufs here so that we can serialise against IO completion + * during unmount. We might be processing a shutdown triggered during unmount, + * and that can occur asynchronously to the unmount thread, and hence we need to + * ensure that completes before tearing down the iclogbufs. Hence we need to + * hold the buffer lock across the log IO to acheive that. */ STATIC int xlog_bdstrat( @@ -1638,6 +1657,7 @@ xlog_bdstrat( { struct xlog_in_core *iclog = bp->b_fspriv; + xfs_buf_lock(bp); if (iclog->ic_state & XLOG_STATE_IOERROR) { xfs_buf_ioerror(bp, EIO); xfs_buf_stale(bp); @@ -1645,7 +1665,8 @@ xlog_bdstrat( /* * It would seem logical to return EIO here, but we rely on * the log state machine to propagate I/O errors instead of - * doing it here. + * doing it here. Similarly, IO completion will unlock the + * buffer, so we don't do it here. */ return 0; } @@ -1847,14 +1868,28 @@ xlog_dealloc_log( xlog_cil_destroy(log); /* - * always need to ensure that the extra buffer does not point to memory - * owned by another log buffer before we free it. + * Cycle all the iclogbuf locks to make sure all log IO completion + * is done before we tear down these buffers. */ + iclog = log->l_iclog; + for (i = 0; i < log->l_iclog_bufs; i++) { + xfs_buf_lock(iclog->ic_bp); + xfs_buf_unlock(iclog->ic_bp); + iclog = iclog->ic_next; + } + + /* + * Always need to ensure that the extra buffer does not point to memory + * owned by another log buffer before we free it. Also, cycle the lock + * first to ensure we've completed IO on it. + */ + xfs_buf_lock(log->l_xbuf); + xfs_buf_unlock(log->l_xbuf); xfs_buf_set_empty(log->l_xbuf, BTOBB(log->l_iclog_size)); xfs_buf_free(log->l_xbuf); iclog = log->l_iclog; - for (i=0; il_iclog_bufs; i++) { + for (i = 0; i < log->l_iclog_bufs; i++) { xfs_buf_free(iclog->ic_bp); next_iclog = iclog->ic_next; kmem_free(iclog); From 07d5035a289f8bebe0ea86c293b2d5412478c481 Mon Sep 17 00:00:00 2001 From: Dave Chinner Date: Thu, 17 Apr 2014 08:15:27 +1000 Subject: [PATCH 220/279] xfs: wrong error sign conversion during failed DIO writes We negate the error value being returned from a generic function incorrectly. The code path that it is running in returned negative errors, so there is no need to negate it to get the correct error signs here. This was uncovered by generic/019. Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 79e96ce987331c..82afdcb3318395 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -679,7 +679,7 @@ xfs_file_dio_aio_write( goto out; if (mapping->nrpages) { - ret = -filemap_write_and_wait_range(VFS_I(ip)->i_mapping, + ret = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, pos, -1); if (ret) goto out; From 8d6c121018bf60d631c05a4a2efc468a392b97bb Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 17 Apr 2014 08:15:28 +1000 Subject: [PATCH 221/279] xfs: fix buffer use after free on IO error When testing exhaustion of dm snapshots, the following appeared with CONFIG_DEBUG_OBJECTS_FREE enabled: ODEBUG: free active (active state 0) object type: work_struct hint: xfs_buf_iodone_work+0x0/0x1d0 [xfs] indicating that we'd freed a buffer which still had a pending reference, down this path: [ 190.867975] [] debug_check_no_obj_freed+0x22b/0x270 [ 190.880820] [] kmem_cache_free+0xd0/0x370 [ 190.892615] [] xfs_buf_free+0xe4/0x210 [xfs] [ 190.905629] [] xfs_buf_rele+0xe7/0x270 [xfs] [ 190.911770] [] xfs_trans_read_buf_map+0x7b6/0xac0 [xfs] At issue is the fact that if IO fails in xfs_buf_iorequest, we'll queue completion unconditionally, and then call xfs_buf_rele; but if IO failed, there are no IOs remaining, and xfs_buf_rele will free the bp while work is still queued. Fix this by not scheduling completion if the buffer has an error on it; run it immediately. The rest is only comment changes. Thanks to dchinner for spotting the root cause. Signed-off-by: Eric Sandeen Reviewed-by: Brian Foster Signed-off-by: Dave Chinner --- fs/xfs/xfs_buf.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 107f2fdfe41fb9..cb10a0aaab3aa7 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1372,21 +1372,29 @@ xfs_buf_iorequest( xfs_buf_wait_unpin(bp); xfs_buf_hold(bp); - /* Set the count to 1 initially, this will stop an I/O + /* + * Set the count to 1 initially, this will stop an I/O * completion callout which happens before we have started * all the I/O from calling xfs_buf_ioend too early. */ atomic_set(&bp->b_io_remaining, 1); _xfs_buf_ioapply(bp); - _xfs_buf_ioend(bp, 1); + /* + * If _xfs_buf_ioapply failed, we'll get back here with + * only the reference we took above. _xfs_buf_ioend will + * drop it to zero, so we'd better not queue it for later, + * or we'll free it before it's done. + */ + _xfs_buf_ioend(bp, bp->b_error ? 0 : 1); xfs_buf_rele(bp); } /* * Waits for I/O to complete on the buffer supplied. It returns immediately if - * no I/O is pending or there is already a pending error on the buffer. It - * returns the I/O error code, if any, or 0 if there was no error. + * no I/O is pending or there is already a pending error on the buffer, in which + * case nothing will ever complete. It returns the I/O error code, if any, or + * 0 if there was no error. */ int xfs_buf_iowait( From 330033d697ed8d296fa52b5303db9d802ad901cc Mon Sep 17 00:00:00 2001 From: Brian Foster Date: Thu, 17 Apr 2014 08:15:30 +1000 Subject: [PATCH 222/279] xfs: fix tmpfile/selinux deadlock and initialize security xfstests generic/004 reproduces an ilock deadlock using the tmpfile interface when selinux is enabled. This occurs because xfs_create_tmpfile() takes the ilock and then calls d_tmpfile(). The latter eventually calls into xfs_xattr_get() which attempts to get the lock again. E.g.: xfs_io D ffffffff81c134c0 4096 3561 3560 0x00000080 ffff8801176a1a68 0000000000000046 ffff8800b401b540 ffff8801176a1fd8 00000000001d5800 00000000001d5800 ffff8800b401b540 ffff8800b401b540 ffff8800b73a6bd0 fffffffeffffffff ffff8800b73a6bd8 ffff8800b5ddb480 Call Trace: [] schedule+0x29/0x70 [] rwsem_down_read_failed+0xc5/0x120 [] ? xfs_ilock_attr_map_shared+0x1f/0x50 [xfs] [] call_rwsem_down_read_failed+0x14/0x30 [] ? down_read_nested+0x89/0xa0 [] ? xfs_ilock+0x122/0x250 [xfs] [] xfs_ilock+0x122/0x250 [xfs] [] xfs_ilock_attr_map_shared+0x1f/0x50 [xfs] [] xfs_attr_get+0x90/0xe0 [xfs] [] xfs_xattr_get+0x37/0x50 [xfs] [] generic_getxattr+0x4f/0x70 [] inode_doinit_with_dentry+0x1ae/0x650 [] selinux_d_instantiate+0x1c/0x20 [] security_d_instantiate+0x1b/0x30 [] d_instantiate+0x50/0x70 [] d_tmpfile+0xb5/0xc0 [] xfs_create_tmpfile+0x362/0x410 [xfs] [] xfs_vn_tmpfile+0x18/0x20 [xfs] [] path_openat+0x228/0x6a0 [] ? sched_clock+0x9/0x10 [] ? kvm_clock_read+0x27/0x40 [] ? __alloc_fd+0xaf/0x1f0 [] do_filp_open+0x3a/0x90 [] ? _raw_spin_unlock+0x27/0x40 [] ? __alloc_fd+0xaf/0x1f0 [] do_sys_open+0x12e/0x210 [] SyS_open+0x1e/0x20 [] system_call_fastpath+0x16/0x1b xfs_vn_tmpfile() also fails to initialize security on the newly created inode. Pull the d_tmpfile() call up into xfs_vn_tmpfile() after the transaction has been committed and the inode unlocked. Also, initialize security on the inode based on the parent directory provided via the tmpfile call. Signed-off-by: Brian Foster Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- fs/xfs/xfs_inode.c | 5 +++-- fs/xfs/xfs_inode.h | 2 +- fs/xfs/xfs_iops.c | 20 +++++++++++++++++--- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 5e7a38fa6ee6bd..768087bedbac58 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1334,7 +1334,8 @@ int xfs_create_tmpfile( struct xfs_inode *dp, struct dentry *dentry, - umode_t mode) + umode_t mode, + struct xfs_inode **ipp) { struct xfs_mount *mp = dp->i_mount; struct xfs_inode *ip = NULL; @@ -1402,7 +1403,6 @@ xfs_create_tmpfile( xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); ip->i_d.di_nlink--; - d_tmpfile(dentry, VFS_I(ip)); error = xfs_iunlink(tp, ip); if (error) goto out_trans_abort; @@ -1415,6 +1415,7 @@ xfs_create_tmpfile( xfs_qm_dqrele(gdqp); xfs_qm_dqrele(pdqp); + *ipp = ip; return 0; out_trans_abort: diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 396cc1fafd0d5e..f2fcde52b66db9 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -334,7 +334,7 @@ int xfs_lookup(struct xfs_inode *dp, struct xfs_name *name, int xfs_create(struct xfs_inode *dp, struct xfs_name *name, umode_t mode, xfs_dev_t rdev, struct xfs_inode **ipp); int xfs_create_tmpfile(struct xfs_inode *dp, struct dentry *dentry, - umode_t mode); + umode_t mode, struct xfs_inode **ipp); int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, struct xfs_inode *ip); int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 89b07e43ca2881..ef1ca010f41771 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1053,11 +1053,25 @@ xfs_vn_tmpfile( struct dentry *dentry, umode_t mode) { - int error; + int error; + struct xfs_inode *ip; + struct inode *inode; - error = xfs_create_tmpfile(XFS_I(dir), dentry, mode); + error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip); + if (unlikely(error)) + return -error; - return -error; + inode = VFS_I(ip); + + error = xfs_init_security(inode, dir, &dentry->d_name); + if (unlikely(error)) { + iput(inode); + return -error; + } + + d_tmpfile(dentry, inode); + + return 0; } static const struct inode_operations xfs_inode_operations = { From 5d6c97c55984b3b991400692f9e8568a702b93c0 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 16 Apr 2014 19:21:53 -0400 Subject: [PATCH 223/279] tracing: Do not try to recreated toplevel set_ftrace_* files With the restructing of the function tracer working with instances, the "top level" buffer is a bit special, as the function tracing is mapped to the same set of filters. This is done by using a "global_ops" descriptor and having the "set_ftrace_filter" and "set_ftrace_notrace" map to it. When an instance is created, it creates the same files but its for the local instance and not the global_ops. The issues is that the local instance creation shares some code with the global instance one and we end up trying to create th top level "set_ftrace_*" files twice, and on boot up, we get an error like this: Could not create debugfs 'set_ftrace_filter' entry Could not create debugfs 'set_ftrace_notrace' entry The reason they failed to be created was because they were created twice, and the second time gives this error as you can not create the same file twice. Reported-by: Borislav Petkov Signed-off-by: Steven Rostedt --- kernel/trace/trace_functions.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c index 5b781d2be383f7..ffd56351b5217d 100644 --- a/kernel/trace/trace_functions.c +++ b/kernel/trace/trace_functions.c @@ -58,12 +58,16 @@ int ftrace_create_function_files(struct trace_array *tr, { int ret; - /* The top level array uses the "global_ops". */ - if (!(tr->flags & TRACE_ARRAY_FL_GLOBAL)) { - ret = allocate_ftrace_ops(tr); - if (ret) - return ret; - } + /* + * The top level array uses the "global_ops", and the files are + * created on boot up. + */ + if (tr->flags & TRACE_ARRAY_FL_GLOBAL) + return 0; + + ret = allocate_ftrace_ops(tr); + if (ret) + return ret; ftrace_create_filter_files(tr->ops, parent); From 94f8cc0eea03648e5cc5de1a4e7dc464de92cc74 Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Wed, 16 Apr 2014 17:12:30 -0700 Subject: [PATCH 224/279] drivers/base/dd.c incorrect pr_debug() parameters pr_debug() parameters are reverse order of format string Signed-off-by: Frank Rowand Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 06051767393f76..8986b9f22781fa 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -187,8 +187,8 @@ static void driver_bound(struct device *dev) return; } - pr_debug("driver: '%s': %s: bound to device '%s'\n", dev_name(dev), - __func__, dev->driver->name); + pr_debug("driver: '%s': %s: bound to device '%s'\n", dev->driver->name, + __func__, dev_name(dev)); klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); From bae9f746a18ee31bbeeb25ae6615805ed6eca173 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Tue, 15 Apr 2014 12:48:49 -0400 Subject: [PATCH 225/279] cifs: fix error handling cifs_user_readv Coverity says: *** CID 1202537: Dereference after null check (FORWARD_NULL) /fs/cifs/file.c: 2873 in cifs_user_readv() 2867 cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize); 2868 npages = DIV_ROUND_UP(cur_len, PAGE_SIZE); 2869 2870 /* allocate a readdata struct */ 2871 rdata = cifs_readdata_alloc(npages, 2872 cifs_uncached_readv_complete); >>> CID 1202537: Dereference after null check (FORWARD_NULL) >>> Comparing "rdata" to null implies that "rdata" might be null. 2873 if (!rdata) { 2874 rc = -ENOMEM; 2875 goto error; 2876 } 2877 2878 rc = cifs_read_allocate_pages(rdata, npages); ...when we "goto error", rc will be non-zero, and then we end up trying to do a kref_put on the rdata (which is NULL). Fix this by replacing the "goto error" with a "break". Reported-by: Signed-off-by: Jeff Layton Signed-off-by: Steve French --- fs/cifs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index d8ee76241b649c..a875eedfd928e7 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2882,7 +2882,7 @@ ssize_t cifs_user_readv(struct kiocb *iocb, const struct iovec *iov, cifs_uncached_readv_complete); if (!rdata) { rc = -ENOMEM; - goto error; + break; } rc = cifs_read_allocate_pages(rdata, npages); From 1f80c0cc39e587edd06a36b43ba3a3b09d4ac428 Mon Sep 17 00:00:00 2001 From: Michael Opdenacker Date: Tue, 15 Apr 2014 10:06:50 +0200 Subject: [PATCH 226/279] cif: fix dead code This issue was found by Coverity (CID 1202536) This proposes a fix for a statement that creates dead code. The "rc < 0" statement is within code that is run with "rc > 0". It seems like "err < 0" was meant to be used here. This way, the error code is returned by the function. Signed-off-by: Michael Opdenacker Acked-by: Al Viro Signed-off-by: Steve French --- fs/cifs/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/cifs/file.c b/fs/cifs/file.c index a875eedfd928e7..5ed03e0b8b40e2 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2599,7 +2599,7 @@ cifs_writev(struct kiocb *iocb, const struct iovec *iov, ssize_t err; err = generic_write_sync(file, iocb->ki_pos - rc, rc); - if (rc < 0) + if (err < 0) rc = err; } } else { From f7018c21350204c4cf628462f229d44d03545254 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Feb 2014 15:31:38 +0200 Subject: [PATCH 227/279] video: move fbdev to drivers/video/fbdev The drivers/video directory is a mess. It contains generic video related files, directories for backlight, console, linux logo, lots of fbdev device drivers, fbdev framework files. Make some order into the chaos by creating drivers/video/fbdev directory, and move all fbdev related files there. No functionality is changed, although I guess it is possible that some subtle Makefile build order related issue could be created by this patch. Signed-off-by: Tomi Valkeinen Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Acked-by: Rob Clark Acked-by: Jingoo Han Acked-by: Daniel Vetter --- Documentation/DocBook/device-drivers.tmpl | 10 +- drivers/Makefile | 4 +- drivers/staging/xgifb/vb_def.h | 2 +- drivers/staging/xgifb/vb_struct.h | 2 +- drivers/staging/xgifb/vgatypes.h | 4 +- drivers/video/Kconfig | 2476 +---------------- drivers/video/Makefile | 166 +- drivers/video/console/sticon.c | 2 +- drivers/video/console/sticore.c | 2 +- drivers/video/{ => fbdev}/68328fb.c | 0 drivers/video/fbdev/Kconfig | 2474 ++++++++++++++++ drivers/video/fbdev/Makefile | 166 ++ drivers/video/{ => fbdev}/acornfb.c | 0 drivers/video/{ => fbdev}/acornfb.h | 0 drivers/video/{ => fbdev}/amba-clcd.c | 0 drivers/video/{ => fbdev}/amifb.c | 0 drivers/video/{ => fbdev}/arcfb.c | 0 drivers/video/{ => fbdev}/arkfb.c | 0 drivers/video/{ => fbdev}/asiliantfb.c | 0 drivers/video/{ => fbdev}/atafb.c | 0 drivers/video/{ => fbdev}/atafb.h | 0 drivers/video/{ => fbdev}/atafb_iplan2p2.c | 0 drivers/video/{ => fbdev}/atafb_iplan2p4.c | 0 drivers/video/{ => fbdev}/atafb_iplan2p8.c | 0 drivers/video/{ => fbdev}/atafb_mfb.c | 0 drivers/video/{ => fbdev}/atafb_utils.h | 0 drivers/video/{ => fbdev}/atmel_lcdfb.c | 0 drivers/video/{ => fbdev}/aty/Makefile | 0 drivers/video/{ => fbdev}/aty/ati_ids.h | 0 drivers/video/{ => fbdev}/aty/aty128fb.c | 0 drivers/video/{ => fbdev}/aty/atyfb.h | 0 drivers/video/{ => fbdev}/aty/atyfb_base.c | 0 drivers/video/{ => fbdev}/aty/mach64_accel.c | 0 drivers/video/{ => fbdev}/aty/mach64_ct.c | 0 drivers/video/{ => fbdev}/aty/mach64_cursor.c | 0 drivers/video/{ => fbdev}/aty/mach64_gx.c | 0 drivers/video/{ => fbdev}/aty/radeon_accel.c | 0 .../video/{ => fbdev}/aty/radeon_backlight.c | 0 drivers/video/{ => fbdev}/aty/radeon_base.c | 0 drivers/video/{ => fbdev}/aty/radeon_i2c.c | 0 .../video/{ => fbdev}/aty/radeon_monitor.c | 0 drivers/video/{ => fbdev}/aty/radeon_pm.c | 0 drivers/video/{ => fbdev}/aty/radeonfb.h | 0 drivers/video/{ => fbdev}/au1100fb.c | 0 drivers/video/{ => fbdev}/au1100fb.h | 0 drivers/video/{ => fbdev}/au1200fb.c | 0 drivers/video/{ => fbdev}/au1200fb.h | 0 drivers/video/{ => fbdev}/auo_k1900fb.c | 0 drivers/video/{ => fbdev}/auo_k1901fb.c | 0 drivers/video/{ => fbdev}/auo_k190x.c | 0 drivers/video/{ => fbdev}/auo_k190x.h | 0 drivers/video/{ => fbdev}/bf537-lq035.c | 0 drivers/video/{ => fbdev}/bf54x-lq043fb.c | 0 drivers/video/{ => fbdev}/bfin-lq035q1-fb.c | 0 drivers/video/{ => fbdev}/bfin-t350mcqb-fb.c | 0 drivers/video/{ => fbdev}/bfin_adv7393fb.c | 0 drivers/video/{ => fbdev}/bfin_adv7393fb.h | 0 drivers/video/{ => fbdev}/broadsheetfb.c | 0 drivers/video/{ => fbdev}/bt431.h | 0 drivers/video/{ => fbdev}/bt455.h | 0 drivers/video/{ => fbdev}/bw2.c | 0 drivers/video/{ => fbdev}/c2p.h | 0 drivers/video/{ => fbdev}/c2p_core.h | 0 drivers/video/{ => fbdev}/c2p_iplan2.c | 0 drivers/video/{ => fbdev}/c2p_planar.c | 0 drivers/video/{ => fbdev}/carminefb.c | 0 drivers/video/{ => fbdev}/carminefb.h | 0 drivers/video/{ => fbdev}/carminefb_regs.h | 0 drivers/video/{ => fbdev}/cfbcopyarea.c | 0 drivers/video/{ => fbdev}/cfbfillrect.c | 0 drivers/video/{ => fbdev}/cfbimgblt.c | 0 drivers/video/{ => fbdev}/cg14.c | 0 drivers/video/{ => fbdev}/cg3.c | 0 drivers/video/{ => fbdev}/cg6.c | 0 drivers/video/{ => fbdev}/chipsfb.c | 0 drivers/video/{ => fbdev}/cirrusfb.c | 0 drivers/video/{ => fbdev}/clps711xfb.c | 0 drivers/video/{ => fbdev}/cobalt_lcdfb.c | 0 drivers/video/{ => fbdev}/controlfb.c | 0 drivers/video/{ => fbdev}/controlfb.h | 0 drivers/video/{ => fbdev}/cyber2000fb.c | 0 drivers/video/{ => fbdev}/cyber2000fb.h | 0 drivers/video/{ => fbdev}/da8xx-fb.c | 0 drivers/video/{ => fbdev}/dnfb.c | 0 drivers/video/{ => fbdev}/edid.h | 0 drivers/video/{ => fbdev}/efifb.c | 0 drivers/video/{ => fbdev}/ep93xx-fb.c | 0 drivers/video/{ => fbdev}/exynos/Kconfig | 0 drivers/video/{ => fbdev}/exynos/Makefile | 0 .../{ => fbdev}/exynos/exynos_mipi_dsi.c | 0 .../exynos/exynos_mipi_dsi_common.c | 0 .../exynos/exynos_mipi_dsi_common.h | 0 .../exynos/exynos_mipi_dsi_lowlevel.c | 0 .../exynos/exynos_mipi_dsi_lowlevel.h | 0 .../{ => fbdev}/exynos/exynos_mipi_dsi_regs.h | 0 drivers/video/{ => fbdev}/exynos/s6e8ax0.c | 0 drivers/video/{ => fbdev}/fb-puv3.c | 0 drivers/video/{ => fbdev}/fb_ddc.c | 0 drivers/video/{ => fbdev}/fb_defio.c | 0 drivers/video/{ => fbdev}/fb_draw.h | 0 drivers/video/{ => fbdev}/fb_notify.c | 0 drivers/video/{ => fbdev}/fb_sys_fops.c | 0 drivers/video/{ => fbdev}/fbcmap.c | 0 drivers/video/{ => fbdev}/fbcvt.c | 0 drivers/video/{ => fbdev}/fbmem.c | 0 drivers/video/{ => fbdev}/fbmon.c | 0 drivers/video/{ => fbdev}/fbsysfs.c | 0 drivers/video/{ => fbdev}/ffb.c | 0 drivers/video/{ => fbdev}/fm2fb.c | 0 drivers/video/{ => fbdev}/fsl-diu-fb.c | 0 drivers/video/{ => fbdev}/g364fb.c | 0 drivers/video/{ => fbdev}/gbefb.c | 0 drivers/video/{ => fbdev}/geode/Kconfig | 0 drivers/video/{ => fbdev}/geode/Makefile | 0 drivers/video/{ => fbdev}/geode/display_gx.c | 0 drivers/video/{ => fbdev}/geode/display_gx1.c | 0 drivers/video/{ => fbdev}/geode/display_gx1.h | 0 drivers/video/{ => fbdev}/geode/geodefb.h | 0 drivers/video/{ => fbdev}/geode/gx1fb_core.c | 0 drivers/video/{ => fbdev}/geode/gxfb.h | 0 drivers/video/{ => fbdev}/geode/gxfb_core.c | 0 drivers/video/{ => fbdev}/geode/lxfb.h | 0 drivers/video/{ => fbdev}/geode/lxfb_core.c | 0 drivers/video/{ => fbdev}/geode/lxfb_ops.c | 0 drivers/video/{ => fbdev}/geode/suspend_gx.c | 0 .../video/{ => fbdev}/geode/video_cs5530.c | 0 .../video/{ => fbdev}/geode/video_cs5530.h | 0 drivers/video/{ => fbdev}/geode/video_gx.c | 0 drivers/video/{ => fbdev}/goldfishfb.c | 0 drivers/video/{ => fbdev}/grvga.c | 0 drivers/video/{ => fbdev}/gxt4500.c | 0 drivers/video/{ => fbdev}/hecubafb.c | 0 drivers/video/{ => fbdev}/hgafb.c | 0 drivers/video/{ => fbdev}/hitfb.c | 0 drivers/video/{ => fbdev}/hpfb.c | 0 drivers/video/{ => fbdev}/hyperv_fb.c | 0 drivers/video/{ => fbdev}/i740_reg.h | 0 drivers/video/{ => fbdev}/i740fb.c | 0 drivers/video/{ => fbdev}/i810/Makefile | 0 drivers/video/{ => fbdev}/i810/i810-i2c.c | 0 drivers/video/{ => fbdev}/i810/i810.h | 0 drivers/video/{ => fbdev}/i810/i810_accel.c | 0 drivers/video/{ => fbdev}/i810/i810_dvt.c | 0 drivers/video/{ => fbdev}/i810/i810_gtf.c | 0 drivers/video/{ => fbdev}/i810/i810_main.c | 0 drivers/video/{ => fbdev}/i810/i810_main.h | 0 drivers/video/{ => fbdev}/i810/i810_regs.h | 0 drivers/video/{ => fbdev}/igafb.c | 0 drivers/video/{ => fbdev}/imsttfb.c | 0 drivers/video/{ => fbdev}/imxfb.c | 0 drivers/video/{ => fbdev}/intelfb/Makefile | 0 drivers/video/{ => fbdev}/intelfb/intelfb.h | 0 .../video/{ => fbdev}/intelfb/intelfb_i2c.c | 0 .../video/{ => fbdev}/intelfb/intelfbdrv.c | 0 drivers/video/{ => fbdev}/intelfb/intelfbhw.c | 0 drivers/video/{ => fbdev}/intelfb/intelfbhw.h | 0 drivers/video/{ => fbdev}/jz4740_fb.c | 0 drivers/video/{ => fbdev}/kyro/Makefile | 0 .../{ => fbdev}/kyro/STG4000InitDevice.c | 0 .../video/{ => fbdev}/kyro/STG4000Interface.h | 0 .../{ => fbdev}/kyro/STG4000OverlayDevice.c | 0 .../video/{ => fbdev}/kyro/STG4000Ramdac.c | 0 drivers/video/{ => fbdev}/kyro/STG4000Reg.h | 0 drivers/video/{ => fbdev}/kyro/STG4000VTG.c | 0 drivers/video/{ => fbdev}/kyro/fbdev.c | 0 drivers/video/{ => fbdev}/leo.c | 0 drivers/video/{ => fbdev}/macfb.c | 0 drivers/video/{ => fbdev}/macmodes.c | 0 drivers/video/{ => fbdev}/macmodes.h | 0 drivers/video/{ => fbdev}/matrox/Makefile | 0 drivers/video/{ => fbdev}/matrox/g450_pll.c | 0 drivers/video/{ => fbdev}/matrox/g450_pll.h | 0 .../video/{ => fbdev}/matrox/i2c-matroxfb.c | 0 .../{ => fbdev}/matrox/matroxfb_DAC1064.c | 0 .../{ => fbdev}/matrox/matroxfb_DAC1064.h | 0 .../{ => fbdev}/matrox/matroxfb_Ti3026.c | 0 .../{ => fbdev}/matrox/matroxfb_Ti3026.h | 0 .../video/{ => fbdev}/matrox/matroxfb_accel.c | 0 .../video/{ => fbdev}/matrox/matroxfb_accel.h | 0 .../video/{ => fbdev}/matrox/matroxfb_base.c | 0 .../video/{ => fbdev}/matrox/matroxfb_base.h | 0 .../video/{ => fbdev}/matrox/matroxfb_crtc2.c | 0 .../video/{ => fbdev}/matrox/matroxfb_crtc2.h | 0 .../video/{ => fbdev}/matrox/matroxfb_g450.c | 0 .../video/{ => fbdev}/matrox/matroxfb_g450.h | 0 .../video/{ => fbdev}/matrox/matroxfb_maven.c | 0 .../video/{ => fbdev}/matrox/matroxfb_maven.h | 0 .../video/{ => fbdev}/matrox/matroxfb_misc.c | 0 .../video/{ => fbdev}/matrox/matroxfb_misc.h | 0 drivers/video/{ => fbdev}/maxinefb.c | 0 drivers/video/{ => fbdev}/mb862xx/Makefile | 0 .../video/{ => fbdev}/mb862xx/mb862xx-i2c.c | 0 .../video/{ => fbdev}/mb862xx/mb862xx_reg.h | 0 drivers/video/{ => fbdev}/mb862xx/mb862xxfb.h | 0 .../{ => fbdev}/mb862xx/mb862xxfb_accel.c | 0 .../{ => fbdev}/mb862xx/mb862xxfb_accel.h | 0 .../video/{ => fbdev}/mb862xx/mb862xxfbdrv.c | 0 drivers/video/{ => fbdev}/mbx/Makefile | 0 drivers/video/{ => fbdev}/mbx/mbxdebugfs.c | 0 drivers/video/{ => fbdev}/mbx/mbxfb.c | 0 drivers/video/{ => fbdev}/mbx/reg_bits.h | 0 drivers/video/{ => fbdev}/mbx/regs.h | 0 drivers/video/{ => fbdev}/metronomefb.c | 0 drivers/video/{ => fbdev}/mmp/Kconfig | 6 +- drivers/video/{ => fbdev}/mmp/Makefile | 0 drivers/video/{ => fbdev}/mmp/core.c | 0 drivers/video/{ => fbdev}/mmp/fb/Kconfig | 0 drivers/video/{ => fbdev}/mmp/fb/Makefile | 0 drivers/video/{ => fbdev}/mmp/fb/mmpfb.c | 0 drivers/video/{ => fbdev}/mmp/fb/mmpfb.h | 0 drivers/video/{ => fbdev}/mmp/hw/Kconfig | 0 drivers/video/{ => fbdev}/mmp/hw/Makefile | 0 drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.c | 0 drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.h | 0 drivers/video/{ => fbdev}/mmp/hw/mmp_spi.c | 0 drivers/video/{ => fbdev}/mmp/panel/Kconfig | 0 drivers/video/{ => fbdev}/mmp/panel/Makefile | 0 .../{ => fbdev}/mmp/panel/tpo_tj032md01bw.c | 0 drivers/video/{ => fbdev}/modedb.c | 0 drivers/video/{ => fbdev}/msm/Makefile | 0 drivers/video/{ => fbdev}/msm/mddi.c | 0 .../video/{ => fbdev}/msm/mddi_client_dummy.c | 0 .../{ => fbdev}/msm/mddi_client_nt35399.c | 0 .../{ => fbdev}/msm/mddi_client_toshiba.c | 0 drivers/video/{ => fbdev}/msm/mddi_hw.h | 0 drivers/video/{ => fbdev}/msm/mdp.c | 0 drivers/video/{ => fbdev}/msm/mdp_csc_table.h | 0 drivers/video/{ => fbdev}/msm/mdp_hw.h | 0 drivers/video/{ => fbdev}/msm/mdp_ppp.c | 0 .../video/{ => fbdev}/msm/mdp_scale_tables.c | 0 .../video/{ => fbdev}/msm/mdp_scale_tables.h | 0 drivers/video/{ => fbdev}/msm/msm_fb.c | 0 drivers/video/{ => fbdev}/mx3fb.c | 0 drivers/video/{ => fbdev}/mxsfb.c | 0 drivers/video/{ => fbdev}/n411.c | 0 drivers/video/{ => fbdev}/neofb.c | 0 drivers/video/{ => fbdev}/nuc900fb.c | 0 drivers/video/{ => fbdev}/nuc900fb.h | 0 drivers/video/{ => fbdev}/nvidia/Makefile | 0 drivers/video/{ => fbdev}/nvidia/nv_accel.c | 0 .../video/{ => fbdev}/nvidia/nv_backlight.c | 0 drivers/video/{ => fbdev}/nvidia/nv_dma.h | 0 drivers/video/{ => fbdev}/nvidia/nv_hw.c | 0 drivers/video/{ => fbdev}/nvidia/nv_i2c.c | 0 drivers/video/{ => fbdev}/nvidia/nv_local.h | 0 drivers/video/{ => fbdev}/nvidia/nv_of.c | 0 drivers/video/{ => fbdev}/nvidia/nv_proto.h | 0 drivers/video/{ => fbdev}/nvidia/nv_setup.c | 0 drivers/video/{ => fbdev}/nvidia/nv_type.h | 0 drivers/video/{ => fbdev}/nvidia/nvidia.c | 0 drivers/video/{ => fbdev}/ocfb.c | 0 drivers/video/{ => fbdev}/offb.c | 0 drivers/video/{ => fbdev}/omap/Kconfig | 0 drivers/video/{ => fbdev}/omap/Makefile | 0 drivers/video/{ => fbdev}/omap/hwa742.c | 0 .../video/{ => fbdev}/omap/lcd_ams_delta.c | 0 drivers/video/{ => fbdev}/omap/lcd_h3.c | 0 .../video/{ => fbdev}/omap/lcd_htcherald.c | 0 drivers/video/{ => fbdev}/omap/lcd_inn1510.c | 0 drivers/video/{ => fbdev}/omap/lcd_inn1610.c | 0 drivers/video/{ => fbdev}/omap/lcd_mipid.c | 0 drivers/video/{ => fbdev}/omap/lcd_osk.c | 0 drivers/video/{ => fbdev}/omap/lcd_palmte.c | 0 drivers/video/{ => fbdev}/omap/lcd_palmtt.c | 0 drivers/video/{ => fbdev}/omap/lcd_palmz71.c | 0 drivers/video/{ => fbdev}/omap/lcdc.c | 0 drivers/video/{ => fbdev}/omap/lcdc.h | 0 drivers/video/{ => fbdev}/omap/omapfb.h | 0 drivers/video/{ => fbdev}/omap/omapfb_main.c | 0 drivers/video/{ => fbdev}/omap/sossi.c | 0 drivers/video/fbdev/omap2/Kconfig | 10 + drivers/video/{ => fbdev}/omap2/Makefile | 0 .../{ => fbdev}/omap2/displays-new/Kconfig | 0 .../{ => fbdev}/omap2/displays-new/Makefile | 0 .../omap2/displays-new/connector-analog-tv.c | 0 .../omap2/displays-new/connector-dvi.c | 0 .../omap2/displays-new/connector-hdmi.c | 0 .../omap2/displays-new/encoder-tfp410.c | 0 .../omap2/displays-new/encoder-tpd12s015.c | 0 .../omap2/displays-new/panel-dpi.c | 0 .../omap2/displays-new/panel-dsi-cm.c | 0 .../displays-new/panel-lgphilips-lb035q02.c | 0 .../omap2/displays-new/panel-nec-nl8048hl11.c | 0 .../displays-new/panel-sharp-ls037v7dw01.c | 0 .../omap2/displays-new/panel-sony-acx565akm.c | 0 .../omap2/displays-new/panel-tpo-td028ttec1.c | 0 .../omap2/displays-new/panel-tpo-td043mtea1.c | 0 drivers/video/{ => fbdev}/omap2/dss/Kconfig | 0 drivers/video/{ => fbdev}/omap2/dss/Makefile | 0 drivers/video/{ => fbdev}/omap2/dss/apply.c | 0 drivers/video/{ => fbdev}/omap2/dss/core.c | 0 .../{ => fbdev}/omap2/dss/dispc-compat.c | 0 .../{ => fbdev}/omap2/dss/dispc-compat.h | 0 drivers/video/{ => fbdev}/omap2/dss/dispc.c | 0 drivers/video/{ => fbdev}/omap2/dss/dispc.h | 0 .../video/{ => fbdev}/omap2/dss/dispc_coefs.c | 0 .../{ => fbdev}/omap2/dss/display-sysfs.c | 0 drivers/video/{ => fbdev}/omap2/dss/display.c | 0 drivers/video/{ => fbdev}/omap2/dss/dpi.c | 0 drivers/video/{ => fbdev}/omap2/dss/dsi.c | 0 drivers/video/{ => fbdev}/omap2/dss/dss-of.c | 0 drivers/video/{ => fbdev}/omap2/dss/dss.c | 0 drivers/video/{ => fbdev}/omap2/dss/dss.h | 0 .../{ => fbdev}/omap2/dss/dss_features.c | 0 .../{ => fbdev}/omap2/dss/dss_features.h | 0 drivers/video/{ => fbdev}/omap2/dss/hdmi.h | 0 drivers/video/{ => fbdev}/omap2/dss/hdmi4.c | 0 .../video/{ => fbdev}/omap2/dss/hdmi4_core.c | 0 .../video/{ => fbdev}/omap2/dss/hdmi4_core.h | 0 .../video/{ => fbdev}/omap2/dss/hdmi_common.c | 0 .../video/{ => fbdev}/omap2/dss/hdmi_phy.c | 0 .../video/{ => fbdev}/omap2/dss/hdmi_pll.c | 0 drivers/video/{ => fbdev}/omap2/dss/hdmi_wp.c | 0 .../{ => fbdev}/omap2/dss/manager-sysfs.c | 0 drivers/video/{ => fbdev}/omap2/dss/manager.c | 0 drivers/video/{ => fbdev}/omap2/dss/output.c | 0 .../{ => fbdev}/omap2/dss/overlay-sysfs.c | 0 drivers/video/{ => fbdev}/omap2/dss/overlay.c | 0 drivers/video/{ => fbdev}/omap2/dss/rfbi.c | 0 drivers/video/{ => fbdev}/omap2/dss/sdi.c | 0 drivers/video/{ => fbdev}/omap2/dss/venc.c | 0 .../video/{ => fbdev}/omap2/dss/venc_panel.c | 0 .../video/{ => fbdev}/omap2/omapfb/Kconfig | 0 .../video/{ => fbdev}/omap2/omapfb/Makefile | 0 .../{ => fbdev}/omap2/omapfb/omapfb-ioctl.c | 0 .../{ => fbdev}/omap2/omapfb/omapfb-main.c | 0 .../{ => fbdev}/omap2/omapfb/omapfb-sysfs.c | 0 .../video/{ => fbdev}/omap2/omapfb/omapfb.h | 0 drivers/video/{ => fbdev}/omap2/vrfb.c | 0 drivers/video/{ => fbdev}/p9100.c | 0 drivers/video/{ => fbdev}/platinumfb.c | 0 drivers/video/{ => fbdev}/platinumfb.h | 0 drivers/video/{ => fbdev}/pm2fb.c | 0 drivers/video/{ => fbdev}/pm3fb.c | 0 drivers/video/{ => fbdev}/pmag-aa-fb.c | 0 drivers/video/{ => fbdev}/pmag-ba-fb.c | 0 drivers/video/{ => fbdev}/pmagb-b-fb.c | 0 drivers/video/{ => fbdev}/ps3fb.c | 0 drivers/video/{ => fbdev}/pvr2fb.c | 0 drivers/video/{ => fbdev}/pxa168fb.c | 0 drivers/video/{ => fbdev}/pxa168fb.h | 0 drivers/video/{ => fbdev}/pxa3xx-gcu.c | 0 drivers/video/{ => fbdev}/pxa3xx-gcu.h | 0 drivers/video/{ => fbdev}/pxafb.c | 0 drivers/video/{ => fbdev}/pxafb.h | 0 drivers/video/{ => fbdev}/q40fb.c | 0 drivers/video/{ => fbdev}/riva/Makefile | 0 drivers/video/{ => fbdev}/riva/fbdev.c | 0 drivers/video/{ => fbdev}/riva/nv_driver.c | 0 drivers/video/{ => fbdev}/riva/nv_type.h | 0 drivers/video/{ => fbdev}/riva/nvreg.h | 0 drivers/video/{ => fbdev}/riva/riva_hw.c | 0 drivers/video/{ => fbdev}/riva/riva_hw.h | 0 drivers/video/{ => fbdev}/riva/riva_tbl.h | 0 drivers/video/{ => fbdev}/riva/rivafb-i2c.c | 0 drivers/video/{ => fbdev}/riva/rivafb.h | 0 drivers/video/{ => fbdev}/s1d13xxxfb.c | 0 drivers/video/{ => fbdev}/s3c-fb.c | 0 drivers/video/{ => fbdev}/s3c2410fb.c | 0 drivers/video/{ => fbdev}/s3c2410fb.h | 0 drivers/video/{ => fbdev}/s3fb.c | 0 drivers/video/{ => fbdev}/sa1100fb.c | 0 drivers/video/{ => fbdev}/sa1100fb.h | 0 drivers/video/{ => fbdev}/savage/Makefile | 0 .../video/{ => fbdev}/savage/savagefb-i2c.c | 0 drivers/video/{ => fbdev}/savage/savagefb.h | 0 .../video/{ => fbdev}/savage/savagefb_accel.c | 0 .../{ => fbdev}/savage/savagefb_driver.c | 0 drivers/video/{ => fbdev}/sbuslib.c | 0 drivers/video/{ => fbdev}/sbuslib.h | 0 drivers/video/{ => fbdev}/sh7760fb.c | 0 drivers/video/{ => fbdev}/sh_mipi_dsi.c | 0 drivers/video/{ => fbdev}/sh_mobile_hdmi.c | 0 drivers/video/{ => fbdev}/sh_mobile_lcdcfb.c | 0 drivers/video/{ => fbdev}/sh_mobile_lcdcfb.h | 0 drivers/video/{ => fbdev}/sh_mobile_meram.c | 0 drivers/video/{ => fbdev}/simplefb.c | 0 drivers/video/{ => fbdev}/sis/300vtbl.h | 0 drivers/video/{ => fbdev}/sis/310vtbl.h | 0 drivers/video/{ => fbdev}/sis/Makefile | 0 drivers/video/{ => fbdev}/sis/init.c | 0 drivers/video/{ => fbdev}/sis/init.h | 0 drivers/video/{ => fbdev}/sis/init301.c | 0 drivers/video/{ => fbdev}/sis/init301.h | 0 drivers/video/{ => fbdev}/sis/initdef.h | 0 drivers/video/{ => fbdev}/sis/initextlfb.c | 0 drivers/video/{ => fbdev}/sis/oem300.h | 0 drivers/video/{ => fbdev}/sis/oem310.h | 0 drivers/video/{ => fbdev}/sis/sis.h | 0 drivers/video/{ => fbdev}/sis/sis_accel.c | 0 drivers/video/{ => fbdev}/sis/sis_accel.h | 0 drivers/video/{ => fbdev}/sis/sis_main.c | 0 drivers/video/{ => fbdev}/sis/sis_main.h | 0 drivers/video/{ => fbdev}/sis/vgatypes.h | 0 drivers/video/{ => fbdev}/sis/vstruct.h | 0 drivers/video/{ => fbdev}/skeletonfb.c | 0 drivers/video/{ => fbdev}/sm501fb.c | 0 drivers/video/{ => fbdev}/smscufx.c | 0 drivers/video/{ => fbdev}/ssd1307fb.c | 0 drivers/video/{ => fbdev}/sstfb.c | 0 drivers/video/{ => fbdev}/sticore.h | 0 drivers/video/{ => fbdev}/stifb.c | 0 drivers/video/{ => fbdev}/sunxvr1000.c | 0 drivers/video/{ => fbdev}/sunxvr2500.c | 0 drivers/video/{ => fbdev}/sunxvr500.c | 0 drivers/video/{ => fbdev}/svgalib.c | 0 drivers/video/{ => fbdev}/syscopyarea.c | 0 drivers/video/{ => fbdev}/sysfillrect.c | 0 drivers/video/{ => fbdev}/sysimgblt.c | 0 drivers/video/{ => fbdev}/tcx.c | 0 drivers/video/{ => fbdev}/tdfxfb.c | 0 drivers/video/{ => fbdev}/tgafb.c | 0 drivers/video/{ => fbdev}/tmiofb.c | 0 drivers/video/{ => fbdev}/tridentfb.c | 0 drivers/video/{ => fbdev}/udlfb.c | 0 drivers/video/{ => fbdev}/uvesafb.c | 0 drivers/video/{ => fbdev}/valkyriefb.c | 0 drivers/video/{ => fbdev}/valkyriefb.h | 0 drivers/video/{ => fbdev}/vermilion/Makefile | 0 drivers/video/{ => fbdev}/vermilion/cr_pll.c | 0 .../video/{ => fbdev}/vermilion/vermilion.c | 0 .../video/{ => fbdev}/vermilion/vermilion.h | 0 drivers/video/{ => fbdev}/vesafb.c | 0 drivers/video/{ => fbdev}/vfb.c | 0 drivers/video/{ => fbdev}/vga16fb.c | 0 drivers/video/{ => fbdev}/via/Makefile | 0 drivers/video/{ => fbdev}/via/accel.c | 0 drivers/video/{ => fbdev}/via/accel.h | 0 drivers/video/{ => fbdev}/via/chip.h | 0 drivers/video/{ => fbdev}/via/debug.h | 0 drivers/video/{ => fbdev}/via/dvi.c | 0 drivers/video/{ => fbdev}/via/dvi.h | 0 drivers/video/{ => fbdev}/via/global.c | 0 drivers/video/{ => fbdev}/via/global.h | 0 drivers/video/{ => fbdev}/via/hw.c | 0 drivers/video/{ => fbdev}/via/hw.h | 0 drivers/video/{ => fbdev}/via/ioctl.c | 0 drivers/video/{ => fbdev}/via/ioctl.h | 0 drivers/video/{ => fbdev}/via/lcd.c | 0 drivers/video/{ => fbdev}/via/lcd.h | 0 drivers/video/{ => fbdev}/via/share.h | 0 drivers/video/{ => fbdev}/via/tblDPASetting.c | 0 drivers/video/{ => fbdev}/via/tblDPASetting.h | 0 drivers/video/{ => fbdev}/via/via-core.c | 0 drivers/video/{ => fbdev}/via/via-gpio.c | 0 drivers/video/{ => fbdev}/via/via_aux.c | 0 drivers/video/{ => fbdev}/via/via_aux.h | 0 .../video/{ => fbdev}/via/via_aux_ch7301.c | 0 drivers/video/{ => fbdev}/via/via_aux_edid.c | 0 .../video/{ => fbdev}/via/via_aux_sii164.c | 0 .../video/{ => fbdev}/via/via_aux_vt1621.c | 0 .../video/{ => fbdev}/via/via_aux_vt1622.c | 0 .../video/{ => fbdev}/via/via_aux_vt1625.c | 0 .../video/{ => fbdev}/via/via_aux_vt1631.c | 0 .../video/{ => fbdev}/via/via_aux_vt1632.c | 0 .../video/{ => fbdev}/via/via_aux_vt1636.c | 0 drivers/video/{ => fbdev}/via/via_clock.c | 0 drivers/video/{ => fbdev}/via/via_clock.h | 0 drivers/video/{ => fbdev}/via/via_i2c.c | 0 .../video/{ => fbdev}/via/via_modesetting.c | 0 .../video/{ => fbdev}/via/via_modesetting.h | 0 drivers/video/{ => fbdev}/via/via_utility.c | 0 drivers/video/{ => fbdev}/via/via_utility.h | 0 drivers/video/{ => fbdev}/via/viafbdev.c | 0 drivers/video/{ => fbdev}/via/viafbdev.h | 0 drivers/video/{ => fbdev}/via/viamode.c | 0 drivers/video/{ => fbdev}/via/viamode.h | 0 drivers/video/{ => fbdev}/via/vt1636.c | 0 drivers/video/{ => fbdev}/via/vt1636.h | 0 drivers/video/{ => fbdev}/vt8500lcdfb.c | 0 drivers/video/{ => fbdev}/vt8500lcdfb.h | 0 drivers/video/{ => fbdev}/vt8623fb.c | 0 drivers/video/{ => fbdev}/w100fb.c | 0 drivers/video/{ => fbdev}/w100fb.h | 0 drivers/video/{ => fbdev}/wm8505fb.c | 0 drivers/video/{ => fbdev}/wm8505fb_regs.h | 0 drivers/video/{ => fbdev}/wmt_ge_rops.c | 0 drivers/video/{ => fbdev}/wmt_ge_rops.h | 0 drivers/video/{ => fbdev}/xen-fbfront.c | 0 drivers/video/{ => fbdev}/xilinxfb.c | 0 drivers/video/omap2/Kconfig | 10 - 481 files changed, 2672 insertions(+), 2662 deletions(-) rename drivers/video/{ => fbdev}/68328fb.c (100%) create mode 100644 drivers/video/fbdev/Kconfig create mode 100644 drivers/video/fbdev/Makefile rename drivers/video/{ => fbdev}/acornfb.c (100%) rename drivers/video/{ => fbdev}/acornfb.h (100%) rename drivers/video/{ => fbdev}/amba-clcd.c (100%) rename drivers/video/{ => fbdev}/amifb.c (100%) rename drivers/video/{ => fbdev}/arcfb.c (100%) rename drivers/video/{ => fbdev}/arkfb.c (100%) rename drivers/video/{ => fbdev}/asiliantfb.c (100%) rename drivers/video/{ => fbdev}/atafb.c (100%) rename drivers/video/{ => fbdev}/atafb.h (100%) rename drivers/video/{ => fbdev}/atafb_iplan2p2.c (100%) rename drivers/video/{ => fbdev}/atafb_iplan2p4.c (100%) rename drivers/video/{ => fbdev}/atafb_iplan2p8.c (100%) rename drivers/video/{ => fbdev}/atafb_mfb.c (100%) rename drivers/video/{ => fbdev}/atafb_utils.h (100%) rename drivers/video/{ => fbdev}/atmel_lcdfb.c (100%) rename drivers/video/{ => fbdev}/aty/Makefile (100%) rename drivers/video/{ => fbdev}/aty/ati_ids.h (100%) rename drivers/video/{ => fbdev}/aty/aty128fb.c (100%) rename drivers/video/{ => fbdev}/aty/atyfb.h (100%) rename drivers/video/{ => fbdev}/aty/atyfb_base.c (100%) rename drivers/video/{ => fbdev}/aty/mach64_accel.c (100%) rename drivers/video/{ => fbdev}/aty/mach64_ct.c (100%) rename drivers/video/{ => fbdev}/aty/mach64_cursor.c (100%) rename drivers/video/{ => fbdev}/aty/mach64_gx.c (100%) rename drivers/video/{ => fbdev}/aty/radeon_accel.c (100%) rename drivers/video/{ => fbdev}/aty/radeon_backlight.c (100%) rename drivers/video/{ => fbdev}/aty/radeon_base.c (100%) rename drivers/video/{ => fbdev}/aty/radeon_i2c.c (100%) rename drivers/video/{ => fbdev}/aty/radeon_monitor.c (100%) rename drivers/video/{ => fbdev}/aty/radeon_pm.c (100%) rename drivers/video/{ => fbdev}/aty/radeonfb.h (100%) rename drivers/video/{ => fbdev}/au1100fb.c (100%) rename drivers/video/{ => fbdev}/au1100fb.h (100%) rename drivers/video/{ => fbdev}/au1200fb.c (100%) rename drivers/video/{ => fbdev}/au1200fb.h (100%) rename drivers/video/{ => fbdev}/auo_k1900fb.c (100%) rename drivers/video/{ => fbdev}/auo_k1901fb.c (100%) rename drivers/video/{ => fbdev}/auo_k190x.c (100%) rename drivers/video/{ => fbdev}/auo_k190x.h (100%) rename drivers/video/{ => fbdev}/bf537-lq035.c (100%) rename drivers/video/{ => fbdev}/bf54x-lq043fb.c (100%) rename drivers/video/{ => fbdev}/bfin-lq035q1-fb.c (100%) rename drivers/video/{ => fbdev}/bfin-t350mcqb-fb.c (100%) rename drivers/video/{ => fbdev}/bfin_adv7393fb.c (100%) rename drivers/video/{ => fbdev}/bfin_adv7393fb.h (100%) rename drivers/video/{ => fbdev}/broadsheetfb.c (100%) rename drivers/video/{ => fbdev}/bt431.h (100%) rename drivers/video/{ => fbdev}/bt455.h (100%) rename drivers/video/{ => fbdev}/bw2.c (100%) rename drivers/video/{ => fbdev}/c2p.h (100%) rename drivers/video/{ => fbdev}/c2p_core.h (100%) rename drivers/video/{ => fbdev}/c2p_iplan2.c (100%) rename drivers/video/{ => fbdev}/c2p_planar.c (100%) rename drivers/video/{ => fbdev}/carminefb.c (100%) rename drivers/video/{ => fbdev}/carminefb.h (100%) rename drivers/video/{ => fbdev}/carminefb_regs.h (100%) rename drivers/video/{ => fbdev}/cfbcopyarea.c (100%) rename drivers/video/{ => fbdev}/cfbfillrect.c (100%) rename drivers/video/{ => fbdev}/cfbimgblt.c (100%) rename drivers/video/{ => fbdev}/cg14.c (100%) rename drivers/video/{ => fbdev}/cg3.c (100%) rename drivers/video/{ => fbdev}/cg6.c (100%) rename drivers/video/{ => fbdev}/chipsfb.c (100%) rename drivers/video/{ => fbdev}/cirrusfb.c (100%) rename drivers/video/{ => fbdev}/clps711xfb.c (100%) rename drivers/video/{ => fbdev}/cobalt_lcdfb.c (100%) rename drivers/video/{ => fbdev}/controlfb.c (100%) rename drivers/video/{ => fbdev}/controlfb.h (100%) rename drivers/video/{ => fbdev}/cyber2000fb.c (100%) rename drivers/video/{ => fbdev}/cyber2000fb.h (100%) rename drivers/video/{ => fbdev}/da8xx-fb.c (100%) rename drivers/video/{ => fbdev}/dnfb.c (100%) rename drivers/video/{ => fbdev}/edid.h (100%) rename drivers/video/{ => fbdev}/efifb.c (100%) rename drivers/video/{ => fbdev}/ep93xx-fb.c (100%) rename drivers/video/{ => fbdev}/exynos/Kconfig (100%) rename drivers/video/{ => fbdev}/exynos/Makefile (100%) rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi.c (100%) rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_common.c (100%) rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_common.h (100%) rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_lowlevel.c (100%) rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_lowlevel.h (100%) rename drivers/video/{ => fbdev}/exynos/exynos_mipi_dsi_regs.h (100%) rename drivers/video/{ => fbdev}/exynos/s6e8ax0.c (100%) rename drivers/video/{ => fbdev}/fb-puv3.c (100%) rename drivers/video/{ => fbdev}/fb_ddc.c (100%) rename drivers/video/{ => fbdev}/fb_defio.c (100%) rename drivers/video/{ => fbdev}/fb_draw.h (100%) rename drivers/video/{ => fbdev}/fb_notify.c (100%) rename drivers/video/{ => fbdev}/fb_sys_fops.c (100%) rename drivers/video/{ => fbdev}/fbcmap.c (100%) rename drivers/video/{ => fbdev}/fbcvt.c (100%) rename drivers/video/{ => fbdev}/fbmem.c (100%) rename drivers/video/{ => fbdev}/fbmon.c (100%) rename drivers/video/{ => fbdev}/fbsysfs.c (100%) rename drivers/video/{ => fbdev}/ffb.c (100%) rename drivers/video/{ => fbdev}/fm2fb.c (100%) rename drivers/video/{ => fbdev}/fsl-diu-fb.c (100%) rename drivers/video/{ => fbdev}/g364fb.c (100%) rename drivers/video/{ => fbdev}/gbefb.c (100%) rename drivers/video/{ => fbdev}/geode/Kconfig (100%) rename drivers/video/{ => fbdev}/geode/Makefile (100%) rename drivers/video/{ => fbdev}/geode/display_gx.c (100%) rename drivers/video/{ => fbdev}/geode/display_gx1.c (100%) rename drivers/video/{ => fbdev}/geode/display_gx1.h (100%) rename drivers/video/{ => fbdev}/geode/geodefb.h (100%) rename drivers/video/{ => fbdev}/geode/gx1fb_core.c (100%) rename drivers/video/{ => fbdev}/geode/gxfb.h (100%) rename drivers/video/{ => fbdev}/geode/gxfb_core.c (100%) rename drivers/video/{ => fbdev}/geode/lxfb.h (100%) rename drivers/video/{ => fbdev}/geode/lxfb_core.c (100%) rename drivers/video/{ => fbdev}/geode/lxfb_ops.c (100%) rename drivers/video/{ => fbdev}/geode/suspend_gx.c (100%) rename drivers/video/{ => fbdev}/geode/video_cs5530.c (100%) rename drivers/video/{ => fbdev}/geode/video_cs5530.h (100%) rename drivers/video/{ => fbdev}/geode/video_gx.c (100%) rename drivers/video/{ => fbdev}/goldfishfb.c (100%) rename drivers/video/{ => fbdev}/grvga.c (100%) rename drivers/video/{ => fbdev}/gxt4500.c (100%) rename drivers/video/{ => fbdev}/hecubafb.c (100%) rename drivers/video/{ => fbdev}/hgafb.c (100%) rename drivers/video/{ => fbdev}/hitfb.c (100%) rename drivers/video/{ => fbdev}/hpfb.c (100%) rename drivers/video/{ => fbdev}/hyperv_fb.c (100%) rename drivers/video/{ => fbdev}/i740_reg.h (100%) rename drivers/video/{ => fbdev}/i740fb.c (100%) rename drivers/video/{ => fbdev}/i810/Makefile (100%) rename drivers/video/{ => fbdev}/i810/i810-i2c.c (100%) rename drivers/video/{ => fbdev}/i810/i810.h (100%) rename drivers/video/{ => fbdev}/i810/i810_accel.c (100%) rename drivers/video/{ => fbdev}/i810/i810_dvt.c (100%) rename drivers/video/{ => fbdev}/i810/i810_gtf.c (100%) rename drivers/video/{ => fbdev}/i810/i810_main.c (100%) rename drivers/video/{ => fbdev}/i810/i810_main.h (100%) rename drivers/video/{ => fbdev}/i810/i810_regs.h (100%) rename drivers/video/{ => fbdev}/igafb.c (100%) rename drivers/video/{ => fbdev}/imsttfb.c (100%) rename drivers/video/{ => fbdev}/imxfb.c (100%) rename drivers/video/{ => fbdev}/intelfb/Makefile (100%) rename drivers/video/{ => fbdev}/intelfb/intelfb.h (100%) rename drivers/video/{ => fbdev}/intelfb/intelfb_i2c.c (100%) rename drivers/video/{ => fbdev}/intelfb/intelfbdrv.c (100%) rename drivers/video/{ => fbdev}/intelfb/intelfbhw.c (100%) rename drivers/video/{ => fbdev}/intelfb/intelfbhw.h (100%) rename drivers/video/{ => fbdev}/jz4740_fb.c (100%) rename drivers/video/{ => fbdev}/kyro/Makefile (100%) rename drivers/video/{ => fbdev}/kyro/STG4000InitDevice.c (100%) rename drivers/video/{ => fbdev}/kyro/STG4000Interface.h (100%) rename drivers/video/{ => fbdev}/kyro/STG4000OverlayDevice.c (100%) rename drivers/video/{ => fbdev}/kyro/STG4000Ramdac.c (100%) rename drivers/video/{ => fbdev}/kyro/STG4000Reg.h (100%) rename drivers/video/{ => fbdev}/kyro/STG4000VTG.c (100%) rename drivers/video/{ => fbdev}/kyro/fbdev.c (100%) rename drivers/video/{ => fbdev}/leo.c (100%) rename drivers/video/{ => fbdev}/macfb.c (100%) rename drivers/video/{ => fbdev}/macmodes.c (100%) rename drivers/video/{ => fbdev}/macmodes.h (100%) rename drivers/video/{ => fbdev}/matrox/Makefile (100%) rename drivers/video/{ => fbdev}/matrox/g450_pll.c (100%) rename drivers/video/{ => fbdev}/matrox/g450_pll.h (100%) rename drivers/video/{ => fbdev}/matrox/i2c-matroxfb.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_DAC1064.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_DAC1064.h (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_Ti3026.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_Ti3026.h (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_accel.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_accel.h (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_base.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_base.h (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_crtc2.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_crtc2.h (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_g450.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_g450.h (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_maven.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_maven.h (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_misc.c (100%) rename drivers/video/{ => fbdev}/matrox/matroxfb_misc.h (100%) rename drivers/video/{ => fbdev}/maxinefb.c (100%) rename drivers/video/{ => fbdev}/mb862xx/Makefile (100%) rename drivers/video/{ => fbdev}/mb862xx/mb862xx-i2c.c (100%) rename drivers/video/{ => fbdev}/mb862xx/mb862xx_reg.h (100%) rename drivers/video/{ => fbdev}/mb862xx/mb862xxfb.h (100%) rename drivers/video/{ => fbdev}/mb862xx/mb862xxfb_accel.c (100%) rename drivers/video/{ => fbdev}/mb862xx/mb862xxfb_accel.h (100%) rename drivers/video/{ => fbdev}/mb862xx/mb862xxfbdrv.c (100%) rename drivers/video/{ => fbdev}/mbx/Makefile (100%) rename drivers/video/{ => fbdev}/mbx/mbxdebugfs.c (100%) rename drivers/video/{ => fbdev}/mbx/mbxfb.c (100%) rename drivers/video/{ => fbdev}/mbx/reg_bits.h (100%) rename drivers/video/{ => fbdev}/mbx/regs.h (100%) rename drivers/video/{ => fbdev}/metronomefb.c (100%) rename drivers/video/{ => fbdev}/mmp/Kconfig (61%) rename drivers/video/{ => fbdev}/mmp/Makefile (100%) rename drivers/video/{ => fbdev}/mmp/core.c (100%) rename drivers/video/{ => fbdev}/mmp/fb/Kconfig (100%) rename drivers/video/{ => fbdev}/mmp/fb/Makefile (100%) rename drivers/video/{ => fbdev}/mmp/fb/mmpfb.c (100%) rename drivers/video/{ => fbdev}/mmp/fb/mmpfb.h (100%) rename drivers/video/{ => fbdev}/mmp/hw/Kconfig (100%) rename drivers/video/{ => fbdev}/mmp/hw/Makefile (100%) rename drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.c (100%) rename drivers/video/{ => fbdev}/mmp/hw/mmp_ctrl.h (100%) rename drivers/video/{ => fbdev}/mmp/hw/mmp_spi.c (100%) rename drivers/video/{ => fbdev}/mmp/panel/Kconfig (100%) rename drivers/video/{ => fbdev}/mmp/panel/Makefile (100%) rename drivers/video/{ => fbdev}/mmp/panel/tpo_tj032md01bw.c (100%) rename drivers/video/{ => fbdev}/modedb.c (100%) rename drivers/video/{ => fbdev}/msm/Makefile (100%) rename drivers/video/{ => fbdev}/msm/mddi.c (100%) rename drivers/video/{ => fbdev}/msm/mddi_client_dummy.c (100%) rename drivers/video/{ => fbdev}/msm/mddi_client_nt35399.c (100%) rename drivers/video/{ => fbdev}/msm/mddi_client_toshiba.c (100%) rename drivers/video/{ => fbdev}/msm/mddi_hw.h (100%) rename drivers/video/{ => fbdev}/msm/mdp.c (100%) rename drivers/video/{ => fbdev}/msm/mdp_csc_table.h (100%) rename drivers/video/{ => fbdev}/msm/mdp_hw.h (100%) rename drivers/video/{ => fbdev}/msm/mdp_ppp.c (100%) rename drivers/video/{ => fbdev}/msm/mdp_scale_tables.c (100%) rename drivers/video/{ => fbdev}/msm/mdp_scale_tables.h (100%) rename drivers/video/{ => fbdev}/msm/msm_fb.c (100%) rename drivers/video/{ => fbdev}/mx3fb.c (100%) rename drivers/video/{ => fbdev}/mxsfb.c (100%) rename drivers/video/{ => fbdev}/n411.c (100%) rename drivers/video/{ => fbdev}/neofb.c (100%) rename drivers/video/{ => fbdev}/nuc900fb.c (100%) rename drivers/video/{ => fbdev}/nuc900fb.h (100%) rename drivers/video/{ => fbdev}/nvidia/Makefile (100%) rename drivers/video/{ => fbdev}/nvidia/nv_accel.c (100%) rename drivers/video/{ => fbdev}/nvidia/nv_backlight.c (100%) rename drivers/video/{ => fbdev}/nvidia/nv_dma.h (100%) rename drivers/video/{ => fbdev}/nvidia/nv_hw.c (100%) rename drivers/video/{ => fbdev}/nvidia/nv_i2c.c (100%) rename drivers/video/{ => fbdev}/nvidia/nv_local.h (100%) rename drivers/video/{ => fbdev}/nvidia/nv_of.c (100%) rename drivers/video/{ => fbdev}/nvidia/nv_proto.h (100%) rename drivers/video/{ => fbdev}/nvidia/nv_setup.c (100%) rename drivers/video/{ => fbdev}/nvidia/nv_type.h (100%) rename drivers/video/{ => fbdev}/nvidia/nvidia.c (100%) rename drivers/video/{ => fbdev}/ocfb.c (100%) rename drivers/video/{ => fbdev}/offb.c (100%) rename drivers/video/{ => fbdev}/omap/Kconfig (100%) rename drivers/video/{ => fbdev}/omap/Makefile (100%) rename drivers/video/{ => fbdev}/omap/hwa742.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_ams_delta.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_h3.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_htcherald.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_inn1510.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_inn1610.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_mipid.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_osk.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_palmte.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_palmtt.c (100%) rename drivers/video/{ => fbdev}/omap/lcd_palmz71.c (100%) rename drivers/video/{ => fbdev}/omap/lcdc.c (100%) rename drivers/video/{ => fbdev}/omap/lcdc.h (100%) rename drivers/video/{ => fbdev}/omap/omapfb.h (100%) rename drivers/video/{ => fbdev}/omap/omapfb_main.c (100%) rename drivers/video/{ => fbdev}/omap/sossi.c (100%) create mode 100644 drivers/video/fbdev/omap2/Kconfig rename drivers/video/{ => fbdev}/omap2/Makefile (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/Kconfig (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/Makefile (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/connector-analog-tv.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/connector-dvi.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/connector-hdmi.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/encoder-tfp410.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/encoder-tpd12s015.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-dpi.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-dsi-cm.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-lgphilips-lb035q02.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-nec-nl8048hl11.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-sharp-ls037v7dw01.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-sony-acx565akm.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-tpo-td028ttec1.c (100%) rename drivers/video/{ => fbdev}/omap2/displays-new/panel-tpo-td043mtea1.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/Kconfig (100%) rename drivers/video/{ => fbdev}/omap2/dss/Makefile (100%) rename drivers/video/{ => fbdev}/omap2/dss/apply.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/core.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dispc-compat.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dispc-compat.h (100%) rename drivers/video/{ => fbdev}/omap2/dss/dispc.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dispc.h (100%) rename drivers/video/{ => fbdev}/omap2/dss/dispc_coefs.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/display-sysfs.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/display.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dpi.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dsi.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dss-of.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dss.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dss.h (100%) rename drivers/video/{ => fbdev}/omap2/dss/dss_features.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/dss_features.h (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi.h (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi4.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi4_core.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi4_core.h (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi_common.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi_phy.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi_pll.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/hdmi_wp.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/manager-sysfs.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/manager.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/output.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/overlay-sysfs.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/overlay.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/rfbi.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/sdi.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/venc.c (100%) rename drivers/video/{ => fbdev}/omap2/dss/venc_panel.c (100%) rename drivers/video/{ => fbdev}/omap2/omapfb/Kconfig (100%) rename drivers/video/{ => fbdev}/omap2/omapfb/Makefile (100%) rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb-ioctl.c (100%) rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb-main.c (100%) rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb-sysfs.c (100%) rename drivers/video/{ => fbdev}/omap2/omapfb/omapfb.h (100%) rename drivers/video/{ => fbdev}/omap2/vrfb.c (100%) rename drivers/video/{ => fbdev}/p9100.c (100%) rename drivers/video/{ => fbdev}/platinumfb.c (100%) rename drivers/video/{ => fbdev}/platinumfb.h (100%) rename drivers/video/{ => fbdev}/pm2fb.c (100%) rename drivers/video/{ => fbdev}/pm3fb.c (100%) rename drivers/video/{ => fbdev}/pmag-aa-fb.c (100%) rename drivers/video/{ => fbdev}/pmag-ba-fb.c (100%) rename drivers/video/{ => fbdev}/pmagb-b-fb.c (100%) rename drivers/video/{ => fbdev}/ps3fb.c (100%) rename drivers/video/{ => fbdev}/pvr2fb.c (100%) rename drivers/video/{ => fbdev}/pxa168fb.c (100%) rename drivers/video/{ => fbdev}/pxa168fb.h (100%) rename drivers/video/{ => fbdev}/pxa3xx-gcu.c (100%) rename drivers/video/{ => fbdev}/pxa3xx-gcu.h (100%) rename drivers/video/{ => fbdev}/pxafb.c (100%) rename drivers/video/{ => fbdev}/pxafb.h (100%) rename drivers/video/{ => fbdev}/q40fb.c (100%) rename drivers/video/{ => fbdev}/riva/Makefile (100%) rename drivers/video/{ => fbdev}/riva/fbdev.c (100%) rename drivers/video/{ => fbdev}/riva/nv_driver.c (100%) rename drivers/video/{ => fbdev}/riva/nv_type.h (100%) rename drivers/video/{ => fbdev}/riva/nvreg.h (100%) rename drivers/video/{ => fbdev}/riva/riva_hw.c (100%) rename drivers/video/{ => fbdev}/riva/riva_hw.h (100%) rename drivers/video/{ => fbdev}/riva/riva_tbl.h (100%) rename drivers/video/{ => fbdev}/riva/rivafb-i2c.c (100%) rename drivers/video/{ => fbdev}/riva/rivafb.h (100%) rename drivers/video/{ => fbdev}/s1d13xxxfb.c (100%) rename drivers/video/{ => fbdev}/s3c-fb.c (100%) rename drivers/video/{ => fbdev}/s3c2410fb.c (100%) rename drivers/video/{ => fbdev}/s3c2410fb.h (100%) rename drivers/video/{ => fbdev}/s3fb.c (100%) rename drivers/video/{ => fbdev}/sa1100fb.c (100%) rename drivers/video/{ => fbdev}/sa1100fb.h (100%) rename drivers/video/{ => fbdev}/savage/Makefile (100%) rename drivers/video/{ => fbdev}/savage/savagefb-i2c.c (100%) rename drivers/video/{ => fbdev}/savage/savagefb.h (100%) rename drivers/video/{ => fbdev}/savage/savagefb_accel.c (100%) rename drivers/video/{ => fbdev}/savage/savagefb_driver.c (100%) rename drivers/video/{ => fbdev}/sbuslib.c (100%) rename drivers/video/{ => fbdev}/sbuslib.h (100%) rename drivers/video/{ => fbdev}/sh7760fb.c (100%) rename drivers/video/{ => fbdev}/sh_mipi_dsi.c (100%) rename drivers/video/{ => fbdev}/sh_mobile_hdmi.c (100%) rename drivers/video/{ => fbdev}/sh_mobile_lcdcfb.c (100%) rename drivers/video/{ => fbdev}/sh_mobile_lcdcfb.h (100%) rename drivers/video/{ => fbdev}/sh_mobile_meram.c (100%) rename drivers/video/{ => fbdev}/simplefb.c (100%) rename drivers/video/{ => fbdev}/sis/300vtbl.h (100%) rename drivers/video/{ => fbdev}/sis/310vtbl.h (100%) rename drivers/video/{ => fbdev}/sis/Makefile (100%) rename drivers/video/{ => fbdev}/sis/init.c (100%) rename drivers/video/{ => fbdev}/sis/init.h (100%) rename drivers/video/{ => fbdev}/sis/init301.c (100%) rename drivers/video/{ => fbdev}/sis/init301.h (100%) rename drivers/video/{ => fbdev}/sis/initdef.h (100%) rename drivers/video/{ => fbdev}/sis/initextlfb.c (100%) rename drivers/video/{ => fbdev}/sis/oem300.h (100%) rename drivers/video/{ => fbdev}/sis/oem310.h (100%) rename drivers/video/{ => fbdev}/sis/sis.h (100%) rename drivers/video/{ => fbdev}/sis/sis_accel.c (100%) rename drivers/video/{ => fbdev}/sis/sis_accel.h (100%) rename drivers/video/{ => fbdev}/sis/sis_main.c (100%) rename drivers/video/{ => fbdev}/sis/sis_main.h (100%) rename drivers/video/{ => fbdev}/sis/vgatypes.h (100%) rename drivers/video/{ => fbdev}/sis/vstruct.h (100%) rename drivers/video/{ => fbdev}/skeletonfb.c (100%) rename drivers/video/{ => fbdev}/sm501fb.c (100%) rename drivers/video/{ => fbdev}/smscufx.c (100%) rename drivers/video/{ => fbdev}/ssd1307fb.c (100%) rename drivers/video/{ => fbdev}/sstfb.c (100%) rename drivers/video/{ => fbdev}/sticore.h (100%) rename drivers/video/{ => fbdev}/stifb.c (100%) rename drivers/video/{ => fbdev}/sunxvr1000.c (100%) rename drivers/video/{ => fbdev}/sunxvr2500.c (100%) rename drivers/video/{ => fbdev}/sunxvr500.c (100%) rename drivers/video/{ => fbdev}/svgalib.c (100%) rename drivers/video/{ => fbdev}/syscopyarea.c (100%) rename drivers/video/{ => fbdev}/sysfillrect.c (100%) rename drivers/video/{ => fbdev}/sysimgblt.c (100%) rename drivers/video/{ => fbdev}/tcx.c (100%) rename drivers/video/{ => fbdev}/tdfxfb.c (100%) rename drivers/video/{ => fbdev}/tgafb.c (100%) rename drivers/video/{ => fbdev}/tmiofb.c (100%) rename drivers/video/{ => fbdev}/tridentfb.c (100%) rename drivers/video/{ => fbdev}/udlfb.c (100%) rename drivers/video/{ => fbdev}/uvesafb.c (100%) rename drivers/video/{ => fbdev}/valkyriefb.c (100%) rename drivers/video/{ => fbdev}/valkyriefb.h (100%) rename drivers/video/{ => fbdev}/vermilion/Makefile (100%) rename drivers/video/{ => fbdev}/vermilion/cr_pll.c (100%) rename drivers/video/{ => fbdev}/vermilion/vermilion.c (100%) rename drivers/video/{ => fbdev}/vermilion/vermilion.h (100%) rename drivers/video/{ => fbdev}/vesafb.c (100%) rename drivers/video/{ => fbdev}/vfb.c (100%) rename drivers/video/{ => fbdev}/vga16fb.c (100%) rename drivers/video/{ => fbdev}/via/Makefile (100%) rename drivers/video/{ => fbdev}/via/accel.c (100%) rename drivers/video/{ => fbdev}/via/accel.h (100%) rename drivers/video/{ => fbdev}/via/chip.h (100%) rename drivers/video/{ => fbdev}/via/debug.h (100%) rename drivers/video/{ => fbdev}/via/dvi.c (100%) rename drivers/video/{ => fbdev}/via/dvi.h (100%) rename drivers/video/{ => fbdev}/via/global.c (100%) rename drivers/video/{ => fbdev}/via/global.h (100%) rename drivers/video/{ => fbdev}/via/hw.c (100%) rename drivers/video/{ => fbdev}/via/hw.h (100%) rename drivers/video/{ => fbdev}/via/ioctl.c (100%) rename drivers/video/{ => fbdev}/via/ioctl.h (100%) rename drivers/video/{ => fbdev}/via/lcd.c (100%) rename drivers/video/{ => fbdev}/via/lcd.h (100%) rename drivers/video/{ => fbdev}/via/share.h (100%) rename drivers/video/{ => fbdev}/via/tblDPASetting.c (100%) rename drivers/video/{ => fbdev}/via/tblDPASetting.h (100%) rename drivers/video/{ => fbdev}/via/via-core.c (100%) rename drivers/video/{ => fbdev}/via/via-gpio.c (100%) rename drivers/video/{ => fbdev}/via/via_aux.c (100%) rename drivers/video/{ => fbdev}/via/via_aux.h (100%) rename drivers/video/{ => fbdev}/via/via_aux_ch7301.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_edid.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_sii164.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_vt1621.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_vt1622.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_vt1625.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_vt1631.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_vt1632.c (100%) rename drivers/video/{ => fbdev}/via/via_aux_vt1636.c (100%) rename drivers/video/{ => fbdev}/via/via_clock.c (100%) rename drivers/video/{ => fbdev}/via/via_clock.h (100%) rename drivers/video/{ => fbdev}/via/via_i2c.c (100%) rename drivers/video/{ => fbdev}/via/via_modesetting.c (100%) rename drivers/video/{ => fbdev}/via/via_modesetting.h (100%) rename drivers/video/{ => fbdev}/via/via_utility.c (100%) rename drivers/video/{ => fbdev}/via/via_utility.h (100%) rename drivers/video/{ => fbdev}/via/viafbdev.c (100%) rename drivers/video/{ => fbdev}/via/viafbdev.h (100%) rename drivers/video/{ => fbdev}/via/viamode.c (100%) rename drivers/video/{ => fbdev}/via/viamode.h (100%) rename drivers/video/{ => fbdev}/via/vt1636.c (100%) rename drivers/video/{ => fbdev}/via/vt1636.h (100%) rename drivers/video/{ => fbdev}/vt8500lcdfb.c (100%) rename drivers/video/{ => fbdev}/vt8500lcdfb.h (100%) rename drivers/video/{ => fbdev}/vt8623fb.c (100%) rename drivers/video/{ => fbdev}/w100fb.c (100%) rename drivers/video/{ => fbdev}/w100fb.h (100%) rename drivers/video/{ => fbdev}/wm8505fb.c (100%) rename drivers/video/{ => fbdev}/wm8505fb_regs.h (100%) rename drivers/video/{ => fbdev}/wmt_ge_rops.c (100%) rename drivers/video/{ => fbdev}/wmt_ge_rops.h (100%) rename drivers/video/{ => fbdev}/xen-fbfront.c (100%) rename drivers/video/{ => fbdev}/xilinxfb.c (100%) delete mode 100644 drivers/video/omap2/Kconfig diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index f5170082bdb373..4d1aa8b44be766 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -276,7 +276,7 @@ X!Isound/sound_firmware.c Frame Buffer Memory -!Edrivers/video/fbmem.c +!Edrivers/video/fbdev/fbmem.c Frame Buffer Colormap -!Edrivers/video/fbcmap.c +!Edrivers/video/fbdev/fbcmap.c Frame Buffer Video Mode Database -!Idrivers/video/modedb.c -!Edrivers/video/modedb.c +!Idrivers/video/fbdev/modedb.c +!Edrivers/video/fbdev/modedb.c Frame Buffer Macintosh Video Mode Database -!Edrivers/video/macmodes.c +!Edrivers/video/fbdev/macmodes.c Frame Buffer Fonts diff --git a/drivers/Makefile b/drivers/Makefile index e3ced91b1784af..d05d81b19b50c2 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -53,8 +53,8 @@ obj-y += gpu/ obj-$(CONFIG_CONNECTOR) += connector/ # i810fb and intelfb depend on char/agp/ -obj-$(CONFIG_FB_I810) += video/i810/ -obj-$(CONFIG_FB_INTEL) += video/intelfb/ +obj-$(CONFIG_FB_I810) += video/fbdev/i810/ +obj-$(CONFIG_FB_INTEL) += video/fbdev/intelfb/ obj-$(CONFIG_PARPORT) += parport/ obj-y += base/ block/ misc/ mfd/ nfc/ diff --git a/drivers/staging/xgifb/vb_def.h b/drivers/staging/xgifb/vb_def.h index 5c739bebd8a518..949f0e5eed8d42 100644 --- a/drivers/staging/xgifb/vb_def.h +++ b/drivers/staging/xgifb/vb_def.h @@ -1,6 +1,6 @@ #ifndef _VB_DEF_ #define _VB_DEF_ -#include "../../video/sis/initdef.h" +#include "../../video/fbdev/sis/initdef.h" #define VB_XGI301C 0x0020 /* for 301C */ diff --git a/drivers/staging/xgifb/vb_struct.h b/drivers/staging/xgifb/vb_struct.h index c08ff5b2d6ee05..0d27594554ca27 100644 --- a/drivers/staging/xgifb/vb_struct.h +++ b/drivers/staging/xgifb/vb_struct.h @@ -1,6 +1,6 @@ #ifndef _VB_STRUCT_ #define _VB_STRUCT_ -#include "../../video/sis/vstruct.h" +#include "../../video/fbdev/sis/vstruct.h" struct XGI_LVDSCRT1HDataStruct { unsigned char Reg[8]; diff --git a/drivers/staging/xgifb/vgatypes.h b/drivers/staging/xgifb/vgatypes.h index ddf7776c295b61..264351441f99ff 100644 --- a/drivers/staging/xgifb/vgatypes.h +++ b/drivers/staging/xgifb/vgatypes.h @@ -2,8 +2,8 @@ #define _VGATYPES_ #include /* for struct fb_var_screeninfo for sis.h */ -#include "../../video/sis/vgatypes.h" -#include "../../video/sis/sis.h" /* for LCD_TYPE */ +#include "../../video/fbdev/sis/vgatypes.h" +#include "../../video/fbdev/sis/sis.h" /* for LCD_TYPE */ #ifndef XGI_VB_CHIP_TYPE enum XGI_VB_CHIP_TYPE { diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 3ad7ebe2a96dbc..ab05d6cb0796fb 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -23,6 +23,10 @@ source "drivers/gpu/host1x/Kconfig" source "drivers/gpu/drm/Kconfig" +source "drivers/video/fbdev/Kconfig" + +source "drivers/video/backlight/Kconfig" + config VGASTATE tristate default n @@ -33,2484 +37,14 @@ config VIDEOMODE_HELPERS config HDMI bool -menuconfig FB - tristate "Support for frame buffer devices" - ---help--- - The frame buffer device provides an abstraction for the graphics - hardware. It represents the frame buffer of some video hardware and - allows application software to access the graphics hardware through - a well-defined interface, so the software doesn't need to know - anything about the low-level (hardware register) stuff. - - Frame buffer devices work identically across the different - architectures supported by Linux and make the implementation of - application programs easier and more portable; at this point, an X - server exists which uses the frame buffer device exclusively. - On several non-X86 architectures, the frame buffer device is the - only way to use the graphics hardware. - - The device is accessed through special device nodes, usually located - in the /dev directory, i.e. /dev/fb*. - - You need an utility program called fbset to make full use of frame - buffer devices. Please read - and the Framebuffer-HOWTO at - for more - information. - - Say Y here and to the driver for your graphics board below if you - are compiling a kernel for a non-x86 architecture. - - If you are compiling for the x86 architecture, you can say Y if you - want to play with it, but it is not essential. Please note that - running graphical applications that directly touch the hardware - (e.g. an accelerated X server) and that are not frame buffer - device-aware may cause unexpected results. If unsure, say N. - -config FIRMWARE_EDID - bool "Enable firmware EDID" - depends on FB - default n - ---help--- - This enables access to the EDID transferred from the firmware. - On the i386, this is from the Video BIOS. Enable this if DDC/I2C - transfers do not work for your driver and if you are using - nvidiafb, i810fb or savagefb. - - In general, choosing Y for this option is safe. If you - experience extremely long delays while booting before you get - something on your display, try setting this to N. Matrox cards in - combination with certain motherboards and monitors are known to - suffer from this problem. - -config FB_DDC - tristate - depends on FB - select I2C_ALGOBIT - select I2C - default n - -config FB_BOOT_VESA_SUPPORT - bool - depends on FB - default n - ---help--- - If true, at least one selected framebuffer driver can take advantage - of VESA video modes set at an early boot stage via the vga= parameter. - -config FB_CFB_FILLRECT - tristate - depends on FB - default n - ---help--- - Include the cfb_fillrect function for generic software rectangle - filling. This is used by drivers that don't provide their own - (accelerated) version. - -config FB_CFB_COPYAREA - tristate - depends on FB - default n - ---help--- - Include the cfb_copyarea function for generic software area copying. - This is used by drivers that don't provide their own (accelerated) - version. - -config FB_CFB_IMAGEBLIT - tristate - depends on FB - default n - ---help--- - Include the cfb_imageblit function for generic software image - blitting. This is used by drivers that don't provide their own - (accelerated) version. - -config FB_CFB_REV_PIXELS_IN_BYTE - bool - depends on FB - default n - ---help--- - Allow generic frame-buffer functions to work on displays with 1, 2 - and 4 bits per pixel depths which has opposite order of pixels in - byte order to bytes in long order. - -config FB_SYS_FILLRECT - tristate - depends on FB - default n - ---help--- - Include the sys_fillrect function for generic software rectangle - filling. This is used by drivers that don't provide their own - (accelerated) version and the framebuffer is in system RAM. - -config FB_SYS_COPYAREA - tristate - depends on FB - default n - ---help--- - Include the sys_copyarea function for generic software area copying. - This is used by drivers that don't provide their own (accelerated) - version and the framebuffer is in system RAM. - -config FB_SYS_IMAGEBLIT - tristate - depends on FB - default n - ---help--- - Include the sys_imageblit function for generic software image - blitting. This is used by drivers that don't provide their own - (accelerated) version and the framebuffer is in system RAM. - -menuconfig FB_FOREIGN_ENDIAN - bool "Framebuffer foreign endianness support" - depends on FB - ---help--- - This menu will let you enable support for the framebuffers with - non-native endianness (e.g. Little-Endian framebuffer on a - Big-Endian machine). Most probably you don't have such hardware, - so it's safe to say "n" here. - -choice - prompt "Choice endianness support" - depends on FB_FOREIGN_ENDIAN - -config FB_BOTH_ENDIAN - bool "Support for Big- and Little-Endian framebuffers" - -config FB_BIG_ENDIAN - bool "Support for Big-Endian framebuffers only" - -config FB_LITTLE_ENDIAN - bool "Support for Little-Endian framebuffers only" - -endchoice - -config FB_SYS_FOPS - tristate - depends on FB - default n - -config FB_DEFERRED_IO - bool - depends on FB - -config FB_HECUBA - tristate - depends on FB - depends on FB_DEFERRED_IO - -config FB_SVGALIB - tristate - depends on FB - default n - ---help--- - Common utility functions useful to fbdev drivers of VGA-based - cards. - -config FB_MACMODES - tristate - depends on FB - default n - -config FB_BACKLIGHT - bool - depends on FB - select BACKLIGHT_LCD_SUPPORT - select BACKLIGHT_CLASS_DEVICE - default n - -config FB_MODE_HELPERS - bool "Enable Video Mode Handling Helpers" - depends on FB - default n - ---help--- - This enables functions for handling video modes using the - Generalized Timing Formula and the EDID parser. A few drivers rely - on this feature such as the radeonfb, rivafb, and the i810fb. If - your driver does not take advantage of this feature, choosing Y will - just increase the kernel size by about 5K. - -config FB_TILEBLITTING - bool "Enable Tile Blitting Support" - depends on FB - default n - ---help--- - This enables tile blitting. Tile blitting is a drawing technique - where the screen is divided into rectangular sections (tiles), whereas - the standard blitting divides the screen into pixels. Because the - default drawing element is a tile, drawing functions will be passed - parameters in terms of number of tiles instead of number of pixels. - For example, to draw a single character, instead of using bitmaps, - an index to an array of bitmaps will be used. To clear or move a - rectangular section of a screen, the rectangle will be described in - terms of number of tiles in the x- and y-axis. - - This is particularly important to one driver, matroxfb. If - unsure, say N. - -comment "Frame buffer hardware drivers" - depends on FB - -config FB_GRVGA - tristate "Aeroflex Gaisler framebuffer support" - depends on FB && SPARC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler. - -config FB_CIRRUS - tristate "Cirrus Logic support" - depends on FB && (ZORRO || PCI) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - This enables support for Cirrus Logic GD542x/543x based boards on - Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. - - If you have a PCI-based system, this enables support for these - chips: GD-543x, GD-544x, GD-5480. - - Please read the file . - - Say N unless you have such a graphics board or plan to get one - before you next recompile the kernel. - -config FB_PM2 - tristate "Permedia2 support" - depends on FB && ((AMIGA && BROKEN) || PCI) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for cards based on - the 3D Labs Permedia, Permedia 2 and Permedia 2V chips. - The driver was tested on the following cards: - Diamond FireGL 1000 PRO AGP - ELSA Gloria Synergy PCI - Appian Jeronimo PRO (both heads) PCI - 3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI - Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC - ASK Graphic Blaster Exxtreme AGP - - To compile this driver as a module, choose M here: the - module will be called pm2fb. - -config FB_PM2_FIFO_DISCONNECT - bool "enable FIFO disconnect feature" - depends on FB_PM2 && PCI - help - Support the Permedia2 FIFO disconnect feature. - -config FB_ARMCLCD - tristate "ARM PrimeCell PL110 support" - depends on ARM || ARM64 || COMPILE_TEST - depends on FB && ARM_AMBA - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This framebuffer device driver is for the ARM PrimeCell PL110 - Colour LCD controller. ARM PrimeCells provide the building - blocks for System on a Chip devices. - - If you want to compile this as a module (=code which can be - inserted into and removed from the running kernel), say M - here and read . The module - will be called amba-clcd. - -config FB_ACORN - bool "Acorn VIDC support" - depends on (FB = y) && ARM && ARCH_ACORN - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the Acorn VIDC graphics - hardware found in Acorn RISC PCs and other ARM-based machines. If - unsure, say N. - -config FB_CLPS711X - bool "CLPS711X LCD support" - depends on (FB = y) && ARM && ARCH_CLPS711X - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Say Y to enable the Framebuffer driver for the CLPS7111 and - EP7212 processors. - -config FB_SA1100 - bool "SA-1100 LCD support" - depends on (FB = y) && ARM && ARCH_SA1100 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is a framebuffer device for the SA-1100 LCD Controller. - See for information on framebuffer - devices. - - If you plan to use the LCD display with your SA-1100 system, say - Y here. - -config FB_IMX - tristate "Freescale i.MX1/21/25/27 LCD support" - depends on FB && ARCH_MXC - select BACKLIGHT_LCD_SUPPORT - select LCD_CLASS_DEVICE - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - -config FB_CYBER2000 - tristate "CyberPro 2000/2010/5000 support" - depends on FB && PCI && (BROKEN || !SPARC64) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This enables support for the Integraphics CyberPro 20x0 and 5000 - VGA chips used in the Rebel.com Netwinder and other machines. - Say Y if you have a NetWinder or a graphics card containing this - device, otherwise say N. - -config FB_CYBER2000_DDC - bool "DDC for CyberPro support" - depends on FB_CYBER2000 - select FB_DDC - default y - help - Say Y here if you want DDC support for your CyberPro graphics - card. This is only I2C bus support, driver does not use EDID. - -config FB_CYBER2000_I2C - bool "CyberPro 2000/2010/5000 I2C support" - depends on FB_CYBER2000 && I2C && ARCH_NETWINDER - select I2C_ALGOBIT - help - Enable support for the I2C video decoder interface on the - Integraphics CyberPro 20x0 and 5000 VGA chips. This is used - on the Netwinder machines for the SAA7111 video capture. - -config FB_APOLLO - bool - depends on (FB = y) && APOLLO - default y - select FB_CFB_FILLRECT - select FB_CFB_IMAGEBLIT - -config FB_Q40 - bool - depends on (FB = y) && Q40 - default y - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - -config FB_AMIGA - tristate "Amiga native chipset support" - depends on FB && AMIGA - help - This is the frame buffer device driver for the builtin graphics - chipset found in Amigas. - - To compile this driver as a module, choose M here: the - module will be called amifb. - -config FB_AMIGA_OCS - bool "Amiga OCS chipset support" - depends on FB_AMIGA - help - This enables support for the original Agnus and Denise video chips, - found in the Amiga 1000 and most A500's and A2000's. If you intend - to run Linux on any of these systems, say Y; otherwise say N. - -config FB_AMIGA_ECS - bool "Amiga ECS chipset support" - depends on FB_AMIGA - help - This enables support for the Enhanced Chip Set, found in later - A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If - you intend to run Linux on any of these systems, say Y; otherwise - say N. - -config FB_AMIGA_AGA - bool "Amiga AGA chipset support" - depends on FB_AMIGA - help - This enables support for the Advanced Graphics Architecture (also - known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T - and CD32. If you intend to run Linux on any of these systems, say Y; - otherwise say N. - -config FB_FM2 - bool "Amiga FrameMaster II/Rainbow II support" - depends on (FB = y) && ZORRO - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the Amiga FrameMaster - card from BSC (exhibited 1992 but not shipped as a CBM product). - -config FB_ARC - tristate "Arc Monochrome LCD board support" - depends on FB && X86 - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - help - This enables support for the Arc Monochrome LCD board. The board - is based on the KS-108 lcd controller and is typically a matrix - of 2*n chips. This driver was tested with a 128x64 panel. This - driver supports it for use with x86 SBCs through a 16 bit GPIO - interface (8 bit data, 8 bit control). If you anticipate using - this driver, say Y or M; otherwise say N. You must specify the - GPIO IO address to be used for setting control and data. - -config FB_ATARI - bool "Atari native chipset support" - depends on (FB = y) && ATARI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the builtin graphics - chipset found in Ataris. - -config FB_OF - bool "Open Firmware frame buffer device support" - depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES - help - Say Y if you want support with Open Firmware for your graphics - board. - -config FB_CONTROL - bool "Apple \"control\" display support" - depends on (FB = y) && PPC_PMAC && PPC32 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES - help - This driver supports a frame buffer for the graphics adapter in the - Power Macintosh 7300 and others. - -config FB_PLATINUM - bool "Apple \"platinum\" display support" - depends on (FB = y) && PPC_PMAC && PPC32 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES - help - This driver supports a frame buffer for the "platinum" graphics - adapter in some Power Macintoshes. - -config FB_VALKYRIE - bool "Apple \"valkyrie\" display support" - depends on (FB = y) && (MAC || (PPC_PMAC && PPC32)) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES - help - This driver supports a frame buffer for the "valkyrie" graphics - adapter in some Power Macintoshes. - -config FB_CT65550 - bool "Chips 65550 display support" - depends on (FB = y) && PPC32 && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the Chips & Technologies - 65550 graphics chip in PowerBooks. - -config FB_ASILIANT - bool "Asiliant (Chips) 69000 display support" - depends on (FB = y) && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the Asiliant 69030 chipset - -config FB_IMSTT - bool "IMS Twin Turbo display support" - depends on (FB = y) && PCI - select FB_CFB_IMAGEBLIT - select FB_MACMODES if PPC - help - The IMS Twin Turbo is a PCI-based frame buffer card bundled with - many Macintosh and compatible computers. - -config FB_VGA16 - tristate "VGA 16-color graphics support" - depends on FB && (X86 || PPC) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - help - This is the frame buffer device driver for VGA 16 color graphic - cards. Say Y if you have such a card. - - To compile this driver as a module, choose M here: the - module will be called vga16fb. - -config FB_BF54X_LQ043 - tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)" - depends on FB && (BF54x) && !BF542 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD - -config FB_BFIN_T350MCQB - tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)" - depends on FB && BLACKFIN - select BFIN_GPTIMERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD - This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI - It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK. - -config FB_BFIN_LQ035Q1 - tristate "SHARP LQ035Q1DH02 TFT LCD" - depends on FB && BLACKFIN && SPI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select BFIN_GPTIMERS - help - This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on - the Blackfin Landscape LCD EZ-Extender Card. - This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI - It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK. - - To compile this driver as a module, choose M here: the - module will be called bfin-lq035q1-fb. - -config FB_BF537_LQ035 - tristate "SHARP LQ035 TFT LCD (BF537 STAMP)" - depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select BFIN_GPTIMERS - help - This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD - attached to a BF537. - - To compile this driver as a module, choose M here: the - module will be called bf537-lq035. - -config FB_BFIN_7393 - tristate "Blackfin ADV7393 Video encoder" - depends on FB && BLACKFIN - select I2C - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device for a ADV7393 video encoder - attached to a Blackfin on the PPI port. - If your Blackfin board has a ADV7393 select Y. - - To compile this driver as a module, choose M here: the - module will be called bfin_adv7393fb. - -choice - prompt "Video mode support" - depends on FB_BFIN_7393 - default NTSC - -config NTSC - bool 'NTSC 720x480' - -config PAL - bool 'PAL 720x576' - -config NTSC_640x480 - bool 'NTSC 640x480 (Experimental)' - -config PAL_640x480 - bool 'PAL 640x480 (Experimental)' - -config NTSC_YCBCR - bool 'NTSC 720x480 YCbCR input' - -config PAL_YCBCR - bool 'PAL 720x576 YCbCR input' - -endchoice - -choice - prompt "Size of ADV7393 frame buffer memory Single/Double Size" - depends on (FB_BFIN_7393) - default ADV7393_1XMEM - -config ADV7393_1XMEM - bool 'Single' - -config ADV7393_2XMEM - bool 'Double' -endchoice - -config FB_STI - tristate "HP STI frame buffer device support" - depends on FB && PARISC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select STI_CONSOLE - select VT - default y - ---help--- - STI refers to the HP "Standard Text Interface" which is a set of - BIOS routines contained in a ROM chip in HP PA-RISC based machines. - Enabling this option will implement the linux framebuffer device - using calls to the STI BIOS routines for initialisation. - - If you enable this option, you will get a planar framebuffer device - /dev/fb which will work on the most common HP graphic cards of the - NGLE family, including the artist chips (in the 7xx and Bxxx series), - HCRX, HCRX24, CRX, CRX24 and VisEG series. - - It is safe to enable this option, so you should probably say "Y". - -config FB_MAC - bool "Generic Macintosh display support" - depends on (FB = y) && MAC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES - -config FB_HP300 - bool - depends on (FB = y) && DIO - select FB_CFB_IMAGEBLIT - default y - -config FB_TGA - tristate "TGA/SFB+ framebuffer support" - depends on FB && (ALPHA || TC) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select BITREVERSE - ---help--- - This is the frame buffer device driver for generic TGA and SFB+ - graphic cards. These include DEC ZLXp-E1, -E2 and -E3 PCI cards, - also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3 - TURBOchannel cards, also known as PMAGD-A, -B and -C. - - Due to hardware limitations ZLX-E2 and E3 cards are not supported - for DECstation 5000/200 systems. Additionally due to firmware - limitations these cards may cause troubles with booting DECstation - 5000/240 and /260 systems, but are fully supported under Linux if - you manage to get it going. ;-) - - Say Y if you have one of those. - -config FB_UVESA - tristate "Userspace VESA VGA graphics support" - depends on FB && CONNECTOR - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MODE_HELPERS - help - This is the frame buffer driver for generic VBE 2.0 compliant - graphic cards. It can also take advantage of VBE 3.0 features, - such as refresh rate adjustment. - - This driver generally provides more features than vesafb but - requires a userspace helper application called 'v86d'. See - for more information. - - If unsure, say N. - -config FB_VESA - bool "VESA VGA graphics support" - depends on (FB = y) && X86 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_BOOT_VESA_SUPPORT - help - This is the frame buffer device driver for generic VESA 2.0 - compliant graphic cards. The older VESA 1.2 cards are not supported. - You will get a boot time penguin logo at no additional cost. Please - read . If unsure, say Y. - -config FB_EFI - bool "EFI-based Framebuffer Support" - depends on (FB = y) && X86 && EFI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the EFI frame buffer device driver. If the firmware on - your platform is EFI 1.10 or UEFI 2.0, select Y to add support for - using the EFI framebuffer as your console. - -config FB_N411 - tristate "N411 Apollo/Hecuba devkit support" - depends on FB && X86 && MMU - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - select FB_HECUBA - help - This enables support for the Apollo display controller in its - Hecuba form using the n411 devkit. - -config FB_HGA - tristate "Hercules mono graphics support" - depends on FB && X86 - help - Say Y here if you have a Hercules mono graphics card. - - To compile this driver as a module, choose M here: the - module will be called hgafb. - - As this card technology is at least 25 years old, - most people will answer N here. - -config FB_GBE - bool "SGI Graphics Backend frame buffer support" - depends on (FB = y) && SGI_IP32 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for SGI Graphics Backend. - This chip is used in SGI O2 and Visual Workstation 320/540. - -config FB_GBE_MEM - int "Video memory size in MB" - depends on FB_GBE - default 4 - help - This is the amount of memory reserved for the framebuffer, - which can be any value between 1MB and 8MB. - -config FB_SBUS - bool "SBUS and UPA framebuffers" - depends on (FB = y) && SPARC - help - Say Y if you want support for SBUS or UPA based frame buffer device. - -config FB_BW2 - bool "BWtwo support" - depends on (FB = y) && (SPARC && FB_SBUS) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the BWtwo frame buffer. - -config FB_CG3 - bool "CGthree support" - depends on (FB = y) && (SPARC && FB_SBUS) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the CGthree frame buffer. - -config FB_CG6 - bool "CGsix (GX,TurboGX) support" - depends on (FB = y) && (SPARC && FB_SBUS) - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the CGsix (GX, TurboGX) - frame buffer. - -config FB_FFB - bool "Creator/Creator3D/Elite3D support" - depends on FB_SBUS && SPARC64 - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the Creator, Creator3D, - and Elite3D graphics boards. - -config FB_TCX - bool "TCX (SS4/SS5 only) support" - depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the TCX 24/8bit frame - buffer. - -config FB_CG14 - bool "CGfourteen (SX) support" - depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the CGfourteen frame - buffer on Desktop SPARCsystems with the SX graphics option. - -config FB_P9100 - bool "P9100 (Sparcbook 3 only) support" - depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the P9100 card - supported on Sparcbook 3 machines. - -config FB_LEO - bool "Leo (ZX) support" - depends on FB_SBUS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the SBUS-based Sun ZX - (leo) frame buffer cards. - -config FB_IGA - bool "IGA 168x display support" - depends on (FB = y) && SPARC32 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device for the INTERGRAPHICS 1680 and - successor frame buffer cards. - -config FB_XVR500 - bool "Sun XVR-500 3DLABS Wildcat support" - depends on (FB = y) && PCI && SPARC64 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device for the Sun XVR-500 and similar - graphics cards based upon the 3DLABS Wildcat chipset. The driver - only works on sparc64 systems where the system firmware has - mostly initialized the card already. It is treated as a - completely dumb framebuffer device. - -config FB_XVR2500 - bool "Sun XVR-2500 3DLABS Wildcat support" - depends on (FB = y) && PCI && SPARC64 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device for the Sun XVR-2500 and similar - graphics cards based upon the 3DLABS Wildcat chipset. The driver - only works on sparc64 systems where the system firmware has - mostly initialized the card already. It is treated as a - completely dumb framebuffer device. - -config FB_XVR1000 - bool "Sun XVR-1000 support" - depends on (FB = y) && SPARC64 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer device for the Sun XVR-1000 and similar - graphics cards. The driver only works on sparc64 systems where - the system firmware has mostly initialized the card already. It - is treated as a completely dumb framebuffer device. - -config FB_PVR2 - tristate "NEC PowerVR 2 display support" - depends on FB && SH_DREAMCAST - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Say Y here if you have a PowerVR 2 card in your box. If you plan to - run linux on your Dreamcast, you will have to say Y here. - This driver may or may not work on other PowerVR 2 cards, but is - totally untested. Use at your own risk. If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called pvr2fb. - - You can pass several parameters to the driver at boot time or at - module load time. The parameters look like "video=pvr2:XXX", where - the meaning of XXX can be found at the end of the main source file - (). Please see the file - . - -config FB_OPENCORES - tristate "OpenCores VGA/LCD core 2.0 framebuffer support" - depends on FB && HAS_DMA - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This enables support for the OpenCores VGA/LCD core. - - The OpenCores VGA/LCD core is typically used together with - softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor - systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs. - - The source code and specification for the core is available at - - -config FB_S1D13XXX - tristate "Epson S1D13XXX framebuffer support" - depends on FB - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Support for S1D13XXX framebuffer device family (currently only - working with S1D13806). Product specs at - - -config FB_ATMEL - tristate "AT91/AT32 LCD Controller support" - depends on FB && HAVE_FB_ATMEL - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - help - This enables support for the AT91/AT32 LCD Controller. - -config FB_INTSRAM - bool "Frame Buffer in internal SRAM" - depends on FB_ATMEL && ARCH_AT91SAM9261 - help - Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want - to let frame buffer in external SDRAM. - -config FB_ATMEL_STN - bool "Use a STN display with AT91/AT32 LCD Controller" - depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK) - default n - help - Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD - Controller. Say N if you want to connect a TFT. - - If unsure, say N. - -config FB_NVIDIA - tristate "nVidia Framebuffer Support" - depends on FB && PCI - select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select BITREVERSE - select VGASTATE - help - This driver supports graphics boards with the nVidia chips, TNT - and newer. For very old chipsets, such as the RIVA128, then use - the rivafb. - Say Y if you have such a graphics board. - - To compile this driver as a module, choose M here: the - module will be called nvidiafb. - -config FB_NVIDIA_I2C - bool "Enable DDC Support" - depends on FB_NVIDIA - select FB_DDC - help - This enables I2C support for nVidia Chipsets. This is used - only for getting EDID information from the attached display - allowing for robust video mode handling and switching. - - Because fbdev-2.6 requires that drivers must be able to - independently validate video mode parameters, you should say Y - here. - -config FB_NVIDIA_DEBUG - bool "Lots of debug output" - depends on FB_NVIDIA - default n - help - Say Y here if you want the nVidia driver to output all sorts - of debugging information to provide to the maintainer when - something goes wrong. - -config FB_NVIDIA_BACKLIGHT - bool "Support for backlight control" - depends on FB_NVIDIA - default y - help - Say Y here if you want to control the backlight of your display. - -config FB_RIVA - tristate "nVidia Riva support" - depends on FB && PCI - select FB_BACKLIGHT if FB_RIVA_BACKLIGHT - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select BITREVERSE - select VGASTATE - help - This driver supports graphics boards with the nVidia Riva/Geforce - chips. - Say Y if you have such a graphics board. - - To compile this driver as a module, choose M here: the - module will be called rivafb. - -config FB_RIVA_I2C - bool "Enable DDC Support" - depends on FB_RIVA - select FB_DDC - help - This enables I2C support for nVidia Chipsets. This is used - only for getting EDID information from the attached display - allowing for robust video mode handling and switching. - - Because fbdev-2.6 requires that drivers must be able to - independently validate video mode parameters, you should say Y - here. - -config FB_RIVA_DEBUG - bool "Lots of debug output" - depends on FB_RIVA - default n - help - Say Y here if you want the Riva driver to output all sorts - of debugging information to provide to the maintainer when - something goes wrong. - -config FB_RIVA_BACKLIGHT - bool "Support for backlight control" - depends on FB_RIVA - default y - help - Say Y here if you want to control the backlight of your display. - -config FB_I740 - tristate "Intel740 support" - depends on FB && PCI - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select VGASTATE - select FB_DDC - help - This driver supports graphics cards based on Intel740 chip. - -config FB_I810 - tristate "Intel 810/815 support" - depends on FB && PCI && X86_32 && AGP_INTEL - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select VGASTATE - help - This driver supports the on-board graphics built in to the Intel 810 - and 815 chipsets. Say Y if you have and plan to use such a board. - - To compile this driver as a module, choose M here: the - module will be called i810fb. - - For more information, please read - - -config FB_I810_GTF - bool "use VESA Generalized Timing Formula" - depends on FB_I810 - help - If you say Y, then the VESA standard, Generalized Timing Formula - or GTF, will be used to calculate the required video timing values - per video mode. Since the GTF allows nondiscrete timings - (nondiscrete being a range of values as opposed to discrete being a - set of values), you'll be able to use any combination of horizontal - and vertical resolutions, and vertical refresh rates without having - to specify your own timing parameters. This is especially useful - to maximize the performance of an aging display, or if you just - have a display with nonstandard dimensions. A VESA compliant - monitor is recommended, but can still work with non-compliant ones. - If you need or want this, then select this option. The timings may - not be compliant with Intel's recommended values. Use at your own - risk. - - If you say N, the driver will revert to discrete video timings - using a set recommended by Intel in their documentation. - - If unsure, say N. - -config FB_I810_I2C - bool "Enable DDC Support" - depends on FB_I810 && FB_I810_GTF - select FB_DDC - help - -config FB_LE80578 - tristate "Intel LE80578 (Vermilion) support" - depends on FB && PCI && X86 - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This driver supports the LE80578 (Vermilion Range) chipset - -config FB_CARILLO_RANCH - tristate "Intel Carillo Ranch support" - depends on FB_LE80578 && FB && PCI && X86 - help - This driver supports the LE80578 (Carillo Ranch) board - -config FB_INTEL - tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support" - depends on FB && PCI && X86 && AGP_INTEL && EXPERT - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_BOOT_VESA_SUPPORT if FB_INTEL = y - depends on !DRM_I915 - help - This driver supports the on-board graphics built in to the Intel - 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. - Say Y if you have and plan to use such a board. - - To make FB_INTELFB=Y work you need to say AGP_INTEL=y too. - - To compile this driver as a module, choose M here: the - module will be called intelfb. - - For more information, please read - -config FB_INTEL_DEBUG - bool "Intel driver Debug Messages" - depends on FB_INTEL - ---help--- - Say Y here if you want the Intel driver to output all sorts - of debugging information to provide to the maintainer when - something goes wrong. - -config FB_INTEL_I2C - bool "DDC/I2C for Intel framebuffer support" - depends on FB_INTEL - select FB_DDC - default y - help - Say Y here if you want DDC/I2C support for your on-board Intel graphics. - -config FB_MATROX - tristate "Matrox acceleration" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_MACMODES if PPC_PMAC - ---help--- - Say Y here if you have a Matrox Millennium, Matrox Millennium II, - Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox - Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video, - Matrox G400, G450 or G550 card in your box. - - To compile this driver as a module, choose M here: the - module will be called matroxfb. - - You can pass several parameters to the driver at boot time or at - module load time. The parameters look like "video=matroxfb:XXX", and - are described in . - -config FB_MATROX_MILLENIUM - bool "Millennium I/II support" - depends on FB_MATROX - help - Say Y here if you have a Matrox Millennium or Matrox Millennium II - video card. If you select "Advanced lowlevel driver options" below, - you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp - packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can - also use font widths different from 8. - -config FB_MATROX_MYSTIQUE - bool "Mystique support" - depends on FB_MATROX - help - Say Y here if you have a Matrox Mystique or Matrox Mystique 220 - video card. If you select "Advanced lowlevel driver options" below, - you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp - packed pixel and 32 bpp packed pixel. You can also use font widths - different from 8. - -config FB_MATROX_G - bool "G100/G200/G400/G450/G550 support" - depends on FB_MATROX - ---help--- - Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based - video card. If you select "Advanced lowlevel driver options", you - should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed - pixel and 32 bpp packed pixel. You can also use font widths - different from 8. - - If you need support for G400 secondary head, you must say Y to - "Matrox I2C support" and "G400 second head support" right below. - G450/G550 secondary head and digital output are supported without - additional modules. - - The driver starts in monitor mode. You must use the matroxset tool - (available at ) to - swap primary and secondary head outputs, or to change output mode. - Secondary head driver always start in 640x480 resolution and you - must use fbset to change it. - - Do not forget that second head supports only 16 and 32 bpp - packed pixels, so it is a good idea to compile them into the kernel - too. You can use only some font widths, as the driver uses generic - painting procedures (the secondary head does not use acceleration - engine). - - G450/G550 hardware can display TV picture only from secondary CRTC, - and it performs no scaling, so picture must have 525 or 625 lines. - -config FB_MATROX_I2C - tristate "Matrox I2C support" - depends on FB_MATROX - select FB_DDC - ---help--- - This drivers creates I2C buses which are needed for accessing the - DDC (I2C) bus present on all Matroxes, an I2C bus which - interconnects Matrox optional devices, like MGA-TVO on G200 and - G400, and the secondary head DDC bus, present on G400 only. - - You can say Y or M here if you want to experiment with monitor - detection code. You must say Y or M here if you want to use either - second head of G400 or MGA-TVO on G200 or G400. - - If you compile it as module, it will create a module named - i2c-matroxfb. - -config FB_MATROX_MAVEN - tristate "G400 second head support" - depends on FB_MATROX_G && FB_MATROX_I2C - ---help--- - WARNING !!! This support does not work with G450 !!! - - Say Y or M here if you want to use a secondary head (meaning two - monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary - head is not compatible with accelerated XFree 3.3.x SVGA servers - - secondary head output is blanked while you are in X. With XFree - 3.9.17 preview you can use both heads if you use SVGA over fbdev or - the fbdev driver on first head and the fbdev driver on second head. - - If you compile it as module, two modules are created, - matroxfb_crtc2 and matroxfb_maven. Matroxfb_maven is needed for - both G200 and G400, matroxfb_crtc2 is needed only by G400. You must - also load i2c-matroxfb to get it to run. - - The driver starts in monitor mode and you must use the matroxset - tool (available at - ) to switch it to - PAL or NTSC or to swap primary and secondary head outputs. - Secondary head driver also always start in 640x480 resolution, you - must use fbset to change it. - - Also do not forget that second head supports only 16 and 32 bpp - packed pixels, so it is a good idea to compile them into the kernel - too. You can use only some font widths, as the driver uses generic - painting procedures (the secondary head does not use acceleration - engine). - -config FB_RADEON - tristate "ATI Radeon display support" - depends on FB && PCI - select FB_BACKLIGHT if FB_RADEON_BACKLIGHT - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MACMODES if PPC_OF - help - Choose this option if you want to use an ATI Radeon graphics card as - a framebuffer device. There are both PCI and AGP versions. You - don't need to choose this to run the Radeon in plain VGA mode. - - There is a product page at - http://products.amd.com/en-us/GraphicCardResult.aspx - -config FB_RADEON_I2C - bool "DDC/I2C for ATI Radeon support" - depends on FB_RADEON - select FB_DDC - default y - help - Say Y here if you want DDC/I2C support for your Radeon board. - -config FB_RADEON_BACKLIGHT - bool "Support for backlight control" - depends on FB_RADEON - default y - help - Say Y here if you want to control the backlight of your display. - -config FB_RADEON_DEBUG - bool "Lots of debug output from Radeon driver" - depends on FB_RADEON - default n - help - Say Y here if you want the Radeon driver to output all sorts - of debugging information to provide to the maintainer when - something goes wrong. - -config FB_ATY128 - tristate "ATI Rage128 display support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_BACKLIGHT if FB_ATY128_BACKLIGHT - select FB_MACMODES if PPC_PMAC - help - This driver supports graphics boards with the ATI Rage128 chips. - Say Y if you have such a graphics board and read - . - - To compile this driver as a module, choose M here: the - module will be called aty128fb. - -config FB_ATY128_BACKLIGHT - bool "Support for backlight control" - depends on FB_ATY128 - default y - help - Say Y here if you want to control the backlight of your display. - -config FB_ATY - tristate "ATI Mach64 display support" if PCI || ATARI - depends on FB && !SPARC32 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_BACKLIGHT if FB_ATY_BACKLIGHT - select FB_MACMODES if PPC - help - This driver supports graphics boards with the ATI Mach64 chips. - Say Y if you have such a graphics board. - - To compile this driver as a module, choose M here: the - module will be called atyfb. - -config FB_ATY_CT - bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support" - depends on PCI && FB_ATY - default y if SPARC64 && PCI - help - Say Y here to support use of ATI's 64-bit Rage boards (or other - boards based on the Mach64 CT, VT, GT, and LT chipsets) as a - framebuffer device. The ATI product support page for these boards - is at . - -config FB_ATY_GENERIC_LCD - bool "Mach64 generic LCD support" - depends on FB_ATY_CT - help - Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility, - Rage XC, or Rage XL chipset. - -config FB_ATY_GX - bool "Mach64 GX support" if PCI - depends on FB_ATY - default y if ATARI - help - Say Y here to support use of the ATI Mach64 Graphics Expression - board (or other boards based on the Mach64 GX chipset) as a - framebuffer device. The ATI product support page for these boards - is at - . - -config FB_ATY_BACKLIGHT - bool "Support for backlight control" - depends on FB_ATY - default y - help - Say Y here if you want to control the backlight of your display. - -config FB_S3 - tristate "S3 Trio/Virge support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_SVGALIB - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - ---help--- - Driver for graphics boards with S3 Trio / S3 Virge chip. - -config FB_S3_DDC - bool "DDC for S3 support" - depends on FB_S3 - select FB_DDC - default y - help - Say Y here if you want DDC support for your S3 graphics card. - -config FB_SAVAGE - tristate "S3 Savage support" - depends on FB && PCI - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select VGASTATE - help - This driver supports notebooks and computers with S3 Savage PCI/AGP - chips. - - Say Y if you have such a graphics card. - - To compile this driver as a module, choose M here; the module - will be called savagefb. - -config FB_SAVAGE_I2C - bool "Enable DDC2 Support" - depends on FB_SAVAGE - select FB_DDC - help - This enables I2C support for S3 Savage Chipsets. This is used - only for getting EDID information from the attached display - allowing for robust video mode handling and switching. - - Because fbdev-2.6 requires that drivers must be able to - independently validate video mode parameters, you should say Y - here. - -config FB_SAVAGE_ACCEL - bool "Enable Console Acceleration" - depends on FB_SAVAGE - default n - help - This option will compile in console acceleration support. If - the resulting framebuffer console has bothersome glitches, then - choose N here. - -config FB_SIS - tristate "SiS/XGI display support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_BOOT_VESA_SUPPORT if FB_SIS = y - help - This is the frame buffer device driver for the SiS 300, 315, 330 - and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. - Specs available at and . - - To compile this driver as a module, choose M here; the module - will be called sisfb. - -config FB_SIS_300 - bool "SiS 300 series support" - depends on FB_SIS - help - Say Y here to support use of the SiS 300/305, 540, 630 and 730. - -config FB_SIS_315 - bool "SiS 315/330/340 series and XGI support" - depends on FB_SIS - help - Say Y here to support use of the SiS 315, 330 and 340 series - (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well - as XGI V3XT, V5, V8 and Z7. - -config FB_VIA - tristate "VIA UniChrome (Pro) and Chrome9 display support" - depends on FB && PCI && X86 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select I2C_ALGOBIT - select I2C - select GPIOLIB - help - This is the frame buffer device driver for Graphics chips of VIA - UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/ - CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896 - /P4M900,VX800) - Say Y if you have a VIA UniChrome graphics board. - - To compile this driver as a module, choose M here: the - module will be called viafb. - -if FB_VIA - -config FB_VIA_DIRECT_PROCFS - bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)" - depends on FB_VIA - default n - help - Allow direct hardware access to some output registers via procfs. - This is dangerous but may provide the only chance to get the - correct output device configuration. - Its use is strongly discouraged. - -config FB_VIA_X_COMPATIBILITY - bool "X server compatibility" - depends on FB_VIA - default n - help - This option reduces the functionality (power saving, ...) of the - framebuffer to avoid negative impact on the OpenChrome X server. - If you use any X server other than fbdev you should enable this - otherwise it should be safe to disable it and allow using all - features. - -endif - -config FB_NEOMAGIC - tristate "NeoMagic display support" - depends on FB && PCI - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select VGASTATE - help - This driver supports notebooks with NeoMagic PCI chips. - Say Y if you have such a graphics card. - - To compile this driver as a module, choose M here: the - module will be called neofb. - -config FB_KYRO - tristate "IMG Kyro support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Say Y here if you have a STG4000 / Kyro / PowerVR 3 based - graphics board. - - To compile this driver as a module, choose M here: the - module will be called kyrofb. - -config FB_3DFX - tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support" - depends on FB && PCI - select FB_CFB_IMAGEBLIT - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_MODE_HELPERS - help - This driver supports graphics boards with the 3Dfx Banshee, - Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have - such a graphics board. - - To compile this driver as a module, choose M here: the - module will be called tdfxfb. - -config FB_3DFX_ACCEL - bool "3Dfx Acceleration functions" - depends on FB_3DFX - ---help--- - This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer - device driver with acceleration functions. - -config FB_3DFX_I2C - bool "Enable DDC/I2C support" - depends on FB_3DFX - select FB_DDC - default y - help - Say Y here if you want DDC/I2C support for your 3dfx Voodoo3. - -config FB_VOODOO1 - tristate "3Dfx Voodoo Graphics (sst1) support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or - Voodoo2 (cvg) based graphics card. - - To compile this driver as a module, choose M here: the - module will be called sstfb. - - WARNING: Do not use any application that uses the 3D engine - (namely glide) while using this driver. - Please read the for supported - options and other important info support. - -config FB_VT8623 - tristate "VIA VT8623 support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_SVGALIB - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - ---help--- - Driver for CastleRock integrated graphics core in the - VIA VT8623 [Apollo CLE266] chipset. - -config FB_TRIDENT - tristate "Trident/CyberXXX/CyberBlade support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - This is the frame buffer device driver for Trident PCI/AGP chipsets. - Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D - and Blade XP. - There are also integrated versions of these chips called CyberXXXX, - CyberImage or CyberBlade. These chips are mostly found in laptops - but also on some motherboards including early VIA EPIA motherboards. - For more information, read - - Say Y if you have such a graphics board. - - To compile this driver as a module, choose M here: the - module will be called tridentfb. - -config FB_ARK - tristate "ARK 2000PV support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_TILEBLITTING - select FB_SVGALIB - select VGASTATE - select FONT_8x16 if FRAMEBUFFER_CONSOLE - ---help--- - Driver for PCI graphics boards with ARK 2000PV chip - and ICS 5342 RAMDAC. - -config FB_PM3 - tristate "Permedia3 support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the 3DLabs Permedia3 - chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & - similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 - and maybe other boards. - -config FB_CARMINE - tristate "Fujitsu carmine frame buffer support" - depends on FB && PCI - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the Fujitsu Carmine chip. - The driver provides two independent frame buffer devices. - -choice - depends on FB_CARMINE - prompt "DRAM timing" - default FB_CARMINE_DRAM_EVAL - -config FB_CARMINE_DRAM_EVAL - bool "Eval board timings" - help - Use timings which work on the eval card. - -config CARMINE_DRAM_CUSTOM - bool "Custom board timings" - help - Use custom board timings. -endchoice - -config FB_AU1100 - bool "Au1100 LCD Driver" - depends on (FB = y) && MIPS_ALCHEMY - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the framebuffer driver for the AMD Au1100 SOC. It can drive - various panels and CRTs by passing in kernel cmd line option - au1100fb:panel=. - -config FB_AU1200 - bool "Au1200/Au1300 LCD Driver" - depends on (FB = y) && MIPS_ALCHEMY - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - help - This is the framebuffer driver for the Au1200/Au1300 SOCs. - It can drive various panels and CRTs by passing in kernel cmd line - option au1200fb:panel=. - -config FB_VT8500 - bool "VIA VT8500 framebuffer support" - depends on (FB = y) && ARM && ARCH_VT8500 - select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) - select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) - select FB_SYS_IMAGEBLIT - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - help - This is the framebuffer driver for VIA VT8500 integrated LCD - controller. - -config FB_WM8505 - bool "Wondermedia WM8xxx-series frame buffer support" - depends on (FB = y) && ARM && ARCH_VT8500 - select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) - select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) - select FB_SYS_IMAGEBLIT - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - help - This is the framebuffer driver for WonderMedia WM8xxx-series - integrated LCD controller. This driver covers the WM8505, WM8650 - and WM8850 SoCs. - -config FB_WMT_GE_ROPS - bool "VT8500/WM8xxx accelerated raster ops support" - depends on (FB = y) && (FB_VT8500 || FB_WM8505) - default n - help - This adds support for accelerated raster operations on the - VIA VT8500 and Wondermedia 85xx series SoCs. - -source "drivers/video/geode/Kconfig" - -config FB_HIT - tristate "HD64461 Frame Buffer support" - depends on FB && HD64461 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This is the frame buffer device driver for the Hitachi HD64461 LCD - frame buffer card. - -config FB_PMAG_AA - bool "PMAG-AA TURBOchannel framebuffer support" - depends on (FB = y) && TC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) - used mainly in the MIPS-based DECstation series. - -config FB_PMAG_BA - tristate "PMAG-BA TURBOchannel framebuffer support" - depends on FB && TC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) - used mainly in the MIPS-based DECstation series. - -config FB_PMAGB_B - tristate "PMAGB-B TURBOchannel framebuffer support" - depends on FB && TC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Support for the PMAGB-B TURBOchannel framebuffer card used mainly - in the MIPS-based DECstation series. The card is currently only - supported in 1280x1024x8 mode. - -config FB_MAXINE - bool "Maxine (Personal DECstation) onboard framebuffer support" - depends on (FB = y) && MACH_DECSTATION - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Support for the onboard framebuffer (1024x768x8) in the Personal - DECstation series (Personal DECstation 5000/20, /25, /33, /50, - Codename "Maxine"). - -config FB_G364 - bool "G364 frame buffer support" - depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - The G364 driver is the framebuffer used in MIPS Magnum 4000 and - Olivetti M700-10 systems. - -config FB_68328 - bool "Motorola 68328 native frame buffer support" - depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Say Y here if you want to support the built-in frame buffer of - the Motorola 68328 CPU family. - -config FB_PXA168 - tristate "PXA168/910 LCD framebuffer support" - depends on FB && (CPU_PXA168 || CPU_PXA910) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the built-in LCD controller in the Marvell - MMP processor. - -config FB_PXA - tristate "PXA LCD framebuffer support" - depends on FB && ARCH_PXA - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the built-in LCD controller in the Intel - PXA2x0 processor. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called pxafb. If you want to compile it as a module, - say M here and read . - - If unsure, say N. - -config FB_PXA_OVERLAY - bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer" - default n - depends on FB_PXA && (PXA27x || PXA3xx) - -config FB_PXA_SMARTPANEL - bool "PXA Smartpanel LCD support" - default n - depends on FB_PXA - -config FB_PXA_PARAMETERS - bool "PXA LCD command line parameters" - default n - depends on FB_PXA - ---help--- - Enable the use of kernel command line or module parameters - to configure the physical properties of the LCD panel when - using the PXA LCD driver. - - This option allows you to override the panel parameters - supplied by the platform in order to support multiple - different models of flatpanel. If you will only be using a - single model of flatpanel then you can safely leave this - option disabled. - - describes the available parameters. - -config PXA3XX_GCU - tristate "PXA3xx 2D graphics accelerator driver" - depends on FB_PXA - help - Kernelspace driver for the 2D graphics controller unit (GCU) - found on PXA3xx processors. There is a counterpart driver in the - DirectFB suite, see http://www.directfb.org/ - - If you compile this as a module, it will be called pxa3xx_gcu. - -config FB_MBX - tristate "2700G LCD framebuffer support" - depends on FB && ARCH_PXA - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Framebuffer driver for the Intel 2700G (Marathon) Graphics - Accelerator - -config FB_MBX_DEBUG - bool "Enable debugging info via debugfs" - depends on FB_MBX && DEBUG_FS - default n - ---help--- - Enable this if you want debugging information using the debug - filesystem (debugfs) - - If unsure, say N. - -config FB_FSL_DIU - tristate "Freescale DIU framebuffer support" - depends on FB && FSL_SOC - select FB_MODE_HELPERS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select PPC_LIB_RHEAP - ---help--- - Framebuffer driver for the Freescale SoC DIU - -config FB_W100 - tristate "W100 frame buffer support" - depends on FB && ARCH_PXA - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. - It can also drive the w3220 chip found on iPAQ hx4700. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called w100fb. If you want to compile it as a module, - say M here and read . - - If unsure, say N. - -config FB_SH_MOBILE_LCDC - tristate "SuperH Mobile LCDC framebuffer support" - depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - select FB_BACKLIGHT - select SH_MIPI_DSI if SH_LCD_MIPI_DSI - ---help--- - Frame buffer driver for the on-chip SH-Mobile LCD controller. - -config FB_SH_MOBILE_HDMI - tristate "SuperH Mobile HDMI controller support" - depends on FB_SH_MOBILE_LCDC - select FB_MODE_HELPERS - select SOUND - select SND - select SND_SOC - ---help--- - Driver for the on-chip SH-Mobile HDMI controller. - -config FB_TMIO - tristate "Toshiba Mobile IO FrameBuffer support" - depends on FB && MFD_CORE - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the Toshiba Mobile IO integrated as found - on the Sharp SL-6000 series - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called tmiofb. If you want to compile it as a module, - say M here and read . - - If unsure, say N. - -config FB_TMIO_ACCELL - bool "tmiofb acceleration" - depends on FB_TMIO - default y - -config FB_S3C - tristate "Samsung S3C framebuffer support" - depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \ - ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the built-in FB controller in the Samsung - SoC line from the S3C2443 onwards, including the S3C2416, S3C2450, - and the S3C64XX series such as the S3C6400 and S3C6410. - - These chips all have the same basic framebuffer design with the - actual capabilities depending on the chip. For instance the S3C6400 - and S3C6410 support 4 hardware windows whereas the S3C24XX series - currently only have two. - - Currently the support is only for the S3C6400 and S3C6410 SoCs. - -config FB_S3C_DEBUG_REGWRITE - bool "Debug register writes" - depends on FB_S3C - ---help--- - Show all register writes via pr_debug() - -config FB_S3C2410 - tristate "S3C2410 LCD framebuffer support" - depends on FB && ARCH_S3C24XX - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the built-in LCD controller in the Samsung - S3C2410 processor. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called s3c2410fb. If you want to compile it as a module, - say M here and read . - - If unsure, say N. -config FB_S3C2410_DEBUG - bool "S3C2410 lcd debug messages" - depends on FB_S3C2410 - help - Turn on debugging messages. Note that you can set/unset at run time - through sysfs - -config FB_NUC900 - bool "NUC900 LCD framebuffer support" - depends on FB && ARCH_W90X900 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the built-in LCD controller in the Nuvoton - NUC900 processor - -config GPM1040A0_320X240 - bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD" - depends on FB_NUC900 - -config FB_SM501 - tristate "Silicon Motion SM501 framebuffer support" - depends on FB && MFD_SM501 - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for the CRT and LCD controllers in the Silicon - Motion SM501. - - This driver is also available as a module ( = code which can be - inserted and removed from the running kernel whenever you want). The - module will be called sm501fb. If you want to compile it as a module, - say M here and read . - - If unsure, say N. - -config FB_SMSCUFX - tristate "SMSC UFX6000/7000 USB Framebuffer support" - depends on FB && USB - select FB_MODE_HELPERS - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - ---help--- - This is a kernel framebuffer driver for SMSC UFX USB devices. - Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and - mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000 - (USB 3.0) devices. - To compile as a module, choose M here: the module name is smscufx. - -config FB_UDL - tristate "Displaylink USB Framebuffer support" - depends on FB && USB - select FB_MODE_HELPERS - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - ---help--- - This is a kernel framebuffer driver for DisplayLink USB devices. - Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and - mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices. - To compile as a module, choose M here: the module name is udlfb. - -config FB_IBM_GXT4500 - tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors" - depends on FB && PPC - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Say Y here to enable support for the IBM GXT4000P/6000P and - GXT4500P/6500P display adaptor based on Raster Engine RC1000, - found on some IBM System P (pSeries) machines. This driver - doesn't use Geometry Engine GT1000. - -config FB_PS3 - tristate "PS3 GPU framebuffer driver" - depends on FB && PS3_PS3AV - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE - ---help--- - Include support for the virtual frame buffer in the PS3 platform. - -config FB_PS3_DEFAULT_SIZE_M - int "PS3 default frame buffer size (in MiB)" - depends on FB_PS3 - default 9 - ---help--- - This is the default size (in MiB) of the virtual frame buffer in - the PS3. - The default value can be overridden on the kernel command line - using the "ps3fb" option (e.g. "ps3fb=9M"); - -config FB_XILINX - tristate "Xilinx frame buffer support" - depends on FB && (XILINX_VIRTEX || MICROBLAZE || ARCH_ZYNQ) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Include support for the Xilinx ML300/ML403 reference design - framebuffer. ML300 carries a 640*480 LCD display on the board, - ML403 uses a standard DB15 VGA connector. - -config FB_GOLDFISH - tristate "Goldfish Framebuffer" - depends on FB && HAS_DMA - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Framebuffer driver for Goldfish Virtual Platform - -config FB_COBALT - tristate "Cobalt server LCD frame buffer support" - depends on FB && (MIPS_COBALT || MIPS_SEAD3) - -config FB_SH7760 - bool "SH7760/SH7763/SH7720/SH7721 LCDC support" - depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ - || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Support for the SH7760/SH7763/SH7720/SH7721 integrated - (D)STN/TFT LCD Controller. - Supports display resolutions up to 1024x1024 pixel, grayscale and - color operation, with depths ranging from 1 bpp to 8 bpp monochrome - and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for - panels <= 320 pixel horizontal resolution. - -config FB_DA8XX - tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support" - depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_CFB_REV_PIXELS_IN_BYTE - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - ---help--- - This is the frame buffer device driver for the TI LCD controller - found on DA8xx/OMAP-L1xx/AM335x SoCs. - If unsure, say N. - -config FB_VIRTUAL - tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" - depends on FB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - ---help--- - This is a `virtual' frame buffer device. It operates on a chunk of - unswappable kernel memory instead of on the memory of a graphics - board. This means you cannot see any output sent to this frame - buffer device, while it does consume precious memory. The main use - of this frame buffer device is testing and debugging the frame - buffer subsystem. Do NOT enable it for normal systems! To protect - the innocent, it has to be enabled explicitly at boot time using the - kernel option `video=vfb:'. - - To compile this driver as a module, choose M here: the - module will be called vfb. In order to load it, you must use - the vfb_enable=1 option. - - If unsure, say N. - -config XEN_FBDEV_FRONTEND - tristate "Xen virtual frame buffer support" - depends on FB && XEN - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC - select XEN_XENBUS_FRONTEND - default y - help - This driver implements the front-end of the Xen virtual - frame buffer driver. It communicates with a back-end - in another domain. - -config FB_METRONOME - tristate "E-Ink Metronome/8track controller support" - depends on FB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - help - This driver implements support for the E-Ink Metronome - controller. The pre-release name for this device was 8track - and could also have been called by some vendors as PVI-nnnn. - -config FB_MB862XX - tristate "Fujitsu MB862xx GDC support" - depends on FB - depends on PCI || (OF && PPC) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. - -choice - prompt "GDC variant" - depends on FB_MB862XX - -config FB_MB862XX_PCI_GDC - bool "Carmine/Coral-P(A) GDC" - depends on PCI - ---help--- - This enables framebuffer support for Fujitsu Carmine/Coral-P(A) - PCI graphics controller devices. - -config FB_MB862XX_LIME - bool "Lime GDC" - depends on OF && PPC - select FB_FOREIGN_ENDIAN - select FB_LITTLE_ENDIAN - ---help--- - Framebuffer support for Fujitsu Lime GDC on host CPU bus. - -endchoice - -config FB_MB862XX_I2C - bool "Support I2C bus on MB862XX GDC" - depends on FB_MB862XX && I2C - default y - help - Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter - driver to support accessing I2C devices on controller's I2C bus. - These are usually some video decoder chips. - -config FB_EP93XX - tristate "EP93XX frame buffer support" - depends on FB && ARCH_EP93XX - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Framebuffer driver for the Cirrus Logic EP93XX series of processors. - This driver is also available as a module. The module will be called - ep93xx-fb. - -config FB_PRE_INIT_FB - bool "Don't reinitialize, use bootloader's GDC/Display configuration" - depends on FB && FB_MB862XX_LIME - ---help--- - Select this option if display contents should be inherited as set by - the bootloader. - -config FB_MSM - tristate "MSM Framebuffer support" - depends on FB && ARCH_MSM - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - -config FB_MX3 - tristate "MX3 Framebuffer support" - depends on FB && MX3_IPU - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - default y - help - This is a framebuffer device for the i.MX31 LCD Controller. So - far only synchronous displays are supported. If you plan to use - an LCD display with your i.MX31 system, say Y here. - -config FB_BROADSHEET - tristate "E-Ink Broadsheet/Epson S1D13521 controller support" - depends on FB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - help - This driver implements support for the E-Ink Broadsheet - controller. The release name for this device was Epson S1D13521 - and could also have been called by other names when coupled with - a bridge adapter. - -config FB_AUO_K190X - tristate "AUO-K190X EPD controller support" - depends on FB - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - select FB_DEFERRED_IO - help - Provides support for epaper controllers from the K190X series - of AUO. These controllers can be used to drive epaper displays - from Sipix. - - This option enables the common support, shared by the individual - controller drivers. You will also have to enable the driver - for the controller type used in your device. - -config FB_AUO_K1900 - tristate "AUO-K1900 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1900 epd-controller. - This controller can drive Sipix epaper displays but can only do - serial updates, reducing the number of possible frames per second. - -config FB_AUO_K1901 - tristate "AUO-K1901 EPD controller support" - depends on FB && FB_AUO_K190X - help - This driver implements support for the AUO K1901 epd-controller. - This controller can drive Sipix epaper displays and supports - concurrent updates, making higher frames per second possible. - -config FB_JZ4740 - tristate "JZ4740 LCD framebuffer support" - depends on FB && MACH_JZ4740 - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - help - Framebuffer support for the JZ4740 SoC. - -config FB_MXS - tristate "MXS LCD framebuffer support" - depends on FB && ARCH_MXS - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - select FB_MODE_HELPERS - select VIDEOMODE_HELPERS - help - Framebuffer support for the MXS SoC. - -config FB_PUV3_UNIGFX - tristate "PKUnity v3 Unigfx framebuffer support" - depends on FB && UNICORE32 && ARCH_PUV3 - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_SYS_FOPS - help - Choose this option if you want to use the Unigfx device as a - framebuffer device. Without the support of PCI & AGP. - -config FB_HYPERV - tristate "Microsoft Hyper-V Synthetic Video support" - depends on FB && HYPERV - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - This framebuffer driver supports Microsoft Hyper-V Synthetic Video. - -config FB_SIMPLE - bool "Simple framebuffer support" - depends on (FB = y) - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - Say Y if you want support for a simple frame-buffer. - - This driver assumes that the display hardware has been initialized - before the kernel boots, and the kernel will simply render to the - pre-allocated frame buffer surface. - - Configuration re: surface address, size, and format must be provided - through device tree, or plain old platform data. - -source "drivers/video/omap/Kconfig" -source "drivers/video/omap2/Kconfig" -source "drivers/video/exynos/Kconfig" -source "drivers/video/mmp/Kconfig" -source "drivers/video/backlight/Kconfig" - if VT source "drivers/video/console/Kconfig" endif if FB || SGI_NEWPORT_CONSOLE source "drivers/video/logo/Kconfig" -endif -config FB_SH_MOBILE_MERAM - tristate "SuperH Mobile MERAM read ahead support" - depends on (SUPERH || ARCH_SHMOBILE) - select GENERIC_ALLOCATOR - ---help--- - Enable MERAM support for the SuperH controller. - - This will allow for caching of the framebuffer to provide more - reliable access under heavy main memory bus traffic situations. - Up to 4 memory channels can be configured, allowing 4 RGB or - 2 YCbCr framebuffers to be configured. +endif -config FB_SSD1307 - tristate "Solomon SSD1307 framebuffer support" - depends on FB && I2C - depends on OF - depends on GPIOLIB - select FB_SYS_FOPS - select FB_SYS_FILLRECT - select FB_SYS_COPYAREA - select FB_SYS_IMAGEBLIT - select FB_DEFERRED_IO - select PWM - help - This driver implements support for the Solomon SSD1307 - OLED controller over I2C. endmenu diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 1be26fe10592e8..9ad3c17d645689 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -1,175 +1,11 @@ -# Makefile for the Linux video drivers. -# 5 Aug 1999, James Simmons, -# Rewritten to use lists instead of if-statements. - -# Each configuration option enables a list of files. - obj-$(CONFIG_VGASTATE) += vgastate.o obj-$(CONFIG_HDMI) += hdmi.o -obj-y += fb_notify.o -obj-$(CONFIG_FB) += fb.o -fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ - modedb.o fbcvt.o -fb-objs := $(fb-y) obj-$(CONFIG_VT) += console/ obj-$(CONFIG_LOGO) += logo/ obj-y += backlight/ -obj-$(CONFIG_EXYNOS_VIDEO) += exynos/ - -obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o -obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o -obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o -obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o -obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o -obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o -obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o -obj-$(CONFIG_FB_SVGALIB) += svgalib.o -obj-$(CONFIG_FB_MACMODES) += macmodes.o -obj-$(CONFIG_FB_DDC) += fb_ddc.o -obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o -obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o - -# Hardware specific drivers go first -obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o -obj-$(CONFIG_FB_ARC) += arcfb.o -obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o -obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o -obj-$(CONFIG_FB_GRVGA) += grvga.o -obj-$(CONFIG_FB_PM2) += pm2fb.o -obj-$(CONFIG_FB_PM3) += pm3fb.o - -obj-$(CONFIG_FB_I740) += i740fb.o -obj-$(CONFIG_FB_MATROX) += matrox/ -obj-$(CONFIG_FB_RIVA) += riva/ -obj-$(CONFIG_FB_NVIDIA) += nvidia/ -obj-$(CONFIG_FB_ATY) += aty/ macmodes.o -obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o -obj-$(CONFIG_FB_RADEON) += aty/ -obj-$(CONFIG_FB_SIS) += sis/ -obj-$(CONFIG_FB_VIA) += via/ -obj-$(CONFIG_FB_KYRO) += kyro/ -obj-$(CONFIG_FB_SAVAGE) += savage/ -obj-$(CONFIG_FB_GEODE) += geode/ -obj-$(CONFIG_FB_MBX) += mbx/ -obj-$(CONFIG_FB_NEOMAGIC) += neofb.o -obj-$(CONFIG_FB_3DFX) += tdfxfb.o -obj-$(CONFIG_FB_CONTROL) += controlfb.o -obj-$(CONFIG_FB_PLATINUM) += platinumfb.o -obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o -obj-$(CONFIG_FB_CT65550) += chipsfb.o -obj-$(CONFIG_FB_IMSTT) += imsttfb.o -obj-$(CONFIG_FB_FM2) += fm2fb.o -obj-$(CONFIG_FB_VT8623) += vt8623fb.o -obj-$(CONFIG_FB_TRIDENT) += tridentfb.o -obj-$(CONFIG_FB_LE80578) += vermilion/ -obj-$(CONFIG_FB_S3) += s3fb.o -obj-$(CONFIG_FB_ARK) += arkfb.o -obj-$(CONFIG_FB_STI) += stifb.o -obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o -obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o -obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o -obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o -obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o -obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o -obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o -obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o -obj-$(CONFIG_FB_ACORN) += acornfb.o -obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \ - atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o -obj-$(CONFIG_FB_MAC) += macfb.o -obj-$(CONFIG_FB_HECUBA) += hecubafb.o -obj-$(CONFIG_FB_N411) += n411.o -obj-$(CONFIG_FB_HGA) += hgafb.o -obj-$(CONFIG_FB_XVR500) += sunxvr500.o -obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o -obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o -obj-$(CONFIG_FB_IGA) += igafb.o -obj-$(CONFIG_FB_APOLLO) += dnfb.o -obj-$(CONFIG_FB_Q40) += q40fb.o -obj-$(CONFIG_FB_TGA) += tgafb.o -obj-$(CONFIG_FB_HP300) += hpfb.o -obj-$(CONFIG_FB_G364) += g364fb.o -obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o -obj-$(CONFIG_FB_SA1100) += sa1100fb.o -obj-$(CONFIG_FB_HIT) += hitfb.o -obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o -obj-$(CONFIG_FB_PVR2) += pvr2fb.o -obj-$(CONFIG_FB_VOODOO1) += sstfb.o -obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o -obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o -obj-$(CONFIG_FB_68328) += 68328fb.o -obj-$(CONFIG_FB_GBE) += gbefb.o -obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o -obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o -obj-$(CONFIG_FB_PXA) += pxafb.o -obj-$(CONFIG_FB_PXA168) += pxa168fb.o -obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o -obj-$(CONFIG_MMP_DISP) += mmp/ -obj-$(CONFIG_FB_W100) += w100fb.o -obj-$(CONFIG_FB_TMIO) += tmiofb.o -obj-$(CONFIG_FB_AU1100) += au1100fb.o -obj-$(CONFIG_FB_AU1200) += au1200fb.o -obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o -obj-$(CONFIG_FB_WM8505) += wm8505fb.o -obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o -obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o -obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o -obj-$(CONFIG_FB_MAXINE) += maxinefb.o -obj-$(CONFIG_FB_METRONOME) += metronomefb.o -obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o -obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o -obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o -obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o -obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o -obj-$(CONFIG_FB_SH7760) += sh7760fb.o -obj-$(CONFIG_FB_IMX) += imxfb.o -obj-$(CONFIG_FB_S3C) += s3c-fb.o -obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o -obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o -obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o -obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o -obj-$(CONFIG_FB_PS3) += ps3fb.o -obj-$(CONFIG_FB_SM501) += sm501fb.o -obj-$(CONFIG_FB_UDL) += udlfb.o -obj-$(CONFIG_FB_SMSCUFX) += smscufx.o -obj-$(CONFIG_FB_XILINX) += xilinxfb.o -obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o -obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o -obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o -obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o -obj-$(CONFIG_FB_OMAP) += omap/ -obj-y += omap2/ -obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o -obj-$(CONFIG_FB_CARMINE) += carminefb.o -obj-$(CONFIG_FB_MB862XX) += mb862xx/ -obj-$(CONFIG_FB_MSM) += msm/ -obj-$(CONFIG_FB_NUC900) += nuc900fb.o -obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o -obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o -obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o -obj-$(CONFIG_FB_OPENCORES) += ocfb.o - -# Platform or fallback drivers go here -obj-$(CONFIG_FB_UVESA) += uvesafb.o -obj-$(CONFIG_FB_VESA) += vesafb.o -obj-$(CONFIG_FB_EFI) += efifb.o -obj-$(CONFIG_FB_VGA16) += vga16fb.o -obj-$(CONFIG_FB_OF) += offb.o -obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o -obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o -obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o -obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o -obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o -obj-$(CONFIG_FB_MX3) += mx3fb.o -obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o -obj-$(CONFIG_FB_MXS) += mxsfb.o -obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o -obj-$(CONFIG_FB_SIMPLE) += simplefb.o - -# the test framebuffer is last -obj-$(CONFIG_FB_VIRTUAL) += vfb.o +obj-y += fbdev/ obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o ifeq ($(CONFIG_OF),y) diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 5f65ca3d85645e..026fd12159332c 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -46,7 +46,7 @@ #include -#include "../sticore.h" +#include "../fbdev/sticore.h" /* switching to graphics mode */ #define BLANK 0 diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index cecd3de01c2422..7da1ad03acb571 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -28,7 +28,7 @@ #include #include -#include "../sticore.h" +#include "../fbdev/sticore.h" #define STI_DRIVERVERSION "Version 0.9b" diff --git a/drivers/video/68328fb.c b/drivers/video/fbdev/68328fb.c similarity index 100% rename from drivers/video/68328fb.c rename to drivers/video/fbdev/68328fb.c diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig new file mode 100644 index 00000000000000..e1f47272fdea0d --- /dev/null +++ b/drivers/video/fbdev/Kconfig @@ -0,0 +1,2474 @@ +# +# fbdev configuration +# + +menuconfig FB + tristate "Support for frame buffer devices" + ---help--- + The frame buffer device provides an abstraction for the graphics + hardware. It represents the frame buffer of some video hardware and + allows application software to access the graphics hardware through + a well-defined interface, so the software doesn't need to know + anything about the low-level (hardware register) stuff. + + Frame buffer devices work identically across the different + architectures supported by Linux and make the implementation of + application programs easier and more portable; at this point, an X + server exists which uses the frame buffer device exclusively. + On several non-X86 architectures, the frame buffer device is the + only way to use the graphics hardware. + + The device is accessed through special device nodes, usually located + in the /dev directory, i.e. /dev/fb*. + + You need an utility program called fbset to make full use of frame + buffer devices. Please read + and the Framebuffer-HOWTO at + for more + information. + + Say Y here and to the driver for your graphics board below if you + are compiling a kernel for a non-x86 architecture. + + If you are compiling for the x86 architecture, you can say Y if you + want to play with it, but it is not essential. Please note that + running graphical applications that directly touch the hardware + (e.g. an accelerated X server) and that are not frame buffer + device-aware may cause unexpected results. If unsure, say N. + +config FIRMWARE_EDID + bool "Enable firmware EDID" + depends on FB + default n + ---help--- + This enables access to the EDID transferred from the firmware. + On the i386, this is from the Video BIOS. Enable this if DDC/I2C + transfers do not work for your driver and if you are using + nvidiafb, i810fb or savagefb. + + In general, choosing Y for this option is safe. If you + experience extremely long delays while booting before you get + something on your display, try setting this to N. Matrox cards in + combination with certain motherboards and monitors are known to + suffer from this problem. + +config FB_DDC + tristate + depends on FB + select I2C_ALGOBIT + select I2C + default n + +config FB_BOOT_VESA_SUPPORT + bool + depends on FB + default n + ---help--- + If true, at least one selected framebuffer driver can take advantage + of VESA video modes set at an early boot stage via the vga= parameter. + +config FB_CFB_FILLRECT + tristate + depends on FB + default n + ---help--- + Include the cfb_fillrect function for generic software rectangle + filling. This is used by drivers that don't provide their own + (accelerated) version. + +config FB_CFB_COPYAREA + tristate + depends on FB + default n + ---help--- + Include the cfb_copyarea function for generic software area copying. + This is used by drivers that don't provide their own (accelerated) + version. + +config FB_CFB_IMAGEBLIT + tristate + depends on FB + default n + ---help--- + Include the cfb_imageblit function for generic software image + blitting. This is used by drivers that don't provide their own + (accelerated) version. + +config FB_CFB_REV_PIXELS_IN_BYTE + bool + depends on FB + default n + ---help--- + Allow generic frame-buffer functions to work on displays with 1, 2 + and 4 bits per pixel depths which has opposite order of pixels in + byte order to bytes in long order. + +config FB_SYS_FILLRECT + tristate + depends on FB + default n + ---help--- + Include the sys_fillrect function for generic software rectangle + filling. This is used by drivers that don't provide their own + (accelerated) version and the framebuffer is in system RAM. + +config FB_SYS_COPYAREA + tristate + depends on FB + default n + ---help--- + Include the sys_copyarea function for generic software area copying. + This is used by drivers that don't provide their own (accelerated) + version and the framebuffer is in system RAM. + +config FB_SYS_IMAGEBLIT + tristate + depends on FB + default n + ---help--- + Include the sys_imageblit function for generic software image + blitting. This is used by drivers that don't provide their own + (accelerated) version and the framebuffer is in system RAM. + +menuconfig FB_FOREIGN_ENDIAN + bool "Framebuffer foreign endianness support" + depends on FB + ---help--- + This menu will let you enable support for the framebuffers with + non-native endianness (e.g. Little-Endian framebuffer on a + Big-Endian machine). Most probably you don't have such hardware, + so it's safe to say "n" here. + +choice + prompt "Choice endianness support" + depends on FB_FOREIGN_ENDIAN + +config FB_BOTH_ENDIAN + bool "Support for Big- and Little-Endian framebuffers" + +config FB_BIG_ENDIAN + bool "Support for Big-Endian framebuffers only" + +config FB_LITTLE_ENDIAN + bool "Support for Little-Endian framebuffers only" + +endchoice + +config FB_SYS_FOPS + tristate + depends on FB + default n + +config FB_DEFERRED_IO + bool + depends on FB + +config FB_HECUBA + tristate + depends on FB + depends on FB_DEFERRED_IO + +config FB_SVGALIB + tristate + depends on FB + default n + ---help--- + Common utility functions useful to fbdev drivers of VGA-based + cards. + +config FB_MACMODES + tristate + depends on FB + default n + +config FB_BACKLIGHT + bool + depends on FB + select BACKLIGHT_LCD_SUPPORT + select BACKLIGHT_CLASS_DEVICE + default n + +config FB_MODE_HELPERS + bool "Enable Video Mode Handling Helpers" + depends on FB + default n + ---help--- + This enables functions for handling video modes using the + Generalized Timing Formula and the EDID parser. A few drivers rely + on this feature such as the radeonfb, rivafb, and the i810fb. If + your driver does not take advantage of this feature, choosing Y will + just increase the kernel size by about 5K. + +config FB_TILEBLITTING + bool "Enable Tile Blitting Support" + depends on FB + default n + ---help--- + This enables tile blitting. Tile blitting is a drawing technique + where the screen is divided into rectangular sections (tiles), whereas + the standard blitting divides the screen into pixels. Because the + default drawing element is a tile, drawing functions will be passed + parameters in terms of number of tiles instead of number of pixels. + For example, to draw a single character, instead of using bitmaps, + an index to an array of bitmaps will be used. To clear or move a + rectangular section of a screen, the rectangle will be described in + terms of number of tiles in the x- and y-axis. + + This is particularly important to one driver, matroxfb. If + unsure, say N. + +comment "Frame buffer hardware drivers" + depends on FB + +config FB_GRVGA + tristate "Aeroflex Gaisler framebuffer support" + depends on FB && SPARC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + This enables support for the SVGACTRL framebuffer in the GRLIB IP library from Aeroflex Gaisler. + +config FB_CIRRUS + tristate "Cirrus Logic support" + depends on FB && (ZORRO || PCI) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + This enables support for Cirrus Logic GD542x/543x based boards on + Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. + + If you have a PCI-based system, this enables support for these + chips: GD-543x, GD-544x, GD-5480. + + Please read the file . + + Say N unless you have such a graphics board or plan to get one + before you next recompile the kernel. + +config FB_PM2 + tristate "Permedia2 support" + depends on FB && ((AMIGA && BROKEN) || PCI) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for cards based on + the 3D Labs Permedia, Permedia 2 and Permedia 2V chips. + The driver was tested on the following cards: + Diamond FireGL 1000 PRO AGP + ELSA Gloria Synergy PCI + Appian Jeronimo PRO (both heads) PCI + 3DLabs Oxygen ACX aka EONtronics Picasso P2 PCI + Techsource Raptor GFX-8P (aka Sun PGX-32) on SPARC + ASK Graphic Blaster Exxtreme AGP + + To compile this driver as a module, choose M here: the + module will be called pm2fb. + +config FB_PM2_FIFO_DISCONNECT + bool "enable FIFO disconnect feature" + depends on FB_PM2 && PCI + help + Support the Permedia2 FIFO disconnect feature. + +config FB_ARMCLCD + tristate "ARM PrimeCell PL110 support" + depends on ARM || ARM64 || COMPILE_TEST + depends on FB && ARM_AMBA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This framebuffer device driver is for the ARM PrimeCell PL110 + Colour LCD controller. ARM PrimeCells provide the building + blocks for System on a Chip devices. + + If you want to compile this as a module (=code which can be + inserted into and removed from the running kernel), say M + here and read . The module + will be called amba-clcd. + +config FB_ACORN + bool "Acorn VIDC support" + depends on (FB = y) && ARM && ARCH_ACORN + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Acorn VIDC graphics + hardware found in Acorn RISC PCs and other ARM-based machines. If + unsure, say N. + +config FB_CLPS711X + bool "CLPS711X LCD support" + depends on (FB = y) && ARM && ARCH_CLPS711X + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y to enable the Framebuffer driver for the CLPS7111 and + EP7212 processors. + +config FB_SA1100 + bool "SA-1100 LCD support" + depends on (FB = y) && ARM && ARCH_SA1100 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is a framebuffer device for the SA-1100 LCD Controller. + See for information on framebuffer + devices. + + If you plan to use the LCD display with your SA-1100 system, say + Y here. + +config FB_IMX + tristate "Freescale i.MX1/21/25/27 LCD support" + depends on FB && ARCH_MXC + select BACKLIGHT_LCD_SUPPORT + select LCD_CLASS_DEVICE + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS + +config FB_CYBER2000 + tristate "CyberPro 2000/2010/5000 support" + depends on FB && PCI && (BROKEN || !SPARC64) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the Integraphics CyberPro 20x0 and 5000 + VGA chips used in the Rebel.com Netwinder and other machines. + Say Y if you have a NetWinder or a graphics card containing this + device, otherwise say N. + +config FB_CYBER2000_DDC + bool "DDC for CyberPro support" + depends on FB_CYBER2000 + select FB_DDC + default y + help + Say Y here if you want DDC support for your CyberPro graphics + card. This is only I2C bus support, driver does not use EDID. + +config FB_CYBER2000_I2C + bool "CyberPro 2000/2010/5000 I2C support" + depends on FB_CYBER2000 && I2C && ARCH_NETWINDER + select I2C_ALGOBIT + help + Enable support for the I2C video decoder interface on the + Integraphics CyberPro 20x0 and 5000 VGA chips. This is used + on the Netwinder machines for the SAA7111 video capture. + +config FB_APOLLO + bool + depends on (FB = y) && APOLLO + default y + select FB_CFB_FILLRECT + select FB_CFB_IMAGEBLIT + +config FB_Q40 + bool + depends on (FB = y) && Q40 + default y + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + +config FB_AMIGA + tristate "Amiga native chipset support" + depends on FB && AMIGA + help + This is the frame buffer device driver for the builtin graphics + chipset found in Amigas. + + To compile this driver as a module, choose M here: the + module will be called amifb. + +config FB_AMIGA_OCS + bool "Amiga OCS chipset support" + depends on FB_AMIGA + help + This enables support for the original Agnus and Denise video chips, + found in the Amiga 1000 and most A500's and A2000's. If you intend + to run Linux on any of these systems, say Y; otherwise say N. + +config FB_AMIGA_ECS + bool "Amiga ECS chipset support" + depends on FB_AMIGA + help + This enables support for the Enhanced Chip Set, found in later + A500's, later A2000's, the A600, the A3000, the A3000T and CDTV. If + you intend to run Linux on any of these systems, say Y; otherwise + say N. + +config FB_AMIGA_AGA + bool "Amiga AGA chipset support" + depends on FB_AMIGA + help + This enables support for the Advanced Graphics Architecture (also + known as the AGA or AA) Chip Set, found in the A1200, A4000, A4000T + and CD32. If you intend to run Linux on any of these systems, say Y; + otherwise say N. + +config FB_FM2 + bool "Amiga FrameMaster II/Rainbow II support" + depends on (FB = y) && ZORRO + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Amiga FrameMaster + card from BSC (exhibited 1992 but not shipped as a CBM product). + +config FB_ARC + tristate "Arc Monochrome LCD board support" + depends on FB && X86 + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + help + This enables support for the Arc Monochrome LCD board. The board + is based on the KS-108 lcd controller and is typically a matrix + of 2*n chips. This driver was tested with a 128x64 panel. This + driver supports it for use with x86 SBCs through a 16 bit GPIO + interface (8 bit data, 8 bit control). If you anticipate using + this driver, say Y or M; otherwise say N. You must specify the + GPIO IO address to be used for setting control and data. + +config FB_ATARI + bool "Atari native chipset support" + depends on (FB = y) && ATARI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the builtin graphics + chipset found in Ataris. + +config FB_OF + bool "Open Firmware frame buffer device support" + depends on (FB = y) && (PPC64 || PPC_OF) && (!PPC_PSERIES || PCI) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + Say Y if you want support with Open Firmware for your graphics + board. + +config FB_CONTROL + bool "Apple \"control\" display support" + depends on (FB = y) && PPC_PMAC && PPC32 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + This driver supports a frame buffer for the graphics adapter in the + Power Macintosh 7300 and others. + +config FB_PLATINUM + bool "Apple \"platinum\" display support" + depends on (FB = y) && PPC_PMAC && PPC32 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + This driver supports a frame buffer for the "platinum" graphics + adapter in some Power Macintoshes. + +config FB_VALKYRIE + bool "Apple \"valkyrie\" display support" + depends on (FB = y) && (MAC || (PPC_PMAC && PPC32)) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + help + This driver supports a frame buffer for the "valkyrie" graphics + adapter in some Power Macintoshes. + +config FB_CT65550 + bool "Chips 65550 display support" + depends on (FB = y) && PPC32 && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Chips & Technologies + 65550 graphics chip in PowerBooks. + +config FB_ASILIANT + bool "Asiliant (Chips) 69000 display support" + depends on (FB = y) && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Asiliant 69030 chipset + +config FB_IMSTT + bool "IMS Twin Turbo display support" + depends on (FB = y) && PCI + select FB_CFB_IMAGEBLIT + select FB_MACMODES if PPC + help + The IMS Twin Turbo is a PCI-based frame buffer card bundled with + many Macintosh and compatible computers. + +config FB_VGA16 + tristate "VGA 16-color graphics support" + depends on FB && (X86 || PPC) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE + help + This is the frame buffer device driver for VGA 16 color graphic + cards. Say Y if you have such a card. + + To compile this driver as a module, choose M here: the + module will be called vga16fb. + +config FB_BF54X_LQ043 + tristate "SHARP LQ043 TFT LCD (BF548 EZKIT)" + depends on FB && (BF54x) && !BF542 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device driver for a SHARP LQ043T1DG01 TFT LCD + +config FB_BFIN_T350MCQB + tristate "Varitronix COG-T350MCQB TFT LCD display (BF527 EZKIT)" + depends on FB && BLACKFIN + select BFIN_GPTIMERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device driver for a Varitronix VL-PS-COG-T350MCQB-01 display TFT LCD + This display is a QVGA 320x240 24-bit RGB display interfaced by an 8-bit wide PPI + It uses PPI[0..7] PPI_FS1, PPI_FS2 and PPI_CLK. + +config FB_BFIN_LQ035Q1 + tristate "SHARP LQ035Q1DH02 TFT LCD" + depends on FB && BLACKFIN && SPI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select BFIN_GPTIMERS + help + This is the framebuffer device driver for a SHARP LQ035Q1DH02 TFT display found on + the Blackfin Landscape LCD EZ-Extender Card. + This display is a QVGA 320x240 18-bit RGB display interfaced by an 16-bit wide PPI + It uses PPI[0..15] PPI_FS1, PPI_FS2 and PPI_CLK. + + To compile this driver as a module, choose M here: the + module will be called bfin-lq035q1-fb. + +config FB_BF537_LQ035 + tristate "SHARP LQ035 TFT LCD (BF537 STAMP)" + depends on FB && (BF534 || BF536 || BF537) && I2C_BLACKFIN_TWI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select BFIN_GPTIMERS + help + This is the framebuffer device for a SHARP LQ035Q7DB03 TFT LCD + attached to a BF537. + + To compile this driver as a module, choose M here: the + module will be called bf537-lq035. + +config FB_BFIN_7393 + tristate "Blackfin ADV7393 Video encoder" + depends on FB && BLACKFIN + select I2C + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for a ADV7393 video encoder + attached to a Blackfin on the PPI port. + If your Blackfin board has a ADV7393 select Y. + + To compile this driver as a module, choose M here: the + module will be called bfin_adv7393fb. + +choice + prompt "Video mode support" + depends on FB_BFIN_7393 + default NTSC + +config NTSC + bool 'NTSC 720x480' + +config PAL + bool 'PAL 720x576' + +config NTSC_640x480 + bool 'NTSC 640x480 (Experimental)' + +config PAL_640x480 + bool 'PAL 640x480 (Experimental)' + +config NTSC_YCBCR + bool 'NTSC 720x480 YCbCR input' + +config PAL_YCBCR + bool 'PAL 720x576 YCbCR input' + +endchoice + +choice + prompt "Size of ADV7393 frame buffer memory Single/Double Size" + depends on (FB_BFIN_7393) + default ADV7393_1XMEM + +config ADV7393_1XMEM + bool 'Single' + +config ADV7393_2XMEM + bool 'Double' +endchoice + +config FB_STI + tristate "HP STI frame buffer device support" + depends on FB && PARISC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select STI_CONSOLE + select VT + default y + ---help--- + STI refers to the HP "Standard Text Interface" which is a set of + BIOS routines contained in a ROM chip in HP PA-RISC based machines. + Enabling this option will implement the linux framebuffer device + using calls to the STI BIOS routines for initialisation. + + If you enable this option, you will get a planar framebuffer device + /dev/fb which will work on the most common HP graphic cards of the + NGLE family, including the artist chips (in the 7xx and Bxxx series), + HCRX, HCRX24, CRX, CRX24 and VisEG series. + + It is safe to enable this option, so you should probably say "Y". + +config FB_MAC + bool "Generic Macintosh display support" + depends on (FB = y) && MAC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES + +config FB_HP300 + bool + depends on (FB = y) && DIO + select FB_CFB_IMAGEBLIT + default y + +config FB_TGA + tristate "TGA/SFB+ framebuffer support" + depends on FB && (ALPHA || TC) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select BITREVERSE + ---help--- + This is the frame buffer device driver for generic TGA and SFB+ + graphic cards. These include DEC ZLXp-E1, -E2 and -E3 PCI cards, + also known as PBXGA-A, -B and -C, and DEC ZLX-E1, -E2 and -E3 + TURBOchannel cards, also known as PMAGD-A, -B and -C. + + Due to hardware limitations ZLX-E2 and E3 cards are not supported + for DECstation 5000/200 systems. Additionally due to firmware + limitations these cards may cause troubles with booting DECstation + 5000/240 and /260 systems, but are fully supported under Linux if + you manage to get it going. ;-) + + Say Y if you have one of those. + +config FB_UVESA + tristate "Userspace VESA VGA graphics support" + depends on FB && CONNECTOR + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + help + This is the frame buffer driver for generic VBE 2.0 compliant + graphic cards. It can also take advantage of VBE 3.0 features, + such as refresh rate adjustment. + + This driver generally provides more features than vesafb but + requires a userspace helper application called 'v86d'. See + for more information. + + If unsure, say N. + +config FB_VESA + bool "VESA VGA graphics support" + depends on (FB = y) && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_BOOT_VESA_SUPPORT + help + This is the frame buffer device driver for generic VESA 2.0 + compliant graphic cards. The older VESA 1.2 cards are not supported. + You will get a boot time penguin logo at no additional cost. Please + read . If unsure, say Y. + +config FB_EFI + bool "EFI-based Framebuffer Support" + depends on (FB = y) && X86 && EFI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the EFI frame buffer device driver. If the firmware on + your platform is EFI 1.10 or UEFI 2.0, select Y to add support for + using the EFI framebuffer as your console. + +config FB_N411 + tristate "N411 Apollo/Hecuba devkit support" + depends on FB && X86 && MMU + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + select FB_HECUBA + help + This enables support for the Apollo display controller in its + Hecuba form using the n411 devkit. + +config FB_HGA + tristate "Hercules mono graphics support" + depends on FB && X86 + help + Say Y here if you have a Hercules mono graphics card. + + To compile this driver as a module, choose M here: the + module will be called hgafb. + + As this card technology is at least 25 years old, + most people will answer N here. + +config FB_GBE + bool "SGI Graphics Backend frame buffer support" + depends on (FB = y) && SGI_IP32 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for SGI Graphics Backend. + This chip is used in SGI O2 and Visual Workstation 320/540. + +config FB_GBE_MEM + int "Video memory size in MB" + depends on FB_GBE + default 4 + help + This is the amount of memory reserved for the framebuffer, + which can be any value between 1MB and 8MB. + +config FB_SBUS + bool "SBUS and UPA framebuffers" + depends on (FB = y) && SPARC + help + Say Y if you want support for SBUS or UPA based frame buffer device. + +config FB_BW2 + bool "BWtwo support" + depends on (FB = y) && (SPARC && FB_SBUS) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the BWtwo frame buffer. + +config FB_CG3 + bool "CGthree support" + depends on (FB = y) && (SPARC && FB_SBUS) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the CGthree frame buffer. + +config FB_CG6 + bool "CGsix (GX,TurboGX) support" + depends on (FB = y) && (SPARC && FB_SBUS) + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the CGsix (GX, TurboGX) + frame buffer. + +config FB_FFB + bool "Creator/Creator3D/Elite3D support" + depends on FB_SBUS && SPARC64 + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Creator, Creator3D, + and Elite3D graphics boards. + +config FB_TCX + bool "TCX (SS4/SS5 only) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the TCX 24/8bit frame + buffer. + +config FB_CG14 + bool "CGfourteen (SX) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the CGfourteen frame + buffer on Desktop SPARCsystems with the SX graphics option. + +config FB_P9100 + bool "P9100 (Sparcbook 3 only) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the P9100 card + supported on Sparcbook 3 machines. + +config FB_LEO + bool "Leo (ZX) support" + depends on FB_SBUS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the SBUS-based Sun ZX + (leo) frame buffer cards. + +config FB_IGA + bool "IGA 168x display support" + depends on (FB = y) && SPARC32 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the INTERGRAPHICS 1680 and + successor frame buffer cards. + +config FB_XVR500 + bool "Sun XVR-500 3DLABS Wildcat support" + depends on (FB = y) && PCI && SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-500 and similar + graphics cards based upon the 3DLABS Wildcat chipset. The driver + only works on sparc64 systems where the system firmware has + mostly initialized the card already. It is treated as a + completely dumb framebuffer device. + +config FB_XVR2500 + bool "Sun XVR-2500 3DLABS Wildcat support" + depends on (FB = y) && PCI && SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-2500 and similar + graphics cards based upon the 3DLABS Wildcat chipset. The driver + only works on sparc64 systems where the system firmware has + mostly initialized the card already. It is treated as a + completely dumb framebuffer device. + +config FB_XVR1000 + bool "Sun XVR-1000 support" + depends on (FB = y) && SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-1000 and similar + graphics cards. The driver only works on sparc64 systems where + the system firmware has mostly initialized the card already. It + is treated as a completely dumb framebuffer device. + +config FB_PVR2 + tristate "NEC PowerVR 2 display support" + depends on FB && SH_DREAMCAST + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Say Y here if you have a PowerVR 2 card in your box. If you plan to + run linux on your Dreamcast, you will have to say Y here. + This driver may or may not work on other PowerVR 2 cards, but is + totally untested. Use at your own risk. If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called pvr2fb. + + You can pass several parameters to the driver at boot time or at + module load time. The parameters look like "video=pvr2:XXX", where + the meaning of XXX can be found at the end of the main source file + (). Please see the file + . + +config FB_OPENCORES + tristate "OpenCores VGA/LCD core 2.0 framebuffer support" + depends on FB && HAS_DMA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This enables support for the OpenCores VGA/LCD core. + + The OpenCores VGA/LCD core is typically used together with + softcore CPUs (e.g. OpenRISC or Microblaze) or hard processor + systems (e.g. Altera socfpga or Xilinx Zynq) on FPGAs. + + The source code and specification for the core is available at + + +config FB_S1D13XXX + tristate "Epson S1D13XXX framebuffer support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for S1D13XXX framebuffer device family (currently only + working with S1D13806). Product specs at + + +config FB_ATMEL + tristate "AT91/AT32 LCD Controller support" + depends on FB && HAVE_FB_ATMEL + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS + help + This enables support for the AT91/AT32 LCD Controller. + +config FB_INTSRAM + bool "Frame Buffer in internal SRAM" + depends on FB_ATMEL && ARCH_AT91SAM9261 + help + Say Y if you want to map Frame Buffer in internal SRAM. Say N if you want + to let frame buffer in external SDRAM. + +config FB_ATMEL_STN + bool "Use a STN display with AT91/AT32 LCD Controller" + depends on FB_ATMEL && (MACH_AT91SAM9261EK || MACH_AT91SAM9G10EK) + default n + help + Say Y if you want to connect a STN LCD display to the AT91/AT32 LCD + Controller. Say N if you want to connect a TFT. + + If unsure, say N. + +config FB_NVIDIA + tristate "nVidia Framebuffer Support" + depends on FB && PCI + select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select BITREVERSE + select VGASTATE + help + This driver supports graphics boards with the nVidia chips, TNT + and newer. For very old chipsets, such as the RIVA128, then use + the rivafb. + Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called nvidiafb. + +config FB_NVIDIA_I2C + bool "Enable DDC Support" + depends on FB_NVIDIA + select FB_DDC + help + This enables I2C support for nVidia Chipsets. This is used + only for getting EDID information from the attached display + allowing for robust video mode handling and switching. + + Because fbdev-2.6 requires that drivers must be able to + independently validate video mode parameters, you should say Y + here. + +config FB_NVIDIA_DEBUG + bool "Lots of debug output" + depends on FB_NVIDIA + default n + help + Say Y here if you want the nVidia driver to output all sorts + of debugging information to provide to the maintainer when + something goes wrong. + +config FB_NVIDIA_BACKLIGHT + bool "Support for backlight control" + depends on FB_NVIDIA + default y + help + Say Y here if you want to control the backlight of your display. + +config FB_RIVA + tristate "nVidia Riva support" + depends on FB && PCI + select FB_BACKLIGHT if FB_RIVA_BACKLIGHT + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select BITREVERSE + select VGASTATE + help + This driver supports graphics boards with the nVidia Riva/Geforce + chips. + Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called rivafb. + +config FB_RIVA_I2C + bool "Enable DDC Support" + depends on FB_RIVA + select FB_DDC + help + This enables I2C support for nVidia Chipsets. This is used + only for getting EDID information from the attached display + allowing for robust video mode handling and switching. + + Because fbdev-2.6 requires that drivers must be able to + independently validate video mode parameters, you should say Y + here. + +config FB_RIVA_DEBUG + bool "Lots of debug output" + depends on FB_RIVA + default n + help + Say Y here if you want the Riva driver to output all sorts + of debugging information to provide to the maintainer when + something goes wrong. + +config FB_RIVA_BACKLIGHT + bool "Support for backlight control" + depends on FB_RIVA + default y + help + Say Y here if you want to control the backlight of your display. + +config FB_I740 + tristate "Intel740 support" + depends on FB && PCI + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select VGASTATE + select FB_DDC + help + This driver supports graphics cards based on Intel740 chip. + +config FB_I810 + tristate "Intel 810/815 support" + depends on FB && PCI && X86_32 && AGP_INTEL + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select VGASTATE + help + This driver supports the on-board graphics built in to the Intel 810 + and 815 chipsets. Say Y if you have and plan to use such a board. + + To compile this driver as a module, choose M here: the + module will be called i810fb. + + For more information, please read + + +config FB_I810_GTF + bool "use VESA Generalized Timing Formula" + depends on FB_I810 + help + If you say Y, then the VESA standard, Generalized Timing Formula + or GTF, will be used to calculate the required video timing values + per video mode. Since the GTF allows nondiscrete timings + (nondiscrete being a range of values as opposed to discrete being a + set of values), you'll be able to use any combination of horizontal + and vertical resolutions, and vertical refresh rates without having + to specify your own timing parameters. This is especially useful + to maximize the performance of an aging display, or if you just + have a display with nonstandard dimensions. A VESA compliant + monitor is recommended, but can still work with non-compliant ones. + If you need or want this, then select this option. The timings may + not be compliant with Intel's recommended values. Use at your own + risk. + + If you say N, the driver will revert to discrete video timings + using a set recommended by Intel in their documentation. + + If unsure, say N. + +config FB_I810_I2C + bool "Enable DDC Support" + depends on FB_I810 && FB_I810_GTF + select FB_DDC + help + +config FB_LE80578 + tristate "Intel LE80578 (Vermilion) support" + depends on FB && PCI && X86 + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This driver supports the LE80578 (Vermilion Range) chipset + +config FB_CARILLO_RANCH + tristate "Intel Carillo Ranch support" + depends on FB_LE80578 && FB && PCI && X86 + help + This driver supports the LE80578 (Carillo Ranch) board + +config FB_INTEL + tristate "Intel 830M/845G/852GM/855GM/865G/915G/945G/945GM/965G/965GM support" + depends on FB && PCI && X86 && AGP_INTEL && EXPERT + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_BOOT_VESA_SUPPORT if FB_INTEL = y + depends on !DRM_I915 + help + This driver supports the on-board graphics built in to the Intel + 830M/845G/852GM/855GM/865G/915G/915GM/945G/945GM/965G/965GM chipsets. + Say Y if you have and plan to use such a board. + + To make FB_INTELFB=Y work you need to say AGP_INTEL=y too. + + To compile this driver as a module, choose M here: the + module will be called intelfb. + + For more information, please read + +config FB_INTEL_DEBUG + bool "Intel driver Debug Messages" + depends on FB_INTEL + ---help--- + Say Y here if you want the Intel driver to output all sorts + of debugging information to provide to the maintainer when + something goes wrong. + +config FB_INTEL_I2C + bool "DDC/I2C for Intel framebuffer support" + depends on FB_INTEL + select FB_DDC + default y + help + Say Y here if you want DDC/I2C support for your on-board Intel graphics. + +config FB_MATROX + tristate "Matrox acceleration" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_TILEBLITTING + select FB_MACMODES if PPC_PMAC + ---help--- + Say Y here if you have a Matrox Millennium, Matrox Millennium II, + Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox + Mystique G200, Matrox Millennium G200, Matrox Marvel G200 video, + Matrox G400, G450 or G550 card in your box. + + To compile this driver as a module, choose M here: the + module will be called matroxfb. + + You can pass several parameters to the driver at boot time or at + module load time. The parameters look like "video=matroxfb:XXX", and + are described in . + +config FB_MATROX_MILLENIUM + bool "Millennium I/II support" + depends on FB_MATROX + help + Say Y here if you have a Matrox Millennium or Matrox Millennium II + video card. If you select "Advanced lowlevel driver options" below, + you should check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp + packed pixel, 24 bpp packed pixel and 32 bpp packed pixel. You can + also use font widths different from 8. + +config FB_MATROX_MYSTIQUE + bool "Mystique support" + depends on FB_MATROX + help + Say Y here if you have a Matrox Mystique or Matrox Mystique 220 + video card. If you select "Advanced lowlevel driver options" below, + you should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp + packed pixel and 32 bpp packed pixel. You can also use font widths + different from 8. + +config FB_MATROX_G + bool "G100/G200/G400/G450/G550 support" + depends on FB_MATROX + ---help--- + Say Y here if you have a Matrox G100, G200, G400, G450 or G550 based + video card. If you select "Advanced lowlevel driver options", you + should check 8 bpp packed pixel, 16 bpp packed pixel, 24 bpp packed + pixel and 32 bpp packed pixel. You can also use font widths + different from 8. + + If you need support for G400 secondary head, you must say Y to + "Matrox I2C support" and "G400 second head support" right below. + G450/G550 secondary head and digital output are supported without + additional modules. + + The driver starts in monitor mode. You must use the matroxset tool + (available at ) to + swap primary and secondary head outputs, or to change output mode. + Secondary head driver always start in 640x480 resolution and you + must use fbset to change it. + + Do not forget that second head supports only 16 and 32 bpp + packed pixels, so it is a good idea to compile them into the kernel + too. You can use only some font widths, as the driver uses generic + painting procedures (the secondary head does not use acceleration + engine). + + G450/G550 hardware can display TV picture only from secondary CRTC, + and it performs no scaling, so picture must have 525 or 625 lines. + +config FB_MATROX_I2C + tristate "Matrox I2C support" + depends on FB_MATROX + select FB_DDC + ---help--- + This drivers creates I2C buses which are needed for accessing the + DDC (I2C) bus present on all Matroxes, an I2C bus which + interconnects Matrox optional devices, like MGA-TVO on G200 and + G400, and the secondary head DDC bus, present on G400 only. + + You can say Y or M here if you want to experiment with monitor + detection code. You must say Y or M here if you want to use either + second head of G400 or MGA-TVO on G200 or G400. + + If you compile it as module, it will create a module named + i2c-matroxfb. + +config FB_MATROX_MAVEN + tristate "G400 second head support" + depends on FB_MATROX_G && FB_MATROX_I2C + ---help--- + WARNING !!! This support does not work with G450 !!! + + Say Y or M here if you want to use a secondary head (meaning two + monitors in parallel) on G400 or MGA-TVO add-on on G200. Secondary + head is not compatible with accelerated XFree 3.3.x SVGA servers - + secondary head output is blanked while you are in X. With XFree + 3.9.17 preview you can use both heads if you use SVGA over fbdev or + the fbdev driver on first head and the fbdev driver on second head. + + If you compile it as module, two modules are created, + matroxfb_crtc2 and matroxfb_maven. Matroxfb_maven is needed for + both G200 and G400, matroxfb_crtc2 is needed only by G400. You must + also load i2c-matroxfb to get it to run. + + The driver starts in monitor mode and you must use the matroxset + tool (available at + ) to switch it to + PAL or NTSC or to swap primary and secondary head outputs. + Secondary head driver also always start in 640x480 resolution, you + must use fbset to change it. + + Also do not forget that second head supports only 16 and 32 bpp + packed pixels, so it is a good idea to compile them into the kernel + too. You can use only some font widths, as the driver uses generic + painting procedures (the secondary head does not use acceleration + engine). + +config FB_RADEON + tristate "ATI Radeon display support" + depends on FB && PCI + select FB_BACKLIGHT if FB_RADEON_BACKLIGHT + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MACMODES if PPC_OF + help + Choose this option if you want to use an ATI Radeon graphics card as + a framebuffer device. There are both PCI and AGP versions. You + don't need to choose this to run the Radeon in plain VGA mode. + + There is a product page at + http://products.amd.com/en-us/GraphicCardResult.aspx + +config FB_RADEON_I2C + bool "DDC/I2C for ATI Radeon support" + depends on FB_RADEON + select FB_DDC + default y + help + Say Y here if you want DDC/I2C support for your Radeon board. + +config FB_RADEON_BACKLIGHT + bool "Support for backlight control" + depends on FB_RADEON + default y + help + Say Y here if you want to control the backlight of your display. + +config FB_RADEON_DEBUG + bool "Lots of debug output from Radeon driver" + depends on FB_RADEON + default n + help + Say Y here if you want the Radeon driver to output all sorts + of debugging information to provide to the maintainer when + something goes wrong. + +config FB_ATY128 + tristate "ATI Rage128 display support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_BACKLIGHT if FB_ATY128_BACKLIGHT + select FB_MACMODES if PPC_PMAC + help + This driver supports graphics boards with the ATI Rage128 chips. + Say Y if you have such a graphics board and read + . + + To compile this driver as a module, choose M here: the + module will be called aty128fb. + +config FB_ATY128_BACKLIGHT + bool "Support for backlight control" + depends on FB_ATY128 + default y + help + Say Y here if you want to control the backlight of your display. + +config FB_ATY + tristate "ATI Mach64 display support" if PCI || ATARI + depends on FB && !SPARC32 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_BACKLIGHT if FB_ATY_BACKLIGHT + select FB_MACMODES if PPC + help + This driver supports graphics boards with the ATI Mach64 chips. + Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called atyfb. + +config FB_ATY_CT + bool "Mach64 CT/VT/GT/LT (incl. 3D RAGE) support" + depends on PCI && FB_ATY + default y if SPARC64 && PCI + help + Say Y here to support use of ATI's 64-bit Rage boards (or other + boards based on the Mach64 CT, VT, GT, and LT chipsets) as a + framebuffer device. The ATI product support page for these boards + is at . + +config FB_ATY_GENERIC_LCD + bool "Mach64 generic LCD support" + depends on FB_ATY_CT + help + Say Y if you have a laptop with an ATI Rage LT PRO, Rage Mobility, + Rage XC, or Rage XL chipset. + +config FB_ATY_GX + bool "Mach64 GX support" if PCI + depends on FB_ATY + default y if ATARI + help + Say Y here to support use of the ATI Mach64 Graphics Expression + board (or other boards based on the Mach64 GX chipset) as a + framebuffer device. The ATI product support page for these boards + is at + . + +config FB_ATY_BACKLIGHT + bool "Support for backlight control" + depends on FB_ATY + default y + help + Say Y here if you want to control the backlight of your display. + +config FB_S3 + tristate "S3 Trio/Virge support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_TILEBLITTING + select FB_SVGALIB + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE + ---help--- + Driver for graphics boards with S3 Trio / S3 Virge chip. + +config FB_S3_DDC + bool "DDC for S3 support" + depends on FB_S3 + select FB_DDC + default y + help + Say Y here if you want DDC support for your S3 graphics card. + +config FB_SAVAGE + tristate "S3 Savage support" + depends on FB && PCI + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select VGASTATE + help + This driver supports notebooks and computers with S3 Savage PCI/AGP + chips. + + Say Y if you have such a graphics card. + + To compile this driver as a module, choose M here; the module + will be called savagefb. + +config FB_SAVAGE_I2C + bool "Enable DDC2 Support" + depends on FB_SAVAGE + select FB_DDC + help + This enables I2C support for S3 Savage Chipsets. This is used + only for getting EDID information from the attached display + allowing for robust video mode handling and switching. + + Because fbdev-2.6 requires that drivers must be able to + independently validate video mode parameters, you should say Y + here. + +config FB_SAVAGE_ACCEL + bool "Enable Console Acceleration" + depends on FB_SAVAGE + default n + help + This option will compile in console acceleration support. If + the resulting framebuffer console has bothersome glitches, then + choose N here. + +config FB_SIS + tristate "SiS/XGI display support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_BOOT_VESA_SUPPORT if FB_SIS = y + help + This is the frame buffer device driver for the SiS 300, 315, 330 + and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. + Specs available at and . + + To compile this driver as a module, choose M here; the module + will be called sisfb. + +config FB_SIS_300 + bool "SiS 300 series support" + depends on FB_SIS + help + Say Y here to support use of the SiS 300/305, 540, 630 and 730. + +config FB_SIS_315 + bool "SiS 315/330/340 series and XGI support" + depends on FB_SIS + help + Say Y here to support use of the SiS 315, 330 and 340 series + (315/H/PRO, 55x, 650, 651, 740, 330, 661, 741, 760, 761) as well + as XGI V3XT, V5, V8 and Z7. + +config FB_VIA + tristate "VIA UniChrome (Pro) and Chrome9 display support" + depends on FB && PCI && X86 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select I2C_ALGOBIT + select I2C + select GPIOLIB + help + This is the frame buffer device driver for Graphics chips of VIA + UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/ + CN700/VN800,CX700/VX700,P4M890) and Chrome9 Family (K8M890,CN896 + /P4M900,VX800) + Say Y if you have a VIA UniChrome graphics board. + + To compile this driver as a module, choose M here: the + module will be called viafb. + +if FB_VIA + +config FB_VIA_DIRECT_PROCFS + bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)" + depends on FB_VIA + default n + help + Allow direct hardware access to some output registers via procfs. + This is dangerous but may provide the only chance to get the + correct output device configuration. + Its use is strongly discouraged. + +config FB_VIA_X_COMPATIBILITY + bool "X server compatibility" + depends on FB_VIA + default n + help + This option reduces the functionality (power saving, ...) of the + framebuffer to avoid negative impact on the OpenChrome X server. + If you use any X server other than fbdev you should enable this + otherwise it should be safe to disable it and allow using all + features. + +endif + +config FB_NEOMAGIC + tristate "NeoMagic display support" + depends on FB && PCI + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select VGASTATE + help + This driver supports notebooks with NeoMagic PCI chips. + Say Y if you have such a graphics card. + + To compile this driver as a module, choose M here: the + module will be called neofb. + +config FB_KYRO + tristate "IMG Kyro support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y here if you have a STG4000 / Kyro / PowerVR 3 based + graphics board. + + To compile this driver as a module, choose M here: the + module will be called kyrofb. + +config FB_3DFX + tristate "3Dfx Banshee/Voodoo3/Voodoo5 display support" + depends on FB && PCI + select FB_CFB_IMAGEBLIT + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_MODE_HELPERS + help + This driver supports graphics boards with the 3Dfx Banshee, + Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have + such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called tdfxfb. + +config FB_3DFX_ACCEL + bool "3Dfx Acceleration functions" + depends on FB_3DFX + ---help--- + This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer + device driver with acceleration functions. + +config FB_3DFX_I2C + bool "Enable DDC/I2C support" + depends on FB_3DFX + select FB_DDC + default y + help + Say Y here if you want DDC/I2C support for your 3dfx Voodoo3. + +config FB_VOODOO1 + tristate "3Dfx Voodoo Graphics (sst1) support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or + Voodoo2 (cvg) based graphics card. + + To compile this driver as a module, choose M here: the + module will be called sstfb. + + WARNING: Do not use any application that uses the 3D engine + (namely glide) while using this driver. + Please read the for supported + options and other important info support. + +config FB_VT8623 + tristate "VIA VT8623 support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_TILEBLITTING + select FB_SVGALIB + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE + ---help--- + Driver for CastleRock integrated graphics core in the + VIA VT8623 [Apollo CLE266] chipset. + +config FB_TRIDENT + tristate "Trident/CyberXXX/CyberBlade support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + This is the frame buffer device driver for Trident PCI/AGP chipsets. + Supported chipset families are TGUI 9440/96XX, 3DImage, Blade3D + and Blade XP. + There are also integrated versions of these chips called CyberXXXX, + CyberImage or CyberBlade. These chips are mostly found in laptops + but also on some motherboards including early VIA EPIA motherboards. + For more information, read + + Say Y if you have such a graphics board. + + To compile this driver as a module, choose M here: the + module will be called tridentfb. + +config FB_ARK + tristate "ARK 2000PV support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_TILEBLITTING + select FB_SVGALIB + select VGASTATE + select FONT_8x16 if FRAMEBUFFER_CONSOLE + ---help--- + Driver for PCI graphics boards with ARK 2000PV chip + and ICS 5342 RAMDAC. + +config FB_PM3 + tristate "Permedia3 support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the 3DLabs Permedia3 + chipset, used in Formac ProFormance III, 3DLabs Oxygen VX1 & + similar boards, 3DLabs Permedia3 Create!, Appian Jeronimo 2000 + and maybe other boards. + +config FB_CARMINE + tristate "Fujitsu carmine frame buffer support" + depends on FB && PCI + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Fujitsu Carmine chip. + The driver provides two independent frame buffer devices. + +choice + depends on FB_CARMINE + prompt "DRAM timing" + default FB_CARMINE_DRAM_EVAL + +config FB_CARMINE_DRAM_EVAL + bool "Eval board timings" + help + Use timings which work on the eval card. + +config CARMINE_DRAM_CUSTOM + bool "Custom board timings" + help + Use custom board timings. +endchoice + +config FB_AU1100 + bool "Au1100 LCD Driver" + depends on (FB = y) && MIPS_ALCHEMY + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer driver for the AMD Au1100 SOC. It can drive + various panels and CRTs by passing in kernel cmd line option + au1100fb:panel=. + +config FB_AU1200 + bool "Au1200/Au1300 LCD Driver" + depends on (FB = y) && MIPS_ALCHEMY + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + help + This is the framebuffer driver for the Au1200/Au1300 SOCs. + It can drive various panels and CRTs by passing in kernel cmd line + option au1200fb:panel=. + +config FB_VT8500 + bool "VIA VT8500 framebuffer support" + depends on (FB = y) && ARM && ARCH_VT8500 + select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) + select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) + select FB_SYS_IMAGEBLIT + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS + help + This is the framebuffer driver for VIA VT8500 integrated LCD + controller. + +config FB_WM8505 + bool "Wondermedia WM8xxx-series frame buffer support" + depends on (FB = y) && ARM && ARCH_VT8500 + select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) + select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) + select FB_SYS_IMAGEBLIT + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS + help + This is the framebuffer driver for WonderMedia WM8xxx-series + integrated LCD controller. This driver covers the WM8505, WM8650 + and WM8850 SoCs. + +config FB_WMT_GE_ROPS + bool "VT8500/WM8xxx accelerated raster ops support" + depends on (FB = y) && (FB_VT8500 || FB_WM8505) + default n + help + This adds support for accelerated raster operations on the + VIA VT8500 and Wondermedia 85xx series SoCs. + +source "drivers/video/fbdev/geode/Kconfig" + +config FB_HIT + tristate "HD64461 Frame Buffer support" + depends on FB && HD64461 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the frame buffer device driver for the Hitachi HD64461 LCD + frame buffer card. + +config FB_PMAG_AA + bool "PMAG-AA TURBOchannel framebuffer support" + depends on (FB = y) && TC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) + used mainly in the MIPS-based DECstation series. + +config FB_PMAG_BA + tristate "PMAG-BA TURBOchannel framebuffer support" + depends on FB && TC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) + used mainly in the MIPS-based DECstation series. + +config FB_PMAGB_B + tristate "PMAGB-B TURBOchannel framebuffer support" + depends on FB && TC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the PMAGB-B TURBOchannel framebuffer card used mainly + in the MIPS-based DECstation series. The card is currently only + supported in 1280x1024x8 mode. + +config FB_MAXINE + bool "Maxine (Personal DECstation) onboard framebuffer support" + depends on (FB = y) && MACH_DECSTATION + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Support for the onboard framebuffer (1024x768x8) in the Personal + DECstation series (Personal DECstation 5000/20, /25, /33, /50, + Codename "Maxine"). + +config FB_G364 + bool "G364 frame buffer support" + depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + The G364 driver is the framebuffer used in MIPS Magnum 4000 and + Olivetti M700-10 systems. + +config FB_68328 + bool "Motorola 68328 native frame buffer support" + depends on (FB = y) && (M68328 || M68EZ328 || M68VZ328) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y here if you want to support the built-in frame buffer of + the Motorola 68328 CPU family. + +config FB_PXA168 + tristate "PXA168/910 LCD framebuffer support" + depends on FB && (CPU_PXA168 || CPU_PXA910) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Marvell + MMP processor. + +config FB_PXA + tristate "PXA LCD framebuffer support" + depends on FB && ARCH_PXA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Intel + PXA2x0 processor. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called pxafb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. + +config FB_PXA_OVERLAY + bool "Support PXA27x/PXA3xx Overlay(s) as framebuffer" + default n + depends on FB_PXA && (PXA27x || PXA3xx) + +config FB_PXA_SMARTPANEL + bool "PXA Smartpanel LCD support" + default n + depends on FB_PXA + +config FB_PXA_PARAMETERS + bool "PXA LCD command line parameters" + default n + depends on FB_PXA + ---help--- + Enable the use of kernel command line or module parameters + to configure the physical properties of the LCD panel when + using the PXA LCD driver. + + This option allows you to override the panel parameters + supplied by the platform in order to support multiple + different models of flatpanel. If you will only be using a + single model of flatpanel then you can safely leave this + option disabled. + + describes the available parameters. + +config PXA3XX_GCU + tristate "PXA3xx 2D graphics accelerator driver" + depends on FB_PXA + help + Kernelspace driver for the 2D graphics controller unit (GCU) + found on PXA3xx processors. There is a counterpart driver in the + DirectFB suite, see http://www.directfb.org/ + + If you compile this as a module, it will be called pxa3xx_gcu. + +config FB_MBX + tristate "2700G LCD framebuffer support" + depends on FB && ARCH_PXA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for the Intel 2700G (Marathon) Graphics + Accelerator + +config FB_MBX_DEBUG + bool "Enable debugging info via debugfs" + depends on FB_MBX && DEBUG_FS + default n + ---help--- + Enable this if you want debugging information using the debug + filesystem (debugfs) + + If unsure, say N. + +config FB_FSL_DIU + tristate "Freescale DIU framebuffer support" + depends on FB && FSL_SOC + select FB_MODE_HELPERS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select PPC_LIB_RHEAP + ---help--- + Framebuffer driver for the Freescale SoC DIU + +config FB_W100 + tristate "W100 frame buffer support" + depends on FB && ARCH_PXA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. + It can also drive the w3220 chip found on iPAQ hx4700. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called w100fb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. + +config FB_SH_MOBILE_LCDC + tristate "SuperH Mobile LCDC framebuffer support" + depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + select FB_BACKLIGHT + select SH_MIPI_DSI if SH_LCD_MIPI_DSI + ---help--- + Frame buffer driver for the on-chip SH-Mobile LCD controller. + +config FB_SH_MOBILE_HDMI + tristate "SuperH Mobile HDMI controller support" + depends on FB_SH_MOBILE_LCDC + select FB_MODE_HELPERS + select SOUND + select SND + select SND_SOC + ---help--- + Driver for the on-chip SH-Mobile HDMI controller. + +config FB_TMIO + tristate "Toshiba Mobile IO FrameBuffer support" + depends on FB && MFD_CORE + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the Toshiba Mobile IO integrated as found + on the Sharp SL-6000 series + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called tmiofb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. + +config FB_TMIO_ACCELL + bool "tmiofb acceleration" + depends on FB_TMIO + default y + +config FB_S3C + tristate "Samsung S3C framebuffer support" + depends on FB && (CPU_S3C2416 || ARCH_S3C64XX || ARCH_S5P64X0 || \ + ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in FB controller in the Samsung + SoC line from the S3C2443 onwards, including the S3C2416, S3C2450, + and the S3C64XX series such as the S3C6400 and S3C6410. + + These chips all have the same basic framebuffer design with the + actual capabilities depending on the chip. For instance the S3C6400 + and S3C6410 support 4 hardware windows whereas the S3C24XX series + currently only have two. + + Currently the support is only for the S3C6400 and S3C6410 SoCs. + +config FB_S3C_DEBUG_REGWRITE + bool "Debug register writes" + depends on FB_S3C + ---help--- + Show all register writes via pr_debug() + +config FB_S3C2410 + tristate "S3C2410 LCD framebuffer support" + depends on FB && ARCH_S3C24XX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Samsung + S3C2410 processor. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called s3c2410fb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. +config FB_S3C2410_DEBUG + bool "S3C2410 lcd debug messages" + depends on FB_S3C2410 + help + Turn on debugging messages. Note that you can set/unset at run time + through sysfs + +config FB_NUC900 + bool "NUC900 LCD framebuffer support" + depends on FB && ARCH_W90X900 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the built-in LCD controller in the Nuvoton + NUC900 processor + +config GPM1040A0_320X240 + bool "Giantplus Technology GPM1040A0 320x240 Color TFT LCD" + depends on FB_NUC900 + +config FB_SM501 + tristate "Silicon Motion SM501 framebuffer support" + depends on FB && MFD_SM501 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for the CRT and LCD controllers in the Silicon + Motion SM501. + + This driver is also available as a module ( = code which can be + inserted and removed from the running kernel whenever you want). The + module will be called sm501fb. If you want to compile it as a module, + say M here and read . + + If unsure, say N. + +config FB_SMSCUFX + tristate "SMSC UFX6000/7000 USB Framebuffer support" + depends on FB && USB + select FB_MODE_HELPERS + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + ---help--- + This is a kernel framebuffer driver for SMSC UFX USB devices. + Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and + mplayer -vo fbdev. Supports both UFX6000 (USB 2.0) and UFX7000 + (USB 3.0) devices. + To compile as a module, choose M here: the module name is smscufx. + +config FB_UDL + tristate "Displaylink USB Framebuffer support" + depends on FB && USB + select FB_MODE_HELPERS + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + ---help--- + This is a kernel framebuffer driver for DisplayLink USB devices. + Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and + mplayer -vo fbdev. Supports all USB 2.0 era DisplayLink devices. + To compile as a module, choose M here: the module name is udlfb. + +config FB_IBM_GXT4500 + tristate "Framebuffer support for IBM GXT4000P/4500P/6000P/6500P adaptors" + depends on FB && PPC + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Say Y here to enable support for the IBM GXT4000P/6000P and + GXT4500P/6500P display adaptor based on Raster Engine RC1000, + found on some IBM System P (pSeries) machines. This driver + doesn't use Geometry Engine GT1000. + +config FB_PS3 + tristate "PS3 GPU framebuffer driver" + depends on FB && PS3_PS3AV + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select VT_HW_CONSOLE_BINDING if FRAMEBUFFER_CONSOLE + ---help--- + Include support for the virtual frame buffer in the PS3 platform. + +config FB_PS3_DEFAULT_SIZE_M + int "PS3 default frame buffer size (in MiB)" + depends on FB_PS3 + default 9 + ---help--- + This is the default size (in MiB) of the virtual frame buffer in + the PS3. + The default value can be overridden on the kernel command line + using the "ps3fb" option (e.g. "ps3fb=9M"); + +config FB_XILINX + tristate "Xilinx frame buffer support" + depends on FB && (XILINX_VIRTEX || MICROBLAZE || ARCH_ZYNQ) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Include support for the Xilinx ML300/ML403 reference design + framebuffer. ML300 carries a 640*480 LCD display on the board, + ML403 uses a standard DB15 VGA connector. + +config FB_GOLDFISH + tristate "Goldfish Framebuffer" + depends on FB && HAS_DMA + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for Goldfish Virtual Platform + +config FB_COBALT + tristate "Cobalt server LCD frame buffer support" + depends on FB && (MIPS_COBALT || MIPS_SEAD3) + +config FB_SH7760 + bool "SH7760/SH7763/SH7720/SH7721 LCDC support" + depends on FB && (CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7763 \ + || CPU_SUBTYPE_SH7720 || CPU_SUBTYPE_SH7721) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Support for the SH7760/SH7763/SH7720/SH7721 integrated + (D)STN/TFT LCD Controller. + Supports display resolutions up to 1024x1024 pixel, grayscale and + color operation, with depths ranging from 1 bpp to 8 bpp monochrome + and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for + panels <= 320 pixel horizontal resolution. + +config FB_DA8XX + tristate "DA8xx/OMAP-L1xx/AM335x Framebuffer support" + depends on FB && (ARCH_DAVINCI_DA8XX || SOC_AM33XX) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_CFB_REV_PIXELS_IN_BYTE + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS + ---help--- + This is the frame buffer device driver for the TI LCD controller + found on DA8xx/OMAP-L1xx/AM335x SoCs. + If unsure, say N. + +config FB_VIRTUAL + tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" + depends on FB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + ---help--- + This is a `virtual' frame buffer device. It operates on a chunk of + unswappable kernel memory instead of on the memory of a graphics + board. This means you cannot see any output sent to this frame + buffer device, while it does consume precious memory. The main use + of this frame buffer device is testing and debugging the frame + buffer subsystem. Do NOT enable it for normal systems! To protect + the innocent, it has to be enabled explicitly at boot time using the + kernel option `video=vfb:'. + + To compile this driver as a module, choose M here: the + module will be called vfb. In order to load it, you must use + the vfb_enable=1 option. + + If unsure, say N. + +config XEN_FBDEV_FRONTEND + tristate "Xen virtual frame buffer support" + depends on FB && XEN + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + select INPUT_XEN_KBDDEV_FRONTEND if INPUT_MISC + select XEN_XENBUS_FRONTEND + default y + help + This driver implements the front-end of the Xen virtual + frame buffer driver. It communicates with a back-end + in another domain. + +config FB_METRONOME + tristate "E-Ink Metronome/8track controller support" + depends on FB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + help + This driver implements support for the E-Ink Metronome + controller. The pre-release name for this device was 8track + and could also have been called by some vendors as PVI-nnnn. + +config FB_MB862XX + tristate "Fujitsu MB862xx GDC support" + depends on FB + depends on PCI || (OF && PPC) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Frame buffer driver for Fujitsu Carmine/Coral-P(A)/Lime controllers. + +choice + prompt "GDC variant" + depends on FB_MB862XX + +config FB_MB862XX_PCI_GDC + bool "Carmine/Coral-P(A) GDC" + depends on PCI + ---help--- + This enables framebuffer support for Fujitsu Carmine/Coral-P(A) + PCI graphics controller devices. + +config FB_MB862XX_LIME + bool "Lime GDC" + depends on OF && PPC + select FB_FOREIGN_ENDIAN + select FB_LITTLE_ENDIAN + ---help--- + Framebuffer support for Fujitsu Lime GDC on host CPU bus. + +endchoice + +config FB_MB862XX_I2C + bool "Support I2C bus on MB862XX GDC" + depends on FB_MB862XX && I2C + default y + help + Selecting this option adds Coral-P(A)/Lime GDC I2C bus adapter + driver to support accessing I2C devices on controller's I2C bus. + These are usually some video decoder chips. + +config FB_EP93XX + tristate "EP93XX frame buffer support" + depends on FB && ARCH_EP93XX + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for the Cirrus Logic EP93XX series of processors. + This driver is also available as a module. The module will be called + ep93xx-fb. + +config FB_PRE_INIT_FB + bool "Don't reinitialize, use bootloader's GDC/Display configuration" + depends on FB && FB_MB862XX_LIME + ---help--- + Select this option if display contents should be inherited as set by + the bootloader. + +config FB_MSM + tristate "MSM Framebuffer support" + depends on FB && ARCH_MSM + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + +config FB_MX3 + tristate "MX3 Framebuffer support" + depends on FB && MX3_IPU + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + default y + help + This is a framebuffer device for the i.MX31 LCD Controller. So + far only synchronous displays are supported. If you plan to use + an LCD display with your i.MX31 system, say Y here. + +config FB_BROADSHEET + tristate "E-Ink Broadsheet/Epson S1D13521 controller support" + depends on FB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + help + This driver implements support for the E-Ink Broadsheet + controller. The release name for this device was Epson S1D13521 + and could also have been called by other names when coupled with + a bridge adapter. + +config FB_AUO_K190X + tristate "AUO-K190X EPD controller support" + depends on FB + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + select FB_DEFERRED_IO + help + Provides support for epaper controllers from the K190X series + of AUO. These controllers can be used to drive epaper displays + from Sipix. + + This option enables the common support, shared by the individual + controller drivers. You will also have to enable the driver + for the controller type used in your device. + +config FB_AUO_K1900 + tristate "AUO-K1900 EPD controller support" + depends on FB && FB_AUO_K190X + help + This driver implements support for the AUO K1900 epd-controller. + This controller can drive Sipix epaper displays but can only do + serial updates, reducing the number of possible frames per second. + +config FB_AUO_K1901 + tristate "AUO-K1901 EPD controller support" + depends on FB && FB_AUO_K190X + help + This driver implements support for the AUO K1901 epd-controller. + This controller can drive Sipix epaper displays and supports + concurrent updates, making higher frames per second possible. + +config FB_JZ4740 + tristate "JZ4740 LCD framebuffer support" + depends on FB && MACH_JZ4740 + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + help + Framebuffer support for the JZ4740 SoC. + +config FB_MXS + tristate "MXS LCD framebuffer support" + depends on FB && ARCH_MXS + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + select FB_MODE_HELPERS + select VIDEOMODE_HELPERS + help + Framebuffer support for the MXS SoC. + +config FB_PUV3_UNIGFX + tristate "PKUnity v3 Unigfx framebuffer support" + depends on FB && UNICORE32 && ARCH_PUV3 + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_SYS_FOPS + help + Choose this option if you want to use the Unigfx device as a + framebuffer device. Without the support of PCI & AGP. + +config FB_HYPERV + tristate "Microsoft Hyper-V Synthetic Video support" + depends on FB && HYPERV + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This framebuffer driver supports Microsoft Hyper-V Synthetic Video. + +config FB_SIMPLE + bool "Simple framebuffer support" + depends on (FB = y) + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Say Y if you want support for a simple frame-buffer. + + This driver assumes that the display hardware has been initialized + before the kernel boots, and the kernel will simply render to the + pre-allocated frame buffer surface. + + Configuration re: surface address, size, and format must be provided + through device tree, or plain old platform data. + +source "drivers/video/fbdev/omap/Kconfig" +source "drivers/video/fbdev/omap2/Kconfig" +source "drivers/video/fbdev/exynos/Kconfig" +source "drivers/video/fbdev/mmp/Kconfig" + +config FB_SH_MOBILE_MERAM + tristate "SuperH Mobile MERAM read ahead support" + depends on (SUPERH || ARCH_SHMOBILE) + select GENERIC_ALLOCATOR + ---help--- + Enable MERAM support for the SuperH controller. + + This will allow for caching of the framebuffer to provide more + reliable access under heavy main memory bus traffic situations. + Up to 4 memory channels can be configured, allowing 4 RGB or + 2 YCbCr framebuffers to be configured. + +config FB_SSD1307 + tristate "Solomon SSD1307 framebuffer support" + depends on FB && I2C + depends on OF + depends on GPIOLIB + select FB_SYS_FOPS + select FB_SYS_FILLRECT + select FB_SYS_COPYAREA + select FB_SYS_IMAGEBLIT + select FB_DEFERRED_IO + select PWM + help + This driver implements support for the Solomon SSD1307 + OLED controller over I2C. diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile new file mode 100644 index 00000000000000..8a79eec2113bd6 --- /dev/null +++ b/drivers/video/fbdev/Makefile @@ -0,0 +1,166 @@ +# Makefile for the Linux video drivers. +# 5 Aug 1999, James Simmons, +# Rewritten to use lists instead of if-statements. + +# Each configuration option enables a list of files. + +obj-y += fb_notify.o +obj-$(CONFIG_FB) += fb.o +fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ + modedb.o fbcvt.o +fb-objs := $(fb-y) + +obj-$(CONFIG_EXYNOS_VIDEO) += exynos/ + +obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o +obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o +obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o +obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o +obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o +obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o +obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o +obj-$(CONFIG_FB_SVGALIB) += svgalib.o +obj-$(CONFIG_FB_MACMODES) += macmodes.o +obj-$(CONFIG_FB_DDC) += fb_ddc.o +obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o +obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o + +# Hardware specific drivers go first +obj-$(CONFIG_FB_AMIGA) += amifb.o c2p_planar.o +obj-$(CONFIG_FB_ARC) += arcfb.o +obj-$(CONFIG_FB_CLPS711X) += clps711xfb.o +obj-$(CONFIG_FB_CYBER2000) += cyber2000fb.o +obj-$(CONFIG_FB_GRVGA) += grvga.o +obj-$(CONFIG_FB_PM2) += pm2fb.o +obj-$(CONFIG_FB_PM3) += pm3fb.o + +obj-$(CONFIG_FB_I740) += i740fb.o +obj-$(CONFIG_FB_MATROX) += matrox/ +obj-$(CONFIG_FB_RIVA) += riva/ +obj-$(CONFIG_FB_NVIDIA) += nvidia/ +obj-$(CONFIG_FB_ATY) += aty/ macmodes.o +obj-$(CONFIG_FB_ATY128) += aty/ macmodes.o +obj-$(CONFIG_FB_RADEON) += aty/ +obj-$(CONFIG_FB_SIS) += sis/ +obj-$(CONFIG_FB_VIA) += via/ +obj-$(CONFIG_FB_KYRO) += kyro/ +obj-$(CONFIG_FB_SAVAGE) += savage/ +obj-$(CONFIG_FB_GEODE) += geode/ +obj-$(CONFIG_FB_MBX) += mbx/ +obj-$(CONFIG_FB_NEOMAGIC) += neofb.o +obj-$(CONFIG_FB_3DFX) += tdfxfb.o +obj-$(CONFIG_FB_CONTROL) += controlfb.o +obj-$(CONFIG_FB_PLATINUM) += platinumfb.o +obj-$(CONFIG_FB_VALKYRIE) += valkyriefb.o +obj-$(CONFIG_FB_CT65550) += chipsfb.o +obj-$(CONFIG_FB_IMSTT) += imsttfb.o +obj-$(CONFIG_FB_FM2) += fm2fb.o +obj-$(CONFIG_FB_VT8623) += vt8623fb.o +obj-$(CONFIG_FB_TRIDENT) += tridentfb.o +obj-$(CONFIG_FB_LE80578) += vermilion/ +obj-$(CONFIG_FB_S3) += s3fb.o +obj-$(CONFIG_FB_ARK) += arkfb.o +obj-$(CONFIG_FB_STI) += stifb.o +obj-$(CONFIG_FB_FFB) += ffb.o sbuslib.o +obj-$(CONFIG_FB_CG6) += cg6.o sbuslib.o +obj-$(CONFIG_FB_CG3) += cg3.o sbuslib.o +obj-$(CONFIG_FB_BW2) += bw2.o sbuslib.o +obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o +obj-$(CONFIG_FB_P9100) += p9100.o sbuslib.o +obj-$(CONFIG_FB_TCX) += tcx.o sbuslib.o +obj-$(CONFIG_FB_LEO) += leo.o sbuslib.o +obj-$(CONFIG_FB_ACORN) += acornfb.o +obj-$(CONFIG_FB_ATARI) += atafb.o c2p_iplan2.o atafb_mfb.o \ + atafb_iplan2p2.o atafb_iplan2p4.o atafb_iplan2p8.o +obj-$(CONFIG_FB_MAC) += macfb.o +obj-$(CONFIG_FB_HECUBA) += hecubafb.o +obj-$(CONFIG_FB_N411) += n411.o +obj-$(CONFIG_FB_HGA) += hgafb.o +obj-$(CONFIG_FB_XVR500) += sunxvr500.o +obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o +obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o +obj-$(CONFIG_FB_IGA) += igafb.o +obj-$(CONFIG_FB_APOLLO) += dnfb.o +obj-$(CONFIG_FB_Q40) += q40fb.o +obj-$(CONFIG_FB_TGA) += tgafb.o +obj-$(CONFIG_FB_HP300) += hpfb.o +obj-$(CONFIG_FB_G364) += g364fb.o +obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o +obj-$(CONFIG_FB_SA1100) += sa1100fb.o +obj-$(CONFIG_FB_HIT) += hitfb.o +obj-$(CONFIG_FB_ATMEL) += atmel_lcdfb.o +obj-$(CONFIG_FB_PVR2) += pvr2fb.o +obj-$(CONFIG_FB_VOODOO1) += sstfb.o +obj-$(CONFIG_FB_ARMCLCD) += amba-clcd.o +obj-$(CONFIG_FB_GOLDFISH) += goldfishfb.o +obj-$(CONFIG_FB_68328) += 68328fb.o +obj-$(CONFIG_FB_GBE) += gbefb.o +obj-$(CONFIG_FB_CIRRUS) += cirrusfb.o +obj-$(CONFIG_FB_ASILIANT) += asiliantfb.o +obj-$(CONFIG_FB_PXA) += pxafb.o +obj-$(CONFIG_FB_PXA168) += pxa168fb.o +obj-$(CONFIG_PXA3XX_GCU) += pxa3xx-gcu.o +obj-$(CONFIG_MMP_DISP) += mmp/ +obj-$(CONFIG_FB_W100) += w100fb.o +obj-$(CONFIG_FB_TMIO) += tmiofb.o +obj-$(CONFIG_FB_AU1100) += au1100fb.o +obj-$(CONFIG_FB_AU1200) += au1200fb.o +obj-$(CONFIG_FB_VT8500) += vt8500lcdfb.o +obj-$(CONFIG_FB_WM8505) += wm8505fb.o +obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o +obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o +obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o +obj-$(CONFIG_FB_MAXINE) += maxinefb.o +obj-$(CONFIG_FB_METRONOME) += metronomefb.o +obj-$(CONFIG_FB_BROADSHEET) += broadsheetfb.o +obj-$(CONFIG_FB_AUO_K190X) += auo_k190x.o +obj-$(CONFIG_FB_AUO_K1900) += auo_k1900fb.o +obj-$(CONFIG_FB_AUO_K1901) += auo_k1901fb.o +obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o +obj-$(CONFIG_FB_SH7760) += sh7760fb.o +obj-$(CONFIG_FB_IMX) += imxfb.o +obj-$(CONFIG_FB_S3C) += s3c-fb.o +obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o +obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o +obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o +obj-$(CONFIG_FB_IBM_GXT4500) += gxt4500.o +obj-$(CONFIG_FB_PS3) += ps3fb.o +obj-$(CONFIG_FB_SM501) += sm501fb.o +obj-$(CONFIG_FB_UDL) += udlfb.o +obj-$(CONFIG_FB_SMSCUFX) += smscufx.o +obj-$(CONFIG_FB_XILINX) += xilinxfb.o +obj-$(CONFIG_SH_MIPI_DSI) += sh_mipi_dsi.o +obj-$(CONFIG_FB_SH_MOBILE_HDMI) += sh_mobile_hdmi.o +obj-$(CONFIG_FB_SH_MOBILE_MERAM) += sh_mobile_meram.o +obj-$(CONFIG_FB_SH_MOBILE_LCDC) += sh_mobile_lcdcfb.o +obj-$(CONFIG_FB_OMAP) += omap/ +obj-y += omap2/ +obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o +obj-$(CONFIG_FB_CARMINE) += carminefb.o +obj-$(CONFIG_FB_MB862XX) += mb862xx/ +obj-$(CONFIG_FB_MSM) += msm/ +obj-$(CONFIG_FB_NUC900) += nuc900fb.o +obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o +obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o +obj-$(CONFIG_FB_HYPERV) += hyperv_fb.o +obj-$(CONFIG_FB_OPENCORES) += ocfb.o + +# Platform or fallback drivers go here +obj-$(CONFIG_FB_UVESA) += uvesafb.o +obj-$(CONFIG_FB_VESA) += vesafb.o +obj-$(CONFIG_FB_EFI) += efifb.o +obj-$(CONFIG_FB_VGA16) += vga16fb.o +obj-$(CONFIG_FB_OF) += offb.o +obj-$(CONFIG_FB_BF537_LQ035) += bf537-lq035.o +obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o +obj-$(CONFIG_FB_BFIN_LQ035Q1) += bfin-lq035q1-fb.o +obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o +obj-$(CONFIG_FB_BFIN_7393) += bfin_adv7393fb.o +obj-$(CONFIG_FB_MX3) += mx3fb.o +obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o +obj-$(CONFIG_FB_MXS) += mxsfb.o +obj-$(CONFIG_FB_SSD1307) += ssd1307fb.o +obj-$(CONFIG_FB_SIMPLE) += simplefb.o + +# the test framebuffer is last +obj-$(CONFIG_FB_VIRTUAL) += vfb.o diff --git a/drivers/video/acornfb.c b/drivers/video/fbdev/acornfb.c similarity index 100% rename from drivers/video/acornfb.c rename to drivers/video/fbdev/acornfb.c diff --git a/drivers/video/acornfb.h b/drivers/video/fbdev/acornfb.h similarity index 100% rename from drivers/video/acornfb.h rename to drivers/video/fbdev/acornfb.h diff --git a/drivers/video/amba-clcd.c b/drivers/video/fbdev/amba-clcd.c similarity index 100% rename from drivers/video/amba-clcd.c rename to drivers/video/fbdev/amba-clcd.c diff --git a/drivers/video/amifb.c b/drivers/video/fbdev/amifb.c similarity index 100% rename from drivers/video/amifb.c rename to drivers/video/fbdev/amifb.c diff --git a/drivers/video/arcfb.c b/drivers/video/fbdev/arcfb.c similarity index 100% rename from drivers/video/arcfb.c rename to drivers/video/fbdev/arcfb.c diff --git a/drivers/video/arkfb.c b/drivers/video/fbdev/arkfb.c similarity index 100% rename from drivers/video/arkfb.c rename to drivers/video/fbdev/arkfb.c diff --git a/drivers/video/asiliantfb.c b/drivers/video/fbdev/asiliantfb.c similarity index 100% rename from drivers/video/asiliantfb.c rename to drivers/video/fbdev/asiliantfb.c diff --git a/drivers/video/atafb.c b/drivers/video/fbdev/atafb.c similarity index 100% rename from drivers/video/atafb.c rename to drivers/video/fbdev/atafb.c diff --git a/drivers/video/atafb.h b/drivers/video/fbdev/atafb.h similarity index 100% rename from drivers/video/atafb.h rename to drivers/video/fbdev/atafb.h diff --git a/drivers/video/atafb_iplan2p2.c b/drivers/video/fbdev/atafb_iplan2p2.c similarity index 100% rename from drivers/video/atafb_iplan2p2.c rename to drivers/video/fbdev/atafb_iplan2p2.c diff --git a/drivers/video/atafb_iplan2p4.c b/drivers/video/fbdev/atafb_iplan2p4.c similarity index 100% rename from drivers/video/atafb_iplan2p4.c rename to drivers/video/fbdev/atafb_iplan2p4.c diff --git a/drivers/video/atafb_iplan2p8.c b/drivers/video/fbdev/atafb_iplan2p8.c similarity index 100% rename from drivers/video/atafb_iplan2p8.c rename to drivers/video/fbdev/atafb_iplan2p8.c diff --git a/drivers/video/atafb_mfb.c b/drivers/video/fbdev/atafb_mfb.c similarity index 100% rename from drivers/video/atafb_mfb.c rename to drivers/video/fbdev/atafb_mfb.c diff --git a/drivers/video/atafb_utils.h b/drivers/video/fbdev/atafb_utils.h similarity index 100% rename from drivers/video/atafb_utils.h rename to drivers/video/fbdev/atafb_utils.h diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/fbdev/atmel_lcdfb.c similarity index 100% rename from drivers/video/atmel_lcdfb.c rename to drivers/video/fbdev/atmel_lcdfb.c diff --git a/drivers/video/aty/Makefile b/drivers/video/fbdev/aty/Makefile similarity index 100% rename from drivers/video/aty/Makefile rename to drivers/video/fbdev/aty/Makefile diff --git a/drivers/video/aty/ati_ids.h b/drivers/video/fbdev/aty/ati_ids.h similarity index 100% rename from drivers/video/aty/ati_ids.h rename to drivers/video/fbdev/aty/ati_ids.h diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/fbdev/aty/aty128fb.c similarity index 100% rename from drivers/video/aty/aty128fb.c rename to drivers/video/fbdev/aty/aty128fb.c diff --git a/drivers/video/aty/atyfb.h b/drivers/video/fbdev/aty/atyfb.h similarity index 100% rename from drivers/video/aty/atyfb.h rename to drivers/video/fbdev/aty/atyfb.h diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c similarity index 100% rename from drivers/video/aty/atyfb_base.c rename to drivers/video/fbdev/aty/atyfb_base.c diff --git a/drivers/video/aty/mach64_accel.c b/drivers/video/fbdev/aty/mach64_accel.c similarity index 100% rename from drivers/video/aty/mach64_accel.c rename to drivers/video/fbdev/aty/mach64_accel.c diff --git a/drivers/video/aty/mach64_ct.c b/drivers/video/fbdev/aty/mach64_ct.c similarity index 100% rename from drivers/video/aty/mach64_ct.c rename to drivers/video/fbdev/aty/mach64_ct.c diff --git a/drivers/video/aty/mach64_cursor.c b/drivers/video/fbdev/aty/mach64_cursor.c similarity index 100% rename from drivers/video/aty/mach64_cursor.c rename to drivers/video/fbdev/aty/mach64_cursor.c diff --git a/drivers/video/aty/mach64_gx.c b/drivers/video/fbdev/aty/mach64_gx.c similarity index 100% rename from drivers/video/aty/mach64_gx.c rename to drivers/video/fbdev/aty/mach64_gx.c diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/fbdev/aty/radeon_accel.c similarity index 100% rename from drivers/video/aty/radeon_accel.c rename to drivers/video/fbdev/aty/radeon_accel.c diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/fbdev/aty/radeon_backlight.c similarity index 100% rename from drivers/video/aty/radeon_backlight.c rename to drivers/video/fbdev/aty/radeon_backlight.c diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/fbdev/aty/radeon_base.c similarity index 100% rename from drivers/video/aty/radeon_base.c rename to drivers/video/fbdev/aty/radeon_base.c diff --git a/drivers/video/aty/radeon_i2c.c b/drivers/video/fbdev/aty/radeon_i2c.c similarity index 100% rename from drivers/video/aty/radeon_i2c.c rename to drivers/video/fbdev/aty/radeon_i2c.c diff --git a/drivers/video/aty/radeon_monitor.c b/drivers/video/fbdev/aty/radeon_monitor.c similarity index 100% rename from drivers/video/aty/radeon_monitor.c rename to drivers/video/fbdev/aty/radeon_monitor.c diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/fbdev/aty/radeon_pm.c similarity index 100% rename from drivers/video/aty/radeon_pm.c rename to drivers/video/fbdev/aty/radeon_pm.c diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/fbdev/aty/radeonfb.h similarity index 100% rename from drivers/video/aty/radeonfb.h rename to drivers/video/fbdev/aty/radeonfb.h diff --git a/drivers/video/au1100fb.c b/drivers/video/fbdev/au1100fb.c similarity index 100% rename from drivers/video/au1100fb.c rename to drivers/video/fbdev/au1100fb.c diff --git a/drivers/video/au1100fb.h b/drivers/video/fbdev/au1100fb.h similarity index 100% rename from drivers/video/au1100fb.h rename to drivers/video/fbdev/au1100fb.h diff --git a/drivers/video/au1200fb.c b/drivers/video/fbdev/au1200fb.c similarity index 100% rename from drivers/video/au1200fb.c rename to drivers/video/fbdev/au1200fb.c diff --git a/drivers/video/au1200fb.h b/drivers/video/fbdev/au1200fb.h similarity index 100% rename from drivers/video/au1200fb.h rename to drivers/video/fbdev/au1200fb.h diff --git a/drivers/video/auo_k1900fb.c b/drivers/video/fbdev/auo_k1900fb.c similarity index 100% rename from drivers/video/auo_k1900fb.c rename to drivers/video/fbdev/auo_k1900fb.c diff --git a/drivers/video/auo_k1901fb.c b/drivers/video/fbdev/auo_k1901fb.c similarity index 100% rename from drivers/video/auo_k1901fb.c rename to drivers/video/fbdev/auo_k1901fb.c diff --git a/drivers/video/auo_k190x.c b/drivers/video/fbdev/auo_k190x.c similarity index 100% rename from drivers/video/auo_k190x.c rename to drivers/video/fbdev/auo_k190x.c diff --git a/drivers/video/auo_k190x.h b/drivers/video/fbdev/auo_k190x.h similarity index 100% rename from drivers/video/auo_k190x.h rename to drivers/video/fbdev/auo_k190x.h diff --git a/drivers/video/bf537-lq035.c b/drivers/video/fbdev/bf537-lq035.c similarity index 100% rename from drivers/video/bf537-lq035.c rename to drivers/video/fbdev/bf537-lq035.c diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/fbdev/bf54x-lq043fb.c similarity index 100% rename from drivers/video/bf54x-lq043fb.c rename to drivers/video/fbdev/bf54x-lq043fb.c diff --git a/drivers/video/bfin-lq035q1-fb.c b/drivers/video/fbdev/bfin-lq035q1-fb.c similarity index 100% rename from drivers/video/bfin-lq035q1-fb.c rename to drivers/video/fbdev/bfin-lq035q1-fb.c diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/fbdev/bfin-t350mcqb-fb.c similarity index 100% rename from drivers/video/bfin-t350mcqb-fb.c rename to drivers/video/fbdev/bfin-t350mcqb-fb.c diff --git a/drivers/video/bfin_adv7393fb.c b/drivers/video/fbdev/bfin_adv7393fb.c similarity index 100% rename from drivers/video/bfin_adv7393fb.c rename to drivers/video/fbdev/bfin_adv7393fb.c diff --git a/drivers/video/bfin_adv7393fb.h b/drivers/video/fbdev/bfin_adv7393fb.h similarity index 100% rename from drivers/video/bfin_adv7393fb.h rename to drivers/video/fbdev/bfin_adv7393fb.h diff --git a/drivers/video/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c similarity index 100% rename from drivers/video/broadsheetfb.c rename to drivers/video/fbdev/broadsheetfb.c diff --git a/drivers/video/bt431.h b/drivers/video/fbdev/bt431.h similarity index 100% rename from drivers/video/bt431.h rename to drivers/video/fbdev/bt431.h diff --git a/drivers/video/bt455.h b/drivers/video/fbdev/bt455.h similarity index 100% rename from drivers/video/bt455.h rename to drivers/video/fbdev/bt455.h diff --git a/drivers/video/bw2.c b/drivers/video/fbdev/bw2.c similarity index 100% rename from drivers/video/bw2.c rename to drivers/video/fbdev/bw2.c diff --git a/drivers/video/c2p.h b/drivers/video/fbdev/c2p.h similarity index 100% rename from drivers/video/c2p.h rename to drivers/video/fbdev/c2p.h diff --git a/drivers/video/c2p_core.h b/drivers/video/fbdev/c2p_core.h similarity index 100% rename from drivers/video/c2p_core.h rename to drivers/video/fbdev/c2p_core.h diff --git a/drivers/video/c2p_iplan2.c b/drivers/video/fbdev/c2p_iplan2.c similarity index 100% rename from drivers/video/c2p_iplan2.c rename to drivers/video/fbdev/c2p_iplan2.c diff --git a/drivers/video/c2p_planar.c b/drivers/video/fbdev/c2p_planar.c similarity index 100% rename from drivers/video/c2p_planar.c rename to drivers/video/fbdev/c2p_planar.c diff --git a/drivers/video/carminefb.c b/drivers/video/fbdev/carminefb.c similarity index 100% rename from drivers/video/carminefb.c rename to drivers/video/fbdev/carminefb.c diff --git a/drivers/video/carminefb.h b/drivers/video/fbdev/carminefb.h similarity index 100% rename from drivers/video/carminefb.h rename to drivers/video/fbdev/carminefb.h diff --git a/drivers/video/carminefb_regs.h b/drivers/video/fbdev/carminefb_regs.h similarity index 100% rename from drivers/video/carminefb_regs.h rename to drivers/video/fbdev/carminefb_regs.h diff --git a/drivers/video/cfbcopyarea.c b/drivers/video/fbdev/cfbcopyarea.c similarity index 100% rename from drivers/video/cfbcopyarea.c rename to drivers/video/fbdev/cfbcopyarea.c diff --git a/drivers/video/cfbfillrect.c b/drivers/video/fbdev/cfbfillrect.c similarity index 100% rename from drivers/video/cfbfillrect.c rename to drivers/video/fbdev/cfbfillrect.c diff --git a/drivers/video/cfbimgblt.c b/drivers/video/fbdev/cfbimgblt.c similarity index 100% rename from drivers/video/cfbimgblt.c rename to drivers/video/fbdev/cfbimgblt.c diff --git a/drivers/video/cg14.c b/drivers/video/fbdev/cg14.c similarity index 100% rename from drivers/video/cg14.c rename to drivers/video/fbdev/cg14.c diff --git a/drivers/video/cg3.c b/drivers/video/fbdev/cg3.c similarity index 100% rename from drivers/video/cg3.c rename to drivers/video/fbdev/cg3.c diff --git a/drivers/video/cg6.c b/drivers/video/fbdev/cg6.c similarity index 100% rename from drivers/video/cg6.c rename to drivers/video/fbdev/cg6.c diff --git a/drivers/video/chipsfb.c b/drivers/video/fbdev/chipsfb.c similarity index 100% rename from drivers/video/chipsfb.c rename to drivers/video/fbdev/chipsfb.c diff --git a/drivers/video/cirrusfb.c b/drivers/video/fbdev/cirrusfb.c similarity index 100% rename from drivers/video/cirrusfb.c rename to drivers/video/fbdev/cirrusfb.c diff --git a/drivers/video/clps711xfb.c b/drivers/video/fbdev/clps711xfb.c similarity index 100% rename from drivers/video/clps711xfb.c rename to drivers/video/fbdev/clps711xfb.c diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/fbdev/cobalt_lcdfb.c similarity index 100% rename from drivers/video/cobalt_lcdfb.c rename to drivers/video/fbdev/cobalt_lcdfb.c diff --git a/drivers/video/controlfb.c b/drivers/video/fbdev/controlfb.c similarity index 100% rename from drivers/video/controlfb.c rename to drivers/video/fbdev/controlfb.c diff --git a/drivers/video/controlfb.h b/drivers/video/fbdev/controlfb.h similarity index 100% rename from drivers/video/controlfb.h rename to drivers/video/fbdev/controlfb.h diff --git a/drivers/video/cyber2000fb.c b/drivers/video/fbdev/cyber2000fb.c similarity index 100% rename from drivers/video/cyber2000fb.c rename to drivers/video/fbdev/cyber2000fb.c diff --git a/drivers/video/cyber2000fb.h b/drivers/video/fbdev/cyber2000fb.h similarity index 100% rename from drivers/video/cyber2000fb.h rename to drivers/video/fbdev/cyber2000fb.h diff --git a/drivers/video/da8xx-fb.c b/drivers/video/fbdev/da8xx-fb.c similarity index 100% rename from drivers/video/da8xx-fb.c rename to drivers/video/fbdev/da8xx-fb.c diff --git a/drivers/video/dnfb.c b/drivers/video/fbdev/dnfb.c similarity index 100% rename from drivers/video/dnfb.c rename to drivers/video/fbdev/dnfb.c diff --git a/drivers/video/edid.h b/drivers/video/fbdev/edid.h similarity index 100% rename from drivers/video/edid.h rename to drivers/video/fbdev/edid.h diff --git a/drivers/video/efifb.c b/drivers/video/fbdev/efifb.c similarity index 100% rename from drivers/video/efifb.c rename to drivers/video/fbdev/efifb.c diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/fbdev/ep93xx-fb.c similarity index 100% rename from drivers/video/ep93xx-fb.c rename to drivers/video/fbdev/ep93xx-fb.c diff --git a/drivers/video/exynos/Kconfig b/drivers/video/fbdev/exynos/Kconfig similarity index 100% rename from drivers/video/exynos/Kconfig rename to drivers/video/fbdev/exynos/Kconfig diff --git a/drivers/video/exynos/Makefile b/drivers/video/fbdev/exynos/Makefile similarity index 100% rename from drivers/video/exynos/Makefile rename to drivers/video/fbdev/exynos/Makefile diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi.c similarity index 100% rename from drivers/video/exynos/exynos_mipi_dsi.c rename to drivers/video/fbdev/exynos/exynos_mipi_dsi.c diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c similarity index 100% rename from drivers/video/exynos/exynos_mipi_dsi_common.c rename to drivers/video/fbdev/exynos/exynos_mipi_dsi_common.c diff --git a/drivers/video/exynos/exynos_mipi_dsi_common.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h similarity index 100% rename from drivers/video/exynos/exynos_mipi_dsi_common.h rename to drivers/video/fbdev/exynos/exynos_mipi_dsi_common.h diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.c b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c similarity index 100% rename from drivers/video/exynos/exynos_mipi_dsi_lowlevel.c rename to drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.c diff --git a/drivers/video/exynos/exynos_mipi_dsi_lowlevel.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h similarity index 100% rename from drivers/video/exynos/exynos_mipi_dsi_lowlevel.h rename to drivers/video/fbdev/exynos/exynos_mipi_dsi_lowlevel.h diff --git a/drivers/video/exynos/exynos_mipi_dsi_regs.h b/drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h similarity index 100% rename from drivers/video/exynos/exynos_mipi_dsi_regs.h rename to drivers/video/fbdev/exynos/exynos_mipi_dsi_regs.h diff --git a/drivers/video/exynos/s6e8ax0.c b/drivers/video/fbdev/exynos/s6e8ax0.c similarity index 100% rename from drivers/video/exynos/s6e8ax0.c rename to drivers/video/fbdev/exynos/s6e8ax0.c diff --git a/drivers/video/fb-puv3.c b/drivers/video/fbdev/fb-puv3.c similarity index 100% rename from drivers/video/fb-puv3.c rename to drivers/video/fbdev/fb-puv3.c diff --git a/drivers/video/fb_ddc.c b/drivers/video/fbdev/fb_ddc.c similarity index 100% rename from drivers/video/fb_ddc.c rename to drivers/video/fbdev/fb_ddc.c diff --git a/drivers/video/fb_defio.c b/drivers/video/fbdev/fb_defio.c similarity index 100% rename from drivers/video/fb_defio.c rename to drivers/video/fbdev/fb_defio.c diff --git a/drivers/video/fb_draw.h b/drivers/video/fbdev/fb_draw.h similarity index 100% rename from drivers/video/fb_draw.h rename to drivers/video/fbdev/fb_draw.h diff --git a/drivers/video/fb_notify.c b/drivers/video/fbdev/fb_notify.c similarity index 100% rename from drivers/video/fb_notify.c rename to drivers/video/fbdev/fb_notify.c diff --git a/drivers/video/fb_sys_fops.c b/drivers/video/fbdev/fb_sys_fops.c similarity index 100% rename from drivers/video/fb_sys_fops.c rename to drivers/video/fbdev/fb_sys_fops.c diff --git a/drivers/video/fbcmap.c b/drivers/video/fbdev/fbcmap.c similarity index 100% rename from drivers/video/fbcmap.c rename to drivers/video/fbdev/fbcmap.c diff --git a/drivers/video/fbcvt.c b/drivers/video/fbdev/fbcvt.c similarity index 100% rename from drivers/video/fbcvt.c rename to drivers/video/fbdev/fbcvt.c diff --git a/drivers/video/fbmem.c b/drivers/video/fbdev/fbmem.c similarity index 100% rename from drivers/video/fbmem.c rename to drivers/video/fbdev/fbmem.c diff --git a/drivers/video/fbmon.c b/drivers/video/fbdev/fbmon.c similarity index 100% rename from drivers/video/fbmon.c rename to drivers/video/fbdev/fbmon.c diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbdev/fbsysfs.c similarity index 100% rename from drivers/video/fbsysfs.c rename to drivers/video/fbdev/fbsysfs.c diff --git a/drivers/video/ffb.c b/drivers/video/fbdev/ffb.c similarity index 100% rename from drivers/video/ffb.c rename to drivers/video/fbdev/ffb.c diff --git a/drivers/video/fm2fb.c b/drivers/video/fbdev/fm2fb.c similarity index 100% rename from drivers/video/fm2fb.c rename to drivers/video/fbdev/fm2fb.c diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c similarity index 100% rename from drivers/video/fsl-diu-fb.c rename to drivers/video/fbdev/fsl-diu-fb.c diff --git a/drivers/video/g364fb.c b/drivers/video/fbdev/g364fb.c similarity index 100% rename from drivers/video/g364fb.c rename to drivers/video/fbdev/g364fb.c diff --git a/drivers/video/gbefb.c b/drivers/video/fbdev/gbefb.c similarity index 100% rename from drivers/video/gbefb.c rename to drivers/video/fbdev/gbefb.c diff --git a/drivers/video/geode/Kconfig b/drivers/video/fbdev/geode/Kconfig similarity index 100% rename from drivers/video/geode/Kconfig rename to drivers/video/fbdev/geode/Kconfig diff --git a/drivers/video/geode/Makefile b/drivers/video/fbdev/geode/Makefile similarity index 100% rename from drivers/video/geode/Makefile rename to drivers/video/fbdev/geode/Makefile diff --git a/drivers/video/geode/display_gx.c b/drivers/video/fbdev/geode/display_gx.c similarity index 100% rename from drivers/video/geode/display_gx.c rename to drivers/video/fbdev/geode/display_gx.c diff --git a/drivers/video/geode/display_gx1.c b/drivers/video/fbdev/geode/display_gx1.c similarity index 100% rename from drivers/video/geode/display_gx1.c rename to drivers/video/fbdev/geode/display_gx1.c diff --git a/drivers/video/geode/display_gx1.h b/drivers/video/fbdev/geode/display_gx1.h similarity index 100% rename from drivers/video/geode/display_gx1.h rename to drivers/video/fbdev/geode/display_gx1.h diff --git a/drivers/video/geode/geodefb.h b/drivers/video/fbdev/geode/geodefb.h similarity index 100% rename from drivers/video/geode/geodefb.h rename to drivers/video/fbdev/geode/geodefb.h diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/fbdev/geode/gx1fb_core.c similarity index 100% rename from drivers/video/geode/gx1fb_core.c rename to drivers/video/fbdev/geode/gx1fb_core.c diff --git a/drivers/video/geode/gxfb.h b/drivers/video/fbdev/geode/gxfb.h similarity index 100% rename from drivers/video/geode/gxfb.h rename to drivers/video/fbdev/geode/gxfb.h diff --git a/drivers/video/geode/gxfb_core.c b/drivers/video/fbdev/geode/gxfb_core.c similarity index 100% rename from drivers/video/geode/gxfb_core.c rename to drivers/video/fbdev/geode/gxfb_core.c diff --git a/drivers/video/geode/lxfb.h b/drivers/video/fbdev/geode/lxfb.h similarity index 100% rename from drivers/video/geode/lxfb.h rename to drivers/video/fbdev/geode/lxfb.h diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/fbdev/geode/lxfb_core.c similarity index 100% rename from drivers/video/geode/lxfb_core.c rename to drivers/video/fbdev/geode/lxfb_core.c diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/fbdev/geode/lxfb_ops.c similarity index 100% rename from drivers/video/geode/lxfb_ops.c rename to drivers/video/fbdev/geode/lxfb_ops.c diff --git a/drivers/video/geode/suspend_gx.c b/drivers/video/fbdev/geode/suspend_gx.c similarity index 100% rename from drivers/video/geode/suspend_gx.c rename to drivers/video/fbdev/geode/suspend_gx.c diff --git a/drivers/video/geode/video_cs5530.c b/drivers/video/fbdev/geode/video_cs5530.c similarity index 100% rename from drivers/video/geode/video_cs5530.c rename to drivers/video/fbdev/geode/video_cs5530.c diff --git a/drivers/video/geode/video_cs5530.h b/drivers/video/fbdev/geode/video_cs5530.h similarity index 100% rename from drivers/video/geode/video_cs5530.h rename to drivers/video/fbdev/geode/video_cs5530.h diff --git a/drivers/video/geode/video_gx.c b/drivers/video/fbdev/geode/video_gx.c similarity index 100% rename from drivers/video/geode/video_gx.c rename to drivers/video/fbdev/geode/video_gx.c diff --git a/drivers/video/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c similarity index 100% rename from drivers/video/goldfishfb.c rename to drivers/video/fbdev/goldfishfb.c diff --git a/drivers/video/grvga.c b/drivers/video/fbdev/grvga.c similarity index 100% rename from drivers/video/grvga.c rename to drivers/video/fbdev/grvga.c diff --git a/drivers/video/gxt4500.c b/drivers/video/fbdev/gxt4500.c similarity index 100% rename from drivers/video/gxt4500.c rename to drivers/video/fbdev/gxt4500.c diff --git a/drivers/video/hecubafb.c b/drivers/video/fbdev/hecubafb.c similarity index 100% rename from drivers/video/hecubafb.c rename to drivers/video/fbdev/hecubafb.c diff --git a/drivers/video/hgafb.c b/drivers/video/fbdev/hgafb.c similarity index 100% rename from drivers/video/hgafb.c rename to drivers/video/fbdev/hgafb.c diff --git a/drivers/video/hitfb.c b/drivers/video/fbdev/hitfb.c similarity index 100% rename from drivers/video/hitfb.c rename to drivers/video/fbdev/hitfb.c diff --git a/drivers/video/hpfb.c b/drivers/video/fbdev/hpfb.c similarity index 100% rename from drivers/video/hpfb.c rename to drivers/video/fbdev/hpfb.c diff --git a/drivers/video/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c similarity index 100% rename from drivers/video/hyperv_fb.c rename to drivers/video/fbdev/hyperv_fb.c diff --git a/drivers/video/i740_reg.h b/drivers/video/fbdev/i740_reg.h similarity index 100% rename from drivers/video/i740_reg.h rename to drivers/video/fbdev/i740_reg.h diff --git a/drivers/video/i740fb.c b/drivers/video/fbdev/i740fb.c similarity index 100% rename from drivers/video/i740fb.c rename to drivers/video/fbdev/i740fb.c diff --git a/drivers/video/i810/Makefile b/drivers/video/fbdev/i810/Makefile similarity index 100% rename from drivers/video/i810/Makefile rename to drivers/video/fbdev/i810/Makefile diff --git a/drivers/video/i810/i810-i2c.c b/drivers/video/fbdev/i810/i810-i2c.c similarity index 100% rename from drivers/video/i810/i810-i2c.c rename to drivers/video/fbdev/i810/i810-i2c.c diff --git a/drivers/video/i810/i810.h b/drivers/video/fbdev/i810/i810.h similarity index 100% rename from drivers/video/i810/i810.h rename to drivers/video/fbdev/i810/i810.h diff --git a/drivers/video/i810/i810_accel.c b/drivers/video/fbdev/i810/i810_accel.c similarity index 100% rename from drivers/video/i810/i810_accel.c rename to drivers/video/fbdev/i810/i810_accel.c diff --git a/drivers/video/i810/i810_dvt.c b/drivers/video/fbdev/i810/i810_dvt.c similarity index 100% rename from drivers/video/i810/i810_dvt.c rename to drivers/video/fbdev/i810/i810_dvt.c diff --git a/drivers/video/i810/i810_gtf.c b/drivers/video/fbdev/i810/i810_gtf.c similarity index 100% rename from drivers/video/i810/i810_gtf.c rename to drivers/video/fbdev/i810/i810_gtf.c diff --git a/drivers/video/i810/i810_main.c b/drivers/video/fbdev/i810/i810_main.c similarity index 100% rename from drivers/video/i810/i810_main.c rename to drivers/video/fbdev/i810/i810_main.c diff --git a/drivers/video/i810/i810_main.h b/drivers/video/fbdev/i810/i810_main.h similarity index 100% rename from drivers/video/i810/i810_main.h rename to drivers/video/fbdev/i810/i810_main.h diff --git a/drivers/video/i810/i810_regs.h b/drivers/video/fbdev/i810/i810_regs.h similarity index 100% rename from drivers/video/i810/i810_regs.h rename to drivers/video/fbdev/i810/i810_regs.h diff --git a/drivers/video/igafb.c b/drivers/video/fbdev/igafb.c similarity index 100% rename from drivers/video/igafb.c rename to drivers/video/fbdev/igafb.c diff --git a/drivers/video/imsttfb.c b/drivers/video/fbdev/imsttfb.c similarity index 100% rename from drivers/video/imsttfb.c rename to drivers/video/fbdev/imsttfb.c diff --git a/drivers/video/imxfb.c b/drivers/video/fbdev/imxfb.c similarity index 100% rename from drivers/video/imxfb.c rename to drivers/video/fbdev/imxfb.c diff --git a/drivers/video/intelfb/Makefile b/drivers/video/fbdev/intelfb/Makefile similarity index 100% rename from drivers/video/intelfb/Makefile rename to drivers/video/fbdev/intelfb/Makefile diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/fbdev/intelfb/intelfb.h similarity index 100% rename from drivers/video/intelfb/intelfb.h rename to drivers/video/fbdev/intelfb/intelfb.h diff --git a/drivers/video/intelfb/intelfb_i2c.c b/drivers/video/fbdev/intelfb/intelfb_i2c.c similarity index 100% rename from drivers/video/intelfb/intelfb_i2c.c rename to drivers/video/fbdev/intelfb/intelfb_i2c.c diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/fbdev/intelfb/intelfbdrv.c similarity index 100% rename from drivers/video/intelfb/intelfbdrv.c rename to drivers/video/fbdev/intelfb/intelfbdrv.c diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/fbdev/intelfb/intelfbhw.c similarity index 100% rename from drivers/video/intelfb/intelfbhw.c rename to drivers/video/fbdev/intelfb/intelfbhw.c diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/fbdev/intelfb/intelfbhw.h similarity index 100% rename from drivers/video/intelfb/intelfbhw.h rename to drivers/video/fbdev/intelfb/intelfbhw.h diff --git a/drivers/video/jz4740_fb.c b/drivers/video/fbdev/jz4740_fb.c similarity index 100% rename from drivers/video/jz4740_fb.c rename to drivers/video/fbdev/jz4740_fb.c diff --git a/drivers/video/kyro/Makefile b/drivers/video/fbdev/kyro/Makefile similarity index 100% rename from drivers/video/kyro/Makefile rename to drivers/video/fbdev/kyro/Makefile diff --git a/drivers/video/kyro/STG4000InitDevice.c b/drivers/video/fbdev/kyro/STG4000InitDevice.c similarity index 100% rename from drivers/video/kyro/STG4000InitDevice.c rename to drivers/video/fbdev/kyro/STG4000InitDevice.c diff --git a/drivers/video/kyro/STG4000Interface.h b/drivers/video/fbdev/kyro/STG4000Interface.h similarity index 100% rename from drivers/video/kyro/STG4000Interface.h rename to drivers/video/fbdev/kyro/STG4000Interface.h diff --git a/drivers/video/kyro/STG4000OverlayDevice.c b/drivers/video/fbdev/kyro/STG4000OverlayDevice.c similarity index 100% rename from drivers/video/kyro/STG4000OverlayDevice.c rename to drivers/video/fbdev/kyro/STG4000OverlayDevice.c diff --git a/drivers/video/kyro/STG4000Ramdac.c b/drivers/video/fbdev/kyro/STG4000Ramdac.c similarity index 100% rename from drivers/video/kyro/STG4000Ramdac.c rename to drivers/video/fbdev/kyro/STG4000Ramdac.c diff --git a/drivers/video/kyro/STG4000Reg.h b/drivers/video/fbdev/kyro/STG4000Reg.h similarity index 100% rename from drivers/video/kyro/STG4000Reg.h rename to drivers/video/fbdev/kyro/STG4000Reg.h diff --git a/drivers/video/kyro/STG4000VTG.c b/drivers/video/fbdev/kyro/STG4000VTG.c similarity index 100% rename from drivers/video/kyro/STG4000VTG.c rename to drivers/video/fbdev/kyro/STG4000VTG.c diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/fbdev/kyro/fbdev.c similarity index 100% rename from drivers/video/kyro/fbdev.c rename to drivers/video/fbdev/kyro/fbdev.c diff --git a/drivers/video/leo.c b/drivers/video/fbdev/leo.c similarity index 100% rename from drivers/video/leo.c rename to drivers/video/fbdev/leo.c diff --git a/drivers/video/macfb.c b/drivers/video/fbdev/macfb.c similarity index 100% rename from drivers/video/macfb.c rename to drivers/video/fbdev/macfb.c diff --git a/drivers/video/macmodes.c b/drivers/video/fbdev/macmodes.c similarity index 100% rename from drivers/video/macmodes.c rename to drivers/video/fbdev/macmodes.c diff --git a/drivers/video/macmodes.h b/drivers/video/fbdev/macmodes.h similarity index 100% rename from drivers/video/macmodes.h rename to drivers/video/fbdev/macmodes.h diff --git a/drivers/video/matrox/Makefile b/drivers/video/fbdev/matrox/Makefile similarity index 100% rename from drivers/video/matrox/Makefile rename to drivers/video/fbdev/matrox/Makefile diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/fbdev/matrox/g450_pll.c similarity index 100% rename from drivers/video/matrox/g450_pll.c rename to drivers/video/fbdev/matrox/g450_pll.c diff --git a/drivers/video/matrox/g450_pll.h b/drivers/video/fbdev/matrox/g450_pll.h similarity index 100% rename from drivers/video/matrox/g450_pll.h rename to drivers/video/fbdev/matrox/g450_pll.h diff --git a/drivers/video/matrox/i2c-matroxfb.c b/drivers/video/fbdev/matrox/i2c-matroxfb.c similarity index 100% rename from drivers/video/matrox/i2c-matroxfb.c rename to drivers/video/fbdev/matrox/i2c-matroxfb.c diff --git a/drivers/video/matrox/matroxfb_DAC1064.c b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c similarity index 100% rename from drivers/video/matrox/matroxfb_DAC1064.c rename to drivers/video/fbdev/matrox/matroxfb_DAC1064.c diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/fbdev/matrox/matroxfb_DAC1064.h similarity index 100% rename from drivers/video/matrox/matroxfb_DAC1064.h rename to drivers/video/fbdev/matrox/matroxfb_DAC1064.h diff --git a/drivers/video/matrox/matroxfb_Ti3026.c b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c similarity index 100% rename from drivers/video/matrox/matroxfb_Ti3026.c rename to drivers/video/fbdev/matrox/matroxfb_Ti3026.c diff --git a/drivers/video/matrox/matroxfb_Ti3026.h b/drivers/video/fbdev/matrox/matroxfb_Ti3026.h similarity index 100% rename from drivers/video/matrox/matroxfb_Ti3026.h rename to drivers/video/fbdev/matrox/matroxfb_Ti3026.h diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/fbdev/matrox/matroxfb_accel.c similarity index 100% rename from drivers/video/matrox/matroxfb_accel.c rename to drivers/video/fbdev/matrox/matroxfb_accel.c diff --git a/drivers/video/matrox/matroxfb_accel.h b/drivers/video/fbdev/matrox/matroxfb_accel.h similarity index 100% rename from drivers/video/matrox/matroxfb_accel.h rename to drivers/video/fbdev/matrox/matroxfb_accel.h diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c similarity index 100% rename from drivers/video/matrox/matroxfb_base.c rename to drivers/video/fbdev/matrox/matroxfb_base.c diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/fbdev/matrox/matroxfb_base.h similarity index 100% rename from drivers/video/matrox/matroxfb_base.h rename to drivers/video/fbdev/matrox/matroxfb_base.h diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/fbdev/matrox/matroxfb_crtc2.c similarity index 100% rename from drivers/video/matrox/matroxfb_crtc2.c rename to drivers/video/fbdev/matrox/matroxfb_crtc2.c diff --git a/drivers/video/matrox/matroxfb_crtc2.h b/drivers/video/fbdev/matrox/matroxfb_crtc2.h similarity index 100% rename from drivers/video/matrox/matroxfb_crtc2.h rename to drivers/video/fbdev/matrox/matroxfb_crtc2.h diff --git a/drivers/video/matrox/matroxfb_g450.c b/drivers/video/fbdev/matrox/matroxfb_g450.c similarity index 100% rename from drivers/video/matrox/matroxfb_g450.c rename to drivers/video/fbdev/matrox/matroxfb_g450.c diff --git a/drivers/video/matrox/matroxfb_g450.h b/drivers/video/fbdev/matrox/matroxfb_g450.h similarity index 100% rename from drivers/video/matrox/matroxfb_g450.h rename to drivers/video/fbdev/matrox/matroxfb_g450.h diff --git a/drivers/video/matrox/matroxfb_maven.c b/drivers/video/fbdev/matrox/matroxfb_maven.c similarity index 100% rename from drivers/video/matrox/matroxfb_maven.c rename to drivers/video/fbdev/matrox/matroxfb_maven.c diff --git a/drivers/video/matrox/matroxfb_maven.h b/drivers/video/fbdev/matrox/matroxfb_maven.h similarity index 100% rename from drivers/video/matrox/matroxfb_maven.h rename to drivers/video/fbdev/matrox/matroxfb_maven.h diff --git a/drivers/video/matrox/matroxfb_misc.c b/drivers/video/fbdev/matrox/matroxfb_misc.c similarity index 100% rename from drivers/video/matrox/matroxfb_misc.c rename to drivers/video/fbdev/matrox/matroxfb_misc.c diff --git a/drivers/video/matrox/matroxfb_misc.h b/drivers/video/fbdev/matrox/matroxfb_misc.h similarity index 100% rename from drivers/video/matrox/matroxfb_misc.h rename to drivers/video/fbdev/matrox/matroxfb_misc.h diff --git a/drivers/video/maxinefb.c b/drivers/video/fbdev/maxinefb.c similarity index 100% rename from drivers/video/maxinefb.c rename to drivers/video/fbdev/maxinefb.c diff --git a/drivers/video/mb862xx/Makefile b/drivers/video/fbdev/mb862xx/Makefile similarity index 100% rename from drivers/video/mb862xx/Makefile rename to drivers/video/fbdev/mb862xx/Makefile diff --git a/drivers/video/mb862xx/mb862xx-i2c.c b/drivers/video/fbdev/mb862xx/mb862xx-i2c.c similarity index 100% rename from drivers/video/mb862xx/mb862xx-i2c.c rename to drivers/video/fbdev/mb862xx/mb862xx-i2c.c diff --git a/drivers/video/mb862xx/mb862xx_reg.h b/drivers/video/fbdev/mb862xx/mb862xx_reg.h similarity index 100% rename from drivers/video/mb862xx/mb862xx_reg.h rename to drivers/video/fbdev/mb862xx/mb862xx_reg.h diff --git a/drivers/video/mb862xx/mb862xxfb.h b/drivers/video/fbdev/mb862xx/mb862xxfb.h similarity index 100% rename from drivers/video/mb862xx/mb862xxfb.h rename to drivers/video/fbdev/mb862xx/mb862xxfb.h diff --git a/drivers/video/mb862xx/mb862xxfb_accel.c b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.c similarity index 100% rename from drivers/video/mb862xx/mb862xxfb_accel.c rename to drivers/video/fbdev/mb862xx/mb862xxfb_accel.c diff --git a/drivers/video/mb862xx/mb862xxfb_accel.h b/drivers/video/fbdev/mb862xx/mb862xxfb_accel.h similarity index 100% rename from drivers/video/mb862xx/mb862xxfb_accel.h rename to drivers/video/fbdev/mb862xx/mb862xxfb_accel.h diff --git a/drivers/video/mb862xx/mb862xxfbdrv.c b/drivers/video/fbdev/mb862xx/mb862xxfbdrv.c similarity index 100% rename from drivers/video/mb862xx/mb862xxfbdrv.c rename to drivers/video/fbdev/mb862xx/mb862xxfbdrv.c diff --git a/drivers/video/mbx/Makefile b/drivers/video/fbdev/mbx/Makefile similarity index 100% rename from drivers/video/mbx/Makefile rename to drivers/video/fbdev/mbx/Makefile diff --git a/drivers/video/mbx/mbxdebugfs.c b/drivers/video/fbdev/mbx/mbxdebugfs.c similarity index 100% rename from drivers/video/mbx/mbxdebugfs.c rename to drivers/video/fbdev/mbx/mbxdebugfs.c diff --git a/drivers/video/mbx/mbxfb.c b/drivers/video/fbdev/mbx/mbxfb.c similarity index 100% rename from drivers/video/mbx/mbxfb.c rename to drivers/video/fbdev/mbx/mbxfb.c diff --git a/drivers/video/mbx/reg_bits.h b/drivers/video/fbdev/mbx/reg_bits.h similarity index 100% rename from drivers/video/mbx/reg_bits.h rename to drivers/video/fbdev/mbx/reg_bits.h diff --git a/drivers/video/mbx/regs.h b/drivers/video/fbdev/mbx/regs.h similarity index 100% rename from drivers/video/mbx/regs.h rename to drivers/video/fbdev/mbx/regs.h diff --git a/drivers/video/metronomefb.c b/drivers/video/fbdev/metronomefb.c similarity index 100% rename from drivers/video/metronomefb.c rename to drivers/video/fbdev/metronomefb.c diff --git a/drivers/video/mmp/Kconfig b/drivers/video/fbdev/mmp/Kconfig similarity index 61% rename from drivers/video/mmp/Kconfig rename to drivers/video/fbdev/mmp/Kconfig index e9ea39e1372283..d4a4ffc24749e1 100644 --- a/drivers/video/mmp/Kconfig +++ b/drivers/video/fbdev/mmp/Kconfig @@ -5,7 +5,7 @@ menuconfig MMP_DISP Marvell Display Subsystem support. if MMP_DISP -source "drivers/video/mmp/hw/Kconfig" -source "drivers/video/mmp/panel/Kconfig" -source "drivers/video/mmp/fb/Kconfig" +source "drivers/video/fbdev/mmp/hw/Kconfig" +source "drivers/video/fbdev/mmp/panel/Kconfig" +source "drivers/video/fbdev/mmp/fb/Kconfig" endif diff --git a/drivers/video/mmp/Makefile b/drivers/video/fbdev/mmp/Makefile similarity index 100% rename from drivers/video/mmp/Makefile rename to drivers/video/fbdev/mmp/Makefile diff --git a/drivers/video/mmp/core.c b/drivers/video/fbdev/mmp/core.c similarity index 100% rename from drivers/video/mmp/core.c rename to drivers/video/fbdev/mmp/core.c diff --git a/drivers/video/mmp/fb/Kconfig b/drivers/video/fbdev/mmp/fb/Kconfig similarity index 100% rename from drivers/video/mmp/fb/Kconfig rename to drivers/video/fbdev/mmp/fb/Kconfig diff --git a/drivers/video/mmp/fb/Makefile b/drivers/video/fbdev/mmp/fb/Makefile similarity index 100% rename from drivers/video/mmp/fb/Makefile rename to drivers/video/fbdev/mmp/fb/Makefile diff --git a/drivers/video/mmp/fb/mmpfb.c b/drivers/video/fbdev/mmp/fb/mmpfb.c similarity index 100% rename from drivers/video/mmp/fb/mmpfb.c rename to drivers/video/fbdev/mmp/fb/mmpfb.c diff --git a/drivers/video/mmp/fb/mmpfb.h b/drivers/video/fbdev/mmp/fb/mmpfb.h similarity index 100% rename from drivers/video/mmp/fb/mmpfb.h rename to drivers/video/fbdev/mmp/fb/mmpfb.h diff --git a/drivers/video/mmp/hw/Kconfig b/drivers/video/fbdev/mmp/hw/Kconfig similarity index 100% rename from drivers/video/mmp/hw/Kconfig rename to drivers/video/fbdev/mmp/hw/Kconfig diff --git a/drivers/video/mmp/hw/Makefile b/drivers/video/fbdev/mmp/hw/Makefile similarity index 100% rename from drivers/video/mmp/hw/Makefile rename to drivers/video/fbdev/mmp/hw/Makefile diff --git a/drivers/video/mmp/hw/mmp_ctrl.c b/drivers/video/fbdev/mmp/hw/mmp_ctrl.c similarity index 100% rename from drivers/video/mmp/hw/mmp_ctrl.c rename to drivers/video/fbdev/mmp/hw/mmp_ctrl.c diff --git a/drivers/video/mmp/hw/mmp_ctrl.h b/drivers/video/fbdev/mmp/hw/mmp_ctrl.h similarity index 100% rename from drivers/video/mmp/hw/mmp_ctrl.h rename to drivers/video/fbdev/mmp/hw/mmp_ctrl.h diff --git a/drivers/video/mmp/hw/mmp_spi.c b/drivers/video/fbdev/mmp/hw/mmp_spi.c similarity index 100% rename from drivers/video/mmp/hw/mmp_spi.c rename to drivers/video/fbdev/mmp/hw/mmp_spi.c diff --git a/drivers/video/mmp/panel/Kconfig b/drivers/video/fbdev/mmp/panel/Kconfig similarity index 100% rename from drivers/video/mmp/panel/Kconfig rename to drivers/video/fbdev/mmp/panel/Kconfig diff --git a/drivers/video/mmp/panel/Makefile b/drivers/video/fbdev/mmp/panel/Makefile similarity index 100% rename from drivers/video/mmp/panel/Makefile rename to drivers/video/fbdev/mmp/panel/Makefile diff --git a/drivers/video/mmp/panel/tpo_tj032md01bw.c b/drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c similarity index 100% rename from drivers/video/mmp/panel/tpo_tj032md01bw.c rename to drivers/video/fbdev/mmp/panel/tpo_tj032md01bw.c diff --git a/drivers/video/modedb.c b/drivers/video/fbdev/modedb.c similarity index 100% rename from drivers/video/modedb.c rename to drivers/video/fbdev/modedb.c diff --git a/drivers/video/msm/Makefile b/drivers/video/fbdev/msm/Makefile similarity index 100% rename from drivers/video/msm/Makefile rename to drivers/video/fbdev/msm/Makefile diff --git a/drivers/video/msm/mddi.c b/drivers/video/fbdev/msm/mddi.c similarity index 100% rename from drivers/video/msm/mddi.c rename to drivers/video/fbdev/msm/mddi.c diff --git a/drivers/video/msm/mddi_client_dummy.c b/drivers/video/fbdev/msm/mddi_client_dummy.c similarity index 100% rename from drivers/video/msm/mddi_client_dummy.c rename to drivers/video/fbdev/msm/mddi_client_dummy.c diff --git a/drivers/video/msm/mddi_client_nt35399.c b/drivers/video/fbdev/msm/mddi_client_nt35399.c similarity index 100% rename from drivers/video/msm/mddi_client_nt35399.c rename to drivers/video/fbdev/msm/mddi_client_nt35399.c diff --git a/drivers/video/msm/mddi_client_toshiba.c b/drivers/video/fbdev/msm/mddi_client_toshiba.c similarity index 100% rename from drivers/video/msm/mddi_client_toshiba.c rename to drivers/video/fbdev/msm/mddi_client_toshiba.c diff --git a/drivers/video/msm/mddi_hw.h b/drivers/video/fbdev/msm/mddi_hw.h similarity index 100% rename from drivers/video/msm/mddi_hw.h rename to drivers/video/fbdev/msm/mddi_hw.h diff --git a/drivers/video/msm/mdp.c b/drivers/video/fbdev/msm/mdp.c similarity index 100% rename from drivers/video/msm/mdp.c rename to drivers/video/fbdev/msm/mdp.c diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/fbdev/msm/mdp_csc_table.h similarity index 100% rename from drivers/video/msm/mdp_csc_table.h rename to drivers/video/fbdev/msm/mdp_csc_table.h diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/fbdev/msm/mdp_hw.h similarity index 100% rename from drivers/video/msm/mdp_hw.h rename to drivers/video/fbdev/msm/mdp_hw.h diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/fbdev/msm/mdp_ppp.c similarity index 100% rename from drivers/video/msm/mdp_ppp.c rename to drivers/video/fbdev/msm/mdp_ppp.c diff --git a/drivers/video/msm/mdp_scale_tables.c b/drivers/video/fbdev/msm/mdp_scale_tables.c similarity index 100% rename from drivers/video/msm/mdp_scale_tables.c rename to drivers/video/fbdev/msm/mdp_scale_tables.c diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/fbdev/msm/mdp_scale_tables.h similarity index 100% rename from drivers/video/msm/mdp_scale_tables.h rename to drivers/video/fbdev/msm/mdp_scale_tables.h diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/fbdev/msm/msm_fb.c similarity index 100% rename from drivers/video/msm/msm_fb.c rename to drivers/video/fbdev/msm/msm_fb.c diff --git a/drivers/video/mx3fb.c b/drivers/video/fbdev/mx3fb.c similarity index 100% rename from drivers/video/mx3fb.c rename to drivers/video/fbdev/mx3fb.c diff --git a/drivers/video/mxsfb.c b/drivers/video/fbdev/mxsfb.c similarity index 100% rename from drivers/video/mxsfb.c rename to drivers/video/fbdev/mxsfb.c diff --git a/drivers/video/n411.c b/drivers/video/fbdev/n411.c similarity index 100% rename from drivers/video/n411.c rename to drivers/video/fbdev/n411.c diff --git a/drivers/video/neofb.c b/drivers/video/fbdev/neofb.c similarity index 100% rename from drivers/video/neofb.c rename to drivers/video/fbdev/neofb.c diff --git a/drivers/video/nuc900fb.c b/drivers/video/fbdev/nuc900fb.c similarity index 100% rename from drivers/video/nuc900fb.c rename to drivers/video/fbdev/nuc900fb.c diff --git a/drivers/video/nuc900fb.h b/drivers/video/fbdev/nuc900fb.h similarity index 100% rename from drivers/video/nuc900fb.h rename to drivers/video/fbdev/nuc900fb.h diff --git a/drivers/video/nvidia/Makefile b/drivers/video/fbdev/nvidia/Makefile similarity index 100% rename from drivers/video/nvidia/Makefile rename to drivers/video/fbdev/nvidia/Makefile diff --git a/drivers/video/nvidia/nv_accel.c b/drivers/video/fbdev/nvidia/nv_accel.c similarity index 100% rename from drivers/video/nvidia/nv_accel.c rename to drivers/video/fbdev/nvidia/nv_accel.c diff --git a/drivers/video/nvidia/nv_backlight.c b/drivers/video/fbdev/nvidia/nv_backlight.c similarity index 100% rename from drivers/video/nvidia/nv_backlight.c rename to drivers/video/fbdev/nvidia/nv_backlight.c diff --git a/drivers/video/nvidia/nv_dma.h b/drivers/video/fbdev/nvidia/nv_dma.h similarity index 100% rename from drivers/video/nvidia/nv_dma.h rename to drivers/video/fbdev/nvidia/nv_dma.h diff --git a/drivers/video/nvidia/nv_hw.c b/drivers/video/fbdev/nvidia/nv_hw.c similarity index 100% rename from drivers/video/nvidia/nv_hw.c rename to drivers/video/fbdev/nvidia/nv_hw.c diff --git a/drivers/video/nvidia/nv_i2c.c b/drivers/video/fbdev/nvidia/nv_i2c.c similarity index 100% rename from drivers/video/nvidia/nv_i2c.c rename to drivers/video/fbdev/nvidia/nv_i2c.c diff --git a/drivers/video/nvidia/nv_local.h b/drivers/video/fbdev/nvidia/nv_local.h similarity index 100% rename from drivers/video/nvidia/nv_local.h rename to drivers/video/fbdev/nvidia/nv_local.h diff --git a/drivers/video/nvidia/nv_of.c b/drivers/video/fbdev/nvidia/nv_of.c similarity index 100% rename from drivers/video/nvidia/nv_of.c rename to drivers/video/fbdev/nvidia/nv_of.c diff --git a/drivers/video/nvidia/nv_proto.h b/drivers/video/fbdev/nvidia/nv_proto.h similarity index 100% rename from drivers/video/nvidia/nv_proto.h rename to drivers/video/fbdev/nvidia/nv_proto.h diff --git a/drivers/video/nvidia/nv_setup.c b/drivers/video/fbdev/nvidia/nv_setup.c similarity index 100% rename from drivers/video/nvidia/nv_setup.c rename to drivers/video/fbdev/nvidia/nv_setup.c diff --git a/drivers/video/nvidia/nv_type.h b/drivers/video/fbdev/nvidia/nv_type.h similarity index 100% rename from drivers/video/nvidia/nv_type.h rename to drivers/video/fbdev/nvidia/nv_type.h diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/fbdev/nvidia/nvidia.c similarity index 100% rename from drivers/video/nvidia/nvidia.c rename to drivers/video/fbdev/nvidia/nvidia.c diff --git a/drivers/video/ocfb.c b/drivers/video/fbdev/ocfb.c similarity index 100% rename from drivers/video/ocfb.c rename to drivers/video/fbdev/ocfb.c diff --git a/drivers/video/offb.c b/drivers/video/fbdev/offb.c similarity index 100% rename from drivers/video/offb.c rename to drivers/video/fbdev/offb.c diff --git a/drivers/video/omap/Kconfig b/drivers/video/fbdev/omap/Kconfig similarity index 100% rename from drivers/video/omap/Kconfig rename to drivers/video/fbdev/omap/Kconfig diff --git a/drivers/video/omap/Makefile b/drivers/video/fbdev/omap/Makefile similarity index 100% rename from drivers/video/omap/Makefile rename to drivers/video/fbdev/omap/Makefile diff --git a/drivers/video/omap/hwa742.c b/drivers/video/fbdev/omap/hwa742.c similarity index 100% rename from drivers/video/omap/hwa742.c rename to drivers/video/fbdev/omap/hwa742.c diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/fbdev/omap/lcd_ams_delta.c similarity index 100% rename from drivers/video/omap/lcd_ams_delta.c rename to drivers/video/fbdev/omap/lcd_ams_delta.c diff --git a/drivers/video/omap/lcd_h3.c b/drivers/video/fbdev/omap/lcd_h3.c similarity index 100% rename from drivers/video/omap/lcd_h3.c rename to drivers/video/fbdev/omap/lcd_h3.c diff --git a/drivers/video/omap/lcd_htcherald.c b/drivers/video/fbdev/omap/lcd_htcherald.c similarity index 100% rename from drivers/video/omap/lcd_htcherald.c rename to drivers/video/fbdev/omap/lcd_htcherald.c diff --git a/drivers/video/omap/lcd_inn1510.c b/drivers/video/fbdev/omap/lcd_inn1510.c similarity index 100% rename from drivers/video/omap/lcd_inn1510.c rename to drivers/video/fbdev/omap/lcd_inn1510.c diff --git a/drivers/video/omap/lcd_inn1610.c b/drivers/video/fbdev/omap/lcd_inn1610.c similarity index 100% rename from drivers/video/omap/lcd_inn1610.c rename to drivers/video/fbdev/omap/lcd_inn1610.c diff --git a/drivers/video/omap/lcd_mipid.c b/drivers/video/fbdev/omap/lcd_mipid.c similarity index 100% rename from drivers/video/omap/lcd_mipid.c rename to drivers/video/fbdev/omap/lcd_mipid.c diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/fbdev/omap/lcd_osk.c similarity index 100% rename from drivers/video/omap/lcd_osk.c rename to drivers/video/fbdev/omap/lcd_osk.c diff --git a/drivers/video/omap/lcd_palmte.c b/drivers/video/fbdev/omap/lcd_palmte.c similarity index 100% rename from drivers/video/omap/lcd_palmte.c rename to drivers/video/fbdev/omap/lcd_palmte.c diff --git a/drivers/video/omap/lcd_palmtt.c b/drivers/video/fbdev/omap/lcd_palmtt.c similarity index 100% rename from drivers/video/omap/lcd_palmtt.c rename to drivers/video/fbdev/omap/lcd_palmtt.c diff --git a/drivers/video/omap/lcd_palmz71.c b/drivers/video/fbdev/omap/lcd_palmz71.c similarity index 100% rename from drivers/video/omap/lcd_palmz71.c rename to drivers/video/fbdev/omap/lcd_palmz71.c diff --git a/drivers/video/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c similarity index 100% rename from drivers/video/omap/lcdc.c rename to drivers/video/fbdev/omap/lcdc.c diff --git a/drivers/video/omap/lcdc.h b/drivers/video/fbdev/omap/lcdc.h similarity index 100% rename from drivers/video/omap/lcdc.h rename to drivers/video/fbdev/omap/lcdc.h diff --git a/drivers/video/omap/omapfb.h b/drivers/video/fbdev/omap/omapfb.h similarity index 100% rename from drivers/video/omap/omapfb.h rename to drivers/video/fbdev/omap/omapfb.h diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c similarity index 100% rename from drivers/video/omap/omapfb_main.c rename to drivers/video/fbdev/omap/omapfb_main.c diff --git a/drivers/video/omap/sossi.c b/drivers/video/fbdev/omap/sossi.c similarity index 100% rename from drivers/video/omap/sossi.c rename to drivers/video/fbdev/omap/sossi.c diff --git a/drivers/video/fbdev/omap2/Kconfig b/drivers/video/fbdev/omap2/Kconfig new file mode 100644 index 00000000000000..c22955d2de9a86 --- /dev/null +++ b/drivers/video/fbdev/omap2/Kconfig @@ -0,0 +1,10 @@ +config OMAP2_VRFB + bool + +if ARCH_OMAP2PLUS + +source "drivers/video/fbdev/omap2/dss/Kconfig" +source "drivers/video/fbdev/omap2/omapfb/Kconfig" +source "drivers/video/fbdev/omap2/displays-new/Kconfig" + +endif diff --git a/drivers/video/omap2/Makefile b/drivers/video/fbdev/omap2/Makefile similarity index 100% rename from drivers/video/omap2/Makefile rename to drivers/video/fbdev/omap2/Makefile diff --git a/drivers/video/omap2/displays-new/Kconfig b/drivers/video/fbdev/omap2/displays-new/Kconfig similarity index 100% rename from drivers/video/omap2/displays-new/Kconfig rename to drivers/video/fbdev/omap2/displays-new/Kconfig diff --git a/drivers/video/omap2/displays-new/Makefile b/drivers/video/fbdev/omap2/displays-new/Makefile similarity index 100% rename from drivers/video/omap2/displays-new/Makefile rename to drivers/video/fbdev/omap2/displays-new/Makefile diff --git a/drivers/video/omap2/displays-new/connector-analog-tv.c b/drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c similarity index 100% rename from drivers/video/omap2/displays-new/connector-analog-tv.c rename to drivers/video/fbdev/omap2/displays-new/connector-analog-tv.c diff --git a/drivers/video/omap2/displays-new/connector-dvi.c b/drivers/video/fbdev/omap2/displays-new/connector-dvi.c similarity index 100% rename from drivers/video/omap2/displays-new/connector-dvi.c rename to drivers/video/fbdev/omap2/displays-new/connector-dvi.c diff --git a/drivers/video/omap2/displays-new/connector-hdmi.c b/drivers/video/fbdev/omap2/displays-new/connector-hdmi.c similarity index 100% rename from drivers/video/omap2/displays-new/connector-hdmi.c rename to drivers/video/fbdev/omap2/displays-new/connector-hdmi.c diff --git a/drivers/video/omap2/displays-new/encoder-tfp410.c b/drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c similarity index 100% rename from drivers/video/omap2/displays-new/encoder-tfp410.c rename to drivers/video/fbdev/omap2/displays-new/encoder-tfp410.c diff --git a/drivers/video/omap2/displays-new/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c similarity index 100% rename from drivers/video/omap2/displays-new/encoder-tpd12s015.c rename to drivers/video/fbdev/omap2/displays-new/encoder-tpd12s015.c diff --git a/drivers/video/omap2/displays-new/panel-dpi.c b/drivers/video/fbdev/omap2/displays-new/panel-dpi.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-dpi.c rename to drivers/video/fbdev/omap2/displays-new/panel-dpi.c diff --git a/drivers/video/omap2/displays-new/panel-dsi-cm.c b/drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-dsi-cm.c rename to drivers/video/fbdev/omap2/displays-new/panel-dsi-cm.c diff --git a/drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c b/drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-lgphilips-lb035q02.c rename to drivers/video/fbdev/omap2/displays-new/panel-lgphilips-lb035q02.c diff --git a/drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c b/drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-nec-nl8048hl11.c rename to drivers/video/fbdev/omap2/displays-new/panel-nec-nl8048hl11.c diff --git a/drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c b/drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-sharp-ls037v7dw01.c rename to drivers/video/fbdev/omap2/displays-new/panel-sharp-ls037v7dw01.c diff --git a/drivers/video/omap2/displays-new/panel-sony-acx565akm.c b/drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-sony-acx565akm.c rename to drivers/video/fbdev/omap2/displays-new/panel-sony-acx565akm.c diff --git a/drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-tpo-td028ttec1.c rename to drivers/video/fbdev/omap2/displays-new/panel-tpo-td028ttec1.c diff --git a/drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c similarity index 100% rename from drivers/video/omap2/displays-new/panel-tpo-td043mtea1.c rename to drivers/video/fbdev/omap2/displays-new/panel-tpo-td043mtea1.c diff --git a/drivers/video/omap2/dss/Kconfig b/drivers/video/fbdev/omap2/dss/Kconfig similarity index 100% rename from drivers/video/omap2/dss/Kconfig rename to drivers/video/fbdev/omap2/dss/Kconfig diff --git a/drivers/video/omap2/dss/Makefile b/drivers/video/fbdev/omap2/dss/Makefile similarity index 100% rename from drivers/video/omap2/dss/Makefile rename to drivers/video/fbdev/omap2/dss/Makefile diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/fbdev/omap2/dss/apply.c similarity index 100% rename from drivers/video/omap2/dss/apply.c rename to drivers/video/fbdev/omap2/dss/apply.c diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/fbdev/omap2/dss/core.c similarity index 100% rename from drivers/video/omap2/dss/core.c rename to drivers/video/fbdev/omap2/dss/core.c diff --git a/drivers/video/omap2/dss/dispc-compat.c b/drivers/video/fbdev/omap2/dss/dispc-compat.c similarity index 100% rename from drivers/video/omap2/dss/dispc-compat.c rename to drivers/video/fbdev/omap2/dss/dispc-compat.c diff --git a/drivers/video/omap2/dss/dispc-compat.h b/drivers/video/fbdev/omap2/dss/dispc-compat.h similarity index 100% rename from drivers/video/omap2/dss/dispc-compat.h rename to drivers/video/fbdev/omap2/dss/dispc-compat.h diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/fbdev/omap2/dss/dispc.c similarity index 100% rename from drivers/video/omap2/dss/dispc.c rename to drivers/video/fbdev/omap2/dss/dispc.c diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/fbdev/omap2/dss/dispc.h similarity index 100% rename from drivers/video/omap2/dss/dispc.h rename to drivers/video/fbdev/omap2/dss/dispc.h diff --git a/drivers/video/omap2/dss/dispc_coefs.c b/drivers/video/fbdev/omap2/dss/dispc_coefs.c similarity index 100% rename from drivers/video/omap2/dss/dispc_coefs.c rename to drivers/video/fbdev/omap2/dss/dispc_coefs.c diff --git a/drivers/video/omap2/dss/display-sysfs.c b/drivers/video/fbdev/omap2/dss/display-sysfs.c similarity index 100% rename from drivers/video/omap2/dss/display-sysfs.c rename to drivers/video/fbdev/omap2/dss/display-sysfs.c diff --git a/drivers/video/omap2/dss/display.c b/drivers/video/fbdev/omap2/dss/display.c similarity index 100% rename from drivers/video/omap2/dss/display.c rename to drivers/video/fbdev/omap2/dss/display.c diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/fbdev/omap2/dss/dpi.c similarity index 100% rename from drivers/video/omap2/dss/dpi.c rename to drivers/video/fbdev/omap2/dss/dpi.c diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/fbdev/omap2/dss/dsi.c similarity index 100% rename from drivers/video/omap2/dss/dsi.c rename to drivers/video/fbdev/omap2/dss/dsi.c diff --git a/drivers/video/omap2/dss/dss-of.c b/drivers/video/fbdev/omap2/dss/dss-of.c similarity index 100% rename from drivers/video/omap2/dss/dss-of.c rename to drivers/video/fbdev/omap2/dss/dss-of.c diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/fbdev/omap2/dss/dss.c similarity index 100% rename from drivers/video/omap2/dss/dss.c rename to drivers/video/fbdev/omap2/dss/dss.c diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/fbdev/omap2/dss/dss.h similarity index 100% rename from drivers/video/omap2/dss/dss.h rename to drivers/video/fbdev/omap2/dss/dss.h diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/fbdev/omap2/dss/dss_features.c similarity index 100% rename from drivers/video/omap2/dss/dss_features.c rename to drivers/video/fbdev/omap2/dss/dss_features.c diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/fbdev/omap2/dss/dss_features.h similarity index 100% rename from drivers/video/omap2/dss/dss_features.h rename to drivers/video/fbdev/omap2/dss/dss_features.h diff --git a/drivers/video/omap2/dss/hdmi.h b/drivers/video/fbdev/omap2/dss/hdmi.h similarity index 100% rename from drivers/video/omap2/dss/hdmi.h rename to drivers/video/fbdev/omap2/dss/hdmi.h diff --git a/drivers/video/omap2/dss/hdmi4.c b/drivers/video/fbdev/omap2/dss/hdmi4.c similarity index 100% rename from drivers/video/omap2/dss/hdmi4.c rename to drivers/video/fbdev/omap2/dss/hdmi4.c diff --git a/drivers/video/omap2/dss/hdmi4_core.c b/drivers/video/fbdev/omap2/dss/hdmi4_core.c similarity index 100% rename from drivers/video/omap2/dss/hdmi4_core.c rename to drivers/video/fbdev/omap2/dss/hdmi4_core.c diff --git a/drivers/video/omap2/dss/hdmi4_core.h b/drivers/video/fbdev/omap2/dss/hdmi4_core.h similarity index 100% rename from drivers/video/omap2/dss/hdmi4_core.h rename to drivers/video/fbdev/omap2/dss/hdmi4_core.h diff --git a/drivers/video/omap2/dss/hdmi_common.c b/drivers/video/fbdev/omap2/dss/hdmi_common.c similarity index 100% rename from drivers/video/omap2/dss/hdmi_common.c rename to drivers/video/fbdev/omap2/dss/hdmi_common.c diff --git a/drivers/video/omap2/dss/hdmi_phy.c b/drivers/video/fbdev/omap2/dss/hdmi_phy.c similarity index 100% rename from drivers/video/omap2/dss/hdmi_phy.c rename to drivers/video/fbdev/omap2/dss/hdmi_phy.c diff --git a/drivers/video/omap2/dss/hdmi_pll.c b/drivers/video/fbdev/omap2/dss/hdmi_pll.c similarity index 100% rename from drivers/video/omap2/dss/hdmi_pll.c rename to drivers/video/fbdev/omap2/dss/hdmi_pll.c diff --git a/drivers/video/omap2/dss/hdmi_wp.c b/drivers/video/fbdev/omap2/dss/hdmi_wp.c similarity index 100% rename from drivers/video/omap2/dss/hdmi_wp.c rename to drivers/video/fbdev/omap2/dss/hdmi_wp.c diff --git a/drivers/video/omap2/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/dss/manager-sysfs.c similarity index 100% rename from drivers/video/omap2/dss/manager-sysfs.c rename to drivers/video/fbdev/omap2/dss/manager-sysfs.c diff --git a/drivers/video/omap2/dss/manager.c b/drivers/video/fbdev/omap2/dss/manager.c similarity index 100% rename from drivers/video/omap2/dss/manager.c rename to drivers/video/fbdev/omap2/dss/manager.c diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/fbdev/omap2/dss/output.c similarity index 100% rename from drivers/video/omap2/dss/output.c rename to drivers/video/fbdev/omap2/dss/output.c diff --git a/drivers/video/omap2/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/dss/overlay-sysfs.c similarity index 100% rename from drivers/video/omap2/dss/overlay-sysfs.c rename to drivers/video/fbdev/omap2/dss/overlay-sysfs.c diff --git a/drivers/video/omap2/dss/overlay.c b/drivers/video/fbdev/omap2/dss/overlay.c similarity index 100% rename from drivers/video/omap2/dss/overlay.c rename to drivers/video/fbdev/omap2/dss/overlay.c diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/fbdev/omap2/dss/rfbi.c similarity index 100% rename from drivers/video/omap2/dss/rfbi.c rename to drivers/video/fbdev/omap2/dss/rfbi.c diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/fbdev/omap2/dss/sdi.c similarity index 100% rename from drivers/video/omap2/dss/sdi.c rename to drivers/video/fbdev/omap2/dss/sdi.c diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/fbdev/omap2/dss/venc.c similarity index 100% rename from drivers/video/omap2/dss/venc.c rename to drivers/video/fbdev/omap2/dss/venc.c diff --git a/drivers/video/omap2/dss/venc_panel.c b/drivers/video/fbdev/omap2/dss/venc_panel.c similarity index 100% rename from drivers/video/omap2/dss/venc_panel.c rename to drivers/video/fbdev/omap2/dss/venc_panel.c diff --git a/drivers/video/omap2/omapfb/Kconfig b/drivers/video/fbdev/omap2/omapfb/Kconfig similarity index 100% rename from drivers/video/omap2/omapfb/Kconfig rename to drivers/video/fbdev/omap2/omapfb/Kconfig diff --git a/drivers/video/omap2/omapfb/Makefile b/drivers/video/fbdev/omap2/omapfb/Makefile similarity index 100% rename from drivers/video/omap2/omapfb/Makefile rename to drivers/video/fbdev/omap2/omapfb/Makefile diff --git a/drivers/video/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c similarity index 100% rename from drivers/video/omap2/omapfb/omapfb-ioctl.c rename to drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c similarity index 100% rename from drivers/video/omap2/omapfb/omapfb-main.c rename to drivers/video/fbdev/omap2/omapfb/omapfb-main.c diff --git a/drivers/video/omap2/omapfb/omapfb-sysfs.c b/drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c similarity index 100% rename from drivers/video/omap2/omapfb/omapfb-sysfs.c rename to drivers/video/fbdev/omap2/omapfb/omapfb-sysfs.c diff --git a/drivers/video/omap2/omapfb/omapfb.h b/drivers/video/fbdev/omap2/omapfb/omapfb.h similarity index 100% rename from drivers/video/omap2/omapfb/omapfb.h rename to drivers/video/fbdev/omap2/omapfb/omapfb.h diff --git a/drivers/video/omap2/vrfb.c b/drivers/video/fbdev/omap2/vrfb.c similarity index 100% rename from drivers/video/omap2/vrfb.c rename to drivers/video/fbdev/omap2/vrfb.c diff --git a/drivers/video/p9100.c b/drivers/video/fbdev/p9100.c similarity index 100% rename from drivers/video/p9100.c rename to drivers/video/fbdev/p9100.c diff --git a/drivers/video/platinumfb.c b/drivers/video/fbdev/platinumfb.c similarity index 100% rename from drivers/video/platinumfb.c rename to drivers/video/fbdev/platinumfb.c diff --git a/drivers/video/platinumfb.h b/drivers/video/fbdev/platinumfb.h similarity index 100% rename from drivers/video/platinumfb.h rename to drivers/video/fbdev/platinumfb.h diff --git a/drivers/video/pm2fb.c b/drivers/video/fbdev/pm2fb.c similarity index 100% rename from drivers/video/pm2fb.c rename to drivers/video/fbdev/pm2fb.c diff --git a/drivers/video/pm3fb.c b/drivers/video/fbdev/pm3fb.c similarity index 100% rename from drivers/video/pm3fb.c rename to drivers/video/fbdev/pm3fb.c diff --git a/drivers/video/pmag-aa-fb.c b/drivers/video/fbdev/pmag-aa-fb.c similarity index 100% rename from drivers/video/pmag-aa-fb.c rename to drivers/video/fbdev/pmag-aa-fb.c diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/fbdev/pmag-ba-fb.c similarity index 100% rename from drivers/video/pmag-ba-fb.c rename to drivers/video/fbdev/pmag-ba-fb.c diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/fbdev/pmagb-b-fb.c similarity index 100% rename from drivers/video/pmagb-b-fb.c rename to drivers/video/fbdev/pmagb-b-fb.c diff --git a/drivers/video/ps3fb.c b/drivers/video/fbdev/ps3fb.c similarity index 100% rename from drivers/video/ps3fb.c rename to drivers/video/fbdev/ps3fb.c diff --git a/drivers/video/pvr2fb.c b/drivers/video/fbdev/pvr2fb.c similarity index 100% rename from drivers/video/pvr2fb.c rename to drivers/video/fbdev/pvr2fb.c diff --git a/drivers/video/pxa168fb.c b/drivers/video/fbdev/pxa168fb.c similarity index 100% rename from drivers/video/pxa168fb.c rename to drivers/video/fbdev/pxa168fb.c diff --git a/drivers/video/pxa168fb.h b/drivers/video/fbdev/pxa168fb.h similarity index 100% rename from drivers/video/pxa168fb.h rename to drivers/video/fbdev/pxa168fb.h diff --git a/drivers/video/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c similarity index 100% rename from drivers/video/pxa3xx-gcu.c rename to drivers/video/fbdev/pxa3xx-gcu.c diff --git a/drivers/video/pxa3xx-gcu.h b/drivers/video/fbdev/pxa3xx-gcu.h similarity index 100% rename from drivers/video/pxa3xx-gcu.h rename to drivers/video/fbdev/pxa3xx-gcu.h diff --git a/drivers/video/pxafb.c b/drivers/video/fbdev/pxafb.c similarity index 100% rename from drivers/video/pxafb.c rename to drivers/video/fbdev/pxafb.c diff --git a/drivers/video/pxafb.h b/drivers/video/fbdev/pxafb.h similarity index 100% rename from drivers/video/pxafb.h rename to drivers/video/fbdev/pxafb.h diff --git a/drivers/video/q40fb.c b/drivers/video/fbdev/q40fb.c similarity index 100% rename from drivers/video/q40fb.c rename to drivers/video/fbdev/q40fb.c diff --git a/drivers/video/riva/Makefile b/drivers/video/fbdev/riva/Makefile similarity index 100% rename from drivers/video/riva/Makefile rename to drivers/video/fbdev/riva/Makefile diff --git a/drivers/video/riva/fbdev.c b/drivers/video/fbdev/riva/fbdev.c similarity index 100% rename from drivers/video/riva/fbdev.c rename to drivers/video/fbdev/riva/fbdev.c diff --git a/drivers/video/riva/nv_driver.c b/drivers/video/fbdev/riva/nv_driver.c similarity index 100% rename from drivers/video/riva/nv_driver.c rename to drivers/video/fbdev/riva/nv_driver.c diff --git a/drivers/video/riva/nv_type.h b/drivers/video/fbdev/riva/nv_type.h similarity index 100% rename from drivers/video/riva/nv_type.h rename to drivers/video/fbdev/riva/nv_type.h diff --git a/drivers/video/riva/nvreg.h b/drivers/video/fbdev/riva/nvreg.h similarity index 100% rename from drivers/video/riva/nvreg.h rename to drivers/video/fbdev/riva/nvreg.h diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/fbdev/riva/riva_hw.c similarity index 100% rename from drivers/video/riva/riva_hw.c rename to drivers/video/fbdev/riva/riva_hw.c diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/fbdev/riva/riva_hw.h similarity index 100% rename from drivers/video/riva/riva_hw.h rename to drivers/video/fbdev/riva/riva_hw.h diff --git a/drivers/video/riva/riva_tbl.h b/drivers/video/fbdev/riva/riva_tbl.h similarity index 100% rename from drivers/video/riva/riva_tbl.h rename to drivers/video/fbdev/riva/riva_tbl.h diff --git a/drivers/video/riva/rivafb-i2c.c b/drivers/video/fbdev/riva/rivafb-i2c.c similarity index 100% rename from drivers/video/riva/rivafb-i2c.c rename to drivers/video/fbdev/riva/rivafb-i2c.c diff --git a/drivers/video/riva/rivafb.h b/drivers/video/fbdev/riva/rivafb.h similarity index 100% rename from drivers/video/riva/rivafb.h rename to drivers/video/fbdev/riva/rivafb.h diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/fbdev/s1d13xxxfb.c similarity index 100% rename from drivers/video/s1d13xxxfb.c rename to drivers/video/fbdev/s1d13xxxfb.c diff --git a/drivers/video/s3c-fb.c b/drivers/video/fbdev/s3c-fb.c similarity index 100% rename from drivers/video/s3c-fb.c rename to drivers/video/fbdev/s3c-fb.c diff --git a/drivers/video/s3c2410fb.c b/drivers/video/fbdev/s3c2410fb.c similarity index 100% rename from drivers/video/s3c2410fb.c rename to drivers/video/fbdev/s3c2410fb.c diff --git a/drivers/video/s3c2410fb.h b/drivers/video/fbdev/s3c2410fb.h similarity index 100% rename from drivers/video/s3c2410fb.h rename to drivers/video/fbdev/s3c2410fb.h diff --git a/drivers/video/s3fb.c b/drivers/video/fbdev/s3fb.c similarity index 100% rename from drivers/video/s3fb.c rename to drivers/video/fbdev/s3fb.c diff --git a/drivers/video/sa1100fb.c b/drivers/video/fbdev/sa1100fb.c similarity index 100% rename from drivers/video/sa1100fb.c rename to drivers/video/fbdev/sa1100fb.c diff --git a/drivers/video/sa1100fb.h b/drivers/video/fbdev/sa1100fb.h similarity index 100% rename from drivers/video/sa1100fb.h rename to drivers/video/fbdev/sa1100fb.h diff --git a/drivers/video/savage/Makefile b/drivers/video/fbdev/savage/Makefile similarity index 100% rename from drivers/video/savage/Makefile rename to drivers/video/fbdev/savage/Makefile diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/fbdev/savage/savagefb-i2c.c similarity index 100% rename from drivers/video/savage/savagefb-i2c.c rename to drivers/video/fbdev/savage/savagefb-i2c.c diff --git a/drivers/video/savage/savagefb.h b/drivers/video/fbdev/savage/savagefb.h similarity index 100% rename from drivers/video/savage/savagefb.h rename to drivers/video/fbdev/savage/savagefb.h diff --git a/drivers/video/savage/savagefb_accel.c b/drivers/video/fbdev/savage/savagefb_accel.c similarity index 100% rename from drivers/video/savage/savagefb_accel.c rename to drivers/video/fbdev/savage/savagefb_accel.c diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/fbdev/savage/savagefb_driver.c similarity index 100% rename from drivers/video/savage/savagefb_driver.c rename to drivers/video/fbdev/savage/savagefb_driver.c diff --git a/drivers/video/sbuslib.c b/drivers/video/fbdev/sbuslib.c similarity index 100% rename from drivers/video/sbuslib.c rename to drivers/video/fbdev/sbuslib.c diff --git a/drivers/video/sbuslib.h b/drivers/video/fbdev/sbuslib.h similarity index 100% rename from drivers/video/sbuslib.h rename to drivers/video/fbdev/sbuslib.h diff --git a/drivers/video/sh7760fb.c b/drivers/video/fbdev/sh7760fb.c similarity index 100% rename from drivers/video/sh7760fb.c rename to drivers/video/fbdev/sh7760fb.c diff --git a/drivers/video/sh_mipi_dsi.c b/drivers/video/fbdev/sh_mipi_dsi.c similarity index 100% rename from drivers/video/sh_mipi_dsi.c rename to drivers/video/fbdev/sh_mipi_dsi.c diff --git a/drivers/video/sh_mobile_hdmi.c b/drivers/video/fbdev/sh_mobile_hdmi.c similarity index 100% rename from drivers/video/sh_mobile_hdmi.c rename to drivers/video/fbdev/sh_mobile_hdmi.c diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/fbdev/sh_mobile_lcdcfb.c similarity index 100% rename from drivers/video/sh_mobile_lcdcfb.c rename to drivers/video/fbdev/sh_mobile_lcdcfb.c diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/fbdev/sh_mobile_lcdcfb.h similarity index 100% rename from drivers/video/sh_mobile_lcdcfb.h rename to drivers/video/fbdev/sh_mobile_lcdcfb.h diff --git a/drivers/video/sh_mobile_meram.c b/drivers/video/fbdev/sh_mobile_meram.c similarity index 100% rename from drivers/video/sh_mobile_meram.c rename to drivers/video/fbdev/sh_mobile_meram.c diff --git a/drivers/video/simplefb.c b/drivers/video/fbdev/simplefb.c similarity index 100% rename from drivers/video/simplefb.c rename to drivers/video/fbdev/simplefb.c diff --git a/drivers/video/sis/300vtbl.h b/drivers/video/fbdev/sis/300vtbl.h similarity index 100% rename from drivers/video/sis/300vtbl.h rename to drivers/video/fbdev/sis/300vtbl.h diff --git a/drivers/video/sis/310vtbl.h b/drivers/video/fbdev/sis/310vtbl.h similarity index 100% rename from drivers/video/sis/310vtbl.h rename to drivers/video/fbdev/sis/310vtbl.h diff --git a/drivers/video/sis/Makefile b/drivers/video/fbdev/sis/Makefile similarity index 100% rename from drivers/video/sis/Makefile rename to drivers/video/fbdev/sis/Makefile diff --git a/drivers/video/sis/init.c b/drivers/video/fbdev/sis/init.c similarity index 100% rename from drivers/video/sis/init.c rename to drivers/video/fbdev/sis/init.c diff --git a/drivers/video/sis/init.h b/drivers/video/fbdev/sis/init.h similarity index 100% rename from drivers/video/sis/init.h rename to drivers/video/fbdev/sis/init.h diff --git a/drivers/video/sis/init301.c b/drivers/video/fbdev/sis/init301.c similarity index 100% rename from drivers/video/sis/init301.c rename to drivers/video/fbdev/sis/init301.c diff --git a/drivers/video/sis/init301.h b/drivers/video/fbdev/sis/init301.h similarity index 100% rename from drivers/video/sis/init301.h rename to drivers/video/fbdev/sis/init301.h diff --git a/drivers/video/sis/initdef.h b/drivers/video/fbdev/sis/initdef.h similarity index 100% rename from drivers/video/sis/initdef.h rename to drivers/video/fbdev/sis/initdef.h diff --git a/drivers/video/sis/initextlfb.c b/drivers/video/fbdev/sis/initextlfb.c similarity index 100% rename from drivers/video/sis/initextlfb.c rename to drivers/video/fbdev/sis/initextlfb.c diff --git a/drivers/video/sis/oem300.h b/drivers/video/fbdev/sis/oem300.h similarity index 100% rename from drivers/video/sis/oem300.h rename to drivers/video/fbdev/sis/oem300.h diff --git a/drivers/video/sis/oem310.h b/drivers/video/fbdev/sis/oem310.h similarity index 100% rename from drivers/video/sis/oem310.h rename to drivers/video/fbdev/sis/oem310.h diff --git a/drivers/video/sis/sis.h b/drivers/video/fbdev/sis/sis.h similarity index 100% rename from drivers/video/sis/sis.h rename to drivers/video/fbdev/sis/sis.h diff --git a/drivers/video/sis/sis_accel.c b/drivers/video/fbdev/sis/sis_accel.c similarity index 100% rename from drivers/video/sis/sis_accel.c rename to drivers/video/fbdev/sis/sis_accel.c diff --git a/drivers/video/sis/sis_accel.h b/drivers/video/fbdev/sis/sis_accel.h similarity index 100% rename from drivers/video/sis/sis_accel.h rename to drivers/video/fbdev/sis/sis_accel.h diff --git a/drivers/video/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c similarity index 100% rename from drivers/video/sis/sis_main.c rename to drivers/video/fbdev/sis/sis_main.c diff --git a/drivers/video/sis/sis_main.h b/drivers/video/fbdev/sis/sis_main.h similarity index 100% rename from drivers/video/sis/sis_main.h rename to drivers/video/fbdev/sis/sis_main.h diff --git a/drivers/video/sis/vgatypes.h b/drivers/video/fbdev/sis/vgatypes.h similarity index 100% rename from drivers/video/sis/vgatypes.h rename to drivers/video/fbdev/sis/vgatypes.h diff --git a/drivers/video/sis/vstruct.h b/drivers/video/fbdev/sis/vstruct.h similarity index 100% rename from drivers/video/sis/vstruct.h rename to drivers/video/fbdev/sis/vstruct.h diff --git a/drivers/video/skeletonfb.c b/drivers/video/fbdev/skeletonfb.c similarity index 100% rename from drivers/video/skeletonfb.c rename to drivers/video/fbdev/skeletonfb.c diff --git a/drivers/video/sm501fb.c b/drivers/video/fbdev/sm501fb.c similarity index 100% rename from drivers/video/sm501fb.c rename to drivers/video/fbdev/sm501fb.c diff --git a/drivers/video/smscufx.c b/drivers/video/fbdev/smscufx.c similarity index 100% rename from drivers/video/smscufx.c rename to drivers/video/fbdev/smscufx.c diff --git a/drivers/video/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c similarity index 100% rename from drivers/video/ssd1307fb.c rename to drivers/video/fbdev/ssd1307fb.c diff --git a/drivers/video/sstfb.c b/drivers/video/fbdev/sstfb.c similarity index 100% rename from drivers/video/sstfb.c rename to drivers/video/fbdev/sstfb.c diff --git a/drivers/video/sticore.h b/drivers/video/fbdev/sticore.h similarity index 100% rename from drivers/video/sticore.h rename to drivers/video/fbdev/sticore.h diff --git a/drivers/video/stifb.c b/drivers/video/fbdev/stifb.c similarity index 100% rename from drivers/video/stifb.c rename to drivers/video/fbdev/stifb.c diff --git a/drivers/video/sunxvr1000.c b/drivers/video/fbdev/sunxvr1000.c similarity index 100% rename from drivers/video/sunxvr1000.c rename to drivers/video/fbdev/sunxvr1000.c diff --git a/drivers/video/sunxvr2500.c b/drivers/video/fbdev/sunxvr2500.c similarity index 100% rename from drivers/video/sunxvr2500.c rename to drivers/video/fbdev/sunxvr2500.c diff --git a/drivers/video/sunxvr500.c b/drivers/video/fbdev/sunxvr500.c similarity index 100% rename from drivers/video/sunxvr500.c rename to drivers/video/fbdev/sunxvr500.c diff --git a/drivers/video/svgalib.c b/drivers/video/fbdev/svgalib.c similarity index 100% rename from drivers/video/svgalib.c rename to drivers/video/fbdev/svgalib.c diff --git a/drivers/video/syscopyarea.c b/drivers/video/fbdev/syscopyarea.c similarity index 100% rename from drivers/video/syscopyarea.c rename to drivers/video/fbdev/syscopyarea.c diff --git a/drivers/video/sysfillrect.c b/drivers/video/fbdev/sysfillrect.c similarity index 100% rename from drivers/video/sysfillrect.c rename to drivers/video/fbdev/sysfillrect.c diff --git a/drivers/video/sysimgblt.c b/drivers/video/fbdev/sysimgblt.c similarity index 100% rename from drivers/video/sysimgblt.c rename to drivers/video/fbdev/sysimgblt.c diff --git a/drivers/video/tcx.c b/drivers/video/fbdev/tcx.c similarity index 100% rename from drivers/video/tcx.c rename to drivers/video/fbdev/tcx.c diff --git a/drivers/video/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c similarity index 100% rename from drivers/video/tdfxfb.c rename to drivers/video/fbdev/tdfxfb.c diff --git a/drivers/video/tgafb.c b/drivers/video/fbdev/tgafb.c similarity index 100% rename from drivers/video/tgafb.c rename to drivers/video/fbdev/tgafb.c diff --git a/drivers/video/tmiofb.c b/drivers/video/fbdev/tmiofb.c similarity index 100% rename from drivers/video/tmiofb.c rename to drivers/video/fbdev/tmiofb.c diff --git a/drivers/video/tridentfb.c b/drivers/video/fbdev/tridentfb.c similarity index 100% rename from drivers/video/tridentfb.c rename to drivers/video/fbdev/tridentfb.c diff --git a/drivers/video/udlfb.c b/drivers/video/fbdev/udlfb.c similarity index 100% rename from drivers/video/udlfb.c rename to drivers/video/fbdev/udlfb.c diff --git a/drivers/video/uvesafb.c b/drivers/video/fbdev/uvesafb.c similarity index 100% rename from drivers/video/uvesafb.c rename to drivers/video/fbdev/uvesafb.c diff --git a/drivers/video/valkyriefb.c b/drivers/video/fbdev/valkyriefb.c similarity index 100% rename from drivers/video/valkyriefb.c rename to drivers/video/fbdev/valkyriefb.c diff --git a/drivers/video/valkyriefb.h b/drivers/video/fbdev/valkyriefb.h similarity index 100% rename from drivers/video/valkyriefb.h rename to drivers/video/fbdev/valkyriefb.h diff --git a/drivers/video/vermilion/Makefile b/drivers/video/fbdev/vermilion/Makefile similarity index 100% rename from drivers/video/vermilion/Makefile rename to drivers/video/fbdev/vermilion/Makefile diff --git a/drivers/video/vermilion/cr_pll.c b/drivers/video/fbdev/vermilion/cr_pll.c similarity index 100% rename from drivers/video/vermilion/cr_pll.c rename to drivers/video/fbdev/vermilion/cr_pll.c diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/fbdev/vermilion/vermilion.c similarity index 100% rename from drivers/video/vermilion/vermilion.c rename to drivers/video/fbdev/vermilion/vermilion.c diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/fbdev/vermilion/vermilion.h similarity index 100% rename from drivers/video/vermilion/vermilion.h rename to drivers/video/fbdev/vermilion/vermilion.h diff --git a/drivers/video/vesafb.c b/drivers/video/fbdev/vesafb.c similarity index 100% rename from drivers/video/vesafb.c rename to drivers/video/fbdev/vesafb.c diff --git a/drivers/video/vfb.c b/drivers/video/fbdev/vfb.c similarity index 100% rename from drivers/video/vfb.c rename to drivers/video/fbdev/vfb.c diff --git a/drivers/video/vga16fb.c b/drivers/video/fbdev/vga16fb.c similarity index 100% rename from drivers/video/vga16fb.c rename to drivers/video/fbdev/vga16fb.c diff --git a/drivers/video/via/Makefile b/drivers/video/fbdev/via/Makefile similarity index 100% rename from drivers/video/via/Makefile rename to drivers/video/fbdev/via/Makefile diff --git a/drivers/video/via/accel.c b/drivers/video/fbdev/via/accel.c similarity index 100% rename from drivers/video/via/accel.c rename to drivers/video/fbdev/via/accel.c diff --git a/drivers/video/via/accel.h b/drivers/video/fbdev/via/accel.h similarity index 100% rename from drivers/video/via/accel.h rename to drivers/video/fbdev/via/accel.h diff --git a/drivers/video/via/chip.h b/drivers/video/fbdev/via/chip.h similarity index 100% rename from drivers/video/via/chip.h rename to drivers/video/fbdev/via/chip.h diff --git a/drivers/video/via/debug.h b/drivers/video/fbdev/via/debug.h similarity index 100% rename from drivers/video/via/debug.h rename to drivers/video/fbdev/via/debug.h diff --git a/drivers/video/via/dvi.c b/drivers/video/fbdev/via/dvi.c similarity index 100% rename from drivers/video/via/dvi.c rename to drivers/video/fbdev/via/dvi.c diff --git a/drivers/video/via/dvi.h b/drivers/video/fbdev/via/dvi.h similarity index 100% rename from drivers/video/via/dvi.h rename to drivers/video/fbdev/via/dvi.h diff --git a/drivers/video/via/global.c b/drivers/video/fbdev/via/global.c similarity index 100% rename from drivers/video/via/global.c rename to drivers/video/fbdev/via/global.c diff --git a/drivers/video/via/global.h b/drivers/video/fbdev/via/global.h similarity index 100% rename from drivers/video/via/global.h rename to drivers/video/fbdev/via/global.h diff --git a/drivers/video/via/hw.c b/drivers/video/fbdev/via/hw.c similarity index 100% rename from drivers/video/via/hw.c rename to drivers/video/fbdev/via/hw.c diff --git a/drivers/video/via/hw.h b/drivers/video/fbdev/via/hw.h similarity index 100% rename from drivers/video/via/hw.h rename to drivers/video/fbdev/via/hw.h diff --git a/drivers/video/via/ioctl.c b/drivers/video/fbdev/via/ioctl.c similarity index 100% rename from drivers/video/via/ioctl.c rename to drivers/video/fbdev/via/ioctl.c diff --git a/drivers/video/via/ioctl.h b/drivers/video/fbdev/via/ioctl.h similarity index 100% rename from drivers/video/via/ioctl.h rename to drivers/video/fbdev/via/ioctl.h diff --git a/drivers/video/via/lcd.c b/drivers/video/fbdev/via/lcd.c similarity index 100% rename from drivers/video/via/lcd.c rename to drivers/video/fbdev/via/lcd.c diff --git a/drivers/video/via/lcd.h b/drivers/video/fbdev/via/lcd.h similarity index 100% rename from drivers/video/via/lcd.h rename to drivers/video/fbdev/via/lcd.h diff --git a/drivers/video/via/share.h b/drivers/video/fbdev/via/share.h similarity index 100% rename from drivers/video/via/share.h rename to drivers/video/fbdev/via/share.h diff --git a/drivers/video/via/tblDPASetting.c b/drivers/video/fbdev/via/tblDPASetting.c similarity index 100% rename from drivers/video/via/tblDPASetting.c rename to drivers/video/fbdev/via/tblDPASetting.c diff --git a/drivers/video/via/tblDPASetting.h b/drivers/video/fbdev/via/tblDPASetting.h similarity index 100% rename from drivers/video/via/tblDPASetting.h rename to drivers/video/fbdev/via/tblDPASetting.h diff --git a/drivers/video/via/via-core.c b/drivers/video/fbdev/via/via-core.c similarity index 100% rename from drivers/video/via/via-core.c rename to drivers/video/fbdev/via/via-core.c diff --git a/drivers/video/via/via-gpio.c b/drivers/video/fbdev/via/via-gpio.c similarity index 100% rename from drivers/video/via/via-gpio.c rename to drivers/video/fbdev/via/via-gpio.c diff --git a/drivers/video/via/via_aux.c b/drivers/video/fbdev/via/via_aux.c similarity index 100% rename from drivers/video/via/via_aux.c rename to drivers/video/fbdev/via/via_aux.c diff --git a/drivers/video/via/via_aux.h b/drivers/video/fbdev/via/via_aux.h similarity index 100% rename from drivers/video/via/via_aux.h rename to drivers/video/fbdev/via/via_aux.h diff --git a/drivers/video/via/via_aux_ch7301.c b/drivers/video/fbdev/via/via_aux_ch7301.c similarity index 100% rename from drivers/video/via/via_aux_ch7301.c rename to drivers/video/fbdev/via/via_aux_ch7301.c diff --git a/drivers/video/via/via_aux_edid.c b/drivers/video/fbdev/via/via_aux_edid.c similarity index 100% rename from drivers/video/via/via_aux_edid.c rename to drivers/video/fbdev/via/via_aux_edid.c diff --git a/drivers/video/via/via_aux_sii164.c b/drivers/video/fbdev/via/via_aux_sii164.c similarity index 100% rename from drivers/video/via/via_aux_sii164.c rename to drivers/video/fbdev/via/via_aux_sii164.c diff --git a/drivers/video/via/via_aux_vt1621.c b/drivers/video/fbdev/via/via_aux_vt1621.c similarity index 100% rename from drivers/video/via/via_aux_vt1621.c rename to drivers/video/fbdev/via/via_aux_vt1621.c diff --git a/drivers/video/via/via_aux_vt1622.c b/drivers/video/fbdev/via/via_aux_vt1622.c similarity index 100% rename from drivers/video/via/via_aux_vt1622.c rename to drivers/video/fbdev/via/via_aux_vt1622.c diff --git a/drivers/video/via/via_aux_vt1625.c b/drivers/video/fbdev/via/via_aux_vt1625.c similarity index 100% rename from drivers/video/via/via_aux_vt1625.c rename to drivers/video/fbdev/via/via_aux_vt1625.c diff --git a/drivers/video/via/via_aux_vt1631.c b/drivers/video/fbdev/via/via_aux_vt1631.c similarity index 100% rename from drivers/video/via/via_aux_vt1631.c rename to drivers/video/fbdev/via/via_aux_vt1631.c diff --git a/drivers/video/via/via_aux_vt1632.c b/drivers/video/fbdev/via/via_aux_vt1632.c similarity index 100% rename from drivers/video/via/via_aux_vt1632.c rename to drivers/video/fbdev/via/via_aux_vt1632.c diff --git a/drivers/video/via/via_aux_vt1636.c b/drivers/video/fbdev/via/via_aux_vt1636.c similarity index 100% rename from drivers/video/via/via_aux_vt1636.c rename to drivers/video/fbdev/via/via_aux_vt1636.c diff --git a/drivers/video/via/via_clock.c b/drivers/video/fbdev/via/via_clock.c similarity index 100% rename from drivers/video/via/via_clock.c rename to drivers/video/fbdev/via/via_clock.c diff --git a/drivers/video/via/via_clock.h b/drivers/video/fbdev/via/via_clock.h similarity index 100% rename from drivers/video/via/via_clock.h rename to drivers/video/fbdev/via/via_clock.h diff --git a/drivers/video/via/via_i2c.c b/drivers/video/fbdev/via/via_i2c.c similarity index 100% rename from drivers/video/via/via_i2c.c rename to drivers/video/fbdev/via/via_i2c.c diff --git a/drivers/video/via/via_modesetting.c b/drivers/video/fbdev/via/via_modesetting.c similarity index 100% rename from drivers/video/via/via_modesetting.c rename to drivers/video/fbdev/via/via_modesetting.c diff --git a/drivers/video/via/via_modesetting.h b/drivers/video/fbdev/via/via_modesetting.h similarity index 100% rename from drivers/video/via/via_modesetting.h rename to drivers/video/fbdev/via/via_modesetting.h diff --git a/drivers/video/via/via_utility.c b/drivers/video/fbdev/via/via_utility.c similarity index 100% rename from drivers/video/via/via_utility.c rename to drivers/video/fbdev/via/via_utility.c diff --git a/drivers/video/via/via_utility.h b/drivers/video/fbdev/via/via_utility.h similarity index 100% rename from drivers/video/via/via_utility.h rename to drivers/video/fbdev/via/via_utility.h diff --git a/drivers/video/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c similarity index 100% rename from drivers/video/via/viafbdev.c rename to drivers/video/fbdev/via/viafbdev.c diff --git a/drivers/video/via/viafbdev.h b/drivers/video/fbdev/via/viafbdev.h similarity index 100% rename from drivers/video/via/viafbdev.h rename to drivers/video/fbdev/via/viafbdev.h diff --git a/drivers/video/via/viamode.c b/drivers/video/fbdev/via/viamode.c similarity index 100% rename from drivers/video/via/viamode.c rename to drivers/video/fbdev/via/viamode.c diff --git a/drivers/video/via/viamode.h b/drivers/video/fbdev/via/viamode.h similarity index 100% rename from drivers/video/via/viamode.h rename to drivers/video/fbdev/via/viamode.h diff --git a/drivers/video/via/vt1636.c b/drivers/video/fbdev/via/vt1636.c similarity index 100% rename from drivers/video/via/vt1636.c rename to drivers/video/fbdev/via/vt1636.c diff --git a/drivers/video/via/vt1636.h b/drivers/video/fbdev/via/vt1636.h similarity index 100% rename from drivers/video/via/vt1636.h rename to drivers/video/fbdev/via/vt1636.h diff --git a/drivers/video/vt8500lcdfb.c b/drivers/video/fbdev/vt8500lcdfb.c similarity index 100% rename from drivers/video/vt8500lcdfb.c rename to drivers/video/fbdev/vt8500lcdfb.c diff --git a/drivers/video/vt8500lcdfb.h b/drivers/video/fbdev/vt8500lcdfb.h similarity index 100% rename from drivers/video/vt8500lcdfb.h rename to drivers/video/fbdev/vt8500lcdfb.h diff --git a/drivers/video/vt8623fb.c b/drivers/video/fbdev/vt8623fb.c similarity index 100% rename from drivers/video/vt8623fb.c rename to drivers/video/fbdev/vt8623fb.c diff --git a/drivers/video/w100fb.c b/drivers/video/fbdev/w100fb.c similarity index 100% rename from drivers/video/w100fb.c rename to drivers/video/fbdev/w100fb.c diff --git a/drivers/video/w100fb.h b/drivers/video/fbdev/w100fb.h similarity index 100% rename from drivers/video/w100fb.h rename to drivers/video/fbdev/w100fb.h diff --git a/drivers/video/wm8505fb.c b/drivers/video/fbdev/wm8505fb.c similarity index 100% rename from drivers/video/wm8505fb.c rename to drivers/video/fbdev/wm8505fb.c diff --git a/drivers/video/wm8505fb_regs.h b/drivers/video/fbdev/wm8505fb_regs.h similarity index 100% rename from drivers/video/wm8505fb_regs.h rename to drivers/video/fbdev/wm8505fb_regs.h diff --git a/drivers/video/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c similarity index 100% rename from drivers/video/wmt_ge_rops.c rename to drivers/video/fbdev/wmt_ge_rops.c diff --git a/drivers/video/wmt_ge_rops.h b/drivers/video/fbdev/wmt_ge_rops.h similarity index 100% rename from drivers/video/wmt_ge_rops.h rename to drivers/video/fbdev/wmt_ge_rops.h diff --git a/drivers/video/xen-fbfront.c b/drivers/video/fbdev/xen-fbfront.c similarity index 100% rename from drivers/video/xen-fbfront.c rename to drivers/video/fbdev/xen-fbfront.c diff --git a/drivers/video/xilinxfb.c b/drivers/video/fbdev/xilinxfb.c similarity index 100% rename from drivers/video/xilinxfb.c rename to drivers/video/fbdev/xilinxfb.c diff --git a/drivers/video/omap2/Kconfig b/drivers/video/omap2/Kconfig deleted file mode 100644 index 63b23f87081d3d..00000000000000 --- a/drivers/video/omap2/Kconfig +++ /dev/null @@ -1,10 +0,0 @@ -config OMAP2_VRFB - bool - -if ARCH_OMAP2PLUS - -source "drivers/video/omap2/dss/Kconfig" -source "drivers/video/omap2/omapfb/Kconfig" -source "drivers/video/omap2/displays-new/Kconfig" - -endif From 19757fc8432ac97a07a890d6310cccc1896a1b36 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Feb 2014 16:24:55 +0200 Subject: [PATCH 228/279] fbdev: move fbdev core files to separate directory Instead of having fbdev framework core files at the root fbdev directory, mixed with random fbdev device drivers, move the fbdev core files to a separate core directory. This makes it much clearer which of the files are actually part of the fbdev framework, and which are part of device drivers. Signed-off-by: Tomi Valkeinen Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Acked-by: Rob Clark Acked-by: Jingoo Han Acked-by: Daniel Vetter --- Documentation/DocBook/device-drivers.tmpl | 8 ++++---- drivers/video/fbdev/Makefile | 16 +--------------- drivers/video/fbdev/aty/mach64_cursor.c | 2 +- drivers/video/fbdev/core/Makefile | 16 ++++++++++++++++ drivers/video/fbdev/{ => core}/cfbcopyarea.c | 0 drivers/video/fbdev/{ => core}/cfbfillrect.c | 0 drivers/video/fbdev/{ => core}/cfbimgblt.c | 0 drivers/video/fbdev/{ => core}/fb_ddc.c | 2 +- drivers/video/fbdev/{ => core}/fb_defio.c | 0 drivers/video/fbdev/{ => core}/fb_draw.h | 0 drivers/video/fbdev/{ => core}/fb_notify.c | 0 drivers/video/fbdev/{ => core}/fb_sys_fops.c | 0 drivers/video/fbdev/{ => core}/fbcmap.c | 0 drivers/video/fbdev/{ => core}/fbcvt.c | 0 drivers/video/fbdev/{ => core}/fbmem.c | 0 drivers/video/fbdev/{ => core}/fbmon.c | 2 +- drivers/video/fbdev/{ => core}/fbsysfs.c | 0 drivers/video/fbdev/{ => core}/modedb.c | 0 drivers/video/fbdev/{ => core}/svgalib.c | 0 drivers/video/fbdev/{ => core}/syscopyarea.c | 0 drivers/video/fbdev/{ => core}/sysfillrect.c | 0 drivers/video/fbdev/{ => core}/sysimgblt.c | 0 drivers/video/fbdev/wmt_ge_rops.c | 2 +- 23 files changed, 25 insertions(+), 23 deletions(-) create mode 100644 drivers/video/fbdev/core/Makefile rename drivers/video/fbdev/{ => core}/cfbcopyarea.c (100%) rename drivers/video/fbdev/{ => core}/cfbfillrect.c (100%) rename drivers/video/fbdev/{ => core}/cfbimgblt.c (100%) rename drivers/video/fbdev/{ => core}/fb_ddc.c (99%) rename drivers/video/fbdev/{ => core}/fb_defio.c (100%) rename drivers/video/fbdev/{ => core}/fb_draw.h (100%) rename drivers/video/fbdev/{ => core}/fb_notify.c (100%) rename drivers/video/fbdev/{ => core}/fb_sys_fops.c (100%) rename drivers/video/fbdev/{ => core}/fbcmap.c (100%) rename drivers/video/fbdev/{ => core}/fbcvt.c (100%) rename drivers/video/fbdev/{ => core}/fbmem.c (100%) rename drivers/video/fbdev/{ => core}/fbmon.c (99%) rename drivers/video/fbdev/{ => core}/fbsysfs.c (100%) rename drivers/video/fbdev/{ => core}/modedb.c (100%) rename drivers/video/fbdev/{ => core}/svgalib.c (100%) rename drivers/video/fbdev/{ => core}/syscopyarea.c (100%) rename drivers/video/fbdev/{ => core}/sysfillrect.c (100%) rename drivers/video/fbdev/{ => core}/sysimgblt.c (100%) diff --git a/Documentation/DocBook/device-drivers.tmpl b/Documentation/DocBook/device-drivers.tmpl index 4d1aa8b44be766..cc63f30de16650 100644 --- a/Documentation/DocBook/device-drivers.tmpl +++ b/Documentation/DocBook/device-drivers.tmpl @@ -276,7 +276,7 @@ X!Isound/sound_firmware.c Frame Buffer Memory -!Edrivers/video/fbdev/fbmem.c +!Edrivers/video/fbdev/core/fbmem.c Frame Buffer Colormap -!Edrivers/video/fbdev/fbcmap.c +!Edrivers/video/fbdev/core/fbcmap.c Frame Buffer Video Mode Database -!Idrivers/video/fbdev/modedb.c -!Edrivers/video/fbdev/modedb.c +!Idrivers/video/fbdev/core/modedb.c +!Edrivers/video/fbdev/core/modedb.c Frame Buffer Macintosh Video Mode Database !Edrivers/video/fbdev/macmodes.c diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile index 8a79eec2113bd6..0284f2a12538c3 100644 --- a/drivers/video/fbdev/Makefile +++ b/drivers/video/fbdev/Makefile @@ -4,25 +4,11 @@ # Each configuration option enables a list of files. -obj-y += fb_notify.o -obj-$(CONFIG_FB) += fb.o -fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ - modedb.o fbcvt.o -fb-objs := $(fb-y) +obj-y += core/ obj-$(CONFIG_EXYNOS_VIDEO) += exynos/ -obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o -obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o -obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o -obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o -obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o -obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o -obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o -obj-$(CONFIG_FB_SVGALIB) += svgalib.o obj-$(CONFIG_FB_MACMODES) += macmodes.o -obj-$(CONFIG_FB_DDC) += fb_ddc.o -obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o obj-$(CONFIG_FB_WMT_GE_ROPS) += wmt_ge_rops.o # Hardware specific drivers go first diff --git a/drivers/video/fbdev/aty/mach64_cursor.c b/drivers/video/fbdev/aty/mach64_cursor.c index 0fe02e22d9a436..2fa0317ab3c7d1 100644 --- a/drivers/video/fbdev/aty/mach64_cursor.c +++ b/drivers/video/fbdev/aty/mach64_cursor.c @@ -5,7 +5,7 @@ #include #include #include -#include "../fb_draw.h" +#include "../core/fb_draw.h" #include diff --git a/drivers/video/fbdev/core/Makefile b/drivers/video/fbdev/core/Makefile new file mode 100644 index 00000000000000..fa306538dac29a --- /dev/null +++ b/drivers/video/fbdev/core/Makefile @@ -0,0 +1,16 @@ +obj-y += fb_notify.o +obj-$(CONFIG_FB) += fb.o +fb-y := fbmem.o fbmon.o fbcmap.o fbsysfs.o \ + modedb.o fbcvt.o +fb-objs := $(fb-y) + +obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o +obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o +obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o +obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o +obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o +obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o +obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o +obj-$(CONFIG_FB_SVGALIB) += svgalib.o +obj-$(CONFIG_FB_DDC) += fb_ddc.o +obj-$(CONFIG_FB_DEFERRED_IO) += fb_defio.o diff --git a/drivers/video/fbdev/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c similarity index 100% rename from drivers/video/fbdev/cfbcopyarea.c rename to drivers/video/fbdev/core/cfbcopyarea.c diff --git a/drivers/video/fbdev/cfbfillrect.c b/drivers/video/fbdev/core/cfbfillrect.c similarity index 100% rename from drivers/video/fbdev/cfbfillrect.c rename to drivers/video/fbdev/core/cfbfillrect.c diff --git a/drivers/video/fbdev/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c similarity index 100% rename from drivers/video/fbdev/cfbimgblt.c rename to drivers/video/fbdev/core/cfbimgblt.c diff --git a/drivers/video/fbdev/fb_ddc.c b/drivers/video/fbdev/core/fb_ddc.c similarity index 99% rename from drivers/video/fbdev/fb_ddc.c rename to drivers/video/fbdev/core/fb_ddc.c index 2b106f046fdee8..94322ccfeddecb 100644 --- a/drivers/video/fbdev/fb_ddc.c +++ b/drivers/video/fbdev/core/fb_ddc.c @@ -15,7 +15,7 @@ #include #include -#include "edid.h" +#include "../edid.h" #define DDC_ADDR 0x50 diff --git a/drivers/video/fbdev/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c similarity index 100% rename from drivers/video/fbdev/fb_defio.c rename to drivers/video/fbdev/core/fb_defio.c diff --git a/drivers/video/fbdev/fb_draw.h b/drivers/video/fbdev/core/fb_draw.h similarity index 100% rename from drivers/video/fbdev/fb_draw.h rename to drivers/video/fbdev/core/fb_draw.h diff --git a/drivers/video/fbdev/fb_notify.c b/drivers/video/fbdev/core/fb_notify.c similarity index 100% rename from drivers/video/fbdev/fb_notify.c rename to drivers/video/fbdev/core/fb_notify.c diff --git a/drivers/video/fbdev/fb_sys_fops.c b/drivers/video/fbdev/core/fb_sys_fops.c similarity index 100% rename from drivers/video/fbdev/fb_sys_fops.c rename to drivers/video/fbdev/core/fb_sys_fops.c diff --git a/drivers/video/fbdev/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c similarity index 100% rename from drivers/video/fbdev/fbcmap.c rename to drivers/video/fbdev/core/fbcmap.c diff --git a/drivers/video/fbdev/fbcvt.c b/drivers/video/fbdev/core/fbcvt.c similarity index 100% rename from drivers/video/fbdev/fbcvt.c rename to drivers/video/fbdev/core/fbcvt.c diff --git a/drivers/video/fbdev/fbmem.c b/drivers/video/fbdev/core/fbmem.c similarity index 100% rename from drivers/video/fbdev/fbmem.c rename to drivers/video/fbdev/core/fbmem.c diff --git a/drivers/video/fbdev/fbmon.c b/drivers/video/fbdev/core/fbmon.c similarity index 99% rename from drivers/video/fbdev/fbmon.c rename to drivers/video/fbdev/core/fbmon.c index 6103fa6fb54f08..c204ebe6187e9f 100644 --- a/drivers/video/fbdev/fbmon.c +++ b/drivers/video/fbdev/core/fbmon.c @@ -37,7 +37,7 @@ #include #include #endif -#include "edid.h" +#include "../edid.h" /* * EDID parser diff --git a/drivers/video/fbdev/fbsysfs.c b/drivers/video/fbdev/core/fbsysfs.c similarity index 100% rename from drivers/video/fbdev/fbsysfs.c rename to drivers/video/fbdev/core/fbsysfs.c diff --git a/drivers/video/fbdev/modedb.c b/drivers/video/fbdev/core/modedb.c similarity index 100% rename from drivers/video/fbdev/modedb.c rename to drivers/video/fbdev/core/modedb.c diff --git a/drivers/video/fbdev/svgalib.c b/drivers/video/fbdev/core/svgalib.c similarity index 100% rename from drivers/video/fbdev/svgalib.c rename to drivers/video/fbdev/core/svgalib.c diff --git a/drivers/video/fbdev/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c similarity index 100% rename from drivers/video/fbdev/syscopyarea.c rename to drivers/video/fbdev/core/syscopyarea.c diff --git a/drivers/video/fbdev/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c similarity index 100% rename from drivers/video/fbdev/sysfillrect.c rename to drivers/video/fbdev/core/sysfillrect.c diff --git a/drivers/video/fbdev/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c similarity index 100% rename from drivers/video/fbdev/sysimgblt.c rename to drivers/video/fbdev/core/sysimgblt.c diff --git a/drivers/video/fbdev/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c index b0a9f34b2e01b7..9df6fe78a44b28 100644 --- a/drivers/video/fbdev/wmt_ge_rops.c +++ b/drivers/video/fbdev/wmt_ge_rops.c @@ -18,7 +18,7 @@ #include #include #include -#include "fb_draw.h" +#include "core/fb_draw.h" #define GE_COMMAND_OFF 0x00 #define GE_DEPTH_OFF 0x04 From 776bbb97e0a37fe67bd0870e5aa4845af856b872 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 13 Feb 2014 16:32:13 +0200 Subject: [PATCH 229/279] video: Kconfig: move drm and fb into separate menus At the moment the "Device Drivers / Graphics support" kernel config page looks rather messy, with DRM and fbdev driver selections on the same page, some on the top level Graphics support page, some under their respective subsystems. If I'm not mistaken, this is caused by the drivers depending on other things than DRM or FB, which causes Kconfig to arrange the options in not-so-neat manner. Both DRM and FB have a main menuconfig option for the whole DRM or FB subsystem. Optimally, this would be enough to arrange all DRM and FB options under the respective subsystem, but for whatever reason this doesn't work reliably. This patch adds an explicit submenu for DRM and FB, making it much clearer which options are related to FB, and which to DRM. Signed-off-by: Tomi Valkeinen Acked-by: Laurent Pinchart Acked-by: Geert Uytterhoeven Acked-by: Rob Clark Reviewed-by: Jingoo Han Acked-by: Daniel Vetter --- drivers/video/Kconfig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ab05d6cb0796fb..c7b4f0f927b1b7 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -21,9 +21,13 @@ source "drivers/gpu/vga/Kconfig" source "drivers/gpu/host1x/Kconfig" +menu "Direct Rendering Manager" source "drivers/gpu/drm/Kconfig" +endmenu +menu "Frame buffer Devices" source "drivers/video/fbdev/Kconfig" +endmenu source "drivers/video/backlight/Kconfig" From c7a6d35e463caacab08ca0333bdec5b8bdce8bbb Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Tue, 15 Apr 2014 09:12:54 +0800 Subject: [PATCH 230/279] raid5: fix a race of stripe count check I hit another BUG_ON with e240c1839d11152b0355442. In __get_priority_stripe(), stripe count equals to 0 initially. Between atomic_inc and BUG_ON, get_active_stripe() finds the stripe. So the stripe count isn't 1 any more. V2: keeps the BUG_ON suggested by Neil. Signed-off-by: Shaohua Li Signed-off-by: NeilBrown --- drivers/md/raid5.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 25247a8529124f..ad1b9bea446ebd 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4370,8 +4370,7 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf, int group) sh->group = NULL; } list_del_init(&sh->lru); - atomic_inc(&sh->count); - BUG_ON(atomic_read(&sh->count) != 1); + BUG_ON(atomic_inc_return(&sh->count) != 1); return sh; } From ea431643d6c38728195e2c456801c3ef66bb9991 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 17 Apr 2014 10:25:53 +0200 Subject: [PATCH 231/279] x86/mce: Fix CMCI preemption bugs The following commit: 27f6c573e0f7 ("x86, CMCI: Add proper detection of end of CMCI storms") Added two preemption bugs: - machine_check_poll() does a get_cpu_var() without a matching put_cpu_var(), which causes preemption imbalance and crashes upon bootup. - it does percpu ops without disabling preemption. Preemption is not disabled due to the mistaken use of a raw spinlock. To fix these bugs fix the imbalance and change cmci_discover_lock to a regular spinlock. Reported-by: Owen Kibel Reported-by: Linus Torvalds Signed-off-by: Ingo Molnar Cc: Chen, Gong Cc: Josh Boyer Cc: Tony Luck Cc: Peter Zijlstra Cc: Alexander Todorov Cc: Borislav Petkov Link: http://lkml.kernel.org/n/tip-jtjptvgigpfkpvtQxpEk1at2@git.kernel.org Signed-off-by: Ingo Molnar -- arch/x86/kernel/cpu/mcheck/mce.c | 4 +--- arch/x86/kernel/cpu/mcheck/mce_intel.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 12 deletions(-) --- arch/x86/kernel/cpu/mcheck/mce.c | 4 +--- arch/x86/kernel/cpu/mcheck/mce_intel.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index eeee23ff75ef8d..68317c80de7f65 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -598,7 +598,6 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) { struct mce m; int i; - unsigned long *v; this_cpu_inc(mce_poll_count); @@ -618,8 +617,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) if (!(m.status & MCI_STATUS_VAL)) continue; - v = &get_cpu_var(mce_polled_error); - set_bit(0, v); + this_cpu_write(mce_polled_error, 1); /* * Uncorrected or signalled events are handled by the exception * handler when it is enabled, so don't process those here. diff --git a/arch/x86/kernel/cpu/mcheck/mce_intel.c b/arch/x86/kernel/cpu/mcheck/mce_intel.c index 3bdb95ae8c430f..9a316b21df8bd4 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_intel.c +++ b/arch/x86/kernel/cpu/mcheck/mce_intel.c @@ -42,7 +42,7 @@ static DEFINE_PER_CPU(mce_banks_t, mce_banks_owned); * cmci_discover_lock protects against parallel discovery attempts * which could race against each other. */ -static DEFINE_RAW_SPINLOCK(cmci_discover_lock); +static DEFINE_SPINLOCK(cmci_discover_lock); #define CMCI_THRESHOLD 1 #define CMCI_POLL_INTERVAL (30 * HZ) @@ -144,14 +144,14 @@ static void cmci_storm_disable_banks(void) int bank; u64 val; - raw_spin_lock_irqsave(&cmci_discover_lock, flags); + spin_lock_irqsave(&cmci_discover_lock, flags); owned = __get_cpu_var(mce_banks_owned); for_each_set_bit(bank, owned, MAX_NR_BANKS) { rdmsrl(MSR_IA32_MCx_CTL2(bank), val); val &= ~MCI_CTL2_CMCI_EN; wrmsrl(MSR_IA32_MCx_CTL2(bank), val); } - raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); + spin_unlock_irqrestore(&cmci_discover_lock, flags); } static bool cmci_storm_detect(void) @@ -211,7 +211,7 @@ static void cmci_discover(int banks) int i; int bios_wrong_thresh = 0; - raw_spin_lock_irqsave(&cmci_discover_lock, flags); + spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) { u64 val; int bios_zero_thresh = 0; @@ -266,7 +266,7 @@ static void cmci_discover(int banks) WARN_ON(!test_bit(i, __get_cpu_var(mce_poll_banks))); } } - raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); + spin_unlock_irqrestore(&cmci_discover_lock, flags); if (mca_cfg.bios_cmci_threshold && bios_wrong_thresh) { pr_info_once( "bios_cmci_threshold: Some banks do not have valid thresholds set\n"); @@ -316,10 +316,10 @@ void cmci_clear(void) if (!cmci_supported(&banks)) return; - raw_spin_lock_irqsave(&cmci_discover_lock, flags); + spin_lock_irqsave(&cmci_discover_lock, flags); for (i = 0; i < banks; i++) __cmci_disable_bank(i); - raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); + spin_unlock_irqrestore(&cmci_discover_lock, flags); } static void cmci_rediscover_work_func(void *arg) @@ -360,9 +360,9 @@ void cmci_disable_bank(int bank) if (!cmci_supported(&banks)) return; - raw_spin_lock_irqsave(&cmci_discover_lock, flags); + spin_lock_irqsave(&cmci_discover_lock, flags); __cmci_disable_bank(bank); - raw_spin_unlock_irqrestore(&cmci_discover_lock, flags); + spin_unlock_irqrestore(&cmci_discover_lock, flags); } static void intel_init_cmci(void) From a1d9a3231eac4117cadaf4b6bba5b2902c15a33e Mon Sep 17 00:00:00 2001 From: Kirill Tkhai Date: Thu, 10 Apr 2014 17:38:36 +0400 Subject: [PATCH 232/279] sched: Check for stop task appearance when balancing happens We need to do it like we do for the other higher priority classes.. Signed-off-by: Kirill Tkhai Cc: Michael wang Cc: Sasha Levin Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/336561397137116@web27h.yandex.ru Signed-off-by: Ingo Molnar --- kernel/sched/deadline.c | 11 ++++++++++- kernel/sched/fair.c | 3 ++- kernel/sched/rt.c | 7 ++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 27ef4092552533..b08095786cb8ff 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -1021,8 +1021,17 @@ struct task_struct *pick_next_task_dl(struct rq *rq, struct task_struct *prev) dl_rq = &rq->dl; - if (need_pull_dl_task(rq, prev)) + if (need_pull_dl_task(rq, prev)) { pull_dl_task(rq); + /* + * pull_rt_task() can drop (and re-acquire) rq->lock; this + * means a stop task can slip in, in which case we need to + * re-start task selection. + */ + if (rq->stop && rq->stop->on_rq) + return RETRY_TASK; + } + /* * When prev is DL, we may throttle it in put_prev_task(). * So, we update time before we check for dl_nr_running. diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 4f14a656a7200e..7570dd969c2838 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -6728,7 +6728,8 @@ static int idle_balance(struct rq *this_rq) out: /* Is there a task of a high priority class? */ if (this_rq->nr_running != this_rq->cfs.h_nr_running && - (this_rq->dl.dl_nr_running || + ((this_rq->stop && this_rq->stop->on_rq) || + this_rq->dl.dl_nr_running || (this_rq->rt.rt_nr_running && !rt_rq_throttled(&this_rq->rt)))) pulled_task = -1; diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index d8cdf1618551c8..bd2267ad404fa7 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1362,10 +1362,11 @@ pick_next_task_rt(struct rq *rq, struct task_struct *prev) pull_rt_task(rq); /* * pull_rt_task() can drop (and re-acquire) rq->lock; this - * means a dl task can slip in, in which case we need to - * re-start task selection. + * means a dl or stop task can slip in, in which case we need + * to re-start task selection. */ - if (unlikely(rq->dl.dl_nr_running)) + if (unlikely((rq->stop && rq->stop->on_rq) || + rq->dl.dl_nr_running)) return RETRY_TASK; } From 57700ad1f2f21d5d7ab7ee0e58d11b5954852434 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Apr 2014 22:29:03 -0400 Subject: [PATCH 233/279] drm/radeon: disable mclk dpm on R7 260X Setting higher mclks seems to cause stability issues on some R7 260X boards. Disable it for now for stability until we find a proper fix. bug: https://bugs.freedesktop.org/show_bug.cgi?id=75992 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/ci_dpm.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index cad89a97752709..6d395ec25c1379 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -5146,6 +5146,10 @@ int ci_dpm_init(struct radeon_device *rdev) pi->mclk_dpm_key_disabled = 0; pi->pcie_dpm_key_disabled = 0; + /* mclk dpm is unstable on some R7 260X cards */ + if (rdev->pdev->device == 0x6658) + pi->mclk_dpm_key_disabled = 1; + pi->caps_sclk_ds = true; pi->mclk_strobe_mode_threshold = 40000; From 90c4cde9d5a2bb6239cb3e253bb3832ed89dc75c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Apr 2014 22:29:01 -0400 Subject: [PATCH 234/279] drm/radeon: fix runpm handling on APUs (v4) Don't try and runtime suspend the APU in PX systems. We only want to power down the dGPU. v2: fix harder v3: fix stupid typo v4: consolidate runpm enablement to a single flag bugs: https://bugs.freedesktop.org/show_bug.cgi?id=75127 https://bugzilla.kernel.org/show_bug.cgi?id=72701 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon.h | 1 + drivers/gpu/drm/radeon/radeon_atpx_handler.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 19 ++++++++-------- drivers/gpu/drm/radeon/radeon_drv.c | 24 ++++---------------- drivers/gpu/drm/radeon/radeon_family.h | 1 + drivers/gpu/drm/radeon/radeon_kms.c | 14 ++++++++---- 6 files changed, 27 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f21db7a0b34d7d..7014bdd688ce6d 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2321,6 +2321,7 @@ struct radeon_device { bool have_disp_power_ref; }; +bool radeon_is_px(struct drm_device *dev); int radeon_device_init(struct radeon_device *rdev, struct drm_device *ddev, struct pci_dev *pdev, diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index fa9a9c02751ea8..dedea72f48c45b 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -59,7 +59,7 @@ struct atpx_mux { u16 mux; } __packed; -bool radeon_is_px(void) { +bool radeon_has_atpx(void) { return radeon_atpx_priv.atpx_detected; } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 835516d2d2576a..511fe26198e4a3 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -102,11 +102,14 @@ static const char radeon_family_name[][16] = { "LAST", }; -#if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_is_px(void); -#else -static inline bool radeon_is_px(void) { return false; } -#endif +bool radeon_is_px(struct drm_device *dev) +{ + struct radeon_device *rdev = dev->dev_private; + + if (rdev->flags & RADEON_IS_PX) + return true; + return false; +} /** * radeon_program_register_sequence - program an array of registers. @@ -1082,7 +1085,7 @@ static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switchero { struct drm_device *dev = pci_get_drvdata(pdev); - if (radeon_is_px() && state == VGA_SWITCHEROO_OFF) + if (radeon_is_px(dev) && state == VGA_SWITCHEROO_OFF) return; if (state == VGA_SWITCHEROO_ON) { @@ -1301,9 +1304,7 @@ int radeon_device_init(struct radeon_device *rdev, * ignore it */ vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode); - if (radeon_runtime_pm == 1) - runtime = true; - if ((radeon_runtime_pm == -1) && radeon_is_px()) + if (rdev->flags & RADEON_IS_PX) runtime = true; vga_switcheroo_register_client(rdev->pdev, &radeon_switcheroo_ops, runtime); if (runtime) diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index d0eba48dd74e1d..25127ba44ed92c 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -115,6 +115,7 @@ extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, int crtc, unsigned int flags, int *vpos, int *hpos, ktime_t *stime, ktime_t *etime); +extern bool radeon_is_px(struct drm_device *dev); extern const struct drm_ioctl_desc radeon_ioctls_kms[]; extern int radeon_max_kms_ioctl; int radeon_mmap(struct file *filp, struct vm_area_struct *vma); @@ -144,11 +145,9 @@ void radeon_debugfs_cleanup(struct drm_minor *minor); #if defined(CONFIG_VGA_SWITCHEROO) void radeon_register_atpx_handler(void); void radeon_unregister_atpx_handler(void); -bool radeon_is_px(void); #else static inline void radeon_register_atpx_handler(void) {} static inline void radeon_unregister_atpx_handler(void) {} -static inline bool radeon_is_px(void) { return false; } #endif int radeon_no_wb; @@ -405,12 +404,7 @@ static int radeon_pmops_runtime_suspend(struct device *dev) struct drm_device *drm_dev = pci_get_drvdata(pdev); int ret; - if (radeon_runtime_pm == 0) { - pm_runtime_forbid(dev); - return -EBUSY; - } - - if (radeon_runtime_pm == -1 && !radeon_is_px()) { + if (!radeon_is_px(drm_dev)) { pm_runtime_forbid(dev); return -EBUSY; } @@ -434,10 +428,7 @@ static int radeon_pmops_runtime_resume(struct device *dev) struct drm_device *drm_dev = pci_get_drvdata(pdev); int ret; - if (radeon_runtime_pm == 0) - return -EINVAL; - - if (radeon_runtime_pm == -1 && !radeon_is_px()) + if (!radeon_is_px(drm_dev)) return -EINVAL; drm_dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; @@ -462,14 +453,7 @@ static int radeon_pmops_runtime_idle(struct device *dev) struct drm_device *drm_dev = pci_get_drvdata(pdev); struct drm_crtc *crtc; - if (radeon_runtime_pm == 0) { - pm_runtime_forbid(dev); - return -EBUSY; - } - - /* are we PX enabled? */ - if (radeon_runtime_pm == -1 && !radeon_is_px()) { - DRM_DEBUG_DRIVER("failing to power off - not px\n"); + if (!radeon_is_px(drm_dev)) { pm_runtime_forbid(dev); return -EBUSY; } diff --git a/drivers/gpu/drm/radeon/radeon_family.h b/drivers/gpu/drm/radeon/radeon_family.h index 614ad549297f28..9da5da4ffd1769 100644 --- a/drivers/gpu/drm/radeon/radeon_family.h +++ b/drivers/gpu/drm/radeon/radeon_family.h @@ -115,6 +115,7 @@ enum radeon_chip_flags { RADEON_NEW_MEMMAP = 0x00400000UL, RADEON_IS_PCI = 0x00800000UL, RADEON_IS_IGPGART = 0x01000000UL, + RADEON_IS_PX = 0x02000000UL, }; #endif diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 3e49342a20e602..9337820e4d378a 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -35,9 +35,9 @@ #include #if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_is_px(void); +bool radeon_has_atpx(void); #else -static inline bool radeon_is_px(void) { return false; } +static inline bool radeon_has_atpx(void) { return false; } #endif /** @@ -107,6 +107,13 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) flags |= RADEON_IS_PCI; } + if (radeon_runtime_pm == 1) + flags |= RADEON_IS_PX; + else if ((radeon_runtime_pm == -1) && + radeon_has_atpx() && + ((flags & RADEON_IS_IGP) == 0)) + flags |= RADEON_IS_PX; + /* radeon_device_init should report only fatal error * like memory allocation failure or iomapping failure, * or memory manager initialization failure, it must @@ -137,8 +144,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) "Error during ACPI methods call\n"); } - if ((radeon_runtime_pm == 1) || - ((radeon_runtime_pm == -1) && radeon_is_px())) { + if (radeon_is_px(dev)) { pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); pm_runtime_set_active(dev->dev); From 6abc6d5c73b22ccf2e5688df6a2eb02ee8dfdf59 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 10 Apr 2014 22:29:02 -0400 Subject: [PATCH 235/279] drm/radeon: update CI DPM powertune settings As per internal recommendations. Signed-off-by: Alex Deucher --- drivers/gpu/drm/radeon/ci_dpm.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 6d395ec25c1379..18e91ee2c8b75c 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -202,24 +202,29 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev) struct ci_power_info *pi = ci_get_pi(rdev); switch (rdev->pdev->device) { + case 0x6649: case 0x6650: + case 0x6651: case 0x6658: case 0x665C: + case 0x665D: default: pi->powertune_defaults = &defaults_bonaire_xt; break; - case 0x6651: - case 0x665D: - pi->powertune_defaults = &defaults_bonaire_pro; - break; case 0x6640: - pi->powertune_defaults = &defaults_saturn_xt; - break; case 0x6641: - pi->powertune_defaults = &defaults_saturn_pro; + case 0x6646: + case 0x6647: + pi->powertune_defaults = &defaults_saturn_xt; break; case 0x67B8: case 0x67B0: + pi->powertune_defaults = &defaults_hawaii_xt; + break; + case 0x67BA: + case 0x67B1: + pi->powertune_defaults = &defaults_hawaii_pro; + break; case 0x67A0: case 0x67A1: case 0x67A2: @@ -228,11 +233,7 @@ static void ci_initialize_powertune_defaults(struct radeon_device *rdev) case 0x67AA: case 0x67B9: case 0x67BE: - pi->powertune_defaults = &defaults_hawaii_xt; - break; - case 0x67BA: - case 0x67B1: - pi->powertune_defaults = &defaults_hawaii_pro; + pi->powertune_defaults = &defaults_bonaire_xt; break; } From 5fb9cc4d8b1639b9a7487c1ee7b2b0c52877327d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 4 Apr 2014 13:45:42 +0200 Subject: [PATCH 236/279] drm/radeon: apply more strict limits for PLL params v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Letting post and refernce divider get to big is bad for signal stability. v2: increase the limit to 210 Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_display.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 386cfa4c194dc4..2f42912031ac97 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -937,6 +937,9 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, } post_div = post_div_best; + /* limit reference * post divider to a maximum */ + ref_div_max = min(210 / post_div, ref_div_max); + /* get matching reference and feedback divider */ ref_div = max(den / post_div, 1u); fb_div = nom; From 1ebe92802eaf0569784dce843bc28a78842d236c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 11 Apr 2014 11:21:49 -0400 Subject: [PATCH 237/279] drm/radeon: add support for newer mc ucode on SI (v2) May fix stability issues with some newer cards. v2: print out mc firmware version used and size Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_ucode.h | 3 +++ drivers/gpu/drm/radeon/si.c | 35 +++++++++++++++++---------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index a77cd274dfc3fb..f4155484b39580 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h @@ -57,6 +57,9 @@ #define BTC_MC_UCODE_SIZE 6024 #define CAYMAN_MC_UCODE_SIZE 6037 #define SI_MC_UCODE_SIZE 7769 +#define TAHITI_MC_UCODE_SIZE 7808 +#define PITCAIRN_MC_UCODE_SIZE 7775 +#define VERDE_MC_UCODE_SIZE 7875 #define OLAND_MC_UCODE_SIZE 7863 #define CIK_MC_UCODE_SIZE 7866 #define HAWAII_MC_UCODE_SIZE 7933 diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index d589475fe9e69b..86f8c9c87f5cf9 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -39,30 +39,35 @@ MODULE_FIRMWARE("radeon/TAHITI_pfp.bin"); MODULE_FIRMWARE("radeon/TAHITI_me.bin"); MODULE_FIRMWARE("radeon/TAHITI_ce.bin"); MODULE_FIRMWARE("radeon/TAHITI_mc.bin"); +MODULE_FIRMWARE("radeon/TAHITI_mc2.bin"); MODULE_FIRMWARE("radeon/TAHITI_rlc.bin"); MODULE_FIRMWARE("radeon/TAHITI_smc.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_me.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin"); +MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin"); MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin"); MODULE_FIRMWARE("radeon/VERDE_pfp.bin"); MODULE_FIRMWARE("radeon/VERDE_me.bin"); MODULE_FIRMWARE("radeon/VERDE_ce.bin"); MODULE_FIRMWARE("radeon/VERDE_mc.bin"); +MODULE_FIRMWARE("radeon/VERDE_mc2.bin"); MODULE_FIRMWARE("radeon/VERDE_rlc.bin"); MODULE_FIRMWARE("radeon/VERDE_smc.bin"); MODULE_FIRMWARE("radeon/OLAND_pfp.bin"); MODULE_FIRMWARE("radeon/OLAND_me.bin"); MODULE_FIRMWARE("radeon/OLAND_ce.bin"); MODULE_FIRMWARE("radeon/OLAND_mc.bin"); +MODULE_FIRMWARE("radeon/OLAND_mc2.bin"); MODULE_FIRMWARE("radeon/OLAND_rlc.bin"); MODULE_FIRMWARE("radeon/OLAND_smc.bin"); MODULE_FIRMWARE("radeon/HAINAN_pfp.bin"); MODULE_FIRMWARE("radeon/HAINAN_me.bin"); MODULE_FIRMWARE("radeon/HAINAN_ce.bin"); MODULE_FIRMWARE("radeon/HAINAN_mc.bin"); +MODULE_FIRMWARE("radeon/HAINAN_mc2.bin"); MODULE_FIRMWARE("radeon/HAINAN_rlc.bin"); MODULE_FIRMWARE("radeon/HAINAN_smc.bin"); @@ -1467,7 +1472,7 @@ int si_mc_load_microcode(struct radeon_device *rdev) const __be32 *fw_data; u32 running, blackout = 0; u32 *io_mc_regs; - int i, ucode_size, regs_size; + int i, regs_size, ucode_size = rdev->mc_fw->size / 4; if (!rdev->mc_fw) return -EINVAL; @@ -1475,28 +1480,23 @@ int si_mc_load_microcode(struct radeon_device *rdev) switch (rdev->family) { case CHIP_TAHITI: io_mc_regs = (u32 *)&tahiti_io_mc_regs; - ucode_size = SI_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_PITCAIRN: io_mc_regs = (u32 *)&pitcairn_io_mc_regs; - ucode_size = SI_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_VERDE: default: io_mc_regs = (u32 *)&verde_io_mc_regs; - ucode_size = SI_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_OLAND: io_mc_regs = (u32 *)&oland_io_mc_regs; - ucode_size = OLAND_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; case CHIP_HAINAN: io_mc_regs = (u32 *)&hainan_io_mc_regs; - ucode_size = OLAND_MC_UCODE_SIZE; regs_size = TAHITI_IO_MC_REGS_SIZE; break; } @@ -1552,7 +1552,7 @@ static int si_init_microcode(struct radeon_device *rdev) const char *chip_name; const char *rlc_chip_name; size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size; - size_t smc_req_size; + size_t smc_req_size, mc2_req_size; char fw_name[30]; int err; @@ -1567,6 +1567,7 @@ static int si_init_microcode(struct radeon_device *rdev) ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; mc_req_size = SI_MC_UCODE_SIZE * 4; + mc2_req_size = TAHITI_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4); break; case CHIP_PITCAIRN: @@ -1577,6 +1578,7 @@ static int si_init_microcode(struct radeon_device *rdev) ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; mc_req_size = SI_MC_UCODE_SIZE * 4; + mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4); break; case CHIP_VERDE: @@ -1587,6 +1589,7 @@ static int si_init_microcode(struct radeon_device *rdev) ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; mc_req_size = SI_MC_UCODE_SIZE * 4; + mc2_req_size = VERDE_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4); break; case CHIP_OLAND: @@ -1596,7 +1599,7 @@ static int si_init_microcode(struct radeon_device *rdev) me_req_size = SI_PM4_UCODE_SIZE * 4; ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; - mc_req_size = OLAND_MC_UCODE_SIZE * 4; + mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4); break; case CHIP_HAINAN: @@ -1606,7 +1609,7 @@ static int si_init_microcode(struct radeon_device *rdev) me_req_size = SI_PM4_UCODE_SIZE * 4; ce_req_size = SI_CE_UCODE_SIZE * 4; rlc_req_size = SI_RLC_UCODE_SIZE * 4; - mc_req_size = OLAND_MC_UCODE_SIZE * 4; + mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4; smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4); break; default: BUG(); @@ -1659,16 +1662,22 @@ static int si_init_microcode(struct radeon_device *rdev) err = -EINVAL; } - snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name); err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); - if (err) - goto out; - if (rdev->mc_fw->size != mc_req_size) { + if (err) { + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); + if (err) + goto out; + } + if ((rdev->mc_fw->size != mc_req_size) && + (rdev->mc_fw->size != mc2_req_size)) { printk(KERN_ERR "si_mc: Bogus length %zu in firmware \"%s\"\n", rdev->mc_fw->size, fw_name); err = -EINVAL; } + DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size); snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); From 277babc374f6ecab6af182554f5d9f35a7768755 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 11 Apr 2014 11:21:50 -0400 Subject: [PATCH 238/279] drm/radeon: add support for newer mc ucode on CI (v2) Fixes mclk stability on certain asics. v2: print out mc firmware version used and size bug: https://bugs.freedesktop.org/show_bug.cgi?id=75992 Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/cik.c | 26 +++++++++++++++++--------- drivers/gpu/drm/radeon/radeon_ucode.h | 4 +++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 745143c2358fc7..7e430450bac0ed 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -38,6 +38,7 @@ MODULE_FIRMWARE("radeon/BONAIRE_me.bin"); MODULE_FIRMWARE("radeon/BONAIRE_ce.bin"); MODULE_FIRMWARE("radeon/BONAIRE_mec.bin"); MODULE_FIRMWARE("radeon/BONAIRE_mc.bin"); +MODULE_FIRMWARE("radeon/BONAIRE_mc2.bin"); MODULE_FIRMWARE("radeon/BONAIRE_rlc.bin"); MODULE_FIRMWARE("radeon/BONAIRE_sdma.bin"); MODULE_FIRMWARE("radeon/BONAIRE_smc.bin"); @@ -46,6 +47,7 @@ MODULE_FIRMWARE("radeon/HAWAII_me.bin"); MODULE_FIRMWARE("radeon/HAWAII_ce.bin"); MODULE_FIRMWARE("radeon/HAWAII_mec.bin"); MODULE_FIRMWARE("radeon/HAWAII_mc.bin"); +MODULE_FIRMWARE("radeon/HAWAII_mc2.bin"); MODULE_FIRMWARE("radeon/HAWAII_rlc.bin"); MODULE_FIRMWARE("radeon/HAWAII_sdma.bin"); MODULE_FIRMWARE("radeon/HAWAII_smc.bin"); @@ -1703,7 +1705,7 @@ int ci_mc_load_microcode(struct radeon_device *rdev) const __be32 *fw_data; u32 running, blackout = 0; u32 *io_mc_regs; - int i, ucode_size, regs_size; + int i, regs_size, ucode_size = rdev->mc_fw->size / 4; if (!rdev->mc_fw) return -EINVAL; @@ -1711,12 +1713,10 @@ int ci_mc_load_microcode(struct radeon_device *rdev) switch (rdev->family) { case CHIP_BONAIRE: io_mc_regs = (u32 *)&bonaire_io_mc_regs; - ucode_size = CIK_MC_UCODE_SIZE; regs_size = BONAIRE_IO_MC_REGS_SIZE; break; case CHIP_HAWAII: io_mc_regs = (u32 *)&hawaii_io_mc_regs; - ucode_size = HAWAII_MC_UCODE_SIZE; regs_size = HAWAII_IO_MC_REGS_SIZE; break; default: @@ -1783,7 +1783,7 @@ static int cik_init_microcode(struct radeon_device *rdev) const char *chip_name; size_t pfp_req_size, me_req_size, ce_req_size, mec_req_size, rlc_req_size, mc_req_size = 0, - sdma_req_size, smc_req_size = 0; + sdma_req_size, smc_req_size = 0, mc2_req_size = 0; char fw_name[30]; int err; @@ -1797,7 +1797,8 @@ static int cik_init_microcode(struct radeon_device *rdev) ce_req_size = CIK_CE_UCODE_SIZE * 4; mec_req_size = CIK_MEC_UCODE_SIZE * 4; rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; - mc_req_size = CIK_MC_UCODE_SIZE * 4; + mc_req_size = BONAIRE_MC_UCODE_SIZE * 4; + mc2_req_size = BONAIRE_MC2_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; smc_req_size = ALIGN(BONAIRE_SMC_UCODE_SIZE, 4); break; @@ -1809,6 +1810,7 @@ static int cik_init_microcode(struct radeon_device *rdev) mec_req_size = CIK_MEC_UCODE_SIZE * 4; rlc_req_size = BONAIRE_RLC_UCODE_SIZE * 4; mc_req_size = HAWAII_MC_UCODE_SIZE * 4; + mc2_req_size = HAWAII_MC2_UCODE_SIZE * 4; sdma_req_size = CIK_SDMA_UCODE_SIZE * 4; smc_req_size = ALIGN(HAWAII_SMC_UCODE_SIZE, 4); break; @@ -1904,16 +1906,22 @@ static int cik_init_microcode(struct radeon_device *rdev) /* No SMC, MC ucode on APUs */ if (!(rdev->flags & RADEON_IS_IGP)) { - snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name); err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); - if (err) - goto out; - if (rdev->mc_fw->size != mc_req_size) { + if (err) { + snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name); + err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev); + if (err) + goto out; + } + if ((rdev->mc_fw->size != mc_req_size) && + (rdev->mc_fw->size != mc2_req_size)){ printk(KERN_ERR "cik_mc: Bogus length %zu in firmware \"%s\"\n", rdev->mc_fw->size, fw_name); err = -EINVAL; } + DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size); snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name); err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); diff --git a/drivers/gpu/drm/radeon/radeon_ucode.h b/drivers/gpu/drm/radeon/radeon_ucode.h index f4155484b39580..58d12938c0b80b 100644 --- a/drivers/gpu/drm/radeon/radeon_ucode.h +++ b/drivers/gpu/drm/radeon/radeon_ucode.h @@ -61,8 +61,10 @@ #define PITCAIRN_MC_UCODE_SIZE 7775 #define VERDE_MC_UCODE_SIZE 7875 #define OLAND_MC_UCODE_SIZE 7863 -#define CIK_MC_UCODE_SIZE 7866 +#define BONAIRE_MC_UCODE_SIZE 7866 +#define BONAIRE_MC2_UCODE_SIZE 7948 #define HAWAII_MC_UCODE_SIZE 7933 +#define HAWAII_MC2_UCODE_SIZE 8091 /* SDMA */ #define CIK_SDMA_UCODE_SIZE 1050 From 7e1858f9aff7d608b3d0abad4bda0130de887b89 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 11 Apr 2014 11:21:51 -0400 Subject: [PATCH 239/279] drm/radeon: re-enable mclk dpm on R7 260X asics If the new mc ucode is available. Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/ci_dpm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index 18e91ee2c8b75c..10dae4106c08e3 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -21,8 +21,10 @@ * */ +#include #include "drmP.h" #include "radeon.h" +#include "radeon_ucode.h" #include "cikd.h" #include "r600_dpm.h" #include "ci_dpm.h" @@ -5147,9 +5149,11 @@ int ci_dpm_init(struct radeon_device *rdev) pi->mclk_dpm_key_disabled = 0; pi->pcie_dpm_key_disabled = 0; - /* mclk dpm is unstable on some R7 260X cards */ - if (rdev->pdev->device == 0x6658) + /* mclk dpm is unstable on some R7 260X cards with the old mc ucode */ + if ((rdev->pdev->device == 0x6658) && + (rdev->mc_fw->size == (BONAIRE_MC_UCODE_SIZE * 4))) { pi->mclk_dpm_key_disabled = 1; + } pi->caps_sclk_ds = true; From 681941c1790b92207334d08ee017007685f35438 Mon Sep 17 00:00:00 2001 From: Christoph Jaeger Date: Tue, 15 Apr 2014 00:10:22 +0200 Subject: [PATCH 240/279] drm/radeon: fix VCE fence command Due to a type mismatch that causes an implicit type conversion, the upper 32 bits of the GPU address have been zeroed out when adding to the command buffer. Picked up by Coverity - CID 1198624. Signed-off-by: Christoph Jaeger --- drivers/gpu/drm/radeon/radeon_vce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_vce.c b/drivers/gpu/drm/radeon/radeon_vce.c index 76e9904bc5377c..ced53dd03e7c1f 100644 --- a/drivers/gpu/drm/radeon/radeon_vce.c +++ b/drivers/gpu/drm/radeon/radeon_vce.c @@ -613,7 +613,7 @@ void radeon_vce_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence) { struct radeon_ring *ring = &rdev->ring[fence->ring]; - uint32_t addr = rdev->fence_drv[fence->ring].gpu_addr; + uint64_t addr = rdev->fence_drv[fence->ring].gpu_addr; radeon_ring_write(ring, VCE_CMD_FENCE); radeon_ring_write(ring, addr); From 74073c9dd29905645feb6dee03c144657a9844cd Mon Sep 17 00:00:00 2001 From: Quentin Casasnovas Date: Tue, 18 Mar 2014 17:16:52 +0100 Subject: [PATCH 241/279] drm/radeon: memory leak on bo reservation failure. v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On bo reservation failure, we end up leaking fpriv. v2 (chk): rebased and added missing free on vm failure as well Fixes: 5e386b574cf7e1 ("drm/radeon: fix missing bo reservation") Cc: stable@vger.kernel.org Cc: Christian König Cc: Alex Deucher Signed-off-by: Quentin Casasnovas Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_kms.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index 9337820e4d378a..fb3d13f693ddb1 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -574,12 +574,17 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) } r = radeon_vm_init(rdev, &fpriv->vm); - if (r) + if (r) { + kfree(fpriv); return r; + } r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false); - if (r) + if (r) { + radeon_vm_fini(rdev, &fpriv->vm); + kfree(fpriv); return r; + } /* map the ib pool buffer read only into * virtual address space */ From f8a2645ecede4eaf90b3d785f2805c8ecb76d43e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 16 Apr 2014 11:54:21 +0200 Subject: [PATCH 242/279] drm/radeon: improve PLL params if we don't match exactly v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we might be quite off on older chipsets. v2: keep ref_div minimum Signed-off-by: Christian König --- drivers/gpu/drm/radeon/radeon_display.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 2f42912031ac97..063d4255137fad 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -865,7 +865,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, unsigned post_div_min, post_div_max, post_div; unsigned ref_div_min, ref_div_max, ref_div; unsigned post_div_best, diff_best; - unsigned nom, den, tmp; + unsigned nom, den; /* determine allowed feedback divider range */ fb_div_min = pll->min_feedback_div; @@ -941,22 +941,23 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, ref_div_max = min(210 / post_div, ref_div_max); /* get matching reference and feedback divider */ - ref_div = max(den / post_div, 1u); - fb_div = nom; + ref_div = max(DIV_ROUND_CLOSEST(den, post_div), 1u); + fb_div = DIV_ROUND_CLOSEST(nom * ref_div * post_div, den); /* we're almost done, but reference and feedback divider might be to large now */ - tmp = ref_div; + nom = fb_div; + den = ref_div; if (fb_div > fb_div_max) { - ref_div = ref_div * fb_div_max / fb_div; + ref_div = DIV_ROUND_CLOSEST(den * fb_div_max, nom); fb_div = fb_div_max; } if (ref_div > ref_div_max) { ref_div = ref_div_max; - fb_div = nom * ref_div_max / tmp; + fb_div = DIV_ROUND_CLOSEST(nom * ref_div_max, den); } /* reduce the numbers to a simpler ratio once more */ From 8c79bae6a30f606b7a4e17c994bc5f72f8fdaf11 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 16 Apr 2014 09:42:22 -0400 Subject: [PATCH 243/279] drm/radeon/si: make sure mc ucode is loaded before checking the size Avoid a possible segfault. Noticed-by: Dan Carpenter Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/si.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 86f8c9c87f5cf9..ac708e006180d3 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1472,11 +1472,13 @@ int si_mc_load_microcode(struct radeon_device *rdev) const __be32 *fw_data; u32 running, blackout = 0; u32 *io_mc_regs; - int i, regs_size, ucode_size = rdev->mc_fw->size / 4; + int i, regs_size, ucode_size; if (!rdev->mc_fw) return -EINVAL; + ucode_size = rdev->mc_fw->size / 4; + switch (rdev->family) { case CHIP_TAHITI: io_mc_regs = (u32 *)&tahiti_io_mc_regs; From bcddee29b0b87af3aeda953840f97b356b24dc5e Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 16 Apr 2014 09:42:23 -0400 Subject: [PATCH 244/279] drm/radeon/ci: make sure mc ucode is loaded before checking the size Avoid a possible segfault. Noticed-by: Dan Carpenter Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/cik.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 7e430450bac0ed..199eb194716f83 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -1705,11 +1705,13 @@ int ci_mc_load_microcode(struct radeon_device *rdev) const __be32 *fw_data; u32 running, blackout = 0; u32 *io_mc_regs; - int i, regs_size, ucode_size = rdev->mc_fw->size / 4; + int i, regs_size, ucode_size; if (!rdev->mc_fw) return -EINVAL; + ucode_size = rdev->mc_fw->size / 4; + switch (rdev->family) { case CHIP_BONAIRE: io_mc_regs = (u32 *)&bonaire_io_mc_regs; From 6ea6215fe394e320468589d9bba464a48f6d823a Mon Sep 17 00:00:00 2001 From: "zhangwei(Jovi)" Date: Thu, 17 Apr 2014 16:05:19 +0800 Subject: [PATCH 245/279] tracing/uprobes: Fix uprobe_cpu_buffer memory leak Forgot to free uprobe_cpu_buffer percpu page in uprobe_buffer_disable(). Link: http://lkml.kernel.org/p/534F8B3F.1090407@huawei.com Cc: stable@vger.kernel.org # v3.14+ Acked-by: Namhyung Kim Signed-off-by: zhangwei(Jovi) Signed-off-by: Steven Rostedt --- kernel/trace/trace_uprobe.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index 930e51462dc871..c082a74413455d 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -732,9 +732,15 @@ static int uprobe_buffer_enable(void) static void uprobe_buffer_disable(void) { + int cpu; + BUG_ON(!mutex_is_locked(&event_mutex)); if (--uprobe_buffer_refcnt == 0) { + for_each_possible_cpu(cpu) + free_page((unsigned long)per_cpu_ptr(uprobe_cpu_buffer, + cpu)->buf); + free_percpu(uprobe_cpu_buffer); uprobe_cpu_buffer = NULL; } From 12de375ec493ab1767d4a07dde823e63ae5edc21 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 17 Apr 2014 09:33:19 -0700 Subject: [PATCH 246/279] Revert "serial: 8250, disable "too much work" messages" This reverts commit f4f653e9875e573860e783fecbebde284a8626f5. Jiri writes: No, please drop this one. We need a better solution as it turned out that some boxes need 16k loops and it will increase with new processors :(. Cc: Jiri Slaby Cc: Martin Pluskal Cc: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 139ab1997e062f..81f909c2101f61 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -1601,7 +1601,8 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id) l = l->next; if (l == i->head && pass_counter++ > PASS_LIMIT) { - pr_debug_ratelimited( + /* If we hit this, we're dead. */ + printk_ratelimited(KERN_ERR "serial8250: too much work for irq%d\n", irq); break; } From a94cdd1f4d30f12904ab528152731fb13a812a16 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 14 Apr 2014 09:46:50 -0500 Subject: [PATCH 247/279] Char: ipmi_bt_sm, fix infinite loop In read_all_bytes, we do unsigned char i; ... bt->read_data[0] = BMC2HOST; bt->read_count = bt->read_data[0]; ... for (i = 1; i <= bt->read_count; i++) bt->read_data[i] = BMC2HOST; If bt->read_data[0] == bt->read_count == 255, we loop infinitely in the 'for' loop. Make 'i' an 'int' instead of 'char' to get rid of the overflow and finish the loop after 255 iterations every time. Signed-off-by: Jiri Slaby Reported-and-debugged-by: Rui Hui Dian Cc: Tomas Cech Cc: Corey Minyard Cc: Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_bt_sm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index f5e4cd7617f689..61e71616689b7c 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -352,7 +352,7 @@ static inline void write_all_bytes(struct si_sm_data *bt) static inline int read_all_bytes(struct si_sm_data *bt) { - unsigned char i; + unsigned int i; /* * length is "framing info", minimum = 4: NetFn, Seq, Cmd, cCode. From 48e8ac2979920ffa39117e2d725afa3a749bfe8d Mon Sep 17 00:00:00 2001 From: Bodo Stroesser Date: Mon, 14 Apr 2014 09:46:51 -0500 Subject: [PATCH 248/279] ipmi: Fix a race restarting the timer With recent changes it is possible for the timer handler to detect an idle interface and not start the timer, but the thread to start an operation at the same time. The thread will not start the timer in that instance, resulting in the timer not running. Instead, move all timer operations under the lock and start the timer in the thread if it detect non-idle and the timer is not already running. Moving under locks allows the last timeout to be set in both the thread and the timer. 'Timer is not running' means that the timer is not pending and smi_timeout() is not running. So we need a flag to detect this correctly. Also fix a few other timeout bugs: setting the last timeout when the interrupt has to be disabled and the timer started, and setting the last timeout in check_start_timer_thread possibly racing with the timer Signed-off-by: Corey Minyard Signed-off-by: Bodo Stroesser Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 46 +++++++++++++++++++------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index b7efd3c1a88252..9c4069151955b6 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -248,6 +248,9 @@ struct smi_info { /* The timer for this si. */ struct timer_list si_timer; + /* This flag is set, if the timer is running (timer_pending() isn't enough) */ + bool timer_running; + /* The time (in jiffies) the last timeout occurred at. */ unsigned long last_timeout_jiffies; @@ -434,6 +437,13 @@ static void start_clear_flags(struct smi_info *smi_info) smi_info->si_state = SI_CLEARING_FLAGS; } +static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val) +{ + smi_info->last_timeout_jiffies = jiffies; + mod_timer(&smi_info->si_timer, new_val); + smi_info->timer_running = true; +} + /* * When we have a situtaion where we run out of memory and cannot * allocate messages, we just leave them in the BMC and run the system @@ -446,8 +456,7 @@ static inline void disable_si_irq(struct smi_info *smi_info) start_disable_irq(smi_info); smi_info->interrupt_disabled = 1; if (!atomic_read(&smi_info->stop_operation)) - mod_timer(&smi_info->si_timer, - jiffies + SI_TIMEOUT_JIFFIES); + smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); } } @@ -907,15 +916,7 @@ static void sender(void *send_info, list_add_tail(&msg->link, &smi_info->xmit_msgs); if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) { - /* - * last_timeout_jiffies is updated here to avoid - * smi_timeout() handler passing very large time_diff - * value to smi_event_handler() that causes - * the send command to abort. - */ - smi_info->last_timeout_jiffies = jiffies; - - mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); + smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); if (smi_info->thread) wake_up_process(smi_info->thread); @@ -1004,6 +1005,17 @@ static int ipmi_thread(void *data) spin_lock_irqsave(&(smi_info->si_lock), flags); smi_result = smi_event_handler(smi_info, 0); + + /* + * If the driver is doing something, there is a possible + * race with the timer. If the timer handler see idle, + * and the thread here sees something else, the timer + * handler won't restart the timer even though it is + * required. So start it here if necessary. + */ + if (smi_result != SI_SM_IDLE && !smi_info->timer_running) + smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); + spin_unlock_irqrestore(&(smi_info->si_lock), flags); busy_wait = ipmi_thread_busy_wait(smi_result, smi_info, &busy_until); @@ -1073,10 +1085,6 @@ static void smi_timeout(unsigned long data) * SI_USEC_PER_JIFFY); smi_result = smi_event_handler(smi_info, time_diff); - spin_unlock_irqrestore(&(smi_info->si_lock), flags); - - smi_info->last_timeout_jiffies = jiffies_now; - if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { /* Running with interrupts, only do long timeouts. */ timeout = jiffies + SI_TIMEOUT_JIFFIES; @@ -1098,7 +1106,10 @@ static void smi_timeout(unsigned long data) do_mod_timer: if (smi_result != SI_SM_IDLE) - mod_timer(&(smi_info->si_timer), timeout); + smi_mod_timer(smi_info, timeout); + else + smi_info->timer_running = false; + spin_unlock_irqrestore(&(smi_info->si_lock), flags); } static irqreturn_t si_irq_handler(int irq, void *data) @@ -1146,8 +1157,7 @@ static int smi_start_processing(void *send_info, /* Set up the timer that drives the interface. */ setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi); - new_smi->last_timeout_jiffies = jiffies; - mod_timer(&new_smi->si_timer, jiffies + SI_TIMEOUT_JIFFIES); + smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES); /* * Check if the user forcefully enabled the daemon. From eb6d78ec213e6938559b801421d64714dafcf4b2 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 14 Apr 2014 09:46:52 -0500 Subject: [PATCH 249/279] ipmi: Reset the KCS timeout when starting error recovery The OBF timer in KCS was not reset in one situation when error recovery was started, resulting in an immediate timeout. Reported-by: Bodo Stroesser Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_kcs_sm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index 6a4bdc18955a52..8c25f596808a9a 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c @@ -251,8 +251,9 @@ static inline int check_obf(struct si_sm_data *kcs, unsigned char status, if (!GET_STATUS_OBF(status)) { kcs->obf_timeout -= time; if (kcs->obf_timeout < 0) { - start_error_recovery(kcs, "OBF not ready in time"); - return 1; + kcs->obf_timeout = OBF_RETRY_TIMEOUT; + start_error_recovery(kcs, "OBF not ready in time"); + return 1; } return 0; } From 0dfe6e7ed47feeb22f3cf8c7d8ac7e65bd4e87f5 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 14 Apr 2014 09:46:53 -0500 Subject: [PATCH 250/279] ipmi: Turn off default probing of interfaces The default probing can cause problems with some system, slow booting, extra CPU usages, etc. Turn it off by default and give a config option to enable it. From: Matthew Garrett Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/char/ipmi/Kconfig | 12 ++++++++++++ drivers/char/ipmi/ipmi_si_intf.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig index 0baa8fab4ea7af..db1c9b7adaa667 100644 --- a/drivers/char/ipmi/Kconfig +++ b/drivers/char/ipmi/Kconfig @@ -50,6 +50,18 @@ config IPMI_SI Currently, only KCS and SMIC are supported. If you are using IPMI, you should probably say "y" here. +config IPMI_SI_PROBE_DEFAULTS + bool 'Probe for all possible IPMI system interfaces by default' + default n + depends on IPMI_SI + help + Modern systems will usually expose IPMI interfaces via a discoverable + firmware mechanism such as ACPI or DMI. Older systems do not, and so + the driver is forced to probe hardware manually. This may cause boot + delays. Say "n" here to disable this manual probing. IPMI will then + only be available on older systems if the "ipmi_si_intf.trydefaults=1" + boot argument is passed. + config IPMI_WATCHDOG tristate 'IPMI Watchdog Timer' help diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 9c4069151955b6..25a1436a429181 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -1239,7 +1239,7 @@ static bool si_tryplatform = 1; #ifdef CONFIG_PCI static bool si_trypci = 1; #endif -static bool si_trydefaults = 1; +static bool si_trydefaults = IS_ENABLED(CONFIG_IPMI_SI_PROBE_DEFAULTS); static char *si_type[SI_MAX_PARMS]; #define MAX_SI_TYPE_STR 30 static char si_type_str[MAX_SI_TYPE_STR]; From 89986496de141213206d49450ffdd36098d41209 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 14 Apr 2014 09:46:54 -0500 Subject: [PATCH 251/279] ipmi: Turn off all activity on an idle ipmi interface The IPMI driver would wake up periodically looking for events and watchdog pretimeouts. If there is nothing waiting for these events, it's really kind of pointless to be checking for them. So modify the driver so the message handler can pass down if it needs the lower layer to be waiting for these. Modify the system interface lower layer to turn off all timer and thread activity if the upper layer doesn't need anything and it is not currently handling messages. And modify the message handler to not restart the timer if its timer is not needed. The timers and kthread will still be enabled if: - the SI interface is handling a message. - a user has enabled watching for events. - the IPMI watchdog timer is in use (since it uses pretimeouts). - the message handler is waiting on a remote response. - a user has registered to receive commands. This mostly affects interfaces without interrupts. Interfaces with interrupts already don't use CPU in the system interface when the interface is idle. Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 219 +++++++++++++++++----------- drivers/char/ipmi/ipmi_si_intf.c | 51 +++++-- include/linux/ipmi.h | 2 +- include/linux/ipmi_smi.h | 7 + 4 files changed, 182 insertions(+), 97 deletions(-) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index ec4e10fcf1a51b..872c4ec79bf4c8 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -55,6 +55,7 @@ static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); static int ipmi_init_msghandler(void); static void smi_recv_tasklet(unsigned long); static void handle_new_recv_msgs(ipmi_smi_t intf); +static void need_waiter(ipmi_smi_t intf); static int initialized; @@ -73,6 +74,20 @@ static struct proc_dir_entry *proc_ipmi_root; */ #define MAX_MSG_TIMEOUT 60000 +/* Call every ~1000 ms. */ +#define IPMI_TIMEOUT_TIME 1000 + +/* How many jiffies does it take to get to the timeout time. */ +#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000) + +/* + * Request events from the queue every second (this is the number of + * IPMI_TIMEOUT_TIMES between event requests). Hopefully, in the + * future, IPMI will add a way to know immediately if an event is in + * the queue and this silliness can go away. + */ +#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME)) + /* * The main "user" data structure. */ @@ -92,7 +107,7 @@ struct ipmi_user { ipmi_smi_t intf; /* Does this interface receive IPMI events? */ - int gets_events; + bool gets_events; }; struct cmd_rcvr { @@ -383,6 +398,9 @@ struct ipmi_smi { unsigned int waiting_events_count; /* How many events in queue? */ char delivering_events; char event_msg_printed; + atomic_t event_waiters; + unsigned int ticks_to_req_ev; + int last_needs_timer; /* * The event receiver for my BMC, only really used at panic @@ -451,7 +469,6 @@ static DEFINE_MUTEX(ipmi_interfaces_mutex); static LIST_HEAD(smi_watchers); static DEFINE_MUTEX(smi_watchers_mutex); - #define ipmi_inc_stat(intf, stat) \ atomic_inc(&(intf)->stats[IPMI_STAT_ ## stat]) #define ipmi_get_stat(intf, stat) \ @@ -772,6 +789,7 @@ static int intf_next_seq(ipmi_smi_t intf, *seq = i; *seqid = intf->seq_table[i].seqid; intf->curr_seq = (i+1)%IPMI_IPMB_NUM_SEQ; + need_waiter(intf); } else { rv = -EAGAIN; } @@ -941,7 +959,7 @@ int ipmi_create_user(unsigned int if_num, new_user->handler = handler; new_user->handler_data = handler_data; new_user->intf = intf; - new_user->gets_events = 0; + new_user->gets_events = false; if (!try_module_get(intf->handlers->owner)) { rv = -ENODEV; @@ -966,6 +984,11 @@ int ipmi_create_user(unsigned int if_num, spin_lock_irqsave(&intf->seq_lock, flags); list_add_rcu(&new_user->link, &intf->users); spin_unlock_irqrestore(&intf->seq_lock, flags); + if (handler->ipmi_watchdog_pretimeout) { + /* User wants pretimeouts, so make sure to watch for them. */ + if (atomic_inc_return(&intf->event_waiters) == 1) + need_waiter(intf); + } *user = new_user; return 0; @@ -1021,6 +1044,12 @@ int ipmi_destroy_user(ipmi_user_t user) user->valid = 0; + if (user->handler->ipmi_watchdog_pretimeout) + atomic_dec(&intf->event_waiters); + + if (user->gets_events) + atomic_dec(&intf->event_waiters); + /* Remove the user from the interface's sequence table. */ spin_lock_irqsave(&intf->seq_lock, flags); list_del_rcu(&user->link); @@ -1184,7 +1213,7 @@ int ipmi_set_maintenance_mode(ipmi_user_t user, int mode) } EXPORT_SYMBOL(ipmi_set_maintenance_mode); -int ipmi_set_gets_events(ipmi_user_t user, int val) +int ipmi_set_gets_events(ipmi_user_t user, bool val) { unsigned long flags; ipmi_smi_t intf = user->intf; @@ -1194,8 +1223,18 @@ int ipmi_set_gets_events(ipmi_user_t user, int val) INIT_LIST_HEAD(&msgs); spin_lock_irqsave(&intf->events_lock, flags); + if (user->gets_events == val) + goto out; + user->gets_events = val; + if (val) { + if (atomic_inc_return(&intf->event_waiters) == 1) + need_waiter(intf); + } else { + atomic_dec(&intf->event_waiters); + } + if (intf->delivering_events) /* * Another thread is delivering events for this, so @@ -1289,6 +1328,9 @@ int ipmi_register_for_cmd(ipmi_user_t user, goto out_unlock; } + if (atomic_inc_return(&intf->event_waiters) == 1) + need_waiter(intf); + list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); out_unlock: @@ -1330,6 +1372,7 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, mutex_unlock(&intf->cmd_rcvrs_mutex); synchronize_rcu(); while (rcvrs) { + atomic_dec(&intf->event_waiters); rcvr = rcvrs; rcvrs = rcvr->next; kfree(rcvr); @@ -2876,6 +2919,8 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, (unsigned long) intf); atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); spin_lock_init(&intf->events_lock); + atomic_set(&intf->event_waiters, 0); + intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; INIT_LIST_HEAD(&intf->waiting_events); intf->waiting_events_count = 0; mutex_init(&intf->cmd_rcvrs_mutex); @@ -3965,7 +4010,8 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, struct list_head *timeouts, long timeout_period, - int slot, unsigned long *flags) + int slot, unsigned long *flags, + unsigned int *waiting_msgs) { struct ipmi_recv_msg *msg; struct ipmi_smi_handlers *handlers; @@ -3977,8 +4023,10 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, return; ent->timeout -= timeout_period; - if (ent->timeout > 0) + if (ent->timeout > 0) { + (*waiting_msgs)++; return; + } if (ent->retries_left == 0) { /* The message has used all its retries. */ @@ -3995,6 +4043,8 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, struct ipmi_smi_msg *smi_msg; /* More retries, send again. */ + (*waiting_msgs)++; + /* * Start with the max timer, set to normal timer after * the message is sent. @@ -4040,117 +4090,118 @@ static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, } } -static void ipmi_timeout_handler(long timeout_period) +static unsigned int ipmi_timeout_handler(ipmi_smi_t intf, long timeout_period) { - ipmi_smi_t intf; struct list_head timeouts; struct ipmi_recv_msg *msg, *msg2; unsigned long flags; int i; + unsigned int waiting_msgs = 0; - rcu_read_lock(); - list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { - tasklet_schedule(&intf->recv_tasklet); - - /* - * Go through the seq table and find any messages that - * have timed out, putting them in the timeouts - * list. - */ - INIT_LIST_HEAD(&timeouts); - spin_lock_irqsave(&intf->seq_lock, flags); - for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) - check_msg_timeout(intf, &(intf->seq_table[i]), - &timeouts, timeout_period, i, - &flags); - spin_unlock_irqrestore(&intf->seq_lock, flags); + /* + * Go through the seq table and find any messages that + * have timed out, putting them in the timeouts + * list. + */ + INIT_LIST_HEAD(&timeouts); + spin_lock_irqsave(&intf->seq_lock, flags); + for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) + check_msg_timeout(intf, &(intf->seq_table[i]), + &timeouts, timeout_period, i, + &flags, &waiting_msgs); + spin_unlock_irqrestore(&intf->seq_lock, flags); - list_for_each_entry_safe(msg, msg2, &timeouts, link) - deliver_err_response(msg, IPMI_TIMEOUT_COMPLETION_CODE); + list_for_each_entry_safe(msg, msg2, &timeouts, link) + deliver_err_response(msg, IPMI_TIMEOUT_COMPLETION_CODE); - /* - * Maintenance mode handling. Check the timeout - * optimistically before we claim the lock. It may - * mean a timeout gets missed occasionally, but that - * only means the timeout gets extended by one period - * in that case. No big deal, and it avoids the lock - * most of the time. - */ + /* + * Maintenance mode handling. Check the timeout + * optimistically before we claim the lock. It may + * mean a timeout gets missed occasionally, but that + * only means the timeout gets extended by one period + * in that case. No big deal, and it avoids the lock + * most of the time. + */ + if (intf->auto_maintenance_timeout > 0) { + spin_lock_irqsave(&intf->maintenance_mode_lock, flags); if (intf->auto_maintenance_timeout > 0) { - spin_lock_irqsave(&intf->maintenance_mode_lock, flags); - if (intf->auto_maintenance_timeout > 0) { - intf->auto_maintenance_timeout - -= timeout_period; - if (!intf->maintenance_mode - && (intf->auto_maintenance_timeout <= 0)) { - intf->maintenance_mode_enable = 0; - maintenance_mode_update(intf); - } + intf->auto_maintenance_timeout + -= timeout_period; + if (!intf->maintenance_mode + && (intf->auto_maintenance_timeout <= 0)) { + intf->maintenance_mode_enable = 0; + maintenance_mode_update(intf); } - spin_unlock_irqrestore(&intf->maintenance_mode_lock, - flags); } + spin_unlock_irqrestore(&intf->maintenance_mode_lock, + flags); } - rcu_read_unlock(); + + tasklet_schedule(&intf->recv_tasklet); + + return waiting_msgs; } -static void ipmi_request_event(void) +static void ipmi_request_event(ipmi_smi_t intf) { - ipmi_smi_t intf; struct ipmi_smi_handlers *handlers; - rcu_read_lock(); - /* - * Called from the timer, no need to check if handlers is - * valid. - */ - list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { - /* No event requests when in maintenance mode. */ - if (intf->maintenance_mode_enable) - continue; + /* No event requests when in maintenance mode. */ + if (intf->maintenance_mode_enable) + return; - handlers = intf->handlers; - if (handlers) - handlers->request_events(intf->send_info); - } - rcu_read_unlock(); + handlers = intf->handlers; + if (handlers) + handlers->request_events(intf->send_info); } static struct timer_list ipmi_timer; -/* Call every ~1000 ms. */ -#define IPMI_TIMEOUT_TIME 1000 - -/* How many jiffies does it take to get to the timeout time. */ -#define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000) - -/* - * Request events from the queue every second (this is the number of - * IPMI_TIMEOUT_TIMES between event requests). Hopefully, in the - * future, IPMI will add a way to know immediately if an event is in - * the queue and this silliness can go away. - */ -#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME)) - static atomic_t stop_operation; -static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME; static void ipmi_timeout(unsigned long data) { + ipmi_smi_t intf; + int nt = 0; + if (atomic_read(&stop_operation)) return; - ticks_to_req_ev--; - if (ticks_to_req_ev == 0) { - ipmi_request_event(); - ticks_to_req_ev = IPMI_REQUEST_EV_TIME; - } + rcu_read_lock(); + list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { + int lnt = 0; + + if (atomic_read(&intf->event_waiters)) { + intf->ticks_to_req_ev--; + if (intf->ticks_to_req_ev == 0) { + ipmi_request_event(intf); + intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME; + } + lnt++; + } - ipmi_timeout_handler(IPMI_TIMEOUT_TIME); + lnt += ipmi_timeout_handler(intf, IPMI_TIMEOUT_TIME); - mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); + lnt = !!lnt; + if (lnt != intf->last_needs_timer && + intf->handlers->set_need_watch) + intf->handlers->set_need_watch(intf->send_info, lnt); + intf->last_needs_timer = lnt; + + nt += lnt; + } + rcu_read_unlock(); + + if (nt) + mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); } +static void need_waiter(ipmi_smi_t intf) +{ + /* Racy, but worst case we start the timer twice. */ + if (!timer_pending(&ipmi_timer)) + mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES); +} static atomic_t smi_msg_inuse_count = ATOMIC_INIT(0); static atomic_t recv_msg_inuse_count = ATOMIC_INIT(0); diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 25a1436a429181..444ea548dfe3f9 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -257,6 +257,9 @@ struct smi_info { /* Used to gracefully stop the timer without race conditions. */ atomic_t stop_operation; + /* Are we waiting for the events, pretimeouts, received msgs? */ + atomic_t need_watch; + /* * The driver will disable interrupts when it gets into a * situation where it cannot handle messages due to lack of @@ -862,6 +865,19 @@ static enum si_sm_result smi_event_handler(struct smi_info *smi_info, return si_sm_result; } +static void check_start_timer_thread(struct smi_info *smi_info) +{ + if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) { + smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); + + if (smi_info->thread) + wake_up_process(smi_info->thread); + + start_next_msg(smi_info); + smi_event_handler(smi_info, 0); + } +} + static void sender(void *send_info, struct ipmi_smi_msg *msg, int priority) @@ -915,15 +931,7 @@ static void sender(void *send_info, else list_add_tail(&msg->link, &smi_info->xmit_msgs); - if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) { - smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); - - if (smi_info->thread) - wake_up_process(smi_info->thread); - - start_next_msg(smi_info); - smi_event_handler(smi_info, 0); - } + check_start_timer_thread(smi_info); spin_unlock_irqrestore(&smi_info->si_lock, flags); } @@ -1023,9 +1031,15 @@ static int ipmi_thread(void *data) ; /* do nothing */ else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) schedule(); - else if (smi_result == SI_SM_IDLE) - schedule_timeout_interruptible(100); - else + else if (smi_result == SI_SM_IDLE) { + if (atomic_read(&smi_info->need_watch)) { + schedule_timeout_interruptible(100); + } else { + /* Wait to be woken up when we are needed. */ + __set_current_state(TASK_INTERRUPTIBLE); + schedule(); + } + } else schedule_timeout_interruptible(1); } return 0; @@ -1061,6 +1075,17 @@ static void request_events(void *send_info) atomic_set(&smi_info->req_events, 1); } +static void set_need_watch(void *send_info, int enable) +{ + struct smi_info *smi_info = send_info; + unsigned long flags; + + atomic_set(&smi_info->need_watch, enable); + spin_lock_irqsave(&smi_info->si_lock, flags); + check_start_timer_thread(smi_info); + spin_unlock_irqrestore(&smi_info->si_lock, flags); +} + static int initialized; static void smi_timeout(unsigned long data) @@ -1212,6 +1237,7 @@ static struct ipmi_smi_handlers handlers = { .get_smi_info = get_smi_info, .sender = sender, .request_events = request_events, + .set_need_watch = set_need_watch, .set_maintenance_mode = set_maintenance_mode, .set_run_to_completion = set_run_to_completion, .poll = poll, @@ -3352,6 +3378,7 @@ static int try_smi_init(struct smi_info *new_smi) new_smi->interrupt_disabled = 1; atomic_set(&new_smi->stop_operation, 0); + atomic_set(&new_smi->need_watch, 0); new_smi->intf_num = smi_num; smi_num++; diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 1f9f56e2885131..76d2acbfa7c69e 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -237,7 +237,7 @@ int ipmi_set_maintenance_mode(ipmi_user_t user, int mode); * The first user that sets this to TRUE will receive all events that * have been queued while no one was waiting for events. */ -int ipmi_set_gets_events(ipmi_user_t user, int val); +int ipmi_set_gets_events(ipmi_user_t user, bool val); /* * Called when a new SMI is registered. This will also be called on diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 8ea3fe0b975984..2a7ff302d99058 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -109,6 +109,13 @@ struct ipmi_smi_handlers { events from the BMC we are attached to. */ void (*request_events)(void *send_info); + /* Called by the upper layer when some user requires that the + interface watch for events, received messages, watchdog + pretimeouts, or not. Used by the SMI to know if it should + watch for these. This may be NULL if the SMI does not + implement it. */ + void (*set_need_watch)(void *send_info, int enable); + /* Called when the interface should go into "run to completion" mode. If this call sets the value to true, the interface should make sure that all messages are flushed From 7aefac26fc67158cb8826a5f5bfc2a5086a7d962 Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 14 Apr 2014 09:46:56 -0500 Subject: [PATCH 252/279] ipmi: boolify some things Convert some ints to bools. Signed-off-by: Corey Minyard Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 22 ++++++------- drivers/char/ipmi/ipmi_si_intf.c | 50 ++++++++++++++--------------- include/linux/ipmi_smi.h | 6 ++-- 3 files changed, 38 insertions(+), 40 deletions(-) diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 872c4ec79bf4c8..e6db9381b2c765 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -94,8 +94,8 @@ static struct proc_dir_entry *proc_ipmi_root; struct ipmi_user { struct list_head link; - /* Set to "0" when the user is destroyed. */ - int valid; + /* Set to false when the user is destroyed. */ + bool valid; struct kref refcount; @@ -413,7 +413,7 @@ struct ipmi_smi { /* For handling of maintenance mode. */ int maintenance_mode; - int maintenance_mode_enable; + bool maintenance_mode_enable; int auto_maintenance_timeout; spinlock_t maintenance_mode_lock; /* Used in a timer... */ @@ -980,7 +980,7 @@ int ipmi_create_user(unsigned int if_num, */ mutex_unlock(&ipmi_interfaces_mutex); - new_user->valid = 1; + new_user->valid = true; spin_lock_irqsave(&intf->seq_lock, flags); list_add_rcu(&new_user->link, &intf->users); spin_unlock_irqrestore(&intf->seq_lock, flags); @@ -1042,7 +1042,7 @@ int ipmi_destroy_user(ipmi_user_t user) struct cmd_rcvr *rcvr; struct cmd_rcvr *rcvrs = NULL; - user->valid = 0; + user->valid = false; if (user->handler->ipmi_watchdog_pretimeout) atomic_dec(&intf->event_waiters); @@ -1184,25 +1184,23 @@ int ipmi_set_maintenance_mode(ipmi_user_t user, int mode) if (intf->maintenance_mode != mode) { switch (mode) { case IPMI_MAINTENANCE_MODE_AUTO: - intf->maintenance_mode = mode; intf->maintenance_mode_enable = (intf->auto_maintenance_timeout > 0); break; case IPMI_MAINTENANCE_MODE_OFF: - intf->maintenance_mode = mode; - intf->maintenance_mode_enable = 0; + intf->maintenance_mode_enable = false; break; case IPMI_MAINTENANCE_MODE_ON: - intf->maintenance_mode = mode; - intf->maintenance_mode_enable = 1; + intf->maintenance_mode_enable = true; break; default: rv = -EINVAL; goto out_unlock; } + intf->maintenance_mode = mode; maintenance_mode_update(intf); } @@ -1578,7 +1576,7 @@ static int i_ipmi_request(ipmi_user_t user, = IPMI_MAINTENANCE_MODE_TIMEOUT; if (!intf->maintenance_mode && !intf->maintenance_mode_enable) { - intf->maintenance_mode_enable = 1; + intf->maintenance_mode_enable = true; maintenance_mode_update(intf); } spin_unlock_irqrestore(&intf->maintenance_mode_lock, @@ -4129,7 +4127,7 @@ static unsigned int ipmi_timeout_handler(ipmi_smi_t intf, long timeout_period) -= timeout_period; if (!intf->maintenance_mode && (intf->auto_maintenance_timeout <= 0)) { - intf->maintenance_mode_enable = 0; + intf->maintenance_mode_enable = false; maintenance_mode_update(intf); } } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 444ea548dfe3f9..1c4bb4f6ce932f 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -217,7 +217,7 @@ struct smi_info { unsigned char msg_flags; /* Does the BMC have an event buffer? */ - char has_event_buffer; + bool has_event_buffer; /* * If set to true, this will request events the next time the @@ -230,7 +230,7 @@ struct smi_info { * call. Generally used after a panic to make sure stuff goes * out. */ - int run_to_completion; + bool run_to_completion; /* The I/O port of an SI interface. */ int port; @@ -266,7 +266,7 @@ struct smi_info { * memory. Once that situation clears up, it will re-enable * interrupts. */ - int interrupt_disabled; + bool interrupt_disabled; /* From the get device id response... */ struct ipmi_device_id device_id; @@ -279,7 +279,7 @@ struct smi_info { * True if we allocated the device, false if it came from * someplace else (like PCI). */ - int dev_registered; + bool dev_registered; /* Slave address, could be reported from DMI. */ unsigned char slave_addr; @@ -303,19 +303,19 @@ struct smi_info { static int force_kipmid[SI_MAX_PARMS]; static int num_force_kipmid; #ifdef CONFIG_PCI -static int pci_registered; +static bool pci_registered; #endif #ifdef CONFIG_ACPI -static int pnp_registered; +static bool pnp_registered; #endif #ifdef CONFIG_PARISC -static int parisc_registered; +static bool parisc_registered; #endif static unsigned int kipmid_max_busy_us[SI_MAX_PARMS]; static int num_max_busy_us; -static int unload_when_empty = 1; +static bool unload_when_empty = true; static int add_smi(struct smi_info *smi); static int try_smi_init(struct smi_info *smi); @@ -457,7 +457,7 @@ static inline void disable_si_irq(struct smi_info *smi_info) { if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { start_disable_irq(smi_info); - smi_info->interrupt_disabled = 1; + smi_info->interrupt_disabled = true; if (!atomic_read(&smi_info->stop_operation)) smi_mod_timer(smi_info, jiffies + SI_TIMEOUT_JIFFIES); } @@ -467,7 +467,7 @@ static inline void enable_si_irq(struct smi_info *smi_info) { if ((smi_info->irq) && (smi_info->interrupt_disabled)) { start_enable_irq(smi_info); - smi_info->interrupt_disabled = 0; + smi_info->interrupt_disabled = false; } } @@ -712,7 +712,7 @@ static void handle_transaction_done(struct smi_info *smi_info) dev_warn(smi_info->dev, "Maybe ok, but ipmi might run very slowly.\n"); } else - smi_info->interrupt_disabled = 0; + smi_info->interrupt_disabled = false; smi_info->si_state = SI_NORMAL; break; } @@ -935,7 +935,7 @@ static void sender(void *send_info, spin_unlock_irqrestore(&smi_info->si_lock, flags); } -static void set_run_to_completion(void *send_info, int i_run_to_completion) +static void set_run_to_completion(void *send_info, bool i_run_to_completion) { struct smi_info *smi_info = send_info; enum si_sm_result result; @@ -1050,7 +1050,7 @@ static void poll(void *send_info) { struct smi_info *smi_info = send_info; unsigned long flags = 0; - int run_to_completion = smi_info->run_to_completion; + bool run_to_completion = smi_info->run_to_completion; /* * Make sure there is some delay in the poll loop so we can @@ -1075,7 +1075,7 @@ static void request_events(void *send_info) atomic_set(&smi_info->req_events, 1); } -static void set_need_watch(void *send_info, int enable) +static void set_need_watch(void *send_info, bool enable) { struct smi_info *smi_info = send_info; unsigned long flags; @@ -1223,7 +1223,7 @@ static int get_smi_info(void *send_info, struct ipmi_smi_info *data) return 0; } -static void set_maintenance_mode(void *send_info, int enable) +static void set_maintenance_mode(void *send_info, bool enable) { struct smi_info *smi_info = send_info; @@ -1364,7 +1364,7 @@ module_param_array(force_kipmid, int, &num_force_kipmid, 0); MODULE_PARM_DESC(force_kipmid, "Force the kipmi daemon to be enabled (1) or" " disabled(0). Normally the IPMI driver auto-detects" " this, but the value may be overridden by this parm."); -module_param(unload_when_empty, int, 0); +module_param(unload_when_empty, bool, 0); MODULE_PARM_DESC(unload_when_empty, "Unload the module if no interfaces are" " specified or found, default is 1. Setting to 0" " is useful for hot add of devices using hotmod."); @@ -3372,11 +3372,11 @@ static int try_smi_init(struct smi_info *new_smi) INIT_LIST_HEAD(&(new_smi->hp_xmit_msgs)); new_smi->curr_msg = NULL; atomic_set(&new_smi->req_events, 0); - new_smi->run_to_completion = 0; + new_smi->run_to_completion = false; for (i = 0; i < SI_NUM_STATS; i++) atomic_set(&new_smi->stats[i], 0); - new_smi->interrupt_disabled = 1; + new_smi->interrupt_disabled = true; atomic_set(&new_smi->stop_operation, 0); atomic_set(&new_smi->need_watch, 0); new_smi->intf_num = smi_num; @@ -3384,7 +3384,7 @@ static int try_smi_init(struct smi_info *new_smi) rv = try_enable_event_buffer(new_smi); if (rv == 0) - new_smi->has_event_buffer = 1; + new_smi->has_event_buffer = true; /* * Start clearing the flags before we enable interrupts or the @@ -3418,7 +3418,7 @@ static int try_smi_init(struct smi_info *new_smi) rv); goto out_err; } - new_smi->dev_registered = 1; + new_smi->dev_registered = true; } rv = ipmi_register_smi(&handlers, @@ -3467,7 +3467,7 @@ static int try_smi_init(struct smi_info *new_smi) wait_for_timer_and_thread(new_smi); out_err: - new_smi->interrupt_disabled = 1; + new_smi->interrupt_disabled = true; if (new_smi->intf) { ipmi_unregister_smi(new_smi->intf); @@ -3503,7 +3503,7 @@ static int try_smi_init(struct smi_info *new_smi) if (new_smi->dev_registered) { platform_device_unregister(new_smi->pdev); - new_smi->dev_registered = 0; + new_smi->dev_registered = false; } return rv; @@ -3558,14 +3558,14 @@ static int init_ipmi_si(void) printk(KERN_ERR PFX "Unable to register " "PCI driver: %d\n", rv); else - pci_registered = 1; + pci_registered = true; } #endif #ifdef CONFIG_ACPI if (si_tryacpi) { pnp_register_driver(&ipmi_pnp_driver); - pnp_registered = 1; + pnp_registered = true; } #endif @@ -3581,7 +3581,7 @@ static int init_ipmi_si(void) #ifdef CONFIG_PARISC register_parisc_driver(&ipmi_parisc_driver); - parisc_registered = 1; + parisc_registered = true; /* poking PC IO addresses will crash machine, don't do it */ si_trydefaults = 0; #endif diff --git a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h index 2a7ff302d99058..bd349240d50ecb 100644 --- a/include/linux/ipmi_smi.h +++ b/include/linux/ipmi_smi.h @@ -114,14 +114,14 @@ struct ipmi_smi_handlers { pretimeouts, or not. Used by the SMI to know if it should watch for these. This may be NULL if the SMI does not implement it. */ - void (*set_need_watch)(void *send_info, int enable); + void (*set_need_watch)(void *send_info, bool enable); /* Called when the interface should go into "run to completion" mode. If this call sets the value to true, the interface should make sure that all messages are flushed out and that none are pending, and any new requests are run to completion immediately. */ - void (*set_run_to_completion)(void *send_info, int run_to_completion); + void (*set_run_to_completion)(void *send_info, bool run_to_completion); /* Called to poll for work to do. This is so upper layers can poll for operations during things like crash dumps. */ @@ -132,7 +132,7 @@ struct ipmi_smi_handlers { setting. The message handler does the mode handling. Note that this is called from interrupt context, so it cannot block. */ - void (*set_maintenance_mode)(void *send_info, int enable); + void (*set_maintenance_mode)(void *send_info, bool enable); /* Tell the handler that we are using it/not using it. The message handler get the modules that this handler belongs From 9a11843987b29b7b7eff650bff7d5731ba5117d5 Mon Sep 17 00:00:00 2001 From: Sergei Antonov Date: Tue, 15 Apr 2014 23:18:37 +0200 Subject: [PATCH 253/279] drm/nouveau/bios: fix a bit shift error introduced by 457e77b Commit 457e77b26428ab4a24998eecfb99f27fa4195397 added two checks applied to a value received from nv_rd32(bios, 0x619f04). But after this new piece of code is executed, the addr local variable does not hold the same value it used to hold before the commit. Here is what is was assigned in the original code: (u64)(nv_rd32(bios, 0x619f04) & 0xffffff00) << 8 in the committed code it ends up with this value: (u64)(nv_rd32(bios, 0x619f04) >> 8) << 8 These expressions are obviously not equivalent. My Nvidia video card does not show anything on the display when I boot a kernel containing this commit. The patch fixes the code so that the new checks are still done, but the side effect of an incorrect addr value is gone. Cc: Ben Skeggs Cc: Dave Airlie Cc: Andrew Morton Signed-off-by: Sergei Antonov Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/core/subdev/bios/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c index e9df94f96d7827..fb0b6b2d1427f4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/base.c @@ -109,7 +109,7 @@ nouveau_bios_shadow_pramin(struct nouveau_bios *bios) return; } - addr = (u64)(addr >> 8) << 8; + addr = (addr & 0xffffff00) << 8; if (!addr) { addr = (u64)nv_rd32(bios, 0x001700) << 16; addr += 0xf0000; From a82049b1f1aeb02818092455cd43134ef83d81ea Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Wed, 16 Apr 2014 19:42:24 +1000 Subject: [PATCH 254/279] drm/ast: fix value check in cbr_scan2 this is a typo vs the ums driver, fix to check correct value. Found initially by Coverity. Reported-by: Daniel Vetter Signed-off-by: Dave Airlie --- drivers/gpu/drm/ast/ast_post.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 977cfb35837a00..635f6ffc27c285 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -572,7 +572,7 @@ static u32 cbr_scan2(struct ast_private *ast) for (loop = 0; loop < CBR_PASSNUM2; loop++) { if ((data = cbr_test2(ast)) != 0) { data2 &= data; - if (!data) + if (!data2) return 0; break; } From b6ccd7b9873dc46becd11838c885d5c783784156 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 15 Apr 2014 10:02:43 +0200 Subject: [PATCH 255/279] drm/plane-helper: Don't fake-implement primary plane disabling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After thinking about this topic a bit more I've reached the conclusion that implementing this doesn't make sense: - The locking is all wrong: set_config(NULL) will also unlink encoders and connectors, but those links are protected with the mode_config mutex. In the ->disable_plane callback we only hold all modeset locks, but eventually we want to switch to just grabbing the per-crtc (and maybe per-plane) locks as needed, maybe based on ww_mutexes. Having a callback which absolutely needs all modeset locks is bad for this conversion. Note that the same isn't true for the provided ->update_plane since we've audited the crtc helpers to make sure that not encoder or connector links are changed. - There's no way to re-enable the plane with an ->update_plane: The connectors/encoder links are lost and so we can't re-enable the CRTC. Even without that issue the driver might have reassigned some shared resources (as opposed to e.g. DPMS off, where drivers are not allowed to do that to make sure the CRTC can be enabled again). - The semantics don't make much sense: Userspace asked to scan out black (or some other color if the driver supports a background color), not that the screen be disabled. - Implementing proper primary plane support (i.e. actually disabling the primary plane without disabling the CRTC) is really simple, at least if all the hw needs is flipping a bit. The big task is auditing all the interactions with other ioctls when the CRTC is on but there's no primary plane (e.g. pageflips). And some of that work still needs to be done. Cc: Matt Roper Signed-off-by: Daniel Vetter Reviewed-by: Ville Syrjälä Reviewed-by: Matt Roper Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_plane_helper.c | 33 +++++------------------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index e768d35ff22ecf..d2b1c03b3d7113 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -203,9 +203,9 @@ EXPORT_SYMBOL(drm_primary_helper_update); * * Provides a default plane disable handler for primary planes. This is handler * is called in response to a userspace SetPlane operation on the plane with a - * NULL framebuffer parameter. We call the driver's modeset handler with a NULL - * framebuffer to disable the CRTC if no other planes are currently enabled. - * If other planes are still enabled on the same CRTC, we return -EBUSY. + * NULL framebuffer parameter. It unconditionally fails the disable call with + * -EINVAL the only way to disable the primary plane without driver support is + * to disable the entier CRTC. Which does not match the plane ->disable hook. * * Note that some hardware may be able to disable the primary plane without * disabling the whole CRTC. Drivers for such hardware should provide their @@ -214,34 +214,11 @@ EXPORT_SYMBOL(drm_primary_helper_update); * disabled primary plane). * * RETURNS: - * Zero on success, error code on failure + * Unconditionally returns -EINVAL. */ int drm_primary_helper_disable(struct drm_plane *plane) { - struct drm_plane *p; - struct drm_mode_set set = { - .crtc = plane->crtc, - .fb = NULL, - }; - - if (plane->crtc == NULL || plane->fb == NULL) - /* Already disabled */ - return 0; - - list_for_each_entry(p, &plane->dev->mode_config.plane_list, head) - if (p != plane && p->fb) { - DRM_DEBUG_KMS("Cannot disable primary plane while other planes are still active on CRTC.\n"); - return -EBUSY; - } - - /* - * N.B. We call set_config() directly here rather than - * drm_mode_set_config_internal() since drm_mode_setplane() already - * handles the basic refcounting and we don't need the special - * cross-CRTC refcounting (no chance of stealing connectors from - * other CRTC's with this update). - */ - return plane->crtc->funcs->set_config(&set); + return -EINVAL; } EXPORT_SYMBOL(drm_primary_helper_disable); From 8d754544202c0e4ef02e9c1abdf379bcf7ef9384 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 10 Apr 2014 10:51:11 +0200 Subject: [PATCH 256/279] drm: Split out drm_probe_helper.c from drm_crtc_helper.c This is leftover stuff from my previous doc round which I kinda wanted to do but didn't yet due to rebase hell. The modeset helpers and the probing helpers a independent and e.g. i915 uses the probing stuff but has its own modeset infrastructure. It hence makes to split this up. While at it add a DOC: comment for the probing libraray. It would be rather neat to pull some of the DocBook documenting these two helpers into in-line DOC: comments. But unfortunately kerneldoc doesn't support markdown or something similar to make nice-looking documentation, so the current state is better. Signed-off-by: Daniel Vetter Signed-off-by: Dave Airlie --- Documentation/DocBook/drm.tmpl | 5 + drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_crtc_helper.c | 370 ------------------------- drivers/gpu/drm/drm_probe_helper.c | 426 +++++++++++++++++++++++++++++ include/drm/drm_crtc_helper.h | 6 +- 5 files changed, 437 insertions(+), 372 deletions(-) create mode 100644 drivers/gpu/drm/drm_probe_helper.c diff --git a/Documentation/DocBook/drm.tmpl b/Documentation/DocBook/drm.tmpl index 702c4474919c54..677a02553ec0cd 100644 --- a/Documentation/DocBook/drm.tmpl +++ b/Documentation/DocBook/drm.tmpl @@ -2285,6 +2285,11 @@ void intel_crt_init(struct drm_device *dev) Modeset Helper Functions Reference !Edrivers/gpu/drm/drm_crtc_helper.c + + + Output Probing Helper Functions Reference +!Pdrivers/gpu/drm/drm_probe_helper.c output probing helper overview +!Edrivers/gpu/drm/drm_probe_helper.c fbdev Helper Functions Reference diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9d25dbbe6771e4..48e38ba2278361 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -23,7 +23,7 @@ drm-$(CONFIG_DRM_PANEL) += drm_panel.o drm-usb-y := drm_usb.o -drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o +drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_probe_helper.o drm_kms_helper-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o drm_kms_helper-$(CONFIG_DRM_KMS_FB_HELPER) += drm_fb_helper.o drm_kms_helper-$(CONFIG_DRM_KMS_CMA_HELPER) += drm_fb_cma_helper.o diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index c43825e8f5c12c..df281b54db0155 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -72,147 +72,6 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) } EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); -static bool drm_kms_helper_poll = true; -module_param_named(poll, drm_kms_helper_poll, bool, 0600); - -static void drm_mode_validate_flag(struct drm_connector *connector, - int flags) -{ - struct drm_display_mode *mode; - - if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | - DRM_MODE_FLAG_3D_MASK)) - return; - - list_for_each_entry(mode, &connector->modes, head) { - if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && - !(flags & DRM_MODE_FLAG_INTERLACE)) - mode->status = MODE_NO_INTERLACE; - if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && - !(flags & DRM_MODE_FLAG_DBLSCAN)) - mode->status = MODE_NO_DBLESCAN; - if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && - !(flags & DRM_MODE_FLAG_3D_MASK)) - mode->status = MODE_NO_STEREO; - } - - return; -} - -/** - * drm_helper_probe_single_connector_modes - get complete set of display modes - * @connector: connector to probe - * @maxX: max width for modes - * @maxY: max height for modes - * - * Based on the helper callbacks implemented by @connector try to detect all - * valid modes. Modes will first be added to the connector's probed_modes list, - * then culled (based on validity and the @maxX, @maxY parameters) and put into - * the normal modes list. - * - * Intended to be use as a generic implementation of the ->fill_modes() - * @connector vfunc for drivers that use the crtc helpers for output mode - * filtering and detection. - * - * Returns: - * The number of modes found on @connector. - */ -int drm_helper_probe_single_connector_modes(struct drm_connector *connector, - uint32_t maxX, uint32_t maxY) -{ - struct drm_device *dev = connector->dev; - struct drm_display_mode *mode; - struct drm_connector_helper_funcs *connector_funcs = - connector->helper_private; - int count = 0; - int mode_flags = 0; - bool verbose_prune = true; - - WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); - - DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, - drm_get_connector_name(connector)); - /* set all modes to the unverified state */ - list_for_each_entry(mode, &connector->modes, head) - mode->status = MODE_UNVERIFIED; - - if (connector->force) { - if (connector->force == DRM_FORCE_ON) - connector->status = connector_status_connected; - else - connector->status = connector_status_disconnected; - if (connector->funcs->force) - connector->funcs->force(connector); - } else { - connector->status = connector->funcs->detect(connector, true); - } - - /* Re-enable polling in case the global poll config changed. */ - if (drm_kms_helper_poll != dev->mode_config.poll_running) - drm_kms_helper_poll_enable(dev); - - dev->mode_config.poll_running = drm_kms_helper_poll; - - if (connector->status == connector_status_disconnected) { - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", - connector->base.id, drm_get_connector_name(connector)); - drm_mode_connector_update_edid_property(connector, NULL); - verbose_prune = false; - goto prune; - } - -#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE - count = drm_load_edid_firmware(connector); - if (count == 0) -#endif - count = (*connector_funcs->get_modes)(connector); - - if (count == 0 && connector->status == connector_status_connected) - count = drm_add_modes_noedid(connector, 1024, 768); - if (count == 0) - goto prune; - - drm_mode_connector_list_update(connector); - - if (maxX && maxY) - drm_mode_validate_size(dev, &connector->modes, maxX, maxY); - - if (connector->interlace_allowed) - mode_flags |= DRM_MODE_FLAG_INTERLACE; - if (connector->doublescan_allowed) - mode_flags |= DRM_MODE_FLAG_DBLSCAN; - if (connector->stereo_allowed) - mode_flags |= DRM_MODE_FLAG_3D_MASK; - drm_mode_validate_flag(connector, mode_flags); - - list_for_each_entry(mode, &connector->modes, head) { - if (mode->status == MODE_OK) - mode->status = connector_funcs->mode_valid(connector, - mode); - } - -prune: - drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); - - if (list_empty(&connector->modes)) - return 0; - - list_for_each_entry(mode, &connector->modes, head) - mode->vrefresh = drm_mode_vrefresh(mode); - - drm_mode_sort(&connector->modes); - - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, - drm_get_connector_name(connector)); - list_for_each_entry(mode, &connector->modes, head) { - drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); - drm_mode_debug_printmodeline(mode); - } - - return count; -} -EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); - /** * drm_helper_encoder_in_use - check if a given encoder is in use * @encoder: encoder to check @@ -1020,232 +879,3 @@ void drm_helper_resume_force_mode(struct drm_device *dev) drm_modeset_unlock_all(dev); } EXPORT_SYMBOL(drm_helper_resume_force_mode); - -/** - * drm_kms_helper_hotplug_event - fire off KMS hotplug events - * @dev: drm_device whose connector state changed - * - * This function fires off the uevent for userspace and also calls the - * output_poll_changed function, which is most commonly used to inform the fbdev - * emulation code and allow it to update the fbcon output configuration. - * - * Drivers should call this from their hotplug handling code when a change is - * detected. Note that this function does not do any output detection of its - * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the - * driver already. - * - * This function must be called from process context with no mode - * setting locks held. - */ -void drm_kms_helper_hotplug_event(struct drm_device *dev) -{ - /* send a uevent + call fbdev */ - drm_sysfs_hotplug_event(dev); - if (dev->mode_config.funcs->output_poll_changed) - dev->mode_config.funcs->output_poll_changed(dev); -} -EXPORT_SYMBOL(drm_kms_helper_hotplug_event); - -#define DRM_OUTPUT_POLL_PERIOD (10*HZ) -static void output_poll_execute(struct work_struct *work) -{ - struct delayed_work *delayed_work = to_delayed_work(work); - struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); - struct drm_connector *connector; - enum drm_connector_status old_status; - bool repoll = false, changed = false; - - if (!drm_kms_helper_poll) - return; - - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - - /* Ignore forced connectors. */ - if (connector->force) - continue; - - /* Ignore HPD capable connectors and connectors where we don't - * want any hotplug detection at all for polling. */ - if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) - continue; - - repoll = true; - - old_status = connector->status; - /* if we are connected and don't want to poll for disconnect - skip it */ - if (old_status == connector_status_connected && - !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) - continue; - - connector->status = connector->funcs->detect(connector, false); - if (old_status != connector->status) { - const char *old, *new; - - old = drm_get_connector_status_name(old_status); - new = drm_get_connector_status_name(connector->status); - - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " - "status updated from %s to %s\n", - connector->base.id, - drm_get_connector_name(connector), - old, new); - - changed = true; - } - } - - mutex_unlock(&dev->mode_config.mutex); - - if (changed) - drm_kms_helper_hotplug_event(dev); - - if (repoll) - schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); -} - -/** - * drm_kms_helper_poll_disable - disable output polling - * @dev: drm_device - * - * This function disables the output polling work. - * - * Drivers can call this helper from their device suspend implementation. It is - * not an error to call this even when output polling isn't enabled or arlready - * disabled. - */ -void drm_kms_helper_poll_disable(struct drm_device *dev) -{ - if (!dev->mode_config.poll_enabled) - return; - cancel_delayed_work_sync(&dev->mode_config.output_poll_work); -} -EXPORT_SYMBOL(drm_kms_helper_poll_disable); - -/** - * drm_kms_helper_poll_enable - re-enable output polling. - * @dev: drm_device - * - * This function re-enables the output polling work. - * - * Drivers can call this helper from their device resume implementation. It is - * an error to call this when the output polling support has not yet been set - * up. - */ -void drm_kms_helper_poll_enable(struct drm_device *dev) -{ - bool poll = false; - struct drm_connector *connector; - - if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) - return; - - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT)) - poll = true; - } - - if (poll) - schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); -} -EXPORT_SYMBOL(drm_kms_helper_poll_enable); - -/** - * drm_kms_helper_poll_init - initialize and enable output polling - * @dev: drm_device - * - * This function intializes and then also enables output polling support for - * @dev. Drivers which do not have reliable hotplug support in hardware can use - * this helper infrastructure to regularly poll such connectors for changes in - * their connection state. - * - * Drivers can control which connectors are polled by setting the - * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On - * connectors where probing live outputs can result in visual distortion drivers - * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. - * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are - * completely ignored by the polling logic. - * - * Note that a connector can be both polled and probed from the hotplug handler, - * in case the hotplug interrupt is known to be unreliable. - */ -void drm_kms_helper_poll_init(struct drm_device *dev) -{ - INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); - dev->mode_config.poll_enabled = true; - - drm_kms_helper_poll_enable(dev); -} -EXPORT_SYMBOL(drm_kms_helper_poll_init); - -/** - * drm_kms_helper_poll_fini - disable output polling and clean it up - * @dev: drm_device - */ -void drm_kms_helper_poll_fini(struct drm_device *dev) -{ - drm_kms_helper_poll_disable(dev); -} -EXPORT_SYMBOL(drm_kms_helper_poll_fini); - -/** - * drm_helper_hpd_irq_event - hotplug processing - * @dev: drm_device - * - * Drivers can use this helper function to run a detect cycle on all connectors - * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All - * other connectors are ignored, which is useful to avoid reprobing fixed - * panels. - * - * This helper function is useful for drivers which can't or don't track hotplug - * interrupts for each connector. - * - * Drivers which support hotplug interrupts for each connector individually and - * which have a more fine-grained detect logic should bypass this code and - * directly call drm_kms_helper_hotplug_event() in case the connector state - * changed. - * - * This function must be called from process context with no mode - * setting locks held. - * - * Note that a connector can be both polled and probed from the hotplug handler, - * in case the hotplug interrupt is known to be unreliable. - */ -bool drm_helper_hpd_irq_event(struct drm_device *dev) -{ - struct drm_connector *connector; - enum drm_connector_status old_status; - bool changed = false; - - if (!dev->mode_config.poll_enabled) - return false; - - mutex_lock(&dev->mode_config.mutex); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - - /* Only handle HPD capable connectors. */ - if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) - continue; - - old_status = connector->status; - - connector->status = connector->funcs->detect(connector, false); - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", - connector->base.id, - drm_get_connector_name(connector), - drm_get_connector_status_name(old_status), - drm_get_connector_status_name(connector->status)); - if (old_status != connector->status) - changed = true; - } - - mutex_unlock(&dev->mode_config.mutex); - - if (changed) - drm_kms_helper_hotplug_event(dev); - - return changed; -} -EXPORT_SYMBOL(drm_helper_hpd_irq_event); diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c new file mode 100644 index 00000000000000..e70f54d4a5810c --- /dev/null +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -0,0 +1,426 @@ +/* + * Copyright (c) 2006-2008 Intel Corporation + * Copyright (c) 2007 Dave Airlie + * + * DRM core CRTC related functions + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + * + * Authors: + * Keith Packard + * Eric Anholt + * Dave Airlie + * Jesse Barnes + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +/** + * DOC: output probing helper overview + * + * This library provides some helper code for output probing. It provides an + * implementation of the core connector->fill_modes interface with + * drm_helper_probe_single_connector_modes. + * + * It also provides support for polling connectors with a work item and for + * generic hotplug interrupt handling where the driver doesn't or cannot keep + * track of a per-connector hpd interrupt. + * + * This helper library can be used independently of the modeset helper library. + * Drivers can also overwrite different parts e.g. use their own hotplug + * handling code to avoid probing unrelated outputs. + */ + +static bool drm_kms_helper_poll = true; +module_param_named(poll, drm_kms_helper_poll, bool, 0600); + +static void drm_mode_validate_flag(struct drm_connector *connector, + int flags) +{ + struct drm_display_mode *mode; + + if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | + DRM_MODE_FLAG_3D_MASK)) + return; + + list_for_each_entry(mode, &connector->modes, head) { + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && + !(flags & DRM_MODE_FLAG_INTERLACE)) + mode->status = MODE_NO_INTERLACE; + if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && + !(flags & DRM_MODE_FLAG_DBLSCAN)) + mode->status = MODE_NO_DBLESCAN; + if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && + !(flags & DRM_MODE_FLAG_3D_MASK)) + mode->status = MODE_NO_STEREO; + } + + return; +} + +/** + * drm_helper_probe_single_connector_modes - get complete set of display modes + * @connector: connector to probe + * @maxX: max width for modes + * @maxY: max height for modes + * + * Based on the helper callbacks implemented by @connector try to detect all + * valid modes. Modes will first be added to the connector's probed_modes list, + * then culled (based on validity and the @maxX, @maxY parameters) and put into + * the normal modes list. + * + * Intended to be use as a generic implementation of the ->fill_modes() + * @connector vfunc for drivers that use the crtc helpers for output mode + * filtering and detection. + * + * Returns: + * The number of modes found on @connector. + */ +int drm_helper_probe_single_connector_modes(struct drm_connector *connector, + uint32_t maxX, uint32_t maxY) +{ + struct drm_device *dev = connector->dev; + struct drm_display_mode *mode; + struct drm_connector_helper_funcs *connector_funcs = + connector->helper_private; + int count = 0; + int mode_flags = 0; + bool verbose_prune = true; + + WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, + drm_get_connector_name(connector)); + /* set all modes to the unverified state */ + list_for_each_entry(mode, &connector->modes, head) + mode->status = MODE_UNVERIFIED; + + if (connector->force) { + if (connector->force == DRM_FORCE_ON) + connector->status = connector_status_connected; + else + connector->status = connector_status_disconnected; + if (connector->funcs->force) + connector->funcs->force(connector); + } else { + connector->status = connector->funcs->detect(connector, true); + } + + /* Re-enable polling in case the global poll config changed. */ + if (drm_kms_helper_poll != dev->mode_config.poll_running) + drm_kms_helper_poll_enable(dev); + + dev->mode_config.poll_running = drm_kms_helper_poll; + + if (connector->status == connector_status_disconnected) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", + connector->base.id, drm_get_connector_name(connector)); + drm_mode_connector_update_edid_property(connector, NULL); + verbose_prune = false; + goto prune; + } + +#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE + count = drm_load_edid_firmware(connector); + if (count == 0) +#endif + count = (*connector_funcs->get_modes)(connector); + + if (count == 0 && connector->status == connector_status_connected) + count = drm_add_modes_noedid(connector, 1024, 768); + if (count == 0) + goto prune; + + drm_mode_connector_list_update(connector); + + if (maxX && maxY) + drm_mode_validate_size(dev, &connector->modes, maxX, maxY); + + if (connector->interlace_allowed) + mode_flags |= DRM_MODE_FLAG_INTERLACE; + if (connector->doublescan_allowed) + mode_flags |= DRM_MODE_FLAG_DBLSCAN; + if (connector->stereo_allowed) + mode_flags |= DRM_MODE_FLAG_3D_MASK; + drm_mode_validate_flag(connector, mode_flags); + + list_for_each_entry(mode, &connector->modes, head) { + if (mode->status == MODE_OK) + mode->status = connector_funcs->mode_valid(connector, + mode); + } + +prune: + drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); + + if (list_empty(&connector->modes)) + return 0; + + list_for_each_entry(mode, &connector->modes, head) + mode->vrefresh = drm_mode_vrefresh(mode); + + drm_mode_sort(&connector->modes); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, + drm_get_connector_name(connector)); + list_for_each_entry(mode, &connector->modes, head) { + drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); + drm_mode_debug_printmodeline(mode); + } + + return count; +} +EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); + +/** + * drm_kms_helper_hotplug_event - fire off KMS hotplug events + * @dev: drm_device whose connector state changed + * + * This function fires off the uevent for userspace and also calls the + * output_poll_changed function, which is most commonly used to inform the fbdev + * emulation code and allow it to update the fbcon output configuration. + * + * Drivers should call this from their hotplug handling code when a change is + * detected. Note that this function does not do any output detection of its + * own, like drm_helper_hpd_irq_event() does - this is assumed to be done by the + * driver already. + * + * This function must be called from process context with no mode + * setting locks held. + */ +void drm_kms_helper_hotplug_event(struct drm_device *dev) +{ + /* send a uevent + call fbdev */ + drm_sysfs_hotplug_event(dev); + if (dev->mode_config.funcs->output_poll_changed) + dev->mode_config.funcs->output_poll_changed(dev); +} +EXPORT_SYMBOL(drm_kms_helper_hotplug_event); + +#define DRM_OUTPUT_POLL_PERIOD (10*HZ) +static void output_poll_execute(struct work_struct *work) +{ + struct delayed_work *delayed_work = to_delayed_work(work); + struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); + struct drm_connector *connector; + enum drm_connector_status old_status; + bool repoll = false, changed = false; + + if (!drm_kms_helper_poll) + return; + + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + + /* Ignore forced connectors. */ + if (connector->force) + continue; + + /* Ignore HPD capable connectors and connectors where we don't + * want any hotplug detection at all for polling. */ + if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) + continue; + + repoll = true; + + old_status = connector->status; + /* if we are connected and don't want to poll for disconnect + skip it */ + if (old_status == connector_status_connected && + !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) + continue; + + connector->status = connector->funcs->detect(connector, false); + if (old_status != connector->status) { + const char *old, *new; + + old = drm_get_connector_status_name(old_status); + new = drm_get_connector_status_name(connector->status); + + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " + "status updated from %s to %s\n", + connector->base.id, + drm_get_connector_name(connector), + old, new); + + changed = true; + } + } + + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); + + if (repoll) + schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); +} + +/** + * drm_kms_helper_poll_disable - disable output polling + * @dev: drm_device + * + * This function disables the output polling work. + * + * Drivers can call this helper from their device suspend implementation. It is + * not an error to call this even when output polling isn't enabled or arlready + * disabled. + */ +void drm_kms_helper_poll_disable(struct drm_device *dev) +{ + if (!dev->mode_config.poll_enabled) + return; + cancel_delayed_work_sync(&dev->mode_config.output_poll_work); +} +EXPORT_SYMBOL(drm_kms_helper_poll_disable); + +/** + * drm_kms_helper_poll_enable - re-enable output polling. + * @dev: drm_device + * + * This function re-enables the output polling work. + * + * Drivers can call this helper from their device resume implementation. It is + * an error to call this when the output polling support has not yet been set + * up. + */ +void drm_kms_helper_poll_enable(struct drm_device *dev) +{ + bool poll = false; + struct drm_connector *connector; + + if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) + return; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | + DRM_CONNECTOR_POLL_DISCONNECT)) + poll = true; + } + + if (poll) + schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); +} +EXPORT_SYMBOL(drm_kms_helper_poll_enable); + +/** + * drm_kms_helper_poll_init - initialize and enable output polling + * @dev: drm_device + * + * This function intializes and then also enables output polling support for + * @dev. Drivers which do not have reliable hotplug support in hardware can use + * this helper infrastructure to regularly poll such connectors for changes in + * their connection state. + * + * Drivers can control which connectors are polled by setting the + * DRM_CONNECTOR_POLL_CONNECT and DRM_CONNECTOR_POLL_DISCONNECT flags. On + * connectors where probing live outputs can result in visual distortion drivers + * should not set the DRM_CONNECTOR_POLL_DISCONNECT flag to avoid this. + * Connectors which have no flag or only DRM_CONNECTOR_POLL_HPD set are + * completely ignored by the polling logic. + * + * Note that a connector can be both polled and probed from the hotplug handler, + * in case the hotplug interrupt is known to be unreliable. + */ +void drm_kms_helper_poll_init(struct drm_device *dev) +{ + INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); + dev->mode_config.poll_enabled = true; + + drm_kms_helper_poll_enable(dev); +} +EXPORT_SYMBOL(drm_kms_helper_poll_init); + +/** + * drm_kms_helper_poll_fini - disable output polling and clean it up + * @dev: drm_device + */ +void drm_kms_helper_poll_fini(struct drm_device *dev) +{ + drm_kms_helper_poll_disable(dev); +} +EXPORT_SYMBOL(drm_kms_helper_poll_fini); + +/** + * drm_helper_hpd_irq_event - hotplug processing + * @dev: drm_device + * + * Drivers can use this helper function to run a detect cycle on all connectors + * which have the DRM_CONNECTOR_POLL_HPD flag set in their &polled member. All + * other connectors are ignored, which is useful to avoid reprobing fixed + * panels. + * + * This helper function is useful for drivers which can't or don't track hotplug + * interrupts for each connector. + * + * Drivers which support hotplug interrupts for each connector individually and + * which have a more fine-grained detect logic should bypass this code and + * directly call drm_kms_helper_hotplug_event() in case the connector state + * changed. + * + * This function must be called from process context with no mode + * setting locks held. + * + * Note that a connector can be both polled and probed from the hotplug handler, + * in case the hotplug interrupt is known to be unreliable. + */ +bool drm_helper_hpd_irq_event(struct drm_device *dev) +{ + struct drm_connector *connector; + enum drm_connector_status old_status; + bool changed = false; + + if (!dev->mode_config.poll_enabled) + return false; + + mutex_lock(&dev->mode_config.mutex); + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + + /* Only handle HPD capable connectors. */ + if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) + continue; + + old_status = connector->status; + + connector->status = connector->funcs->detect(connector, false); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", + connector->base.id, + drm_get_connector_name(connector), + drm_get_connector_status_name(old_status), + drm_get_connector_status_name(connector->status)); + if (old_status != connector->status) + changed = true; + } + + mutex_unlock(&dev->mode_config.mutex); + + if (changed) + drm_kms_helper_hotplug_event(dev); + + return changed; +} +EXPORT_SYMBOL(drm_helper_hpd_irq_event); diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h index 0bb34ca2ad2be8..36a5febac2a600 100644 --- a/include/drm/drm_crtc_helper.h +++ b/include/drm/drm_crtc_helper.h @@ -125,7 +125,6 @@ struct drm_connector_helper_funcs { struct drm_encoder *(*best_encoder)(struct drm_connector *connector); }; -extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); extern void drm_helper_disable_unused_functions(struct drm_device *dev); extern int drm_crtc_helper_set_config(struct drm_mode_set *set); extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, @@ -161,6 +160,11 @@ static inline void drm_connector_helper_add(struct drm_connector *connector, } extern void drm_helper_resume_force_mode(struct drm_device *dev); + +/* drm_probe_helper.c */ +extern int drm_helper_probe_single_connector_modes(struct drm_connector + *connector, uint32_t maxX, + uint32_t maxY); extern void drm_kms_helper_poll_init(struct drm_device *dev); extern void drm_kms_helper_poll_fini(struct drm_device *dev); extern bool drm_helper_hpd_irq_event(struct drm_device *dev); From 2f1e800799bf478494cec3573cd63eb34ca89c9d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 14 Apr 2014 11:34:48 +0200 Subject: [PATCH 257/279] drm: cirrus: add power management support cirrus kms driver lacks power management support, thus the vga display doesn't work any more after S3 resume. Fix this by adding suspend and resume functions. Also make the mode_set function unblank the screen. Signed-off-by: Gerd Hoffmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/cirrus/cirrus_drv.c | 42 ++++++++++++++++++++++++++++ drivers/gpu/drm/cirrus/cirrus_mode.c | 3 ++ 2 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c index 953fc8aea69c14..08ce520f61a5aa 100644 --- a/drivers/gpu/drm/cirrus/cirrus_drv.c +++ b/drivers/gpu/drm/cirrus/cirrus_drv.c @@ -11,6 +11,7 @@ #include #include #include +#include #include "cirrus_drv.h" @@ -75,6 +76,41 @@ static void cirrus_pci_remove(struct pci_dev *pdev) drm_put_dev(dev); } +static int cirrus_pm_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct cirrus_device *cdev = drm_dev->dev_private; + + drm_kms_helper_poll_disable(drm_dev); + + if (cdev->mode_info.gfbdev) { + console_lock(); + fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 1); + console_unlock(); + } + + return 0; +} + +static int cirrus_pm_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct cirrus_device *cdev = drm_dev->dev_private; + + drm_helper_resume_force_mode(drm_dev); + + if (cdev->mode_info.gfbdev) { + console_lock(); + fb_set_suspend(cdev->mode_info.gfbdev->helper.fbdev, 0); + console_unlock(); + } + + drm_kms_helper_poll_enable(drm_dev); + return 0; +} + static const struct file_operations cirrus_driver_fops = { .owner = THIS_MODULE, .open = drm_open, @@ -103,11 +139,17 @@ static struct drm_driver driver = { .dumb_destroy = drm_gem_dumb_destroy, }; +static const struct dev_pm_ops cirrus_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(cirrus_pm_suspend, + cirrus_pm_resume) +}; + static struct pci_driver cirrus_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, .probe = cirrus_pci_probe, .remove = cirrus_pci_remove, + .driver.pm = &cirrus_pm_ops, }; static int __init cirrus_init(void) diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index 2d64aea83df21a..f59433b7610c56 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -308,6 +308,9 @@ static int cirrus_crtc_mode_set(struct drm_crtc *crtc, WREG_HDR(hdr); cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0); + + /* Unblank (needed on S3 resume, vgabios doesn't do it then) */ + outb(0x20, 0x3c0); return 0; } From b8ccd70f1363f7d4e49219dbc46ec973a14f49cd Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 14 Apr 2014 11:34:49 +0200 Subject: [PATCH 258/279] drm: bochs: add power management support bochs kms driver lacks power management support, thus the vga display doesn't work any more after S3 resume. Fix this by adding suspend and resume functions. Signed-off-by: Gerd Hoffmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/bochs/bochs.h | 1 + drivers/gpu/drm/bochs/bochs_drv.c | 44 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 741965c001a687..460820551b0995 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -1,5 +1,6 @@ #include #include +#include #include #include diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 395bba261c9a6d..9c13df29fd20ea 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -94,6 +94,49 @@ static struct drm_driver bochs_driver = { .dumb_destroy = drm_gem_dumb_destroy, }; +/* ---------------------------------------------------------------------- */ +/* pm interface */ + +static int bochs_pm_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct bochs_device *bochs = drm_dev->dev_private; + + drm_kms_helper_poll_disable(drm_dev); + + if (bochs->fb.initialized) { + console_lock(); + fb_set_suspend(bochs->fb.helper.fbdev, 1); + console_unlock(); + } + + return 0; +} + +static int bochs_pm_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct bochs_device *bochs = drm_dev->dev_private; + + drm_helper_resume_force_mode(drm_dev); + + if (bochs->fb.initialized) { + console_lock(); + fb_set_suspend(bochs->fb.helper.fbdev, 0); + console_unlock(); + } + + drm_kms_helper_poll_enable(drm_dev); + return 0; +} + +static const struct dev_pm_ops bochs_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(bochs_pm_suspend, + bochs_pm_resume) +}; + /* ---------------------------------------------------------------------- */ /* pci interface */ @@ -155,6 +198,7 @@ static struct pci_driver bochs_pci_driver = { .id_table = bochs_pci_tbl, .probe = bochs_pci_probe, .remove = bochs_pci_remove, + .driver.pm = &bochs_pm_ops, }; /* ---------------------------------------------------------------------- */ From c044330baa91b6885597cfaaa58b00b6aa690958 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Mon, 14 Apr 2014 11:34:50 +0200 Subject: [PATCH 259/279] drm: bochs: drop unused struct fields Signed-off-by: Gerd Hoffmann Signed-off-by: Dave Airlie --- drivers/gpu/drm/bochs/bochs.h | 2 -- drivers/gpu/drm/bochs/bochs_fbdev.c | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 460820551b0995..7eb52dd44b0109 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -88,8 +88,6 @@ struct bochs_device { struct bochs_framebuffer gfb; struct drm_fb_helper helper; int size; - int x1, y1, x2, y2; /* dirty rect */ - spinlock_t dirty_lock; bool initialized; } fb; }; diff --git a/drivers/gpu/drm/bochs/bochs_fbdev.c b/drivers/gpu/drm/bochs/bochs_fbdev.c index 4da5206b7cc975..561b84474122a0 100644 --- a/drivers/gpu/drm/bochs/bochs_fbdev.c +++ b/drivers/gpu/drm/bochs/bochs_fbdev.c @@ -190,7 +190,6 @@ int bochs_fbdev_init(struct bochs_device *bochs) int ret; bochs->fb.helper.funcs = &bochs_fb_helper_funcs; - spin_lock_init(&bochs->fb.dirty_lock); ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, 1, 1); From 20cd477c398decd6a8461ac48609b6c0ab4c7567 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 16 Apr 2014 10:49:20 +0400 Subject: [PATCH 260/279] of: add empty of_find_node_by_path() for !OF Add an empty version of of_find_node_by_path(). This fixes following build error for asoc tree: sound/soc/fsl/fsl_ssi.c: In function 'fsl_ssi_probe': sound/soc/fsl/fsl_ssi.c:1471:2: error: implicit declaration of function 'of_find_node_by_path' [-Werror=implicit-function-declaration] sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL); Reported-by: Stephen Rothwell Signed-off-by: Alexander Shiyan Signed-off-by: Rob Herring --- include/linux/of.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/linux/of.h b/include/linux/of.h index 919bf211877db7..3bad8d106e0ea0 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -374,6 +374,11 @@ static inline struct device_node *of_find_matching_node_and_match( return NULL; } +static inline struct device_node *of_find_node_by_path(const char *path) +{ + return NULL; +} + static inline struct device_node *of_get_parent(const struct device_node *node) { return NULL; From 64ee9f32c33cbd53545284742e73c17fedf9d429 Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Fri, 18 Apr 2014 13:38:34 +0530 Subject: [PATCH 261/279] ARC: Delete stale barrier.h Commit 93ea02bb8435 ("arch: Clean up asm/barrier.h implementations") wired generic barrier.h for ARC, but failed to delete the existing file. In 3.15, due to rcupdate.h updates, this causes a build breakage on ARC: CC arch/arc/kernel/asm-offsets.s In file included from include/linux/sched.h:45:0, from arch/arc/kernel/asm-offsets.c:9: include/linux/rculist.h: In function __list_add_rcu: include/linux/rculist.h:54:2: error: implicit declaration of function smp_store_release [-Werror=implicit-function-declaration] rcu_assign_pointer(list_next_rcu(prev), new); ^ Cc: Peter Zijlstra Signed-off-by: Vineet Gupta Signed-off-by: Linus Torvalds --- arch/arc/include/asm/barrier.h | 37 ---------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 arch/arc/include/asm/barrier.h diff --git a/arch/arc/include/asm/barrier.h b/arch/arc/include/asm/barrier.h deleted file mode 100644 index c32245c3d1e9b5..00000000000000 --- a/arch/arc/include/asm/barrier.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __ASM_BARRIER_H -#define __ASM_BARRIER_H - -#ifndef __ASSEMBLY__ - -/* TODO-vineetg: Need to see what this does, don't we need sync anywhere */ -#define mb() __asm__ __volatile__ ("" : : : "memory") -#define rmb() mb() -#define wmb() mb() -#define set_mb(var, value) do { var = value; mb(); } while (0) -#define set_wmb(var, value) do { var = value; wmb(); } while (0) -#define read_barrier_depends() mb() - -/* TODO-vineetg verify the correctness of macros here */ -#ifdef CONFIG_SMP -#define smp_mb() mb() -#define smp_rmb() rmb() -#define smp_wmb() wmb() -#else -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#endif - -#define smp_read_barrier_depends() do { } while (0) - -#endif - -#endif From dc8eaaa006350d24030502a4521542e74b5cb39f Mon Sep 17 00:00:00 2001 From: dingtianhong Date: Thu, 17 Apr 2014 18:40:36 +0800 Subject: [PATCH 262/279] vlan: Fix lockdep warning when vlan dev handle notification When I open the LOCKDEP config and run these steps: modprobe 8021q vconfig add eth2 20 vconfig add eth2.20 30 ifconfig eth2 xx.xx.xx.xx then the Call Trace happened: [32524.386288] ============================================= [32524.386293] [ INFO: possible recursive locking detected ] [32524.386298] 3.14.0-rc2-0.7-default+ #35 Tainted: G O [32524.386302] --------------------------------------------- [32524.386306] ifconfig/3103 is trying to acquire lock: [32524.386310] (&vlan_netdev_addr_lock_key/1){+.....}, at: [] dev_mc_sync+0x64/0xb0 [32524.386326] [32524.386326] but task is already holding lock: [32524.386330] (&vlan_netdev_addr_lock_key/1){+.....}, at: [] dev_set_rx_mode+0x23/0x40 [32524.386341] [32524.386341] other info that might help us debug this: [32524.386345] Possible unsafe locking scenario: [32524.386345] [32524.386350] CPU0 [32524.386352] ---- [32524.386354] lock(&vlan_netdev_addr_lock_key/1); [32524.386359] lock(&vlan_netdev_addr_lock_key/1); [32524.386364] [32524.386364] *** DEADLOCK *** [32524.386364] [32524.386368] May be due to missing lock nesting notation [32524.386368] [32524.386373] 2 locks held by ifconfig/3103: [32524.386376] #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x12/0x20 [32524.386387] #1: (&vlan_netdev_addr_lock_key/1){+.....}, at: [] dev_set_rx_mode+0x23/0x40 [32524.386398] [32524.386398] stack backtrace: [32524.386403] CPU: 1 PID: 3103 Comm: ifconfig Tainted: G O 3.14.0-rc2-0.7-default+ #35 [32524.386409] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 [32524.386414] ffffffff81ffae40 ffff8800d9625ae8 ffffffff814f68a2 ffff8800d9625bc8 [32524.386421] ffffffff810a35fb ffff8800d8a8d9d0 00000000d9625b28 ffff8800d8a8e5d0 [32524.386428] 000003cc00000000 0000000000000002 ffff8800d8a8e5f8 0000000000000000 [32524.386435] Call Trace: [32524.386441] [] dump_stack+0x6a/0x78 [32524.386448] [] __lock_acquire+0x7ab/0x1940 [32524.386454] [] ? __lock_acquire+0x3ea/0x1940 [32524.386459] [] lock_acquire+0xe4/0x110 [32524.386464] [] ? dev_mc_sync+0x64/0xb0 [32524.386471] [] _raw_spin_lock_nested+0x2a/0x40 [32524.386476] [] ? dev_mc_sync+0x64/0xb0 [32524.386481] [] dev_mc_sync+0x64/0xb0 [32524.386489] [] vlan_dev_set_rx_mode+0x2b/0x50 [8021q] [32524.386495] [] __dev_set_rx_mode+0x5f/0xb0 [32524.386500] [] dev_set_rx_mode+0x2b/0x40 [32524.386506] [] __dev_open+0xef/0x150 [32524.386511] [] __dev_change_flags+0xa7/0x190 [32524.386516] [] dev_change_flags+0x32/0x80 [32524.386524] [] devinet_ioctl+0x7d6/0x830 [32524.386532] [] ? dev_ioctl+0x34b/0x660 [32524.386540] [] inet_ioctl+0x80/0xa0 [32524.386550] [] sock_do_ioctl+0x2d/0x60 [32524.386558] [] sock_ioctl+0x82/0x2a0 [32524.386568] [] do_vfs_ioctl+0x93/0x590 [32524.386578] [] ? rcu_read_lock_held+0x45/0x50 [32524.386586] [] ? __fget_light+0x105/0x110 [32524.386594] [] SyS_ioctl+0x91/0xb0 [32524.386604] [] system_call_fastpath+0x16/0x1b ======================================================================== The reason is that all of the addr_lock_key for vlan dev have the same class, so if we change the status for vlan dev, the vlan dev and its real dev will hold the same class of addr_lock_key together, so the warning happened. we should distinguish the lock depth for vlan dev and its real dev. v1->v2: Convert the vlan_netdev_addr_lock_key to an array of eight elements, which could support to add 8 vlan id on a same vlan dev, I think it is enough for current scene, because a netdev's name is limited to IFNAMSIZ which could not hold 8 vlan id, and the vlan dev would not meet the same class key with its real dev. The new function vlan_dev_get_lockdep_subkey() will return the subkey and make the vlan dev could get a suitable class key. v2->v3: According David's suggestion, I use the subclass to distinguish the lock key for vlan dev and its real dev, but it make no sense, because the difference for subclass in the lock_class_key doesn't mean that the difference class for lock_key, so I use lock_depth to distinguish the different depth for every vlan dev, the same depth of the vlan dev could have the same lock_class_key, I import the MAX_LOCK_DEPTH from the include/linux/sched.h, I think it is enough here, the lockdep should never exceed that value. v3->v4: Add a huge array of locking keys will waste static kernel memory and is not a appropriate method, we could use _nested() variants to fix the problem, calculate the depth for every vlan dev, and use the depth as the subclass for addr_lock_key. Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller --- net/8021q/vlan_dev.c | 46 +++++++++++++++++++++++++++++++++++++++----- net/core/dev.c | 1 + 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 6f142f03716d04..733ec283ed1b9e 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -493,10 +493,48 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) } } +static int vlan_calculate_locking_subclass(struct net_device *real_dev) +{ + int subclass = 0; + + while (is_vlan_dev(real_dev)) { + subclass++; + real_dev = vlan_dev_priv(real_dev)->real_dev; + } + + return subclass; +} + +static void vlan_dev_mc_sync(struct net_device *to, struct net_device *from) +{ + int err = 0, subclass; + + subclass = vlan_calculate_locking_subclass(to); + + spin_lock_nested(&to->addr_list_lock, subclass); + err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); + if (!err) + __dev_set_rx_mode(to); + spin_unlock(&to->addr_list_lock); +} + +static void vlan_dev_uc_sync(struct net_device *to, struct net_device *from) +{ + int err = 0, subclass; + + subclass = vlan_calculate_locking_subclass(to); + + spin_lock_nested(&to->addr_list_lock, subclass); + err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); + if (!err) + __dev_set_rx_mode(to); + spin_unlock(&to->addr_list_lock); +} + static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) { - dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); - dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); + vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); + vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); } /* @@ -608,9 +646,7 @@ static int vlan_dev_init(struct net_device *dev) SET_NETDEV_DEVTYPE(dev, &vlan_type); - if (is_vlan_dev(real_dev)) - subclass = 1; - + subclass = vlan_calculate_locking_subclass(dev); vlan_dev_set_lockdep_class(dev, subclass); vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); diff --git a/net/core/dev.c b/net/core/dev.c index 5b3042e69f8564..d2c8a06b3a9883 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5238,6 +5238,7 @@ void __dev_set_rx_mode(struct net_device *dev) if (ops->ndo_set_rx_mode) ops->ndo_set_rx_mode(dev); } +EXPORT_SYMBOL(__dev_set_rx_mode); void dev_set_rx_mode(struct net_device *dev) { From ba67b510035141bd89b40bf65efa0a79834311ca Mon Sep 17 00:00:00 2001 From: Ivan Vecera Date: Thu, 17 Apr 2014 14:51:08 +0200 Subject: [PATCH 263/279] tg3: update rx_jumbo_pending ring param only when jumbo frames are enabled The patch fixes a problem with dropped jumbo frames after usage of 'ethtool -G ... rx'. Scenario: 1. ip link set eth0 up 2. ethtool -G eth0 rx N # <- This zeroes rx-jumbo 3. ip link set mtu 9000 dev eth0 The ethtool command set rx_jumbo_pending to zero so any received jumbo packets are dropped and you need to use 'ethtool -G eth0 rx-jumbo N' to workaround the issue. The patch changes the logic so rx_jumbo_pending value is changed only if jumbo frames are enabled (MTU > 1500). Signed-off-by: Ivan Vecera Acked-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/tg3.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index b9f7022f4e81e1..e5d95c5ce1ad8d 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -12286,7 +12286,9 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e if (tg3_flag(tp, MAX_RXPEND_64) && tp->rx_pending > 63) tp->rx_pending = 63; - tp->rx_jumbo_pending = ering->rx_jumbo_pending; + + if (tg3_flag(tp, JUMBO_RING_ENABLE)) + tp->rx_jumbo_pending = ering->rx_jumbo_pending; for (i = 0; i < tp->irq_max; i++) tp->napi[i].tx_pending = ering->tx_pending; From b14878ccb7fac0242db82720b784ab62c467c0dc Mon Sep 17 00:00:00 2001 From: Vlad Yasevich Date: Thu, 17 Apr 2014 17:26:50 +0200 Subject: [PATCH 264/279] net: sctp: cache auth_enable per endpoint Currently, it is possible to create an SCTP socket, then switch auth_enable via sysctl setting to 1 and crash the system on connect: Oops[#1]: CPU: 0 PID: 0 Comm: swapper Not tainted 3.14.1-mipsgit-20140415 #1 task: ffffffff8056ce80 ti: ffffffff8055c000 task.ti: ffffffff8055c000 [...] Call Trace: [] sctp_auth_asoc_set_default_hmac+0x68/0x80 [] sctp_process_init+0x5e0/0x8a4 [] sctp_sf_do_5_1B_init+0x234/0x34c [] sctp_do_sm+0xb4/0x1e8 [] sctp_endpoint_bh_rcv+0x1c4/0x214 [] sctp_rcv+0x588/0x630 [] sctp6_rcv+0x10/0x24 [] ip6_input+0x2c0/0x440 [] __netif_receive_skb_core+0x4a8/0x564 [] process_backlog+0xb4/0x18c [] net_rx_action+0x12c/0x210 [] __do_softirq+0x17c/0x2ac [] irq_exit+0x54/0xb0 [] ret_from_irq+0x0/0x4 [] rm7k_wait_irqoff+0x24/0x48 [] cpu_startup_entry+0xc0/0x148 [] start_kernel+0x37c/0x398 Code: dd0900b8 000330f8 0126302d 50c0fff1 0047182a a48306a0 03e00008 00000000 ---[ end trace b530b0551467f2fd ]--- Kernel panic - not syncing: Fatal exception in interrupt What happens while auth_enable=0 in that case is, that ep->auth_hmacs is initialized to NULL in sctp_auth_init_hmacs() when endpoint is being created. After that point, if an admin switches over to auth_enable=1, the machine can crash due to NULL pointer dereference during reception of an INIT chunk. When we enter sctp_process_init() via sctp_sf_do_5_1B_init() in order to respond to an INIT chunk, the INIT verification succeeds and while we walk and process all INIT params via sctp_process_param() we find that net->sctp.auth_enable is set, therefore do not fall through, but invoke sctp_auth_asoc_set_default_hmac() instead, and thus, dereference what we have set to NULL during endpoint initialization phase. The fix is to make auth_enable immutable by caching its value during endpoint initialization, so that its original value is being carried along until destruction. The bug seems to originate from the very first days. Fix in joint work with Daniel Borkmann. Reported-by: Joshua Kinard Signed-off-by: Vlad Yasevich Signed-off-by: Daniel Borkmann Acked-by: Neil Horman Tested-by: Joshua Kinard Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 4 ++- net/sctp/auth.c | 17 +++++------- net/sctp/endpointola.c | 3 ++- net/sctp/sm_make_chunk.c | 32 +++++++++++----------- net/sctp/sm_statefuns.c | 6 ++--- net/sctp/socket.c | 54 ++++++++++++++++++-------------------- net/sctp/sysctl.c | 36 ++++++++++++++++++++++++- 7 files changed, 92 insertions(+), 60 deletions(-) diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index d992ca3145fec9..0dfcc92600e86c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -1241,6 +1241,7 @@ struct sctp_endpoint { /* SCTP-AUTH: endpoint shared keys */ struct list_head endpoint_shared_keys; __u16 active_key_id; + __u8 auth_enable; }; /* Recover the outter endpoint structure. */ @@ -1269,7 +1270,8 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *, int sctp_has_association(struct net *net, const union sctp_addr *laddr, const union sctp_addr *paddr); -int sctp_verify_init(struct net *net, const struct sctp_association *asoc, +int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep, + const struct sctp_association *asoc, sctp_cid_t, sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk, struct sctp_chunk **err_chunk); int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk, diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 683c7d1b13060a..0e8529113dc5a0 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -386,14 +386,13 @@ int sctp_auth_asoc_copy_shkeys(const struct sctp_endpoint *ep, */ int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) { - struct net *net = sock_net(asoc->base.sk); struct sctp_auth_bytes *secret; struct sctp_shared_key *ep_key; /* If we don't support AUTH, or peer is not capable * we don't need to do anything. */ - if (!net->sctp.auth_enable || !asoc->peer.auth_capable) + if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) return 0; /* If the key_id is non-zero and we couldn't find an @@ -440,16 +439,16 @@ struct sctp_shared_key *sctp_auth_get_shkey( */ int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) { - struct net *net = sock_net(ep->base.sk); struct crypto_hash *tfm = NULL; __u16 id; - /* if the transforms are already allocted, we are done */ - if (!net->sctp.auth_enable) { + /* If AUTH extension is disabled, we are done */ + if (!ep->auth_enable) { ep->auth_hmacs = NULL; return 0; } + /* If the transforms are already allocated, we are done */ if (ep->auth_hmacs) return 0; @@ -665,12 +664,10 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) /* Check if peer requested that this chunk is authenticated */ int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) { - struct net *net; if (!asoc) return 0; - net = sock_net(asoc->base.sk); - if (!net->sctp.auth_enable || !asoc->peer.auth_capable) + if (!asoc->ep->auth_enable || !asoc->peer.auth_capable) return 0; return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); @@ -679,12 +676,10 @@ int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) /* Check if we requested that peer authenticate this chunk. */ int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) { - struct net *net; if (!asoc) return 0; - net = sock_net(asoc->base.sk); - if (!net->sctp.auth_enable) + if (!asoc->ep->auth_enable) return 0; return __sctp_auth_cid(chunk, diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 8e5fdea05216b8..3d9f429858dca2 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -68,7 +68,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, if (!ep->digest) return NULL; - if (net->sctp.auth_enable) { + ep->auth_enable = net->sctp.auth_enable; + if (ep->auth_enable) { /* Allocate space for HMACS and CHUNKS authentication * variables. There are arrays that we encode directly * into parameters to make the rest of the operations easier. diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 3a1767ef3201a6..fee5552ddf929e 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -219,6 +219,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, gfp_t gfp, int vparam_len) { struct net *net = sock_net(asoc->base.sk); + struct sctp_endpoint *ep = asoc->ep; sctp_inithdr_t init; union sctp_params addrs; size_t chunksize; @@ -278,7 +279,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, chunksize += vparam_len; /* Account for AUTH related parameters */ - if (net->sctp.auth_enable) { + if (ep->auth_enable) { /* Add random parameter length*/ chunksize += sizeof(asoc->c.auth_random); @@ -363,7 +364,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, } /* Add SCTP-AUTH chunks to the parameter list */ - if (net->sctp.auth_enable) { + if (ep->auth_enable) { sctp_addto_chunk(retval, sizeof(asoc->c.auth_random), asoc->c.auth_random); if (auth_hmacs) @@ -2010,7 +2011,7 @@ static void sctp_process_ext_param(struct sctp_association *asoc, /* if the peer reports AUTH, assume that he * supports AUTH. */ - if (net->sctp.auth_enable) + if (asoc->ep->auth_enable) asoc->peer.auth_capable = 1; break; case SCTP_CID_ASCONF: @@ -2102,6 +2103,7 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, * SCTP_IERROR_NO_ERROR - continue with the chunk */ static sctp_ierror_t sctp_verify_param(struct net *net, + const struct sctp_endpoint *ep, const struct sctp_association *asoc, union sctp_params param, sctp_cid_t cid, @@ -2152,7 +2154,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, goto fallthrough; case SCTP_PARAM_RANDOM: - if (!net->sctp.auth_enable) + if (!ep->auth_enable) goto fallthrough; /* SCTP-AUTH: Secion 6.1 @@ -2169,7 +2171,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, break; case SCTP_PARAM_CHUNKS: - if (!net->sctp.auth_enable) + if (!ep->auth_enable) goto fallthrough; /* SCTP-AUTH: Section 3.2 @@ -2185,7 +2187,7 @@ static sctp_ierror_t sctp_verify_param(struct net *net, break; case SCTP_PARAM_HMAC_ALGO: - if (!net->sctp.auth_enable) + if (!ep->auth_enable) goto fallthrough; hmacs = (struct sctp_hmac_algo_param *)param.p; @@ -2220,10 +2222,9 @@ static sctp_ierror_t sctp_verify_param(struct net *net, } /* Verify the INIT packet before we process it. */ -int sctp_verify_init(struct net *net, const struct sctp_association *asoc, - sctp_cid_t cid, - sctp_init_chunk_t *peer_init, - struct sctp_chunk *chunk, +int sctp_verify_init(struct net *net, const struct sctp_endpoint *ep, + const struct sctp_association *asoc, sctp_cid_t cid, + sctp_init_chunk_t *peer_init, struct sctp_chunk *chunk, struct sctp_chunk **errp) { union sctp_params param; @@ -2264,8 +2265,8 @@ int sctp_verify_init(struct net *net, const struct sctp_association *asoc, /* Verify all the variable length parameters */ sctp_walk_params(param, peer_init, init_hdr.params) { - - result = sctp_verify_param(net, asoc, param, cid, chunk, errp); + result = sctp_verify_param(net, ep, asoc, param, cid, + chunk, errp); switch (result) { case SCTP_IERROR_ABORT: case SCTP_IERROR_NOMEM: @@ -2497,6 +2498,7 @@ static int sctp_process_param(struct sctp_association *asoc, struct sctp_af *af; union sctp_addr_param *addr_param; struct sctp_transport *t; + struct sctp_endpoint *ep = asoc->ep; /* We maintain all INIT parameters in network byte order all the * time. This allows us to not worry about whether the parameters @@ -2636,7 +2638,7 @@ static int sctp_process_param(struct sctp_association *asoc, goto fall_through; case SCTP_PARAM_RANDOM: - if (!net->sctp.auth_enable) + if (!ep->auth_enable) goto fall_through; /* Save peer's random parameter */ @@ -2649,7 +2651,7 @@ static int sctp_process_param(struct sctp_association *asoc, break; case SCTP_PARAM_HMAC_ALGO: - if (!net->sctp.auth_enable) + if (!ep->auth_enable) goto fall_through; /* Save peer's HMAC list */ @@ -2665,7 +2667,7 @@ static int sctp_process_param(struct sctp_association *asoc, break; case SCTP_PARAM_CHUNKS: - if (!net->sctp.auth_enable) + if (!ep->auth_enable) goto fall_through; asoc->peer.peer_chunks = kmemdup(param.p, diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ae9fbeba40b03c..5170a1ff95a1db 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -357,7 +357,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net, /* Verify the INIT chunk before processing it. */ err_chunk = NULL; - if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, + if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, &err_chunk)) { /* This chunk contains fatal error. It is to be discarded. @@ -524,7 +524,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, /* Verify the INIT chunk before processing it. */ err_chunk = NULL; - if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, + if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, &err_chunk)) { @@ -1430,7 +1430,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( /* Verify the INIT chunk before processing it. */ err_chunk = NULL; - if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, + if (!sctp_verify_init(net, ep, asoc, chunk->chunk_hdr->type, (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, &err_chunk)) { /* This chunk contains fatal error. It is to be discarded. diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ff20e2dbbbc7ef..fee06b99a4da8d 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3321,10 +3321,10 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, char __user *optval, unsigned int optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_authchunk val; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (optlen != sizeof(struct sctp_authchunk)) @@ -3341,7 +3341,7 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, } /* add this chunk id to the endpoint */ - return sctp_auth_ep_add_chunkid(sctp_sk(sk)->ep, val.sauth_chunk); + return sctp_auth_ep_add_chunkid(ep, val.sauth_chunk); } /* @@ -3354,12 +3354,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, char __user *optval, unsigned int optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_hmacalgo *hmacs; u32 idents; int err; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (optlen < sizeof(struct sctp_hmacalgo)) @@ -3376,7 +3376,7 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, goto out; } - err = sctp_auth_ep_set_hmacs(sctp_sk(sk)->ep, hmacs); + err = sctp_auth_ep_set_hmacs(ep, hmacs); out: kfree(hmacs); return err; @@ -3392,12 +3392,12 @@ static int sctp_setsockopt_auth_key(struct sock *sk, char __user *optval, unsigned int optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_authkey *authkey; struct sctp_association *asoc; int ret; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (optlen <= sizeof(struct sctp_authkey)) @@ -3418,7 +3418,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk, goto out; } - ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); + ret = sctp_auth_set_key(ep, asoc, authkey); out: kzfree(authkey); return ret; @@ -3434,11 +3434,11 @@ static int sctp_setsockopt_active_key(struct sock *sk, char __user *optval, unsigned int optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_authkeyid val; struct sctp_association *asoc; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (optlen != sizeof(struct sctp_authkeyid)) @@ -3450,8 +3450,7 @@ static int sctp_setsockopt_active_key(struct sock *sk, if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) return -EINVAL; - return sctp_auth_set_active_key(sctp_sk(sk)->ep, asoc, - val.scact_keynumber); + return sctp_auth_set_active_key(ep, asoc, val.scact_keynumber); } /* @@ -3463,11 +3462,11 @@ static int sctp_setsockopt_del_key(struct sock *sk, char __user *optval, unsigned int optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_authkeyid val; struct sctp_association *asoc; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (optlen != sizeof(struct sctp_authkeyid)) @@ -3479,8 +3478,7 @@ static int sctp_setsockopt_del_key(struct sock *sk, if (!asoc && val.scact_assoc_id && sctp_style(sk, UDP)) return -EINVAL; - return sctp_auth_del_key_id(sctp_sk(sk)->ep, asoc, - val.scact_keynumber); + return sctp_auth_del_key_id(ep, asoc, val.scact_keynumber); } @@ -5387,16 +5385,16 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, char __user *optval, int __user *optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_hmacalgo __user *p = (void __user *)optval; struct sctp_hmac_algo_param *hmacs; __u16 data_len = 0; u32 num_idents; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; - hmacs = sctp_sk(sk)->ep->auth_hmacs_list; + hmacs = ep->auth_hmacs_list; data_len = ntohs(hmacs->param_hdr.length) - sizeof(sctp_paramhdr_t); if (len < sizeof(struct sctp_hmacalgo) + data_len) @@ -5417,11 +5415,11 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, static int sctp_getsockopt_active_key(struct sock *sk, int len, char __user *optval, int __user *optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_authkeyid val; struct sctp_association *asoc; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (len < sizeof(struct sctp_authkeyid)) @@ -5436,7 +5434,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, if (asoc) val.scact_keynumber = asoc->active_key_id; else - val.scact_keynumber = sctp_sk(sk)->ep->active_key_id; + val.scact_keynumber = ep->active_key_id; len = sizeof(struct sctp_authkeyid); if (put_user(len, optlen)) @@ -5450,7 +5448,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, char __user *optval, int __user *optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_authchunks __user *p = (void __user *)optval; struct sctp_authchunks val; struct sctp_association *asoc; @@ -5458,7 +5456,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, u32 num_chunks = 0; char __user *to; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (len < sizeof(struct sctp_authchunks)) @@ -5495,7 +5493,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, char __user *optval, int __user *optlen) { - struct net *net = sock_net(sk); + struct sctp_endpoint *ep = sctp_sk(sk)->ep; struct sctp_authchunks __user *p = (void __user *)optval; struct sctp_authchunks val; struct sctp_association *asoc; @@ -5503,7 +5501,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, u32 num_chunks = 0; char __user *to; - if (!net->sctp.auth_enable) + if (!ep->auth_enable) return -EACCES; if (len < sizeof(struct sctp_authchunks)) @@ -5520,7 +5518,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, if (asoc) ch = (struct sctp_chunks_param *)asoc->c.auth_chunks; else - ch = sctp_sk(sk)->ep->auth_chunk_list; + ch = ep->auth_chunk_list; if (!ch) goto num; diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 35c8923b5554aa..c82fdc1eab7c35 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c @@ -64,6 +64,9 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write, static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos); +static int proc_sctp_do_auth(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos); static struct ctl_table sctp_table[] = { { @@ -266,7 +269,7 @@ static struct ctl_table sctp_net_table[] = { .data = &init_net.sctp.auth_enable, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_sctp_do_auth, }, { .procname = "addr_scope_policy", @@ -400,6 +403,37 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write, return ret; } +static int proc_sctp_do_auth(struct ctl_table *ctl, int write, + void __user *buffer, size_t *lenp, + loff_t *ppos) +{ + struct net *net = current->nsproxy->net_ns; + struct ctl_table tbl; + int new_value, ret; + + memset(&tbl, 0, sizeof(struct ctl_table)); + tbl.maxlen = sizeof(unsigned int); + + if (write) + tbl.data = &new_value; + else + tbl.data = &net->sctp.auth_enable; + + ret = proc_dointvec(&tbl, write, buffer, lenp, ppos); + + if (write) { + struct sock *sk = net->sctp.ctl_sock; + + net->sctp.auth_enable = new_value; + /* Update the value in the control socket */ + lock_sock(sk); + sctp_sk(sk)->ep->auth_enable = new_value; + release_sock(sk); + } + + return ret; +} + int sctp_sysctl_net_register(struct net *net) { struct ctl_table *table = sctp_net_table; From 83da7510058736c09a14b9c17ec7d851940a4332 Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Fri, 18 Apr 2014 15:07:10 -0700 Subject: [PATCH 265/279] vmscan: reclaim_clean_pages_from_list() must use mod_zone_page_state() Seems to be called with preemption enabled. Therefore it must use mod_zone_page_state instead. Signed-off-by: Christoph Lameter Reported-by: Grygorii Strashko Tested-by: Grygorii Strashko Cc: Tejun Heo Cc: Santosh Shilimkar Cc: Ingo Molnar Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmscan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 9b6497eda80678..3f56c8deb3c05f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1158,7 +1158,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, TTU_UNMAP|TTU_IGNORE_ACCESS, &dummy1, &dummy2, &dummy3, &dummy4, &dummy5, true); list_splice(&clean_pages, page_list); - __mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret); + mod_zone_page_state(zone, NR_ISOLATED_FILE, -ret); return ret; } From 82c04ff89eba09d0e46e3f3649c6d3aa18e764a0 Mon Sep 17 00:00:00 2001 From: Peter Foley Date: Fri, 18 Apr 2014 15:07:11 -0700 Subject: [PATCH 266/279] init/Kconfig: move the trusted keyring config option to general setup The SYSTEM_TRUSTED_KEYRING config option is not in any menu, causing it to show up in the toplevel of the kernel configuration. Fix this by moving it under the General Setup menu. Signed-off-by: Peter Foley Cc: David Howells Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/Kconfig | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/init/Kconfig b/init/Kconfig index 765018c24cf9b0..9d3585bb2a7a3c 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1646,6 +1646,18 @@ config MMAP_ALLOW_UNINITIALIZED See Documentation/nommu-mmap.txt for more information. +config SYSTEM_TRUSTED_KEYRING + bool "Provide system-wide ring of trusted keys" + depends on KEYS + help + Provide a system keyring to which trusted keys can be added. Keys in + the keyring are considered to be trusted. Keys may be added at will + by the kernel from compiled-in data and from hardware key stores, but + userspace may only add extra keys if those keys can be verified by + keys already in the keyring. + + Keys in this keyring are used by module signature checking. + config PROFILING bool "Profiling support" help @@ -1681,18 +1693,6 @@ config BASE_SMALL default 0 if BASE_FULL default 1 if !BASE_FULL -config SYSTEM_TRUSTED_KEYRING - bool "Provide system-wide ring of trusted keys" - depends on KEYS - help - Provide a system keyring to which trusted keys can be added. Keys in - the keyring are considered to be trusted. Keys may be added at will - by the kernel from compiled-in data and from hardware key stores, but - userspace may only add extra keys if those keys can be verified by - keys already in the keyring. - - Keys in this keyring are used by module signature checking. - menuconfig MODULES bool "Enable loadable module support" option modules From 7861144b8cb217634d738e94a748deeae139a1e2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 18 Apr 2014 15:07:12 -0700 Subject: [PATCH 267/279] kernel/watchdog.c:touch_softlockup_watchdog(): use raw_cpu_write() Fix: BUG: using __this_cpu_write() in preemptible [00000000] code: systemd-udevd/497 caller is __this_cpu_preempt_check+0x13/0x20 CPU: 3 PID: 497 Comm: systemd-udevd Tainted: G W 3.15.0-rc1 #9 Hardware name: Hewlett-Packard HP EliteBook 8470p/179B, BIOS 68ICF Ver. F.02 04/27/2012 Call Trace: check_preemption_disabled+0xe1/0xf0 __this_cpu_preempt_check+0x13/0x20 touch_nmi_watchdog+0x28/0x40 Reported-by: Luis Henriques Tested-by: Luis Henriques Cc: Eric Piel Cc: Robert Moore Cc: Lv Zheng Cc: "Rafael J. Wysocki" Cc: Len Brown Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/watchdog.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index e90089fd78e003..516203e665fcbd 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -138,7 +138,11 @@ static void __touch_watchdog(void) void touch_softlockup_watchdog(void) { - __this_cpu_write(watchdog_touch_ts, 0); + /* + * Preemption can be enabled. It doesn't matter which CPU's timestamp + * gets zeroed here, so use the raw_ operation. + */ + raw_cpu_write(watchdog_touch_ts, 0); } EXPORT_SYMBOL(touch_softlockup_watchdog); From 12c743eb2289bcaace32859d4919417ff5707768 Mon Sep 17 00:00:00 2001 From: Mike Qiu Date: Fri, 18 Apr 2014 15:07:14 -0700 Subject: [PATCH 268/279] powerpc/mm: fix ".__node_distance" undefined CHK include/config/kernel.release CHK include/generated/uapi/linux/version.h CHK include/generated/utsrelease.h ... Building modules, stage 2. WARNING: 1 bad relocations c0000000013d6a30 R_PPC64_ADDR64 uprobes_fetch_type_table WRAP arch/powerpc/boot/zImage.pseries WRAP arch/powerpc/boot/zImage.epapr MODPOST 1849 modules ERROR: ".__node_distance" [drivers/block/nvme.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 make: *** Waiting for unfinished jobs.... The reason is symbol "__node_distance" not been exported in powerpc. Signed-off-by: Mike Qiu Acked-by: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Nathan Fontenot Cc: Stephen Rothwell Cc: Srivatsa S. Bhat Cc: Jesse Larrew Cc: Robert Jennings Cc: Alistair Popple Cc: Mike Qiu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/mm/numa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 4ebbb9e99286e4..3b181b22cd469b 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -232,6 +232,7 @@ int __node_distance(int a, int b) return distance; } +EXPORT_SYMBOL(__node_distance); static void initialize_distance_lookup_table(int nid, const __be32 *associativity) From 8f28ed92d9314b98dc2033df770f5e6b85c5ffb7 Mon Sep 17 00:00:00 2001 From: Tang Chen Date: Fri, 18 Apr 2014 15:07:15 -0700 Subject: [PATCH 269/279] Documentation/vm/numa_memory_policy.txt: fix wrong document in numa_memory_policy.txt In document numa_memory_policy.txt, the following examples for flag MPOL_F_RELATIVE_NODES are incorrect. For example, consider a task that is attached to a cpuset with mems 2-5 that sets an Interleave policy over the same set with MPOL_F_RELATIVE_NODES. If the cpuset's mems change to 3-7, the interleave now occurs over nodes 3,5-6. If the cpuset's mems then change to 0,2-3,5, then the interleave occurs over nodes 0,3,5. According to the comment of the patch adding flag MPOL_F_RELATIVE_NODES, the nodemasks the user specifies should be considered relative to the current task's mems_allowed. (https://lkml.org/lkml/2008/2/29/428) And according to numa_memory_policy.txt, if the user's nodemask includes nodes that are outside the range of the new set of allowed nodes, then the remap wraps around to the beginning of the nodemask and, if not already set, sets the node in the mempolicy nodemask. So in the example, if the user specifies 2-5, for a task whose mems_allowed is 3-7, the nodemasks should be remapped the third, fourth, fifth, sixth node in mems_allowed. like the following: mems_allowed: 3 4 5 6 7 relative index: 0 1 2 3 4 5 So the nodemasks should be remapped to 3,5-7, but not 3,5-6. And for a task whose mems_allowed is 0,2-3,5, the nodemasks should be remapped to 0,2-3,5, but not 0,3,5. mems_allowed: 0 2 3 5 relative index: 0 1 2 3 4 5 Signed-off-by: Tang Chen Cc: Randy Dunlap Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/numa_memory_policy.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 4e7da654342471..badb0507608fd1 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -174,7 +174,6 @@ Components of Memory Policies allocation fails, the kernel will search other nodes, in order of increasing distance from the preferred node based on information provided by the platform firmware. - containing the cpu where the allocation takes place. Internally, the Preferred policy uses a single node--the preferred_node member of struct mempolicy. When the internal @@ -275,9 +274,9 @@ Components of Memory Policies For example, consider a task that is attached to a cpuset with mems 2-5 that sets an Interleave policy over the same set with MPOL_F_RELATIVE_NODES. If the cpuset's mems change to 3-7, the - interleave now occurs over nodes 3,5-6. If the cpuset's mems + interleave now occurs over nodes 3,5-7. If the cpuset's mems then change to 0,2-3,5, then the interleave occurs over nodes - 0,3,5. + 0,2-3,5. Thanks to the consistent remapping, applications preparing nodemasks to specify memory policies using this flag should From 9cc236827fde5e254fd995a0023c05c5ee3a3ba6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Fri, 18 Apr 2014 15:07:16 -0700 Subject: [PATCH 270/279] Shiraz has moved shiraz.hashim@st.com email-id doesn't exist anymore as he has left the company. Replace ST's id with shiraz.linux.kernel@gmail.com. It also updates .mailmap file to fix address for 'git shortlog'. Signed-off-by: Viresh Kumar Cc: Shiraz Hashim Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .mailmap | 1 + MAINTAINERS | 2 +- arch/arm/boot/dts/spear320-hmi.dts | 2 +- arch/arm/mach-spear/headsmp.S | 2 +- arch/arm/mach-spear/platsmp.c | 2 +- arch/arm/mach-spear/time.c | 2 +- drivers/gpio/gpio-spear-spics.c | 4 ++-- drivers/irqchip/spear-shirq.c | 2 +- drivers/mtd/devices/spear_smi.c | 4 ++-- drivers/pwm/pwm-spear.c | 4 ++-- include/linux/mtd/spear_smi.h | 2 +- 11 files changed, 14 insertions(+), 13 deletions(-) diff --git a/.mailmap b/.mailmap index 658003aa944686..df1baba43a64c7 100644 --- a/.mailmap +++ b/.mailmap @@ -99,6 +99,7 @@ Sachin P Sant Sam Ravnborg Sascha Hauer S.Çağlar Onur +Shiraz Hashim Simon Kelley Stéphane Witzmann Stephen Hemminger diff --git a/MAINTAINERS b/MAINTAINERS index 80399fff805d09..e67ea244204163 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8315,7 +8315,7 @@ F: include/linux/compiler.h SPEAR PLATFORM SUPPORT M: Viresh Kumar -M: Shiraz Hashim +M: Shiraz Hashim L: spear-devel@list.st.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) W: http://www.st.com/spear diff --git a/arch/arm/boot/dts/spear320-hmi.dts b/arch/arm/boot/dts/spear320-hmi.dts index 3075d2d3a8bec0..0aa6fef5ce2263 100644 --- a/arch/arm/boot/dts/spear320-hmi.dts +++ b/arch/arm/boot/dts/spear320-hmi.dts @@ -1,7 +1,7 @@ /* * DTS file for SPEAr320 Evaluation Baord * - * Copyright 2012 Shiraz Hashim + * Copyright 2012 Shiraz Hashim * * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License diff --git a/arch/arm/mach-spear/headsmp.S b/arch/arm/mach-spear/headsmp.S index ed85473a047fe9..c52192dc3d9f9e 100644 --- a/arch/arm/mach-spear/headsmp.S +++ b/arch/arm/mach-spear/headsmp.S @@ -3,7 +3,7 @@ * * Picked from realview * Copyright (c) 2012 ST Microelectronics Limited - * Shiraz Hashim + * Shiraz Hashim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/arch/arm/mach-spear/platsmp.c b/arch/arm/mach-spear/platsmp.c index 5c4a19887b2bb1..c19751fff2c60d 100644 --- a/arch/arm/mach-spear/platsmp.c +++ b/arch/arm/mach-spear/platsmp.c @@ -4,7 +4,7 @@ * based upon linux/arch/arm/mach-realview/platsmp.c * * Copyright (C) 2012 ST Microelectronics Ltd. - * Shiraz Hashim + * Shiraz Hashim * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c index 218ba5b67d9298..64790353951f0c 100644 --- a/arch/arm/mach-spear/time.c +++ b/arch/arm/mach-spear/time.c @@ -2,7 +2,7 @@ * arch/arm/plat-spear/time.c * * Copyright (C) 2010 ST Microelectronics - * Shiraz Hashim + * Shiraz Hashim * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/gpio/gpio-spear-spics.c b/drivers/gpio/gpio-spear-spics.c index e9a0415834ea52..30bcc539425d10 100644 --- a/drivers/gpio/gpio-spear-spics.c +++ b/drivers/gpio/gpio-spear-spics.c @@ -2,7 +2,7 @@ * SPEAr platform SPI chipselect abstraction over gpiolib * * Copyright (C) 2012 ST Microelectronics - * Shiraz Hashim + * Shiraz Hashim * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -205,6 +205,6 @@ static int __init spics_gpio_init(void) } subsys_initcall(spics_gpio_init); -MODULE_AUTHOR("Shiraz Hashim "); +MODULE_AUTHOR("Shiraz Hashim "); MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction"); MODULE_LICENSE("GPL"); diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c index 8527743b5cef14..3fdda3a4026936 100644 --- a/drivers/irqchip/spear-shirq.c +++ b/drivers/irqchip/spear-shirq.c @@ -5,7 +5,7 @@ * Viresh Kumar * * Copyright (C) 2012 ST Microelectronics - * Shiraz Hashim + * Shiraz Hashim * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any diff --git a/drivers/mtd/devices/spear_smi.c b/drivers/mtd/devices/spear_smi.c index 363da96e6891ce..c4176b0f382d20 100644 --- a/drivers/mtd/devices/spear_smi.c +++ b/drivers/mtd/devices/spear_smi.c @@ -6,7 +6,7 @@ * * Copyright © 2010 STMicroelectronics. * Ashish Priyadarshi - * Shiraz Hashim + * Shiraz Hashim * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -1089,5 +1089,5 @@ static struct platform_driver spear_smi_driver = { module_platform_driver(spear_smi_driver); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim "); +MODULE_AUTHOR("Ashish Priyadarshi, Shiraz Hashim "); MODULE_DESCRIPTION("MTD SMI driver for serial nor flash chips"); diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c index 8ad26b8bf4189d..cb2d4f0f97114b 100644 --- a/drivers/pwm/pwm-spear.c +++ b/drivers/pwm/pwm-spear.c @@ -2,7 +2,7 @@ * ST Microelectronics SPEAr Pulse Width Modulator driver * * Copyright (C) 2012 ST Microelectronics - * Shiraz Hashim + * Shiraz Hashim * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -264,6 +264,6 @@ static struct platform_driver spear_pwm_driver = { module_platform_driver(spear_pwm_driver); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Shiraz Hashim "); +MODULE_AUTHOR("Shiraz Hashim "); MODULE_AUTHOR("Viresh Kumar "); MODULE_ALIAS("platform:spear-pwm"); diff --git a/include/linux/mtd/spear_smi.h b/include/linux/mtd/spear_smi.h index 8ae1726044c3e9..581603ac127769 100644 --- a/include/linux/mtd/spear_smi.h +++ b/include/linux/mtd/spear_smi.h @@ -1,6 +1,6 @@ /* * Copyright © 2010 ST Microelectronics - * Shiraz Hashim + * Shiraz Hashim * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any From 8b32201de1f87878ace971bfdc2846a4f3a5bb2b Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Fri, 18 Apr 2014 15:07:17 -0700 Subject: [PATCH 271/279] wait: explain the shadowing and type inconsistencies Stick in a comment before someone else tries to fix the sparse warning this generates. Suggested-by: Andrew Morton Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-o2ro6f3vkxklni0bc8f7m68s@git.kernel.org Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/wait.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/linux/wait.h b/include/linux/wait.h index e7d9d9ed14f562..bd68819f081592 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -191,11 +191,23 @@ wait_queue_head_t *bit_waitqueue(void *, int); (!__builtin_constant_p(state) || \ state == TASK_INTERRUPTIBLE || state == TASK_KILLABLE) \ +/* + * The below macro ___wait_event() has an explicit shadow of the __ret + * variable when used from the wait_event_*() macros. + * + * This is so that both can use the ___wait_cond_timeout() construct + * to wrap the condition. + * + * The type inconsistency of the wait_event_*() __ret variable is also + * on purpose; we use long where we can return timeout values and int + * otherwise. + */ + #define ___wait_event(wq, condition, state, exclusive, ret, cmd) \ ({ \ __label__ __out; \ wait_queue_t __wait; \ - long __ret = ret; \ + long __ret = ret; /* explicit shadow */ \ \ INIT_LIST_HEAD(&__wait.task_list); \ if (exclusive) \ From 7848a4bf51b34f41fcc9bd77e837126d99ae84e3 Mon Sep 17 00:00:00 2001 From: "Mizuma, Masayoshi" Date: Fri, 18 Apr 2014 15:07:18 -0700 Subject: [PATCH 272/279] mm/hugetlb.c: add cond_resched_lock() in return_unused_surplus_pages() soft lockup in freeing gigantic hugepage fixed in commit 55f67141a892 "mm: hugetlb: fix softlockup when a large number of hugepages are freed." can happen in return_unused_surplus_pages(), so let's fix it. Signed-off-by: Masayoshi Mizuma Signed-off-by: Naoya Horiguchi Cc: Joonsoo Kim Cc: Michal Hocko Cc: Aneesh Kumar Cc: KOSAKI Motohiro Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/hugetlb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index dd30f22b35e0c9..246192929a2d5c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1172,6 +1172,7 @@ static void return_unused_surplus_pages(struct hstate *h, while (nr_pages--) { if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1)) break; + cond_resched_lock(&hugetlb_lock); } } From 8229f1a044894f84324292608c149f0b4563532b Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 18 Apr 2014 15:07:19 -0700 Subject: [PATCH 273/279] mips: export flush_icache_range The lkdtm module performs tests against executable memory ranges, so it needs to flush the icache for proper behaviors. Other architectures already export this, so do the same for MIPS. [akpm@linux-foundation.org: relocate export sites] Signed-off-by: Kees Cook Cc: Paul Gortmaker Cc: Ralf Baechle Cc: Sanjay Lal Cc: John Crispin Cc: Sergei Shtylyov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mips/mm/cache.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index e422b38d3113b0..9e67cdea3c7484 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -29,15 +29,15 @@ void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start, void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn); void (*flush_icache_range)(unsigned long start, unsigned long end); +EXPORT_SYMBOL_GPL(flush_icache_range); void (*local_flush_icache_range)(unsigned long start, unsigned long end); void (*__flush_cache_vmap)(void); void (*__flush_cache_vunmap)(void); void (*__flush_kernel_vmap_range)(unsigned long vaddr, int size); -void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size); - EXPORT_SYMBOL_GPL(__flush_kernel_vmap_range); +void (*__invalidate_kernel_vmap_range)(unsigned long vaddr, int size); /* MIPS specific cache operations */ void (*flush_cache_sigtramp)(unsigned long addr); From 29c7787075c92ca8af353acd5301481e6f37082f Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Fri, 18 Apr 2014 15:07:21 -0700 Subject: [PATCH 274/279] mm: use paravirt friendly ops for NUMA hinting ptes David Vrabel identified a regression when using automatic NUMA balancing under Xen whereby page table entries were getting corrupted due to the use of native PTE operations. Quoting him Xen PV guest page tables require that their entries use machine addresses if the preset bit (_PAGE_PRESENT) is set, and (for successful migration) non-present PTEs must use pseudo-physical addresses. This is because on migration MFNs in present PTEs are translated to PFNs (canonicalised) so they may be translated back to the new MFN in the destination domain (uncanonicalised). pte_mknonnuma(), pmd_mknonnuma(), pte_mknuma() and pmd_mknuma() set and clear the _PAGE_PRESENT bit using pte_set_flags(), pte_clear_flags(), etc. In a Xen PV guest, these functions must translate MFNs to PFNs when clearing _PAGE_PRESENT and translate PFNs to MFNs when setting _PAGE_PRESENT. His suggested fix converted p[te|md]_[set|clear]_flags to using paravirt-friendly ops but this is overkill. He suggested an alternative of using p[te|md]_modify in the NUMA page table operations but this is does more work than necessary and would require looking up a VMA for protections. This patch modifies the NUMA page table operations to use paravirt friendly operations to set/clear the flags of interest. Unfortunately this will take a performance hit when updating the PTEs on CONFIG_PARAVIRT but I do not see a way around it that does not break Xen. Signed-off-by: Mel Gorman Acked-by: David Vrabel Tested-by: David Vrabel Cc: Ingo Molnar Cc: Peter Anvin Cc: Fengguang Wu Cc: Linus Torvalds Cc: Steven Noonan Cc: Rik van Riel Cc: Peter Zijlstra Cc: Andrea Arcangeli Cc: Dave Hansen Cc: Srikar Dronamraju Cc: Cyrill Gorcunov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-generic/pgtable.h | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 1ec08c198b66a8..a8015a7a55bbd5 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -693,24 +693,35 @@ static inline int pmd_numa(pmd_t pmd) #ifndef pte_mknonnuma static inline pte_t pte_mknonnuma(pte_t pte) { - pte = pte_clear_flags(pte, _PAGE_NUMA); - return pte_set_flags(pte, _PAGE_PRESENT|_PAGE_ACCESSED); + pteval_t val = pte_val(pte); + + val &= ~_PAGE_NUMA; + val |= (_PAGE_PRESENT|_PAGE_ACCESSED); + return __pte(val); } #endif #ifndef pmd_mknonnuma static inline pmd_t pmd_mknonnuma(pmd_t pmd) { - pmd = pmd_clear_flags(pmd, _PAGE_NUMA); - return pmd_set_flags(pmd, _PAGE_PRESENT|_PAGE_ACCESSED); + pmdval_t val = pmd_val(pmd); + + val &= ~_PAGE_NUMA; + val |= (_PAGE_PRESENT|_PAGE_ACCESSED); + + return __pmd(val); } #endif #ifndef pte_mknuma static inline pte_t pte_mknuma(pte_t pte) { - pte = pte_set_flags(pte, _PAGE_NUMA); - return pte_clear_flags(pte, _PAGE_PRESENT); + pteval_t val = pte_val(pte); + + val &= ~_PAGE_PRESENT; + val |= _PAGE_NUMA; + + return __pte(val); } #endif @@ -729,8 +740,12 @@ static inline void ptep_set_numa(struct mm_struct *mm, unsigned long addr, #ifndef pmd_mknuma static inline pmd_t pmd_mknuma(pmd_t pmd) { - pmd = pmd_set_flags(pmd, _PAGE_NUMA); - return pmd_clear_flags(pmd, _PAGE_PRESENT); + pmdval_t val = pmd_val(pmd); + + val &= ~_PAGE_PRESENT; + val |= _PAGE_NUMA; + + return __pmd(val); } #endif From a663dad65f3f41a0f9a8d0f2f1bc352524c4ff65 Mon Sep 17 00:00:00 2001 From: Davidlohr Bueso Date: Fri, 18 Apr 2014 15:07:22 -0700 Subject: [PATCH 275/279] mm: fix CONFIG_DEBUG_VM_RB description This appears to be a copy/paste error. Update the description to reflect extra rbtree debug and checks for the config option instead of duplicating CONFIG_DEBUG_VM. Signed-off-by: Davidlohr Bueso Cc: Aswin Chandramouleeswaran Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 140b66a874c1d5..819ac51202c010 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -505,8 +505,7 @@ config DEBUG_VM_RB bool "Debug VM red-black trees" depends on DEBUG_VM help - Enable this to turn on more extended checks in the virtual-memory - system that may impact performance. + Enable VM red-black tree debugging information and extra validations. If unsure, say N. From b59b8cbca6291a23928f1a103defba03d1cdab2c Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 18 Apr 2014 15:07:23 -0700 Subject: [PATCH 276/279] mm: fix new kernel-doc warning in filemap.c Fix new kernel-doc warning in mm/filemap.c: Warning(mm/filemap.c:2600): Excess function parameter 'ppos' description in '__generic_file_aio_write' Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/filemap.c | 1 - 1 file changed, 1 deletion(-) diff --git a/mm/filemap.c b/mm/filemap.c index a82fbe4c9e8e1c..5020b280a771a4 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2581,7 +2581,6 @@ EXPORT_SYMBOL(generic_perform_write); * @iocb: IO state structure (file, offset, etc.) * @iov: vector with data to write * @nr_segs: number of segments in the vector - * @ppos: position where to write * * This function does all the work needed for actually writing data to a * file. It does all basic checks, removes SUID from the file, updates From b5a8cad376eebbd8598642697e92a27983aee802 Mon Sep 17 00:00:00 2001 From: "Kirill A. Shutemov" Date: Fri, 18 Apr 2014 15:07:25 -0700 Subject: [PATCH 277/279] thp: close race between split and zap huge pages Sasha Levin has reported two THP BUGs[1][2]. I believe both of them have the same root cause. Let's look to them one by one. The first bug[1] is "kernel BUG at mm/huge_memory.c:1829!". It's BUG_ON(mapcount != page_mapcount(page)) in __split_huge_page(). From my testing I see that page_mapcount() is higher than mapcount here. I think it happens due to race between zap_huge_pmd() and page_check_address_pmd(). page_check_address_pmd() misses PMD which is under zap: CPU0 CPU1 zap_huge_pmd() pmdp_get_and_clear() __split_huge_page() anon_vma_interval_tree_foreach() __split_huge_page_splitting() page_check_address_pmd() mm_find_pmd() /* * We check if PMD present without taking ptl: no * serialization against zap_huge_pmd(). We miss this PMD, * it's not accounted to 'mapcount' in __split_huge_page(). */ pmd_present(pmd) == 0 BUG_ON(mapcount != page_mapcount(page)) // CRASH!!! page_remove_rmap(page) atomic_add_negative(-1, &page->_mapcount) The second bug[2] is "kernel BUG at mm/huge_memory.c:1371!". It's VM_BUG_ON_PAGE(!PageHead(page), page) in zap_huge_pmd(). This happens in similar way: CPU0 CPU1 zap_huge_pmd() pmdp_get_and_clear() page_remove_rmap(page) atomic_add_negative(-1, &page->_mapcount) __split_huge_page() anon_vma_interval_tree_foreach() __split_huge_page_splitting() page_check_address_pmd() mm_find_pmd() pmd_present(pmd) == 0 /* The same comment as above */ /* * No crash this time since we already decremented page->_mapcount in * zap_huge_pmd(). */ BUG_ON(mapcount != page_mapcount(page)) /* * We split the compound page here into small pages without * serialization against zap_huge_pmd() */ __split_huge_page_refcount() VM_BUG_ON_PAGE(!PageHead(page), page); // CRASH!!! So my understanding the problem is pmd_present() check in mm_find_pmd() without taking page table lock. The bug was introduced by me commit with commit 117b0791ac42. Sorry for that. :( Let's open code mm_find_pmd() in page_check_address_pmd() and do the check under page table lock. Note that __page_check_address() does the same for PTE entires if sync != 0. I've stress tested split and zap code paths for 36+ hours by now and don't see crashes with the patch applied. Before it took <20 min to trigger the first bug and few hours for second one (if we ignore first). [1] https://lkml.kernel.org/g/<53440991.9090001@oracle.com> [2] https://lkml.kernel.org/g/<5310C56C.60709@oracle.com> Signed-off-by: Kirill A. Shutemov Reported-by: Sasha Levin Tested-by: Sasha Levin Cc: Bob Liu Cc: Andrea Arcangeli Cc: Rik van Riel Cc: Mel Gorman Cc: Michel Lespinasse Cc: Dave Jones Cc: Vlastimil Babka Cc: [3.13+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/huge_memory.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 64635f5278ff2d..b4b1feba647242 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1536,16 +1536,23 @@ pmd_t *page_check_address_pmd(struct page *page, enum page_check_address_pmd_flag flag, spinlock_t **ptl) { + pgd_t *pgd; + pud_t *pud; pmd_t *pmd; if (address & ~HPAGE_PMD_MASK) return NULL; - pmd = mm_find_pmd(mm, address); - if (!pmd) + pgd = pgd_offset(mm, address); + if (!pgd_present(*pgd)) return NULL; + pud = pud_offset(pgd, address); + if (!pud_present(*pud)) + return NULL; + pmd = pmd_offset(pud, address); + *ptl = pmd_lock(mm, pmd); - if (pmd_none(*pmd)) + if (!pmd_present(*pmd)) goto unlock; if (pmd_page(*pmd) != page) goto unlock; From 404ca80eb5c2727d78cd517d12108b040c522e12 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sat, 19 Apr 2014 10:15:07 -0700 Subject: [PATCH 278/279] coredump: fix va_list corruption A va_list needs to be copied in case it needs to be used twice. Thanks to Hugh for debugging this issue, leading to various panics. Tested: lpq84:~# echo "|/foobar12345 %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h" >/proc/sys/kernel/core_pattern 'produce_core' is simply : main() { *(int *)0 = 1;} lpq84:~# ./produce_core Segmentation fault (core dumped) lpq84:~# dmesg | tail -1 [ 614.352947] Core dump to |/foobar12345 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 lpq84 (null) pipe failed Notice the last argument was replaced by a NULL (we were lucky enough to not crash, but do not try this on your production machine !) After fix : lpq83:~# echo "|/foobar12345 %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h %h" >/proc/sys/kernel/core_pattern lpq83:~# ./produce_core Segmentation fault lpq83:~# dmesg | tail -1 [ 740.800441] Core dump to |/foobar12345 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 lpq83 pipe failed Fixes: 5fe9d8ca21cc ("coredump: cn_vprintf() has no reason to call vsnprintf() twice") Signed-off-by: Eric Dumazet Diagnosed-by: Hugh Dickins Acked-by: Oleg Nesterov Cc: Neil Horman Cc: Andrew Morton Cc: stable@vger.kernel.org # 3.11+ Signed-off-by: Linus Torvalds --- fs/coredump.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/coredump.c b/fs/coredump.c index e3ad709a4232f4..0b2528fb640e77 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -73,10 +73,15 @@ static int expand_corename(struct core_name *cn, int size) static int cn_vprintf(struct core_name *cn, const char *fmt, va_list arg) { int free, need; + va_list arg_copy; again: free = cn->size - cn->used; - need = vsnprintf(cn->corename + cn->used, free, fmt, arg); + + va_copy(arg_copy, arg); + need = vsnprintf(cn->corename + cn->used, free, fmt, arg_copy); + va_end(arg_copy); + if (need < free) { cn->used += need; return 0; From a798c10faf62a505d24e5f6213fbaf904a39623f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 20 Apr 2014 11:08:50 -0700 Subject: [PATCH 279/279] Linux 3.15-rc2 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 60ccbfe750a264..80a2d2448531e1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION = 3 PATCHLEVEL = 15 SUBLEVEL = 0 -EXTRAVERSION = -rc1 +EXTRAVERSION = -rc2 NAME = Shuffling Zombie Juror # *DOCUMENTATION*