From 95f158eab42f971c2a6f82cc886ce657d92a25f4 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 11 Dec 2009 23:44:49 +0100 Subject: drm/nv04-nv40: Fix "conflicting memory types" when saving/restoring VGA fonts. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_display.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index b47c757ff48..cdddbaa8c45 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -103,6 +103,7 @@ nv04_display_create(struct drm_device *dev) if (nv_two_heads(dev)) nv04_display_store_initial_head_owner(dev); + nouveau_hw_save_vga_fonts(dev, 1); drm_mode_config_init(dev); drm_mode_create_scaling_mode_property(dev); @@ -203,8 +204,6 @@ nv04_display_create(struct drm_device *dev) /* Save previous state */ NVLockVgaCrtcs(dev, false); - nouveau_hw_save_vga_fonts(dev, 1); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) crtc->funcs->save(crtc); @@ -246,9 +245,9 @@ nv04_display_destroy(struct drm_device *dev) list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) crtc->funcs->restore(crtc); - nouveau_hw_save_vga_fonts(dev, 0); - drm_mode_config_cleanup(dev); + + nouveau_hw_save_vga_fonts(dev, 0); } void -- cgit v1.2.3-70-g09d2 From dc4a684ae80d914b2b7fe75b2733a3296a8b92d2 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Tue, 15 Dec 2009 01:34:42 +0100 Subject: drm/i2c/ch7006: Fix load detection false positives right after system init. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/i2c/ch7006_drv.c | 5 +++++ drivers/gpu/drm/i2c/ch7006_mode.c | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i2c/ch7006_drv.c b/drivers/gpu/drm/i2c/ch7006_drv.c index 9422a74c8b5..81681a07a80 100644 --- a/drivers/gpu/drm/i2c/ch7006_drv.c +++ b/drivers/gpu/drm/i2c/ch7006_drv.c @@ -408,6 +408,11 @@ static int ch7006_probe(struct i2c_client *client, const struct i2c_device_id *i ch7006_info(client, "Detected version ID: %x\n", val); + /* I don't know what this is for, but otherwise I get no + * signal. + */ + ch7006_write(client, 0x3d, 0x0); + return 0; fail: diff --git a/drivers/gpu/drm/i2c/ch7006_mode.c b/drivers/gpu/drm/i2c/ch7006_mode.c index 87f5445092e..e447dfb6389 100644 --- a/drivers/gpu/drm/i2c/ch7006_mode.c +++ b/drivers/gpu/drm/i2c/ch7006_mode.c @@ -427,11 +427,6 @@ void ch7006_state_load(struct i2c_client *client, ch7006_load_reg(client, state, CH7006_SUBC_INC7); ch7006_load_reg(client, state, CH7006_PLL_CONTROL); ch7006_load_reg(client, state, CH7006_CALC_SUBC_INC0); - - /* I don't know what this is for, but otherwise I get no - * signal. - */ - ch7006_write(client, 0x3d, 0x0); } void ch7006_state_save(struct i2c_client *client, -- cgit v1.2.3-70-g09d2 From ef2bb506687a5f1cc8ef2fef370bb168b2808106 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 13 Dec 2009 16:53:12 +0100 Subject: drm/nouveau: use drm debug levels - Use driver level (0x2) for NV_DEBUG instead of all levels - Create a NV_DEBUG_KMS for KMS level (0x4) and use them in modesetting code - Remove a few odd NV_TRACE calls and replace some of them with NV_DEBUG_KMS or NV_INFO Signed-off-by: Maarten Maathuis Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 12 ++++++------ drivers/gpu/drm/nouveau/nouveau_connector.c | 8 ++++---- drivers/gpu/drm/nouveau/nouveau_dp.c | 28 ++++++++++++++-------------- drivers/gpu/drm/nouveau/nouveau_drv.h | 14 ++++++++++++-- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +- drivers/gpu/drm/nouveau/nv04_crtc.c | 10 +++++----- drivers/gpu/drm/nouveau/nv04_dac.c | 8 ++------ drivers/gpu/drm/nouveau/nv04_dfp.c | 8 +++++--- drivers/gpu/drm/nouveau/nv04_display.c | 4 ++-- drivers/gpu/drm/nouveau/nv17_tv.c | 4 ++-- drivers/gpu/drm/nouveau/nv50_crtc.c | 22 +++++++++++----------- drivers/gpu/drm/nouveau/nv50_cursor.c | 8 ++++---- drivers/gpu/drm/nouveau/nv50_dac.c | 20 ++++++++++---------- drivers/gpu/drm/nouveau/nv50_display.c | 20 ++++++++++---------- drivers/gpu/drm/nouveau/nv50_sor.c | 16 ++++++++-------- 15 files changed, 96 insertions(+), 88 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 5eec5ed6948..62fadbbd1f4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -3854,7 +3854,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, * script tables is a pointer to the script to execute. */ - NV_DEBUG(dev, "Searching for output entry for %d %d %d\n", + NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", dcbent->type, dcbent->location, dcbent->or); otable = bios_output_config_match(dev, dcbent, table[1] + bios->display.script_table_ptr, @@ -3884,7 +3884,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, if (pxclk == 0) { script = ROM16(otable[6]); if (!script) { - NV_DEBUG(dev, "output script 0 not found\n"); + NV_DEBUG_KMS(dev, "output script 0 not found\n"); return 1; } @@ -3894,7 +3894,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, if (pxclk == -1) { script = ROM16(otable[8]); if (!script) { - NV_DEBUG(dev, "output script 1 not found\n"); + NV_DEBUG_KMS(dev, "output script 1 not found\n"); return 1; } @@ -3907,7 +3907,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, else script = 0; if (!script) { - NV_DEBUG(dev, "output script 2 not found\n"); + NV_DEBUG_KMS(dev, "output script 2 not found\n"); return 1; } @@ -3931,7 +3931,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, if (script) script = clkcmptable(bios, script, -pxclk); if (!script) { - NV_DEBUG(dev, "clock script 1 not found\n"); + NV_DEBUG_KMS(dev, "clock script 1 not found\n"); return 1; } @@ -5234,7 +5234,7 @@ parse_dcb_connector_table(struct nvbios *bios) int i; if (!bios->bdcb.connector_table_ptr) { - NV_DEBUG(dev, "No DCB connector table present\n"); + NV_DEBUG_KMS(dev, "No DCB connector table present\n"); return; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 032cf098fa1..5a10deb8bdb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -86,7 +86,7 @@ nouveau_connector_destroy(struct drm_connector *drm_connector) struct nouveau_connector *connector = nouveau_connector(drm_connector); struct drm_device *dev = connector->base.dev; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); if (!connector) return; @@ -420,7 +420,7 @@ nouveau_connector_native_mode(struct nouveau_connector *connector) /* Use preferred mode if there is one.. */ list_for_each_entry(mode, &connector->base.probed_modes, head) { if (mode->type & DRM_MODE_TYPE_PREFERRED) { - NV_DEBUG(dev, "native mode from preferred\n"); + NV_DEBUG_KMS(dev, "native mode from preferred\n"); return drm_mode_duplicate(dev, mode); } } @@ -445,7 +445,7 @@ nouveau_connector_native_mode(struct nouveau_connector *connector) largest = mode; } - NV_DEBUG(dev, "native mode from largest: %dx%d@%d\n", + NV_DEBUG_KMS(dev, "native mode from largest: %dx%d@%d\n", high_w, high_h, high_v); return largest ? drm_mode_duplicate(dev, largest) : NULL; } @@ -725,7 +725,7 @@ nouveau_connector_create(struct drm_device *dev, int index, int type) struct drm_encoder *encoder; int ret; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); if (!nv_connector) diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index de61f4640e1..9e2926c4857 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -187,7 +187,7 @@ nouveau_dp_link_train_adjust(struct drm_encoder *encoder, uint8_t *config) if (ret) return false; - NV_DEBUG(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); + NV_DEBUG_KMS(dev, "\t\tadjust 0x%02x 0x%02x\n", request[0], request[1]); /* Keep all lanes at the same level.. */ for (i = 0; i < nv_encoder->dp.link_nr; i++) { @@ -228,7 +228,7 @@ nouveau_dp_link_train_commit(struct drm_encoder *encoder, uint8_t *config) int or = nv_encoder->or, link = !(nv_encoder->dcb->sorconf.link & 1); int dpe_headerlen, ret, i; - NV_DEBUG(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", + NV_DEBUG_KMS(dev, "\t\tconfig 0x%02x 0x%02x 0x%02x 0x%02x\n", config[0], config[1], config[2], config[3]); dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen); @@ -276,12 +276,12 @@ nouveau_dp_link_train(struct drm_encoder *encoder) bool cr_done, cr_max_vs, eq_done; int ret = 0, i, tries, voltage; - NV_DEBUG(dev, "link training!!\n"); + NV_DEBUG_KMS(dev, "link training!!\n"); train: cr_done = eq_done = false; /* set link configuration */ - NV_DEBUG(dev, "\tbegin train: bw %d, lanes %d\n", + NV_DEBUG_KMS(dev, "\tbegin train: bw %d, lanes %d\n", nv_encoder->dp.link_bw, nv_encoder->dp.link_nr); ret = nouveau_dp_link_bw_set(encoder, nv_encoder->dp.link_bw); @@ -297,7 +297,7 @@ train: return false; /* clock recovery */ - NV_DEBUG(dev, "\tbegin cr\n"); + NV_DEBUG_KMS(dev, "\tbegin cr\n"); ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_1); if (ret) goto stop; @@ -314,7 +314,7 @@ train: ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 2); if (ret) break; - NV_DEBUG(dev, "\t\tstatus: 0x%02x 0x%02x\n", + NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", status[0], status[1]); cr_done = true; @@ -346,7 +346,7 @@ train: goto stop; /* channel equalisation */ - NV_DEBUG(dev, "\tbegin eq\n"); + NV_DEBUG_KMS(dev, "\tbegin eq\n"); ret = nouveau_dp_link_train_set(encoder, DP_TRAINING_PATTERN_2); if (ret) goto stop; @@ -357,7 +357,7 @@ train: ret = auxch_rd(encoder, DP_LANE0_1_STATUS, status, 3); if (ret) break; - NV_DEBUG(dev, "\t\tstatus: 0x%02x 0x%02x\n", + NV_DEBUG_KMS(dev, "\t\tstatus: 0x%02x 0x%02x\n", status[0], status[1]); eq_done = true; @@ -395,9 +395,9 @@ stop: /* retry at a lower setting, if possible */ if (!ret && !(eq_done && cr_done)) { - NV_DEBUG(dev, "\twe failed\n"); + NV_DEBUG_KMS(dev, "\twe failed\n"); if (nv_encoder->dp.link_bw != DP_LINK_BW_1_62) { - NV_DEBUG(dev, "retry link training at low rate\n"); + NV_DEBUG_KMS(dev, "retry link training at low rate\n"); nv_encoder->dp.link_bw = DP_LINK_BW_1_62; goto train; } @@ -418,7 +418,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) if (ret) return false; - NV_DEBUG(dev, "encoder: link_bw %d, link_nr %d\n" + NV_DEBUG_KMS(dev, "encoder: link_bw %d, link_nr %d\n" "display: link_bw %d, link_nr %d version 0x%02x\n", nv_encoder->dcb->dpconf.link_bw, nv_encoder->dcb->dpconf.link_nr, @@ -446,7 +446,7 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, uint32_t tmp, ctrl, stat = 0, data32[4] = {}; int ret = 0, i, index = auxch->rd; - NV_DEBUG(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); + NV_DEBUG_KMS(dev, "ch %d cmd %d addr 0x%x len %d\n", index, cmd, addr, data_nr); tmp = nv_rd32(dev, NV50_AUXCH_CTRL(auxch->rd)); nv_wr32(dev, NV50_AUXCH_CTRL(auxch->rd), tmp | 0x00100000); @@ -472,7 +472,7 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, if (!(cmd & 1)) { memcpy(data32, data, data_nr); for (i = 0; i < 4; i++) { - NV_DEBUG(dev, "wr %d: 0x%08x\n", i, data32[i]); + NV_DEBUG_KMS(dev, "wr %d: 0x%08x\n", i, data32[i]); nv_wr32(dev, NV50_AUXCH_DATA_OUT(index, i), data32[i]); } } @@ -504,7 +504,7 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, if (cmd & 1) { for (i = 0; i < 4; i++) { data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); - NV_DEBUG(dev, "rd %d: 0x%08x\n", i, data32[i]); + NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); } memcpy(data, data32, data_nr); } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 88b4c7b77e7..bc6ffa5eeac 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -1207,14 +1207,24 @@ static inline void nv_wo32(struct drm_device *dev, struct nouveau_gpuobj *obj, pci_name(d->pdev), ##arg) #ifndef NV_DEBUG_NOTRACE #define NV_DEBUG(d, fmt, arg...) do { \ - if (drm_debug) { \ + if (drm_debug & DRM_UT_DRIVER) { \ + NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \ + __LINE__, ##arg); \ + } \ +} while (0) +#define NV_DEBUG_KMS(d, fmt, arg...) do { \ + if (drm_debug & DRM_UT_KMS) { \ NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__, \ __LINE__, ##arg); \ } \ } while (0) #else #define NV_DEBUG(d, fmt, arg...) do { \ - if (drm_debug) \ + if (drm_debug & DRM_UT_DRIVER) \ + NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \ +} while (0) +#define NV_DEBUG_KMS(d, fmt, arg...) do { \ + if (drm_debug & DRM_UT_KMS) \ NV_PRINTK(KERN_DEBUG, d, fmt, ##arg); \ } while (0) #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 36e8c5e4503..489d4926811 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -347,7 +347,7 @@ out: int nouveau_fbcon_probe(struct drm_device *dev) { - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); return drm_fb_helper_single_fb_probe(dev, 32, nouveau_fbcon_create); } diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index b9136360605..d2f143ed97c 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c @@ -143,10 +143,10 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK; if (pv->NM2) - NV_TRACE(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", + NV_DEBUG_KMS(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P); else - NV_TRACE(dev, "vpll: n %d m %d log2p %d\n", + NV_DEBUG_KMS(dev, "vpll: n %d m %d log2p %d\n", pv->N1, pv->M1, pv->log2P); nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset); @@ -160,7 +160,7 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) unsigned char seq1 = 0, crtc17 = 0; unsigned char crtc1A; - NV_TRACE(dev, "Setting dpms mode %d on CRTC %d\n", mode, + NV_DEBUG_KMS(dev, "Setting dpms mode %d on CRTC %d\n", mode, nv_crtc->index); if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */ @@ -603,7 +603,7 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct drm_nouveau_private *dev_priv = dev->dev_private; - NV_DEBUG(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index); + NV_DEBUG_KMS(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index); drm_mode_debug_printmodeline(adjusted_mode); /* unlock must come after turning off FP_TG_CONTROL in output_prepare */ @@ -703,7 +703,7 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - NV_DEBUG(crtc->dev, "\n"); + NV_DEBUG_KMS(crtc->dev, "\n"); if (!nv_crtc) return; diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index a5fa51714e8..d9f32879ba3 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -205,7 +205,7 @@ out: NVWriteVgaSeq(dev, 0, NV_VIO_SR_CLOCK_INDEX, saved_seq1); if (blue == 0x18) { - NV_TRACE(dev, "Load detected on head A\n"); + NV_INFO(dev, "Load detected on head A\n"); return connector_status_connected; } @@ -350,14 +350,10 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_device *dev = encoder->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; int head = nouveau_crtc(encoder->crtc)->index; - NV_TRACE(dev, "%s called for encoder %d\n", __func__, - nv_encoder->dcb->index); - if (nv_gf4_disp_arch(dev)) { struct drm_encoder *rebind; uint32_t dac_offset = nv04_dac_output_offset(encoder); @@ -466,7 +462,7 @@ static void nv04_dac_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - NV_DEBUG(encoder->dev, "\n"); + NV_DEBUG_KMS(encoder->dev, "\n"); drm_encoder_cleanup(encoder); kfree(nv_encoder); diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index e5b33339d59..483f875bdb6 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -261,7 +261,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *output_mode = &nv_encoder->mode; uint32_t mode_ratio, panel_ratio; - NV_DEBUG(dev, "Output mode on CRTC %d:\n", nv_crtc->index); + NV_DEBUG_KMS(dev, "Output mode on CRTC %d:\n", nv_crtc->index); drm_mode_debug_printmodeline(output_mode); /* Initialize the FP registers in this CRTC. */ @@ -413,7 +413,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) struct dcb_entry *dcbe = nv_encoder->dcb; int head = nouveau_crtc(encoder->crtc)->index; - NV_TRACE(dev, "%s called for encoder %d\n", __func__, nv_encoder->dcb->index); + NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), + nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); if (dcbe->type == OUTPUT_TMDS) run_tmds_table(dev, dcbe, head, nv_encoder->mode.clock); @@ -550,7 +552,7 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - NV_DEBUG(encoder->dev, "\n"); + NV_DEBUG_KMS(encoder->dev, "\n"); drm_encoder_cleanup(encoder); kfree(nv_encoder); diff --git a/drivers/gpu/drm/nouveau/nv04_display.c b/drivers/gpu/drm/nouveau/nv04_display.c index cdddbaa8c45..ef77215fa5b 100644 --- a/drivers/gpu/drm/nouveau/nv04_display.c +++ b/drivers/gpu/drm/nouveau/nv04_display.c @@ -99,7 +99,7 @@ nv04_display_create(struct drm_device *dev) uint16_t connector[16] = { 0 }; int i, ret; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); if (nv_two_heads(dev)) nv04_display_store_initial_head_owner(dev); @@ -222,7 +222,7 @@ nv04_display_destroy(struct drm_device *dev) struct drm_encoder *encoder; struct drm_crtc *crtc; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); /* Turn every CRTC off. */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { diff --git a/drivers/gpu/drm/nouveau/nv17_tv.c b/drivers/gpu/drm/nouveau/nv17_tv.c index 46cfd9c6047..81c01353a9f 100644 --- a/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/drivers/gpu/drm/nouveau/nv17_tv.c @@ -219,7 +219,7 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) return; nouveau_encoder(encoder)->last_dpms = mode; - NV_TRACE(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", mode, nouveau_encoder(encoder)->dcb->index); regs->ptv_200 &= ~1; @@ -619,7 +619,7 @@ static void nv17_tv_destroy(struct drm_encoder *encoder) { struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); - NV_DEBUG(encoder->dev, "\n"); + NV_DEBUG_KMS(encoder->dev, "\n"); drm_encoder_cleanup(encoder); kfree(tv_enc); diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index f8e28a1e44e..118d3285fd8 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -45,7 +45,7 @@ nv50_crtc_lut_load(struct drm_crtc *crtc) void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); int i; - NV_DEBUG(crtc->dev, "\n"); + NV_DEBUG_KMS(crtc->dev, "\n"); for (i = 0; i < 256; i++) { writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0); @@ -68,8 +68,8 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) struct nouveau_channel *evo = dev_priv->evo; int index = nv_crtc->index, ret; - NV_DEBUG(dev, "index %d\n", nv_crtc->index); - NV_DEBUG(dev, "%s\n", blanked ? "blanked" : "unblanked"); + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); + NV_DEBUG_KMS(dev, "%s\n", blanked ? "blanked" : "unblanked"); if (blanked) { nv_crtc->cursor.hide(nv_crtc, false); @@ -139,7 +139,7 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) struct nouveau_channel *evo = dev_priv->evo; int ret; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); if (ret) { @@ -193,7 +193,7 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) uint32_t outX, outY, horiz, vert; int ret; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); switch (scaling_mode) { case DRM_MODE_SCALE_NONE: @@ -301,7 +301,7 @@ nv50_crtc_destroy(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); if (!crtc) return; @@ -433,7 +433,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct drm_encoder *encoder; - NV_DEBUG(dev, "index %d\n", nv_crtc->index); + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); /* Disconnect all unused encoders. */ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { @@ -458,7 +458,7 @@ nv50_crtc_commit(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ret; - NV_DEBUG(dev, "index %d\n", nv_crtc->index); + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); nv50_crtc_blank(nv_crtc, false); @@ -497,7 +497,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, int x, int y, struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); int ret, format; - NV_DEBUG(dev, "index %d\n", nv_crtc->index); + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); switch (drm_fb->depth) { case 8: @@ -612,7 +612,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, *nv_crtc->mode = *adjusted_mode; - NV_DEBUG(dev, "index %d\n", nv_crtc->index); + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start; vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start; @@ -706,7 +706,7 @@ nv50_crtc_create(struct drm_device *dev, int index) struct nouveau_crtc *nv_crtc = NULL; int ret, i; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); if (!nv_crtc) diff --git a/drivers/gpu/drm/nouveau/nv50_cursor.c b/drivers/gpu/drm/nouveau/nv50_cursor.c index e2e79a8f220..753e723adb3 100644 --- a/drivers/gpu/drm/nouveau/nv50_cursor.c +++ b/drivers/gpu/drm/nouveau/nv50_cursor.c @@ -41,7 +41,7 @@ nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) struct drm_device *dev = nv_crtc->base.dev; int ret; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); if (update && nv_crtc->cursor.visible) return; @@ -76,7 +76,7 @@ nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) struct drm_device *dev = nv_crtc->base.dev; int ret; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); if (update && !nv_crtc->cursor.visible) return; @@ -116,7 +116,7 @@ nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) static void nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) { - NV_DEBUG(nv_crtc->base.dev, "\n"); + NV_DEBUG_KMS(nv_crtc->base.dev, "\n"); if (offset == nv_crtc->cursor.offset) return; @@ -143,7 +143,7 @@ nv50_cursor_fini(struct nouveau_crtc *nv_crtc) struct drm_device *dev = nv_crtc->base.dev; int idx = nv_crtc->index; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), 0); if (!nv_wait(NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(idx), diff --git a/drivers/gpu/drm/nouveau/nv50_dac.c b/drivers/gpu/drm/nouveau/nv50_dac.c index fb5838e3be2..f08f042a8e1 100644 --- a/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/drivers/gpu/drm/nouveau/nv50_dac.c @@ -44,7 +44,7 @@ nv50_dac_disconnect(struct nouveau_encoder *nv_encoder) struct nouveau_channel *evo = dev_priv->evo; int ret; - NV_DEBUG(dev, "Disconnecting DAC %d\n", nv_encoder->or); + NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); ret = RING_SPACE(evo, 2); if (ret) { @@ -81,11 +81,11 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) /* Use bios provided value if possible. */ if (dev_priv->vbios->dactestval) { load_pattern = dev_priv->vbios->dactestval; - NV_DEBUG(dev, "Using bios provided load_pattern of %d\n", + NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n", load_pattern); } else { load_pattern = 340; - NV_DEBUG(dev, "Using default load_pattern of %d\n", + NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n", load_pattern); } @@ -103,9 +103,9 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) status = connector_status_connected; if (status == connector_status_connected) - NV_DEBUG(dev, "Load was detected on output with or %d\n", or); + NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or); else - NV_DEBUG(dev, "Load was not detected on output with or %d\n", or); + NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or); return status; } @@ -118,7 +118,7 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode) uint32_t val; int or = nv_encoder->or; - NV_DEBUG(dev, "or %d mode %d\n", or, mode); + NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); /* wait for it to be done */ if (!nv_wait(NV50_PDISPLAY_DAC_DPMS_CTRL(or), @@ -173,7 +173,7 @@ nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_connector *connector; - NV_DEBUG(encoder->dev, "or %d\n", nv_encoder->or); + NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); connector = nouveau_encoder_connector_get(nv_encoder); if (!connector) { @@ -213,7 +213,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, uint32_t mode_ctl = 0, mode_ctl2 = 0; int ret; - NV_DEBUG(dev, "or %d\n", nv_encoder->or); + NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or); nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); @@ -264,7 +264,7 @@ nv50_dac_destroy(struct drm_encoder *encoder) if (!encoder) return; - NV_DEBUG(encoder->dev, "\n"); + NV_DEBUG_KMS(encoder->dev, "\n"); drm_encoder_cleanup(encoder); kfree(nv_encoder); @@ -280,7 +280,7 @@ nv50_dac_create(struct drm_device *dev, struct dcb_entry *entry) struct nouveau_encoder *nv_encoder; struct drm_encoder *encoder; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); NV_INFO(dev, "Detected a DAC output\n"); nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 12c5ee63495..a9263d92a23 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -188,7 +188,7 @@ nv50_display_init(struct drm_device *dev) uint64_t start; int ret, i; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); /* @@ -232,7 +232,7 @@ nv50_display_init(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_UNK_380, 0); /* RAM is clamped to 256 MiB. */ ram_amount = nouveau_mem_fb_amount(dev); - NV_DEBUG(dev, "ram_amount %d\n", ram_amount); + NV_DEBUG_KMS(dev, "ram_amount %d\n", ram_amount); if (ram_amount > 256*1024*1024) ram_amount = 256*1024*1024; nv_wr32(dev, NV50_PDISPLAY_RAM_AMOUNT, ram_amount - 1); @@ -398,7 +398,7 @@ static int nv50_display_disable(struct drm_device *dev) struct drm_crtc *drm_crtc; int ret, i; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); @@ -469,7 +469,7 @@ int nv50_display_create(struct drm_device *dev) uint32_t connector[16] = {}; int ret, i; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); /* init basic kernel modesetting */ drm_mode_config_init(dev); @@ -573,7 +573,7 @@ int nv50_display_destroy(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); drm_mode_config_cleanup(dev); @@ -617,7 +617,7 @@ nv50_display_irq_head(struct drm_device *dev, int *phead, * CRTC separately, and submission will be blocked by the GPU * until we handle each in turn. */ - NV_DEBUG(dev, "0x610030: 0x%08x\n", unk30); + NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); head = ffs((unk30 >> 9) & 3) - 1; if (head < 0) return -EINVAL; @@ -661,7 +661,7 @@ nv50_display_irq_head(struct drm_device *dev, int *phead, or = i; } - NV_DEBUG(dev, "type %d, or %d\n", type, or); + NV_DEBUG_KMS(dev, "type %d, or %d\n", type, or); if (type == OUTPUT_ANY) { NV_ERROR(dev, "unknown encoder!!\n"); return -1; @@ -811,7 +811,7 @@ nv50_display_unk20_handler(struct drm_device *dev) pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(head, CLOCK)) & 0x3fffff; script = nv50_display_script_select(dev, dcbent, pclk); - NV_DEBUG(dev, "head %d pxclk: %dKHz\n", head, pclk); + NV_DEBUG_KMS(dev, "head %d pxclk: %dKHz\n", head, pclk); if (dcbent->type != OUTPUT_DP) nouveau_bios_run_display_table(dev, dcbent, 0, -2); @@ -870,7 +870,7 @@ nv50_display_irq_handler_bh(struct work_struct *work) uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); - NV_DEBUG(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); + NV_DEBUG_KMS(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10) nv50_display_unk10_handler(dev); @@ -974,7 +974,7 @@ nv50_display_irq_handler(struct drm_device *dev) uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); uint32_t clock; - NV_DEBUG(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); + NV_DEBUG_KMS(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); if (!intr0 && !(intr1 & ~delayed)) break; diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index 8c280463a66..e395c16d30f 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c @@ -44,7 +44,7 @@ nv50_sor_disconnect(struct nouveau_encoder *nv_encoder) struct nouveau_channel *evo = dev_priv->evo; int ret; - NV_DEBUG(dev, "Disconnecting SOR %d\n", nv_encoder->or); + NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); ret = RING_SPACE(evo, 2); if (ret) { @@ -70,7 +70,7 @@ nv50_sor_dp_link_train(struct drm_encoder *encoder) } if (dpe->script0) { - NV_DEBUG(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); + NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script0), nv_encoder->dcb); } @@ -79,7 +79,7 @@ nv50_sor_dp_link_train(struct drm_encoder *encoder) NV_ERROR(dev, "SOR-%d: link training failed\n", nv_encoder->or); if (dpe->script1) { - NV_DEBUG(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); + NV_DEBUG_KMS(dev, "SOR-%d: running DP script 1\n", nv_encoder->or); nouveau_bios_run_init_table(dev, le16_to_cpu(dpe->script1), nv_encoder->dcb); } @@ -93,7 +93,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) uint32_t val; int or = nv_encoder->or; - NV_DEBUG(dev, "or %d mode %d\n", or, mode); + NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); /* wait for it to be done */ if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), @@ -142,7 +142,7 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_connector *connector; - NV_DEBUG(encoder->dev, "or %d\n", nv_encoder->or); + NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); connector = nouveau_encoder_connector_get(nv_encoder); if (!connector) { @@ -182,7 +182,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, uint32_t mode_ctl = 0; int ret; - NV_DEBUG(dev, "or %d\n", nv_encoder->or); + NV_DEBUG_KMS(dev, "or %d\n", nv_encoder->or); nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); @@ -246,7 +246,7 @@ nv50_sor_destroy(struct drm_encoder *encoder) if (!encoder) return; - NV_DEBUG(encoder->dev, "\n"); + NV_DEBUG_KMS(encoder->dev, "\n"); drm_encoder_cleanup(encoder); @@ -265,7 +265,7 @@ nv50_sor_create(struct drm_device *dev, struct dcb_entry *entry) bool dum; int type; - NV_DEBUG(dev, "\n"); + NV_DEBUG_KMS(dev, "\n"); switch (entry->type) { case OUTPUT_TMDS: -- cgit v1.2.3-70-g09d2 From 657b6245ba23d32c7a4fd273549c8c0beebec770 Mon Sep 17 00:00:00 2001 From: Marcin KoÅ›cielnicki Date: Tue, 15 Dec 2009 00:37:30 +0000 Subject: drm/nouveau: Kill global state in NvShadowBIOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin KoÅ›cielnicki Signed-off-by: Maarten Maathuis Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 47 +++++++++++++++------------------- 1 file changed, 21 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 62fadbbd1f4..519faa95504 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -181,43 +181,42 @@ struct methods { const char desc[8]; void (*loadbios)(struct drm_device *, uint8_t *); const bool rw; - int score; }; static struct methods nv04_methods[] = { { "PROM", load_vbios_prom, false }, { "PRAMIN", load_vbios_pramin, true }, { "PCIROM", load_vbios_pci, true }, - { } }; static struct methods nv50_methods[] = { { "PRAMIN", load_vbios_pramin, true }, { "PROM", load_vbios_prom, false }, { "PCIROM", load_vbios_pci, true }, - { } }; +#define METHODCNT 3 + static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct methods *methods, *method; + struct methods *methods; + int i; int testscore = 3; + int scores[METHODCNT]; if (nouveau_vbios) { - method = nv04_methods; - while (method->loadbios) { - if (!strcasecmp(nouveau_vbios, method->desc)) + methods = nv04_methods; + for (i = 0; i < METHODCNT; i++) + if (!strcasecmp(nouveau_vbios, methods[i].desc)) break; - method++; - } - if (method->loadbios) { + if (i < METHODCNT) { NV_INFO(dev, "Attempting to use BIOS image from %s\n", - method->desc); + methods[i].desc); - method->loadbios(dev, data); - if (score_vbios(dev, data, method->rw)) + methods[i].loadbios(dev, data); + if (score_vbios(dev, data, methods[i].rw)) return true; } @@ -229,28 +228,24 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) else methods = nv50_methods; - method = methods; - while (method->loadbios) { + for (i = 0; i < METHODCNT; i++) { NV_TRACE(dev, "Attempting to load BIOS image from %s\n", - method->desc); + methods[i].desc); data[0] = data[1] = 0; /* avoid reuse of previous image */ - method->loadbios(dev, data); - method->score = score_vbios(dev, data, method->rw); - if (method->score == testscore) + methods[i].loadbios(dev, data); + scores[i] = score_vbios(dev, data, methods[i].rw); + if (scores[i] == testscore) return true; - method++; } while (--testscore > 0) { - method = methods; - while (method->loadbios) { - if (method->score == testscore) { + for (i = 0; i < METHODCNT; i++) { + if (scores[i] == testscore) { NV_TRACE(dev, "Using BIOS image from %s\n", - method->desc); - method->loadbios(dev, data); + methods[i].desc); + methods[i].loadbios(dev, data); return true; } - method++; } } -- cgit v1.2.3-70-g09d2 From 37383650e4f47aef633055e3f62e87a44d83312d Mon Sep 17 00:00:00 2001 From: Marcin KoÅ›cielnicki Date: Tue, 15 Dec 2009 00:37:31 +0000 Subject: drm/nouveau: Kill global state in BIOS script interpreter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin KoÅ›cielnicki Signed-off-by: Maarten Maathuis Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bios.c | 562 ++++++++++++++++----------------- drivers/gpu/drm/nouveau/nouveau_bios.h | 1 + 2 files changed, 276 insertions(+), 287 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 519faa95504..ba143972769 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -256,10 +256,7 @@ static bool NVShadowVBIOS(struct drm_device *dev, uint8_t *data) struct init_tbl_entry { char *name; uint8_t id; - int length; - int length_offset; - int length_multiplier; - bool (*handler)(struct nvbios *, uint16_t, struct init_exec *); + int (*handler)(struct nvbios *, uint16_t, struct init_exec *); }; struct bit_entry { @@ -815,7 +812,7 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv) } } -static bool +static int init_io_restrict_prog(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -847,9 +844,10 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset, uint32_t reg = ROM32(bios->data[offset + 7]); uint8_t config; uint32_t configval; + int len = 11 + count * 4; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", @@ -860,7 +858,7 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset, NV_ERROR(bios->dev, "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", offset, config, count); - return false; + return 0; } configval = ROM32(bios->data[offset + 11 + config * 4]); @@ -869,10 +867,10 @@ init_io_restrict_prog(struct nvbios *bios, uint16_t offset, bios_wr32(bios, reg, configval); - return true; + return len; } -static bool +static int init_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -907,10 +905,10 @@ init_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) iexec->repeat = false; - return true; + return 2; } -static bool +static int init_io_restrict_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -946,9 +944,10 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, uint32_t reg = ROM32(bios->data[offset + 8]); uint8_t config; uint16_t freq; + int len = 12 + count * 2; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " "Shift: 0x%02X, IO Flag Condition: 0x%02X, " @@ -961,7 +960,7 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, NV_ERROR(bios->dev, "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", offset, config, count); - return false; + return 0; } freq = ROM16(bios->data[offset + 12 + config * 2]); @@ -981,10 +980,10 @@ init_io_restrict_pll(struct nvbios *bios, uint16_t offset, setPLL(bios, reg, freq * 10); - return true; + return len; } -static bool +static int init_end_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1002,12 +1001,12 @@ init_end_repeat(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) * we're not in repeat mode */ if (iexec->repeat) - return false; + return 0; - return true; + return 1; } -static bool +static int init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1036,7 +1035,7 @@ init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t crtcdata; if (!iexec->execute) - return true; + return 11; BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%02X, " "Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X\n", @@ -1055,10 +1054,10 @@ init_copy(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) crtcdata |= (uint8_t)data; bios_idxprt_wr(bios, crtcport, crtcindex, crtcdata); - return true; + return 11; } -static bool +static int init_not(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1074,10 +1073,10 @@ init_not(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) BIOSLOG(bios, "0x%04X: ------ Executing following commands ------\n", offset); iexec->execute = !iexec->execute; - return true; + return 1; } -static bool +static int init_io_flag_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1095,7 +1094,7 @@ init_io_flag_condition(struct nvbios *bios, uint16_t offset, uint8_t cond = bios->data[offset + 1]; if (!iexec->execute) - return true; + return 2; if (io_flag_condition_met(bios, offset, cond)) BIOSLOG(bios, "0x%04X: Condition fulfilled -- continuing to execute\n", offset); @@ -1104,10 +1103,10 @@ init_io_flag_condition(struct nvbios *bios, uint16_t offset, iexec->execute = false; } - return true; + return 2; } -static bool +static int init_idx_addr_latched(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1135,11 +1134,12 @@ init_idx_addr_latched(struct nvbios *bios, uint16_t offset, uint32_t mask = ROM32(bios->data[offset + 9]); uint32_t data = ROM32(bios->data[offset + 13]); uint8_t count = bios->data[offset + 17]; + int len = 18 + count * 2; uint32_t value; int i; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: ControlReg: 0x%08X, DataReg: 0x%08X, " "Mask: 0x%08X, Data: 0x%08X, Count: 0x%02X\n", @@ -1159,10 +1159,10 @@ init_idx_addr_latched(struct nvbios *bios, uint16_t offset, bios_wr32(bios, controlreg, value); } - return true; + return len; } -static bool +static int init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1191,25 +1191,26 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, uint8_t shift = bios->data[offset + 5]; uint8_t count = bios->data[offset + 6]; uint32_t reg = ROM32(bios->data[offset + 7]); + int len = 11 + count * 4; uint8_t config; uint32_t freq; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " "Shift: 0x%02X, Count: 0x%02X, Reg: 0x%08X\n", offset, crtcport, crtcindex, mask, shift, count, reg); if (!reg) - return true; + return len; config = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) >> shift; if (config > count) { NV_ERROR(bios->dev, "0x%04X: Config 0x%02X exceeds maximal bound 0x%02X\n", offset, config, count); - return false; + return 0; } freq = ROM32(bios->data[offset + 11 + config * 4]); @@ -1219,10 +1220,10 @@ init_io_restrict_pll2(struct nvbios *bios, uint16_t offset, setPLL(bios, reg, freq); - return true; + return len; } -static bool +static int init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1239,16 +1240,16 @@ init_pll2(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint32_t freq = ROM32(bios->data[offset + 5]); if (!iexec->execute) - return true; + return 9; BIOSLOG(bios, "0x%04X: Reg: 0x%04X, Freq: %dkHz\n", offset, reg, freq); setPLL(bios, reg, freq); - return true; + return 9; } -static bool +static int init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1272,12 +1273,13 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_address = bios->data[offset + 2]; uint8_t count = bios->data[offset + 3]; + int len = 4 + count * 3; struct nouveau_i2c_chan *chan; struct i2c_msg msg; int i; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " "Count: 0x%02X\n", @@ -1285,7 +1287,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) chan = init_i2c_device_find(bios->dev, i2c_index); if (!chan) - return false; + return 0; for (i = 0; i < count; i++) { uint8_t i2c_reg = bios->data[offset + 4 + i * 3]; @@ -1298,7 +1300,7 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) msg.len = 1; msg.buf = &value; if (i2c_transfer(&chan->adapter, &msg, 1) != 1) - return false; + return 0; BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " "Mask: 0x%02X, Data: 0x%02X\n", @@ -1312,14 +1314,14 @@ init_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) msg.len = 1; msg.buf = &value; if (i2c_transfer(&chan->adapter, &msg, 1) != 1) - return false; + return 0; } } - return true; + return len; } -static bool +static int init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1341,12 +1343,13 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_address = bios->data[offset + 2]; uint8_t count = bios->data[offset + 3]; + int len = 4 + count * 2; struct nouveau_i2c_chan *chan; struct i2c_msg msg; int i; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " "Count: 0x%02X\n", @@ -1354,7 +1357,7 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) chan = init_i2c_device_find(bios->dev, i2c_index); if (!chan) - return false; + return 0; for (i = 0; i < count; i++) { uint8_t i2c_reg = bios->data[offset + 4 + i * 2]; @@ -1369,14 +1372,14 @@ init_zm_i2c_byte(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) msg.len = 1; msg.buf = &data; if (i2c_transfer(&chan->adapter, &msg, 1) != 1) - return false; + return 0; } } - return true; + return len; } -static bool +static int init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1396,13 +1399,14 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t i2c_index = bios->data[offset + 1]; uint8_t i2c_address = bios->data[offset + 2]; uint8_t count = bios->data[offset + 3]; + int len = 4 + count; struct nouveau_i2c_chan *chan; struct i2c_msg msg; uint8_t data[256]; int i; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X, " "Count: 0x%02X\n", @@ -1410,7 +1414,7 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) chan = init_i2c_device_find(bios->dev, i2c_index); if (!chan) - return false; + return 0; for (i = 0; i < count; i++) { data[i] = bios->data[offset + 4 + i]; @@ -1424,13 +1428,13 @@ init_zm_i2c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) msg.len = count; msg.buf = data; if (i2c_transfer(&chan->adapter, &msg, 1) != 1) - return false; + return 0; } - return true; + return len; } -static bool +static int init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1455,7 +1459,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint32_t reg, value; if (!iexec->execute) - return true; + return 5; BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, TMDSAddr: 0x%02X, " "Mask: 0x%02X, Data: 0x%02X\n", @@ -1463,7 +1467,7 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) reg = get_tmds_index_reg(bios->dev, mlv); if (!reg) - return false; + return 0; bios_wr32(bios, reg, tmdsaddr | NV_PRAMDAC_FP_TMDS_CONTROL_WRITE_DISABLE); @@ -1471,10 +1475,10 @@ init_tmds(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) bios_wr32(bios, reg + 4, value); bios_wr32(bios, reg, tmdsaddr); - return true; + return 5; } -static bool +static int init_zm_tmds_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1495,18 +1499,19 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, uint8_t mlv = bios->data[offset + 1]; uint8_t count = bios->data[offset + 2]; + int len = 3 + count * 2; uint32_t reg; int i; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: MagicLookupValue: 0x%02X, Count: 0x%02X\n", offset, mlv, count); reg = get_tmds_index_reg(bios->dev, mlv); if (!reg) - return false; + return 0; for (i = 0; i < count; i++) { uint8_t tmdsaddr = bios->data[offset + 3 + i * 2]; @@ -1516,10 +1521,10 @@ init_zm_tmds_group(struct nvbios *bios, uint16_t offset, bios_wr32(bios, reg, tmdsaddr); } - return true; + return len; } -static bool +static int init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1542,11 +1547,12 @@ init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset, uint8_t crtcindex2 = bios->data[offset + 2]; uint8_t baseaddr = bios->data[offset + 3]; uint8_t count = bios->data[offset + 4]; + int len = 5 + count; uint8_t oldaddr, data; int i; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: Index1: 0x%02X, Index2: 0x%02X, " "BaseAddr: 0x%02X, Count: 0x%02X\n", @@ -1563,10 +1569,10 @@ init_cr_idx_adr_latch(struct nvbios *bios, uint16_t offset, bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex1, oldaddr); - return true; + return len; } -static bool +static int init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1587,7 +1593,7 @@ init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t value; if (!iexec->execute) - return true; + return 4; BIOSLOG(bios, "0x%04X: Index: 0x%02X, Mask: 0x%02X, Data: 0x%02X\n", offset, crtcindex, mask, data); @@ -1596,10 +1602,10 @@ init_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) value |= data; bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, value); - return true; + return 4; } -static bool +static int init_zm_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1616,14 +1622,14 @@ init_zm_cr(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t data = bios->data[offset + 2]; if (!iexec->execute) - return true; + return 3; bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, crtcindex, data); - return true; + return 3; } -static bool +static int init_zm_cr_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1640,18 +1646,19 @@ init_zm_cr_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) */ uint8_t count = bios->data[offset + 1]; + int len = 2 + count * 2; int i; if (!iexec->execute) - return true; + return len; for (i = 0; i < count; i++) init_zm_cr(bios, offset + 2 + 2 * i - 1, iexec); - return true; + return len; } -static bool +static int init_condition_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1675,7 +1682,7 @@ init_condition_time(struct nvbios *bios, uint16_t offset, unsigned cnt; if (!iexec->execute) - return true; + return 3; if (retries > 100) retries = 100; @@ -1706,10 +1713,10 @@ init_condition_time(struct nvbios *bios, uint16_t offset, iexec->execute = false; } - return true; + return 3; } -static bool +static int init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1729,10 +1736,11 @@ init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, uint32_t basereg = ROM32(bios->data[offset + 1]); uint32_t count = bios->data[offset + 5]; + int len = 6 + count * 4; int i; if (!iexec->execute) - return true; + return len; BIOSLOG(bios, "0x%04X: BaseReg: 0x%08X, Count: 0x%02X\n", offset, basereg, count); @@ -1744,10 +1752,10 @@ init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, bios_wr32(bios, reg, data); } - return true; + return len; } -static bool +static int init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1763,7 +1771,7 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint16_t sub_offset = ROM16(bios->data[offset + 1]); if (!iexec->execute) - return true; + return 3; BIOSLOG(bios, "0x%04X: Executing subroutine at 0x%04X\n", offset, sub_offset); @@ -1772,10 +1780,10 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) BIOSLOG(bios, "0x%04X: End of 0x%04X subroutine\n", offset, sub_offset); - return true; + return 3; } -static bool +static int init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1803,7 +1811,7 @@ init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint32_t srcvalue, dstvalue; if (!iexec->execute) - return true; + return 22; BIOSLOG(bios, "0x%04X: SrcReg: 0x%08X, Shift: 0x%02X, SrcMask: 0x%08X, " "Xor: 0x%08X, DstReg: 0x%08X, DstMask: 0x%08X\n", @@ -1822,10 +1830,10 @@ init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) bios_wr32(bios, dstreg, dstvalue | srcvalue); - return true; + return 22; } -static bool +static int init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1843,14 +1851,14 @@ init_zm_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t data = bios->data[offset + 4]; if (!iexec->execute) - return true; + return 5; bios_idxprt_wr(bios, crtcport, crtcindex, data); - return true; + return 5; } -static bool +static int init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1899,7 +1907,7 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) struct drm_nouveau_private *dev_priv = bios->dev->dev_private; if (dev_priv->card_type >= NV_50) - return true; + return 1; /* * On every card I've seen, this step gets done for us earlier in @@ -1917,10 +1925,10 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) /* write back the saved configuration value */ bios_wr32(bios, NV_PFB_CFG0, bios->state.saved_nv_pfb_cfg0); - return true; + return 1; } -static bool +static int init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -1954,10 +1962,10 @@ init_reset(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) pci_nv_20 &= ~NV_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED; /* 0xfffffffe */ bios_wr32(bios, NV_PBUS_PCI_NV_20, pci_nv_20); - return true; + return 13; } -static bool +static int init_configure_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -1978,7 +1986,7 @@ init_configure_mem(struct nvbios *bios, uint16_t offset, uint32_t reg, data; if (bios->major_version > 2) - return false; + return 0; bios_idxprt_wr(bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX, bios_idxprt_rd( bios, NV_VIO_SRX, NV_VIO_SR_CLOCK_INDEX) | 0x20); @@ -2010,10 +2018,10 @@ init_configure_mem(struct nvbios *bios, uint16_t offset, bios_wr32(bios, reg, data); } - return true; + return 1; } -static bool +static int init_configure_clk(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -2033,7 +2041,7 @@ init_configure_clk(struct nvbios *bios, uint16_t offset, int clock; if (bios->major_version > 2) - return false; + return 0; clock = ROM16(bios->data[meminitoffs + 4]) * 10; setPLL(bios, NV_PRAMDAC_NVPLL_COEFF, clock); @@ -2043,10 +2051,10 @@ init_configure_clk(struct nvbios *bios, uint16_t offset, clock *= 2; setPLL(bios, NV_PRAMDAC_MPLL_COEFF, clock); - return true; + return 1; } -static bool +static int init_configure_preinit(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -2066,15 +2074,15 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset, uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); if (bios->major_version > 2) - return false; + return 0; bios_idxprt_wr(bios, NV_CIO_CRX__COLOR, NV_CIO_CRE_SCRATCH4__INDEX, cr3c); - return true; + return 1; } -static bool +static int init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2094,7 +2102,7 @@ init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t data = bios->data[offset + 4]; if (!iexec->execute) - return true; + return 5; BIOSLOG(bios, "0x%04X: Port: 0x%04X, Mask: 0x%02X, Data: 0x%02X\n", offset, crtcport, mask, data); @@ -2153,15 +2161,15 @@ init_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) for (i = 0; i < 2; i++) bios_wr32(bios, 0x614108 + (i*0x800), bios_rd32( bios, 0x614108 + (i*0x800)) & 0x0fffffff); - return true; + return 5; } bios_port_wr(bios, crtcport, (bios_port_rd(bios, crtcport) & mask) | data); - return true; + return 5; } -static bool +static int init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2176,7 +2184,7 @@ init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t sub = bios->data[offset + 1]; if (!iexec->execute) - return true; + return 2; BIOSLOG(bios, "0x%04X: Calling script %d\n", offset, sub); @@ -2186,10 +2194,10 @@ init_sub(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) BIOSLOG(bios, "0x%04X: End of script %d\n", offset, sub); - return true; + return 2; } -static bool +static int init_ram_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -2210,7 +2218,7 @@ init_ram_condition(struct nvbios *bios, uint16_t offset, uint8_t data; if (!iexec->execute) - return true; + return 3; data = bios_rd32(bios, NV_PFB_BOOT_0) & mask; @@ -2224,10 +2232,10 @@ init_ram_condition(struct nvbios *bios, uint16_t offset, iexec->execute = false; } - return true; + return 3; } -static bool +static int init_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2246,17 +2254,17 @@ init_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint32_t data = ROM32(bios->data[offset + 9]); if (!iexec->execute) - return true; + return 13; BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Mask: 0x%08X, Data: 0x%08X\n", offset, reg, mask, data); bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | data); - return true; + return 13; } -static bool +static int init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2280,7 +2288,7 @@ init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) int i; if (!iexec->execute) - return true; + return 2; BIOSLOG(bios, "0x%04X: Macro: 0x%02X, MacroTableIndex: 0x%02X, " "Count: 0x%02X\n", @@ -2295,10 +2303,10 @@ init_macro(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) bios_wr32(bios, reg, data); } - return true; + return 2; } -static bool +static int init_done(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2310,10 +2318,10 @@ init_done(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) */ /* mild retval abuse to stop parsing this table */ - return false; + return 0; } -static bool +static int init_resume(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2325,15 +2333,15 @@ init_resume(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) */ if (iexec->execute) - return true; + return 1; iexec->execute = true; BIOSLOG(bios, "0x%04X: ---- Executing following commands ----\n", offset); - return true; + return 1; } -static bool +static int init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2348,7 +2356,7 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) unsigned time = ROM16(bios->data[offset + 1]); if (!iexec->execute) - return true; + return 3; BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X microseconds\n", offset, time); @@ -2358,10 +2366,10 @@ init_time(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) else msleep((time + 900) / 1000); - return true; + return 3; } -static bool +static int init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2378,7 +2386,7 @@ init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t cond = bios->data[offset + 1]; if (!iexec->execute) - return true; + return 2; BIOSLOG(bios, "0x%04X: Condition: 0x%02X\n", offset, cond); @@ -2389,10 +2397,10 @@ init_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) iexec->execute = false; } - return true; + return 2; } -static bool +static int init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2409,7 +2417,7 @@ init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t cond = bios->data[offset + 1]; if (!iexec->execute) - return true; + return 2; BIOSLOG(bios, "0x%04X: IO condition: 0x%02X\n", offset, cond); @@ -2420,10 +2428,10 @@ init_io_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) iexec->execute = false; } - return true; + return 2; } -static bool +static int init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2446,7 +2454,7 @@ init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint8_t value; if (!iexec->execute) - return true; + return 6; BIOSLOG(bios, "0x%04X: Port: 0x%04X, Index: 0x%02X, Mask: 0x%02X, " "Data: 0x%02X\n", @@ -2455,10 +2463,10 @@ init_index_io(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) value = (bios_idxprt_rd(bios, crtcport, crtcindex) & mask) | data; bios_idxprt_wr(bios, crtcport, crtcindex, value); - return true; + return 6; } -static bool +static int init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2476,16 +2484,16 @@ init_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint16_t freq = ROM16(bios->data[offset + 5]); if (!iexec->execute) - return true; + return 7; BIOSLOG(bios, "0x%04X: Reg: 0x%08X, Freq: %d0kHz\n", offset, reg, freq); setPLL(bios, reg, freq * 10); - return true; + return 7; } -static bool +static int init_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2502,17 +2510,17 @@ init_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint32_t value = ROM32(bios->data[offset + 5]); if (!iexec->execute) - return true; + return 9; if (reg == 0x000200) value |= 1; bios_wr32(bios, reg, value); - return true; + return 9; } -static bool +static int init_ram_restrict_pll(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -2538,14 +2546,15 @@ init_ram_restrict_pll(struct nvbios *bios, uint16_t offset, uint8_t type = bios->data[offset + 1]; uint32_t freq = ROM32(bios->data[offset + 2 + (index * 4)]); uint8_t *pll_limits = &bios->data[bios->pll_limit_tbl_ptr], *entry; + int len = 2 + bios->ram_restrict_group_count * 4; int i; if (!iexec->execute) - return true; + return len; if (!bios->pll_limit_tbl_ptr || (pll_limits[0] & 0xf0) != 0x30) { NV_ERROR(dev, "PLL limits table not version 3.x\n"); - return true; /* deliberate, allow default clocks to remain */ + return len; /* deliberate, allow default clocks to remain */ } entry = pll_limits + pll_limits[1]; @@ -2558,15 +2567,15 @@ init_ram_restrict_pll(struct nvbios *bios, uint16_t offset, offset, type, reg, freq); setPLL(bios, reg, freq); - return true; + return len; } } NV_ERROR(dev, "PLL type 0x%02x not found in PLL limits table", type); - return true; + return len; } -static bool +static int init_8c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2576,10 +2585,10 @@ init_8c(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) * */ - return true; + return 1; } -static bool +static int init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2589,10 +2598,10 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) * */ - return true; + return 1; } -static bool +static int init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2610,14 +2619,17 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) const uint8_t *gpio_entry; int i; + if (!iexec->execute) + return 1; + if (bios->bdcb.version != 0x40) { NV_ERROR(bios->dev, "DCB table not version 4.0\n"); - return false; + return 0; } if (!bios->bdcb.gpio_table_ptr) { NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n"); - return false; + return 0; } gpio_entry = gpio_table + gpio_table[1]; @@ -2655,13 +2667,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) bios_wr32(bios, r, v); } - return true; + return 1; } -/* hack to avoid moving the itbl_entry array before this function */ -int init_ram_restrict_zm_reg_group_blocklen; - -static bool +static int init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -2687,21 +2696,21 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, uint8_t regincrement = bios->data[offset + 5]; uint8_t count = bios->data[offset + 6]; uint32_t strap_ramcfg, data; - uint16_t blocklen; + /* previously set by 'M' BIT table */ + uint16_t blocklen = bios->ram_restrict_group_count * 4; + int len = 7 + count * blocklen; uint8_t index; int i; - /* previously set by 'M' BIT table */ - blocklen = init_ram_restrict_zm_reg_group_blocklen; if (!iexec->execute) - return true; + return len; if (!blocklen) { NV_ERROR(bios->dev, "0x%04X: Zero block length - has the M table " "been parsed?\n", offset); - return false; + return 0; } strap_ramcfg = (bios_rd32(bios, NV_PEXTDEV_BOOT_0) >> 2) & 0xf; @@ -2719,10 +2728,10 @@ init_ram_restrict_zm_reg_group(struct nvbios *bios, uint16_t offset, reg += regincrement; } - return true; + return len; } -static bool +static int init_copy_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2739,14 +2748,14 @@ init_copy_zm_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) uint32_t dstreg = ROM32(bios->data[offset + 5]); if (!iexec->execute) - return true; + return 9; bios_wr32(bios, dstreg, bios_rd32(bios, srcreg)); - return true; + return 9; } -static bool +static int init_zm_reg_group_addr_latched(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -2764,20 +2773,21 @@ init_zm_reg_group_addr_latched(struct nvbios *bios, uint16_t offset, uint32_t reg = ROM32(bios->data[offset + 1]); uint8_t count = bios->data[offset + 5]; + int len = 6 + count * 4; int i; if (!iexec->execute) - return true; + return len; for (i = 0; i < count; i++) { uint32_t data = ROM32(bios->data[offset + 6 + 4 * i]); bios_wr32(bios, reg, data); } - return true; + return len; } -static bool +static int init_reserved(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2788,10 +2798,10 @@ init_reserved(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) * Seemingly does nothing */ - return true; + return 1; } -static bool +static int init_96(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2824,13 +2834,13 @@ init_96(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) val <<= bios->data[offset + 16]; if (!iexec->execute) - return true; + return 17; bios_wr32(bios, reg, (bios_rd32(bios, reg) & mask) | val); - return true; + return 17; } -static bool +static int init_97(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2854,13 +2864,13 @@ init_97(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) val = (val & mask) | ((val + add) & ~mask); if (!iexec->execute) - return true; + return 13; bios_wr32(bios, reg, val); - return true; + return 13; } -static bool +static int init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2878,32 +2888,33 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) struct drm_device *dev = bios->dev; struct nouveau_i2c_chan *auxch; uint32_t addr = ROM32(bios->data[offset + 1]); - uint8_t len = bios->data[offset + 5]; + uint8_t count = bios->data[offset + 5]; + int len = 6 + count * 2; int ret, i; if (!bios->display.output) { NV_ERROR(dev, "INIT_AUXCH: no active output\n"); - return false; + return 0; } auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); if (!auxch) { NV_ERROR(dev, "INIT_AUXCH: couldn't get auxch %d\n", bios->display.output->i2c_index); - return false; + return 0; } if (!iexec->execute) - return true; + return len; offset += 6; - for (i = 0; i < len; i++, offset += 2) { + for (i = 0; i < count; i++, offset += 2) { uint8_t data; ret = nouveau_dp_auxch(auxch, 9, addr, &data, 1); if (ret) { NV_ERROR(dev, "INIT_AUXCH: rd auxch fail %d\n", ret); - return false; + return 0; } data &= bios->data[offset + 0]; @@ -2912,14 +2923,14 @@ init_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ret = nouveau_dp_auxch(auxch, 8, addr, &data, 1); if (ret) { NV_ERROR(dev, "INIT_AUXCH: wr auxch fail %d\n", ret); - return false; + return 0; } } - return true; + return len; } -static bool +static int init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { /* @@ -2936,106 +2947,99 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) struct drm_device *dev = bios->dev; struct nouveau_i2c_chan *auxch; uint32_t addr = ROM32(bios->data[offset + 1]); - uint8_t len = bios->data[offset + 5]; + uint8_t count = bios->data[offset + 5]; + int len = 6 + count; int ret, i; if (!bios->display.output) { NV_ERROR(dev, "INIT_ZM_AUXCH: no active output\n"); - return false; + return 0; } auxch = init_i2c_device_find(dev, bios->display.output->i2c_index); if (!auxch) { NV_ERROR(dev, "INIT_ZM_AUXCH: couldn't get auxch %d\n", bios->display.output->i2c_index); - return false; + return 0; } if (!iexec->execute) - return true; + return len; offset += 6; - for (i = 0; i < len; i++, offset++) { + for (i = 0; i < count; i++, offset++) { ret = nouveau_dp_auxch(auxch, 8, addr, &bios->data[offset], 1); if (ret) { NV_ERROR(dev, "INIT_ZM_AUXCH: wr auxch fail %d\n", ret); - return false; + return 0; } } - return true; + return len; } static struct init_tbl_entry itbl_entry[] = { /* command name , id , length , offset , mult , command handler */ /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ - { "INIT_IO_RESTRICT_PROG" , 0x32, 11 , 6 , 4 , init_io_restrict_prog }, - { "INIT_REPEAT" , 0x33, 2 , 0 , 0 , init_repeat }, - { "INIT_IO_RESTRICT_PLL" , 0x34, 12 , 7 , 2 , init_io_restrict_pll }, - { "INIT_END_REPEAT" , 0x36, 1 , 0 , 0 , init_end_repeat }, - { "INIT_COPY" , 0x37, 11 , 0 , 0 , init_copy }, - { "INIT_NOT" , 0x38, 1 , 0 , 0 , init_not }, - { "INIT_IO_FLAG_CONDITION" , 0x39, 2 , 0 , 0 , init_io_flag_condition }, - { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, 18 , 17 , 2 , init_idx_addr_latched }, - { "INIT_IO_RESTRICT_PLL2" , 0x4A, 11 , 6 , 4 , init_io_restrict_pll2 }, - { "INIT_PLL2" , 0x4B, 9 , 0 , 0 , init_pll2 }, - { "INIT_I2C_BYTE" , 0x4C, 4 , 3 , 3 , init_i2c_byte }, - { "INIT_ZM_I2C_BYTE" , 0x4D, 4 , 3 , 2 , init_zm_i2c_byte }, - { "INIT_ZM_I2C" , 0x4E, 4 , 3 , 1 , init_zm_i2c }, - { "INIT_TMDS" , 0x4F, 5 , 0 , 0 , init_tmds }, - { "INIT_ZM_TMDS_GROUP" , 0x50, 3 , 2 , 2 , init_zm_tmds_group }, - { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, 5 , 4 , 1 , init_cr_idx_adr_latch }, - { "INIT_CR" , 0x52, 4 , 0 , 0 , init_cr }, - { "INIT_ZM_CR" , 0x53, 3 , 0 , 0 , init_zm_cr }, - { "INIT_ZM_CR_GROUP" , 0x54, 2 , 1 , 2 , init_zm_cr_group }, - { "INIT_CONDITION_TIME" , 0x56, 3 , 0 , 0 , init_condition_time }, - { "INIT_ZM_REG_SEQUENCE" , 0x58, 6 , 5 , 4 , init_zm_reg_sequence }, + { "INIT_IO_RESTRICT_PROG" , 0x32, init_io_restrict_prog }, + { "INIT_REPEAT" , 0x33, init_repeat }, + { "INIT_IO_RESTRICT_PLL" , 0x34, init_io_restrict_pll }, + { "INIT_END_REPEAT" , 0x36, init_end_repeat }, + { "INIT_COPY" , 0x37, init_copy }, + { "INIT_NOT" , 0x38, init_not }, + { "INIT_IO_FLAG_CONDITION" , 0x39, init_io_flag_condition }, + { "INIT_INDEX_ADDRESS_LATCHED" , 0x49, init_idx_addr_latched }, + { "INIT_IO_RESTRICT_PLL2" , 0x4A, init_io_restrict_pll2 }, + { "INIT_PLL2" , 0x4B, init_pll2 }, + { "INIT_I2C_BYTE" , 0x4C, init_i2c_byte }, + { "INIT_ZM_I2C_BYTE" , 0x4D, init_zm_i2c_byte }, + { "INIT_ZM_I2C" , 0x4E, init_zm_i2c }, + { "INIT_TMDS" , 0x4F, init_tmds }, + { "INIT_ZM_TMDS_GROUP" , 0x50, init_zm_tmds_group }, + { "INIT_CR_INDEX_ADDRESS_LATCHED" , 0x51, init_cr_idx_adr_latch }, + { "INIT_CR" , 0x52, init_cr }, + { "INIT_ZM_CR" , 0x53, init_zm_cr }, + { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, + { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, + { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ - { "INIT_SUB_DIRECT" , 0x5B, 3 , 0 , 0 , init_sub_direct }, - { "INIT_COPY_NV_REG" , 0x5F, 22 , 0 , 0 , init_copy_nv_reg }, - { "INIT_ZM_INDEX_IO" , 0x62, 5 , 0 , 0 , init_zm_index_io }, - { "INIT_COMPUTE_MEM" , 0x63, 1 , 0 , 0 , init_compute_mem }, - { "INIT_RESET" , 0x65, 13 , 0 , 0 , init_reset }, - { "INIT_CONFIGURE_MEM" , 0x66, 1 , 0 , 0 , init_configure_mem }, - { "INIT_CONFIGURE_CLK" , 0x67, 1 , 0 , 0 , init_configure_clk }, - { "INIT_CONFIGURE_PREINIT" , 0x68, 1 , 0 , 0 , init_configure_preinit }, - { "INIT_IO" , 0x69, 5 , 0 , 0 , init_io }, - { "INIT_SUB" , 0x6B, 2 , 0 , 0 , init_sub }, - { "INIT_RAM_CONDITION" , 0x6D, 3 , 0 , 0 , init_ram_condition }, - { "INIT_NV_REG" , 0x6E, 13 , 0 , 0 , init_nv_reg }, - { "INIT_MACRO" , 0x6F, 2 , 0 , 0 , init_macro }, - { "INIT_DONE" , 0x71, 1 , 0 , 0 , init_done }, - { "INIT_RESUME" , 0x72, 1 , 0 , 0 , init_resume }, + { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, + { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, + { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, + { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, + { "INIT_RESET" , 0x65, init_reset }, + { "INIT_CONFIGURE_MEM" , 0x66, init_configure_mem }, + { "INIT_CONFIGURE_CLK" , 0x67, init_configure_clk }, + { "INIT_CONFIGURE_PREINIT" , 0x68, init_configure_preinit }, + { "INIT_IO" , 0x69, init_io }, + { "INIT_SUB" , 0x6B, init_sub }, + { "INIT_RAM_CONDITION" , 0x6D, init_ram_condition }, + { "INIT_NV_REG" , 0x6E, init_nv_reg }, + { "INIT_MACRO" , 0x6F, init_macro }, + { "INIT_DONE" , 0x71, init_done }, + { "INIT_RESUME" , 0x72, init_resume }, /* INIT_RAM_CONDITION2 (0x73, 9, 0, 0) removed due to no example of use */ - { "INIT_TIME" , 0x74, 3 , 0 , 0 , init_time }, - { "INIT_CONDITION" , 0x75, 2 , 0 , 0 , init_condition }, - { "INIT_IO_CONDITION" , 0x76, 2 , 0 , 0 , init_io_condition }, - { "INIT_INDEX_IO" , 0x78, 6 , 0 , 0 , init_index_io }, - { "INIT_PLL" , 0x79, 7 , 0 , 0 , init_pll }, - { "INIT_ZM_REG" , 0x7A, 9 , 0 , 0 , init_zm_reg }, - /* INIT_RAM_RESTRICT_PLL's length is adjusted by the BIT M table */ - { "INIT_RAM_RESTRICT_PLL" , 0x87, 2 , 0 , 0 , init_ram_restrict_pll }, - { "INIT_8C" , 0x8C, 1 , 0 , 0 , init_8c }, - { "INIT_8D" , 0x8D, 1 , 0 , 0 , init_8d }, - { "INIT_GPIO" , 0x8E, 1 , 0 , 0 , init_gpio }, - /* INIT_RAM_RESTRICT_ZM_REG_GROUP's mult is loaded by M table in BIT */ - { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, 7 , 6 , 0 , init_ram_restrict_zm_reg_group }, - { "INIT_COPY_ZM_REG" , 0x90, 9 , 0 , 0 , init_copy_zm_reg }, - { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, 6 , 5 , 4 , init_zm_reg_group_addr_latched }, - { "INIT_RESERVED" , 0x92, 1 , 0 , 0 , init_reserved }, - { "INIT_96" , 0x96, 17 , 0 , 0 , init_96 }, - { "INIT_97" , 0x97, 13 , 0 , 0 , init_97 }, - { "INIT_AUXCH" , 0x98, 6 , 5 , 2 , init_auxch }, - { "INIT_ZM_AUXCH" , 0x99, 6 , 5 , 1 , init_zm_auxch }, - { NULL , 0 , 0 , 0 , 0 , NULL } + { "INIT_TIME" , 0x74, init_time }, + { "INIT_CONDITION" , 0x75, init_condition }, + { "INIT_IO_CONDITION" , 0x76, init_io_condition }, + { "INIT_INDEX_IO" , 0x78, init_index_io }, + { "INIT_PLL" , 0x79, init_pll }, + { "INIT_ZM_REG" , 0x7A, init_zm_reg }, + { "INIT_RAM_RESTRICT_PLL" , 0x87, init_ram_restrict_pll }, + { "INIT_8C" , 0x8C, init_8c }, + { "INIT_8D" , 0x8D, init_8d }, + { "INIT_GPIO" , 0x8E, init_gpio }, + { "INIT_RAM_RESTRICT_ZM_REG_GROUP" , 0x8F, init_ram_restrict_zm_reg_group }, + { "INIT_COPY_ZM_REG" , 0x90, init_copy_zm_reg }, + { "INIT_ZM_REG_GROUP_ADDRESS_LATCHED" , 0x91, init_zm_reg_group_addr_latched }, + { "INIT_RESERVED" , 0x92, init_reserved }, + { "INIT_96" , 0x96, init_96 }, + { "INIT_97" , 0x97, init_97 }, + { "INIT_AUXCH" , 0x98, init_auxch }, + { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, + { NULL , 0 , NULL } }; -static unsigned int get_init_table_entry_length(struct nvbios *bios, unsigned int offset, int i) -{ - /* Calculates the length of a given init table entry. */ - return itbl_entry[i].length + bios->data[offset + itbl_entry[i].length_offset]*itbl_entry[i].length_multiplier; -} - #define MAX_TABLE_OPS 1000 static int @@ -3051,7 +3055,7 @@ parse_init_table(struct nvbios *bios, unsigned int offset, * is changed back to EXECUTE. */ - int count = 0, i; + int count = 0, i, res; uint8_t id; /* @@ -3071,22 +3075,21 @@ parse_init_table(struct nvbios *bios, unsigned int offset, offset, itbl_entry[i].id, itbl_entry[i].name); /* execute eventual command handler */ - if (itbl_entry[i].handler) - if (!(*itbl_entry[i].handler)(bios, offset, iexec)) - break; + res = (*itbl_entry[i].handler)(bios, offset, iexec); + if (!res) + break; + /* + * Add the offset of the current command including all data + * of that command. The offset will then be pointing on the + * next op code. + */ + offset += res; } else { NV_ERROR(bios->dev, "0x%04X: Init table command not found: " "0x%02X\n", offset, id); return -ENOENT; } - - /* - * Add the offset of the current command including all data - * of that command. The offset will then be pointing on the - * next op code. - */ - offset += get_init_table_entry_length(bios, offset, i); } if (offset >= bios->length) @@ -4601,10 +4604,6 @@ parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios, * stuff that we don't use - their use currently unknown */ - uint16_t rr_strap_xlat; - uint8_t rr_group_count; - int i; - /* * Older bios versions don't have a sufficiently long table for * what we want @@ -4613,24 +4612,13 @@ parse_bit_M_tbl_entry(struct drm_device *dev, struct nvbios *bios, return 0; if (bitentry->id[1] < 2) { - rr_group_count = bios->data[bitentry->offset + 2]; - rr_strap_xlat = ROM16(bios->data[bitentry->offset + 3]); + bios->ram_restrict_group_count = bios->data[bitentry->offset + 2]; + bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 3]); } else { - rr_group_count = bios->data[bitentry->offset + 0]; - rr_strap_xlat = ROM16(bios->data[bitentry->offset + 1]); + bios->ram_restrict_group_count = bios->data[bitentry->offset + 0]; + bios->ram_restrict_tbl_ptr = ROM16(bios->data[bitentry->offset + 1]); } - /* adjust length of INIT_87 */ - for (i = 0; itbl_entry[i].name && (itbl_entry[i].id != 0x87); i++); - itbl_entry[i].length += rr_group_count * 4; - - /* set up multiplier for INIT_RAM_RESTRICT_ZM_REG_GROUP */ - for (; itbl_entry[i].name && (itbl_entry[i].id != 0x8f); i++); - itbl_entry[i].length_multiplier = rr_group_count * 4; - - init_ram_restrict_zm_reg_group_blocklen = itbl_entry[i].length_multiplier; - bios->ram_restrict_tbl_ptr = rr_strap_xlat; - return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 1d5f10bd78e..058e98c76d8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -227,6 +227,7 @@ struct nvbios { uint16_t pll_limit_tbl_ptr; uint16_t ram_restrict_tbl_ptr; + uint8_t ram_restrict_group_count; uint16_t some_script_ptr; /* BIT I + 14 */ uint16_t init96_tbl_ptr; /* BIT I + 16 */ -- cgit v1.2.3-70-g09d2 From 13c5443b515109f175bb9917c578a7ae973f6851 Mon Sep 17 00:00:00 2001 From: Marcin KoÅ›cielnicki Date: Mon, 14 Dec 2009 20:38:17 +0000 Subject: drm/nv04: Fix NV04 set_operation software method. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin KoÅ›cielnicki Signed-off-by: Maarten Maathuis Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv04_graph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 396ee92118f..d561d773c0f 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c @@ -543,7 +543,7 @@ nv04_graph_mthd_set_operation(struct nouveau_channel *chan, int grclass, nv_wi32(dev, instance, tmp); nv_wr32(dev, NV04_PGRAPH_CTX_SWITCH1, tmp); - nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + subc, tmp); + nv_wr32(dev, NV04_PGRAPH_CTX_CACHE1 + (subc<<2), tmp); return 0; } -- cgit v1.2.3-70-g09d2 From c5804be0627508487bd9eacebf9de7f807e5d4e7 Mon Sep 17 00:00:00 2001 From: Marcin KoÅ›cielnicki Date: Mon, 14 Dec 2009 20:58:39 +0000 Subject: drm/nouveau: Add proper error handling to nouveau_card_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marcin KoÅ›cielnicki Signed-off-by: Maarten Maathuis Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_state.c | 73 ++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 2ed41d339f6..9fc582432da 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -317,7 +317,7 @@ nouveau_card_init(struct drm_device *dev) /* Initialise internal driver API hooks */ ret = nouveau_init_engine_ptrs(dev); if (ret) - return ret; + goto out; engine = &dev_priv->engine; dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED; @@ -325,12 +325,12 @@ nouveau_card_init(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) { ret = nouveau_bios_init(dev); if (ret) - return ret; + goto out; } ret = nouveau_gpuobj_early_init(dev); if (ret) - return ret; + goto out_bios; /* Initialise instance memory, must happen before mem_init so we * know exactly how much VRAM we're able to use for "normal" @@ -338,52 +338,52 @@ nouveau_card_init(struct drm_device *dev) */ ret = engine->instmem.init(dev); if (ret) - return ret; + goto out_gpuobj_early; /* Setup the memory manager */ ret = nouveau_mem_init(dev); if (ret) - return ret; + goto out_instmem; ret = nouveau_gpuobj_init(dev); if (ret) - return ret; + goto out_mem; /* PMC */ ret = engine->mc.init(dev); if (ret) - return ret; + goto out_gpuobj; /* PTIMER */ ret = engine->timer.init(dev); if (ret) - return ret; + goto out_mc; /* PFB */ ret = engine->fb.init(dev); if (ret) - return ret; + goto out_timer; /* PGRAPH */ ret = engine->graph.init(dev); if (ret) - return ret; + goto out_fb; /* PFIFO */ ret = engine->fifo.init(dev); if (ret) - return ret; + goto out_graph; /* this call irq_preinstall, register irq handler and * call irq_postinstall */ ret = drm_irq_install(dev); if (ret) - return ret; + goto out_fifo; ret = drm_vblank_init(dev, 0); if (ret) - return ret; + goto out_irq; /* what about PVIDEO/PCRTC/PRAMDAC etc? */ @@ -391,7 +391,7 @@ nouveau_card_init(struct drm_device *dev) (struct drm_file *)-2, NvDmaFB, NvDmaTT); if (ret) - return ret; + goto out_irq; gpuobj = NULL; ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, @@ -399,13 +399,13 @@ nouveau_card_init(struct drm_device *dev) NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, &gpuobj); if (ret) - return ret; + goto out_irq; ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, gpuobj, NULL); if (ret) { nouveau_gpuobj_del(dev, &gpuobj); - return ret; + goto out_irq; } gpuobj = NULL; @@ -413,25 +413,22 @@ nouveau_card_init(struct drm_device *dev) dev_priv->gart_info.aper_size, NV_DMA_ACCESS_RW, &gpuobj, NULL); if (ret) - return ret; + goto out_irq; ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, gpuobj, NULL); if (ret) { nouveau_gpuobj_del(dev, &gpuobj); - return ret; + goto out_irq; } if (drm_core_check_feature(dev, DRIVER_MODESET)) { - if (dev_priv->card_type >= NV_50) { + if (dev_priv->card_type >= NV_50) ret = nv50_display_create(dev); - if (ret) - return ret; - } else { + else ret = nv04_display_create(dev); - if (ret) - return ret; - } + if (ret) + goto out_irq; } ret = nouveau_backlight_init(dev); @@ -444,6 +441,32 @@ nouveau_card_init(struct drm_device *dev) drm_helper_initial_config(dev); return 0; + +out_irq: + drm_irq_uninstall(dev); +out_fifo: + engine->fifo.takedown(dev); +out_graph: + engine->graph.takedown(dev); +out_fb: + engine->fb.takedown(dev); +out_timer: + engine->timer.takedown(dev); +out_mc: + engine->mc.takedown(dev); +out_gpuobj: + nouveau_gpuobj_takedown(dev); +out_mem: + nouveau_mem_close(dev); +out_instmem: + engine->instmem.takedown(dev); +out_gpuobj_early: + nouveau_gpuobj_late_takedown(dev); +out_bios: + nouveau_bios_takedown(dev); +out: + vga_client_register(dev->pdev, NULL, NULL, NULL); + return ret; } static void nouveau_card_takedown(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 22fbd53809eb7a1b00fe09159fe0a565fb6c725c Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Fri, 11 Dec 2009 18:40:17 +0100 Subject: drm/nouveau: Fix up buffer eviction, and evict them to GART, if possible. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index aa2dfbc3e35..e9f01906c52 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -400,10 +400,16 @@ nouveau_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl) struct nouveau_bo *nvbo = nouveau_bo(bo); switch (bo->mem.mem_type) { + case TTM_PL_VRAM: + nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_TT | + TTM_PL_FLAG_SYSTEM); + break; default: nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_SYSTEM); break; } + + *pl = nvbo->placement; } -- cgit v1.2.3-70-g09d2 From 15bee69ee1532a29e13124b298027ee6ef54bac8 Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Mon, 14 Dec 2009 15:00:30 +0100 Subject: drm/nv10: Add the initial graph context and soft methods needed for LMA. Signed-off-by: Francisco Jerez Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv10_graph.c | 197 +++++++++++++++++++++++++++-------- 1 file changed, 154 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index 6bf6804bb0e..6870e0ee2e7 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c @@ -389,49 +389,50 @@ struct graph_state { int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)]; int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)]; struct pipe_state pipe_state; + uint32_t lma_window[4]; }; +#define PIPE_SAVE(dev, state, addr) \ + do { \ + int __i; \ + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ + state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ + } while (0) + +#define PIPE_RESTORE(dev, state, addr) \ + do { \ + int __i; \ + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ + for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \ + } while (0) + static void nv10_graph_save_pipe(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct graph_state *pgraph_ctx = chan->pgraph_ctx; - struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; - int i; -#define PIPE_SAVE(addr) \ - do { \ - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ - for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \ - fifo_pipe_state->pipe_##addr[i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ - } while (0) - - PIPE_SAVE(0x4400); - PIPE_SAVE(0x0200); - PIPE_SAVE(0x6400); - PIPE_SAVE(0x6800); - PIPE_SAVE(0x6c00); - PIPE_SAVE(0x7000); - PIPE_SAVE(0x7400); - PIPE_SAVE(0x7800); - PIPE_SAVE(0x0040); - PIPE_SAVE(0x0000); - -#undef PIPE_SAVE + struct pipe_state *pipe = &pgraph_ctx->pipe_state; + + PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); + PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400); + PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800); + PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00); + PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000); + PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400); + PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800); + PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040); + PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000); } static void nv10_graph_load_pipe(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct graph_state *pgraph_ctx = chan->pgraph_ctx; - struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; - int i; + struct pipe_state *pipe = &pgraph_ctx->pipe_state; uint32_t xfmode0, xfmode1; -#define PIPE_RESTORE(addr) \ - do { \ - nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ - for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \ - nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, fifo_pipe_state->pipe_##addr[i]); \ - } while (0) - + int i; nouveau_wait_for_idle(dev); /* XXX check haiku comments */ @@ -457,24 +458,22 @@ static void nv10_graph_load_pipe(struct nouveau_channel *chan) nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); - PIPE_RESTORE(0x0200); + PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); nouveau_wait_for_idle(dev); /* restore XFMODE */ nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); - PIPE_RESTORE(0x6400); - PIPE_RESTORE(0x6800); - PIPE_RESTORE(0x6c00); - PIPE_RESTORE(0x7000); - PIPE_RESTORE(0x7400); - PIPE_RESTORE(0x7800); - PIPE_RESTORE(0x4400); - PIPE_RESTORE(0x0000); - PIPE_RESTORE(0x0040); + PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400); + PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800); + PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00); + PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000); + PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400); + PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800); + PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); + PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000); + PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040); nouveau_wait_for_idle(dev); - -#undef PIPE_RESTORE } static void nv10_graph_create_pipe(struct nouveau_channel *chan) @@ -832,6 +831,9 @@ int nv10_graph_init(struct drm_device *dev) (1<<31)); if (dev_priv->chipset >= 0x17) { nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000); + nv_wr32(dev, 0x400a10, 0x3ff3fb6); + nv_wr32(dev, 0x400838, 0x2f8684); + nv_wr32(dev, 0x40083c, 0x115f3f); nv_wr32(dev, 0x004006b0, 0x40000020); } else nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); @@ -867,6 +869,115 @@ void nv10_graph_takedown(struct drm_device *dev) { } +static int +nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + struct drm_device *dev = chan->dev; + struct graph_state *ctx = chan->pgraph_ctx; + struct pipe_state *pipe = &ctx->pipe_state; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; + uint32_t xfmode0, xfmode1; + int i; + + ctx->lma_window[(mthd - 0x1638) / 4] = data; + + if (mthd != 0x1644) + return 0; + + nouveau_wait_for_idle(dev); + + PIPE_SAVE(dev, pipe_0x0040, 0x0040); + PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); + + PIPE_RESTORE(dev, ctx->lma_window, 0x6790); + + nouveau_wait_for_idle(dev); + + xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0); + xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1); + + PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); + PIPE_SAVE(dev, pipe_0x64c0, 0x64c0); + PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0); + PIPE_SAVE(dev, pipe_0x6a80, 0x6a80); + + nouveau_wait_for_idle(dev); + + nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000); + nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000); + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); + for (i = 0; i < 4; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + for (i = 0; i < 4; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); + for (i = 0; i < 3; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); + + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); + for (i = 0; i < 3; i++) + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); + + PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); + + nouveau_wait_for_idle(dev); + + PIPE_RESTORE(dev, pipe_0x0040, 0x0040); + + nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); + nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); + + PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0); + PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0); + PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80); + PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); + + nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); + nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); + + nouveau_wait_for_idle(dev); + + pgraph->fifo_access(dev, true); + + return 0; +} + +static int +nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass, + int mthd, uint32_t data) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + + nouveau_wait_for_idle(dev); + + nv_wr32(dev, NV10_PGRAPH_DEBUG_4, + nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8); + nv_wr32(dev, 0x004006b0, + nv_rd32(dev, 0x004006b0) | 0x8 << 24); + + pgraph->fifo_access(dev, true); + + return 0; +} + +static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = { + { 0x1638, nv17_graph_mthd_lma_window }, + { 0x163c, nv17_graph_mthd_lma_window }, + { 0x1640, nv17_graph_mthd_lma_window }, + { 0x1644, nv17_graph_mthd_lma_window }, + { 0x1658, nv17_graph_mthd_lma_enable }, + {} +}; + struct nouveau_pgraph_object_class nv10_graph_grclass[] = { { 0x0030, false, NULL }, /* null */ { 0x0039, false, NULL }, /* m2mf */ @@ -887,6 +998,6 @@ struct nouveau_pgraph_object_class nv10_graph_grclass[] = { { 0x0095, false, NULL }, /* multitex_tri */ { 0x0056, false, NULL }, /* celcius (nv10) */ { 0x0096, false, NULL }, /* celcius (nv11) */ - { 0x0099, false, NULL }, /* celcius (nv17) */ + { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */ {} }; -- cgit v1.2.3-70-g09d2 From 054b93e444550a72aef17115363cdef253b9ee7c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 15 Dec 2009 22:02:47 +1000 Subject: drm/nv40: implement ctxprog/state generation The context programs are *very* simple compared to the ones used by the binary driver. There's notes in nv40_grctx.c explaining most of the things we don't implement. If we discover if/why any of it is required further down the track, we'll handle it then. The PGRAPH state generated for each chipset should match what NVIDIA do almost exactly (there's a couple of exceptions). If someone has a lot of time on their hands, they could figure out the mapping of object/method to PGRAPH register and demagic the initial state a little, it's not terribly important however. At time of commit, confirmed to be working at least well enough for accelerated X (and where tested, for 3D apps) on NV40, NV43, NV44, NV46, NV49, NV4A, NV4B and NV4E. A module option has been added to force the use of external firmware blobs if it becomes required. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/Makefile | 5 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 4 + drivers/gpu/drm/nouveau/nouveau_drv.h | 13 +- drivers/gpu/drm/nouveau/nouveau_grctx.c | 158 ++++++++ drivers/gpu/drm/nouveau/nouveau_grctx.h | 133 +++++++ drivers/gpu/drm/nouveau/nv40_graph.c | 212 ++-------- drivers/gpu/drm/nouveau/nv40_grctx.c | 678 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/nouveau/nv50_graph.c | 10 +- 8 files changed, 1031 insertions(+), 182 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nouveau_grctx.c create mode 100644 drivers/gpu/drm/nouveau/nouveau_grctx.h create mode 100644 drivers/gpu/drm/nouveau/nv40_grctx.c (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 1d90d4d0144..48c290b5da8 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile @@ -8,14 +8,15 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ nouveau_sgdma.o nouveau_dma.o \ nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ - nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ - nouveau_dp.o \ + nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ + nouveau_dp.o nouveau_grctx.o \ nv04_timer.o \ nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_fb.o nv10_fb.o nv40_fb.o \ nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ nv04_graph.o nv10_graph.o nv20_graph.o \ nv40_graph.o nv50_graph.o \ + nv40_grctx.o \ nv04_instmem.o nv50_instmem.o \ nv50_crtc.o nv50_dac.o nv50_sor.o \ nv50_cursor.o nv50_display.o nv50_fbcon.o \ diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 35249c35118..78662cc1c8d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -35,6 +35,10 @@ #include "drm_pciids.h" +MODULE_PARM_DESC(ctxfw, "Use external firmware blob for grctx init (NV40)"); +int nouveau_ctxfw = 0; +module_param_named(ctxfw, nouveau_ctxfw, int, 0400); + MODULE_PARM_DESC(noagp, "Disable AGP"); int nouveau_noagp; module_param_named(noagp, nouveau_noagp, int, 0400); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index bc6ffa5eeac..5f8cbb79c49 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -54,6 +54,7 @@ struct nouveau_fpriv { #include "nouveau_drm.h" #include "nouveau_reg.h" #include "nouveau_bios.h" +struct nouveau_grctx; #define MAX_NUM_DCB_ENTRIES 16 @@ -317,6 +318,7 @@ struct nouveau_pgraph_engine { bool accel_blocked; void *ctxprog; void *ctxvals; + int grctx_size; int (*init)(struct drm_device *); void (*takedown)(struct drm_device *); @@ -647,6 +649,7 @@ extern int nouveau_fbpercrtc; extern char *nouveau_tv_norm; extern int nouveau_reg_debug; extern char *nouveau_vbios; +extern int nouveau_ctxfw; /* nouveau_state.c */ extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); @@ -959,9 +962,7 @@ extern int nv40_graph_create_context(struct nouveau_channel *); extern void nv40_graph_destroy_context(struct nouveau_channel *); extern int nv40_graph_load_context(struct nouveau_channel *); extern int nv40_graph_unload_context(struct drm_device *); -extern int nv40_grctx_init(struct drm_device *); -extern void nv40_grctx_fini(struct drm_device *); -extern void nv40_grctx_vals_load(struct drm_device *, struct nouveau_gpuobj *); +extern void nv40_grctx_init(struct nouveau_grctx *); /* nv50_graph.c */ extern struct nouveau_pgraph_object_class nv50_graph_grclass[]; @@ -975,6 +976,12 @@ extern int nv50_graph_load_context(struct nouveau_channel *); extern int nv50_graph_unload_context(struct drm_device *); extern void nv50_graph_context_switch(struct drm_device *); +/* nouveau_grctx.c */ +extern int nouveau_grctx_prog_load(struct drm_device *); +extern void nouveau_grctx_vals_load(struct drm_device *, + struct nouveau_gpuobj *); +extern void nouveau_grctx_fini(struct drm_device *); + /* nv04_instmem.c */ extern int nv04_instmem_init(struct drm_device *); extern void nv04_instmem_takedown(struct drm_device *); diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.c b/drivers/gpu/drm/nouveau/nouveau_grctx.c new file mode 100644 index 00000000000..d5d84c87f75 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_grctx.c @@ -0,0 +1,158 @@ +/* + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +#include + +#include "drmP.h" +#include "nouveau_drv.h" + +struct nouveau_ctxprog { + uint32_t signature; + uint8_t version; + uint16_t length; + uint32_t data[]; +} __attribute__ ((packed)); + +struct nouveau_ctxvals { + uint32_t signature; + uint8_t version; + uint32_t length; + struct { + uint32_t offset; + uint32_t value; + } data[]; +} __attribute__ ((packed)); + +int +nouveau_grctx_prog_load(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + const int chipset = dev_priv->chipset; + const struct firmware *fw; + const struct nouveau_ctxprog *cp; + const struct nouveau_ctxvals *cv; + char name[32]; + int ret, i; + + if (!pgraph->ctxprog) { + sprintf(name, "nouveau/nv%02x.ctxprog", chipset); + ret = request_firmware(&fw, name, &dev->pdev->dev); + if (ret) { + NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset); + return ret; + } + + pgraph->ctxprog = kmalloc(fw->size, GFP_KERNEL); + if (!pgraph->ctxprog) { + NV_ERROR(dev, "OOM copying ctxprog\n"); + release_firmware(fw); + return -ENOMEM; + } + memcpy(pgraph->ctxprog, fw->data, fw->size); + + cp = pgraph->ctxprog; + if (le32_to_cpu(cp->signature) != 0x5043564e || + cp->version != 0 || + le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) { + NV_ERROR(dev, "ctxprog invalid\n"); + release_firmware(fw); + nouveau_grctx_fini(dev); + return -EINVAL; + } + release_firmware(fw); + } + + if (!pgraph->ctxvals) { + sprintf(name, "nouveau/nv%02x.ctxvals", chipset); + ret = request_firmware(&fw, name, &dev->pdev->dev); + if (ret) { + NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset); + nouveau_grctx_fini(dev); + return ret; + } + + pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL); + if (!pgraph->ctxprog) { + NV_ERROR(dev, "OOM copying ctxprog\n"); + release_firmware(fw); + nouveau_grctx_fini(dev); + return -ENOMEM; + } + memcpy(pgraph->ctxvals, fw->data, fw->size); + + cv = (void *)pgraph->ctxvals; + if (le32_to_cpu(cv->signature) != 0x5643564e || + cv->version != 0 || + le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) { + NV_ERROR(dev, "ctxvals invalid\n"); + release_firmware(fw); + nouveau_grctx_fini(dev); + return -EINVAL; + } + release_firmware(fw); + } + + cp = pgraph->ctxprog; + + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + for (i = 0; i < le16_to_cpu(cp->length); i++) + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, + le32_to_cpu(cp->data[i])); + + return 0; +} + +void +nouveau_grctx_fini(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + + if (pgraph->ctxprog) { + kfree(pgraph->ctxprog); + pgraph->ctxprog = NULL; + } + + if (pgraph->ctxvals) { + kfree(pgraph->ctxprog); + pgraph->ctxvals = NULL; + } +} + +void +nouveau_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; + struct nouveau_ctxvals *cv = pgraph->ctxvals; + int i; + + if (!cv) + return; + + for (i = 0; i < le32_to_cpu(cv->length); i++) + nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset), + le32_to_cpu(cv->data[i].value)); +} diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.h b/drivers/gpu/drm/nouveau/nouveau_grctx.h new file mode 100644 index 00000000000..5d39c4ce800 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_grctx.h @@ -0,0 +1,133 @@ +#ifndef __NOUVEAU_GRCTX_H__ +#define __NOUVEAU_GRCTX_H__ + +struct nouveau_grctx { + struct drm_device *dev; + + enum { + NOUVEAU_GRCTX_PROG, + NOUVEAU_GRCTX_VALS + } mode; + void *data; + + uint32_t ctxprog_max; + uint32_t ctxprog_len; + uint32_t ctxprog_reg; + int ctxprog_label[32]; + uint32_t ctxvals_pos; + uint32_t ctxvals_base; +}; + +#ifdef CP_CTX +static inline void +cp_out(struct nouveau_grctx *ctx, uint32_t inst) +{ + uint32_t *ctxprog = ctx->data; + + if (ctx->mode != NOUVEAU_GRCTX_PROG) + return; + + BUG_ON(ctx->ctxprog_len == ctx->ctxprog_max); + ctxprog[ctx->ctxprog_len++] = inst; +} + +static inline void +cp_lsr(struct nouveau_grctx *ctx, uint32_t val) +{ + cp_out(ctx, CP_LOAD_SR | val); +} + +static inline void +cp_ctx(struct nouveau_grctx *ctx, uint32_t reg, uint32_t length) +{ + ctx->ctxprog_reg = (reg - 0x00400000) >> 2; + + ctx->ctxvals_base = ctx->ctxvals_pos; + ctx->ctxvals_pos = ctx->ctxvals_base + length; + + if (length > (CP_CTX_COUNT >> CP_CTX_COUNT_SHIFT)) { + cp_lsr(ctx, length); + length = 0; + } + + cp_out(ctx, CP_CTX | (length << CP_CTX_COUNT_SHIFT) | ctx->ctxprog_reg); +} + +static inline void +cp_name(struct nouveau_grctx *ctx, int name) +{ + uint32_t *ctxprog = ctx->data; + int i; + + if (ctx->mode != NOUVEAU_GRCTX_PROG) + return; + + ctx->ctxprog_label[name] = ctx->ctxprog_len; + for (i = 0; i < ctx->ctxprog_len; i++) { + if ((ctxprog[i] & 0xfff00000) != 0xff400000) + continue; + if ((ctxprog[i] & CP_BRA_IP) != ((name) << CP_BRA_IP_SHIFT)) + continue; + ctxprog[i] = (ctxprog[i] & 0x00ff00ff) | + (ctx->ctxprog_len << CP_BRA_IP_SHIFT); + } +} + +static inline void +_cp_bra(struct nouveau_grctx *ctx, u32 mod, int flag, int state, int name) +{ + int ip = 0; + + if (mod != 2) { + ip = ctx->ctxprog_label[name] << CP_BRA_IP_SHIFT; + if (ip == 0) + ip = 0xff000000 | (name << CP_BRA_IP_SHIFT); + } + + cp_out(ctx, CP_BRA | (mod << 18) | ip | flag | + (state ? 0 : CP_BRA_IF_CLEAR)); +} +#define cp_bra(c,f,s,n) _cp_bra((c), 0, CP_FLAG_##f, CP_FLAG_##f##_##s, n) +#ifdef CP_BRA_MOD +#define cp_cal(c,f,s,n) _cp_bra((c), 1, CP_FLAG_##f, CP_FLAG_##f##_##s, n) +#define cp_ret(c,f,s) _cp_bra((c), 2, CP_FLAG_##f, CP_FLAG_##f##_##s, 0) +#endif + +static inline void +_cp_wait(struct nouveau_grctx *ctx, int flag, int state) +{ + cp_out(ctx, CP_WAIT | flag | (state ? CP_WAIT_SET : 0)); +} +#define cp_wait(c,f,s) _cp_wait((c), CP_FLAG_##f, CP_FLAG_##f##_##s) + +static inline void +_cp_set(struct nouveau_grctx *ctx, int flag, int state) +{ + cp_out(ctx, CP_SET | flag | (state ? CP_SET_1 : 0)); +} +#define cp_set(c,f,s) _cp_set((c), CP_FLAG_##f, CP_FLAG_##f##_##s) + +static inline void +cp_pos(struct nouveau_grctx *ctx, int offset) +{ + ctx->ctxvals_pos = offset; + ctx->ctxvals_base = ctx->ctxvals_pos; + + cp_lsr(ctx, ctx->ctxvals_pos); + cp_out(ctx, CP_SET_CONTEXT_POINTER); +} + +static inline void +gr_def(struct nouveau_grctx *ctx, uint32_t reg, uint32_t val) +{ + if (ctx->mode != NOUVEAU_GRCTX_VALS) + return; + + reg = (reg - 0x00400000) / 4; + reg = (reg - ctx->ctxprog_reg) + ctx->ctxvals_base; + + nv_wo32(ctx->dev, ctx->data, reg, val); +} +#endif + +#endif diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 7e8547cb583..2b332bb55ac 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c @@ -24,36 +24,10 @@ * */ -#include - #include "drmP.h" #include "drm.h" #include "nouveau_drv.h" - -MODULE_FIRMWARE("nouveau/nv40.ctxprog"); -MODULE_FIRMWARE("nouveau/nv40.ctxvals"); -MODULE_FIRMWARE("nouveau/nv41.ctxprog"); -MODULE_FIRMWARE("nouveau/nv41.ctxvals"); -MODULE_FIRMWARE("nouveau/nv42.ctxprog"); -MODULE_FIRMWARE("nouveau/nv42.ctxvals"); -MODULE_FIRMWARE("nouveau/nv43.ctxprog"); -MODULE_FIRMWARE("nouveau/nv43.ctxvals"); -MODULE_FIRMWARE("nouveau/nv44.ctxprog"); -MODULE_FIRMWARE("nouveau/nv44.ctxvals"); -MODULE_FIRMWARE("nouveau/nv46.ctxprog"); -MODULE_FIRMWARE("nouveau/nv46.ctxvals"); -MODULE_FIRMWARE("nouveau/nv47.ctxprog"); -MODULE_FIRMWARE("nouveau/nv47.ctxvals"); -MODULE_FIRMWARE("nouveau/nv49.ctxprog"); -MODULE_FIRMWARE("nouveau/nv49.ctxvals"); -MODULE_FIRMWARE("nouveau/nv4a.ctxprog"); -MODULE_FIRMWARE("nouveau/nv4a.ctxvals"); -MODULE_FIRMWARE("nouveau/nv4b.ctxprog"); -MODULE_FIRMWARE("nouveau/nv4b.ctxvals"); -MODULE_FIRMWARE("nouveau/nv4c.ctxprog"); -MODULE_FIRMWARE("nouveau/nv4c.ctxvals"); -MODULE_FIRMWARE("nouveau/nv4e.ctxprog"); -MODULE_FIRMWARE("nouveau/nv4e.ctxvals"); +#include "nouveau_grctx.h" struct nouveau_channel * nv40_graph_channel(struct drm_device *dev) @@ -83,27 +57,30 @@ nv40_graph_create_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpuobj *ctx; + struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; int ret; - /* Allocate a 175KiB block of PRAMIN to store the context. This - * is massive overkill for a lot of chipsets, but it should be safe - * until we're able to implement this properly (will happen at more - * or less the same time we're able to write our own context programs. - */ - ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 175*1024, 16, - NVOBJ_FLAG_ZERO_ALLOC, - &chan->ramin_grctx); + ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size, + 16, NVOBJ_FLAG_ZERO_ALLOC, + &chan->ramin_grctx); if (ret) return ret; - ctx = chan->ramin_grctx->gpuobj; /* Initialise default context values */ dev_priv->engine.instmem.prepare_access(dev, true); - nv40_grctx_vals_load(dev, ctx); - nv_wo32(dev, ctx, 0, ctx->im_pramin->start); - dev_priv->engine.instmem.finish_access(dev); + if (!pgraph->ctxprog) { + struct nouveau_grctx ctx = {}; + ctx.dev = chan->dev; + ctx.mode = NOUVEAU_GRCTX_VALS; + ctx.data = chan->ramin_grctx->gpuobj; + nv40_grctx_init(&ctx); + } else { + nouveau_grctx_vals_load(dev, chan->ramin_grctx->gpuobj); + } + nv_wo32(dev, chan->ramin_grctx->gpuobj, 0, + chan->ramin_grctx->gpuobj->im_pramin->start); + dev_priv->engine.instmem.finish_access(dev); return 0; } @@ -204,139 +181,6 @@ nv40_graph_unload_context(struct drm_device *dev) return ret; } -struct nouveau_ctxprog { - uint32_t signature; - uint8_t version; - uint16_t length; - uint32_t data[]; -} __attribute__ ((packed)); - -struct nouveau_ctxvals { - uint32_t signature; - uint8_t version; - uint32_t length; - struct { - uint32_t offset; - uint32_t value; - } data[]; -} __attribute__ ((packed)); - -int -nv40_grctx_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - const int chipset = dev_priv->chipset; - const struct firmware *fw; - const struct nouveau_ctxprog *cp; - const struct nouveau_ctxvals *cv; - char name[32]; - int ret, i; - - pgraph->accel_blocked = true; - - if (!pgraph->ctxprog) { - sprintf(name, "nouveau/nv%02x.ctxprog", chipset); - ret = request_firmware(&fw, name, &dev->pdev->dev); - if (ret) { - NV_ERROR(dev, "No ctxprog for NV%02x\n", chipset); - return ret; - } - - pgraph->ctxprog = kmalloc(fw->size, GFP_KERNEL); - if (!pgraph->ctxprog) { - NV_ERROR(dev, "OOM copying ctxprog\n"); - release_firmware(fw); - return -ENOMEM; - } - memcpy(pgraph->ctxprog, fw->data, fw->size); - - cp = pgraph->ctxprog; - if (le32_to_cpu(cp->signature) != 0x5043564e || - cp->version != 0 || - le16_to_cpu(cp->length) != ((fw->size - 7) / 4)) { - NV_ERROR(dev, "ctxprog invalid\n"); - release_firmware(fw); - nv40_grctx_fini(dev); - return -EINVAL; - } - release_firmware(fw); - } - - if (!pgraph->ctxvals) { - sprintf(name, "nouveau/nv%02x.ctxvals", chipset); - ret = request_firmware(&fw, name, &dev->pdev->dev); - if (ret) { - NV_ERROR(dev, "No ctxvals for NV%02x\n", chipset); - nv40_grctx_fini(dev); - return ret; - } - - pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL); - if (!pgraph->ctxprog) { - NV_ERROR(dev, "OOM copying ctxprog\n"); - release_firmware(fw); - nv40_grctx_fini(dev); - return -ENOMEM; - } - memcpy(pgraph->ctxvals, fw->data, fw->size); - - cv = (void *)pgraph->ctxvals; - if (le32_to_cpu(cv->signature) != 0x5643564e || - cv->version != 0 || - le32_to_cpu(cv->length) != ((fw->size - 9) / 8)) { - NV_ERROR(dev, "ctxvals invalid\n"); - release_firmware(fw); - nv40_grctx_fini(dev); - return -EINVAL; - } - release_firmware(fw); - } - - cp = pgraph->ctxprog; - - nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); - for (i = 0; i < le16_to_cpu(cp->length); i++) - nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, - le32_to_cpu(cp->data[i])); - - pgraph->accel_blocked = false; - return 0; -} - -void -nv40_grctx_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - - if (pgraph->ctxprog) { - kfree(pgraph->ctxprog); - pgraph->ctxprog = NULL; - } - - if (pgraph->ctxvals) { - kfree(pgraph->ctxprog); - pgraph->ctxvals = NULL; - } -} - -void -nv40_grctx_vals_load(struct drm_device *dev, struct nouveau_gpuobj *ctx) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; - struct nouveau_ctxvals *cv = pgraph->ctxvals; - int i; - - if (!cv) - return; - - for (i = 0; i < le32_to_cpu(cv->length); i++) - nv_wo32(dev, ctx, le32_to_cpu(cv->data[i].offset), - le32_to_cpu(cv->data[i].value)); -} - /* * G70 0x47 * G71 0x49 @@ -359,7 +203,26 @@ nv40_graph_init(struct drm_device *dev) nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) | NV_PMC_ENABLE_PGRAPH); - nv40_grctx_init(dev); + if (nouveau_ctxfw) { + nouveau_grctx_prog_load(dev); + dev_priv->engine.graph.grctx_size = 175 * 1024; + } + + if (!dev_priv->engine.graph.ctxprog) { + struct nouveau_grctx ctx = {}; + uint32_t cp[256]; + + ctx.dev = dev; + ctx.mode = NOUVEAU_GRCTX_PROG; + ctx.data = cp; + ctx.ctxprog_max = 256; + nv40_grctx_init(&ctx); + dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4; + + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); + for (i = 0; i < ctx.ctxprog_len; i++) + nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); + } /* No context present currently */ nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0x00000000); @@ -539,6 +402,7 @@ nv40_graph_init(struct drm_device *dev) void nv40_graph_takedown(struct drm_device *dev) { + nouveau_grctx_fini(dev); } struct nouveau_pgraph_object_class nv40_graph_grclass[] = { diff --git a/drivers/gpu/drm/nouveau/nv40_grctx.c b/drivers/gpu/drm/nouveau/nv40_grctx.c new file mode 100644 index 00000000000..11b11c31f54 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nv40_grctx.c @@ -0,0 +1,678 @@ +/* + * Copyright 2009 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Ben Skeggs + */ + +/* NVIDIA context programs handle a number of other conditions which are + * not implemented in our versions. It's not clear why NVIDIA context + * programs have this code, nor whether it's strictly necessary for + * correct operation. We'll implement additional handling if/when we + * discover it's necessary. + * + * - On context save, NVIDIA set 0x400314 bit 0 to 1 if the "3D state" + * flag is set, this gets saved into the context. + * - On context save, the context program for all cards load nsource + * into a flag register and check for ILLEGAL_MTHD. If it's set, + * opcode 0x60000d is called before resuming normal operation. + * - Some context programs check more conditions than the above. NV44 + * checks: ((nsource & 0x0857) || (0x400718 & 0x0100) || (intr & 0x0001)) + * and calls 0x60000d before resuming normal operation. + * - At the very beginning of NVIDIA's context programs, flag 9 is checked + * and if true 0x800001 is called with count=0, pos=0, the flag is cleared + * and then the ctxprog is aborted. It looks like a complicated NOP, + * its purpose is unknown. + * - In the section of code that loads the per-vs state, NVIDIA check + * flag 10. If it's set, they only transfer the small 0x300 byte block + * of state + the state for a single vs as opposed to the state for + * all vs units. It doesn't seem likely that it'll occur in normal + * operation, especially seeing as it appears NVIDIA may have screwed + * up the ctxprogs for some cards and have an invalid instruction + * rather than a cp_lsr(ctx, dwords_for_1_vs_unit) instruction. + * - There's a number of places where context offset 0 (where we place + * the PRAMIN offset of the context) is loaded into either 0x408000, + * 0x408004 or 0x408008. Not sure what's up there either. + * - The ctxprogs for some cards save 0x400a00 again during the cleanup + * path for auto-loadctx. + */ + +#define CP_FLAG_CLEAR 0 +#define CP_FLAG_SET 1 +#define CP_FLAG_SWAP_DIRECTION ((0 * 32) + 0) +#define CP_FLAG_SWAP_DIRECTION_LOAD 0 +#define CP_FLAG_SWAP_DIRECTION_SAVE 1 +#define CP_FLAG_USER_SAVE ((0 * 32) + 5) +#define CP_FLAG_USER_SAVE_NOT_PENDING 0 +#define CP_FLAG_USER_SAVE_PENDING 1 +#define CP_FLAG_USER_LOAD ((0 * 32) + 6) +#define CP_FLAG_USER_LOAD_NOT_PENDING 0 +#define CP_FLAG_USER_LOAD_PENDING 1 +#define CP_FLAG_STATUS ((3 * 32) + 0) +#define CP_FLAG_STATUS_IDLE 0 +#define CP_FLAG_STATUS_BUSY 1 +#define CP_FLAG_AUTO_SAVE ((3 * 32) + 4) +#define CP_FLAG_AUTO_SAVE_NOT_PENDING 0 +#define CP_FLAG_AUTO_SAVE_PENDING 1 +#define CP_FLAG_AUTO_LOAD ((3 * 32) + 5) +#define CP_FLAG_AUTO_LOAD_NOT_PENDING 0 +#define CP_FLAG_AUTO_LOAD_PENDING 1 +#define CP_FLAG_UNK54 ((3 * 32) + 6) +#define CP_FLAG_UNK54_CLEAR 0 +#define CP_FLAG_UNK54_SET 1 +#define CP_FLAG_ALWAYS ((3 * 32) + 8) +#define CP_FLAG_ALWAYS_FALSE 0 +#define CP_FLAG_ALWAYS_TRUE 1 +#define CP_FLAG_UNK57 ((3 * 32) + 9) +#define CP_FLAG_UNK57_CLEAR 0 +#define CP_FLAG_UNK57_SET 1 + +#define CP_CTX 0x00100000 +#define CP_CTX_COUNT 0x000fc000 +#define CP_CTX_COUNT_SHIFT 14 +#define CP_CTX_REG 0x00003fff +#define CP_LOAD_SR 0x00200000 +#define CP_LOAD_SR_VALUE 0x000fffff +#define CP_BRA 0x00400000 +#define CP_BRA_IP 0x0000ff00 +#define CP_BRA_IP_SHIFT 8 +#define CP_BRA_IF_CLEAR 0x00000080 +#define CP_BRA_FLAG 0x0000007f +#define CP_WAIT 0x00500000 +#define CP_WAIT_SET 0x00000080 +#define CP_WAIT_FLAG 0x0000007f +#define CP_SET 0x00700000 +#define CP_SET_1 0x00000080 +#define CP_SET_FLAG 0x0000007f +#define CP_NEXT_TO_SWAP 0x00600007 +#define CP_NEXT_TO_CURRENT 0x00600009 +#define CP_SET_CONTEXT_POINTER 0x0060000a +#define CP_END 0x0060000e +#define CP_LOAD_MAGIC_UNK01 0x00800001 /* unknown */ +#define CP_LOAD_MAGIC_NV44TCL 0x00800029 /* per-vs state (0x4497) */ +#define CP_LOAD_MAGIC_NV40TCL 0x00800041 /* per-vs state (0x4097) */ + +#include "drmP.h" +#include "nouveau_drv.h" +#include "nouveau_grctx.h" + +/* TODO: + * - get vs count from 0x1540 + * - document unimplemented bits compared to nvidia + * - nsource handling + * - R0 & 0x0200 handling + * - single-vs handling + * - 400314 bit 0 + */ + +static int +nv40_graph_4097(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + if ((dev_priv->chipset & 0xf0) == 0x60) + return 0; + + return !!(0x0baf & (1 << dev_priv->chipset)); +} + +static int +nv40_graph_vs_count(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + return 8; + case 0x40: + return 6; + case 0x41: + case 0x42: + return 5; + case 0x43: + case 0x44: + case 0x46: + case 0x4a: + return 3; + case 0x4c: + case 0x4e: + case 0x67: + default: + return 1; + } +} + + +enum cp_label { + cp_check_load = 1, + cp_setup_auto_load, + cp_setup_load, + cp_setup_save, + cp_swap_state, + cp_swap_state3d_3_is_save, + cp_prepare_exit, + cp_exit, +}; + +static void +nv40_graph_construct_general(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + + cp_ctx(ctx, 0x4000a4, 1); + gr_def(ctx, 0x4000a4, 0x00000008); + cp_ctx(ctx, 0x400144, 58); + gr_def(ctx, 0x400144, 0x00000001); + cp_ctx(ctx, 0x400314, 1); + gr_def(ctx, 0x400314, 0x00000000); + cp_ctx(ctx, 0x400400, 10); + cp_ctx(ctx, 0x400480, 10); + cp_ctx(ctx, 0x400500, 19); + gr_def(ctx, 0x400514, 0x00040000); + gr_def(ctx, 0x400524, 0x55555555); + gr_def(ctx, 0x400528, 0x55555555); + gr_def(ctx, 0x40052c, 0x55555555); + gr_def(ctx, 0x400530, 0x55555555); + cp_ctx(ctx, 0x400560, 6); + gr_def(ctx, 0x400568, 0x0000ffff); + gr_def(ctx, 0x40056c, 0x0000ffff); + cp_ctx(ctx, 0x40057c, 5); + cp_ctx(ctx, 0x400710, 3); + gr_def(ctx, 0x400710, 0x20010001); + gr_def(ctx, 0x400714, 0x0f73ef00); + cp_ctx(ctx, 0x400724, 1); + gr_def(ctx, 0x400724, 0x02008821); + cp_ctx(ctx, 0x400770, 3); + if (dev_priv->chipset == 0x40) { + cp_ctx(ctx, 0x400814, 4); + cp_ctx(ctx, 0x400828, 5); + cp_ctx(ctx, 0x400840, 5); + gr_def(ctx, 0x400850, 0x00000040); + cp_ctx(ctx, 0x400858, 4); + gr_def(ctx, 0x400858, 0x00000040); + gr_def(ctx, 0x40085c, 0x00000040); + gr_def(ctx, 0x400864, 0x80000000); + cp_ctx(ctx, 0x40086c, 9); + gr_def(ctx, 0x40086c, 0x80000000); + gr_def(ctx, 0x400870, 0x80000000); + gr_def(ctx, 0x400874, 0x80000000); + gr_def(ctx, 0x400878, 0x80000000); + gr_def(ctx, 0x400888, 0x00000040); + gr_def(ctx, 0x40088c, 0x80000000); + cp_ctx(ctx, 0x4009c0, 8); + gr_def(ctx, 0x4009cc, 0x80000000); + gr_def(ctx, 0x4009dc, 0x80000000); + } else { + cp_ctx(ctx, 0x400840, 20); + if (!nv40_graph_4097(ctx->dev)) { + for (i = 0; i < 8; i++) + gr_def(ctx, 0x400860 + (i * 4), 0x00000001); + } + gr_def(ctx, 0x400880, 0x00000040); + gr_def(ctx, 0x400884, 0x00000040); + gr_def(ctx, 0x400888, 0x00000040); + cp_ctx(ctx, 0x400894, 11); + gr_def(ctx, 0x400894, 0x00000040); + if (nv40_graph_4097(ctx->dev)) { + for (i = 0; i < 8; i++) + gr_def(ctx, 0x4008a0 + (i * 4), 0x80000000); + } + cp_ctx(ctx, 0x4008e0, 2); + cp_ctx(ctx, 0x4008f8, 2); + if (dev_priv->chipset == 0x4c || + (dev_priv->chipset & 0xf0) == 0x60) + cp_ctx(ctx, 0x4009f8, 1); + } + cp_ctx(ctx, 0x400a00, 73); + gr_def(ctx, 0x400b0c, 0x0b0b0b0c); + cp_ctx(ctx, 0x401000, 4); + cp_ctx(ctx, 0x405004, 1); + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x403448, 1); + gr_def(ctx, 0x403448, 0x00001010); + break; + default: + cp_ctx(ctx, 0x403440, 1); + switch (dev_priv->chipset) { + case 0x40: + gr_def(ctx, 0x403440, 0x00000010); + break; + case 0x44: + case 0x46: + case 0x4a: + gr_def(ctx, 0x403440, 0x00003010); + break; + case 0x41: + case 0x42: + case 0x43: + case 0x4c: + case 0x4e: + case 0x67: + default: + gr_def(ctx, 0x403440, 0x00001010); + break; + } + break; + } +} + +static void +nv40_graph_construct_state3d(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + + if (dev_priv->chipset == 0x40) { + cp_ctx(ctx, 0x401880, 51); + gr_def(ctx, 0x401940, 0x00000100); + } else + if (dev_priv->chipset == 0x46 || dev_priv->chipset == 0x47 || + dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) { + cp_ctx(ctx, 0x401880, 32); + for (i = 0; i < 16; i++) + gr_def(ctx, 0x401880 + (i * 4), 0x00000111); + if (dev_priv->chipset == 0x46) + cp_ctx(ctx, 0x401900, 16); + cp_ctx(ctx, 0x401940, 3); + } + cp_ctx(ctx, 0x40194c, 18); + gr_def(ctx, 0x401954, 0x00000111); + gr_def(ctx, 0x401958, 0x00080060); + gr_def(ctx, 0x401974, 0x00000080); + gr_def(ctx, 0x401978, 0xffff0000); + gr_def(ctx, 0x40197c, 0x00000001); + gr_def(ctx, 0x401990, 0x46400000); + if (dev_priv->chipset == 0x40) { + cp_ctx(ctx, 0x4019a0, 2); + cp_ctx(ctx, 0x4019ac, 5); + } else { + cp_ctx(ctx, 0x4019a0, 1); + cp_ctx(ctx, 0x4019b4, 3); + } + gr_def(ctx, 0x4019bc, 0xffff0000); + switch (dev_priv->chipset) { + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x4019c0, 18); + for (i = 0; i < 16; i++) + gr_def(ctx, 0x4019c0 + (i * 4), 0x88888888); + break; + } + cp_ctx(ctx, 0x401a08, 8); + gr_def(ctx, 0x401a10, 0x0fff0000); + gr_def(ctx, 0x401a14, 0x0fff0000); + gr_def(ctx, 0x401a1c, 0x00011100); + cp_ctx(ctx, 0x401a2c, 4); + cp_ctx(ctx, 0x401a44, 26); + for (i = 0; i < 16; i++) + gr_def(ctx, 0x401a44 + (i * 4), 0x07ff0000); + gr_def(ctx, 0x401a8c, 0x4b7fffff); + if (dev_priv->chipset == 0x40) { + cp_ctx(ctx, 0x401ab8, 3); + } else { + cp_ctx(ctx, 0x401ab8, 1); + cp_ctx(ctx, 0x401ac0, 1); + } + cp_ctx(ctx, 0x401ad0, 8); + gr_def(ctx, 0x401ad0, 0x30201000); + gr_def(ctx, 0x401ad4, 0x70605040); + gr_def(ctx, 0x401ad8, 0xb8a89888); + gr_def(ctx, 0x401adc, 0xf8e8d8c8); + cp_ctx(ctx, 0x401b10, dev_priv->chipset == 0x40 ? 2 : 1); + gr_def(ctx, 0x401b10, 0x40100000); + cp_ctx(ctx, 0x401b18, dev_priv->chipset == 0x40 ? 6 : 5); + gr_def(ctx, 0x401b28, dev_priv->chipset == 0x40 ? + 0x00000004 : 0x00000000); + cp_ctx(ctx, 0x401b30, 25); + gr_def(ctx, 0x401b34, 0x0000ffff); + gr_def(ctx, 0x401b68, 0x435185d6); + gr_def(ctx, 0x401b6c, 0x2155b699); + gr_def(ctx, 0x401b70, 0xfedcba98); + gr_def(ctx, 0x401b74, 0x00000098); + gr_def(ctx, 0x401b84, 0xffffffff); + gr_def(ctx, 0x401b88, 0x00ff7000); + gr_def(ctx, 0x401b8c, 0x0000ffff); + if (dev_priv->chipset != 0x44 && dev_priv->chipset != 0x4a && + dev_priv->chipset != 0x4e) + cp_ctx(ctx, 0x401b94, 1); + cp_ctx(ctx, 0x401b98, 8); + gr_def(ctx, 0x401b9c, 0x00ff0000); + cp_ctx(ctx, 0x401bc0, 9); + gr_def(ctx, 0x401be0, 0x00ffff00); + cp_ctx(ctx, 0x401c00, 192); + for (i = 0; i < 16; i++) { /* fragment texture units */ + gr_def(ctx, 0x401c40 + (i * 4), 0x00018488); + gr_def(ctx, 0x401c80 + (i * 4), 0x00028202); + gr_def(ctx, 0x401d00 + (i * 4), 0x0000aae4); + gr_def(ctx, 0x401d40 + (i * 4), 0x01012000); + gr_def(ctx, 0x401d80 + (i * 4), 0x00080008); + gr_def(ctx, 0x401e00 + (i * 4), 0x00100008); + } + for (i = 0; i < 4; i++) { /* vertex texture units */ + gr_def(ctx, 0x401e90 + (i * 4), 0x0001bc80); + gr_def(ctx, 0x401ea0 + (i * 4), 0x00000202); + gr_def(ctx, 0x401ec0 + (i * 4), 0x00000008); + gr_def(ctx, 0x401ee0 + (i * 4), 0x00080008); + } + cp_ctx(ctx, 0x400f5c, 3); + gr_def(ctx, 0x400f5c, 0x00000002); + cp_ctx(ctx, 0x400f84, 1); +} + +static void +nv40_graph_construct_state3d_2(struct nouveau_grctx *ctx) +{ + struct drm_nouveau_private *dev_priv = ctx->dev->dev_private; + int i; + + cp_ctx(ctx, 0x402000, 1); + cp_ctx(ctx, 0x402404, dev_priv->chipset == 0x40 ? 1 : 2); + switch (dev_priv->chipset) { + case 0x40: + gr_def(ctx, 0x402404, 0x00000001); + break; + case 0x4c: + case 0x4e: + case 0x67: + gr_def(ctx, 0x402404, 0x00000020); + break; + case 0x46: + case 0x49: + case 0x4b: + gr_def(ctx, 0x402404, 0x00000421); + break; + default: + gr_def(ctx, 0x402404, 0x00000021); + } + if (dev_priv->chipset != 0x40) + gr_def(ctx, 0x402408, 0x030c30c3); + switch (dev_priv->chipset) { + case 0x44: + case 0x46: + case 0x4a: + case 0x4c: + case 0x4e: + case 0x67: + cp_ctx(ctx, 0x402440, 1); + gr_def(ctx, 0x402440, 0x00011001); + break; + default: + break; + } + cp_ctx(ctx, 0x402480, dev_priv->chipset == 0x40 ? 8 : 9); + gr_def(ctx, 0x402488, 0x3e020200); + gr_def(ctx, 0x40248c, 0x00ffffff); + switch (dev_priv->chipset) { + case 0x40: + gr_def(ctx, 0x402490, 0x60103f00); + break; + case 0x47: + gr_def(ctx, 0x402490, 0x40103f00); + break; + case 0x41: + case 0x42: + case 0x49: + case 0x4b: + gr_def(ctx, 0x402490, 0x20103f00); + break; + default: + gr_def(ctx, 0x402490, 0x0c103f00); + break; + } + gr_def(ctx, 0x40249c, dev_priv->chipset <= 0x43 ? + 0x00020000 : 0x00040000); + cp_ctx(ctx, 0x402500, 31); + gr_def(ctx, 0x402530, 0x00008100); + if (dev_priv->chipset == 0x40) + cp_ctx(ctx, 0x40257c, 6); + cp_ctx(ctx, 0x402594, 16); + cp_ctx(ctx, 0x402800, 17); + gr_def(ctx, 0x402800, 0x00000001); + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x402864, 1); + gr_def(ctx, 0x402864, 0x00001001); + cp_ctx(ctx, 0x402870, 3); + gr_def(ctx, 0x402878, 0x00000003); + if (dev_priv->chipset != 0x47) { /* belong at end!! */ + cp_ctx(ctx, 0x402900, 1); + cp_ctx(ctx, 0x402940, 1); + cp_ctx(ctx, 0x402980, 1); + cp_ctx(ctx, 0x4029c0, 1); + cp_ctx(ctx, 0x402a00, 1); + cp_ctx(ctx, 0x402a40, 1); + cp_ctx(ctx, 0x402a80, 1); + cp_ctx(ctx, 0x402ac0, 1); + } + break; + case 0x40: + cp_ctx(ctx, 0x402844, 1); + gr_def(ctx, 0x402844, 0x00000001); + cp_ctx(ctx, 0x402850, 1); + break; + default: + cp_ctx(ctx, 0x402844, 1); + gr_def(ctx, 0x402844, 0x00001001); + cp_ctx(ctx, 0x402850, 2); + gr_def(ctx, 0x402854, 0x00000003); + break; + } + + cp_ctx(ctx, 0x402c00, 4); + gr_def(ctx, 0x402c00, dev_priv->chipset == 0x40 ? + 0x80800001 : 0x00888001); + switch (dev_priv->chipset) { + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x402c20, 40); + for (i = 0; i < 32; i++) + gr_def(ctx, 0x402c40 + (i * 4), 0xffffffff); + cp_ctx(ctx, 0x4030b8, 13); + gr_def(ctx, 0x4030dc, 0x00000005); + gr_def(ctx, 0x4030e8, 0x0000ffff); + break; + default: + cp_ctx(ctx, 0x402c10, 4); + if (dev_priv->chipset == 0x40) + cp_ctx(ctx, 0x402c20, 36); + else + if (dev_priv->chipset <= 0x42) + cp_ctx(ctx, 0x402c20, 24); + else + if (dev_priv->chipset <= 0x4a) + cp_ctx(ctx, 0x402c20, 16); + else + cp_ctx(ctx, 0x402c20, 8); + cp_ctx(ctx, 0x402cb0, dev_priv->chipset == 0x40 ? 12 : 13); + gr_def(ctx, 0x402cd4, 0x00000005); + if (dev_priv->chipset != 0x40) + gr_def(ctx, 0x402ce0, 0x0000ffff); + break; + } + + cp_ctx(ctx, 0x403400, dev_priv->chipset == 0x40 ? 4 : 3); + cp_ctx(ctx, 0x403410, dev_priv->chipset == 0x40 ? 4 : 3); + cp_ctx(ctx, 0x403420, nv40_graph_vs_count(ctx->dev)); + for (i = 0; i < nv40_graph_vs_count(ctx->dev); i++) + gr_def(ctx, 0x403420 + (i * 4), 0x00005555); + + if (dev_priv->chipset != 0x40) { + cp_ctx(ctx, 0x403600, 1); + gr_def(ctx, 0x403600, 0x00000001); + } + cp_ctx(ctx, 0x403800, 1); + + cp_ctx(ctx, 0x403c18, 1); + gr_def(ctx, 0x403c18, 0x00000001); + switch (dev_priv->chipset) { + case 0x46: + case 0x47: + case 0x49: + case 0x4b: + cp_ctx(ctx, 0x405018, 1); + gr_def(ctx, 0x405018, 0x08e00001); + cp_ctx(ctx, 0x405c24, 1); + gr_def(ctx, 0x405c24, 0x000e3000); + break; + } + if (dev_priv->chipset != 0x4e) + cp_ctx(ctx, 0x405800, 11); + cp_ctx(ctx, 0x407000, 1); +} + +static void +nv40_graph_construct_state3d_3(struct nouveau_grctx *ctx) +{ + int len = nv40_graph_4097(ctx->dev) ? 0x0684 : 0x0084; + + cp_out (ctx, 0x300000); + cp_lsr (ctx, len - 4); + cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_swap_state3d_3_is_save); + cp_lsr (ctx, len); + cp_name(ctx, cp_swap_state3d_3_is_save); + cp_out (ctx, 0x800001); + + ctx->ctxvals_pos += len; +} + +static void +nv40_graph_construct_shader(struct nouveau_grctx *ctx) +{ + struct drm_device *dev = ctx->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *obj = ctx->data; + int vs, vs_nr, vs_len, vs_nr_b0, vs_nr_b1, b0_offset, b1_offset; + int offset, i; + + vs_nr = nv40_graph_vs_count(ctx->dev); + vs_nr_b0 = 363; + vs_nr_b1 = dev_priv->chipset == 0x40 ? 128 : 64; + if (dev_priv->chipset == 0x40) { + b0_offset = 0x2200/4; /* 33a0 */ + b1_offset = 0x55a0/4; /* 1500 */ + vs_len = 0x6aa0/4; + } else + if (dev_priv->chipset == 0x41 || dev_priv->chipset == 0x42) { + b0_offset = 0x2200/4; /* 2200 */ + b1_offset = 0x4400/4; /* 0b00 */ + vs_len = 0x4f00/4; + } else { + b0_offset = 0x1d40/4; /* 2200 */ + b1_offset = 0x3f40/4; /* 0b00 : 0a40 */ + vs_len = nv40_graph_4097(dev) ? 0x4a40/4 : 0x4980/4; + } + + cp_lsr(ctx, vs_len * vs_nr + 0x300/4); + cp_out(ctx, nv40_graph_4097(dev) ? 0x800041 : 0x800029); + + offset = ctx->ctxvals_pos; + ctx->ctxvals_pos += (0x0300/4 + (vs_nr * vs_len)); + + if (ctx->mode != NOUVEAU_GRCTX_VALS) + return; + + offset += 0x0280/4; + for (i = 0; i < 16; i++, offset += 2) + nv_wo32(dev, obj, offset, 0x3f800000); + + for (vs = 0; vs < vs_nr; vs++, offset += vs_len) { + for (i = 0; i < vs_nr_b0 * 6; i += 6) + nv_wo32(dev, obj, offset + b0_offset + i, 0x00000001); + for (i = 0; i < vs_nr_b1 * 4; i += 4) + nv_wo32(dev, obj, offset + b1_offset + i, 0x3f800000); + } +} + +void +nv40_grctx_init(struct nouveau_grctx *ctx) +{ + /* decide whether we're loading/unloading the context */ + cp_bra (ctx, AUTO_SAVE, PENDING, cp_setup_save); + cp_bra (ctx, USER_SAVE, PENDING, cp_setup_save); + + cp_name(ctx, cp_check_load); + cp_bra (ctx, AUTO_LOAD, PENDING, cp_setup_auto_load); + cp_bra (ctx, USER_LOAD, PENDING, cp_setup_load); + cp_bra (ctx, ALWAYS, TRUE, cp_exit); + + /* setup for context load */ + cp_name(ctx, cp_setup_auto_load); + cp_wait(ctx, STATUS, IDLE); + cp_out (ctx, CP_NEXT_TO_SWAP); + cp_name(ctx, cp_setup_load); + cp_wait(ctx, STATUS, IDLE); + cp_set (ctx, SWAP_DIRECTION, LOAD); + cp_out (ctx, 0x00910880); /* ?? */ + cp_out (ctx, 0x00901ffe); /* ?? */ + cp_out (ctx, 0x01940000); /* ?? */ + cp_lsr (ctx, 0x20); + cp_out (ctx, 0x0060000b); /* ?? */ + cp_wait(ctx, UNK57, CLEAR); + cp_out (ctx, 0x0060000c); /* ?? */ + cp_bra (ctx, ALWAYS, TRUE, cp_swap_state); + + /* setup for context save */ + cp_name(ctx, cp_setup_save); + cp_set (ctx, SWAP_DIRECTION, SAVE); + + /* general PGRAPH state */ + cp_name(ctx, cp_swap_state); + cp_pos (ctx, 0x00020/4); + nv40_graph_construct_general(ctx); + cp_wait(ctx, STATUS, IDLE); + + /* 3D state, block 1 */ + cp_bra (ctx, UNK54, CLEAR, cp_prepare_exit); + nv40_graph_construct_state3d(ctx); + cp_wait(ctx, STATUS, IDLE); + + /* 3D state, block 2 */ + nv40_graph_construct_state3d_2(ctx); + + /* Some other block of "random" state */ + nv40_graph_construct_state3d_3(ctx); + + /* Per-vertex shader state */ + cp_pos (ctx, ctx->ctxvals_pos); + nv40_graph_construct_shader(ctx); + + /* pre-exit state updates */ + cp_name(ctx, cp_prepare_exit); + cp_bra (ctx, SWAP_DIRECTION, SAVE, cp_check_load); + cp_bra (ctx, USER_SAVE, PENDING, cp_exit); + cp_out (ctx, CP_NEXT_TO_CURRENT); + + cp_name(ctx, cp_exit); + cp_set (ctx, USER_SAVE, NOT_PENDING); + cp_set (ctx, USER_LOAD, NOT_PENDING); + cp_out (ctx, CP_END); +} + diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index 177d8229336..ca79f32be44 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c @@ -107,9 +107,13 @@ nv50_graph_init_regs(struct drm_device *dev) static int nv50_graph_init_ctxctl(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + NV_DEBUG(dev, "\n"); - nv40_grctx_init(dev); + nouveau_grctx_prog_load(dev); + if (!dev_priv->engine.graph.ctxprog) + dev_priv->engine.graph.accel_blocked = true; nv_wr32(dev, 0x400320, 4); nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0); @@ -140,7 +144,7 @@ void nv50_graph_takedown(struct drm_device *dev) { NV_DEBUG(dev, "\n"); - nv40_grctx_fini(dev); + nouveau_grctx_fini(dev); } void @@ -207,7 +211,7 @@ nv50_graph_create_context(struct nouveau_channel *chan) dev_priv->engine.instmem.finish_access(dev); dev_priv->engine.instmem.prepare_access(dev, true); - nv40_grctx_vals_load(dev, ctx); + nouveau_grctx_vals_load(dev, ctx); nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12); if ((dev_priv->chipset & 0xf0) == 0xa0) nv_wo32(dev, ctx, 0x00004/4, 0x00000000); -- cgit v1.2.3-70-g09d2 From 3c8868d3dbba5110bd43b49879f12d1a6b2a28ca Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 16 Dec 2009 14:51:13 +1000 Subject: drm/nv50: fix two potential suspend/resume oopses This avoids touching the dummy channel 0/127 we have on nv50. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_drv.c | 2 +- drivers/gpu/drm/nouveau/nv50_fifo.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 78662cc1c8d..58c717247f2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -277,7 +277,7 @@ nouveau_pci_resume(struct pci_dev *pdev) for (i = 0; i < dev_priv->engine.fifo.channels; i++) { chan = dev_priv->fifos[i]; - if (!chan) + if (!chan || !chan->pushbuf_bo) continue; for (j = 0; j < NOUVEAU_DMA_SKIPS; j++) diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index 77ae1aaa0bc..b7282284f08 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -416,7 +416,7 @@ nv50_fifo_unload_context(struct drm_device *dev) NV_DEBUG(dev, "\n"); chid = pfifo->channel_id(dev); - if (chid < 0 || chid >= dev_priv->engine.fifo.channels) + if (chid < 1 || chid >= dev_priv->engine.fifo.channels - 1) return 0; chan = dev_priv->fifos[chid]; -- cgit v1.2.3-70-g09d2 From 0735f62e116fae1e4f36237a97de28e8a56b4c2c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 16 Dec 2009 14:28:55 +1000 Subject: drm/nouveau: prevent all channel creation if accel not available Previously, if there was no firmware available, the DRM would just disable channel creation from userspace, but still use a single channel for its own purposes. With a bit of care it should actually be possible to do this, due to the DRM's very limited use of the engine. It currently doesn't work correctly however, resulting in corrupted fbcon and hangs on a number of cards. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 8 ++-- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 20 ++++---- drivers/gpu/drm/nouveau/nouveau_state.c | 84 ++++++++++++++++++++------------- 3 files changed, 64 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e9f01906c52..2f5d4702110 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -461,11 +461,8 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, int no_wait, int ret; chan = nvbo->channel; - if (!chan || nvbo->tile_flags || nvbo->no_vm) { + if (!chan || nvbo->tile_flags || nvbo->no_vm) chan = dev_priv->channel; - if (!chan) - return -EINVAL; - } src_offset = old_mem->mm_node->start << PAGE_SHIFT; dst_offset = new_mem->mm_node->start << PAGE_SHIFT; @@ -631,7 +628,8 @@ nouveau_bo_move(struct ttm_buffer_object *bo, bool evict, bool intr, return ret; } - if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE) + if (dev_priv->init_state != NOUVEAU_CARD_INIT_DONE || + !dev_priv->channel) return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) { diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 489d4926811..84af25c238b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -58,7 +58,7 @@ nouveau_fbcon_sync(struct fb_info *info) struct nouveau_channel *chan = dev_priv->channel; int ret, i; - if (!chan->accel_done || + if (!chan || !chan->accel_done || info->state != FBINFO_STATE_RUNNING || info->flags & FBINFO_HWACCEL_DISABLED) return 0; @@ -318,14 +318,16 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, par->nouveau_fb = nouveau_fb; par->dev = dev; - switch (dev_priv->card_type) { - case NV_50: - nv50_fbcon_accel_init(info); - break; - default: - nv04_fbcon_accel_init(info); - break; - }; + if (dev_priv->channel) { + switch (dev_priv->card_type) { + case NV_50: + nv50_fbcon_accel_init(info); + break; + default: + nv04_fbcon_accel_init(info); + break; + }; + } nouveau_fbcon_zfill(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 9fc582432da..e76ec2d207a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -299,12 +299,57 @@ nouveau_vga_set_decode(void *priv, bool state) return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; } +static int +nouveau_card_init_channel(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpuobj *gpuobj; + int ret; + + ret = nouveau_channel_alloc(dev, &dev_priv->channel, + (struct drm_file *)-2, + NvDmaFB, NvDmaTT); + if (ret) + return ret; + + gpuobj = NULL; + ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, + 0, nouveau_mem_fb_amount(dev), + NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, + &gpuobj); + if (ret) + goto out_err; + + ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, + gpuobj, NULL); + if (ret) + goto out_err; + + gpuobj = NULL; + ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, + dev_priv->gart_info.aper_size, + NV_DMA_ACCESS_RW, &gpuobj, NULL); + if (ret) + goto out_err; + + ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, + gpuobj, NULL); + if (ret) + goto out_err; + + return 0; +out_err: + nouveau_gpuobj_del(dev, &gpuobj); + nouveau_channel_free(dev_priv->channel); + dev_priv->channel = NULL; + return ret; +} + int nouveau_card_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine; - struct nouveau_gpuobj *gpuobj; int ret; NV_DEBUG(dev, "prev state = %d\n", dev_priv->init_state); @@ -387,39 +432,10 @@ nouveau_card_init(struct drm_device *dev) /* what about PVIDEO/PCRTC/PRAMDAC etc? */ - ret = nouveau_channel_alloc(dev, &dev_priv->channel, - (struct drm_file *)-2, - NvDmaFB, NvDmaTT); - if (ret) - goto out_irq; - - gpuobj = NULL; - ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY, - 0, nouveau_mem_fb_amount(dev), - NV_DMA_ACCESS_RW, NV_DMA_TARGET_VIDMEM, - &gpuobj); - if (ret) - goto out_irq; - - ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaVRAM, - gpuobj, NULL); - if (ret) { - nouveau_gpuobj_del(dev, &gpuobj); - goto out_irq; - } - - gpuobj = NULL; - ret = nouveau_gpuobj_gart_dma_new(dev_priv->channel, 0, - dev_priv->gart_info.aper_size, - NV_DMA_ACCESS_RW, &gpuobj, NULL); - if (ret) - goto out_irq; - - ret = nouveau_gpuobj_ref_add(dev, dev_priv->channel, NvDmaGART, - gpuobj, NULL); - if (ret) { - nouveau_gpuobj_del(dev, &gpuobj); - goto out_irq; + if (!engine->graph.accel_blocked) { + ret = nouveau_card_init_channel(dev); + if (ret) + goto out_irq; } if (drm_core_check_feature(dev, DRIVER_MODESET)) { -- cgit v1.2.3-70-g09d2 From 65ec01a9406327f22b1c740f8a42cb93eb676eb5 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 16 Dec 2009 15:07:45 +1000 Subject: drm/nv50: fix suspend/resume delays without firmware present Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_grctx.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_grctx.c b/drivers/gpu/drm/nouveau/nouveau_grctx.c index d5d84c87f75..419f4c2b3b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_grctx.c +++ b/drivers/gpu/drm/nouveau/nouveau_grctx.c @@ -56,6 +56,9 @@ nouveau_grctx_prog_load(struct drm_device *dev) char name[32]; int ret, i; + if (pgraph->accel_blocked) + return -ENODEV; + if (!pgraph->ctxprog) { sprintf(name, "nouveau/nv%02x.ctxprog", chipset); ret = request_firmware(&fw, name, &dev->pdev->dev); -- cgit v1.2.3-70-g09d2 From 37cb3e08852be92d94e6a65c489bd8afa2e8a15f Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 16 Dec 2009 16:22:42 +1000 Subject: drm/nouveau: fix bug causing pinned buffers to lose their NO_EVICT flag Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 2f5d4702110..0cad6d834eb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -154,6 +154,11 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t memtype) nvbo->placement.busy_placement = nvbo->placements; nvbo->placement.num_placement = n; nvbo->placement.num_busy_placement = n; + + if (nvbo->pin_refcnt) { + while (n--) + nvbo->placements[n] |= TTM_PL_FLAG_NO_EVICT; + } } int -- cgit v1.2.3-70-g09d2 From 0ad3dc3af8ba028368263b190a7a270f8d5cf5ae Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 00:36:09 -0800 Subject: tc1100-wmi - switch to using attribute group Sysfs attribute group takes care of proper creation of a set of attributes and implements proper error unwinding so the driver does not have to do it. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/tc1100-wmi.c | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index 44166003d4e..0d53d516657 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -183,30 +183,15 @@ static DEVICE_ATTR(value, S_IWUGO | S_IRUGO | S_IWUSR, \ show_set_bool(wireless, TC1100_INSTANCE_WIRELESS); show_set_bool(jogdial, TC1100_INSTANCE_JOGDIAL); -static void remove_fs(void) -{ - device_remove_file(&tc1100_device->dev, &dev_attr_wireless); - device_remove_file(&tc1100_device->dev, &dev_attr_jogdial); -} - -static int add_fs(void) -{ - int ret; - - ret = device_create_file(&tc1100_device->dev, &dev_attr_wireless); - if (ret) - goto add_sysfs_error; - - ret = device_create_file(&tc1100_device->dev, &dev_attr_jogdial); - if (ret) - goto add_sysfs_error; - - return ret; +static struct attribute *tc1100_attributes[] = { + &dev_attr_wireless.attr, + &dev_attr_jogdial.attr, + NULL +}; -add_sysfs_error: - remove_fs(); - return ret; -} +static struct attribute_group tc1100_attribute_group = { + .attrs = tc1100_attributes, +}; /* -------------------------------------------------------------------------- Driver Model @@ -214,16 +199,14 @@ add_sysfs_error: static int tc1100_probe(struct platform_device *device) { - int result = 0; - - result = add_fs(); - return result; + return sysfs_create_group(&device->dev.kobj, &tc1100_attribute_group); } static int tc1100_remove(struct platform_device *device) { - remove_fs(); + sysfs_remove_group(&device->dev.kobj, &tc1100_attribute_group); + return 0; } -- cgit v1.2.3-70-g09d2 From 9634a627b330fcc7cdca25df4d7853ca9c7745de Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 00:36:15 -0800 Subject: tc1100-wmi - add error handling for device registration Any of the platform API functions can fail; driver should be prepared to handle such failures. Also: - changed to platform_driver_probe() since the device is created right there with the driver; - added __devexit annotation to remove method; - fixed memory leak on module unload - named platform_device_del() is not enough to free platform device, need platform_device_unregister(). Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/tc1100-wmi.c | 58 ++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index 0d53d516657..fa2995bfa1d 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -47,22 +47,6 @@ MODULE_DESCRIPTION("HP Compaq TC1100 Tablet WMI Extras"); MODULE_LICENSE("GPL"); MODULE_ALIAS("wmi:C364AC71-36DB-495A-8494-B439D472A505"); -static int tc1100_probe(struct platform_device *device); -static int tc1100_remove(struct platform_device *device); -static int tc1100_suspend(struct platform_device *device, pm_message_t state); -static int tc1100_resume(struct platform_device *device); - -static struct platform_driver tc1100_driver = { - .driver = { - .name = "tc1100-wmi", - .owner = THIS_MODULE, - }, - .probe = tc1100_probe, - .remove = tc1100_remove, - .suspend = tc1100_suspend, - .resume = tc1100_resume, -}; - static struct platform_device *tc1100_device; struct tc1100_data { @@ -197,13 +181,13 @@ static struct attribute_group tc1100_attribute_group = { Driver Model -------------------------------------------------------------------------- */ -static int tc1100_probe(struct platform_device *device) +static int __init tc1100_probe(struct platform_device *device) { return sysfs_create_group(&device->dev.kobj, &tc1100_attribute_group); } -static int tc1100_remove(struct platform_device *device) +static int __devexit tc1100_remove(struct platform_device *device) { sysfs_remove_group(&device->dev.kobj, &tc1100_attribute_group); @@ -240,31 +224,49 @@ static int tc1100_resume(struct platform_device *dev) return ret; } +static struct platform_driver tc1100_driver = { + .driver = { + .name = "tc1100-wmi", + .owner = THIS_MODULE, + }, + .remove = __devexit_p(tc1100_remove), + .suspend = tc1100_suspend, + .resume = tc1100_resume, +}; + static int __init tc1100_init(void) { - int result = 0; + int error; if (!wmi_has_guid(GUID)) return -ENODEV; - result = platform_driver_register(&tc1100_driver); - if (result) - return result; - tc1100_device = platform_device_alloc("tc1100-wmi", -1); - platform_device_add(tc1100_device); + if (!tc1100_device) + return -ENOMEM; + + error = platform_device_add(tc1100_device); + if (error) + goto err_device_put; + + error = platform_driver_probe(&tc1100_driver, tc1100_probe); + if (error) + goto err_device_del; printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras loaded\n"); + return 0; - return result; + err_device_del: + platform_device_del(tc1100_device); + err_device_put: + platform_device_put(tc1100_device); + return error; } static void __exit tc1100_exit(void) { - platform_device_del(tc1100_device); + platform_device_unregister(tc1100_device); platform_driver_unregister(&tc1100_driver); - - printk(TC1100_INFO "HP Compaq TC1100 Tablet WMI Extras unloaded\n"); } module_init(tc1100_init); -- cgit v1.2.3-70-g09d2 From 8e698a3c47887fe5aa5e2252c27bb6ff416a07e4 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Fri, 4 Dec 2009 00:36:20 -0800 Subject: tc1100-wmi - switch to using dev_pm_ops Also guard PM operations with CONFIG_PM. Signed-off-by: Dmitry Torokhov Signed-off-by: Len Brown --- drivers/platform/x86/tc1100-wmi.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/tc1100-wmi.c b/drivers/platform/x86/tc1100-wmi.c index fa2995bfa1d..dd33b51c348 100644 --- a/drivers/platform/x86/tc1100-wmi.c +++ b/drivers/platform/x86/tc1100-wmi.c @@ -194,7 +194,8 @@ static int __devexit tc1100_remove(struct platform_device *device) return 0; } -static int tc1100_suspend(struct platform_device *dev, pm_message_t state) +#ifdef CONFIG_PM +static int tc1100_suspend(struct device *dev) { int ret; @@ -206,10 +207,10 @@ static int tc1100_suspend(struct platform_device *dev, pm_message_t state) if (ret) return ret; - return ret; + return 0; } -static int tc1100_resume(struct platform_device *dev) +static int tc1100_resume(struct device *dev) { int ret; @@ -221,17 +222,26 @@ static int tc1100_resume(struct platform_device *dev) if (ret) return ret; - return ret; + return 0; } +static const struct dev_pm_ops tc1100_pm_ops = { + .suspend = tc1100_suspend, + .resume = tc1100_resume, + .freeze = tc1100_suspend, + .restore = tc1100_resume, +}; +#endif + static struct platform_driver tc1100_driver = { .driver = { .name = "tc1100-wmi", .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &tc1100_pm_ops, +#endif }, .remove = __devexit_p(tc1100_remove), - .suspend = tc1100_suspend, - .resume = tc1100_resume, }; static int __init tc1100_init(void) -- cgit v1.2.3-70-g09d2 From 4f924ba5b5aaf1477daafeae779495d39549186d Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 17 Dec 2009 00:08:33 +0900 Subject: sony-laptop: add AVMode key mapping Some models are equipped with an "AVMode" function key that sends sony-laptop: Unknown event: 0x100 0xa1 sony-laptop: Unknown event: 0x100 0x21 for press and release respectively. Cc: "Matthew W. S. Bell" Cc: Dmitry Torokhov Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 4 ++++ include/linux/sonypi.h | 1 + 2 files changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index a2a742c8ff7..9710f70040b 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -232,6 +232,7 @@ static int sony_laptop_input_index[] = { 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ + 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */ }; static int sony_laptop_input_keycode_map[] = { @@ -293,6 +294,7 @@ static int sony_laptop_input_keycode_map[] = { KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ + KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */ }; /* release buttons after a short delay if pressed */ @@ -890,6 +892,8 @@ static struct sony_nc_event sony_100_events[] = { { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, + { 0xa1, SONYPI_EVENT_MEDIA_PRESSED }, + { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0, 0 }, }; diff --git a/include/linux/sonypi.h b/include/linux/sonypi.h index 34c4475ac4a..4f95c1aac2f 100644 --- a/include/linux/sonypi.h +++ b/include/linux/sonypi.h @@ -111,6 +111,7 @@ #define SONYPI_EVENT_VOLUME_INC_PRESSED 69 #define SONYPI_EVENT_VOLUME_DEC_PRESSED 70 #define SONYPI_EVENT_BRIGHTNESS_PRESSED 71 +#define SONYPI_EVENT_MEDIA_PRESSED 72 /* get/set brightness */ #define SONYPI_IOCGBRT _IOR('v', 0, __u8) -- cgit v1.2.3-70-g09d2 From 652fd781a52ad6e24b908cd8b83d12699754f253 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 16 Dec 2009 19:23:43 +0100 Subject: Bluetooth: Prevent ill-timed autosuspend in USB driver The device must be marked busy as it receives data. Signed-off-by: Oliver Neukum Tested-by: Matthew Garrett Signed-off-by: Marcel Holtmann --- drivers/bluetooth/btusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 4d290599675..a699f09ddf7 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -307,6 +307,7 @@ static void btusb_bulk_complete(struct urb *urb) return; usb_anchor_urb(urb, &data->bulk_anchor); + usb_mark_last_busy(data->udev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { -- cgit v1.2.3-70-g09d2 From 875ab0b74e85d6801a49392447d26e0b28688d86 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 18 Dec 2009 01:57:31 +0100 Subject: PM: Make the initcall_debug style timing for suspend/resume complete Commit f2511774863487e61b56a97da07ebf8dd61d7836 (PM: Add initcall_debug style timing for suspend/resume) introduced basic timing instrumentation, needed for a scritps/bootgraph.pl equivalent or humans, but it missed the fact that bus types and device classes which haven't been switched to using struct dev_pm_ops objects yet need special handling. As a result, the suspend/resume timing information is only available for devices whose bus types or device classes use struct dev_pm_ops objects, so the majority of devices is not covered. Fix this by adding basic suspend/resume timing instrumentation for devices whose bus types and device classes still don't use struct dev_pm_ops objects for power management. To reduce code duplication move the timing code to helper functions. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 97 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 77 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 1a216c114a0..c448d5972a0 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -161,6 +161,32 @@ void device_pm_move_last(struct device *dev) list_move_tail(&dev->power.entry, &dpm_list); } +static ktime_t initcall_debug_start(struct device *dev) +{ + ktime_t calltime = ktime_set(0, 0); + + if (initcall_debug) { + pr_info("calling %s+ @ %i\n", + dev_name(dev), task_pid_nr(current)); + calltime = ktime_get(); + } + + return calltime; +} + +static void initcall_debug_report(struct device *dev, ktime_t calltime, + int error) +{ + ktime_t delta, rettime; + + if (initcall_debug) { + rettime = ktime_get(); + delta = ktime_sub(rettime, calltime); + pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), + error, (unsigned long long)ktime_to_ns(delta) >> 10); + } +} + /** * pm_op - Execute the PM operation appropriate for given PM event. * @dev: Device to handle. @@ -172,13 +198,9 @@ static int pm_op(struct device *dev, pm_message_t state) { int error = 0; - ktime_t calltime, delta, rettime; + ktime_t calltime; - if (initcall_debug) { - pr_info("calling %s+ @ %i\n", - dev_name(dev), task_pid_nr(current)); - calltime = ktime_get(); - } + calltime = initcall_debug_start(dev); switch (state.event) { #ifdef CONFIG_SUSPEND @@ -227,12 +249,7 @@ static int pm_op(struct device *dev, error = -EINVAL; } - if (initcall_debug) { - rettime = ktime_get(); - delta = ktime_sub(rettime, calltime); - pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), - error, (unsigned long long)ktime_to_ns(delta) >> 10); - } + initcall_debug_report(dev, calltime, error); return error; } @@ -309,8 +326,9 @@ static int pm_noirq_op(struct device *dev, if (initcall_debug) { rettime = ktime_get(); delta = ktime_sub(rettime, calltime); - printk("initcall %s_i+ returned %d after %Ld usecs\n", dev_name(dev), - error, (unsigned long long)ktime_to_ns(delta) >> 10); + printk("initcall %s_i+ returned %d after %Ld usecs\n", + dev_name(dev), error, + (unsigned long long)ktime_to_ns(delta) >> 10); } return error; @@ -407,6 +425,26 @@ void dpm_resume_noirq(pm_message_t state) } EXPORT_SYMBOL_GPL(dpm_resume_noirq); +/** + * legacy_resume - Execute a legacy (bus or class) resume callback for device. + * dev: Device to resume. + * cb: Resume callback to execute. + */ +static int legacy_resume(struct device *dev, int (*cb)(struct device *dev)) +{ + int error; + ktime_t calltime; + + calltime = initcall_debug_start(dev); + + error = cb(dev); + suspend_report_result(cb, error); + + initcall_debug_report(dev, calltime, error); + + return error; +} + /** * device_resume - Execute "resume" callbacks for given device. * @dev: Device to handle. @@ -427,7 +465,7 @@ static int device_resume(struct device *dev, pm_message_t state) error = pm_op(dev, dev->bus->pm, state); } else if (dev->bus->resume) { pm_dev_dbg(dev, state, "legacy "); - error = dev->bus->resume(dev); + error = legacy_resume(dev, dev->bus->resume); } if (error) goto End; @@ -448,7 +486,7 @@ static int device_resume(struct device *dev, pm_message_t state) error = pm_op(dev, dev->class->pm, state); } else if (dev->class->resume) { pm_dev_dbg(dev, state, "legacy class "); - error = dev->class->resume(dev); + error = legacy_resume(dev, dev->class->resume); } } End: @@ -647,6 +685,27 @@ int dpm_suspend_noirq(pm_message_t state) } EXPORT_SYMBOL_GPL(dpm_suspend_noirq); +/** + * legacy_suspend - Execute a legacy (bus or class) suspend callback for device. + * dev: Device to suspend. + * cb: Suspend callback to execute. + */ +static int legacy_suspend(struct device *dev, pm_message_t state, + int (*cb)(struct device *dev, pm_message_t state)) +{ + int error; + ktime_t calltime; + + calltime = initcall_debug_start(dev); + + error = cb(dev, state); + suspend_report_result(cb, error); + + initcall_debug_report(dev, calltime, error); + + return error; +} + /** * device_suspend - Execute "suspend" callbacks for given device. * @dev: Device to handle. @@ -664,8 +723,7 @@ static int device_suspend(struct device *dev, pm_message_t state) error = pm_op(dev, dev->class->pm, state); } else if (dev->class->suspend) { pm_dev_dbg(dev, state, "legacy class "); - error = dev->class->suspend(dev, state); - suspend_report_result(dev->class->suspend, error); + error = legacy_suspend(dev, state, dev->class->suspend); } if (error) goto End; @@ -686,8 +744,7 @@ static int device_suspend(struct device *dev, pm_message_t state) error = pm_op(dev, dev->bus->pm, state); } else if (dev->bus->suspend) { pm_dev_dbg(dev, state, "legacy "); - error = dev->bus->suspend(dev, state); - suspend_report_result(dev->bus->suspend, error); + error = legacy_suspend(dev, state, dev->bus->suspend); } } End: -- cgit v1.2.3-70-g09d2 From ecf762b2581e12ac761d12a6e4e297c2224aa899 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 18 Dec 2009 01:57:47 +0100 Subject: PM: Measure device suspend and resume times Measure and print the time of suspending and resuming all devices. Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'drivers') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index c448d5972a0..8052dafc0ba 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -372,6 +372,23 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info, kobject_name(&dev->kobj), pm_verb(state.event), info, error); } +static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) +{ + ktime_t calltime; + s64 usecs64; + int usecs; + + calltime = ktime_get(); + usecs64 = ktime_to_ns(ktime_sub(calltime, starttime)); + do_div(usecs64, NSEC_PER_USEC); + usecs = usecs64; + if (usecs == 0) + usecs = 1; + pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n", + info ?: "", info ? " " : "", pm_verb(state.event), + usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC); +} + /*------------------------- Resume routines -------------------------*/ /** @@ -408,6 +425,7 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) void dpm_resume_noirq(pm_message_t state) { struct device *dev; + ktime_t starttime = ktime_get(); mutex_lock(&dpm_list_mtx); transition_started = false; @@ -421,6 +439,7 @@ void dpm_resume_noirq(pm_message_t state) pm_dev_err(dev, state, " early", error); } mutex_unlock(&dpm_list_mtx); + dpm_show_time(starttime, state, "early"); resume_device_irqs(); } EXPORT_SYMBOL_GPL(dpm_resume_noirq); @@ -506,6 +525,7 @@ static int device_resume(struct device *dev, pm_message_t state) static void dpm_resume(pm_message_t state) { struct list_head list; + ktime_t starttime = ktime_get(); INIT_LIST_HEAD(&list); mutex_lock(&dpm_list_mtx); @@ -534,6 +554,7 @@ static void dpm_resume(pm_message_t state) } list_splice(&list, &dpm_list); mutex_unlock(&dpm_list_mtx); + dpm_show_time(starttime, state, NULL); } /** @@ -666,6 +687,7 @@ static int device_suspend_noirq(struct device *dev, pm_message_t state) int dpm_suspend_noirq(pm_message_t state) { struct device *dev; + ktime_t starttime = ktime_get(); int error = 0; suspend_device_irqs(); @@ -681,6 +703,8 @@ int dpm_suspend_noirq(pm_message_t state) mutex_unlock(&dpm_list_mtx); if (error) dpm_resume_noirq(resume_event(state)); + else + dpm_show_time(starttime, state, "late"); return error; } EXPORT_SYMBOL_GPL(dpm_suspend_noirq); @@ -760,6 +784,7 @@ static int device_suspend(struct device *dev, pm_message_t state) static int dpm_suspend(pm_message_t state) { struct list_head list; + ktime_t starttime = ktime_get(); int error = 0; INIT_LIST_HEAD(&list); @@ -785,6 +810,8 @@ static int dpm_suspend(pm_message_t state) } list_splice(&list, dpm_list.prev); mutex_unlock(&dpm_list_mtx); + if (!error) + dpm_show_time(starttime, state, NULL); return error; } -- cgit v1.2.3-70-g09d2 From ed8b67040965e4fe695db333d5914e18ea5f146f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 16 Dec 2009 22:17:09 +0000 Subject: drm: convert drm_ioctl to unlocked_ioctl drm_ioctl is called with the Big Kernel Lock held, which shows up very high in statistics on vfs_ioctl. Moving the lock into the drm_ioctl function itself makes sure we blame the right subsystem and it gets us one step closer to eliminating the locked version of fops->ioctl. Since drm_ioctl does not require the lock itself, we only need to hold it while calling the specific handler. The 32 bit conversion handlers do not interact with any other code, so they don't need the BKL here either and can just call drm_ioctl. As a bonus, this cleans up all the other users of drm_ioctl which now no longer have to find the inode or call lock_kernel. [airlied: squashed the non-driver bits of the second patch in here, this provides the flag for drivers to use to select unlocked ioctls - but doesn't modify any drivers]. Signed-off-by: Arnd Bergmann Cc: David Airlie Cc: dri-devel@lists.sourceforge.net Cc: Frederic Weisbecker Cc: Thomas Gleixner Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_drv.c | 13 +++-- drivers/gpu/drm/drm_ioc32.c | 89 +++++++++++---------------------- drivers/gpu/drm/i810/i810_dma.c | 2 +- drivers/gpu/drm/i810/i810_drv.c | 2 +- drivers/gpu/drm/i830/i830_dma.c | 2 +- drivers/gpu/drm/i830/i830_drv.c | 2 +- drivers/gpu/drm/i915/i915_drv.c | 2 +- drivers/gpu/drm/i915/i915_ioc32.c | 23 ++++----- drivers/gpu/drm/mga/mga_drv.c | 2 +- drivers/gpu/drm/mga/mga_ioc32.c | 13 ++--- drivers/gpu/drm/nouveau/nouveau_drv.c | 2 +- drivers/gpu/drm/nouveau/nouveau_ioc32.c | 4 +- drivers/gpu/drm/r128/r128_drv.c | 2 +- drivers/gpu/drm/r128/r128_ioc32.c | 16 ++---- drivers/gpu/drm/radeon/radeon_drv.c | 4 +- drivers/gpu/drm/radeon/radeon_ioc32.c | 38 +++++--------- drivers/gpu/drm/savage/savage_drv.c | 2 +- drivers/gpu/drm/sis/sis_drv.c | 2 +- drivers/gpu/drm/tdfx/tdfx_drv.c | 2 +- drivers/gpu/drm/via/via_drv.c | 2 +- include/drm/drmP.h | 5 +- 21 files changed, 89 insertions(+), 140 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index ff2f1042cb4..766c46875a2 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -434,11 +434,11 @@ static int drm_version(struct drm_device *dev, void *data, * Looks up the ioctl function in the ::ioctls table, checking for root * previleges if so required, and dispatches to the respective function. */ -int drm_ioctl(struct inode *inode, struct file *filp, +long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->minor->dev; + struct drm_device *dev; struct drm_ioctl_desc *ioctl; drm_ioctl_t *func; unsigned int nr = DRM_IOCTL_NR(cmd); @@ -446,6 +446,7 @@ int drm_ioctl(struct inode *inode, struct file *filp, char stack_kdata[128]; char *kdata = NULL; + dev = file_priv->minor->dev; atomic_inc(&dev->ioctl_count); atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); ++file_priv->ioctl_count; @@ -501,7 +502,13 @@ int drm_ioctl(struct inode *inode, struct file *filp, goto err_i1; } } - retcode = func(dev, kdata, file_priv); + if (ioctl->flags & DRM_UNLOCKED) + retcode = func(dev, kdata, file_priv); + else { + lock_kernel(); + retcode = func(dev, kdata, file_priv); + unlock_kernel(); + } if (cmd & IOC_OUT) { if (copy_to_user((void __user *)arg, kdata, diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index 282d9fdf9f4..d61d185cf04 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -104,7 +104,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd, &version->desc)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, + err = drm_ioctl(file, DRM_IOCTL_VERSION, (unsigned long)version); if (err) return err; @@ -145,8 +145,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, &u->unique)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_GET_UNIQUE, (unsigned long)u); + err = drm_ioctl(file, DRM_IOCTL_GET_UNIQUE, (unsigned long)u); if (err) return err; @@ -174,8 +173,7 @@ static int compat_drm_setunique(struct file *file, unsigned int cmd, &u->unique)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_SET_UNIQUE, (unsigned long)u); + return drm_ioctl(file, DRM_IOCTL_SET_UNIQUE, (unsigned long)u); } typedef struct drm_map32 { @@ -205,8 +203,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd, if (__put_user(idx, &map->offset)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_GET_MAP, (unsigned long)map); + err = drm_ioctl(file, DRM_IOCTL_GET_MAP, (unsigned long)map); if (err) return err; @@ -246,8 +243,7 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd, || __put_user(m32.flags, &map->flags)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_ADD_MAP, (unsigned long)map); + err = drm_ioctl(file, DRM_IOCTL_ADD_MAP, (unsigned long)map); if (err) return err; @@ -284,8 +280,7 @@ static int compat_drm_rmmap(struct file *file, unsigned int cmd, if (__put_user((void *)(unsigned long)handle, &map->handle)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RM_MAP, (unsigned long)map); + return drm_ioctl(file, DRM_IOCTL_RM_MAP, (unsigned long)map); } typedef struct drm_client32 { @@ -314,8 +309,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, if (__put_user(idx, &client->idx)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_GET_CLIENT, (unsigned long)client); + err = drm_ioctl(file, DRM_IOCTL_GET_CLIENT, (unsigned long)client); if (err) return err; @@ -351,8 +345,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd, if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats))) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_GET_STATS, (unsigned long)stats); + err = drm_ioctl(file, DRM_IOCTL_GET_STATS, (unsigned long)stats); if (err) return err; @@ -395,8 +388,7 @@ static int compat_drm_addbufs(struct file *file, unsigned int cmd, || __put_user(agp_start, &buf->agp_start)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_ADD_BUFS, (unsigned long)buf); + err = drm_ioctl(file, DRM_IOCTL_ADD_BUFS, (unsigned long)buf); if (err) return err; @@ -427,8 +419,7 @@ static int compat_drm_markbufs(struct file *file, unsigned int cmd, || __put_user(b32.high_mark, &buf->high_mark)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_MARK_BUFS, (unsigned long)buf); + return drm_ioctl(file, DRM_IOCTL_MARK_BUFS, (unsigned long)buf); } typedef struct drm_buf_info32 { @@ -469,8 +460,7 @@ static int compat_drm_infobufs(struct file *file, unsigned int cmd, || __put_user(list, &request->list)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_INFO_BUFS, (unsigned long)request); + err = drm_ioctl(file, DRM_IOCTL_INFO_BUFS, (unsigned long)request); if (err) return err; @@ -531,8 +521,7 @@ static int compat_drm_mapbufs(struct file *file, unsigned int cmd, || __put_user(list, &request->list)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_MAP_BUFS, (unsigned long)request); + err = drm_ioctl(file, DRM_IOCTL_MAP_BUFS, (unsigned long)request); if (err) return err; @@ -578,8 +567,7 @@ static int compat_drm_freebufs(struct file *file, unsigned int cmd, &request->list)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_FREE_BUFS, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_FREE_BUFS, (unsigned long)request); } typedef struct drm_ctx_priv_map32 { @@ -605,8 +593,7 @@ static int compat_drm_setsareactx(struct file *file, unsigned int cmd, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_SET_SAREA_CTX, (unsigned long)request); } static int compat_drm_getsareactx(struct file *file, unsigned int cmd, @@ -628,8 +615,7 @@ static int compat_drm_getsareactx(struct file *file, unsigned int cmd, if (__put_user(ctx_id, &request->ctx_id)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); + err = drm_ioctl(file, DRM_IOCTL_GET_SAREA_CTX, (unsigned long)request); if (err) return err; @@ -664,8 +650,7 @@ static int compat_drm_resctx(struct file *file, unsigned int cmd, &res->contexts)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RES_CTX, (unsigned long)res); + err = drm_ioctl(file, DRM_IOCTL_RES_CTX, (unsigned long)res); if (err) return err; @@ -718,8 +703,7 @@ static int compat_drm_dma(struct file *file, unsigned int cmd, &d->request_sizes)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_DMA, (unsigned long)d); + err = drm_ioctl(file, DRM_IOCTL_DMA, (unsigned long)d); if (err) return err; @@ -751,8 +735,7 @@ static int compat_drm_agp_enable(struct file *file, unsigned int cmd, if (put_user(m32.mode, &mode->mode)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); + return drm_ioctl(file, DRM_IOCTL_AGP_ENABLE, (unsigned long)mode); } typedef struct drm_agp_info32 { @@ -781,8 +764,7 @@ static int compat_drm_agp_info(struct file *file, unsigned int cmd, if (!access_ok(VERIFY_WRITE, info, sizeof(*info))) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_AGP_INFO, (unsigned long)info); + err = drm_ioctl(file, DRM_IOCTL_AGP_INFO, (unsigned long)info); if (err) return err; @@ -827,16 +809,14 @@ static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, || __put_user(req32.type, &request->type)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_AGP_ALLOC, (unsigned long)request); + err = drm_ioctl(file, DRM_IOCTL_AGP_ALLOC, (unsigned long)request); if (err) return err; if (__get_user(req32.handle, &request->handle) || __get_user(req32.physical, &request->physical) || copy_to_user(argp, &req32, sizeof(req32))) { - drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_AGP_FREE, (unsigned long)request); + drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request); return -EFAULT; } @@ -856,8 +836,7 @@ static int compat_drm_agp_free(struct file *file, unsigned int cmd, || __put_user(handle, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_AGP_FREE, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_AGP_FREE, (unsigned long)request); } typedef struct drm_agp_binding32 { @@ -881,8 +860,7 @@ static int compat_drm_agp_bind(struct file *file, unsigned int cmd, || __put_user(req32.offset, &request->offset)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_AGP_BIND, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_AGP_BIND, (unsigned long)request); } static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, @@ -898,8 +876,7 @@ static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, || __put_user(handle, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_AGP_UNBIND, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_AGP_UNBIND, (unsigned long)request); } #endif /* __OS_HAS_AGP */ @@ -923,8 +900,7 @@ static int compat_drm_sg_alloc(struct file *file, unsigned int cmd, || __put_user(x, &request->size)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_SG_ALLOC, (unsigned long)request); + err = drm_ioctl(file, DRM_IOCTL_SG_ALLOC, (unsigned long)request); if (err) return err; @@ -950,8 +926,7 @@ static int compat_drm_sg_free(struct file *file, unsigned int cmd, || __put_user(x << PAGE_SHIFT, &request->handle)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_SG_FREE, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_SG_FREE, (unsigned long)request); } #if defined(CONFIG_X86) || defined(CONFIG_IA64) @@ -981,8 +956,7 @@ static int compat_drm_update_draw(struct file *file, unsigned int cmd, __put_user(update32.data, &request->data)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_UPDATE_DRAW, (unsigned long)request); + err = drm_ioctl(file, DRM_IOCTL_UPDATE_DRAW, (unsigned long)request); return err; } #endif @@ -1023,8 +997,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd, || __put_user(req32.request.signal, &request->request.signal)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_WAIT_VBLANK, (unsigned long)request); + err = drm_ioctl(file, DRM_IOCTL_WAIT_VBLANK, (unsigned long)request); if (err) return err; @@ -1094,16 +1067,14 @@ long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) * than always failing. */ if (nr >= ARRAY_SIZE(drm_compat_ioctls)) - return drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + return drm_ioctl(filp, cmd, arg); fn = drm_compat_ioctls[nr]; - lock_kernel(); /* XXX for now */ if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 7d1d88cdf2d..de32d22a8c3 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -115,7 +115,7 @@ static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma) static const struct file_operations i810_buffer_fops = { .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = i810_mmap_buffers, .fasync = drm_fasync, }; diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index fabb9a81796..c1e02752e02 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -59,7 +59,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/i830/i830_dma.c b/drivers/gpu/drm/i830/i830_dma.c index 877bf6cb14a..06bd732e646 100644 --- a/drivers/gpu/drm/i830/i830_dma.c +++ b/drivers/gpu/drm/i830/i830_dma.c @@ -117,7 +117,7 @@ static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma) static const struct file_operations i830_buffer_fops = { .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = i830_mmap_buffers, .fasync = drm_fasync, }; diff --git a/drivers/gpu/drm/i830/i830_drv.c b/drivers/gpu/drm/i830/i830_drv.c index 389597e4a62..44f990bed8f 100644 --- a/drivers/gpu/drm/i830/i830_drv.c +++ b/drivers/gpu/drm/i830/i830_drv.c @@ -70,7 +70,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 2fa21786205..24286ca168f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -329,7 +329,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_gem_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c index 1fe68a251b7..13b028994b2 100644 --- a/drivers/gpu/drm/i915/i915_ioc32.c +++ b/drivers/gpu/drm/i915/i915_ioc32.c @@ -66,8 +66,7 @@ static int compat_i915_batchbuffer(struct file *file, unsigned int cmd, &batchbuffer->cliprects)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_I915_BATCHBUFFER, + return drm_ioctl(file, DRM_IOCTL_I915_BATCHBUFFER, (unsigned long)batchbuffer); } @@ -102,8 +101,8 @@ static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd, &cmdbuffer->cliprects)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_I915_CMDBUFFER, (unsigned long)cmdbuffer); + return drm_ioctl(file, DRM_IOCTL_I915_CMDBUFFER, + (unsigned long)cmdbuffer); } typedef struct drm_i915_irq_emit32 { @@ -125,8 +124,8 @@ static int compat_i915_irq_emit(struct file *file, unsigned int cmd, &request->irq_seq)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_I915_IRQ_EMIT, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_I915_IRQ_EMIT, + (unsigned long)request); } typedef struct drm_i915_getparam32 { int param; @@ -149,8 +148,8 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_I915_GETPARAM, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_I915_GETPARAM, + (unsigned long)request); } typedef struct drm_i915_mem_alloc32 { @@ -178,8 +177,8 @@ static int compat_i915_alloc(struct file *file, unsigned int cmd, &request->region_offset)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_I915_ALLOC, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_I915_ALLOC, + (unsigned long)request); } drm_ioctl_compat_t *i915_compat_ioctls[] = { @@ -211,12 +210,10 @@ long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls)) fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE]; - lock_kernel(); /* XXX for now */ if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 97ee566ef74..ddfe16197b5 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -68,7 +68,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/mga/mga_ioc32.c b/drivers/gpu/drm/mga/mga_ioc32.c index 30d00478dde..c1f877b7bac 100644 --- a/drivers/gpu/drm/mga/mga_ioc32.c +++ b/drivers/gpu/drm/mga/mga_ioc32.c @@ -100,8 +100,7 @@ static int compat_mga_init(struct file *file, unsigned int cmd, if (err) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_MGA_INIT, (unsigned long)init); + return drm_ioctl(file, DRM_IOCTL_MGA_INIT, (unsigned long)init); } typedef struct drm_mga_getparam32 { @@ -125,8 +124,7 @@ static int compat_mga_getparam(struct file *file, unsigned int cmd, &getparam->value)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); + return drm_ioctl(file, DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam); } typedef struct drm_mga_drm_bootstrap32 { @@ -166,8 +164,7 @@ static int compat_mga_dma_bootstrap(struct file *file, unsigned int cmd, || __put_user(dma_bootstrap32.agp_size, &dma_bootstrap->agp_size)) return -EFAULT; - err = drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_MGA_DMA_BOOTSTRAP, + err = drm_ioctl(file, DRM_IOCTL_MGA_DMA_BOOTSTRAP, (unsigned long)dma_bootstrap); if (err) return err; @@ -220,12 +217,10 @@ long mga_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE]; - lock_kernel(); /* XXX for now */ if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 35249c35118..3f943c01e99 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -341,7 +341,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = nouveau_ttm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/nouveau/nouveau_ioc32.c b/drivers/gpu/drm/nouveau/nouveau_ioc32.c index a2c30f4611b..475ba810bba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ioc32.c +++ b/drivers/gpu/drm/nouveau/nouveau_ioc32.c @@ -61,12 +61,10 @@ long nouveau_compat_ioctl(struct file *filp, unsigned int cmd, if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls)) fn = nouveau_compat_ioctls[nr - DRM_COMMAND_BASE]; #endif - lock_kernel(); /* XXX for now */ if (fn != NULL) ret = (*fn)(filp, cmd, arg); else - ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } diff --git a/drivers/gpu/drm/r128/r128_drv.c b/drivers/gpu/drm/r128/r128_drv.c index 601f4c0e5da..b806fdcc717 100644 --- a/drivers/gpu/drm/r128/r128_drv.c +++ b/drivers/gpu/drm/r128/r128_drv.c @@ -64,7 +64,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c index d3cb676eee8..51c99fc4dd3 100644 --- a/drivers/gpu/drm/r128/r128_ioc32.c +++ b/drivers/gpu/drm/r128/r128_ioc32.c @@ -95,8 +95,7 @@ static int compat_r128_init(struct file *file, unsigned int cmd, &init->agp_textures_offset)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_R128_INIT, (unsigned long)init); + return drm_ioctl(file, DRM_IOCTL_R128_INIT, (unsigned long)init); } typedef struct drm_r128_depth32 { @@ -129,8 +128,7 @@ static int compat_r128_depth(struct file *file, unsigned int cmd, &depth->mask)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_R128_DEPTH, (unsigned long)depth); + return drm_ioctl(file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth); } @@ -153,8 +151,7 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd, &stipple->mask)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); + return drm_ioctl(file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); } typedef struct drm_r128_getparam32 { @@ -178,8 +175,7 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd, &getparam->value)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); + return drm_ioctl(file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); } drm_ioctl_compat_t *r128_compat_ioctls[] = { @@ -210,12 +206,10 @@ long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls)) fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE]; - lock_kernel(); /* XXX for now */ if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dbd56ef82f9..8ba3de7994d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -196,7 +196,7 @@ static struct drm_driver driver_old = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, @@ -284,7 +284,7 @@ static struct drm_driver kms_driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = radeon_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/radeon/radeon_ioc32.c b/drivers/gpu/drm/radeon/radeon_ioc32.c index a1bf11de308..48b7cea31e0 100644 --- a/drivers/gpu/drm/radeon/radeon_ioc32.c +++ b/drivers/gpu/drm/radeon/radeon_ioc32.c @@ -92,8 +92,7 @@ static int compat_radeon_cp_init(struct file *file, unsigned int cmd, &init->gart_textures_offset)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); + return drm_ioctl(file, DRM_IOCTL_RADEON_CP_INIT, (unsigned long)init); } typedef struct drm_radeon_clear32 { @@ -125,8 +124,7 @@ static int compat_radeon_cp_clear(struct file *file, unsigned int cmd, &clr->depth_boxes)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); + return drm_ioctl(file, DRM_IOCTL_RADEON_CLEAR, (unsigned long)clr); } typedef struct drm_radeon_stipple32 { @@ -149,8 +147,7 @@ static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd, &request->mask)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_STIPPLE, (unsigned long)request); } typedef struct drm_radeon_tex_image32 { @@ -204,8 +201,7 @@ static int compat_radeon_cp_texture(struct file *file, unsigned int cmd, &image->data)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_TEXTURE, (unsigned long)request); } typedef struct drm_radeon_vertex2_32 { @@ -238,8 +234,7 @@ static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd, &request->prim)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_VERTEX2, (unsigned long)request); } typedef struct drm_radeon_cmd_buffer32 { @@ -268,8 +263,7 @@ static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd, &request->boxes)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_CMDBUF, (unsigned long)request); } typedef struct drm_radeon_getparam32 { @@ -293,8 +287,7 @@ static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_GETPARAM, (unsigned long)request); } typedef struct drm_radeon_mem_alloc32 { @@ -322,8 +315,7 @@ static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd, &request->region_offset)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_ALLOC, (unsigned long)request); } typedef struct drm_radeon_irq_emit32 { @@ -345,8 +337,7 @@ static int compat_radeon_irq_emit(struct file *file, unsigned int cmd, &request->irq_seq)) return -EFAULT; - return drm_ioctl(file->f_path.dentry->d_inode, file, - DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); + return drm_ioctl(file, DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long)request); } /* The two 64-bit arches where alignof(u64)==4 in 32-bit code */ @@ -372,8 +363,7 @@ static int compat_radeon_cp_setparam(struct file *file, unsigned int cmd, &request->value)) return -EFAULT; - return drm_ioctl(file->f_dentry->d_inode, file, - DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); + return drm_ioctl(file, DRM_IOCTL_RADEON_SETPARAM, (unsigned long) request); } #else #define compat_radeon_cp_setparam NULL @@ -413,12 +403,10 @@ long radeon_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls)) fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE]; - lock_kernel(); /* XXX for now */ if (fn != NULL) ret = (*fn) (filp, cmd, arg); else - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } @@ -431,9 +419,7 @@ long radeon_kms_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long if (nr < DRM_COMMAND_BASE) return drm_compat_ioctl(filp, cmd, arg); - lock_kernel(); /* XXX for now */ - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); + ret = drm_ioctl(filp, cmd, arg); return ret; } diff --git a/drivers/gpu/drm/savage/savage_drv.c b/drivers/gpu/drm/savage/savage_drv.c index eee52aa92a7..021de44c15a 100644 --- a/drivers/gpu/drm/savage/savage_drv.c +++ b/drivers/gpu/drm/savage/savage_drv.c @@ -50,7 +50,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index e725cc0b115..4fd1f067d38 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -80,7 +80,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 012ff2e356b..ec5a43e6572 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -48,7 +48,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index bc2f5184300..7a1b210401e 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -58,7 +58,7 @@ static struct drm_driver driver = { .owner = THIS_MODULE, .open = drm_open, .release = drm_release, - .ioctl = drm_ioctl, + .unlocked_ioctl = drm_ioctl, .mmap = drm_mmap, .poll = drm_poll, .fasync = drm_fasync, diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 19ef8ebdc66..71dafb69cfe 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -296,6 +296,7 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, #define DRM_MASTER 0x2 #define DRM_ROOT_ONLY 0x4 #define DRM_CONTROL_ALLOW 0x8 +#define DRM_UNLOCKED 0x10 struct drm_ioctl_desc { unsigned int cmd; @@ -1128,8 +1129,8 @@ static inline int drm_mtrr_del(int handle, unsigned long offset, /* Driver support (drm_drv.h) */ extern int drm_init(struct drm_driver *driver); extern void drm_exit(struct drm_driver *driver); -extern int drm_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern long drm_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg); extern long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); extern int drm_lastclose(struct drm_device *dev); -- cgit v1.2.3-70-g09d2 From 925cc71e512a29e2594bcc17dc58d0a0e9c4d524 Mon Sep 17 00:00:00 2001 From: Robert Jennings Date: Thu, 17 Dec 2009 14:44:38 +0000 Subject: mm: Add notifier in pageblock isolation for balloon drivers Memory balloon drivers can allocate a large amount of memory which is not movable but could be freed to accomodate memory hotplug remove. Prior to calling the memory hotplug notifier chain the memory in the pageblock is isolated. Currently, if the migrate type is not MIGRATE_MOVABLE the isolation will not proceed, causing the memory removal for that page range to fail. Rather than failing pageblock isolation if the migrateteype is not MIGRATE_MOVABLE, this patch checks if all of the pages in the pageblock, and not on the LRU, are owned by a registered balloon driver (or other entity) using a notifier chain. If all of the non-movable pages are owned by a balloon, they can be freed later through the memory notifier chain and the range can still be isolated in set_migratetype_isolate(). Signed-off-by: Robert Jennings Cc: Mel Gorman Cc: Ingo Molnar Cc: Brian King Cc: Paul Mackerras Cc: Martin Schwidefsky Cc: Gerald Schaefer Cc: KAMEZAWA Hiroyuki Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Benjamin Herrenschmidt --- drivers/base/memory.c | 19 +++++++++++++++++ include/linux/memory.h | 27 ++++++++++++++++++++++++ mm/page_alloc.c | 57 +++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 96 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/base/memory.c b/drivers/base/memory.c index c4c8f2e1dd1..d7d77d4a402 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -63,6 +63,20 @@ void unregister_memory_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(unregister_memory_notifier); +static ATOMIC_NOTIFIER_HEAD(memory_isolate_chain); + +int register_memory_isolate_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&memory_isolate_chain, nb); +} +EXPORT_SYMBOL(register_memory_isolate_notifier); + +void unregister_memory_isolate_notifier(struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&memory_isolate_chain, nb); +} +EXPORT_SYMBOL(unregister_memory_isolate_notifier); + /* * register_memory - Setup a sysfs device for a memory block */ @@ -157,6 +171,11 @@ int memory_notify(unsigned long val, void *v) return blocking_notifier_call_chain(&memory_chain, val, v); } +int memory_isolate_notify(unsigned long val, void *v) +{ + return atomic_notifier_call_chain(&memory_isolate_chain, val, v); +} + /* * MEMORY_HOTPLUG depends on SPARSEMEM in mm/Kconfig, so it is * OK to have direct references to sparsemem variables in here. diff --git a/include/linux/memory.h b/include/linux/memory.h index 37fa19b34ef..1adfe779eb9 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -50,6 +50,19 @@ struct memory_notify { int status_change_nid; }; +/* + * During pageblock isolation, count the number of pages within the + * range [start_pfn, start_pfn + nr_pages) which are owned by code + * in the notifier chain. + */ +#define MEM_ISOLATE_COUNT (1<<0) + +struct memory_isolate_notify { + unsigned long start_pfn; /* Start of range to check */ + unsigned int nr_pages; /* # pages in range to check */ + unsigned int pages_found; /* # pages owned found by callbacks */ +}; + struct notifier_block; struct mem_section; @@ -76,14 +89,28 @@ static inline int memory_notify(unsigned long val, void *v) { return 0; } +static inline int register_memory_isolate_notifier(struct notifier_block *nb) +{ + return 0; +} +static inline void unregister_memory_isolate_notifier(struct notifier_block *nb) +{ +} +static inline int memory_isolate_notify(unsigned long val, void *v) +{ + return 0; +} #else extern int register_memory_notifier(struct notifier_block *nb); extern void unregister_memory_notifier(struct notifier_block *nb); +extern int register_memory_isolate_notifier(struct notifier_block *nb); +extern void unregister_memory_isolate_notifier(struct notifier_block *nb); extern int register_new_memory(int, struct mem_section *); extern int unregister_memory_section(struct mem_section *); extern int memory_dev_init(void); extern int remove_memory_block(unsigned long, struct mem_section *, int); extern int memory_notify(unsigned long val, void *v); +extern int memory_isolate_notify(unsigned long val, void *v); extern struct memory_block *find_memory_block(struct mem_section *); #define CONFIG_MEM_BLOCK_SIZE (PAGES_PER_SECTION< #include #include +#include #include #include @@ -5008,23 +5009,65 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags, int set_migratetype_isolate(struct page *page) { struct zone *zone; - unsigned long flags; + struct page *curr_page; + unsigned long flags, pfn, iter; + unsigned long immobile = 0; + struct memory_isolate_notify arg; + int notifier_ret; int ret = -EBUSY; int zone_idx; zone = page_zone(page); zone_idx = zone_idx(zone); + spin_lock_irqsave(&zone->lock, flags); + if (get_pageblock_migratetype(page) == MIGRATE_MOVABLE || + zone_idx == ZONE_MOVABLE) { + ret = 0; + goto out; + } + + pfn = page_to_pfn(page); + arg.start_pfn = pfn; + arg.nr_pages = pageblock_nr_pages; + arg.pages_found = 0; + /* - * In future, more migrate types will be able to be isolation target. + * It may be possible to isolate a pageblock even if the + * migratetype is not MIGRATE_MOVABLE. The memory isolation + * notifier chain is used by balloon drivers to return the + * number of pages in a range that are held by the balloon + * driver to shrink memory. If all the pages are accounted for + * by balloons, are free, or on the LRU, isolation can continue. + * Later, for example, when memory hotplug notifier runs, these + * pages reported as "can be isolated" should be isolated(freed) + * by the balloon driver through the memory notifier chain. */ - if (get_pageblock_migratetype(page) != MIGRATE_MOVABLE && - zone_idx != ZONE_MOVABLE) + notifier_ret = memory_isolate_notify(MEM_ISOLATE_COUNT, &arg); + notifier_ret = notifier_to_errno(notifier_ret); + if (notifier_ret || !arg.pages_found) goto out; - set_pageblock_migratetype(page, MIGRATE_ISOLATE); - move_freepages_block(zone, page, MIGRATE_ISOLATE); - ret = 0; + + for (iter = pfn; iter < (pfn + pageblock_nr_pages); iter++) { + if (!pfn_valid_within(pfn)) + continue; + + curr_page = pfn_to_page(iter); + if (!page_count(curr_page) || PageLRU(curr_page)) + continue; + + immobile++; + } + + if (arg.pages_found == immobile) + ret = 0; + out: + if (!ret) { + set_pageblock_migratetype(page, MIGRATE_ISOLATE); + move_freepages_block(zone, page, MIGRATE_ISOLATE); + } + spin_unlock_irqrestore(&zone->lock, flags); if (!ret) drain_all_pages(); -- cgit v1.2.3-70-g09d2 From afdafff130142ef4d6478dcff6d9e879394fd348 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Fri, 18 Dec 2009 20:13:35 -0800 Subject: netxen: use module parameter correctly Netxen driver is doing this bogus thing to create a control file. This fails if device doesn't exist, and overall is a bad way to do the module parameter. Rather than fix borked code, just rewrite. Just using a writeable module parameter of 0/1 is the correct way Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic_main.c | 57 ++---------------------------------- 1 file changed, 3 insertions(+), 54 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f4996846a23..6cae26a5bd6 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -57,7 +57,9 @@ static int use_msi = 1; static int use_msi_x = 1; -static unsigned long auto_fw_reset = AUTO_FW_RESET_ENABLED; +static int auto_fw_reset = AUTO_FW_RESET_ENABLED; +module_param(auto_fw_reset, int, 0644); +MODULE_PARM_DESC(auto_fw_reset,"Auto firmware reset (0=disabled, 1=enabled"); static int __devinit netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -2534,42 +2536,6 @@ static struct bin_attribute bin_attr_mem = { .write = netxen_sysfs_write_mem, }; -#ifdef CONFIG_MODULES -static ssize_t -netxen_store_auto_fw_reset(struct module_attribute *mattr, - struct module *mod, const char *buf, size_t count) - -{ - unsigned long new; - - if (strict_strtoul(buf, 16, &new)) - return -EINVAL; - - if ((new == AUTO_FW_RESET_ENABLED) || (new == AUTO_FW_RESET_DISABLED)) { - auto_fw_reset = new; - return count; - } - - return -EINVAL; -} - -static ssize_t -netxen_show_auto_fw_reset(struct module_attribute *mattr, - struct module *mod, char *buf) - -{ - if (auto_fw_reset == AUTO_FW_RESET_ENABLED) - return sprintf(buf, "enabled\n"); - else - return sprintf(buf, "disabled\n"); -} - -static struct module_attribute mod_attr_fw_reset = { - .attr = {.name = "auto_fw_reset", .mode = (S_IRUGO | S_IWUSR)}, - .show = netxen_show_auto_fw_reset, - .store = netxen_store_auto_fw_reset, -}; -#endif static void netxen_create_sysfs_entries(struct netxen_adapter *adapter) @@ -2775,23 +2741,12 @@ static struct pci_driver netxen_driver = { static int __init netxen_init_module(void) { -#ifdef CONFIG_MODULES - struct module *mod = THIS_MODULE; -#endif - printk(KERN_INFO "%s\n", netxen_nic_driver_string); #ifdef CONFIG_INET register_netdevice_notifier(&netxen_netdev_cb); register_inetaddr_notifier(&netxen_inetaddr_cb); #endif - -#ifdef CONFIG_MODULES - if (sysfs_create_file(&mod->mkobj.kobj, &mod_attr_fw_reset.attr)) - printk(KERN_ERR "%s: Failed to create auto_fw_reset " - "sysfs entry.", netxen_nic_driver_name); -#endif - return pci_register_driver(&netxen_driver); } @@ -2799,12 +2754,6 @@ module_init(netxen_init_module); static void __exit netxen_exit_module(void) { -#ifdef CONFIG_MODULES - struct module *mod = THIS_MODULE; - - sysfs_remove_file(&mod->mkobj.kobj, &mod_attr_fw_reset.attr); -#endif - pci_unregister_driver(&netxen_driver); #ifdef CONFIG_INET -- cgit v1.2.3-70-g09d2 From db94ce90d3d571c11637a912cc39cfb80df3879c Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 18 Dec 2009 20:14:59 -0800 Subject: e1000e: LED settings in EEPROM ignored on 82571 and 82572 Do not override the customizable LED configuration set in the EEPROM. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/e1000e/82571.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index c1a42cfc80b..b979464091b 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c @@ -1290,7 +1290,6 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw) static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) { u32 ctrl; - u32 led_ctrl; s32 ret_val; ctrl = er32(CTRL); @@ -1305,11 +1304,6 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) break; case e1000_phy_igp_2: ret_val = e1000e_copper_link_setup_igp(hw); - /* Setup activity LED */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); break; default: return -E1000_ERR_PHY; -- cgit v1.2.3-70-g09d2 From 5ee6f6a17cfde9c3141e4d57cf88b5cdf638b463 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 18 Dec 2009 20:16:10 -0800 Subject: broadcom: bcm54xx_shadow_read() errors ignored in bcm54xx_adjust_rxrefclk() If not signed read errors are ignored. Signed-off-by: Roel Kluin Acked-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/phy/broadcom.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index f63c96a4ecb..c13cf64095b 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -326,7 +326,8 @@ error: static void bcm54xx_adjust_rxrefclk(struct phy_device *phydev) { - u32 val, orig; + u32 orig; + int val; bool clk125en = true; /* Abort if we are using an untested phy. */ -- cgit v1.2.3-70-g09d2 From 70abc8cb90e679d8519721e2761d8366a18212a6 Mon Sep 17 00:00:00 2001 From: Roger Oksanen Date: Fri, 18 Dec 2009 20:18:21 -0800 Subject: e100: Fix broken cbs accounting due to missing memset. Alan Stern noticed that e100 caused slab corruption. commit 98468efddb101f8a29af974101c17ba513b07be1 changed the allocation of cbs to use dma pools that don't return zeroed memory, especially the cb->status field used to track which cb to clean, causing (the visible) double freeing of skbs and a wrong free cbs count. Now the cbs are explicitly zeroed at allocation time. Reported-by: Alan Stern Tested-by: Alan Stern Signed-off-by: Roger Oksanen Acked-by: Jesse Brandeburg Signed-off-by: David S. Miller --- drivers/net/e100.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 929701ca07d..839fb2b136d 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1829,6 +1829,7 @@ static int e100_alloc_cbs(struct nic *nic) &nic->cbs_dma_addr); if (!nic->cbs) return -ENOMEM; + memset(nic->cbs, 0, count * sizeof(struct cb)); for (cb = nic->cbs, i = 0; i < count; cb++, i++) { cb->next = (i + 1 < count) ? cb + 1 : nic->cbs; @@ -1837,7 +1838,6 @@ static int e100_alloc_cbs(struct nic *nic) cb->dma_addr = nic->cbs_dma_addr + i * sizeof(struct cb); cb->link = cpu_to_le32(nic->cbs_dma_addr + ((i+1) % count) * sizeof(struct cb)); - cb->skb = NULL; } nic->cb_to_use = nic->cb_to_send = nic->cb_to_clean = nic->cbs; -- cgit v1.2.3-70-g09d2 From f9c4171e01f6befdf5d15346070b819d341c9c73 Mon Sep 17 00:00:00 2001 From: Nageswari Srinivasan Date: Fri, 18 Dec 2009 20:21:21 -0800 Subject: TI DaVinci EMAC: Fix MDIO bus frequency configuration There was a typo in "if condition" checking for validity of MDIO bus frequency passed as part of platform data. Bitwise AND was being used instead of a Logical AND. Tested on: DM6467 EVM Signed-off-by: Nageswari Srinivasan Acked-by: Anant Gole Signed-off-by: David S. Miller --- drivers/net/davinci_emac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 8edac8915ea..34e03104c3c 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -2272,7 +2272,7 @@ static int emac_mii_reset(struct mii_bus *bus) unsigned int clk_div; int mdio_bus_freq = emac_bus_frequency; - if (mdio_max_freq & mdio_bus_freq) + if (mdio_max_freq && mdio_bus_freq) clk_div = ((mdio_bus_freq / mdio_max_freq) - 1); else clk_div = 0xFF; -- cgit v1.2.3-70-g09d2 From 4529819c45161e4a119134f56ef504e69420bc98 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 18 Dec 2009 20:29:04 -0800 Subject: bnx2: reset_task is crashing the kernel. Fixing it. If bnx2 schedules a reset via the reset_task, e.g., due to a TX timeout, it's possible for the NIC to be disabled with packets pending for transmit. In this case, napi_disable will loop forever, eventually crashing the kernel. This patch moves the disable of the device to after the napi_disable call. Signed-off-by: Breno Leitao Acked-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 4bfc8081292..c3e2b279fca 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -653,7 +653,6 @@ static void bnx2_netif_stop(struct bnx2 *bp) { bnx2_cnic_stop(bp); - bnx2_disable_int_sync(bp); if (netif_running(bp->dev)) { bnx2_napi_disable(bp); netif_tx_disable(bp->dev); @@ -672,6 +671,7 @@ bnx2_netif_start(struct bnx2 *bp) bnx2_cnic_start(bp); } } + bnx2_disable_int_sync(bp); } static void -- cgit v1.2.3-70-g09d2 From 01a1e7ec6c3769dc7c5fde23ebc253c6be5f68eb Mon Sep 17 00:00:00 2001 From: Yong Zhang Date: Fri, 18 Dec 2009 20:30:11 -0800 Subject: mISDN: use DECLARE_COMPLETION_ONSTACK for non-constant completion The _ONSTACK variant should be used for on-stack completion, otherwise it will break lockdep. Signed-off-by: Yong Zhang Acked-by: Karsten Keil Signed-off-by: David S. Miller --- drivers/isdn/mISDN/l1oip_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c index 7e5f30dbc0a..f1e8af54dff 100644 --- a/drivers/isdn/mISDN/l1oip_core.c +++ b/drivers/isdn/mISDN/l1oip_core.c @@ -661,7 +661,7 @@ l1oip_socket_thread(void *data) size_t recvbuf_size = 1500; int recvlen; struct socket *socket = NULL; - DECLARE_COMPLETION(wait); + DECLARE_COMPLETION_ONSTACK(wait); /* allocate buffer memory */ recvbuf = kmalloc(recvbuf_size, GFP_KERNEL); -- cgit v1.2.3-70-g09d2 From 4773a47d8a564633cd80b94df397e91e946893e2 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Fri, 18 Dec 2009 20:31:56 -0800 Subject: can/at91: don't check platform_get_irq's return value against zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit platform_get_irq returns -ENXIO on failure, so !irq was probably always true. Better use (int)irq <= 0. Note that a return value of zero is still handled as error even though this could mean irq0. This is a followup to 305b3228f9ff4d59f49e6d34a7034d44ee8ce2f0 that changed the return value of platform_get_irq from 0 to -ENXIO on error. Signed-off-by: Uwe Kleine-König Signed-off-by: Wolfgang Grandegger Signed-off-by: David S. Miller --- drivers/net/can/at91_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index d0ec17878ff..166cc7e579c 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1037,7 +1037,7 @@ static int __init at91_can_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!res || !irq) { + if (!res || irq <= 0) { err = -ENODEV; goto exit_put; } -- cgit v1.2.3-70-g09d2 From e6bf95ffa8d6f8f4b7ee33ea01490d95b0bbeb6e Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 18 Dec 2009 20:35:34 -0800 Subject: bnx2: fixing a timout error due not refreshing TX timers correctly When running the following script on an active bnx2 interface: while(true); do ifconfig ethX mtu 9000; ifconfig ethX mtu 1500; done A timeout error appears and dumps the following stack: NETDEV WATCHDOG: eth4 (bnx2): transmit queue 0 timed out ------------[ cut here ]------------ Badness at net/sched/sch_generic.c:261 This patch just fixes the way that ->trans_start is refreshed. Signed-off-by: Breno Leitao Acked-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index c3e2b279fca..f38764ec02c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -654,9 +654,17 @@ bnx2_netif_stop(struct bnx2 *bp) { bnx2_cnic_stop(bp); if (netif_running(bp->dev)) { + int i; + bnx2_napi_disable(bp); netif_tx_disable(bp->dev); - bp->dev->trans_start = jiffies; /* prevent tx timeout */ + /* prevent tx timeout */ + for (i = 0; i < bp->dev->num_tx_queues; i++) { + struct netdev_queue *txq; + + txq = netdev_get_tx_queue(bp->dev, i); + txq->trans_start = jiffies; + } } } -- cgit v1.2.3-70-g09d2 From 1ccb8389f26f2d513b06abe45d8e0b8f32458302 Mon Sep 17 00:00:00 2001 From: Sandeep Gopalpet Date: Wed, 16 Dec 2009 01:14:58 +0000 Subject: gianfar: Fix a filer bug We need to enable filer whenever we need to use multiple RX queues. Also, need to program RIR0 register with the required distribution we require, if using RX filer hashing support for packet distribution to multiple queues. Signed-off-by: Sandeep Gopalpet Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 8 +++++++- drivers/net/gianfar.h | 4 ++++ 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6850dc0a7b9..1616531a71f 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -357,8 +357,11 @@ static void gfar_init_mac(struct net_device *ndev) /* Configure the coalescing support */ gfar_configure_coalescing(priv, 0xFF, 0xFF); - if (priv->rx_filer_enable) + if (priv->rx_filer_enable) { rctrl |= RCTRL_FILREN; + /* Program the RIR0 reg with the required distribution */ + gfar_write(®s->rir0, DEFAULT_RIR0); + } if (priv->rx_csum_enable) rctrl |= RCTRL_CHECKSUMMING; @@ -1022,6 +1025,9 @@ static int gfar_probe(struct of_device *ofdev, priv->rx_queue[i]->rxic = DEFAULT_RXIC; } + /* enable filer if using multiple RX queues*/ + if(priv->num_rx_queues > 1) + priv->rx_filer_enable = 1; /* Enable most messages by default */ priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index cbb451011cb..68d16dc6e7c 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -401,6 +401,10 @@ extern const char gfar_driver_version[]; #define FPR_FILER_MASK 0xFFFFFFFF #define MAX_FILER_IDX 0xFF +/* This default RIR value directly corresponds + * to the 3-bit hash value generated */ +#define DEFAULT_RIR0 0x05397700 + /* RQFCR register bits */ #define RQFCR_GPI 0x80000000 #define RQFCR_HASHTBL_Q 0x00000000 -- cgit v1.2.3-70-g09d2 From a7f38041b8c38d0721b042c123bd5d6bd2d21feb Mon Sep 17 00:00:00 2001 From: Sandeep Gopalpet Date: Wed, 16 Dec 2009 01:15:07 +0000 Subject: gianfar: Fix stats support This patch updates the per rx/tx queue stats. To update the per rx queue stats a new structure has been introduced rx_q_stats. The per tx queue stats are updated via the netdev_queue structure itself. Note that we update only the tx_packtes, tx_bytes, rx_packets, rx_bytes and rx_dropped stats on a per queue basis. Signed-off-by: Sandeep Gopalpet Signed-off-by: David S. Miller --- drivers/net/gianfar.c | 42 ++++++++++++++++++++++++++++++++++++------ drivers/net/gianfar.h | 10 ++++++++++ 2 files changed, 46 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 1616531a71f..e0620d08464 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -417,6 +417,36 @@ static void gfar_init_mac(struct net_device *ndev) gfar_write(®s->fifo_tx_starve_shutoff, priv->fifo_starve_off); } +static struct net_device_stats *gfar_get_stats(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + struct netdev_queue *txq; + unsigned long rx_packets = 0, rx_bytes = 0, rx_dropped = 0; + unsigned long tx_packets = 0, tx_bytes = 0; + int i = 0; + + for (i = 0; i < priv->num_rx_queues; i++) { + rx_packets += priv->rx_queue[i]->stats.rx_packets; + rx_bytes += priv->rx_queue[i]->stats.rx_bytes; + rx_dropped += priv->rx_queue[i]->stats.rx_dropped; + } + + dev->stats.rx_packets = rx_packets; + dev->stats.rx_bytes = rx_bytes; + dev->stats.rx_dropped = rx_dropped; + + for (i = 0; i < priv->num_tx_queues; i++) { + txq = netdev_get_tx_queue(dev, i); + tx_bytes += txq->tx_bytes; + tx_packets += txq->tx_packets; + } + + dev->stats.tx_bytes = tx_bytes; + dev->stats.tx_packets = tx_packets; + + return &dev->stats; +} + static const struct net_device_ops gfar_netdev_ops = { .ndo_open = gfar_enet_open, .ndo_start_xmit = gfar_start_xmit, @@ -426,6 +456,7 @@ static const struct net_device_ops gfar_netdev_ops = { .ndo_tx_timeout = gfar_timeout, .ndo_do_ioctl = gfar_ioctl, .ndo_select_queue = gfar_select_queue, + .ndo_get_stats = gfar_get_stats, .ndo_vlan_rx_register = gfar_vlan_rx_register, .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, @@ -1943,7 +1974,8 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* Update transmit stats */ - dev->stats.tx_bytes += skb->len; + txq->tx_bytes += skb->len; + txq->tx_packets ++; txbdp = txbdp_start = tx_queue->cur_tx; @@ -2301,8 +2333,6 @@ static int gfar_clean_tx_ring(struct gfar_priv_tx_q *tx_queue) tx_queue->skb_dirtytx = skb_dirtytx; tx_queue->dirty_tx = bdp; - dev->stats.tx_packets += howmany; - return howmany; } @@ -2516,14 +2546,14 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) } } else { /* Increment the number of packets */ - dev->stats.rx_packets++; + rx_queue->stats.rx_packets++; howmany++; if (likely(skb)) { pkt_len = bdp->length - ETH_FCS_LEN; /* Remove the FCS from the packet length */ skb_put(skb, pkt_len); - dev->stats.rx_bytes += pkt_len; + rx_queue->stats.rx_bytes += pkt_len; gfar_process_frame(dev, skb, amount_pull); @@ -2531,7 +2561,7 @@ int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, int rx_work_limit) if (netif_msg_rx_err(priv)) printk(KERN_WARNING "%s: Missing skb!\n", dev->name); - dev->stats.rx_dropped++; + rx_queue->stats.rx_dropped++; priv->extra_stats.rx_skbmissing++; } diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 68d16dc6e7c..4943cbe642a 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -940,6 +940,15 @@ struct gfar_priv_tx_q { unsigned short txtime; }; +/* + * Per RX queue stats + */ +struct rx_q_stats { + unsigned long rx_packets; + unsigned long rx_bytes; + unsigned long rx_dropped; +}; + /** * struct gfar_priv_rx_q - per rx queue structure * @rxlock: per queue rx spin lock @@ -962,6 +971,7 @@ struct gfar_priv_rx_q { struct rxbd8 *cur_rx; struct net_device *dev; struct gfar_priv_grp *grp; + struct rx_q_stats stats; u16 skb_currx; u16 qindex; unsigned int rx_ring_size; -- cgit v1.2.3-70-g09d2 From 7c65ec7958f4f301d5d2ff50476a21e7735c73e8 Mon Sep 17 00:00:00 2001 From: Sandeep Gopalpet Date: Wed, 16 Dec 2009 01:15:17 +0000 Subject: gianfar: Fix bit definitions of IMASK_GRSC and IMASK_GTSC Signed-off-by: Sandeep Gopalpet Signed-off-by: David S. Miller --- drivers/net/gianfar.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 4943cbe642a..3d72dc43dca 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -333,7 +333,7 @@ extern const char gfar_driver_version[]; #define IMASK_BSY 0x20000000 #define IMASK_EBERR 0x10000000 #define IMASK_MSRO 0x04000000 -#define IMASK_GRSC 0x02000000 +#define IMASK_GTSC 0x02000000 #define IMASK_BABT 0x01000000 #define IMASK_TXC 0x00800000 #define IMASK_TXEEN 0x00400000 @@ -344,7 +344,7 @@ extern const char gfar_driver_version[]; #define IMASK_XFUN 0x00010000 #define IMASK_RXB0 0x00008000 #define IMASK_MAG 0x00000800 -#define IMASK_GTSC 0x00000100 +#define IMASK_GRSC 0x00000100 #define IMASK_RXFEN0 0x00000080 #define IMASK_FIR 0x00000008 #define IMASK_FIQ 0x00000004 -- cgit v1.2.3-70-g09d2 From cdd90fb575807622e69245d5c3048281f47c77b3 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 19 Dec 2009 23:36:00 +0000 Subject: ARM: add missing include to nwflash.c nwflash needs jiffie definitions. Signed-off-by: Russell King --- drivers/char/nwflash.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index 8c7df5ba088..f80810901db 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include -- cgit v1.2.3-70-g09d2 From 06393afde321b0fd7626b2d0966ebcaf6077de93 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Sun, 20 Dec 2009 15:39:55 -0500 Subject: Revert "pata_cmd64x: implement serialization as per notes" This reverts commit d43744390e460dce6626fb8de2c02a24ff650005, because it breaks the boot on several machines (mostly sparc64, at present). Signed-off-by: Jeff Garzik --- drivers/ata/pata_cmd64x.c | 116 ++++------------------------------------------ 1 file changed, 8 insertions(+), 108 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index dadfc358ba1..58c09e22383 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -31,7 +31,7 @@ #include #define DRV_NAME "pata_cmd64x" -#define DRV_VERSION "0.3.1" +#define DRV_VERSION "0.2.5" /* * CMD64x specific registers definition. @@ -254,109 +254,17 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc) } /** - * cmd64x_bmdma_stop - DMA stop callback + * cmd646r1_dma_stop - DMA stop callback * @qc: Command in progress * - * Track the completion of live DMA commands and clear the - * host->private_data DMA tracking flag as we do. + * Stub for now while investigating the r1 quirk in the old driver. */ -static void cmd64x_bmdma_stop(struct ata_queued_cmd *qc) +static void cmd646r1_bmdma_stop(struct ata_queued_cmd *qc) { - struct ata_port *ap = qc->ap; ata_bmdma_stop(qc); - WARN_ON(ap->host->private_data != ap); - ap->host->private_data = NULL; -} - -/** - * cmd64x_qc_defer - Defer logic for chip limits - * @qc: queued command - * - * Decide whether we can issue the command. Called under the host lock. - */ - -static int cmd64x_qc_defer(struct ata_queued_cmd *qc) -{ - struct ata_host *host = qc->ap->host; - struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; - int rc; - int dma = 0; - - /* Apply the ATA rules first */ - rc = ata_std_qc_defer(qc); - if (rc) - return rc; - - if (qc->tf.protocol == ATAPI_PROT_DMA || - qc->tf.protocol == ATA_PROT_DMA) - dma = 1; - - /* If the other port is not live then issue the command */ - if (alt == NULL || !alt->qc_active) { - if (dma) - host->private_data = qc->ap; - return 0; - } - /* If there is a live DMA command then wait */ - if (host->private_data != NULL) - return ATA_DEFER_PORT; - if (dma) - /* Cannot overlap our DMA command */ - return ATA_DEFER_PORT; - return 0; } -/** - * cmd64x_interrupt - ATA host interrupt handler - * @irq: irq line (unused) - * @dev_instance: pointer to our ata_host information structure - * - * Our interrupt handler for PCI IDE devices. Calls - * ata_sff_host_intr() for each port that is flagging an IRQ. We cannot - * use the defaults as we need to avoid touching status/altstatus during - * a DMA. - * - * LOCKING: - * Obtains host lock during operation. - * - * RETURNS: - * IRQ_NONE or IRQ_HANDLED. - */ -irqreturn_t cmd64x_interrupt(int irq, void *dev_instance) -{ - struct ata_host *host = dev_instance; - struct pci_dev *pdev = to_pci_dev(host->dev); - unsigned int i; - unsigned int handled = 0; - unsigned long flags; - static const u8 irq_reg[2] = { CFR, ARTTIM23 }; - static const u8 irq_mask[2] = { 1 << 2, 1 << 4 }; - - /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ - spin_lock_irqsave(&host->lock, flags); - - for (i = 0; i < host->n_ports; i++) { - struct ata_port *ap; - u8 reg; - - pci_read_config_byte(pdev, irq_reg[i], ®); - ap = host->ports[i]; - if (ap && (reg & irq_mask[i]) && - !(ap->flags & ATA_FLAG_DISABLED)) { - struct ata_queued_cmd *qc; - - qc = ata_qc_from_tag(ap, ap->link.active_tag); - if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)) && - (qc->flags & ATA_QCFLAG_ACTIVE)) - handled |= ata_sff_host_intr(ap, qc); - } - } - - spin_unlock_irqrestore(&host->lock, flags); - - return IRQ_RETVAL(handled); -} static struct scsi_host_template cmd64x_sht = { ATA_BMDMA_SHT(DRV_NAME), }; @@ -365,8 +273,6 @@ static const struct ata_port_operations cmd64x_base_ops = { .inherits = &ata_bmdma_port_ops, .set_piomode = cmd64x_set_piomode, .set_dmamode = cmd64x_set_dmamode, - .bmdma_stop = cmd64x_bmdma_stop, - .qc_defer = cmd64x_qc_defer, }; static struct ata_port_operations cmd64x_port_ops = { @@ -376,6 +282,7 @@ static struct ata_port_operations cmd64x_port_ops = { static struct ata_port_operations cmd646r1_port_ops = { .inherits = &cmd64x_base_ops, + .bmdma_stop = cmd646r1_bmdma_stop, .cable_detect = ata_cable_40wire, }; @@ -383,7 +290,6 @@ static struct ata_port_operations cmd648_port_ops = { .inherits = &cmd64x_base_ops, .bmdma_stop = cmd648_bmdma_stop, .cable_detect = cmd648_cable_detect, - .qc_defer = ata_std_qc_defer }; static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) @@ -432,7 +338,6 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL }; u8 mrdmode; int rc; - struct ata_host *host; rc = pcim_enable_device(pdev); if (rc) @@ -450,25 +355,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) ppi[0] = &cmd_info[3]; } - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64); pci_read_config_byte(pdev, MRDMODE, &mrdmode); mrdmode &= ~ 0x30; /* IRQ set up */ mrdmode |= 0x02; /* Memory read line enable */ pci_write_config_byte(pdev, MRDMODE, mrdmode); + /* Force PIO 0 here.. */ + /* PPC specific fixup copied from old driver */ #ifdef CONFIG_PPC pci_write_config_byte(pdev, UDIDETCR0, 0xF0); #endif - rc = ata_pci_sff_prepare_host(pdev, ppi, &host); - if (rc) - return rc; - /* We use this pointer to track the AP which has DMA running */ - host->private_data = NULL; - pci_set_master(pdev); - return ata_pci_sff_activate_host(host, cmd64x_interrupt, &cmd64x_sht); + return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL); } #ifdef CONFIG_PM -- cgit v1.2.3-70-g09d2 From 509426bd46ad0903dca409803e0ee3d30f99f1e8 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 20 Dec 2009 19:22:33 +0100 Subject: pata_cmd64x: fix overclocking of UDMA0-2 modes adev->dma_mode stores the transfer mode value not UDMA mode number so the condition in cmd64x_set_dmamode() is always true and the higher UDMA clock is always selected. This can potentially result in data corruption when UDMA33 device is used, when 40-wire cable is used or when the error recovery code decides to lower the device speed down. The issue was introduced in the commit 6a40da0 ("libata cmd64x: whack into a shape that looks like the documentation") which goes back to kernel 2.6.20. Cc: stable@kernel.org Signed-off-by: Bartlomiej Zolnierkiewicz Signed-off-by: Jeff Garzik --- drivers/ata/pata_cmd64x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 58c09e22383..0efb1f58f25 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -219,7 +219,7 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev) regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; /* Merge the control bits */ regU |= 1 << adev->devno; /* UDMA on */ - if (adev->dma_mode > 2) /* 15nS timing */ + if (adev->dma_mode > XFER_UDMA_2) /* 15nS timing */ regU |= 4 << adev->devno; } else { regU &= ~ (1 << adev->devno); /* UDMA off */ -- cgit v1.2.3-70-g09d2 From aa0baaef97c89de2ef216fcc017215ee01662a10 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 21 Dec 2009 02:46:11 +0100 Subject: PM: Use pm_runtime_put_sync in system resume This patch (as1317) fixes a bug in the PM core. When a device is resumed following a system sleep, the core decrements the device's runtime PM usage counter but doesn't issue an idle notification if the counter reaches 0. This could prevent an otherwise unused device from being runtime-suspended again after the system sleep. The fix is to call pm_runtime_put_sync() instead of pm_runtime_put_noidle(). Signed-off-by: Alan Stern Signed-off-by: Rafael J. Wysocki --- drivers/base/power/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 8052dafc0ba..48adf80926a 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -607,7 +607,7 @@ static void dpm_complete(pm_message_t state) mutex_unlock(&dpm_list_mtx); device_complete(dev, state); - pm_runtime_put_noidle(dev); + pm_runtime_put_sync(dev); mutex_lock(&dpm_list_mtx); } @@ -880,7 +880,7 @@ static int dpm_prepare(pm_message_t state) pm_runtime_get_noresume(dev); if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) { /* Wake-up requested during system sleep transition. */ - pm_runtime_put_noidle(dev); + pm_runtime_put_sync(dev); error = -EBUSY; } else { error = device_prepare(dev, state); -- cgit v1.2.3-70-g09d2 From b74665606962456af7f92b1e448cee30ce70967b Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sun, 20 Dec 2009 18:40:18 -0800 Subject: bnx2: Fix bnx2_netif_stop() merge error. The error was introduced while merging: commit 4529819c45161e4a119134f56ef504e69420bc98 bnx2: reset_task is crashing the kernel. Fixing it. Signed-off-by: Michael Chan k Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index f38764ec02c..65df1de447e 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -666,6 +666,7 @@ bnx2_netif_stop(struct bnx2 *bp) txq->trans_start = jiffies; } } + bnx2_disable_int_sync(bp); } static void @@ -679,7 +680,6 @@ bnx2_netif_start(struct bnx2 *bp) bnx2_cnic_start(bp); } } - bnx2_disable_int_sync(bp); } static void -- cgit v1.2.3-70-g09d2 From 3439d65062a4af6af0433c8816fd54697d782ff4 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Tue, 14 Jul 2009 13:39:47 -0400 Subject: pata_bf54x: handle portmuxing of pins through GPIO PORTs By default, the PATA pins are routed to the async address lines in which case, no peripheral muxing needs to be done. However, if the pins get routed through the GPIO PORTs pins, we need to make sure to request them so that the muxing is properly set up. Signed-off-by: Sonic Zhang Signed-off-by: Bryan Wu Signed-off-by: Mike Frysinger Signed-off-by: Jeff Garzik --- drivers/ata/pata_bf54x.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index c4b47a3e544..02c81f12c70 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1557,6 +1557,25 @@ static unsigned short atapi_io_port[] = { P_ATAPI_DMARQ, P_ATAPI_INTRQ, P_ATAPI_IORDY, + P_ATAPI_D0A, + P_ATAPI_D1A, + P_ATAPI_D2A, + P_ATAPI_D3A, + P_ATAPI_D4A, + P_ATAPI_D5A, + P_ATAPI_D6A, + P_ATAPI_D7A, + P_ATAPI_D8A, + P_ATAPI_D9A, + P_ATAPI_D10A, + P_ATAPI_D11A, + P_ATAPI_D12A, + P_ATAPI_D13A, + P_ATAPI_D14A, + P_ATAPI_D15A, + P_ATAPI_A0A, + P_ATAPI_A1A, + P_ATAPI_A2A, 0 }; -- cgit v1.2.3-70-g09d2 From 81074e90f5c150ca70ab8dfcc77860cbe76f364d Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Mon, 21 Dec 2009 16:13:15 +0800 Subject: ACPI: disable _OSI(Windows 2009) on Asus K50IJ Fix a win7 compability issue on Asus K50IJ. Here is the _BCM method of this laptop: Method (_BCM, 1, NotSerialized) { If (LGreaterEqual (OSFG, OSVT)) { If (LNotEqual (OSFG, OSW7)) { Store (One, BCMD) Store (GCBL (Arg0), Local0) Subtract (0x0F, Local0, LBTN) ^^^SBRG.EC0.STBR () ... } Else { DBGR (0x0B, Zero, Zero, Arg0) Store (Arg0, LBTN) ^^^SBRG.EC0.STBR () ... } } } LBTN is used to store the index of the brightness level in the _BCL. GCBL is a method that convert the percentage value to the index value. If _OSI(Windows 2009) is not disabled, LBTN is stored a percentage value which is surely beyond the end of _BCL package. http://bugzilla.kernel.org/show_bug.cgi?id=14753 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/blacklist.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/blacklist.c b/drivers/acpi/blacklist.c index 23e5a0519af..2815df66f6f 100644 --- a/drivers/acpi/blacklist.c +++ b/drivers/acpi/blacklist.c @@ -185,6 +185,12 @@ static int __init dmi_disable_osi_vista(const struct dmi_system_id *d) acpi_osi_setup("!Windows 2006"); return 0; } +static int __init dmi_disable_osi_win7(const struct dmi_system_id *d) +{ + printk(KERN_NOTICE PREFIX "DMI detected: %s\n", d->ident); + acpi_osi_setup("!Windows 2009"); + return 0; +} static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { { @@ -211,6 +217,14 @@ static struct dmi_system_id acpi_osi_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Sony VGN-SR290J"), }, }, + { + .callback = dmi_disable_osi_win7, + .ident = "ASUS K50IJ", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K50IJ"), + }, + }, /* * BIOS invocation of _OSI(Linux) is almost always a BIOS bug. -- cgit v1.2.3-70-g09d2 From 55b313f249e11b815fd0be51869f166aaf368f44 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Tue, 22 Dec 2009 02:42:52 -0500 Subject: ACPI: EC: Fix MSI DMI detection MSI strings should be ORed, not ANDed. Reference: http://bugzilla.kernel.org/show_bug.cgi?id=14446 cc: stable@kernel.org Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index baef28c1e63..7511029a1e0 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -916,6 +916,7 @@ static int ec_validate_ecdt(const struct dmi_system_id *id) /* MSI EC needs special treatment, enable it */ static int ec_flag_msi(const struct dmi_system_id *id) { + printk(KERN_DEBUG PREFIX "Detected MSI hardware, enabling workarounds.\n"); EC_FLAGS_MSI = 1; EC_FLAGS_VALIDATE_ECDT = 1; return 0; @@ -928,8 +929,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "JFL92") }, NULL}, { ec_flag_msi, "MSI hardware", { - DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star"), - DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star") }, NULL}, + DMI_MATCH(DMI_BIOS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star")}, NULL}, + { + ec_flag_msi, "MSI hardware", { + DMI_MATCH(DMI_CHASSIS_VENDOR, "MICRO-Star")}, NULL}, { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BIOS_VENDOR, "ASUS") }, NULL}, -- cgit v1.2.3-70-g09d2 From 78f1699659963fff97975df44db6d5dbe7218e55 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:09 -0700 Subject: ACPI: processor: call _PDC early We discovered that at least one machine (HP Envy), methods in the DSDT attempt to call external methods defined in a dynamically loaded SSDT. Unfortunately, the DSDT methods we are trying to call are part of the EC initialization, which happens very early, and the the dynamic SSDT is only loaded when a processor _PDC method runs much later. This results in namespace lookup errors for the (as of yet) undefined methods. Since Windows doesn't have any issues with this machine, we take it as a hint that they must be evaluating _PDC much earlier than we are. Thus, the proper thing for Linux to do should be to match the Windows implementation more closely. Provide a mechanism to call _PDC before we enable the EC. Doing so loads the dynamic tables, and allows the EC to be enabled correctly. The ACPI processor driver will still evaluate _PDC in its .add() method to cover the hotplug case. Resolves: http://bugzilla.kernel.org/show_bug.cgi?id=14824 Cc: ming.m.lin@intel.com Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/Makefile | 1 + drivers/acpi/bus.c | 2 + drivers/acpi/internal.h | 1 + drivers/acpi/processor_core.c | 69 --------------------------- drivers/acpi/processor_pdc.c | 108 ++++++++++++++++++++++++++++++++++++++++++ include/acpi/processor.h | 3 ++ 6 files changed, 115 insertions(+), 69 deletions(-) create mode 100644 drivers/acpi/processor_pdc.c (limited to 'drivers') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index c7b10b4298e..66cc3f36a95 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -32,6 +32,7 @@ acpi-$(CONFIG_ACPI_SLEEP) += proc.o # acpi-y += bus.o glue.o acpi-y += scan.o +acpi-y += processor_pdc.o acpi-y += ec.o acpi-$(CONFIG_ACPI_DOCK) += dock.o acpi-y += pci_root.o pci_link.o pci_irq.o pci_bind.o diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f12..0bdf24a6fd0 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -888,6 +888,8 @@ static int __init acpi_bus_init(void) goto error1; } + acpi_early_processor_set_pdc(); + /* * Maybe EC region is required at bus_scan/acpi_get_devices. So it * is necessary to enable it as early as possible. diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 074cf8682d5..cb28e0502ac 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -43,6 +43,7 @@ int acpi_power_transition(struct acpi_device *device, int state); extern int acpi_power_nocheck; int acpi_wakeup_device_init(void); +void acpi_early_processor_set_pdc(void); /* -------------------------------------------------------------------------- Embedded Controller diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 41731236f9a..a19a4ff962e 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -124,29 +124,6 @@ static const struct file_operations acpi_processor_info_fops = { DEFINE_PER_CPU(struct acpi_processor *, processors); struct acpi_processor_errata errata __read_mostly; -static int set_no_mwait(const struct dmi_system_id *id) -{ - printk(KERN_NOTICE PREFIX "%s detected - " - "disabling mwait for CPU C-states\n", id->ident); - idle_nomwait = 1; - return 0; -} - -static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { - { - set_no_mwait, "IFL91 board", { - DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), - DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), - DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), - DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, - { - set_no_mwait, "Extensa 5220", { - DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), - DMI_MATCH(DMI_SYS_VENDOR, "Acer"), - DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), - DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, - {}, -}; /* -------------------------------------------------------------------------- Errata Handling @@ -276,45 +253,6 @@ static int acpi_processor_errata(struct acpi_processor *pr) return result; } -/* -------------------------------------------------------------------------- - Common ACPI processor functions - -------------------------------------------------------------------------- */ - -/* - * _PDC is required for a BIOS-OS handshake for most of the newer - * ACPI processor features. - */ -static int acpi_processor_set_pdc(struct acpi_processor *pr) -{ - struct acpi_object_list *pdc_in = pr->pdc; - acpi_status status = AE_OK; - - - if (!pdc_in) - return status; - if (idle_nomwait) { - /* - * If mwait is disabled for CPU C-states, the C2C3_FFH access - * mode will be disabled in the parameter of _PDC object. - * Of course C1_FFH access mode will also be disabled. - */ - union acpi_object *obj; - u32 *buffer = NULL; - - obj = pdc_in->pointer; - buffer = (u32 *)(obj->buffer.pointer); - buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); - - } - status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); - - if (ACPI_FAILURE(status)) - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Could not evaluate _PDC, using legacy perf. control...\n")); - - return status; -} - /* -------------------------------------------------------------------------- FS Interface (/proc) -------------------------------------------------------------------------- */ @@ -825,9 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) } /* _PDC call should be done before doing anything else (if reqd.). */ - arch_acpi_processor_init_pdc(pr); acpi_processor_set_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); @@ -1145,11 +1081,6 @@ static int __init acpi_processor_init(void) if (!acpi_processor_dir) return -ENOMEM; #endif - /* - * Check whether the system is DMI table. If yes, OSPM - * should not use mwait for CPU-states. - */ - dmi_check_system(processor_idle_dmi_table); result = cpuidle_register_driver(&acpi_idle_driver); if (result < 0) goto out_proc; diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c new file mode 100644 index 00000000000..b416c32dda0 --- /dev/null +++ b/drivers/acpi/processor_pdc.c @@ -0,0 +1,108 @@ +#include + +#include +#include + +#include "internal.h" + +#define PREFIX "ACPI: " +#define _COMPONENT ACPI_PROCESSOR_COMPONENT +ACPI_MODULE_NAME("processor_pdc"); + +static int set_no_mwait(const struct dmi_system_id *id) +{ + printk(KERN_NOTICE PREFIX "%s detected - " + "disabling mwait for CPU C-states\n", id->ident); + idle_nomwait = 1; + return 0; +} + +static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { + { + set_no_mwait, "IFL91 board", { + DMI_MATCH(DMI_BIOS_VENDOR, "COMPAL"), + DMI_MATCH(DMI_SYS_VENDOR, "ZEPTO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "3215W"), + DMI_MATCH(DMI_BOARD_NAME, "IFL91") }, NULL}, + { + set_no_mwait, "Extensa 5220", { + DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"), + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_VERSION, "0100"), + DMI_MATCH(DMI_BOARD_NAME, "Columbia") }, NULL}, + {}, +}; + +/* + * _PDC is required for a BIOS-OS handshake for most of the newer + * ACPI processor features. + */ +static int acpi_processor_eval_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *pdc_in = pr->pdc; + acpi_status status = AE_OK; + + if (!pdc_in) + return status; + if (idle_nomwait) { + /* + * If mwait is disabled for CPU C-states, the C2C3_FFH access + * mode will be disabled in the parameter of _PDC object. + * Of course C1_FFH access mode will also be disabled. + */ + union acpi_object *obj; + u32 *buffer = NULL; + + obj = pdc_in->pointer; + buffer = (u32 *)(obj->buffer.pointer); + buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); + + } + status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); + + if (ACPI_FAILURE(status)) + ACPI_DEBUG_PRINT((ACPI_DB_INFO, + "Could not evaluate _PDC, using legacy perf. control.\n")); + + return status; +} + +void acpi_processor_set_pdc(struct acpi_processor *pr) +{ + arch_acpi_processor_init_pdc(pr); + acpi_processor_eval_pdc(pr); + arch_acpi_processor_cleanup_pdc(pr); +} +EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); + +static acpi_status +early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) +{ + struct acpi_processor pr; + + pr.handle = handle; + + /* x86 implementation looks at pr.id to determine some + * CPU capabilites. We can just hard code to 0 since we're + * assuming the CPUs in the system are homogenous and all + * have the same capabilities. + */ + pr.id = 0; + + acpi_processor_set_pdc(&pr); + + return AE_OK; +} + +void acpi_early_processor_set_pdc(void) +{ + /* + * Check whether the system is DMI table. If yes, OSPM + * should not use mwait for CPU-states. + */ + dmi_check_system(processor_idle_dmi_table); + + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + early_init_pdc, NULL, NULL, NULL); +} diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 29245c6b5c0..a1b748a7a76 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -325,6 +325,9 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) #endif /* CONFIG_CPU_FREQ */ +/* in processor_pdc.c */ +void acpi_processor_set_pdc(struct acpi_processor *pr); + /* in processor_throttling.c */ int acpi_processor_tstate_has_changed(struct acpi_processor *pr); int acpi_processor_get_throttling_info(struct acpi_processor *pr); -- cgit v1.2.3-70-g09d2 From 1d9cb470a755409ce97c3376174b1e234bd20371 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:14 -0700 Subject: ACPI: processor: introduce arch_has_acpi_pdc arch dependent helper function that tells us if we should attempt to evaluate _PDC on this machine or not. The x86 implementation assumes that the CPUs in the machine must be homogeneous, and that you cannot mix CPUs of different vendors. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/include/asm/acpi.h | 2 ++ arch/x86/include/asm/acpi.h | 7 +++++++ arch/x86/kernel/acpi/processor.c | 4 +--- drivers/acpi/processor_pdc.c | 3 +++ 4 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 91df9686a0d..3b788829464 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -132,6 +132,8 @@ extern int __devinitdata pxm_to_nid_map[MAX_PXM_DOMAINS]; extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif +static inline bool arch_has_acpi_pdc(void) { return true; } + #define acpi_unlazy_tlb(x) #ifdef CONFIG_ACPI_NUMA diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index 60d2b2db0bc..d787e6e92bd 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -142,6 +142,13 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate) return max_cstate; } +static inline bool arch_has_acpi_pdc(void) +{ + struct cpuinfo_x86 *c = &cpu_data(0); + return (c->x86_vendor == X86_VENDOR_INTEL || + c->x86_vendor == X86_VENDOR_CENTAUR); +} + #else /* !CONFIG_ACPI */ #define acpi_lapic 0 diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index d85d1b2432b..bcb6efe08c5 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -79,9 +79,7 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) struct cpuinfo_x86 *c = &cpu_data(pr->id); pr->pdc = NULL; - if (c->x86_vendor == X86_VENDOR_INTEL || - c->x86_vendor == X86_VENDOR_CENTAUR) - init_intel_pdc(pr, c); + init_intel_pdc(pr, c); return; } diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index b416c32dda0..931e735e9e3 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -69,6 +69,9 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + if (arch_has_acpi_pdc() == false) + return; + arch_acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); -- cgit v1.2.3-70-g09d2 From 407cd87c54e76c266245e8faef8dd4a84b7254fe Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:19 -0700 Subject: ACPI: processor: unify arch_acpi_processor_init_pdc The x86 and ia64 implementations of arch_acpi_processor_init_pdc() are almost exactly the same. The only difference is in what bits they set in obj_list buffer. Combine the boilerplate memory management code, and leave the arch-specific bit twiddling in separate implementations. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/kernel/acpi-processor.c | 34 +---------------------------- arch/x86/kernel/acpi/processor.c | 34 +---------------------------- drivers/acpi/processor_pdc.c | 45 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 46 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index dbda7bde611..ab72d46f52c 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c @@ -16,31 +16,7 @@ static void init_intel_pdc(struct acpi_processor *pr) { - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return; - } + u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; @@ -52,20 +28,12 @@ static void init_intel_pdc(struct acpi_processor *pr) */ buf[2] |= ACPI_PDC_SMP_T_SWCOORD; - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - pr->pdc = obj_list; - return; } /* Initialize _PDC data based on the CPU vendor */ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) { - pr->pdc = NULL; init_intel_pdc(pr); return; } diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index bcb6efe08c5..967860b43f2 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -14,31 +14,7 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) { - struct acpi_object_list *obj_list; - union acpi_object *obj; - u32 *buf; - - /* allocate and initialize pdc. It will be used later. */ - obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); - if (!obj_list) { - printk(KERN_ERR "Memory allocation error\n"); - return; - } - - obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); - if (!obj) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj_list); - return; - } - - buf = kmalloc(12, GFP_KERNEL); - if (!buf) { - printk(KERN_ERR "Memory allocation error\n"); - kfree(obj); - kfree(obj_list); - return; - } + u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; @@ -62,13 +38,6 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) if (!cpu_has(c, X86_FEATURE_MWAIT)) buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); - obj->type = ACPI_TYPE_BUFFER; - obj->buffer.length = 12; - obj->buffer.pointer = (u8 *) buf; - obj_list->count = 1; - obj_list->pointer = obj; - pr->pdc = obj_list; - return; } @@ -78,7 +47,6 @@ void arch_acpi_processor_init_pdc(struct acpi_processor *pr) { struct cpuinfo_x86 *c = &cpu_data(pr->id); - pr->pdc = NULL; init_intel_pdc(pr, c); return; diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 931e735e9e3..87946b6da76 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,49 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_processor_init_pdc(struct acpi_processor *pr) +{ + struct acpi_object_list *obj_list; + union acpi_object *obj; + u32 *buf; + + pr->pdc = NULL; + + /* allocate and initialize pdc. It will be used later. */ + obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); + if (!obj_list) { + printk(KERN_ERR "Memory allocation error\n"); + return; + } + + obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); + if (!obj) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj_list); + return; + } + + buf = kmalloc(12, GFP_KERNEL); + if (!buf) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(obj); + kfree(obj_list); + return; + } + + obj->type = ACPI_TYPE_BUFFER; + obj->buffer.length = 12; + obj->buffer.pointer = (u8 *) buf; + obj_list->count = 1; + obj_list->pointer = obj; + pr->pdc = obj_list; + + /* Now let the arch do the bit-twiddling to buf[] */ + arch_acpi_processor_init_pdc(pr); + + return; +} + /* * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. @@ -72,7 +115,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (arch_has_acpi_pdc() == false) return; - arch_acpi_processor_init_pdc(pr); + acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); arch_acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3-70-g09d2 From 08ea48a326d8030ef5b7fb02292faf5a53c95e0a Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:24 -0700 Subject: ACPI: processor: factor out common _PDC settings Both x86 and ia64 initialize _PDC with mostly common bit settings. Factor out the common settings and leave the arch-specific ones alone. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/kernel/acpi-processor.c | 10 +--------- arch/x86/kernel/acpi/processor.c | 10 +--------- drivers/acpi/processor_pdc.c | 11 +++++++++++ 3 files changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index ab72d46f52c..ebe23f58bd6 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c @@ -18,15 +18,7 @@ static void init_intel_pdc(struct acpi_processor *pr) { u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_EST_CAPABILITY_SMP; - /* - * The default of PDC_SMP_T_SWCOORD bit is set for IA64 cpu so - * that OSPM is capable of native ACPI throttling software - * coordination using BIOS supplied _TSD info. - */ - buf[2] |= ACPI_PDC_SMP_T_SWCOORD; + buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; return; } diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index 967860b43f2..d722ca8cb4c 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -16,16 +16,8 @@ static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) { u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - buf[0] = ACPI_PDC_REVISION_ID; - buf[1] = 1; - buf[2] = ACPI_PDC_C_CAPABILITY_SMP; + buf[2] |= ACPI_PDC_C_CAPABILITY_SMP; - /* - * The default of PDC_SMP_T_SWCOORD bit is set for intel x86 cpu so - * that OSPM is capable of native ACPI throttling software - * coordination using BIOS supplied _TSD info. - */ - buf[2] |= ACPI_PDC_SMP_T_SWCOORD; if (cpu_has(c, X86_FEATURE_EST)) buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 87946b6da76..ccda7c95d07 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -33,6 +33,15 @@ static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = { {}, }; +static void acpi_set_pdc_bits(u32 *buf) +{ + buf[0] = ACPI_PDC_REVISION_ID; + buf[1] = 1; + + /* Enable coordination with firmware's _TSD info */ + buf[2] = ACPI_PDC_SMP_T_SWCOORD; +} + static void acpi_processor_init_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -63,6 +72,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) return; } + acpi_set_pdc_bits(buf); + obj->type = ACPI_TYPE_BUFFER; obj->buffer.length = 12; obj->buffer.pointer = (u8 *) buf; -- cgit v1.2.3-70-g09d2 From 6c5807d7bc7d051fce00863ffb98d36325501eb2 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:29 -0700 Subject: ACPI: processor: finish unifying arch_acpi_processor_init_pdc() The only thing arch-specific about calling _PDC is what bits get set in the input obj_list buffer. There's no need for several levels of indirection to twiddle those bits. Additionally, since we're just messing around with a buffer, we can simplify the interface; no need to pass around the entire struct acpi_processor * just to get at the buffer. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/include/asm/acpi.h | 4 ++++ arch/ia64/kernel/acpi-processor.c | 18 ------------------ arch/x86/include/asm/acpi.h | 19 +++++++++++++++++++ arch/x86/kernel/acpi/processor.c | 34 ---------------------------------- drivers/acpi/processor_pdc.c | 6 +++--- include/acpi/processor.h | 1 - 6 files changed, 26 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/arch/ia64/include/asm/acpi.h b/arch/ia64/include/asm/acpi.h index 3b788829464..7ae58892ba8 100644 --- a/arch/ia64/include/asm/acpi.h +++ b/arch/ia64/include/asm/acpi.h @@ -133,6 +133,10 @@ extern int __initdata nid_to_pxm_map[MAX_NUMNODES]; #endif static inline bool arch_has_acpi_pdc(void) { return true; } +static inline void arch_acpi_set_pdc_bits(u32 *buf) +{ + buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; +} #define acpi_unlazy_tlb(x) diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c index ebe23f58bd6..7ba5accebf6 100644 --- a/arch/ia64/kernel/acpi-processor.c +++ b/arch/ia64/kernel/acpi-processor.c @@ -14,24 +14,6 @@ #include #include -static void init_intel_pdc(struct acpi_processor *pr) -{ - u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - - buf[2] |= ACPI_PDC_EST_CAPABILITY_SMP; - - return; -} - -/* Initialize _PDC data based on the CPU vendor */ -void arch_acpi_processor_init_pdc(struct acpi_processor *pr) -{ - init_intel_pdc(pr); - return; -} - -EXPORT_SYMBOL(arch_acpi_processor_init_pdc); - void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) { if (pr->pdc) { diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h index d787e6e92bd..56f462cf22d 100644 --- a/arch/x86/include/asm/acpi.h +++ b/arch/x86/include/asm/acpi.h @@ -149,6 +149,25 @@ static inline bool arch_has_acpi_pdc(void) c->x86_vendor == X86_VENDOR_CENTAUR); } +static inline void arch_acpi_set_pdc_bits(u32 *buf) +{ + struct cpuinfo_x86 *c = &cpu_data(0); + + buf[2] |= ACPI_PDC_C_CAPABILITY_SMP; + + if (cpu_has(c, X86_FEATURE_EST)) + buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; + + if (cpu_has(c, X86_FEATURE_ACPI)) + buf[2] |= ACPI_PDC_T_FFH; + + /* + * If mwait/monitor is unsupported, C2/C3_FFH will be disabled + */ + if (!cpu_has(c, X86_FEATURE_MWAIT)) + buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); +} + #else /* !CONFIG_ACPI */ #define acpi_lapic 0 diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c index d722ca8cb4c..0f57307f822 100644 --- a/arch/x86/kernel/acpi/processor.c +++ b/arch/x86/kernel/acpi/processor.c @@ -12,40 +12,6 @@ #include #include -static void init_intel_pdc(struct acpi_processor *pr, struct cpuinfo_x86 *c) -{ - u32 *buf = (u32 *)pr->pdc->pointer->buffer.pointer; - - buf[2] |= ACPI_PDC_C_CAPABILITY_SMP; - - if (cpu_has(c, X86_FEATURE_EST)) - buf[2] |= ACPI_PDC_EST_CAPABILITY_SWSMP; - - if (cpu_has(c, X86_FEATURE_ACPI)) - buf[2] |= ACPI_PDC_T_FFH; - - /* - * If mwait/monitor is unsupported, C2/C3_FFH will be disabled - */ - if (!cpu_has(c, X86_FEATURE_MWAIT)) - buf[2] &= ~(ACPI_PDC_C_C2C3_FFH); - - return; -} - - -/* Initialize _PDC data based on the CPU vendor */ -void arch_acpi_processor_init_pdc(struct acpi_processor *pr) -{ - struct cpuinfo_x86 *c = &cpu_data(pr->id); - - init_intel_pdc(pr, c); - - return; -} - -EXPORT_SYMBOL(arch_acpi_processor_init_pdc); - void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) { if (pr->pdc) { diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index ccda7c95d07..48df08ebcec 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -40,6 +40,9 @@ static void acpi_set_pdc_bits(u32 *buf) /* Enable coordination with firmware's _TSD info */ buf[2] = ACPI_PDC_SMP_T_SWCOORD; + + /* Twiddle arch-specific bits needed for _PDC */ + arch_acpi_set_pdc_bits(buf); } static void acpi_processor_init_pdc(struct acpi_processor *pr) @@ -81,9 +84,6 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj_list->pointer = obj; pr->pdc = obj_list; - /* Now let the arch do the bit-twiddling to buf[] */ - arch_acpi_processor_init_pdc(pr); - return; } diff --git a/include/acpi/processor.h b/include/acpi/processor.h index a1b748a7a76..50edd734aec 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -257,7 +257,6 @@ int acpi_processor_notify_smm(struct module *calling_module); DECLARE_PER_CPU(struct acpi_processor *, processors); extern struct acpi_processor_errata errata; -void arch_acpi_processor_init_pdc(struct acpi_processor *pr); void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr); #ifdef ARCH_HAS_POWER_INIT -- cgit v1.2.3-70-g09d2 From 47817254b8637b56730aec26eed2c337d3938bb5 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:34 -0700 Subject: ACPI: processor: unify arch_acpi_processor_cleanup_pdc The x86 and ia64 implementations of the function in $subject are exactly the same. Also, since the arch-specific implementations of setting _PDC have been completely hollowed out, remove the empty shells. Cc: Tony Luck Cc: Thomas Gleixner Cc: Ingo Molnar Cc: "H. Peter Anvin" Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- arch/ia64/kernel/Makefile | 4 ---- arch/ia64/kernel/acpi-processor.c | 27 --------------------------- arch/x86/kernel/acpi/Makefile | 2 +- arch/x86/kernel/acpi/processor.c | 25 ------------------------- drivers/acpi/processor_pdc.c | 21 ++++++++++++++++++++- include/acpi/processor.h | 2 -- 6 files changed, 21 insertions(+), 60 deletions(-) delete mode 100644 arch/ia64/kernel/acpi-processor.c delete mode 100644 arch/x86/kernel/acpi/processor.c (limited to 'drivers') diff --git a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile index 2a75e937ae8..e1236349c99 100644 --- a/arch/ia64/kernel/Makefile +++ b/arch/ia64/kernel/Makefile @@ -18,10 +18,6 @@ obj-$(CONFIG_IA64_GENERIC) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1) += acpi-ext.o obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += acpi-ext.o -ifneq ($(CONFIG_ACPI_PROCESSOR),) -obj-y += acpi-processor.o -endif - obj-$(CONFIG_IA64_PALINFO) += palinfo.o obj-$(CONFIG_IOSAPIC) += iosapic.o obj-$(CONFIG_MODULES) += module.o diff --git a/arch/ia64/kernel/acpi-processor.c b/arch/ia64/kernel/acpi-processor.c deleted file mode 100644 index 7ba5accebf6..00000000000 --- a/arch/ia64/kernel/acpi-processor.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * arch/ia64/kernel/acpi-processor.c - * - * Copyright (C) 2005 Intel Corporation - * Venkatesh Pallipadi - * - Added _PDC for platforms with Intel CPUs - */ - -#include -#include -#include -#include - -#include -#include - -void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - -EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc); diff --git a/arch/x86/kernel/acpi/Makefile b/arch/x86/kernel/acpi/Makefile index fd5ca97a2ad..6f35260bb3e 100644 --- a/arch/x86/kernel/acpi/Makefile +++ b/arch/x86/kernel/acpi/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_ACPI) += boot.o obj-$(CONFIG_ACPI_SLEEP) += sleep.o wakeup_rm.o wakeup_$(BITS).o ifneq ($(CONFIG_ACPI_PROCESSOR),) -obj-y += cstate.o processor.o +obj-y += cstate.o endif $(obj)/wakeup_rm.o: $(obj)/realmode/wakeup.bin diff --git a/arch/x86/kernel/acpi/processor.c b/arch/x86/kernel/acpi/processor.c deleted file mode 100644 index 0f57307f822..00000000000 --- a/arch/x86/kernel/acpi/processor.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2005 Intel Corporation - * Venkatesh Pallipadi - * - Added _PDC for platforms with Intel CPUs - */ - -#include -#include -#include -#include - -#include -#include - -void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - -EXPORT_SYMBOL(arch_acpi_processor_cleanup_pdc); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 48df08ebcec..e786e2ce188 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -1,3 +1,12 @@ +/* + * Copyright (C) 2005 Intel Corporation + * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. + * + * Alex Chiang + * - Unified x86/ia64 implementations + * Venkatesh Pallipadi + * - Added _PDC for platforms with Intel CPUs + */ #include #include @@ -121,6 +130,16 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) return status; } +static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) +{ + if (pr->pdc) { + kfree(pr->pdc->pointer->buffer.pointer); + kfree(pr->pdc->pointer); + kfree(pr->pdc); + pr->pdc = NULL; + } +} + void acpi_processor_set_pdc(struct acpi_processor *pr) { if (arch_has_acpi_pdc() == false) @@ -128,7 +147,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) acpi_processor_init_pdc(pr); acpi_processor_eval_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); + acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 50edd734aec..0873cd57510 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -257,8 +257,6 @@ int acpi_processor_notify_smm(struct module *calling_module); DECLARE_PER_CPU(struct acpi_processor *, processors); extern struct acpi_processor_errata errata; -void arch_acpi_processor_cleanup_pdc(struct acpi_processor *pr); - #ifdef ARCH_HAS_POWER_INIT void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags, unsigned int cpu); -- cgit v1.2.3-70-g09d2 From 3b407aef573b82139c3bc4dcaad2731fad56c054 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:39 -0700 Subject: ACPI: processor: introduce acpi_processor_alloc_pdc() acpi_processor_init_pdc() isn't really doing anything interesting with the struct acpi_processor * parameter. Its real job is to allocate the buffer for the _PDC bits. So rename the function to acpi_processor_alloc_pdc(), and just return the struct acpi_object_list * it's supposed to allocate. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index e786e2ce188..23d2828157e 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -54,26 +54,24 @@ static void acpi_set_pdc_bits(u32 *buf) arch_acpi_set_pdc_bits(buf); } -static void acpi_processor_init_pdc(struct acpi_processor *pr) +static struct acpi_object_list *acpi_processor_alloc_pdc(void) { struct acpi_object_list *obj_list; union acpi_object *obj; u32 *buf; - pr->pdc = NULL; - /* allocate and initialize pdc. It will be used later. */ obj_list = kmalloc(sizeof(struct acpi_object_list), GFP_KERNEL); if (!obj_list) { printk(KERN_ERR "Memory allocation error\n"); - return; + return NULL; } obj = kmalloc(sizeof(union acpi_object), GFP_KERNEL); if (!obj) { printk(KERN_ERR "Memory allocation error\n"); kfree(obj_list); - return; + return NULL; } buf = kmalloc(12, GFP_KERNEL); @@ -81,7 +79,7 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) printk(KERN_ERR "Memory allocation error\n"); kfree(obj); kfree(obj_list); - return; + return NULL; } acpi_set_pdc_bits(buf); @@ -91,9 +89,8 @@ static void acpi_processor_init_pdc(struct acpi_processor *pr) obj->buffer.pointer = (u8 *) buf; obj_list->count = 1; obj_list->pointer = obj; - pr->pdc = obj_list; - return; + return obj_list; } /* @@ -142,10 +139,17 @@ static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) void acpi_processor_set_pdc(struct acpi_processor *pr) { + struct acpi_object_list *obj_list; + if (arch_has_acpi_pdc() == false) return; - acpi_processor_init_pdc(pr); + obj_list = acpi_processor_alloc_pdc(); + if (!obj_list) + return; + + pr->pdc = obj_list; + acpi_processor_eval_pdc(pr); acpi_processor_cleanup_pdc(pr); } -- cgit v1.2.3-70-g09d2 From fa118564ed66f785f957d8230745b62e9244700d Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:19:45 -0700 Subject: ACPI: processor: change acpi_processor_eval_pdc interface acpi_processor_eval_pdc() really only needs a handle and an acpi_object_list * to do its work. No need to pass in a struct acpi_processor *, so let's be more specific about what we want. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 23d2828157e..974de4eb298 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -97,13 +97,11 @@ static struct acpi_object_list *acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int acpi_processor_eval_pdc(struct acpi_processor *pr) +static int +acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { - struct acpi_object_list *pdc_in = pr->pdc; acpi_status status = AE_OK; - if (!pdc_in) - return status; if (idle_nomwait) { /* * If mwait is disabled for CPU C-states, the C2C3_FFH access @@ -118,7 +116,7 @@ static int acpi_processor_eval_pdc(struct acpi_processor *pr) buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH); } - status = acpi_evaluate_object(pr->handle, "_PDC", pdc_in, NULL); + status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL); if (ACPI_FAILURE(status)) ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -148,9 +146,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - pr->pdc = obj_list; - - acpi_processor_eval_pdc(pr); + acpi_processor_eval_pdc(pr->handle, obj_list); acpi_processor_cleanup_pdc(pr); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3-70-g09d2 From b9c2db783456bcbce31e2482214cd337528db295 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:11 -0700 Subject: ACPI: processor: open code acpi_processor_cleanup_pdc We have the acpi_object_list * right there in acpi_processor_set_pdc() so it doesn't seem necessary for an entire helper function just to free it. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_pdc.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index 974de4eb298..deeba22c932 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,16 +125,6 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -static void acpi_processor_cleanup_pdc(struct acpi_processor *pr) -{ - if (pr->pdc) { - kfree(pr->pdc->pointer->buffer.pointer); - kfree(pr->pdc->pointer); - kfree(pr->pdc); - pr->pdc = NULL; - } -} - void acpi_processor_set_pdc(struct acpi_processor *pr) { struct acpi_object_list *obj_list; @@ -147,7 +137,10 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) return; acpi_processor_eval_pdc(pr->handle, obj_list); - acpi_processor_cleanup_pdc(pr); + + kfree(obj_list->pointer->buffer.pointer); + kfree(obj_list->pointer); + kfree(obj_list); } EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); -- cgit v1.2.3-70-g09d2 From 43bab25ced218385f7e6a076c2459ea008cfd2e1 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sun, 20 Dec 2009 12:23:16 -0700 Subject: ACPI: processor: change acpi_processor_set_pdc() interface When calling _PDC, we really only need the handle to the processor to call the method; we don't look at any other parts of the struct acpi_processor * given to us. In the early path, when we walk the namespace, we are given the handle directly, so just pass it through to acpi_processor_set_pdc() without stuffing it into a wasteful struct acpi_processor allocated on the stack each time This saves 2834 bytes of stack. Update the interface accordingly. Signed-off-by: Alex Chiang Signed-off-by: Len Brown --- drivers/acpi/processor_core.c | 2 +- drivers/acpi/processor_pdc.c | 18 +++--------------- include/acpi/processor.h | 2 +- 3 files changed, 5 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index a19a4ff962e..9863c98c81b 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -763,7 +763,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) } /* _PDC call should be done before doing anything else (if reqd.). */ - acpi_processor_set_pdc(pr); + acpi_processor_set_pdc(pr->handle); #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr, 0); diff --git a/drivers/acpi/processor_pdc.c b/drivers/acpi/processor_pdc.c index deeba22c932..30e4dc0cdf3 100644 --- a/drivers/acpi/processor_pdc.c +++ b/drivers/acpi/processor_pdc.c @@ -125,7 +125,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -void acpi_processor_set_pdc(struct acpi_processor *pr) +void acpi_processor_set_pdc(acpi_handle handle) { struct acpi_object_list *obj_list; @@ -136,7 +136,7 @@ void acpi_processor_set_pdc(struct acpi_processor *pr) if (!obj_list) return; - acpi_processor_eval_pdc(pr->handle, obj_list); + acpi_processor_eval_pdc(handle, obj_list); kfree(obj_list->pointer->buffer.pointer); kfree(obj_list->pointer); @@ -147,19 +147,7 @@ EXPORT_SYMBOL_GPL(acpi_processor_set_pdc); static acpi_status early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv) { - struct acpi_processor pr; - - pr.handle = handle; - - /* x86 implementation looks at pr.id to determine some - * CPU capabilites. We can just hard code to 0 since we're - * assuming the CPUs in the system are homogenous and all - * have the same capabilities. - */ - pr.id = 0; - - acpi_processor_set_pdc(&pr); - + acpi_processor_set_pdc(handle); return AE_OK; } diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 0873cd57510..7cc433d6993 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -323,7 +323,7 @@ static inline int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) #endif /* CONFIG_CPU_FREQ */ /* in processor_pdc.c */ -void acpi_processor_set_pdc(struct acpi_processor *pr); +void acpi_processor_set_pdc(acpi_handle handle); /* in processor_throttling.c */ int acpi_processor_tstate_has_changed(struct acpi_processor *pr); -- cgit v1.2.3-70-g09d2 From 05f94c9b74b0bed5469d97edffae350ec9c1f205 Mon Sep 17 00:00:00 2001 From: Evgeniy Polyakov Date: Fri, 18 Dec 2009 15:40:44 +0300 Subject: pohmelfs needs I_LOCK Kill debugging printk in question Signed-off-by: Evgeniy Polyakov Signed-off-by: Al Viro --- drivers/staging/pohmelfs/dir.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/pohmelfs/dir.c b/drivers/staging/pohmelfs/dir.c index 6c5b261e9f0..aacd25bfb0c 100644 --- a/drivers/staging/pohmelfs/dir.c +++ b/drivers/staging/pohmelfs/dir.c @@ -722,8 +722,6 @@ static int pohmelfs_remove_entry(struct inode *dir, struct dentry *dentry) if (inode->i_nlink) inode_dec_link_count(inode); } - dprintk("%s: inode: %p, lock: %ld, unhashed: %d.\n", - __func__, pi, inode->i_state & I_LOCK, hlist_unhashed(&inode->i_hash)); return err; } -- cgit v1.2.3-70-g09d2 From a6ab7aa9f432f722808c6fea5a8b7f5f229de031 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 22 Dec 2009 20:43:17 +0100 Subject: PM / Runtime: Use device type and device class callbacks The power management of some devices is handled through device types and device classes rather than through bus types. Since these devices may also benefit from using the run-time power management core, extend it so that the device type and device class run-time PM callbacks can be taken into consideration by it if the bus type callback is not defined. Update the run-time PM core documentation to reflect this change. Signed-off-by: Rafael J. Wysocki --- Documentation/power/runtime_pm.txt | 173 +++++++++++++++++++------------------ drivers/base/power/runtime.c | 45 ++++++++++ 2 files changed, 132 insertions(+), 86 deletions(-) (limited to 'drivers') diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 4a3109b2884..7b5ab270124 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -42,80 +42,81 @@ struct dev_pm_ops { ... }; -The ->runtime_suspend() callback is executed by the PM core for the bus type of -the device being suspended. The bus type's callback is then _entirely_ -_responsible_ for handling the device as appropriate, which may, but need not -include executing the device driver's own ->runtime_suspend() callback (from the +The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are +executed by the PM core for either the bus type, or device type (if the bus +type's callback is not defined), or device class (if the bus type's and device +type's callbacks are not defined) of given device. The bus type, device type +and device class callbacks are referred to as subsystem-level callbacks in what +follows. + +The subsystem-level suspend callback is _entirely_ _responsible_ for handling +the suspend of the device as appropriate, which may, but need not include +executing the device driver's own ->runtime_suspend() callback (from the PM core's point of view it is not necessary to implement a ->runtime_suspend() -callback in a device driver as long as the bus type's ->runtime_suspend() knows -what to do to handle the device). +callback in a device driver as long as the subsystem-level suspend callback +knows what to do to handle the device). - * Once the bus type's ->runtime_suspend() callback has completed successfully + * Once the subsystem-level suspend callback has completed successfully for given device, the PM core regards the device as suspended, which need not mean that the device has been put into a low power state. It is supposed to mean, however, that the device will not process data and will - not communicate with the CPU(s) and RAM until its bus type's - ->runtime_resume() callback is executed for it. The run-time PM status of - a device after successful execution of its bus type's ->runtime_suspend() - callback is 'suspended'. - - * If the bus type's ->runtime_suspend() callback returns -EBUSY or -EAGAIN, - the device's run-time PM status is supposed to be 'active', which means that - the device _must_ be fully operational afterwards. - - * If the bus type's ->runtime_suspend() callback returns an error code - different from -EBUSY or -EAGAIN, the PM core regards this as a fatal - error and will refuse to run the helper functions described in Section 4 - for the device, until the status of it is directly set either to 'active' - or to 'suspended' (the PM core provides special helper functions for this - purpose). - -In particular, if the driver requires remote wakeup capability for proper -functioning and device_run_wake() returns 'false' for the device, then -->runtime_suspend() should return -EBUSY. On the other hand, if -device_run_wake() returns 'true' for the device and the device is put -into a low power state during the execution of its bus type's -->runtime_suspend(), it is expected that remote wake-up (i.e. hardware mechanism -allowing the device to request a change of its power state, such as PCI PME) -will be enabled for the device. Generally, remote wake-up should be enabled -for all input devices put into a low power state at run time. - -The ->runtime_resume() callback is executed by the PM core for the bus type of -the device being woken up. The bus type's callback is then _entirely_ -_responsible_ for handling the device as appropriate, which may, but need not -include executing the device driver's own ->runtime_resume() callback (from the -PM core's point of view it is not necessary to implement a ->runtime_resume() -callback in a device driver as long as the bus type's ->runtime_resume() knows -what to do to handle the device). - - * Once the bus type's ->runtime_resume() callback has completed successfully, - the PM core regards the device as fully operational, which means that the - device _must_ be able to complete I/O operations as needed. The run-time - PM status of the device is then 'active'. - - * If the bus type's ->runtime_resume() callback returns an error code, the PM - core regards this as a fatal error and will refuse to run the helper - functions described in Section 4 for the device, until its status is - directly set either to 'active' or to 'suspended' (the PM core provides - special helper functions for this purpose). - -The ->runtime_idle() callback is executed by the PM core for the bus type of -given device whenever the device appears to be idle, which is indicated to the -PM core by two counters, the device's usage counter and the counter of 'active' -children of the device. + not communicate with the CPU(s) and RAM until the subsystem-level resume + callback is executed for it. The run-time PM status of a device after + successful execution of the subsystem-level suspend callback is 'suspended'. + + * If the subsystem-level suspend callback returns -EBUSY or -EAGAIN, + the device's run-time PM status is 'active', which means that the device + _must_ be fully operational afterwards. + + * If the subsystem-level suspend callback returns an error code different + from -EBUSY or -EAGAIN, the PM core regards this as a fatal error and will + refuse to run the helper functions described in Section 4 for the device, + until the status of it is directly set either to 'active', or to 'suspended' + (the PM core provides special helper functions for this purpose). + +In particular, if the driver requires remote wake-up capability (i.e. hardware +mechanism allowing the device to request a change of its power state, such as +PCI PME) for proper functioning and device_run_wake() returns 'false' for the +device, then ->runtime_suspend() should return -EBUSY. On the other hand, if +device_run_wake() returns 'true' for the device and the device is put into a low +power state during the execution of the subsystem-level suspend callback, it is +expected that remote wake-up will be enabled for the device. Generally, remote +wake-up should be enabled for all input devices put into a low power state at +run time. + +The subsystem-level resume callback is _entirely_ _responsible_ for handling the +resume of the device as appropriate, which may, but need not include executing +the device driver's own ->runtime_resume() callback (from the PM core's point of +view it is not necessary to implement a ->runtime_resume() callback in a device +driver as long as the subsystem-level resume callback knows what to do to handle +the device). + + * Once the subsystem-level resume callback has completed successfully, the PM + core regards the device as fully operational, which means that the device + _must_ be able to complete I/O operations as needed. The run-time PM status + of the device is then 'active'. + + * If the subsystem-level resume callback returns an error code, the PM core + regards this as a fatal error and will refuse to run the helper functions + described in Section 4 for the device, until its status is directly set + either to 'active' or to 'suspended' (the PM core provides special helper + functions for this purpose). + +The subsystem-level idle callback is executed by the PM core whenever the device +appears to be idle, which is indicated to the PM core by two counters, the +device's usage counter and the counter of 'active' children of the device. * If any of these counters is decreased using a helper function provided by the PM core and it turns out to be equal to zero, the other counter is checked. If that counter also is equal to zero, the PM core executes the - device bus type's ->runtime_idle() callback (with the device as an - argument). + subsystem-level idle callback with the device as an argument. -The action performed by a bus type's ->runtime_idle() callback is totally -dependent on the bus type in question, but the expected and recommended action -is to check if the device can be suspended (i.e. if all of the conditions -necessary for suspending the device are satisfied) and to queue up a suspend -request for the device in that case. The value returned by this callback is -ignored by the PM core. +The action performed by a subsystem-level idle callback is totally dependent on +the subsystem in question, but the expected and recommended action is to check +if the device can be suspended (i.e. if all of the conditions necessary for +suspending the device are satisfied) and to queue up a suspend request for the +device in that case. The value returned by this callback is ignored by the PM +core. The helper functions provided by the PM core, described in Section 4, guarantee that the following constraints are met with respect to the bus type's run-time @@ -238,41 +239,41 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: removing the device from device hierarchy int pm_runtime_idle(struct device *dev); - - execute ->runtime_idle() for the device's bus type; returns 0 on success - or error code on failure, where -EINPROGRESS means that ->runtime_idle() - is already being executed + - execute the subsystem-level idle callback for the device; returns 0 on + success or error code on failure, where -EINPROGRESS means that + ->runtime_idle() is already being executed int pm_runtime_suspend(struct device *dev); - - execute ->runtime_suspend() for the device's bus type; returns 0 on + - execute the subsystem-level suspend callback for the device; returns 0 on success, 1 if the device's run-time PM status was already 'suspended', or error code on failure, where -EAGAIN or -EBUSY means it is safe to attempt to suspend the device again in future int pm_runtime_resume(struct device *dev); - - execute ->runtime_resume() for the device's bus type; returns 0 on + - execute the subsystem-leve resume callback for the device; returns 0 on success, 1 if the device's run-time PM status was already 'active' or error code on failure, where -EAGAIN means it may be safe to attempt to resume the device again in future, but 'power.runtime_error' should be checked additionally int pm_request_idle(struct device *dev); - - submit a request to execute ->runtime_idle() for the device's bus type - (the request is represented by a work item in pm_wq); returns 0 on success - or error code if the request has not been queued up + - submit a request to execute the subsystem-level idle callback for the + device (the request is represented by a work item in pm_wq); returns 0 on + success or error code if the request has not been queued up int pm_schedule_suspend(struct device *dev, unsigned int delay); - - schedule the execution of ->runtime_suspend() for the device's bus type - in future, where 'delay' is the time to wait before queuing up a suspend - work item in pm_wq, in milliseconds (if 'delay' is zero, the work item is - queued up immediately); returns 0 on success, 1 if the device's PM + - schedule the execution of the subsystem-level suspend callback for the + device in future, where 'delay' is the time to wait before queuing up a + suspend work item in pm_wq, in milliseconds (if 'delay' is zero, the work + item is queued up immediately); returns 0 on success, 1 if the device's PM run-time status was already 'suspended', or error code if the request hasn't been scheduled (or queued up if 'delay' is 0); if the execution of ->runtime_suspend() is already scheduled and not yet expired, the new value of 'delay' will be used as the time to wait int pm_request_resume(struct device *dev); - - submit a request to execute ->runtime_resume() for the device's bus type - (the request is represented by a work item in pm_wq); returns 0 on + - submit a request to execute the subsystem-level resume callback for the + device (the request is represented by a work item in pm_wq); returns 0 on success, 1 if the device's run-time PM status was already 'active', or error code if the request hasn't been queued up @@ -303,12 +304,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: run-time PM callbacks described in Section 2 int pm_runtime_disable(struct device *dev); - - prevent the run-time PM helper functions from running the device bus - type's run-time PM callbacks, make sure that all of the pending run-time - PM operations on the device are either completed or canceled; returns - 1 if there was a resume request pending and it was necessary to execute - ->runtime_resume() for the device's bus type to satisfy that request, - otherwise 0 is returned + - prevent the run-time PM helper functions from running subsystem-level + run-time PM callbacks for the device, make sure that all of the pending + run-time PM operations on the device are either completed or canceled; + returns 1 if there was a resume request pending and it was necessary to + execute the subsystem-level resume callback for the device to satisfy that + request, otherwise 0 is returned void pm_suspend_ignore_children(struct device *dev, bool enable); - set/unset the power.ignore_children flag of the device @@ -378,5 +379,5 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has -finished, so the PM core uses pm_runtime_idle_sync() to invoke the device bus -type's ->runtime_idle() callback at that time. +finished, so the PM core uses pm_runtime_idle_sync() to invoke the +subsystem-level idle callback for the device at that time. diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 40d7720a4b2..f8b044e8aef 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -84,6 +84,19 @@ static int __pm_runtime_idle(struct device *dev) dev->bus->pm->runtime_idle(dev); + spin_lock_irq(&dev->power.lock); + } else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle) { + spin_unlock_irq(&dev->power.lock); + + dev->type->pm->runtime_idle(dev); + + spin_lock_irq(&dev->power.lock); + } else if (dev->class && dev->class->pm + && dev->class->pm->runtime_idle) { + spin_unlock_irq(&dev->power.lock); + + dev->class->pm->runtime_idle(dev); + spin_lock_irq(&dev->power.lock); } @@ -192,6 +205,22 @@ int __pm_runtime_suspend(struct device *dev, bool from_wq) retval = dev->bus->pm->runtime_suspend(dev); + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; + } else if (dev->type && dev->type->pm + && dev->type->pm->runtime_suspend) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->type->pm->runtime_suspend(dev); + + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; + } else if (dev->class && dev->class->pm + && dev->class->pm->runtime_suspend) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->class->pm->runtime_suspend(dev); + spin_lock_irq(&dev->power.lock); dev->power.runtime_error = retval; } else { @@ -357,6 +386,22 @@ int __pm_runtime_resume(struct device *dev, bool from_wq) retval = dev->bus->pm->runtime_resume(dev); + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; + } else if (dev->type && dev->type->pm + && dev->type->pm->runtime_resume) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->type->pm->runtime_resume(dev); + + spin_lock_irq(&dev->power.lock); + dev->power.runtime_error = retval; + } else if (dev->class && dev->class->pm + && dev->class->pm->runtime_resume) { + spin_unlock_irq(&dev->power.lock); + + retval = dev->class->pm->runtime_resume(dev); + spin_lock_irq(&dev->power.lock); dev->power.runtime_error = retval; } else { -- cgit v1.2.3-70-g09d2 From 45465487897a1c6d508b14b904dc5777f7ec7e04 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:26 -0800 Subject: kfifo: move struct kfifo in place This is a new generic kernel FIFO implementation. The current kernel fifo API is not very widely used, because it has to many constrains. Only 17 files in the current 2.6.31-rc5 used it. FIFO's are like list's a very basic thing and a kfifo API which handles the most use case would save a lot of development time and memory resources. I think this are the reasons why kfifo is not in use: - The API is to simple, important functions are missing - A fifo can be only allocated dynamically - There is a requirement of a spinlock whether you need it or not - There is no support for data records inside a fifo So I decided to extend the kfifo in a more generic way without blowing up the API to much. The new API has the following benefits: - Generic usage: For kernel internal use and/or device driver. - Provide an API for the most use case. - Slim API: The whole API provides 25 functions. - Linux style habit. - DECLARE_KFIFO, DEFINE_KFIFO and INIT_KFIFO Macros - Direct copy_to_user from the fifo and copy_from_user into the fifo. - The kfifo itself is an in place member of the using data structure, this save an indirection access and does not waste the kernel allocator. - Lockless access: if only one reader and one writer is active on the fifo, which is the common use case, no additional locking is necessary. - Remove spinlock - give the user the freedom of choice what kind of locking to use if one is required. - Ability to handle records. Three type of records are supported: - Variable length records between 0-255 bytes, with a record size field of 1 bytes. - Variable length records between 0-65535 bytes, with a record size field of 2 bytes. - Fixed size records, which no record size field. - Preserve memory resource. - Performance! - Easy to use! This patch: Since most users want to have the kfifo as part of another object, reorganize the code to allow including struct kfifo in another data structure. This requires changing the kfifo_alloc and kfifo_init prototypes so that we pass an existing kfifo pointer into them. This patch changes the implementation and all existing users. [akpm@linux-foundation.org: fix warning] Signed-off-by: Stefani Seibold Acked-by: Greg Kroah-Hartman Acked-by: Mauro Carvalho Chehab Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/nozomi.c | 21 +++++----- drivers/char/sonypi.c | 40 +++++++++--------- drivers/infiniband/hw/cxgb3/cxio_hal.h | 9 ++-- drivers/infiniband/hw/cxgb3/cxio_resource.c | 60 +++++++++++++------------- drivers/media/video/meye.c | 48 ++++++++++----------- drivers/media/video/meye.h | 4 +- drivers/net/wireless/libertas/cmd.c | 4 +- drivers/net/wireless/libertas/dev.h | 4 +- drivers/net/wireless/libertas/main.c | 16 ++++--- drivers/platform/x86/fujitsu-laptop.c | 18 ++++---- drivers/platform/x86/sony-laptop.c | 46 ++++++++++---------- drivers/scsi/libiscsi.c | 22 ++++------ drivers/scsi/libiscsi_tcp.c | 29 +++++++------ drivers/scsi/libsrp.c | 13 +++--- drivers/usb/host/fhci-sched.c | 10 ++--- drivers/usb/host/fhci-tds.c | 35 ++++++++-------- drivers/usb/host/fhci.h | 10 ++--- drivers/usb/serial/usb-serial.c | 5 +-- include/linux/kfifo.h | 11 ++--- include/scsi/libiscsi.h | 3 +- include/scsi/libiscsi_tcp.h | 2 +- include/scsi/libsrp.h | 2 +- kernel/kfifo.c | 65 +++++++++++++++-------------- net/dccp/probe.c | 20 ++++----- 24 files changed, 238 insertions(+), 259 deletions(-) (limited to 'drivers') diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index d3400b20444..0f39bec28b4 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -358,7 +358,7 @@ struct port { u8 update_flow_control; struct ctrl_ul ctrl_ul; struct ctrl_dl ctrl_dl; - struct kfifo *fifo_ul; + struct kfifo fifo_ul; void __iomem *dl_addr[2]; u32 dl_size[2]; u8 toggle_dl; @@ -685,8 +685,8 @@ static int nozomi_read_config_table(struct nozomi *dc) dump_table(dc); for (i = PORT_MDM; i < MAX_PORT; i++) { - dc->port[i].fifo_ul = - kfifo_alloc(FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL); + kfifo_alloc(&dc->port[i].fifo_ul, + FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL); memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); } @@ -798,7 +798,7 @@ static int send_data(enum port_type index, struct nozomi *dc) struct tty_struct *tty = tty_port_tty_get(&port->port); /* Get data from tty and place in buf for now */ - size = __kfifo_get(port->fifo_ul, dc->send_buf, + size = __kfifo_get(&port->fifo_ul, dc->send_buf, ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); if (size == 0) { @@ -988,11 +988,11 @@ static int receive_flow_control(struct nozomi *dc) } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) { - if (__kfifo_len(dc->port[port].fifo_ul)) { + if (__kfifo_len(&dc->port[port].fifo_ul)) { DBG1("Enable interrupt (0x%04X) on port: %d", enable_ier, port); DBG1("Data in buffer [%d], enable transmit! ", - __kfifo_len(dc->port[port].fifo_ul)); + __kfifo_len(&dc->port[port].fifo_ul)); enable_transmit_ul(port, dc); } else { DBG1("No data in buffer..."); @@ -1536,8 +1536,7 @@ static void __devexit nozomi_card_exit(struct pci_dev *pdev) free_irq(pdev->irq, dc); for (i = 0; i < MAX_PORT; i++) - if (dc->port[i].fifo_ul) - kfifo_free(dc->port[i].fifo_ul); + kfifo_free(&dc->port[i].fifo_ul); kfree(dc->send_buf); @@ -1673,7 +1672,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, goto exit; } - rval = __kfifo_put(port->fifo_ul, (unsigned char *)buffer, count); + rval = __kfifo_put(&port->fifo_ul, (unsigned char *)buffer, count); /* notify card */ if (unlikely(dc == NULL)) { @@ -1721,7 +1720,7 @@ static int ntty_write_room(struct tty_struct *tty) if (!port->port.count) goto exit; - room = port->fifo_ul->size - __kfifo_len(port->fifo_ul); + room = port->fifo_ul.size - __kfifo_len(&port->fifo_ul); exit: mutex_unlock(&port->tty_sem); @@ -1878,7 +1877,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) goto exit_in_buffer; } - rval = __kfifo_len(port->fifo_ul); + rval = __kfifo_len(&port->fifo_ul); exit_in_buffer: return rval; diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 8c262aaf7c2..9e6efb1f029 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -487,7 +487,7 @@ static struct sonypi_device { int camera_power; int bluetooth_power; struct mutex lock; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; wait_queue_head_t fifo_proc_list; struct fasync_struct *fifo_async; @@ -496,7 +496,7 @@ static struct sonypi_device { struct input_dev *input_jog_dev; struct input_dev *input_key_dev; struct work_struct input_work; - struct kfifo *input_fifo; + struct kfifo input_fifo; spinlock_t input_fifo_lock; } sonypi_device; @@ -777,7 +777,7 @@ static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; - while (kfifo_get(sonypi_device.input_fifo, (unsigned char *)&kp, + while (kfifo_get(&sonypi_device.input_fifo, (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { msleep(10); input_report_key(kp.dev, kp.key, 0); @@ -827,7 +827,7 @@ static void sonypi_report_input_event(u8 event) if (kp.dev) { input_report_key(kp.dev, kp.key, 1); input_sync(kp.dev); - kfifo_put(sonypi_device.input_fifo, + kfifo_put(&sonypi_device.input_fifo, (unsigned char *)&kp, sizeof(kp)); schedule_work(&sonypi_device.input_work); } @@ -880,7 +880,7 @@ found: acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event); #endif - kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); + kfifo_put(&sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_device.fifo_proc_list); @@ -906,7 +906,7 @@ static int sonypi_misc_open(struct inode *inode, struct file *file) mutex_lock(&sonypi_device.lock); /* Flush input queue on first open */ if (!sonypi_device.open_count) - kfifo_reset(sonypi_device.fifo); + kfifo_reset(&sonypi_device.fifo); sonypi_device.open_count++; mutex_unlock(&sonypi_device.lock); unlock_kernel(); @@ -919,17 +919,17 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, ssize_t ret; unsigned char c; - if ((kfifo_len(sonypi_device.fifo) == 0) && + if ((kfifo_len(&sonypi_device.fifo) == 0) && (file->f_flags & O_NONBLOCK)) return -EAGAIN; ret = wait_event_interruptible(sonypi_device.fifo_proc_list, - kfifo_len(sonypi_device.fifo) != 0); + kfifo_len(&sonypi_device.fifo) != 0); if (ret) return ret; while (ret < count && - (kfifo_get(sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) { + (kfifo_get(&sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; @@ -946,7 +946,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) { poll_wait(file, &sonypi_device.fifo_proc_list, wait); - if (kfifo_len(sonypi_device.fifo)) + if (kfifo_len(&sonypi_device.fifo)) return POLLIN | POLLRDNORM; return 0; } @@ -1313,11 +1313,11 @@ static int __devinit sonypi_probe(struct platform_device *dev) "http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n"); spin_lock_init(&sonypi_device.fifo_lock); - sonypi_device.fifo = kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, + error = kfifo_alloc(&sonypi_device.fifo, SONYPI_BUF_SIZE, GFP_KERNEL, &sonypi_device.fifo_lock); - if (IS_ERR(sonypi_device.fifo)) { + if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - return PTR_ERR(sonypi_device.fifo); + return error; } init_waitqueue_head(&sonypi_device.fifo_proc_list); @@ -1393,12 +1393,10 @@ static int __devinit sonypi_probe(struct platform_device *dev) } spin_lock_init(&sonypi_device.input_fifo_lock); - sonypi_device.input_fifo = - kfifo_alloc(SONYPI_BUF_SIZE, GFP_KERNEL, - &sonypi_device.input_fifo_lock); - if (IS_ERR(sonypi_device.input_fifo)) { + error = kfifo_alloc(&sonypi_device.input_fifo, SONYPI_BUF_SIZE, + GFP_KERNEL, &sonypi_device.input_fifo_lock); + if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); - error = PTR_ERR(sonypi_device.input_fifo); goto err_inpdev_unregister; } @@ -1423,7 +1421,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) pci_disable_device(pcidev); err_put_pcidev: pci_dev_put(pcidev); - kfifo_free(sonypi_device.fifo); + kfifo_free(&sonypi_device.fifo); return error; } @@ -1438,7 +1436,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) if (useinput) { input_unregister_device(sonypi_device.input_key_dev); input_unregister_device(sonypi_device.input_jog_dev); - kfifo_free(sonypi_device.input_fifo); + kfifo_free(&sonypi_device.input_fifo); } misc_deregister(&sonypi_misc_device); @@ -1451,7 +1449,7 @@ static int __devexit sonypi_remove(struct platform_device *dev) pci_dev_put(sonypi_device.dev); } - kfifo_free(sonypi_device.fifo); + kfifo_free(&sonypi_device.fifo); return 0; } diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.h b/drivers/infiniband/hw/cxgb3/cxio_hal.h index bfd03bf8be5..f3d440cc68f 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.h +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.h @@ -34,6 +34,7 @@ #include #include +#include #include "t3_cpl.h" #include "t3cdev.h" @@ -75,13 +76,13 @@ struct cxio_hal_ctrl_qp { }; struct cxio_hal_resource { - struct kfifo *tpt_fifo; + struct kfifo tpt_fifo; spinlock_t tpt_fifo_lock; - struct kfifo *qpid_fifo; + struct kfifo qpid_fifo; spinlock_t qpid_fifo_lock; - struct kfifo *cqid_fifo; + struct kfifo cqid_fifo; spinlock_t cqid_fifo_lock; - struct kfifo *pdid_fifo; + struct kfifo pdid_fifo; spinlock_t pdid_fifo_lock; }; diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index bd233c08765..65072bdfc1b 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c @@ -39,12 +39,12 @@ #include "cxio_resource.h" #include "cxio_hal.h" -static struct kfifo *rhdl_fifo; +static struct kfifo rhdl_fifo; static spinlock_t rhdl_fifo_lock; #define RANDOM_SIZE 16 -static int __cxio_init_resource_fifo(struct kfifo **fifo, +static int __cxio_init_resource_fifo(struct kfifo *fifo, spinlock_t *fifo_lock, u32 nr, u32 skip_low, u32 skip_high, @@ -55,12 +55,11 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo, u32 rarray[16]; spin_lock_init(fifo_lock); - *fifo = kfifo_alloc(nr * sizeof(u32), GFP_KERNEL, fifo_lock); - if (IS_ERR(*fifo)) + if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL, fifo_lock)) return -ENOMEM; for (i = 0; i < skip_low + skip_high; i++) - __kfifo_put(*fifo, (unsigned char *) &entry, sizeof(u32)); + __kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)); if (random) { j = 0; random_bytes = random32(); @@ -72,33 +71,33 @@ static int __cxio_init_resource_fifo(struct kfifo **fifo, random_bytes = random32(); } idx = (random_bytes >> (j * 2)) & 0xF; - __kfifo_put(*fifo, + __kfifo_put(fifo, (unsigned char *) &rarray[idx], sizeof(u32)); rarray[idx] = i; j++; } for (i = 0; i < RANDOM_SIZE; i++) - __kfifo_put(*fifo, + __kfifo_put(fifo, (unsigned char *) &rarray[i], sizeof(u32)); } else for (i = skip_low; i < nr - skip_high; i++) - __kfifo_put(*fifo, (unsigned char *) &i, sizeof(u32)); + __kfifo_put(fifo, (unsigned char *) &i, sizeof(u32)); for (i = 0; i < skip_low + skip_high; i++) - kfifo_get(*fifo, (unsigned char *) &entry, sizeof(u32)); + kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32)); return 0; } -static int cxio_init_resource_fifo(struct kfifo **fifo, spinlock_t * fifo_lock, +static int cxio_init_resource_fifo(struct kfifo *fifo, spinlock_t * fifo_lock, u32 nr, u32 skip_low, u32 skip_high) { return (__cxio_init_resource_fifo(fifo, fifo_lock, nr, skip_low, skip_high, 0)); } -static int cxio_init_resource_fifo_random(struct kfifo **fifo, +static int cxio_init_resource_fifo_random(struct kfifo *fifo, spinlock_t * fifo_lock, u32 nr, u32 skip_low, u32 skip_high) { @@ -113,15 +112,14 @@ static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p) spin_lock_init(&rdev_p->rscp->qpid_fifo_lock); - rdev_p->rscp->qpid_fifo = kfifo_alloc(T3_MAX_NUM_QP * sizeof(u32), + if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, T3_MAX_NUM_QP * sizeof(u32), GFP_KERNEL, - &rdev_p->rscp->qpid_fifo_lock); - if (IS_ERR(rdev_p->rscp->qpid_fifo)) + &rdev_p->rscp->qpid_fifo_lock)) return -ENOMEM; for (i = 16; i < T3_MAX_NUM_QP; i++) if (!(i & rdev_p->qpmask)) - __kfifo_put(rdev_p->rscp->qpid_fifo, + __kfifo_put(&rdev_p->rscp->qpid_fifo, (unsigned char *) &i, sizeof(u32)); return 0; } @@ -134,7 +132,7 @@ int cxio_hal_init_rhdl_resource(u32 nr_rhdl) void cxio_hal_destroy_rhdl_resource(void) { - kfifo_free(rhdl_fifo); + kfifo_free(&rhdl_fifo); } /* nr_* must be power of 2 */ @@ -167,11 +165,11 @@ int cxio_hal_init_resource(struct cxio_rdev *rdev_p, goto pdid_err; return 0; pdid_err: - kfifo_free(rscp->cqid_fifo); + kfifo_free(&rscp->cqid_fifo); cqid_err: - kfifo_free(rscp->qpid_fifo); + kfifo_free(&rscp->qpid_fifo); qpid_err: - kfifo_free(rscp->tpt_fifo); + kfifo_free(&rscp->tpt_fifo); tpt_err: return -ENOMEM; } @@ -195,17 +193,17 @@ static void cxio_hal_put_resource(struct kfifo *fifo, u32 entry) u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(rscp->tpt_fifo); + return cxio_hal_get_resource(&rscp->tpt_fifo); } void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) { - cxio_hal_put_resource(rscp->tpt_fifo, stag); + cxio_hal_put_resource(&rscp->tpt_fifo, stag); } u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) { - u32 qpid = cxio_hal_get_resource(rscp->qpid_fifo); + u32 qpid = cxio_hal_get_resource(&rscp->qpid_fifo); PDBG("%s qpid 0x%x\n", __func__, qpid); return qpid; } @@ -213,35 +211,35 @@ u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) { PDBG("%s qpid 0x%x\n", __func__, qpid); - cxio_hal_put_resource(rscp->qpid_fifo, qpid); + cxio_hal_put_resource(&rscp->qpid_fifo, qpid); } u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(rscp->cqid_fifo); + return cxio_hal_get_resource(&rscp->cqid_fifo); } void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) { - cxio_hal_put_resource(rscp->cqid_fifo, cqid); + cxio_hal_put_resource(&rscp->cqid_fifo, cqid); } u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(rscp->pdid_fifo); + return cxio_hal_get_resource(&rscp->pdid_fifo); } void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) { - cxio_hal_put_resource(rscp->pdid_fifo, pdid); + cxio_hal_put_resource(&rscp->pdid_fifo, pdid); } void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) { - kfifo_free(rscp->tpt_fifo); - kfifo_free(rscp->cqid_fifo); - kfifo_free(rscp->qpid_fifo); - kfifo_free(rscp->pdid_fifo); + kfifo_free(&rscp->tpt_fifo); + kfifo_free(&rscp->cqid_fifo); + kfifo_free(&rscp->qpid_fifo); + kfifo_free(&rscp->pdid_fifo); kfree(rscp); } diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 6ffa64cd1c6..dacbbb839b9 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -800,7 +800,7 @@ again: return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { - if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, + if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, sizeof(int)) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; @@ -811,7 +811,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); wake_up_interruptible(&meye.proc_list); } else { int size; @@ -820,7 +820,7 @@ again: mchip_free_frame(); goto again; } - if (kfifo_get(meye.grabq, (unsigned char *)&reqnr, + if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, sizeof(int)) != sizeof(int)) { mchip_free_frame(); goto again; @@ -831,7 +831,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); wake_up_interruptible(&meye.proc_list); } mchip_free_frame(); @@ -859,8 +859,8 @@ static int meye_open(struct file *file) for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; - kfifo_reset(meye.grabq); - kfifo_reset(meye.doneq); + kfifo_reset(&meye.grabq); + kfifo_reset(&meye.doneq); return 0; } @@ -933,7 +933,7 @@ static int meyeioc_qbuf_capt(int *nb) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)nb, sizeof(int)); + kfifo_put(&meye.grabq, (unsigned char *)nb, sizeof(int)); mutex_unlock(&meye.lock); return 0; @@ -965,7 +965,7 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get(meye.doneq, (unsigned char *)&unused, sizeof(int)); + kfifo_get(&meye.doneq, (unsigned char *)&unused, sizeof(int)); } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); @@ -1452,7 +1452,7 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put(meye.grabq, (unsigned char *)&buf->index, sizeof(int)); + kfifo_put(&meye.grabq, (unsigned char *)&buf->index, sizeof(int)); mutex_unlock(&meye.lock); return 0; @@ -1467,18 +1467,18 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) mutex_lock(&meye.lock); - if (kfifo_len(meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { + if (kfifo_len(&meye.doneq) == 0 && file->f_flags & O_NONBLOCK) { mutex_unlock(&meye.lock); return -EAGAIN; } if (wait_event_interruptible(meye.proc_list, - kfifo_len(meye.doneq) != 0) < 0) { + kfifo_len(&meye.doneq) != 0) < 0) { mutex_unlock(&meye.lock); return -EINTR; } - if (!kfifo_get(meye.doneq, (unsigned char *)&reqnr, + if (!kfifo_get(&meye.doneq, (unsigned char *)&reqnr, sizeof(int))) { mutex_unlock(&meye.lock); return -EBUSY; @@ -1529,8 +1529,8 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i) { mutex_lock(&meye.lock); mchip_hic_stop(); - kfifo_reset(meye.grabq); - kfifo_reset(meye.doneq); + kfifo_reset(&meye.grabq); + kfifo_reset(&meye.doneq); for (i = 0; i < MEYE_MAX_BUFNBRS; i++) meye.grab_buffer[i].state = MEYE_BUF_UNUSED; @@ -1572,7 +1572,7 @@ static unsigned int meye_poll(struct file *file, poll_table *wait) mutex_lock(&meye.lock); poll_wait(file, &meye.proc_list, wait); - if (kfifo_len(meye.doneq)) + if (kfifo_len(&meye.doneq)) res = POLLIN | POLLRDNORM; mutex_unlock(&meye.lock); return res; @@ -1745,16 +1745,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, } spin_lock_init(&meye.grabq_lock); - meye.grabq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.grabq_lock); - if (IS_ERR(meye.grabq)) { + if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, + &meye.grabq_lock)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc1; } spin_lock_init(&meye.doneq_lock); - meye.doneq = kfifo_alloc(sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.doneq_lock); - if (IS_ERR(meye.doneq)) { + if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, + &meye.doneq_lock)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc2; } @@ -1868,9 +1866,9 @@ outregions: outenabledev: sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); outsonypienable: - kfifo_free(meye.doneq); + kfifo_free(&meye.doneq); outkfifoalloc2: - kfifo_free(meye.grabq); + kfifo_free(&meye.grabq); outkfifoalloc1: vfree(meye.grab_temp); outvmalloc: @@ -1901,8 +1899,8 @@ static void __devexit meye_remove(struct pci_dev *pcidev) sony_pic_camera_command(SONY_PIC_COMMAND_SETCAMERA, 0); - kfifo_free(meye.doneq); - kfifo_free(meye.grabq); + kfifo_free(&meye.doneq); + kfifo_free(&meye.grabq); vfree(meye.grab_temp); diff --git a/drivers/media/video/meye.h b/drivers/media/video/meye.h index 5f70a106ba2..1321ad5d659 100644 --- a/drivers/media/video/meye.h +++ b/drivers/media/video/meye.h @@ -303,9 +303,9 @@ struct meye { struct meye_grab_buffer grab_buffer[MEYE_MAX_BUFNBRS]; int vma_use_count[MEYE_MAX_BUFNBRS]; /* mmap count */ struct mutex lock; /* mutex for open/mmap... */ - struct kfifo *grabq; /* queue for buffers to be grabbed */ + struct kfifo grabq; /* queue for buffers to be grabbed */ spinlock_t grabq_lock; /* lock protecting the queue */ - struct kfifo *doneq; /* queue for grabbed buffers */ + struct kfifo doneq; /* queue for grabbed buffers */ spinlock_t doneq_lock; /* lock protecting the queue */ wait_queue_head_t proc_list; /* wait queue */ struct video_device *video_dev; /* video device parameters */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index b9b371bfa30..ffed17f4f50 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1365,7 +1365,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) priv->dnld_sent = DNLD_RES_RECEIVED; /* If nothing to do, go back to sleep (?) */ - if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) + if (!__kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) priv->psstate = PS_STATE_SLEEP; spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -1439,7 +1439,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) } /* Pending events or command responses? */ - if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { + if (__kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) { allowed = 0; lbs_deb_host("pending events or command responses\n"); } diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 6a8d2b291d8..05bb298dfae 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h @@ -10,7 +10,7 @@ #include "scan.h" #include "assoc.h" - +#include /** sleep_params */ struct sleep_params { @@ -120,7 +120,7 @@ struct lbs_private { u32 resp_len[2]; /* Events sent from hardware to driver */ - struct kfifo *event_fifo; + struct kfifo event_fifo; /** thread to service interrupts */ struct task_struct *main_thread; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index db38a5a719f..40390928741 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -459,7 +459,7 @@ static int lbs_thread(void *data) else if (!list_empty(&priv->cmdpendingq) && !(priv->wakeup_dev_required)) shouldsleep = 0; /* We have a command to send */ - else if (__kfifo_len(priv->event_fifo)) + else if (__kfifo_len(&priv->event_fifo)) shouldsleep = 0; /* We have an event to process */ else shouldsleep = 1; /* No command */ @@ -511,9 +511,9 @@ static int lbs_thread(void *data) /* Process hardware events, e.g. card removed, link lost */ spin_lock_irq(&priv->driver_lock); - while (__kfifo_len(priv->event_fifo)) { + while (__kfifo_len(&priv->event_fifo)) { u32 event; - __kfifo_get(priv->event_fifo, (unsigned char *) &event, + __kfifo_get(&priv->event_fifo, (unsigned char *) &event, sizeof(event)); spin_unlock_irq(&priv->driver_lock); lbs_process_event(priv, event); @@ -883,10 +883,9 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->resp_len[0] = priv->resp_len[1] = 0; /* Create the event FIFO */ - priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); - if (IS_ERR(priv->event_fifo)) { + ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL, NULL); + if (ret) { lbs_pr_err("Out of memory allocating event FIFO buffer\n"); - ret = -ENOMEM; goto out; } @@ -901,8 +900,7 @@ static void lbs_free_adapter(struct lbs_private *priv) lbs_deb_enter(LBS_DEB_MAIN); lbs_free_cmd_buffer(priv); - if (priv->event_fifo) - kfifo_free(priv->event_fifo); + kfifo_free(&priv->event_fifo); del_timer(&priv->command_timer); del_timer(&priv->auto_deepsleep_timer); kfree(priv->networks); @@ -1177,7 +1175,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event) if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; - __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); + __kfifo_put(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); wake_up_interruptible(&priv->waitq); diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index bcd4ba8be7d..f999fba0e25 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -164,7 +164,7 @@ struct fujitsu_hotkey_t { struct input_dev *input; char phys[32]; struct platform_device *pf_device; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; int rfkill_supported; int rfkill_state; @@ -824,12 +824,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) /* kfifo */ spin_lock_init(&fujitsu_hotkey->fifo_lock); - fujitsu_hotkey->fifo = - kfifo_alloc(RINGBUFFERSIZE * sizeof(int), GFP_KERNEL, - &fujitsu_hotkey->fifo_lock); - if (IS_ERR(fujitsu_hotkey->fifo)) { + error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int), + GFP_KERNEL, &fujitsu_hotkey->fifo_lock); + if (error) { printk(KERN_ERR "kfifo_alloc failed\n"); - error = PTR_ERR(fujitsu_hotkey->fifo); goto err_stop; } @@ -934,7 +932,7 @@ err_unregister_input_dev: err_free_input_dev: input_free_device(input); err_free_fifo: - kfifo_free(fujitsu_hotkey->fifo); + kfifo_free(&fujitsu_hotkey->fifo); err_stop: return result; } @@ -956,7 +954,7 @@ static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type) input_free_device(input); - kfifo_free(fujitsu_hotkey->fifo); + kfifo_free(&fujitsu_hotkey->fifo); fujitsu_hotkey->acpi_handle = NULL; @@ -1008,7 +1006,7 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) vdbg_printk(FUJLAPTOP_DBG_TRACE, "Push keycode into ringbuffer [%d]\n", keycode); - status = kfifo_put(fujitsu_hotkey->fifo, + status = kfifo_put(&fujitsu_hotkey->fifo, (unsigned char *)&keycode, sizeof(keycode)); if (status != sizeof(keycode)) { @@ -1022,7 +1020,7 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) } else if (keycode == 0) { while ((status = kfifo_get - (fujitsu_hotkey->fifo, (unsigned char *) + (&fujitsu_hotkey->fifo, (unsigned char *) &keycode_r, sizeof (keycode_r))) == sizeof(keycode_r)) { diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 7a2cc8a5c97..04625a048e7 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -142,7 +142,7 @@ struct sony_laptop_input_s { atomic_t users; struct input_dev *jog_dev; struct input_dev *key_dev; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; struct workqueue_struct *wq; }; @@ -300,7 +300,7 @@ static void do_sony_laptop_release_key(struct work_struct *work) { struct sony_laptop_keypress kp; - while (kfifo_get(sony_laptop_input.fifo, (unsigned char *)&kp, + while (kfifo_get(&sony_laptop_input.fifo, (unsigned char *)&kp, sizeof(kp)) == sizeof(kp)) { msleep(10); input_report_key(kp.dev, kp.key, 0); @@ -362,7 +362,7 @@ static void sony_laptop_report_input_event(u8 event) /* we emit the scancode so we can always remap the key */ input_event(kp.dev, EV_MSC, MSC_SCAN, event); input_sync(kp.dev); - kfifo_put(sony_laptop_input.fifo, + kfifo_put(&sony_laptop_input.fifo, (unsigned char *)&kp, sizeof(kp)); if (!work_pending(&sony_laptop_release_key_work)) @@ -385,12 +385,11 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) /* kfifo */ spin_lock_init(&sony_laptop_input.fifo_lock); - sony_laptop_input.fifo = - kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, + error = + kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, &sony_laptop_input.fifo_lock); - if (IS_ERR(sony_laptop_input.fifo)) { + if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); - error = PTR_ERR(sony_laptop_input.fifo); goto err_dec_users; } @@ -474,7 +473,7 @@ err_destroy_wq: destroy_workqueue(sony_laptop_input.wq); err_free_kfifo: - kfifo_free(sony_laptop_input.fifo); + kfifo_free(&sony_laptop_input.fifo); err_dec_users: atomic_dec(&sony_laptop_input.users); @@ -500,7 +499,7 @@ static void sony_laptop_remove_input(void) } destroy_workqueue(sony_laptop_input.wq); - kfifo_free(sony_laptop_input.fifo); + kfifo_free(&sony_laptop_input.fifo); } /*********** Platform Device ***********/ @@ -2079,7 +2078,7 @@ static struct attribute_group spic_attribute_group = { struct sonypi_compat_s { struct fasync_struct *fifo_async; - struct kfifo *fifo; + struct kfifo fifo; spinlock_t fifo_lock; wait_queue_head_t fifo_proc_list; atomic_t open_count; @@ -2104,12 +2103,12 @@ static int sonypi_misc_open(struct inode *inode, struct file *file) /* Flush input queue on first open */ unsigned long flags; - spin_lock_irqsave(sonypi_compat.fifo->lock, flags); + spin_lock_irqsave(&sonypi_compat.fifo_lock, flags); if (atomic_inc_return(&sonypi_compat.open_count) == 1) - __kfifo_reset(sonypi_compat.fifo); + __kfifo_reset(&sonypi_compat.fifo); - spin_unlock_irqrestore(sonypi_compat.fifo->lock, flags); + spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags); return 0; } @@ -2120,17 +2119,17 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, ssize_t ret; unsigned char c; - if ((kfifo_len(sonypi_compat.fifo) == 0) && + if ((kfifo_len(&sonypi_compat.fifo) == 0) && (file->f_flags & O_NONBLOCK)) return -EAGAIN; ret = wait_event_interruptible(sonypi_compat.fifo_proc_list, - kfifo_len(sonypi_compat.fifo) != 0); + kfifo_len(&sonypi_compat.fifo) != 0); if (ret) return ret; while (ret < count && - (kfifo_get(sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { + (kfifo_get(&sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; @@ -2147,7 +2146,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, static unsigned int sonypi_misc_poll(struct file *file, poll_table *wait) { poll_wait(file, &sonypi_compat.fifo_proc_list, wait); - if (kfifo_len(sonypi_compat.fifo)) + if (kfifo_len(&sonypi_compat.fifo)) return POLLIN | POLLRDNORM; return 0; } @@ -2309,7 +2308,7 @@ static struct miscdevice sonypi_misc_device = { static void sonypi_compat_report_event(u8 event) { - kfifo_put(sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); + kfifo_put(&sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_compat.fifo_proc_list); } @@ -2319,11 +2318,12 @@ static int sonypi_compat_init(void) int error; spin_lock_init(&sonypi_compat.fifo_lock); - sonypi_compat.fifo = kfifo_alloc(SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, + error = + kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, &sonypi_compat.fifo_lock); - if (IS_ERR(sonypi_compat.fifo)) { + if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); - return PTR_ERR(sonypi_compat.fifo); + return error; } init_waitqueue_head(&sonypi_compat.fifo_proc_list); @@ -2342,14 +2342,14 @@ static int sonypi_compat_init(void) return 0; err_free_kfifo: - kfifo_free(sonypi_compat.fifo); + kfifo_free(&sonypi_compat.fifo); return error; } static void sonypi_compat_exit(void) { misc_deregister(&sonypi_misc_device); - kfifo_free(sonypi_compat.fifo); + kfifo_free(&sonypi_compat.fifo); } #else static int sonypi_compat_init(void) { return 0; } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index b7689f3d05f..cf0aa7e90be 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -517,7 +517,7 @@ static void iscsi_free_task(struct iscsi_task *task) if (conn->login_task == task) return; - __kfifo_put(session->cmdpool.queue, (void*)&task, sizeof(void*)); + __kfifo_put(&session->cmdpool.queue, (void*)&task, sizeof(void*)); if (sc) { task->sc = NULL; @@ -737,7 +737,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); - if (!__kfifo_get(session->cmdpool.queue, + if (!__kfifo_get(&session->cmdpool.queue, (void*)&task, sizeof(void*))) return NULL; } @@ -1567,7 +1567,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, { struct iscsi_task *task; - if (!__kfifo_get(conn->session->cmdpool.queue, + if (!__kfifo_get(&conn->session->cmdpool.queue, (void *) &task, sizeof(void *))) return NULL; @@ -2461,12 +2461,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) if (q->pool == NULL) return -ENOMEM; - q->queue = kfifo_init((void*)q->pool, max * sizeof(void*), - GFP_KERNEL, NULL); - if (IS_ERR(q->queue)) { - q->queue = NULL; - goto enomem; - } + kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*), NULL); for (i = 0; i < max; i++) { q->pool[i] = kzalloc(item_size, GFP_KERNEL); @@ -2474,7 +2469,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) q->max = i; goto enomem; } - __kfifo_put(q->queue, (void*)&q->pool[i], sizeof(void*)); + __kfifo_put(&q->queue, (void*)&q->pool[i], sizeof(void*)); } if (items) { @@ -2497,7 +2492,6 @@ void iscsi_pool_free(struct iscsi_pool *q) for (i = 0; i < q->max; i++) kfree(q->pool[i]); kfree(q->pool); - kfree(q->queue); } EXPORT_SYMBOL_GPL(iscsi_pool_free); @@ -2825,7 +2819,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, /* allocate login_task used for the login/text sequences */ spin_lock_bh(&session->lock); - if (!__kfifo_get(session->cmdpool.queue, + if (!__kfifo_get(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*))) { spin_unlock_bh(&session->lock); @@ -2845,7 +2839,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, return cls_conn; login_task_data_alloc_fail: - __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, + __kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); login_task_alloc_fail: iscsi_destroy_conn(cls_conn); @@ -2908,7 +2902,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) free_pages((unsigned long) conn->data, get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); kfree(conn->persistent_address); - __kfifo_put(session->cmdpool.queue, (void*)&conn->login_task, + __kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); if (session->leadconn == conn) session->leadconn = NULL; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index ca25ee5190b..a83ee56a185 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -445,15 +445,15 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task) return; /* flush task's r2t queues */ - while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + while (__kfifo_get(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { + __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n"); } r2t = tcp_task->r2t; if (r2t != NULL) { - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); tcp_task->r2t = NULL; } @@ -541,7 +541,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) return 0; } - rc = __kfifo_get(tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); + rc = __kfifo_get(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); if (!rc) { iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. " "Target has sent more R2Ts than it " @@ -554,7 +554,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) if (r2t->data_length == 0) { iscsi_conn_printk(KERN_ERR, conn, "invalid R2T with zero data len\n"); - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -570,7 +570,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) "invalid R2T with data len %u at offset %u " "and total length %d\n", r2t->data_length, r2t->data_offset, scsi_out(task->sc)->length); - __kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t, + __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -580,7 +580,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) r2t->sent = 0; tcp_task->exp_datasn = r2tsn + 1; - __kfifo_put(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); + __kfifo_put(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); conn->r2t_pdus_cnt++; iscsi_requeue_task(task); @@ -951,7 +951,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task) return conn->session->tt->init_pdu(task, 0, task->data_count); } - BUG_ON(__kfifo_len(tcp_task->r2tqueue)); + BUG_ON(__kfifo_len(&tcp_task->r2tqueue)); tcp_task->exp_datasn = 0; /* Prepare PDU, optionally w/ immediate data */ @@ -982,7 +982,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) if (r2t->data_length <= r2t->sent) { ISCSI_DBG_TCP(task->conn, " done with r2t %p\n", r2t); - __kfifo_put(tcp_task->r2tpool.queue, + __kfifo_put(&tcp_task->r2tpool.queue, (void *)&tcp_task->r2t, sizeof(void *)); tcp_task->r2t = r2t = NULL; @@ -990,7 +990,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) } if (r2t == NULL) { - __kfifo_get(tcp_task->r2tqueue, + __kfifo_get(&tcp_task->r2tqueue, (void *)&tcp_task->r2t, sizeof(void *)); r2t = tcp_task->r2t; } @@ -1127,9 +1127,8 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session) } /* R2T xmit queue */ - tcp_task->r2tqueue = kfifo_alloc( - session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL); - if (tcp_task->r2tqueue == ERR_PTR(-ENOMEM)) { + if (kfifo_alloc(&tcp_task->r2tqueue, + session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL)) { iscsi_pool_free(&tcp_task->r2tpool); goto r2t_alloc_fail; } @@ -1142,7 +1141,7 @@ r2t_alloc_fail: struct iscsi_task *task = session->cmds[i]; struct iscsi_tcp_task *tcp_task = task->dd_data; - kfifo_free(tcp_task->r2tqueue); + kfifo_free(&tcp_task->r2tqueue); iscsi_pool_free(&tcp_task->r2tpool); } return -ENOMEM; @@ -1157,7 +1156,7 @@ void iscsi_tcp_r2tpool_free(struct iscsi_session *session) struct iscsi_task *task = session->cmds[i]; struct iscsi_tcp_task *tcp_task = task->dd_data; - kfifo_free(tcp_task->r2tqueue); + kfifo_free(&tcp_task->r2tqueue); iscsi_pool_free(&tcp_task->r2tpool); } } diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 9ad38e81e34..b1b5e51ca8e 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -58,19 +58,16 @@ static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, goto free_pool; spin_lock_init(&q->lock); - q->queue = kfifo_init((void *) q->pool, max * sizeof(void *), - GFP_KERNEL, &q->lock); - if (IS_ERR(q->queue)) - goto free_item; + kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *), + &q->lock); for (i = 0, iue = q->items; i < max; i++) { - __kfifo_put(q->queue, (void *) &iue, sizeof(void *)); + __kfifo_put(&q->queue, (void *) &iue, sizeof(void *)); iue->sbuf = ring[i]; iue++; } return 0; -free_item: kfree(q->items); free_pool: kfree(q->pool); @@ -167,7 +164,7 @@ struct iu_entry *srp_iu_get(struct srp_target *target) { struct iu_entry *iue = NULL; - kfifo_get(target->iu_queue.queue, (void *) &iue, sizeof(void *)); + kfifo_get(&target->iu_queue.queue, (void *) &iue, sizeof(void *)); if (!iue) return iue; iue->target = target; @@ -179,7 +176,7 @@ EXPORT_SYMBOL_GPL(srp_iu_get); void srp_iu_put(struct iu_entry *iue) { - kfifo_put(iue->target->iu_queue.queue, (void *) &iue, sizeof(void *)); + kfifo_put(&iue->target->iu_queue.queue, (void *) &iue, sizeof(void *)); } EXPORT_SYMBOL_GPL(srp_iu_put); diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 00a29855d0c..ff43747a614 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c @@ -37,7 +37,7 @@ static void recycle_frame(struct fhci_usb *usb, struct packet *pkt) pkt->info = 0; pkt->priv_data = NULL; - cq_put(usb->ep0->empty_frame_Q, pkt); + cq_put(&usb->ep0->empty_frame_Q, pkt); } /* confirm submitted packet */ @@ -57,7 +57,7 @@ void fhci_transaction_confirm(struct fhci_usb *usb, struct packet *pkt) if ((td->data + td->actual_len) && trans_len) memcpy(td->data + td->actual_len, pkt->data, trans_len); - cq_put(usb->ep0->dummy_packets_Q, pkt->data); + cq_put(&usb->ep0->dummy_packets_Q, pkt->data); } recycle_frame(usb, pkt); @@ -213,7 +213,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) } /* update frame object fields before transmitting */ - pkt = cq_get(usb->ep0->empty_frame_Q); + pkt = cq_get(&usb->ep0->empty_frame_Q); if (!pkt) { fhci_dbg(usb->fhci, "there is no empty frame\n"); return -1; @@ -222,7 +222,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) pkt->info = 0; if (data == NULL) { - data = cq_get(usb->ep0->dummy_packets_Q); + data = cq_get(&usb->ep0->dummy_packets_Q); BUG_ON(!data); pkt->info = PKT_DUMMY_PACKET; } @@ -246,7 +246,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td) list_del_init(&td->frame_lh); td->status = USB_TD_OK; if (pkt->info & PKT_DUMMY_PACKET) - cq_put(usb->ep0->dummy_packets_Q, pkt->data); + cq_put(&usb->ep0->dummy_packets_Q, pkt->data); recycle_frame(usb, pkt); usb->actual_frame->total_bytes -= (len + PROTOCOL_OVERHEAD); fhci_err(usb->fhci, "host transaction failed\n"); diff --git a/drivers/usb/host/fhci-tds.c b/drivers/usb/host/fhci-tds.c index b4033229031..d224ab467a4 100644 --- a/drivers/usb/host/fhci-tds.c +++ b/drivers/usb/host/fhci-tds.c @@ -106,33 +106,33 @@ void fhci_ep0_free(struct fhci_usb *usb) cpm_muram_free(cpm_muram_offset(ep->td_base)); if (ep->conf_frame_Q) { - size = cq_howmany(ep->conf_frame_Q); + size = cq_howmany(&ep->conf_frame_Q); for (; size; size--) { - struct packet *pkt = cq_get(ep->conf_frame_Q); + struct packet *pkt = cq_get(&ep->conf_frame_Q); kfree(pkt); } - cq_delete(ep->conf_frame_Q); + cq_delete(&ep->conf_frame_Q); } if (ep->empty_frame_Q) { - size = cq_howmany(ep->empty_frame_Q); + size = cq_howmany(&ep->empty_frame_Q); for (; size; size--) { - struct packet *pkt = cq_get(ep->empty_frame_Q); + struct packet *pkt = cq_get(&ep->empty_frame_Q); kfree(pkt); } - cq_delete(ep->empty_frame_Q); + cq_delete(&ep->empty_frame_Q); } if (ep->dummy_packets_Q) { - size = cq_howmany(ep->dummy_packets_Q); + size = cq_howmany(&ep->dummy_packets_Q); for (; size; size--) { - u8 *buff = cq_get(ep->dummy_packets_Q); + u8 *buff = cq_get(&ep->dummy_packets_Q); kfree(buff); } - cq_delete(ep->dummy_packets_Q); + cq_delete(&ep->dummy_packets_Q); } kfree(ep); @@ -175,10 +175,9 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, ep->td_base = cpm_muram_addr(ep_offset); /* zero all queue pointers */ - ep->conf_frame_Q = cq_new(ring_len + 2); - ep->empty_frame_Q = cq_new(ring_len + 2); - ep->dummy_packets_Q = cq_new(ring_len + 2); - if (!ep->conf_frame_Q || !ep->empty_frame_Q || !ep->dummy_packets_Q) { + if (cq_new(&ep->conf_frame_Q, ring_len + 2) || + cq_new(&ep->empty_frame_Q, ring_len + 2) || + cq_new(&ep->dummy_packets_Q, ring_len + 2)) { err_for = "frame_queues"; goto err; } @@ -199,8 +198,8 @@ u32 fhci_create_ep(struct fhci_usb *usb, enum fhci_mem_alloc data_mem, err_for = "buffer"; goto err; } - cq_put(ep->empty_frame_Q, pkt); - cq_put(ep->dummy_packets_Q, buff); + cq_put(&ep->empty_frame_Q, pkt); + cq_put(&ep->dummy_packets_Q, buff); } /* we put the endpoint parameter RAM right behind the TD ring */ @@ -319,7 +318,7 @@ static void fhci_td_transaction_confirm(struct fhci_usb *usb) if ((buf == DUMMY2_BD_BUFFER) && !(td_status & ~TD_W)) continue; - pkt = cq_get(ep->conf_frame_Q); + pkt = cq_get(&ep->conf_frame_Q); if (!pkt) fhci_err(usb->fhci, "no frame to confirm\n"); @@ -460,9 +459,9 @@ u32 fhci_host_transaction(struct fhci_usb *usb, out_be16(&td->length, pkt->len); /* put the frame to the confirmation queue */ - cq_put(ep->conf_frame_Q, pkt); + cq_put(&ep->conf_frame_Q, pkt); - if (cq_howmany(ep->conf_frame_Q) == 1) + if (cq_howmany(&ep->conf_frame_Q) == 1) out_8(&usb->fhci->regs->usb_comm, USB_CMD_STR_FIFO); return 0; diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index 7116284ed21..2277428ef5d 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h @@ -423,9 +423,9 @@ struct endpoint { struct usb_td __iomem *td_base; /* first TD in the ring */ struct usb_td __iomem *conf_td; /* next TD for confirm after transac */ struct usb_td __iomem *empty_td;/* next TD for new transaction req. */ - struct kfifo *empty_frame_Q; /* Empty frames list to use */ - struct kfifo *conf_frame_Q; /* frames passed to TDs,waiting for tx */ - struct kfifo *dummy_packets_Q;/* dummy packets for the CRC overun */ + struct kfifo empty_frame_Q; /* Empty frames list to use */ + struct kfifo conf_frame_Q; /* frames passed to TDs,waiting for tx */ + struct kfifo dummy_packets_Q;/* dummy packets for the CRC overun */ bool already_pushed_dummy_bd; }; @@ -493,9 +493,9 @@ static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci) } /* fifo of pointers */ -static inline struct kfifo *cq_new(int size) +static inline int cq_new(struct kfifo *fifo, int size) { - return kfifo_alloc(size * sizeof(void *), GFP_KERNEL, NULL); + return kfifo_alloc(fifo, size * sizeof(void *), GFP_KERNEL, NULL); } static inline void cq_delete(struct kfifo *kfifo) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 4543f359be7..44b72d47fac 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -939,9 +939,8 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "No free urbs available\n"); goto probe_error; } - port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL, - &port->lock); - if (IS_ERR(port->write_fifo)) + if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL, + &port->lock)) goto probe_error; buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->bulk_out_size = buffer_size; diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index ad6bdf5a597..c3f8d82efd3 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -1,6 +1,7 @@ /* - * A simple kernel FIFO implementation. + * A generic kernel FIFO implementation. * + * Copyright (C) 2009 Stefani Seibold * Copyright (C) 2004 Stelian Pop * * This program is free software; you can redistribute it and/or modify @@ -32,10 +33,10 @@ struct kfifo { spinlock_t *lock; /* protects concurrent modifications */ }; -extern struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, - gfp_t gfp_mask, spinlock_t *lock); -extern struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, - spinlock_t *lock); +extern void kfifo_init(struct kfifo *fifo, unsigned char *buffer, + unsigned int size, spinlock_t *lock); +extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, + gfp_t gfp_mask, spinlock_t *lock); extern void kfifo_free(struct kfifo *fifo); extern unsigned int __kfifo_put(struct kfifo *fifo, const unsigned char *buffer, unsigned int len); diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 7394e3bc8f4..ff92b46f515 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -231,7 +232,7 @@ struct iscsi_conn { }; struct iscsi_pool { - struct kfifo *queue; /* FIFO Queue */ + struct kfifo queue; /* FIFO Queue */ void **pool; /* Pool of elements */ int max; /* Max number of elements */ }; diff --git a/include/scsi/libiscsi_tcp.h b/include/scsi/libiscsi_tcp.h index 9e3182e659d..741ae7ed439 100644 --- a/include/scsi/libiscsi_tcp.h +++ b/include/scsi/libiscsi_tcp.h @@ -80,7 +80,7 @@ struct iscsi_tcp_task { int data_offset; struct iscsi_r2t_info *r2t; /* in progress solict R2T */ struct iscsi_pool r2tpool; - struct kfifo *r2tqueue; + struct kfifo r2tqueue; void *dd_data; }; diff --git a/include/scsi/libsrp.h b/include/scsi/libsrp.h index ba615e4c1d7..07e3adde21d 100644 --- a/include/scsi/libsrp.h +++ b/include/scsi/libsrp.h @@ -21,7 +21,7 @@ struct srp_buf { struct srp_queue { void *pool; void *items; - struct kfifo *queue; + struct kfifo queue; spinlock_t lock; }; diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 3765ff3c1bb..8da6bb9782b 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -1,6 +1,7 @@ /* - * A simple kernel FIFO implementation. + * A generic kernel FIFO implementation. * + * Copyright (C) 2009 Stefani Seibold * Copyright (C) 2004 Stelian Pop * * This program is free software; you can redistribute it and/or modify @@ -26,49 +27,51 @@ #include #include +static void _kfifo_init(struct kfifo *fifo, unsigned char *buffer, + unsigned int size, spinlock_t *lock) +{ + fifo->buffer = buffer; + fifo->size = size; + fifo->lock = lock; + + kfifo_reset(fifo); +} + /** - * kfifo_init - allocates a new FIFO using a preallocated buffer + * kfifo_init - initialize a FIFO using a preallocated buffer + * @fifo: the fifo to assign the buffer * @buffer: the preallocated buffer to be used. * @size: the size of the internal buffer, this have to be a power of 2. - * @gfp_mask: get_free_pages mask, passed to kmalloc() * @lock: the lock to be used to protect the fifo buffer * - * Do NOT pass the kfifo to kfifo_free() after use! Simply free the - * &struct kfifo with kfree(). */ -struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size, - gfp_t gfp_mask, spinlock_t *lock) +void kfifo_init(struct kfifo *fifo, unsigned char *buffer, unsigned int size, + spinlock_t *lock) { - struct kfifo *fifo; - /* size must be a power of 2 */ BUG_ON(!is_power_of_2(size)); - fifo = kmalloc(sizeof(struct kfifo), gfp_mask); - if (!fifo) - return ERR_PTR(-ENOMEM); - - fifo->buffer = buffer; - fifo->size = size; - fifo->in = fifo->out = 0; - fifo->lock = lock; - - return fifo; + _kfifo_init(fifo, buffer, size, lock); } EXPORT_SYMBOL(kfifo_init); /** - * kfifo_alloc - allocates a new FIFO and its internal buffer - * @size: the size of the internal buffer to be allocated. + * kfifo_alloc - allocates a new FIFO internal buffer + * @fifo: the fifo to assign then new buffer + * @size: the size of the buffer to be allocated, this have to be a power of 2. * @gfp_mask: get_free_pages mask, passed to kmalloc() * @lock: the lock to be used to protect the fifo buffer * + * This function dynamically allocates a new fifo internal buffer + * * The size will be rounded-up to a power of 2. + * The buffer will be release with kfifo_free(). + * Return 0 if no error, otherwise the an error code */ -struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) +int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask, + spinlock_t *lock) { unsigned char *buffer; - struct kfifo *ret; /* * round up to the next power of 2, since our 'let the indices @@ -80,26 +83,24 @@ struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock) } buffer = kmalloc(size, gfp_mask); - if (!buffer) - return ERR_PTR(-ENOMEM); - - ret = kfifo_init(buffer, size, gfp_mask, lock); + if (!buffer) { + _kfifo_init(fifo, 0, 0, NULL); + return -ENOMEM; + } - if (IS_ERR(ret)) - kfree(buffer); + _kfifo_init(fifo, buffer, size, lock); - return ret; + return 0; } EXPORT_SYMBOL(kfifo_alloc); /** - * kfifo_free - frees the FIFO + * kfifo_free - frees the FIFO internal buffer * @fifo: the fifo to be freed. */ void kfifo_free(struct kfifo *fifo) { kfree(fifo->buffer); - kfree(fifo); } EXPORT_SYMBOL(kfifo_free); diff --git a/net/dccp/probe.c b/net/dccp/probe.c index dc328425fa2..6230ceb0823 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -43,7 +43,7 @@ static int bufsize = 64 * 1024; static const char procname[] = "dccpprobe"; static struct { - struct kfifo *fifo; + struct kfifo fifo; spinlock_t lock; wait_queue_head_t wait; struct timespec tstart; @@ -67,7 +67,7 @@ static void printl(const char *fmt, ...) len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); va_end(args); - kfifo_put(dccpw.fifo, tbuf, len); + kfifo_put(&dccpw.fifo, tbuf, len); wake_up(&dccpw.wait); } @@ -109,7 +109,7 @@ static struct jprobe dccp_send_probe = { static int dccpprobe_open(struct inode *inode, struct file *file) { - kfifo_reset(dccpw.fifo); + kfifo_reset(&dccpw.fifo); getnstimeofday(&dccpw.tstart); return 0; } @@ -131,11 +131,11 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf, return -ENOMEM; error = wait_event_interruptible(dccpw.wait, - __kfifo_len(dccpw.fifo) != 0); + __kfifo_len(&dccpw.fifo) != 0); if (error) goto out_free; - cnt = kfifo_get(dccpw.fifo, tbuf, len); + cnt = kfifo_get(&dccpw.fifo, tbuf, len); error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0; out_free: @@ -156,10 +156,8 @@ static __init int dccpprobe_init(void) init_waitqueue_head(&dccpw.wait); spin_lock_init(&dccpw.lock); - dccpw.fifo = kfifo_alloc(bufsize, GFP_KERNEL, &dccpw.lock); - if (IS_ERR(dccpw.fifo)) - return PTR_ERR(dccpw.fifo); - + if (kfifo_alloc(&dccpw.fifo, bufsize, GFP_KERNEL, &dccpw.lock)) + return ret; if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops)) goto err0; @@ -172,14 +170,14 @@ static __init int dccpprobe_init(void) err1: proc_net_remove(&init_net, procname); err0: - kfifo_free(dccpw.fifo); + kfifo_free(&dccpw.fifo); return ret; } module_init(dccpprobe_init); static __exit void dccpprobe_exit(void) { - kfifo_free(dccpw.fifo); + kfifo_free(&dccpw.fifo); proc_net_remove(&init_net, procname); unregister_jprobe(&dccp_send_probe); -- cgit v1.2.3-70-g09d2 From c1e13f25674ed564948ecb7dfe5f83e578892896 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:27 -0800 Subject: kfifo: move out spinlock Move the pointer to the spinlock out of struct kfifo. Most users in tree do not actually use a spinlock, so the few exceptions now have to call kfifo_{get,put}_locked, which takes an extra argument to a spinlock. Signed-off-by: Stefani Seibold Acked-by: Greg Kroah-Hartman Acked-by: Mauro Carvalho Chehab Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/nozomi.c | 2 +- drivers/char/sonypi.c | 21 ++++---- drivers/infiniband/hw/cxgb3/cxio_resource.c | 36 +++++++------ drivers/media/video/meye.c | 35 +++++++------ drivers/net/wireless/libertas/main.c | 2 +- drivers/platform/x86/fujitsu-laptop.c | 18 ++++--- drivers/platform/x86/sony-laptop.c | 22 ++++---- drivers/scsi/libiscsi.c | 2 +- drivers/scsi/libiscsi_tcp.c | 2 +- drivers/scsi/libsrp.c | 9 ++-- drivers/usb/host/fhci.h | 2 +- drivers/usb/serial/generic.c | 4 +- drivers/usb/serial/usb-serial.c | 3 +- include/linux/kfifo.h | 80 +++++++++++++---------------- kernel/kfifo.c | 17 +++--- net/dccp/probe.c | 6 +-- 16 files changed, 131 insertions(+), 130 deletions(-) (limited to 'drivers') diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 0f39bec28b4..935b30d80ad 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -686,7 +686,7 @@ static int nozomi_read_config_table(struct nozomi *dc) for (i = PORT_MDM; i < MAX_PORT; i++) { kfifo_alloc(&dc->port[i].fifo_ul, - FIFO_BUFFER_SIZE_UL, GFP_ATOMIC, NULL); + FIFO_BUFFER_SIZE_UL, GFP_ATOMIC); memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); } diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index 9e6efb1f029..dbcb3bd192c 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -777,8 +777,9 @@ static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; - while (kfifo_get(&sonypi_device.input_fifo, (unsigned char *)&kp, - sizeof(kp)) == sizeof(kp)) { + while (kfifo_get_locked(&sonypi_device.input_fifo, (unsigned char *)&kp, + sizeof(kp), &sonypi_device.input_fifo_lock) + == sizeof(kp)) { msleep(10); input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); @@ -827,8 +828,9 @@ static void sonypi_report_input_event(u8 event) if (kp.dev) { input_report_key(kp.dev, kp.key, 1); input_sync(kp.dev); - kfifo_put(&sonypi_device.input_fifo, - (unsigned char *)&kp, sizeof(kp)); + kfifo_put_locked(&sonypi_device.input_fifo, + (unsigned char *)&kp, sizeof(kp), + &sonypi_device.input_fifo_lock); schedule_work(&sonypi_device.input_work); } } @@ -880,7 +882,8 @@ found: acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event); #endif - kfifo_put(&sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); + kfifo_put_locked(&sonypi_device.fifo, (unsigned char *)&event, + sizeof(event), &sonypi_device.fifo_lock); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_device.fifo_proc_list); @@ -929,7 +932,8 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, return ret; while (ret < count && - (kfifo_get(&sonypi_device.fifo, &c, sizeof(c)) == sizeof(c))) { + (kfifo_get_locked(&sonypi_device.fifo, &c, sizeof(c), + &sonypi_device.fifo_lock) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; @@ -1313,8 +1317,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) "http://www.linux.it/~malattia/wiki/index.php/Sony_drivers\n"); spin_lock_init(&sonypi_device.fifo_lock); - error = kfifo_alloc(&sonypi_device.fifo, SONYPI_BUF_SIZE, GFP_KERNEL, - &sonypi_device.fifo_lock); + error = kfifo_alloc(&sonypi_device.fifo, SONYPI_BUF_SIZE, GFP_KERNEL); if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); return error; @@ -1394,7 +1397,7 @@ static int __devinit sonypi_probe(struct platform_device *dev) spin_lock_init(&sonypi_device.input_fifo_lock); error = kfifo_alloc(&sonypi_device.input_fifo, SONYPI_BUF_SIZE, - GFP_KERNEL, &sonypi_device.input_fifo_lock); + GFP_KERNEL); if (error) { printk(KERN_ERR "sonypi: kfifo_alloc failed\n"); goto err_inpdev_unregister; diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index 65072bdfc1b..98f24e6d906 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c @@ -55,7 +55,7 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, u32 rarray[16]; spin_lock_init(fifo_lock); - if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL, fifo_lock)) + if (kfifo_alloc(fifo, nr * sizeof(u32), GFP_KERNEL)) return -ENOMEM; for (i = 0; i < skip_low + skip_high; i++) @@ -86,7 +86,8 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, __kfifo_put(fifo, (unsigned char *) &i, sizeof(u32)); for (i = 0; i < skip_low + skip_high; i++) - kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32)); + kfifo_get_locked(fifo, (unsigned char *) &entry, + sizeof(u32), fifo_lock); return 0; } @@ -113,8 +114,7 @@ static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p) spin_lock_init(&rdev_p->rscp->qpid_fifo_lock); if (kfifo_alloc(&rdev_p->rscp->qpid_fifo, T3_MAX_NUM_QP * sizeof(u32), - GFP_KERNEL, - &rdev_p->rscp->qpid_fifo_lock)) + GFP_KERNEL)) return -ENOMEM; for (i = 16; i < T3_MAX_NUM_QP; i++) @@ -177,33 +177,37 @@ tpt_err: /* * returns 0 if no resource available */ -static u32 cxio_hal_get_resource(struct kfifo *fifo) +static u32 cxio_hal_get_resource(struct kfifo *fifo, spinlock_t * lock) { u32 entry; - if (kfifo_get(fifo, (unsigned char *) &entry, sizeof(u32))) + if (kfifo_get_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock)) return entry; else return 0; /* fifo emptry */ } -static void cxio_hal_put_resource(struct kfifo *fifo, u32 entry) +static void cxio_hal_put_resource(struct kfifo *fifo, spinlock_t * lock, + u32 entry) { - BUG_ON(kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)) == 0); + BUG_ON( + kfifo_put_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock) + == 0); } u32 cxio_hal_get_stag(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(&rscp->tpt_fifo); + return cxio_hal_get_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock); } void cxio_hal_put_stag(struct cxio_hal_resource *rscp, u32 stag) { - cxio_hal_put_resource(&rscp->tpt_fifo, stag); + cxio_hal_put_resource(&rscp->tpt_fifo, &rscp->tpt_fifo_lock, stag); } u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) { - u32 qpid = cxio_hal_get_resource(&rscp->qpid_fifo); + u32 qpid = cxio_hal_get_resource(&rscp->qpid_fifo, + &rscp->qpid_fifo_lock); PDBG("%s qpid 0x%x\n", __func__, qpid); return qpid; } @@ -211,27 +215,27 @@ u32 cxio_hal_get_qpid(struct cxio_hal_resource *rscp) void cxio_hal_put_qpid(struct cxio_hal_resource *rscp, u32 qpid) { PDBG("%s qpid 0x%x\n", __func__, qpid); - cxio_hal_put_resource(&rscp->qpid_fifo, qpid); + cxio_hal_put_resource(&rscp->qpid_fifo, &rscp->qpid_fifo_lock, qpid); } u32 cxio_hal_get_cqid(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(&rscp->cqid_fifo); + return cxio_hal_get_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock); } void cxio_hal_put_cqid(struct cxio_hal_resource *rscp, u32 cqid) { - cxio_hal_put_resource(&rscp->cqid_fifo, cqid); + cxio_hal_put_resource(&rscp->cqid_fifo, &rscp->cqid_fifo_lock, cqid); } u32 cxio_hal_get_pdid(struct cxio_hal_resource *rscp) { - return cxio_hal_get_resource(&rscp->pdid_fifo); + return cxio_hal_get_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock); } void cxio_hal_put_pdid(struct cxio_hal_resource *rscp, u32 pdid) { - cxio_hal_put_resource(&rscp->pdid_fifo, pdid); + cxio_hal_put_resource(&rscp->pdid_fifo, &rscp->pdid_fifo_lock, pdid); } void cxio_hal_destroy_resource(struct cxio_hal_resource *rscp) diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index dacbbb839b9..38bcedfd9fe 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -800,8 +800,8 @@ again: return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { - if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, - sizeof(int)) != sizeof(int)) { + if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; } @@ -811,7 +811,8 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } else { int size; @@ -820,8 +821,8 @@ again: mchip_free_frame(); goto again; } - if (kfifo_get(&meye.grabq, (unsigned char *)&reqnr, - sizeof(int)) != sizeof(int)) { + if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); goto again; } @@ -831,7 +832,8 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put(&meye.doneq, (unsigned char *)&reqnr, sizeof(int)); + kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } mchip_free_frame(); @@ -933,7 +935,8 @@ static int meyeioc_qbuf_capt(int *nb) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put(&meye.grabq, (unsigned char *)nb, sizeof(int)); + kfifo_put_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), + &meye.grabq_lock); mutex_unlock(&meye.lock); return 0; @@ -965,7 +968,8 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get(&meye.doneq, (unsigned char *)&unused, sizeof(int)); + kfifo_get_locked(&meye.doneq, (unsigned char *)&unused, + sizeof(int), &meye.doneq_lock); } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); @@ -1452,7 +1456,8 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put(&meye.grabq, (unsigned char *)&buf->index, sizeof(int)); + kfifo_put_locked(&meye.grabq, (unsigned char *)&buf->index, + sizeof(int), &meye.grabq_lock); mutex_unlock(&meye.lock); return 0; @@ -1478,8 +1483,8 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) return -EINTR; } - if (!kfifo_get(&meye.doneq, (unsigned char *)&reqnr, - sizeof(int))) { + if (!kfifo_get_locked(&meye.doneq, (unsigned char *)&reqnr, + sizeof(int), &meye.doneq_lock)) { mutex_unlock(&meye.lock); return -EBUSY; } @@ -1745,14 +1750,14 @@ static int __devinit meye_probe(struct pci_dev *pcidev, } spin_lock_init(&meye.grabq_lock); - if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.grabq_lock)) { + if (kfifo_alloc(&meye.grabq, sizeof(int) * MEYE_MAX_BUFNBRS, + GFP_KERNEL)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc1; } spin_lock_init(&meye.doneq_lock); - if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, GFP_KERNEL, - &meye.doneq_lock)) { + if (kfifo_alloc(&meye.doneq, sizeof(int) * MEYE_MAX_BUFNBRS, + GFP_KERNEL)) { printk(KERN_ERR "meye: fifo allocation failed\n"); goto outkfifoalloc2; } diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 40390928741..2cc7ecd8d12 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -883,7 +883,7 @@ static int lbs_init_adapter(struct lbs_private *priv) priv->resp_len[0] = priv->resp_len[1] = 0; /* Create the event FIFO */ - ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL, NULL); + ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL); if (ret) { lbs_pr_err("Out of memory allocating event FIFO buffer\n"); goto out; diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index f999fba0e25..13dc7bedcfc 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -825,7 +825,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) /* kfifo */ spin_lock_init(&fujitsu_hotkey->fifo_lock); error = kfifo_alloc(&fujitsu_hotkey->fifo, RINGBUFFERSIZE * sizeof(int), - GFP_KERNEL, &fujitsu_hotkey->fifo_lock); + GFP_KERNEL); if (error) { printk(KERN_ERR "kfifo_alloc failed\n"); goto err_stop; @@ -1006,9 +1006,10 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) vdbg_printk(FUJLAPTOP_DBG_TRACE, "Push keycode into ringbuffer [%d]\n", keycode); - status = kfifo_put(&fujitsu_hotkey->fifo, + status = kfifo_put_locked(&fujitsu_hotkey->fifo, (unsigned char *)&keycode, - sizeof(keycode)); + sizeof(keycode), + &fujitsu_hotkey->fifo_lock); if (status != sizeof(keycode)) { vdbg_printk(FUJLAPTOP_DBG_WARN, "Could not push keycode [0x%x]\n", @@ -1019,11 +1020,12 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) } } else if (keycode == 0) { while ((status = - kfifo_get - (&fujitsu_hotkey->fifo, (unsigned char *) - &keycode_r, - sizeof - (keycode_r))) == sizeof(keycode_r)) { + kfifo_get_locked( + &fujitsu_hotkey->fifo, + (unsigned char *) &keycode_r, + sizeof(keycode_r), + &fujitsu_hotkey->fifo_lock)) + == sizeof(keycode_r)) { input_report_key(input, keycode_r, 0); input_sync(input); vdbg_printk(FUJLAPTOP_DBG_TRACE, diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 04625a048e7..1538a0a3c0a 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -300,8 +300,9 @@ static void do_sony_laptop_release_key(struct work_struct *work) { struct sony_laptop_keypress kp; - while (kfifo_get(&sony_laptop_input.fifo, (unsigned char *)&kp, - sizeof(kp)) == sizeof(kp)) { + while (kfifo_get_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, + sizeof(kp), &sony_laptop_input.fifo_lock) + == sizeof(kp)) { msleep(10); input_report_key(kp.dev, kp.key, 0); input_sync(kp.dev); @@ -362,8 +363,9 @@ static void sony_laptop_report_input_event(u8 event) /* we emit the scancode so we can always remap the key */ input_event(kp.dev, EV_MSC, MSC_SCAN, event); input_sync(kp.dev); - kfifo_put(&sony_laptop_input.fifo, - (unsigned char *)&kp, sizeof(kp)); + kfifo_put_locked(&sony_laptop_input.fifo, + (unsigned char *)&kp, sizeof(kp), + &sony_laptop_input.fifo_lock); if (!work_pending(&sony_laptop_release_key_work)) queue_work(sony_laptop_input.wq, @@ -386,8 +388,7 @@ static int sony_laptop_setup_input(struct acpi_device *acpi_device) /* kfifo */ spin_lock_init(&sony_laptop_input.fifo_lock); error = - kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, - &sony_laptop_input.fifo_lock); + kfifo_alloc(&sony_laptop_input.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); goto err_dec_users; @@ -2129,7 +2130,8 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, return ret; while (ret < count && - (kfifo_get(&sonypi_compat.fifo, &c, sizeof(c)) == sizeof(c))) { + (kfifo_get_locked(&sonypi_compat.fifo, &c, sizeof(c), + &sonypi_compat.fifo_lock) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; ret++; @@ -2308,7 +2310,8 @@ static struct miscdevice sonypi_misc_device = { static void sonypi_compat_report_event(u8 event) { - kfifo_put(&sonypi_compat.fifo, (unsigned char *)&event, sizeof(event)); + kfifo_put_locked(&sonypi_compat.fifo, (unsigned char *)&event, + sizeof(event), &sonypi_compat.fifo_lock); kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_compat.fifo_proc_list); } @@ -2319,8 +2322,7 @@ static int sonypi_compat_init(void) spin_lock_init(&sonypi_compat.fifo_lock); error = - kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL, - &sonypi_compat.fifo_lock); + kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL); if (error) { printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n"); return error; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index cf0aa7e90be..1bccbc1e588 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -2461,7 +2461,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) if (q->pool == NULL) return -ENOMEM; - kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*), NULL); + kfifo_init(&q->queue, (void*)q->pool, max * sizeof(void*)); for (i = 0; i < max; i++) { q->pool[i] = kzalloc(item_size, GFP_KERNEL); diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index a83ee56a185..41643c860d2 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -1128,7 +1128,7 @@ int iscsi_tcp_r2tpool_alloc(struct iscsi_session *session) /* R2T xmit queue */ if (kfifo_alloc(&tcp_task->r2tqueue, - session->max_r2t * 4 * sizeof(void*), GFP_KERNEL, NULL)) { + session->max_r2t * 4 * sizeof(void*), GFP_KERNEL)) { iscsi_pool_free(&tcp_task->r2tpool); goto r2t_alloc_fail; } diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index b1b5e51ca8e..db1b41c55fd 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -58,8 +58,7 @@ static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, goto free_pool; spin_lock_init(&q->lock); - kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *), - &q->lock); + kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *)); for (i = 0, iue = q->items; i < max; i++) { __kfifo_put(&q->queue, (void *) &iue, sizeof(void *)); @@ -164,7 +163,8 @@ struct iu_entry *srp_iu_get(struct srp_target *target) { struct iu_entry *iue = NULL; - kfifo_get(&target->iu_queue.queue, (void *) &iue, sizeof(void *)); + kfifo_get_locked(&target->iu_queue.queue, (void *) &iue, + sizeof(void *), &target->iu_queue.lock); if (!iue) return iue; iue->target = target; @@ -176,7 +176,8 @@ EXPORT_SYMBOL_GPL(srp_iu_get); void srp_iu_put(struct iu_entry *iue) { - kfifo_put(&iue->target->iu_queue.queue, (void *) &iue, sizeof(void *)); + kfifo_put_locked(&iue->target->iu_queue.queue, (void *) &iue, + sizeof(void *), &iue->target->iu_queue.lock); } EXPORT_SYMBOL_GPL(srp_iu_put); diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index 2277428ef5d..a76da201183 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h @@ -495,7 +495,7 @@ static inline struct usb_hcd *fhci_to_hcd(struct fhci_hcd *fhci) /* fifo of pointers */ static inline int cq_new(struct kfifo *fifo, int size) { - return kfifo_alloc(fifo, size * sizeof(void *), GFP_KERNEL, NULL); + return kfifo_alloc(fifo, size * sizeof(void *), GFP_KERNEL); } static inline void cq_delete(struct kfifo *kfifo) diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index bbe005cefcf..61eef18218b 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -285,7 +285,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) return 0; data = port->write_urb->transfer_buffer; - count = kfifo_get(port->write_fifo, data, port->bulk_out_size); + count = kfifo_get_locked(port->write_fifo, data, port->bulk_out_size, &port->lock); usb_serial_debug_data(debug, &port->dev, __func__, count, data); /* set up our urb */ @@ -345,7 +345,7 @@ int usb_serial_generic_write(struct tty_struct *tty, return usb_serial_multi_urb_write(tty, port, buf, count); - count = kfifo_put(port->write_fifo, buf, count); + count = kfifo_put_locked(port->write_fifo, buf, count, &port->lock); result = usb_serial_generic_write_start(port); if (result >= 0) diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 44b72d47fac..636a4f23445 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -939,8 +939,7 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "No free urbs available\n"); goto probe_error; } - if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL, - &port->lock)) + if (kfifo_alloc(port->write_fifo, PAGE_SIZE, GFP_KERNEL)) goto probe_error; buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->bulk_out_size = buffer_size; diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index c3f8d82efd3..e0f5c9d4197 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -30,13 +30,12 @@ struct kfifo { unsigned int size; /* the size of the allocated buffer */ unsigned int in; /* data is added at offset (in % size) */ unsigned int out; /* data is extracted from off. (out % size) */ - spinlock_t *lock; /* protects concurrent modifications */ }; extern void kfifo_init(struct kfifo *fifo, unsigned char *buffer, - unsigned int size, spinlock_t *lock); + unsigned int size); extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, - gfp_t gfp_mask, spinlock_t *lock); + gfp_t gfp_mask); extern void kfifo_free(struct kfifo *fifo); extern unsigned int __kfifo_put(struct kfifo *fifo, const unsigned char *buffer, unsigned int len); @@ -58,58 +57,67 @@ static inline void __kfifo_reset(struct kfifo *fifo) */ static inline void kfifo_reset(struct kfifo *fifo) { - unsigned long flags; - - spin_lock_irqsave(fifo->lock, flags); - __kfifo_reset(fifo); +} + +/** + * __kfifo_len - returns the number of bytes available in the FIFO + * @fifo: the fifo to be used. + */ +static inline unsigned int __kfifo_len(struct kfifo *fifo) +{ + register unsigned int out; - spin_unlock_irqrestore(fifo->lock, flags); + out = fifo->out; + smp_rmb(); + return fifo->in - out; } /** - * kfifo_put - puts some data into the FIFO + * kfifo_put_locked - puts some data into the FIFO using a spinlock for locking * @fifo: the fifo to be used. - * @buffer: the data to be added. - * @len: the length of the data to be added. + * @from: the data to be added. + * @n: the length of the data to be added. + * @lock: pointer to the spinlock to use for locking. * - * This function copies at most @len bytes from the @buffer into + * This function copies at most @len bytes from the @from buffer into * the FIFO depending on the free space, and returns the number of * bytes copied. */ -static inline unsigned int kfifo_put(struct kfifo *fifo, - const unsigned char *buffer, unsigned int len) +static inline __must_check unsigned int kfifo_put_locked(struct kfifo *fifo, + const unsigned char *from, unsigned int n, spinlock_t *lock) { unsigned long flags; unsigned int ret; - spin_lock_irqsave(fifo->lock, flags); + spin_lock_irqsave(lock, flags); - ret = __kfifo_put(fifo, buffer, len); + ret = __kfifo_put(fifo, from, n); - spin_unlock_irqrestore(fifo->lock, flags); + spin_unlock_irqrestore(lock, flags); return ret; } /** - * kfifo_get - gets some data from the FIFO + * kfifo_get_locked - gets some data from the FIFO using a spinlock for locking * @fifo: the fifo to be used. - * @buffer: where the data must be copied. - * @len: the size of the destination buffer. + * @to: where the data must be copied. + * @n: the size of the destination buffer. + * @lock: pointer to the spinlock to use for locking. * * This function copies at most @len bytes from the FIFO into the - * @buffer and returns the number of copied bytes. + * @to buffer and returns the number of copied bytes. */ -static inline unsigned int kfifo_get(struct kfifo *fifo, - unsigned char *buffer, unsigned int len) +static inline __must_check unsigned int kfifo_get_locked(struct kfifo *fifo, + unsigned char *to, unsigned int n, spinlock_t *lock) { unsigned long flags; unsigned int ret; - spin_lock_irqsave(fifo->lock, flags); + spin_lock_irqsave(lock, flags); - ret = __kfifo_get(fifo, buffer, len); + ret = __kfifo_get(fifo, to, n); /* * optimization: if the FIFO is empty, set the indices to 0 @@ -118,36 +126,18 @@ static inline unsigned int kfifo_get(struct kfifo *fifo, if (fifo->in == fifo->out) fifo->in = fifo->out = 0; - spin_unlock_irqrestore(fifo->lock, flags); + spin_unlock_irqrestore(lock, flags); return ret; } -/** - * __kfifo_len - returns the number of bytes available in the FIFO, no locking version - * @fifo: the fifo to be used. - */ -static inline unsigned int __kfifo_len(struct kfifo *fifo) -{ - return fifo->in - fifo->out; -} - /** * kfifo_len - returns the number of bytes available in the FIFO * @fifo: the fifo to be used. */ static inline unsigned int kfifo_len(struct kfifo *fifo) { - unsigned long flags; - unsigned int ret; - - spin_lock_irqsave(fifo->lock, flags); - - ret = __kfifo_len(fifo); - - spin_unlock_irqrestore(fifo->lock, flags); - - return ret; + return __kfifo_len(fifo); } #endif diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 8da6bb9782b..4950bdbe347 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -28,11 +28,10 @@ #include static void _kfifo_init(struct kfifo *fifo, unsigned char *buffer, - unsigned int size, spinlock_t *lock) + unsigned int size) { fifo->buffer = buffer; fifo->size = size; - fifo->lock = lock; kfifo_reset(fifo); } @@ -42,16 +41,14 @@ static void _kfifo_init(struct kfifo *fifo, unsigned char *buffer, * @fifo: the fifo to assign the buffer * @buffer: the preallocated buffer to be used. * @size: the size of the internal buffer, this have to be a power of 2. - * @lock: the lock to be used to protect the fifo buffer * */ -void kfifo_init(struct kfifo *fifo, unsigned char *buffer, unsigned int size, - spinlock_t *lock) +void kfifo_init(struct kfifo *fifo, unsigned char *buffer, unsigned int size) { /* size must be a power of 2 */ BUG_ON(!is_power_of_2(size)); - _kfifo_init(fifo, buffer, size, lock); + _kfifo_init(fifo, buffer, size); } EXPORT_SYMBOL(kfifo_init); @@ -60,7 +57,6 @@ EXPORT_SYMBOL(kfifo_init); * @fifo: the fifo to assign then new buffer * @size: the size of the buffer to be allocated, this have to be a power of 2. * @gfp_mask: get_free_pages mask, passed to kmalloc() - * @lock: the lock to be used to protect the fifo buffer * * This function dynamically allocates a new fifo internal buffer * @@ -68,8 +64,7 @@ EXPORT_SYMBOL(kfifo_init); * The buffer will be release with kfifo_free(). * Return 0 if no error, otherwise the an error code */ -int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask, - spinlock_t *lock) +int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask) { unsigned char *buffer; @@ -84,11 +79,11 @@ int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask, buffer = kmalloc(size, gfp_mask); if (!buffer) { - _kfifo_init(fifo, 0, 0, NULL); + _kfifo_init(fifo, 0, 0); return -ENOMEM; } - _kfifo_init(fifo, buffer, size, lock); + _kfifo_init(fifo, buffer, size); return 0; } diff --git a/net/dccp/probe.c b/net/dccp/probe.c index 6230ceb0823..c6b50351aa7 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -67,7 +67,7 @@ static void printl(const char *fmt, ...) len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); va_end(args); - kfifo_put(&dccpw.fifo, tbuf, len); + kfifo_put_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); wake_up(&dccpw.wait); } @@ -135,7 +135,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf, if (error) goto out_free; - cnt = kfifo_get(&dccpw.fifo, tbuf, len); + cnt = kfifo_get_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0; out_free: @@ -156,7 +156,7 @@ static __init int dccpprobe_init(void) init_waitqueue_head(&dccpw.wait); spin_lock_init(&dccpw.lock); - if (kfifo_alloc(&dccpw.fifo, bufsize, GFP_KERNEL, &dccpw.lock)) + if (kfifo_alloc(&dccpw.fifo, bufsize, GFP_KERNEL)) return ret; if (!proc_net_fops_create(&init_net, procname, S_IRUSR, &dccpprobe_fops)) goto err0; -- cgit v1.2.3-70-g09d2 From e64c026dd09b73faf20707711402fc5ed55a8e70 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:28 -0800 Subject: kfifo: cleanup namespace change name of __kfifo_* functions to kfifo_*, because the prefix __kfifo should be reserved for internal functions only. Signed-off-by: Stefani Seibold Acked-by: Greg Kroah-Hartman Acked-by: Mauro Carvalho Chehab Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/nozomi.c | 12 +++++------ drivers/infiniband/hw/cxgb3/cxio_resource.c | 10 ++++----- drivers/net/wireless/libertas/cmd.c | 4 ++-- drivers/net/wireless/libertas/main.c | 8 ++++---- drivers/platform/x86/sony-laptop.c | 2 +- drivers/scsi/libiscsi.c | 14 ++++++------- drivers/scsi/libiscsi_tcp.c | 20 +++++++++--------- drivers/scsi/libsrp.c | 2 +- drivers/usb/host/fhci.h | 6 +++--- drivers/usb/serial/generic.c | 4 ++-- include/linux/kfifo.h | 32 +++++++---------------------- kernel/kfifo.c | 12 +++++------ net/dccp/probe.c | 2 +- 13 files changed, 55 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 935b30d80ad..61f5bfe74f3 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -798,7 +798,7 @@ static int send_data(enum port_type index, struct nozomi *dc) struct tty_struct *tty = tty_port_tty_get(&port->port); /* Get data from tty and place in buf for now */ - size = __kfifo_get(&port->fifo_ul, dc->send_buf, + size = kfifo_get(&port->fifo_ul, dc->send_buf, ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); if (size == 0) { @@ -988,11 +988,11 @@ static int receive_flow_control(struct nozomi *dc) } else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) { - if (__kfifo_len(&dc->port[port].fifo_ul)) { + if (kfifo_len(&dc->port[port].fifo_ul)) { DBG1("Enable interrupt (0x%04X) on port: %d", enable_ier, port); DBG1("Data in buffer [%d], enable transmit! ", - __kfifo_len(&dc->port[port].fifo_ul)); + kfifo_len(&dc->port[port].fifo_ul)); enable_transmit_ul(port, dc); } else { DBG1("No data in buffer..."); @@ -1672,7 +1672,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, goto exit; } - rval = __kfifo_put(&port->fifo_ul, (unsigned char *)buffer, count); + rval = kfifo_put(&port->fifo_ul, (unsigned char *)buffer, count); /* notify card */ if (unlikely(dc == NULL)) { @@ -1720,7 +1720,7 @@ static int ntty_write_room(struct tty_struct *tty) if (!port->port.count) goto exit; - room = port->fifo_ul.size - __kfifo_len(&port->fifo_ul); + room = port->fifo_ul.size - kfifo_len(&port->fifo_ul); exit: mutex_unlock(&port->tty_sem); @@ -1877,7 +1877,7 @@ static s32 ntty_chars_in_buffer(struct tty_struct *tty) goto exit_in_buffer; } - rval = __kfifo_len(&port->fifo_ul); + rval = kfifo_len(&port->fifo_ul); exit_in_buffer: return rval; diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index 98f24e6d906..d7d18fb02c9 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c @@ -59,7 +59,7 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, return -ENOMEM; for (i = 0; i < skip_low + skip_high; i++) - __kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)); + kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)); if (random) { j = 0; random_bytes = random32(); @@ -71,19 +71,19 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, random_bytes = random32(); } idx = (random_bytes >> (j * 2)) & 0xF; - __kfifo_put(fifo, + kfifo_put(fifo, (unsigned char *) &rarray[idx], sizeof(u32)); rarray[idx] = i; j++; } for (i = 0; i < RANDOM_SIZE; i++) - __kfifo_put(fifo, + kfifo_put(fifo, (unsigned char *) &rarray[i], sizeof(u32)); } else for (i = skip_low; i < nr - skip_high; i++) - __kfifo_put(fifo, (unsigned char *) &i, sizeof(u32)); + kfifo_put(fifo, (unsigned char *) &i, sizeof(u32)); for (i = 0; i < skip_low + skip_high; i++) kfifo_get_locked(fifo, (unsigned char *) &entry, @@ -119,7 +119,7 @@ static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p) for (i = 16; i < T3_MAX_NUM_QP; i++) if (!(i & rdev_p->qpmask)) - __kfifo_put(&rdev_p->rscp->qpid_fifo, + kfifo_put(&rdev_p->rscp->qpid_fifo, (unsigned char *) &i, sizeof(u32)); return 0; } diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index ffed17f4f50..42611bea76a 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c @@ -1365,7 +1365,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) priv->dnld_sent = DNLD_RES_RECEIVED; /* If nothing to do, go back to sleep (?) */ - if (!__kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) + if (!kfifo_len(&priv->event_fifo) && !priv->resp_len[priv->resp_idx]) priv->psstate = PS_STATE_SLEEP; spin_unlock_irqrestore(&priv->driver_lock, flags); @@ -1439,7 +1439,7 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv) } /* Pending events or command responses? */ - if (__kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) { + if (kfifo_len(&priv->event_fifo) || priv->resp_len[priv->resp_idx]) { allowed = 0; lbs_deb_host("pending events or command responses\n"); } diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 2cc7ecd8d12..0622104f0a0 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -459,7 +459,7 @@ static int lbs_thread(void *data) else if (!list_empty(&priv->cmdpendingq) && !(priv->wakeup_dev_required)) shouldsleep = 0; /* We have a command to send */ - else if (__kfifo_len(&priv->event_fifo)) + else if (kfifo_len(&priv->event_fifo)) shouldsleep = 0; /* We have an event to process */ else shouldsleep = 1; /* No command */ @@ -511,9 +511,9 @@ static int lbs_thread(void *data) /* Process hardware events, e.g. card removed, link lost */ spin_lock_irq(&priv->driver_lock); - while (__kfifo_len(&priv->event_fifo)) { + while (kfifo_len(&priv->event_fifo)) { u32 event; - __kfifo_get(&priv->event_fifo, (unsigned char *) &event, + kfifo_get(&priv->event_fifo, (unsigned char *) &event, sizeof(event)); spin_unlock_irq(&priv->driver_lock); lbs_process_event(priv, event); @@ -1175,7 +1175,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event) if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; - __kfifo_put(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); + kfifo_put(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); wake_up_interruptible(&priv->waitq); diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 1538a0a3c0a..36e5dc6fc95 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -2107,7 +2107,7 @@ static int sonypi_misc_open(struct inode *inode, struct file *file) spin_lock_irqsave(&sonypi_compat.fifo_lock, flags); if (atomic_inc_return(&sonypi_compat.open_count) == 1) - __kfifo_reset(&sonypi_compat.fifo); + kfifo_reset(&sonypi_compat.fifo); spin_unlock_irqrestore(&sonypi_compat.fifo_lock, flags); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 1bccbc1e588..5f0c46f43ee 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -517,7 +517,7 @@ static void iscsi_free_task(struct iscsi_task *task) if (conn->login_task == task) return; - __kfifo_put(&session->cmdpool.queue, (void*)&task, sizeof(void*)); + kfifo_put(&session->cmdpool.queue, (void*)&task, sizeof(void*)); if (sc) { task->sc = NULL; @@ -737,7 +737,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); - if (!__kfifo_get(&session->cmdpool.queue, + if (!kfifo_get(&session->cmdpool.queue, (void*)&task, sizeof(void*))) return NULL; } @@ -1567,7 +1567,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, { struct iscsi_task *task; - if (!__kfifo_get(&conn->session->cmdpool.queue, + if (!kfifo_get(&conn->session->cmdpool.queue, (void *) &task, sizeof(void *))) return NULL; @@ -2469,7 +2469,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) q->max = i; goto enomem; } - __kfifo_put(&q->queue, (void*)&q->pool[i], sizeof(void*)); + kfifo_put(&q->queue, (void*)&q->pool[i], sizeof(void*)); } if (items) { @@ -2819,7 +2819,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, /* allocate login_task used for the login/text sequences */ spin_lock_bh(&session->lock); - if (!__kfifo_get(&session->cmdpool.queue, + if (!kfifo_get(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*))) { spin_unlock_bh(&session->lock); @@ -2839,7 +2839,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, return cls_conn; login_task_data_alloc_fail: - __kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, + kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); login_task_alloc_fail: iscsi_destroy_conn(cls_conn); @@ -2902,7 +2902,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) free_pages((unsigned long) conn->data, get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); kfree(conn->persistent_address); - __kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, + kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); if (session->leadconn == conn) session->leadconn = NULL; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 41643c860d2..c0be926637b 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -445,15 +445,15 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task) return; /* flush task's r2t queues */ - while (__kfifo_get(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { - __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + while (kfifo_get(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { + kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n"); } r2t = tcp_task->r2t; if (r2t != NULL) { - __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); tcp_task->r2t = NULL; } @@ -541,7 +541,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) return 0; } - rc = __kfifo_get(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); + rc = kfifo_get(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); if (!rc) { iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. " "Target has sent more R2Ts than it " @@ -554,7 +554,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) if (r2t->data_length == 0) { iscsi_conn_printk(KERN_ERR, conn, "invalid R2T with zero data len\n"); - __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -570,7 +570,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) "invalid R2T with data len %u at offset %u " "and total length %d\n", r2t->data_length, r2t->data_offset, scsi_out(task->sc)->length); - __kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -580,7 +580,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) r2t->sent = 0; tcp_task->exp_datasn = r2tsn + 1; - __kfifo_put(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); + kfifo_put(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); conn->r2t_pdus_cnt++; iscsi_requeue_task(task); @@ -951,7 +951,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task) return conn->session->tt->init_pdu(task, 0, task->data_count); } - BUG_ON(__kfifo_len(&tcp_task->r2tqueue)); + BUG_ON(kfifo_len(&tcp_task->r2tqueue)); tcp_task->exp_datasn = 0; /* Prepare PDU, optionally w/ immediate data */ @@ -982,7 +982,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) if (r2t->data_length <= r2t->sent) { ISCSI_DBG_TCP(task->conn, " done with r2t %p\n", r2t); - __kfifo_put(&tcp_task->r2tpool.queue, + kfifo_put(&tcp_task->r2tpool.queue, (void *)&tcp_task->r2t, sizeof(void *)); tcp_task->r2t = r2t = NULL; @@ -990,7 +990,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) } if (r2t == NULL) { - __kfifo_get(&tcp_task->r2tqueue, + kfifo_get(&tcp_task->r2tqueue, (void *)&tcp_task->r2t, sizeof(void *)); r2t = tcp_task->r2t; } diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index db1b41c55fd..975e448cfcb 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -61,7 +61,7 @@ static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *)); for (i = 0, iue = q->items; i < max; i++) { - __kfifo_put(&q->queue, (void *) &iue, sizeof(void *)); + kfifo_put(&q->queue, (void *) &iue, sizeof(void *)); iue->sbuf = ring[i]; iue++; } diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index a76da201183..96aa787f208 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h @@ -505,19 +505,19 @@ static inline void cq_delete(struct kfifo *kfifo) static inline unsigned int cq_howmany(struct kfifo *kfifo) { - return __kfifo_len(kfifo) / sizeof(void *); + return kfifo_len(kfifo) / sizeof(void *); } static inline int cq_put(struct kfifo *kfifo, void *p) { - return __kfifo_put(kfifo, (void *)&p, sizeof(p)); + return kfifo_put(kfifo, (void *)&p, sizeof(p)); } static inline void *cq_get(struct kfifo *kfifo) { void *p = NULL; - __kfifo_get(kfifo, (void *)&p, sizeof(p)); + kfifo_get(kfifo, (void *)&p, sizeof(p)); return p; } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 61eef18218b..d0a2e464cac 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -276,7 +276,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) if (port->write_urb_busy) start_io = false; else { - start_io = (__kfifo_len(port->write_fifo) != 0); + start_io = (kfifo_len(port->write_fifo) != 0); port->write_urb_busy = start_io; } spin_unlock_irqrestore(&port->lock, flags); @@ -370,7 +370,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty) (serial->type->max_in_flight_urbs - port->urbs_in_flight); } else if (serial->num_bulk_out) - room = port->write_fifo->size - __kfifo_len(port->write_fifo); + room = port->write_fifo->size - kfifo_len(port->write_fifo); spin_unlock_irqrestore(&port->lock, flags); dbg("%s - returns %d", __func__, room); diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index e0f5c9d4197..a893acda396 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -37,34 +37,25 @@ extern void kfifo_init(struct kfifo *fifo, unsigned char *buffer, extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); extern void kfifo_free(struct kfifo *fifo); -extern unsigned int __kfifo_put(struct kfifo *fifo, +extern unsigned int kfifo_put(struct kfifo *fifo, const unsigned char *buffer, unsigned int len); -extern unsigned int __kfifo_get(struct kfifo *fifo, +extern unsigned int kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len); -/** - * __kfifo_reset - removes the entire FIFO contents, no locking version - * @fifo: the fifo to be emptied. - */ -static inline void __kfifo_reset(struct kfifo *fifo) -{ - fifo->in = fifo->out = 0; -} - /** * kfifo_reset - removes the entire FIFO contents * @fifo: the fifo to be emptied. */ static inline void kfifo_reset(struct kfifo *fifo) { - __kfifo_reset(fifo); + fifo->in = fifo->out = 0; } /** - * __kfifo_len - returns the number of bytes available in the FIFO + * kfifo_len - returns the number of used bytes in the FIFO * @fifo: the fifo to be used. */ -static inline unsigned int __kfifo_len(struct kfifo *fifo) +static inline unsigned int kfifo_len(struct kfifo *fifo) { register unsigned int out; @@ -92,7 +83,7 @@ static inline __must_check unsigned int kfifo_put_locked(struct kfifo *fifo, spin_lock_irqsave(lock, flags); - ret = __kfifo_put(fifo, from, n); + ret = kfifo_put(fifo, from, n); spin_unlock_irqrestore(lock, flags); @@ -117,7 +108,7 @@ static inline __must_check unsigned int kfifo_get_locked(struct kfifo *fifo, spin_lock_irqsave(lock, flags); - ret = __kfifo_get(fifo, to, n); + ret = kfifo_get(fifo, to, n); /* * optimization: if the FIFO is empty, set the indices to 0 @@ -131,13 +122,4 @@ static inline __must_check unsigned int kfifo_get_locked(struct kfifo *fifo, return ret; } -/** - * kfifo_len - returns the number of bytes available in the FIFO - * @fifo: the fifo to be used. - */ -static inline unsigned int kfifo_len(struct kfifo *fifo) -{ - return __kfifo_len(fifo); -} - #endif diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 4950bdbe347..963ffde4af1 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -100,7 +100,7 @@ void kfifo_free(struct kfifo *fifo) EXPORT_SYMBOL(kfifo_free); /** - * __kfifo_put - puts some data into the FIFO, no locking version + * kfifo_put - puts some data into the FIFO, no locking version * @fifo: the fifo to be used. * @buffer: the data to be added. * @len: the length of the data to be added. @@ -112,7 +112,7 @@ EXPORT_SYMBOL(kfifo_free); * Note that with only one concurrent reader and one concurrent * writer, you don't need extra locking to use these functions. */ -unsigned int __kfifo_put(struct kfifo *fifo, +unsigned int kfifo_put(struct kfifo *fifo, const unsigned char *buffer, unsigned int len) { unsigned int l; @@ -144,10 +144,10 @@ unsigned int __kfifo_put(struct kfifo *fifo, return len; } -EXPORT_SYMBOL(__kfifo_put); +EXPORT_SYMBOL(kfifo_put); /** - * __kfifo_get - gets some data from the FIFO, no locking version + * kfifo_get - gets some data from the FIFO, no locking version * @fifo: the fifo to be used. * @buffer: where the data must be copied. * @len: the size of the destination buffer. @@ -158,7 +158,7 @@ EXPORT_SYMBOL(__kfifo_put); * Note that with only one concurrent reader and one concurrent * writer, you don't need extra locking to use these functions. */ -unsigned int __kfifo_get(struct kfifo *fifo, +unsigned int kfifo_get(struct kfifo *fifo, unsigned char *buffer, unsigned int len) { unsigned int l; @@ -190,4 +190,4 @@ unsigned int __kfifo_get(struct kfifo *fifo, return len; } -EXPORT_SYMBOL(__kfifo_get); +EXPORT_SYMBOL(kfifo_get); diff --git a/net/dccp/probe.c b/net/dccp/probe.c index c6b50351aa7..9ef36849edd 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -131,7 +131,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf, return -ENOMEM; error = wait_event_interruptible(dccpw.wait, - __kfifo_len(&dccpw.fifo) != 0); + kfifo_len(&dccpw.fifo) != 0); if (error) goto out_free; -- cgit v1.2.3-70-g09d2 From 7acd72eb85f1c7a15e8b5eb554994949241737f1 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:28 -0800 Subject: kfifo: rename kfifo_put... into kfifo_in... and kfifo_get... into kfifo_out... rename kfifo_put... into kfifo_in... to prevent miss use of old non in kernel-tree drivers ditto for kfifo_get... -> kfifo_out... Improve the prototypes of kfifo_in and kfifo_out to make the kerneldoc annotations more readable. Add mini "howto porting to the new API" in kfifo.h Signed-off-by: Stefani Seibold Acked-by: Greg Kroah-Hartman Acked-by: Mauro Carvalho Chehab Acked-by: Andi Kleen Acked-by: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/nozomi.c | 4 +-- drivers/char/sonypi.c | 8 +++--- drivers/infiniband/hw/cxgb3/cxio_resource.c | 16 ++++++------ drivers/media/video/meye.c | 16 ++++++------ drivers/net/wireless/libertas/main.c | 5 ++-- drivers/platform/x86/fujitsu-laptop.c | 4 +-- drivers/platform/x86/sony-laptop.c | 8 +++--- drivers/scsi/libiscsi.c | 14 +++++------ drivers/scsi/libiscsi_tcp.c | 18 ++++++------- drivers/scsi/libsrp.c | 6 ++--- drivers/usb/host/fhci.h | 4 +-- drivers/usb/serial/generic.c | 4 +-- include/linux/kfifo.h | 39 +++++++++++++++++++++-------- kernel/kfifo.c | 32 +++++++++++------------ net/dccp/probe.c | 4 +-- 15 files changed, 101 insertions(+), 81 deletions(-) (limited to 'drivers') diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 61f5bfe74f3..9ef24342901 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -798,7 +798,7 @@ static int send_data(enum port_type index, struct nozomi *dc) struct tty_struct *tty = tty_port_tty_get(&port->port); /* Get data from tty and place in buf for now */ - size = kfifo_get(&port->fifo_ul, dc->send_buf, + size = kfifo_out(&port->fifo_ul, dc->send_buf, ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX); if (size == 0) { @@ -1672,7 +1672,7 @@ static int ntty_write(struct tty_struct *tty, const unsigned char *buffer, goto exit; } - rval = kfifo_put(&port->fifo_ul, (unsigned char *)buffer, count); + rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count); /* notify card */ if (unlikely(dc == NULL)) { diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index dbcb3bd192c..0798754a607 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c @@ -777,7 +777,7 @@ static void input_keyrelease(struct work_struct *work) { struct sonypi_keypress kp; - while (kfifo_get_locked(&sonypi_device.input_fifo, (unsigned char *)&kp, + while (kfifo_out_locked(&sonypi_device.input_fifo, (unsigned char *)&kp, sizeof(kp), &sonypi_device.input_fifo_lock) == sizeof(kp)) { msleep(10); @@ -828,7 +828,7 @@ static void sonypi_report_input_event(u8 event) if (kp.dev) { input_report_key(kp.dev, kp.key, 1); input_sync(kp.dev); - kfifo_put_locked(&sonypi_device.input_fifo, + kfifo_in_locked(&sonypi_device.input_fifo, (unsigned char *)&kp, sizeof(kp), &sonypi_device.input_fifo_lock); schedule_work(&sonypi_device.input_work); @@ -882,7 +882,7 @@ found: acpi_bus_generate_proc_event(sonypi_acpi_device, 1, event); #endif - kfifo_put_locked(&sonypi_device.fifo, (unsigned char *)&event, + kfifo_in_locked(&sonypi_device.fifo, (unsigned char *)&event, sizeof(event), &sonypi_device.fifo_lock); kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_device.fifo_proc_list); @@ -932,7 +932,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, return ret; while (ret < count && - (kfifo_get_locked(&sonypi_device.fifo, &c, sizeof(c), + (kfifo_out_locked(&sonypi_device.fifo, &c, sizeof(c), &sonypi_device.fifo_lock) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index d7d18fb02c9..dcbf2606c43 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c @@ -59,7 +59,7 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, return -ENOMEM; for (i = 0; i < skip_low + skip_high; i++) - kfifo_put(fifo, (unsigned char *) &entry, sizeof(u32)); + kfifo_in(fifo, (unsigned char *) &entry, sizeof(u32)); if (random) { j = 0; random_bytes = random32(); @@ -71,22 +71,22 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, random_bytes = random32(); } idx = (random_bytes >> (j * 2)) & 0xF; - kfifo_put(fifo, + kfifo_in(fifo, (unsigned char *) &rarray[idx], sizeof(u32)); rarray[idx] = i; j++; } for (i = 0; i < RANDOM_SIZE; i++) - kfifo_put(fifo, + kfifo_in(fifo, (unsigned char *) &rarray[i], sizeof(u32)); } else for (i = skip_low; i < nr - skip_high; i++) - kfifo_put(fifo, (unsigned char *) &i, sizeof(u32)); + kfifo_in(fifo, (unsigned char *) &i, sizeof(u32)); for (i = 0; i < skip_low + skip_high; i++) - kfifo_get_locked(fifo, (unsigned char *) &entry, + kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), fifo_lock); return 0; } @@ -119,7 +119,7 @@ static int cxio_init_qpid_fifo(struct cxio_rdev *rdev_p) for (i = 16; i < T3_MAX_NUM_QP; i++) if (!(i & rdev_p->qpmask)) - kfifo_put(&rdev_p->rscp->qpid_fifo, + kfifo_in(&rdev_p->rscp->qpid_fifo, (unsigned char *) &i, sizeof(u32)); return 0; } @@ -180,7 +180,7 @@ tpt_err: static u32 cxio_hal_get_resource(struct kfifo *fifo, spinlock_t * lock) { u32 entry; - if (kfifo_get_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock)) + if (kfifo_out_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock)) return entry; else return 0; /* fifo emptry */ @@ -190,7 +190,7 @@ static void cxio_hal_put_resource(struct kfifo *fifo, spinlock_t * lock, u32 entry) { BUG_ON( - kfifo_put_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock) + kfifo_in_locked(fifo, (unsigned char *) &entry, sizeof(u32), lock) == 0); } diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 38bcedfd9fe..884a569d60a 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -800,7 +800,7 @@ again: return IRQ_HANDLED; if (meye.mchip_mode == MCHIP_HIC_MODE_CONT_OUT) { - if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); return IRQ_HANDLED; @@ -811,7 +811,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } else { @@ -821,7 +821,7 @@ again: mchip_free_frame(); goto again; } - if (kfifo_get_locked(&meye.grabq, (unsigned char *)&reqnr, + if (kfifo_out_locked(&meye.grabq, (unsigned char *)&reqnr, sizeof(int), &meye.grabq_lock) != sizeof(int)) { mchip_free_frame(); goto again; @@ -832,7 +832,7 @@ again: meye.grab_buffer[reqnr].state = MEYE_BUF_DONE; do_gettimeofday(&meye.grab_buffer[reqnr].timestamp); meye.grab_buffer[reqnr].sequence = sequence++; - kfifo_put_locked(&meye.doneq, (unsigned char *)&reqnr, + kfifo_in_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock); wake_up_interruptible(&meye.proc_list); } @@ -935,7 +935,7 @@ static int meyeioc_qbuf_capt(int *nb) mchip_cont_compression_start(); meye.grab_buffer[*nb].state = MEYE_BUF_USING; - kfifo_put_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), + kfifo_in_locked(&meye.grabq, (unsigned char *)nb, sizeof(int), &meye.grabq_lock); mutex_unlock(&meye.lock); @@ -968,7 +968,7 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_get_locked(&meye.doneq, (unsigned char *)&unused, + kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, sizeof(int), &meye.doneq_lock); } *i = meye.grab_buffer[*i].size; @@ -1456,7 +1456,7 @@ static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf) buf->flags |= V4L2_BUF_FLAG_QUEUED; buf->flags &= ~V4L2_BUF_FLAG_DONE; meye.grab_buffer[buf->index].state = MEYE_BUF_USING; - kfifo_put_locked(&meye.grabq, (unsigned char *)&buf->index, + kfifo_in_locked(&meye.grabq, (unsigned char *)&buf->index, sizeof(int), &meye.grabq_lock); mutex_unlock(&meye.lock); @@ -1483,7 +1483,7 @@ static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf) return -EINTR; } - if (!kfifo_get_locked(&meye.doneq, (unsigned char *)&reqnr, + if (!kfifo_out_locked(&meye.doneq, (unsigned char *)&reqnr, sizeof(int), &meye.doneq_lock)) { mutex_unlock(&meye.lock); return -EBUSY; diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 0622104f0a0..2bcfa745524 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -513,7 +513,8 @@ static int lbs_thread(void *data) spin_lock_irq(&priv->driver_lock); while (kfifo_len(&priv->event_fifo)) { u32 event; - kfifo_get(&priv->event_fifo, (unsigned char *) &event, + + kfifo_out(&priv->event_fifo, (unsigned char *) &event, sizeof(event)); spin_unlock_irq(&priv->driver_lock); lbs_process_event(priv, event); @@ -1175,7 +1176,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event) if (priv->psstate == PS_STATE_SLEEP) priv->psstate = PS_STATE_AWAKE; - kfifo_put(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); + kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); wake_up_interruptible(&priv->waitq); diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index 13dc7bedcfc..b66029bd75d 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -1006,7 +1006,7 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) vdbg_printk(FUJLAPTOP_DBG_TRACE, "Push keycode into ringbuffer [%d]\n", keycode); - status = kfifo_put_locked(&fujitsu_hotkey->fifo, + status = kfifo_in_locked(&fujitsu_hotkey->fifo, (unsigned char *)&keycode, sizeof(keycode), &fujitsu_hotkey->fifo_lock); @@ -1020,7 +1020,7 @@ static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event) } } else if (keycode == 0) { while ((status = - kfifo_get_locked( + kfifo_out_locked( &fujitsu_hotkey->fifo, (unsigned char *) &keycode_r, sizeof(keycode_r), diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 36e5dc6fc95..2896ca4cd9a 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -300,7 +300,7 @@ static void do_sony_laptop_release_key(struct work_struct *work) { struct sony_laptop_keypress kp; - while (kfifo_get_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, + while (kfifo_out_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, sizeof(kp), &sony_laptop_input.fifo_lock) == sizeof(kp)) { msleep(10); @@ -363,7 +363,7 @@ static void sony_laptop_report_input_event(u8 event) /* we emit the scancode so we can always remap the key */ input_event(kp.dev, EV_MSC, MSC_SCAN, event); input_sync(kp.dev); - kfifo_put_locked(&sony_laptop_input.fifo, + kfifo_in_locked(&sony_laptop_input.fifo, (unsigned char *)&kp, sizeof(kp), &sony_laptop_input.fifo_lock); @@ -2130,7 +2130,7 @@ static ssize_t sonypi_misc_read(struct file *file, char __user *buf, return ret; while (ret < count && - (kfifo_get_locked(&sonypi_compat.fifo, &c, sizeof(c), + (kfifo_out_locked(&sonypi_compat.fifo, &c, sizeof(c), &sonypi_compat.fifo_lock) == sizeof(c))) { if (put_user(c, buf++)) return -EFAULT; @@ -2310,7 +2310,7 @@ static struct miscdevice sonypi_misc_device = { static void sonypi_compat_report_event(u8 event) { - kfifo_put_locked(&sonypi_compat.fifo, (unsigned char *)&event, + kfifo_in_locked(&sonypi_compat.fifo, (unsigned char *)&event, sizeof(event), &sonypi_compat.fifo_lock); kill_fasync(&sonypi_compat.fifo_async, SIGIO, POLL_IN); wake_up_interruptible(&sonypi_compat.fifo_proc_list); diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 5f0c46f43ee..c28a712fd4d 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -517,7 +517,7 @@ static void iscsi_free_task(struct iscsi_task *task) if (conn->login_task == task) return; - kfifo_put(&session->cmdpool.queue, (void*)&task, sizeof(void*)); + kfifo_in(&session->cmdpool.queue, (void*)&task, sizeof(void*)); if (sc) { task->sc = NULL; @@ -737,7 +737,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, BUG_ON(conn->c_stage == ISCSI_CONN_INITIAL_STAGE); BUG_ON(conn->c_stage == ISCSI_CONN_STOPPED); - if (!kfifo_get(&session->cmdpool.queue, + if (!kfifo_out(&session->cmdpool.queue, (void*)&task, sizeof(void*))) return NULL; } @@ -1567,7 +1567,7 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, { struct iscsi_task *task; - if (!kfifo_get(&conn->session->cmdpool.queue, + if (!kfifo_out(&conn->session->cmdpool.queue, (void *) &task, sizeof(void *))) return NULL; @@ -2469,7 +2469,7 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size) q->max = i; goto enomem; } - kfifo_put(&q->queue, (void*)&q->pool[i], sizeof(void*)); + kfifo_in(&q->queue, (void*)&q->pool[i], sizeof(void*)); } if (items) { @@ -2819,7 +2819,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, /* allocate login_task used for the login/text sequences */ spin_lock_bh(&session->lock); - if (!kfifo_get(&session->cmdpool.queue, + if (!kfifo_out(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*))) { spin_unlock_bh(&session->lock); @@ -2839,7 +2839,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, return cls_conn; login_task_data_alloc_fail: - kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, + kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); login_task_alloc_fail: iscsi_destroy_conn(cls_conn); @@ -2902,7 +2902,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) free_pages((unsigned long) conn->data, get_order(ISCSI_DEF_MAX_RECV_SEG_LEN)); kfree(conn->persistent_address); - kfifo_put(&session->cmdpool.queue, (void*)&conn->login_task, + kfifo_in(&session->cmdpool.queue, (void*)&conn->login_task, sizeof(void*)); if (session->leadconn == conn) session->leadconn = NULL; diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index c0be926637b..d51ffeca2ec 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -445,15 +445,15 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task) return; /* flush task's r2t queues */ - while (kfifo_get(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { - kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + while (kfifo_out(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) { + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n"); } r2t = tcp_task->r2t; if (r2t != NULL) { - kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); tcp_task->r2t = NULL; } @@ -541,7 +541,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) return 0; } - rc = kfifo_get(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); + rc = kfifo_out(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); if (!rc) { iscsi_conn_printk(KERN_ERR, conn, "Could not allocate R2T. " "Target has sent more R2Ts than it " @@ -554,7 +554,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) if (r2t->data_length == 0) { iscsi_conn_printk(KERN_ERR, conn, "invalid R2T with zero data len\n"); - kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -570,7 +570,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) "invalid R2T with data len %u at offset %u " "and total length %d\n", r2t->data_length, r2t->data_offset, scsi_out(task->sc)->length); - kfifo_put(&tcp_task->r2tpool.queue, (void*)&r2t, + kfifo_in(&tcp_task->r2tpool.queue, (void*)&r2t, sizeof(void*)); return ISCSI_ERR_DATALEN; } @@ -580,7 +580,7 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task) r2t->sent = 0; tcp_task->exp_datasn = r2tsn + 1; - kfifo_put(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); + kfifo_in(&tcp_task->r2tqueue, (void*)&r2t, sizeof(void*)); conn->r2t_pdus_cnt++; iscsi_requeue_task(task); @@ -982,7 +982,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) if (r2t->data_length <= r2t->sent) { ISCSI_DBG_TCP(task->conn, " done with r2t %p\n", r2t); - kfifo_put(&tcp_task->r2tpool.queue, + kfifo_in(&tcp_task->r2tpool.queue, (void *)&tcp_task->r2t, sizeof(void *)); tcp_task->r2t = r2t = NULL; @@ -990,7 +990,7 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) } if (r2t == NULL) { - kfifo_get(&tcp_task->r2tqueue, + kfifo_out(&tcp_task->r2tqueue, (void *)&tcp_task->r2t, sizeof(void *)); r2t = tcp_task->r2t; } diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 975e448cfcb..8424b8606ef 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -61,7 +61,7 @@ static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *)); for (i = 0, iue = q->items; i < max; i++) { - kfifo_put(&q->queue, (void *) &iue, sizeof(void *)); + kfifo_in(&q->queue, (void *) &iue, sizeof(void *)); iue->sbuf = ring[i]; iue++; } @@ -163,7 +163,7 @@ struct iu_entry *srp_iu_get(struct srp_target *target) { struct iu_entry *iue = NULL; - kfifo_get_locked(&target->iu_queue.queue, (void *) &iue, + kfifo_out_locked(&target->iu_queue.queue, (void *) &iue, sizeof(void *), &target->iu_queue.lock); if (!iue) return iue; @@ -176,7 +176,7 @@ EXPORT_SYMBOL_GPL(srp_iu_get); void srp_iu_put(struct iu_entry *iue) { - kfifo_put_locked(&iue->target->iu_queue.queue, (void *) &iue, + kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue, sizeof(void *), &iue->target->iu_queue.lock); } EXPORT_SYMBOL_GPL(srp_iu_put); diff --git a/drivers/usb/host/fhci.h b/drivers/usb/host/fhci.h index 96aa787f208..72dae1c5ab3 100644 --- a/drivers/usb/host/fhci.h +++ b/drivers/usb/host/fhci.h @@ -510,14 +510,14 @@ static inline unsigned int cq_howmany(struct kfifo *kfifo) static inline int cq_put(struct kfifo *kfifo, void *p) { - return kfifo_put(kfifo, (void *)&p, sizeof(p)); + return kfifo_in(kfifo, (void *)&p, sizeof(p)); } static inline void *cq_get(struct kfifo *kfifo) { void *p = NULL; - kfifo_get(kfifo, (void *)&p, sizeof(p)); + kfifo_out(kfifo, (void *)&p, sizeof(p)); return p; } diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index d0a2e464cac..b0f1183755c 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -285,7 +285,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) return 0; data = port->write_urb->transfer_buffer; - count = kfifo_get_locked(port->write_fifo, data, port->bulk_out_size, &port->lock); + count = kfifo_out_locked(port->write_fifo, data, port->bulk_out_size, &port->lock); usb_serial_debug_data(debug, &port->dev, __func__, count, data); /* set up our urb */ @@ -345,7 +345,7 @@ int usb_serial_generic_write(struct tty_struct *tty, return usb_serial_multi_urb_write(tty, port, buf, count); - count = kfifo_put_locked(port->write_fifo, buf, count, &port->lock); + count = kfifo_in_locked(port->write_fifo, buf, count, &port->lock); result = usb_serial_generic_write_start(port); if (result >= 0) diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index a893acda396..1b59c4a0e85 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -19,6 +19,25 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ + +/* + * Howto porting drivers to the new generic fifo API: + * + * - Modify the declaration of the "struct kfifo *" object into a + * in-place "struct kfifo" object + * - Init the in-place object with kfifo_alloc() or kfifo_init() + * Note: The address of the in-place "struct kfifo" object must be + * passed as the first argument to this functions + * - Replace the use of __kfifo_put into kfifo_in and __kfifo_get + * into kfifo_out + * - Replace the use of kfifo_put into kfifo_in_locked and kfifo_get + * into kfifo_out_locked + * Note: the spinlock pointer formerly passed to kfifo_init/kfifo_alloc + * must be passed now to the kfifo_in_locked and kfifo_out_locked + * as the last parameter. + * - All formerly name __kfifo_* functions has been renamed into kfifo_* + */ + #ifndef _LINUX_KFIFO_H #define _LINUX_KFIFO_H @@ -37,10 +56,10 @@ extern void kfifo_init(struct kfifo *fifo, unsigned char *buffer, extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); extern void kfifo_free(struct kfifo *fifo); -extern unsigned int kfifo_put(struct kfifo *fifo, - const unsigned char *buffer, unsigned int len); -extern unsigned int kfifo_get(struct kfifo *fifo, - unsigned char *buffer, unsigned int len); +extern __must_check unsigned int kfifo_in(struct kfifo *fifo, + const unsigned char *from, unsigned int len); +extern __must_check unsigned int kfifo_out(struct kfifo *fifo, + unsigned char *to, unsigned int len); /** * kfifo_reset - removes the entire FIFO contents @@ -65,7 +84,7 @@ static inline unsigned int kfifo_len(struct kfifo *fifo) } /** - * kfifo_put_locked - puts some data into the FIFO using a spinlock for locking + * kfifo_in_locked - puts some data into the FIFO using a spinlock for locking * @fifo: the fifo to be used. * @from: the data to be added. * @n: the length of the data to be added. @@ -75,7 +94,7 @@ static inline unsigned int kfifo_len(struct kfifo *fifo) * the FIFO depending on the free space, and returns the number of * bytes copied. */ -static inline __must_check unsigned int kfifo_put_locked(struct kfifo *fifo, +static inline __must_check unsigned int kfifo_in_locked(struct kfifo *fifo, const unsigned char *from, unsigned int n, spinlock_t *lock) { unsigned long flags; @@ -83,7 +102,7 @@ static inline __must_check unsigned int kfifo_put_locked(struct kfifo *fifo, spin_lock_irqsave(lock, flags); - ret = kfifo_put(fifo, from, n); + ret = kfifo_in(fifo, from, n); spin_unlock_irqrestore(lock, flags); @@ -91,7 +110,7 @@ static inline __must_check unsigned int kfifo_put_locked(struct kfifo *fifo, } /** - * kfifo_get_locked - gets some data from the FIFO using a spinlock for locking + * kfifo_out_locked - gets some data from the FIFO using a spinlock for locking * @fifo: the fifo to be used. * @to: where the data must be copied. * @n: the size of the destination buffer. @@ -100,7 +119,7 @@ static inline __must_check unsigned int kfifo_put_locked(struct kfifo *fifo, * This function copies at most @len bytes from the FIFO into the * @to buffer and returns the number of copied bytes. */ -static inline __must_check unsigned int kfifo_get_locked(struct kfifo *fifo, +static inline __must_check unsigned int kfifo_out_locked(struct kfifo *fifo, unsigned char *to, unsigned int n, spinlock_t *lock) { unsigned long flags; @@ -108,7 +127,7 @@ static inline __must_check unsigned int kfifo_get_locked(struct kfifo *fifo, spin_lock_irqsave(lock, flags); - ret = kfifo_get(fifo, to, n); + ret = kfifo_out(fifo, to, n); /* * optimization: if the FIFO is empty, set the indices to 0 diff --git a/kernel/kfifo.c b/kernel/kfifo.c index 963ffde4af1..d659442e73f 100644 --- a/kernel/kfifo.c +++ b/kernel/kfifo.c @@ -100,20 +100,20 @@ void kfifo_free(struct kfifo *fifo) EXPORT_SYMBOL(kfifo_free); /** - * kfifo_put - puts some data into the FIFO, no locking version + * kfifo_in - puts some data into the FIFO * @fifo: the fifo to be used. - * @buffer: the data to be added. + * @from: the data to be added. * @len: the length of the data to be added. * - * This function copies at most @len bytes from the @buffer into + * This function copies at most @len bytes from the @from buffer into * the FIFO depending on the free space, and returns the number of * bytes copied. * * Note that with only one concurrent reader and one concurrent * writer, you don't need extra locking to use these functions. */ -unsigned int kfifo_put(struct kfifo *fifo, - const unsigned char *buffer, unsigned int len) +unsigned int kfifo_in(struct kfifo *fifo, + const unsigned char *from, unsigned int len) { unsigned int l; @@ -128,10 +128,10 @@ unsigned int kfifo_put(struct kfifo *fifo, /* first put the data starting from fifo->in to buffer end */ l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); - memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); + memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), from, l); /* then put the rest (if any) at the beginning of the buffer */ - memcpy(fifo->buffer, buffer + l, len - l); + memcpy(fifo->buffer, from + l, len - l); /* * Ensure that we add the bytes to the kfifo -before- @@ -144,22 +144,22 @@ unsigned int kfifo_put(struct kfifo *fifo, return len; } -EXPORT_SYMBOL(kfifo_put); +EXPORT_SYMBOL(kfifo_in); /** - * kfifo_get - gets some data from the FIFO, no locking version + * kfifo_out - gets some data from the FIFO * @fifo: the fifo to be used. - * @buffer: where the data must be copied. + * @to: where the data must be copied. * @len: the size of the destination buffer. * * This function copies at most @len bytes from the FIFO into the - * @buffer and returns the number of copied bytes. + * @to buffer and returns the number of copied bytes. * * Note that with only one concurrent reader and one concurrent * writer, you don't need extra locking to use these functions. */ -unsigned int kfifo_get(struct kfifo *fifo, - unsigned char *buffer, unsigned int len) +unsigned int kfifo_out(struct kfifo *fifo, + unsigned char *to, unsigned int len) { unsigned int l; @@ -174,10 +174,10 @@ unsigned int kfifo_get(struct kfifo *fifo, /* first get the data from fifo->out until the end of the buffer */ l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); - memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); + memcpy(to, fifo->buffer + (fifo->out & (fifo->size - 1)), l); /* then get the rest (if any) from the beginning of the buffer */ - memcpy(buffer + l, fifo->buffer, len - l); + memcpy(to + l, fifo->buffer, len - l); /* * Ensure that we remove the bytes from the kfifo -before- @@ -190,4 +190,4 @@ unsigned int kfifo_get(struct kfifo *fifo, return len; } -EXPORT_SYMBOL(kfifo_get); +EXPORT_SYMBOL(kfifo_out); diff --git a/net/dccp/probe.c b/net/dccp/probe.c index 9ef36849edd..a1362dc8abb 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c @@ -67,7 +67,7 @@ static void printl(const char *fmt, ...) len += vscnprintf(tbuf+len, sizeof(tbuf)-len, fmt, args); va_end(args); - kfifo_put_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); + kfifo_in_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); wake_up(&dccpw.wait); } @@ -135,7 +135,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf, if (error) goto out_free; - cnt = kfifo_get_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); + cnt = kfifo_out_locked(&dccpw.fifo, tbuf, len, &dccpw.lock); error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0; out_free: -- cgit v1.2.3-70-g09d2 From 9842c38e917636fa7dc6b88aff17a8f1fd7f0cc0 Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:29 -0800 Subject: kfifo: fix warn_unused_result Fix the "ignoring return value of '...', declared with attribute warn_unused_result" compiler warning in several users of the new kfifo API. It removes the __must_check attribute from kfifo_in() and kfifo_in_locked() which must not necessary performed. Fix the allocation bug in the nozomi driver file, by moving out the kfifo_alloc from the interrupt handler into the probe function. Fix the kfifo_out() and kfifo_out_locked() users to handle a unexpected end of fifo. Signed-off-by: Stefani Seibold Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/nozomi.c | 31 +++++++++++++++++++++++++---- drivers/infiniband/hw/cxgb3/cxio_resource.c | 5 +++-- drivers/media/video/meye.c | 5 +++-- drivers/net/wireless/libertas/main.c | 6 ++++-- drivers/scsi/libiscsi_tcp.c | 9 +++++++-- drivers/scsi/libsrp.c | 7 +++++-- include/linux/kfifo.h | 4 ++-- 7 files changed, 51 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c index 9ef24342901..7d73cd43034 100644 --- a/drivers/char/nozomi.c +++ b/drivers/char/nozomi.c @@ -685,8 +685,6 @@ static int nozomi_read_config_table(struct nozomi *dc) dump_table(dc); for (i = PORT_MDM; i < MAX_PORT; i++) { - kfifo_alloc(&dc->port[i].fifo_ul, - FIFO_BUFFER_SIZE_UL, GFP_ATOMIC); memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl)); memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul)); } @@ -1433,6 +1431,16 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, goto err_free_sbuf; } + for (i = PORT_MDM; i < MAX_PORT; i++) { + if (kfifo_alloc(&dc->port[i].fifo_ul, + FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) { + dev_err(&pdev->dev, + "Could not allocate kfifo buffer\n"); + ret = -ENOMEM; + goto err_free_kfifo; + } + } + spin_lock_init(&dc->spin_mutex); nozomi_setup_private_data(dc); @@ -1445,7 +1453,7 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, NOZOMI_NAME, dc); if (unlikely(ret)) { dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq); - goto err_free_sbuf; + goto err_free_kfifo; } DBG1("base_addr: %p", dc->base_addr); @@ -1464,13 +1472,28 @@ static int __devinit nozomi_card_init(struct pci_dev *pdev, dc->state = NOZOMI_STATE_ENABLED; for (i = 0; i < MAX_PORT; i++) { + struct device *tty_dev; + mutex_init(&dc->port[i].tty_sem); tty_port_init(&dc->port[i].port); - tty_register_device(ntty_driver, dc->index_start + i, + tty_dev = tty_register_device(ntty_driver, dc->index_start + i, &pdev->dev); + + if (IS_ERR(tty_dev)) { + ret = PTR_ERR(tty_dev); + dev_err(&pdev->dev, "Could not allocate tty?\n"); + goto err_free_tty; + } } + return 0; +err_free_tty: + for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i) + tty_unregister_device(ntty_driver, i); +err_free_kfifo: + for (i = 0; i < MAX_PORT; i++) + kfifo_free(&dc->port[i].fifo_ul); err_free_sbuf: kfree(dc->send_buf); iounmap(dc->base_addr); diff --git a/drivers/infiniband/hw/cxgb3/cxio_resource.c b/drivers/infiniband/hw/cxgb3/cxio_resource.c index dcbf2606c43..31f9201b298 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_resource.c +++ b/drivers/infiniband/hw/cxgb3/cxio_resource.c @@ -86,8 +86,9 @@ static int __cxio_init_resource_fifo(struct kfifo *fifo, kfifo_in(fifo, (unsigned char *) &i, sizeof(u32)); for (i = 0; i < skip_low + skip_high; i++) - kfifo_out_locked(fifo, (unsigned char *) &entry, - sizeof(u32), fifo_lock); + if (kfifo_out_locked(fifo, (unsigned char *) &entry, + sizeof(u32), fifo_lock) != sizeof(u32)) + break; return 0; } diff --git a/drivers/media/video/meye.c b/drivers/media/video/meye.c index 884a569d60a..b421858ccf9 100644 --- a/drivers/media/video/meye.c +++ b/drivers/media/video/meye.c @@ -968,8 +968,9 @@ static int meyeioc_sync(struct file *file, void *fh, int *i) /* fall through */ case MEYE_BUF_DONE: meye.grab_buffer[*i].state = MEYE_BUF_UNUSED; - kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, - sizeof(int), &meye.doneq_lock); + if (kfifo_out_locked(&meye.doneq, (unsigned char *)&unused, + sizeof(int), &meye.doneq_lock) != sizeof(int)) + break; } *i = meye.grab_buffer[*i].size; mutex_unlock(&meye.lock); diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 2bcfa745524..c2975c8e2f2 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c @@ -514,8 +514,10 @@ static int lbs_thread(void *data) while (kfifo_len(&priv->event_fifo)) { u32 event; - kfifo_out(&priv->event_fifo, (unsigned char *) &event, - sizeof(event)); + if (kfifo_out(&priv->event_fifo, + (unsigned char *) &event, sizeof(event)) != + sizeof(event)) + break; spin_unlock_irq(&priv->driver_lock); lbs_process_event(priv, event); spin_lock_irq(&priv->driver_lock); diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index d51ffeca2ec..db6856c138f 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -990,8 +990,13 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task) } if (r2t == NULL) { - kfifo_out(&tcp_task->r2tqueue, - (void *)&tcp_task->r2t, sizeof(void *)); + if (kfifo_out(&tcp_task->r2tqueue, + (void *)&tcp_task->r2t, sizeof(void *)) != + sizeof(void *)) { + WARN_ONCE(1, "unexpected fifo state"); + r2t = NULL; + } + r2t = tcp_task->r2t; } spin_unlock_bh(&session->lock); diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 8424b8606ef..ab19b3b4be5 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -163,8 +163,11 @@ struct iu_entry *srp_iu_get(struct srp_target *target) { struct iu_entry *iue = NULL; - kfifo_out_locked(&target->iu_queue.queue, (void *) &iue, - sizeof(void *), &target->iu_queue.lock); + if (kfifo_out_locked(&target->iu_queue.queue, (void *) &iue, + sizeof(void *), &target->iu_queue.lock) != sizeof(void *)) { + WARN_ONCE(1, "unexpected fifo state"); + return NULL; + } if (!iue) return iue; iue->target = target; diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h index 1b59c4a0e85..5ed2565c89b 100644 --- a/include/linux/kfifo.h +++ b/include/linux/kfifo.h @@ -56,7 +56,7 @@ extern void kfifo_init(struct kfifo *fifo, unsigned char *buffer, extern __must_check int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); extern void kfifo_free(struct kfifo *fifo); -extern __must_check unsigned int kfifo_in(struct kfifo *fifo, +extern unsigned int kfifo_in(struct kfifo *fifo, const unsigned char *from, unsigned int len); extern __must_check unsigned int kfifo_out(struct kfifo *fifo, unsigned char *to, unsigned int len); @@ -94,7 +94,7 @@ static inline unsigned int kfifo_len(struct kfifo *fifo) * the FIFO depending on the free space, and returns the number of * bytes copied. */ -static inline __must_check unsigned int kfifo_in_locked(struct kfifo *fifo, +static inline unsigned int kfifo_in_locked(struct kfifo *fifo, const unsigned char *from, unsigned int n, spinlock_t *lock) { unsigned long flags; -- cgit v1.2.3-70-g09d2 From 7801edb0b8b66e83c13623b483bc2e846c007c9d Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Mon, 21 Dec 2009 14:37:33 -0800 Subject: media video cx23888 driver: ported to new kfifo API Fix the cx23888 driver to use the new kfifo API. Using kfifo_reset() may result in a possible race conditions. This patch fixes it by using a spinlock around the kfifo_reset() function. Signed-off-by: Stefani Seibold Cc: Mauro Carvalho Chehab Reviewed-by: Andy Walls Acked-by: Andy Walls Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx23885/cx23888-ir.c | 44 ++++++++++++++------------------ 1 file changed, 19 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index 3ccc8afeccf..2bf57a4527d 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -124,15 +124,12 @@ struct cx23888_ir_state { atomic_t rxclk_divider; atomic_t rx_invert; - struct kfifo *rx_kfifo; + struct kfifo rx_kfifo; spinlock_t rx_kfifo_lock; struct v4l2_subdev_ir_parameters tx_params; struct mutex tx_params_lock; atomic_t txclk_divider; - - struct kfifo *tx_kfifo; - spinlock_t tx_kfifo_lock; }; static inline struct cx23888_ir_state *to_state(struct v4l2_subdev *sd) @@ -522,6 +519,7 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, { struct cx23888_ir_state *state = to_state(sd); struct cx23885_dev *dev = state->dev; + unsigned long flags; u32 cntrl = cx23888_ir_read4(dev, CX23888_IR_CNTRL_REG); u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); @@ -594,8 +592,9 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, if (i == 0) break; j = i * sizeof(u32); - k = kfifo_put(state->rx_kfifo, - (unsigned char *) rx_data, j); + k = kfifo_in_locked(&state->rx_kfifo, + (unsigned char *) rx_data, j, + &state->rx_kfifo_lock); if (k != j) kror++; /* rx_kfifo over run */ } @@ -631,8 +630,11 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, cx23888_ir_write4(dev, CX23888_IR_CNTRL_REG, cntrl); *handled = true; } - if (kfifo_len(state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) + + spin_lock_irqsave(&state->rx_kfifo_lock, flags); + if (kfifo_len(&state->rx_kfifo) >= CX23888_IR_RX_KFIFO_SIZE / 2) events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ; + spin_unlock_irqrestore(&state->rx_kfifo_lock, flags); if (events) v4l2_subdev_notify(sd, V4L2_SUBDEV_IR_RX_NOTIFY, &events); @@ -657,7 +659,7 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, return 0; } - n = kfifo_get(state->rx_kfifo, buf, n); + n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock); n /= sizeof(u32); *num = n * sizeof(u32); @@ -785,7 +787,12 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, o->interrupt_enable = p->interrupt_enable; o->enable = p->enable; if (p->enable) { - kfifo_reset(state->rx_kfifo); + unsigned long flags; + + spin_lock_irqsave(&state->rx_kfifo_lock, flags); + kfifo_reset(&state->rx_kfifo); + /* reset tx_fifo too if there is one... */ + spin_unlock_irqrestore(&state->rx_kfifo_lock, flags); if (p->interrupt_enable) irqenable_rx(dev, IRQEN_RSE | IRQEN_RTE | IRQEN_ROE); control_rx_enable(dev, p->enable); @@ -892,7 +899,6 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, o->interrupt_enable = p->interrupt_enable; o->enable = p->enable; if (p->enable) { - kfifo_reset(state->tx_kfifo); if (p->interrupt_enable) irqenable_tx(dev, IRQEN_TSE); control_tx_enable(dev, p->enable); @@ -1168,18 +1174,8 @@ int cx23888_ir_probe(struct cx23885_dev *dev) return -ENOMEM; spin_lock_init(&state->rx_kfifo_lock); - state->rx_kfifo = kfifo_alloc(CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL, - &state->rx_kfifo_lock); - if (state->rx_kfifo == NULL) - return -ENOMEM; - - spin_lock_init(&state->tx_kfifo_lock); - state->tx_kfifo = kfifo_alloc(CX23888_IR_TX_KFIFO_SIZE, GFP_KERNEL, - &state->tx_kfifo_lock); - if (state->tx_kfifo == NULL) { - kfifo_free(state->rx_kfifo); + if (kfifo_alloc(&state->rx_kfifo, CX23888_IR_RX_KFIFO_SIZE, GFP_KERNEL)) return -ENOMEM; - } state->dev = dev; state->id = V4L2_IDENT_CX23888_IR; @@ -1211,8 +1207,7 @@ int cx23888_ir_probe(struct cx23885_dev *dev) sizeof(struct v4l2_subdev_ir_parameters)); v4l2_subdev_call(sd, ir, tx_s_parameters, &default_params); } else { - kfifo_free(state->rx_kfifo); - kfifo_free(state->tx_kfifo); + kfifo_free(&state->rx_kfifo); } return ret; } @@ -1231,8 +1226,7 @@ int cx23888_ir_remove(struct cx23885_dev *dev) state = to_state(sd); v4l2_device_unregister_subdev(sd); - kfifo_free(state->rx_kfifo); - kfifo_free(state->tx_kfifo); + kfifo_free(&state->rx_kfifo); kfree(state); /* Nothing more to free() as state held the actual v4l2_subdev object */ return 0; -- cgit v1.2.3-70-g09d2 From 01136acff8cc8251822fbae77f11e8029049c6f1 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Mon, 21 Dec 2009 02:24:47 +0100 Subject: DRM: Rename clamp variable linux/kernel.h has a "clamp" macro, but r300_cmdbuf also uses a variable with the same name. Right now it doesn't seem to include the header, but sooner or later someone will. So better rename the variable now. Signed-off-by: Andi Kleen Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300_cmdbuf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index cb2e470f97d..34bffa0e4b7 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -990,7 +990,7 @@ static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv, int sz; int addr; int type; - int clamp; + int isclamp; int stride; RING_LOCALS; @@ -999,10 +999,10 @@ static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv, addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo; type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE); - clamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); + isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); addr |= (type << 16); - addr |= (clamp << 17); + addr |= (isclamp << 17); stride = type ? 4 : 6; -- cgit v1.2.3-70-g09d2 From e265f39e1ff026dcc787f1953c048f3de5aefd16 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 19 Dec 2009 08:16:33 +0100 Subject: drivers/gpu: Use kzalloc for allocating only one thing Use kzalloc rather than kcalloc(1,...) The use of the allocated memory that looks like an array is &p->relocs[0], but this should be the same as p->relocs. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ @@ - kcalloc(1, + kzalloc( ...) // Signed-off-by: Julia Lawall Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r600_cs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 0d820764f34..44060b92d9e 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -170,7 +170,7 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, idx, relocs_chunk->length_dw); return -EINVAL; } - *cs_reloc = &p->relocs[0]; + *cs_reloc = p->relocs; (*cs_reloc)->lobj.gpu_offset = (u64)relocs_chunk->kdata[idx + 3] << 32; (*cs_reloc)->lobj.gpu_offset |= relocs_chunk->kdata[idx + 0]; return 0; @@ -717,7 +717,7 @@ static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p) if (p->chunk_relocs_idx == -1) { return 0; } - p->relocs = kcalloc(1, sizeof(struct radeon_cs_reloc), GFP_KERNEL); + p->relocs = kzalloc(sizeof(struct radeon_cs_reloc), GFP_KERNEL); if (p->relocs == NULL) { return -ENOMEM; } -- cgit v1.2.3-70-g09d2 From 794f3141a194a4f4c28c1d417b071a901f78d9bb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 20 Dec 2009 16:08:40 +1000 Subject: drm/radeon: fix build on 64-bit with some compilers. drivers/gpu/drm/radeon/radeon_test.c:45: undefined reference to `__udivdi3' Reported-by: Mr. James W. Laferriere Cc: stable@kernel.org Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 391c973ec4d..9f5e2f929da 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -42,8 +42,8 @@ void radeon_test_moves(struct radeon_device *rdev) /* Number of tests = * (Total GTT - IB pool - writeback page - ring buffer) / test size */ - n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE - - rdev->cp.ring_size) / size; + n = ((u32)(rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - RADEON_GPU_PAGE_SIZE - + rdev->cp.ring_size)) / size; gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL); if (!gtt_obj) { -- cgit v1.2.3-70-g09d2 From e1f7800315d78686481b27b113a3317ac687b6bf Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 8 Dec 2009 12:57:51 +0100 Subject: drm/vmwgfx: Fix unlocked ioctl and add proper access control This fixes up vmwgfx for the unlocked ioctl code to avoid doing it in the driver. Also adds ioctl flags. Signed-off-by: Thomas Hellstrom Signed-off-by: Jakob Bornecrantz Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 47 +++++++++++++++---------------------- 1 file changed, 19 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 7b48bb3b63b..1db1ef30be2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -103,37 +103,39 @@ */ static struct drm_ioctl_desc vmw_ioctls[] = { - VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl, 0), + VMW_IOCTL_DEF(DRM_IOCTL_VMW_GET_PARAM, vmw_getparam_ioctl, + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_ALLOC_DMABUF, vmw_dmabuf_alloc_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_DMABUF, vmw_dmabuf_unref_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_CURSOR_BYPASS, - vmw_kms_cursor_bypass_ioctl, 0), + vmw_kms_cursor_bypass_ioctl, + DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_CONTROL_STREAM, vmw_overlay_ioctl, - 0), + DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_CLAIM_STREAM, vmw_stream_claim_ioctl, - 0), + DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_STREAM, vmw_stream_unref_ioctl, - 0), + DRM_MASTER | DRM_CONTROL_ALLOW | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_CONTEXT, vmw_context_define_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_CONTEXT, vmw_context_destroy_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_CREATE_SURFACE, vmw_surface_define_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_UNREF_SURFACE, vmw_surface_destroy_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_REF_SURFACE, vmw_surface_reference_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_EXECBUF, vmw_execbuf_ioctl, - 0), + DRM_AUTH | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_FIFO_DEBUG, vmw_fifo_debug_ioctl, - 0), + DRM_AUTH | DRM_ROOT_ONLY | DRM_MASTER | DRM_UNLOCKED), VMW_IOCTL_DEF(DRM_IOCTL_VMW_FENCE_WAIT, vmw_fence_wait_ioctl, - 0) + DRM_AUTH | DRM_UNLOCKED) }; static struct pci_device_id vmw_pci_id_list[] = { @@ -460,11 +462,9 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd, struct drm_file *file_priv = filp->private_data; struct drm_device *dev = file_priv->minor->dev; unsigned int nr = DRM_IOCTL_NR(cmd); - long ret; /* - * The driver private ioctls and TTM ioctls should be - * thread-safe. + * Do extra checking on driver private ioctls. */ if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) @@ -477,18 +477,9 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd, nr - DRM_COMMAND_BASE); return -EINVAL; } - return drm_ioctl(filp->f_path.dentry->d_inode, - filp, cmd, arg); } - /* - * Not all old drm ioctls are thread-safe. - */ - - lock_kernel(); - ret = drm_ioctl(filp->f_path.dentry->d_inode, filp, cmd, arg); - unlock_kernel(); - return ret; + return drm_ioctl(filp, cmd, arg); } static int vmw_firstopen(struct drm_device *dev) -- cgit v1.2.3-70-g09d2 From 3d3a5b3290043618e8409f3fb68a63de6156fdd4 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 8 Dec 2009 12:59:34 +0100 Subject: drm/vmwgfx: Return -ERESTARTSYS when interrupted by a signal. Fixes for TTM API change. Signed-off-by: Thomas Hellstrom Signed-off-by: Jakob Bornecrantz Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 4 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 6 ++---- drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 6 ++---- 3 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 7a39f3e6dc2..7e73cf51e29 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -386,7 +386,7 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv, return 0; ret = vmw_gmr_bind(dev_priv, bo); - if (likely(ret == 0 || ret == -ERESTART)) + if (likely(ret == 0 || ret == -ERESTARTSYS)) return ret; @@ -429,7 +429,7 @@ int vmw_execbuf_ioctl(struct drm_device *dev, void *data, ret = mutex_lock_interruptible(&dev_priv->cmdbuf_mutex); if (unlikely(ret != 0)) { - ret = -ERESTART; + ret = -ERESTARTSYS; goto out_no_cmd_mutex; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 76b0693e245..01feb48af33 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c @@ -191,7 +191,7 @@ static int vmw_fifo_wait_noirq(struct vmw_private *dev_priv, } schedule_timeout(1); if (interruptible && signal_pending(current)) { - ret = -ERESTART; + ret = -ERESTARTSYS; break; } } @@ -237,9 +237,7 @@ static int vmw_fifo_wait(struct vmw_private *dev_priv, (dev_priv->fifo_queue, !vmw_fifo_is_full(dev_priv, bytes), timeout); - if (unlikely(ret == -ERESTARTSYS)) - ret = -ERESTART; - else if (unlikely(ret == 0)) + if (unlikely(ret == 0)) ret = -EBUSY; else if (likely(ret > 0)) ret = 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 9e0f0306eed..d40086fc864 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -155,7 +155,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, TASK_UNINTERRUPTIBLE); } if (interruptible && signal_pending(current)) { - ret = -ERESTART; + ret = -ERESTARTSYS; break; } } @@ -218,9 +218,7 @@ int vmw_wait_fence(struct vmw_private *dev_priv, vmw_fence_signaled(dev_priv, sequence), timeout); - if (unlikely(ret == -ERESTARTSYS)) - ret = -ERESTART; - else if (unlikely(ret == 0)) + if (unlikely(ret == 0)) ret = -EBUSY; else if (likely(ret > 0)) ret = 0; -- cgit v1.2.3-70-g09d2 From 7a73ba7469cbea631050094fd14f73acebb97cf9 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Tue, 22 Dec 2009 16:53:41 +0100 Subject: drm/vmwgfx: Use TTM handles instead of SIDs as user-space surface handles. Improve the command verifier to catch all occurences of surface handles, and translate to SIDs. This way DMA buffers and 3D surfaces share a common handle space, which makes it possible for the kms code to differentiate. Signed-off-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 10 +- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 153 ++++++++++++++++++++++++++----- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 149 ++++++++++++++---------------- 4 files changed, 209 insertions(+), 111 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 43546d09d1b..e61bd85b697 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -123,6 +123,7 @@ struct vmw_sw_context{ uint32_t last_cid; bool cid_valid; uint32_t last_sid; + uint32_t sid_translation; bool sid_valid; struct ttm_object_file *tfile; struct list_head validate_nodes; @@ -317,9 +318,10 @@ extern void vmw_surface_res_free(struct vmw_resource *res); extern int vmw_surface_init(struct vmw_private *dev_priv, struct vmw_surface *srf, void (*res_free) (struct vmw_resource *res)); -extern int vmw_user_surface_lookup(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - int sid, struct vmw_surface **out); +extern int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv, + struct ttm_object_file *tfile, + uint32_t handle, + struct vmw_surface **out); extern int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_surface_define_ioctl(struct drm_device *dev, void *data, @@ -328,7 +330,7 @@ extern int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); extern int vmw_surface_check(struct vmw_private *dev_priv, struct ttm_object_file *tfile, - int id); + uint32_t handle, int *id); extern void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo); extern int vmw_dmabuf_init(struct vmw_private *dev_priv, struct vmw_dma_buffer *vmw_bo, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 7e73cf51e29..2e92da56740 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -73,21 +73,32 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv, static int vmw_cmd_sid_check(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, - uint32_t sid) + uint32_t *sid) { - if (unlikely((!sw_context->sid_valid || sid != sw_context->last_sid) && - sid != SVGA3D_INVALID_ID)) { - int ret = vmw_surface_check(dev_priv, sw_context->tfile, sid); + if (*sid == SVGA3D_INVALID_ID) + return 0; + + if (unlikely((!sw_context->sid_valid || + *sid != sw_context->last_sid))) { + int real_id; + int ret = vmw_surface_check(dev_priv, sw_context->tfile, + *sid, &real_id); if (unlikely(ret != 0)) { - DRM_ERROR("Could ot find or use surface %u\n", - (unsigned) sid); + DRM_ERROR("Could ot find or use surface 0x%08x " + "address 0x%08lx\n", + (unsigned int) *sid, + (unsigned long) sid); return ret; } - sw_context->last_sid = sid; + sw_context->last_sid = *sid; sw_context->sid_valid = true; - } + *sid = real_id; + sw_context->sid_translation = real_id; + } else + *sid = sw_context->sid_translation; + return 0; } @@ -107,7 +118,8 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, return ret; cmd = container_of(header, struct vmw_sid_cmd, header); - return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.target.sid); + ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.target.sid); + return ret; } static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv, @@ -121,10 +133,10 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv, int ret; cmd = container_of(header, struct vmw_sid_cmd, header); - ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid); + ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid); if (unlikely(ret != 0)) return ret; - return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid); + return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid); } static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv, @@ -138,10 +150,10 @@ static int vmw_cmd_stretch_blt_check(struct vmw_private *dev_priv, int ret; cmd = container_of(header, struct vmw_sid_cmd, header); - ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.src.sid); + ret = vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.src.sid); if (unlikely(ret != 0)) return ret; - return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.dest.sid); + return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.dest.sid); } static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv, @@ -154,7 +166,7 @@ static int vmw_cmd_blt_surf_screen_check(struct vmw_private *dev_priv, } *cmd; cmd = container_of(header, struct vmw_sid_cmd, header); - return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.srcImage.sid); + return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.srcImage.sid); } static int vmw_cmd_present_check(struct vmw_private *dev_priv, @@ -167,7 +179,7 @@ static int vmw_cmd_present_check(struct vmw_private *dev_priv, } *cmd; cmd = container_of(header, struct vmw_sid_cmd, header); - return vmw_cmd_sid_check(dev_priv, sw_context, cmd->body.sid); + return vmw_cmd_sid_check(dev_priv, sw_context, &cmd->body.sid); } static int vmw_cmd_dma(struct vmw_private *dev_priv, @@ -187,12 +199,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, uint32_t cur_validate_node; struct ttm_validate_buffer *val_buf; - cmd = container_of(header, struct vmw_dma_cmd, header); - ret = vmw_cmd_sid_check(dev_priv, sw_context, cmd->dma.host.sid); - if (unlikely(ret != 0)) - return ret; - handle = cmd->dma.guest.ptr.gmrId; ret = vmw_user_dmabuf_lookup(sw_context->tfile, handle, &vmw_bo); if (unlikely(ret != 0)) { @@ -228,14 +235,23 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv, ++sw_context->cur_val_buf; } - ret = vmw_user_surface_lookup(dev_priv, sw_context->tfile, - cmd->dma.host.sid, &srf); + ret = vmw_user_surface_lookup_handle(dev_priv, sw_context->tfile, + cmd->dma.host.sid, &srf); if (ret) { DRM_ERROR("could not find surface\n"); goto out_no_reloc; } + /** + * Patch command stream with device SID. + */ + + cmd->dma.host.sid = srf->res.id; vmw_kms_cursor_snoop(srf, sw_context->tfile, bo, header); + /** + * FIXME: May deadlock here when called from the + * command parsing code. + */ vmw_surface_unreference(&srf); out_no_reloc: @@ -243,6 +259,90 @@ out_no_reloc: return ret; } +static int vmw_cmd_draw(struct vmw_private *dev_priv, + struct vmw_sw_context *sw_context, + SVGA3dCmdHeader *header) +{ + struct vmw_draw_cmd { + SVGA3dCmdHeader header; + SVGA3dCmdDrawPrimitives body; + } *cmd; + SVGA3dVertexDecl *decl = (SVGA3dVertexDecl *)( + (unsigned long)header + sizeof(*cmd)); + SVGA3dPrimitiveRange *range; + uint32_t i; + uint32_t maxnum; + int ret; + + ret = vmw_cmd_cid_check(dev_priv, sw_context, header); + if (unlikely(ret != 0)) + return ret; + + cmd = container_of(header, struct vmw_draw_cmd, header); + maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl); + + if (unlikely(cmd->body.numVertexDecls > maxnum)) { + DRM_ERROR("Illegal number of vertex declarations.\n"); + return -EINVAL; + } + + for (i = 0; i < cmd->body.numVertexDecls; ++i, ++decl) { + ret = vmw_cmd_sid_check(dev_priv, sw_context, + &decl->array.surfaceId); + if (unlikely(ret != 0)) + return ret; + } + + maxnum = (header->size - sizeof(cmd->body) - + cmd->body.numVertexDecls * sizeof(*decl)) / sizeof(*range); + if (unlikely(cmd->body.numRanges > maxnum)) { + DRM_ERROR("Illegal number of index ranges.\n"); + return -EINVAL; + } + + range = (SVGA3dPrimitiveRange *) decl; + for (i = 0; i < cmd->body.numRanges; ++i, ++range) { + ret = vmw_cmd_sid_check(dev_priv, sw_context, + &range->indexArray.surfaceId); + if (unlikely(ret != 0)) + return ret; + } + return 0; +} + + +static int vmw_cmd_tex_state(struct vmw_private *dev_priv, + struct vmw_sw_context *sw_context, + SVGA3dCmdHeader *header) +{ + struct vmw_tex_state_cmd { + SVGA3dCmdHeader header; + SVGA3dCmdSetTextureState state; + }; + + SVGA3dTextureState *last_state = (SVGA3dTextureState *) + ((unsigned long) header + header->size + sizeof(header)); + SVGA3dTextureState *cur_state = (SVGA3dTextureState *) + ((unsigned long) header + sizeof(struct vmw_tex_state_cmd)); + int ret; + + ret = vmw_cmd_cid_check(dev_priv, sw_context, header); + if (unlikely(ret != 0)) + return ret; + + for (; cur_state < last_state; ++cur_state) { + if (likely(cur_state->name != SVGA3D_TS_BIND_TEXTURE)) + continue; + + ret = vmw_cmd_sid_check(dev_priv, sw_context, + &cur_state->value); + if (unlikely(ret != 0)) + return ret; + } + + return 0; +} + typedef int (*vmw_cmd_func) (struct vmw_private *, struct vmw_sw_context *, @@ -264,7 +364,7 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = { VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERSTATE, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_SETRENDERTARGET, &vmw_cmd_set_render_target_check), - VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_cid_check), + VMW_CMD_DEF(SVGA_3D_CMD_SETTEXTURESTATE, &vmw_cmd_tex_state), VMW_CMD_DEF(SVGA_3D_CMD_SETMATERIAL, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTDATA, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_SETLIGHTENABLED, &vmw_cmd_cid_check), @@ -276,7 +376,7 @@ static vmw_cmd_func vmw_cmd_funcs[SVGA_3D_CMD_MAX] = { VMW_CMD_DEF(SVGA_3D_CMD_SHADER_DESTROY, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_SET_SHADER_CONST, &vmw_cmd_cid_check), - VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_cid_check), + VMW_CMD_DEF(SVGA_3D_CMD_DRAW_PRIMITIVES, &vmw_cmd_draw), VMW_CMD_DEF(SVGA_3D_CMD_SETSCISSORRECT, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_BEGIN_QUERY, &vmw_cmd_cid_check), VMW_CMD_DEF(SVGA_3D_CMD_END_QUERY, &vmw_cmd_cid_check), @@ -291,6 +391,7 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, void *buf, uint32_t *size) { uint32_t cmd_id; + uint32_t size_remaining = *size; SVGA3dCmdHeader *header = (SVGA3dCmdHeader *) buf; int ret; @@ -304,6 +405,9 @@ static int vmw_cmd_check(struct vmw_private *dev_priv, *size = le32_to_cpu(header->size) + sizeof(SVGA3dCmdHeader); cmd_id -= SVGA_3D_CMD_BASE; + if (unlikely(*size > size_remaining)) + goto out_err; + if (unlikely(cmd_id >= SVGA_3D_CMD_MAX - SVGA_3D_CMD_BASE)) goto out_err; @@ -326,6 +430,7 @@ static int vmw_cmd_check_all(struct vmw_private *dev_priv, int ret; while (cur_size > 0) { + size = cur_size; ret = vmw_cmd_check(dev_priv, sw_context, buf, &size); if (unlikely(ret != 0)) return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e9403be446f..b1af76e371c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -106,8 +106,8 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, int ret; if (handle) { - ret = vmw_user_surface_lookup(dev_priv, tfile, - handle, &surface); + ret = vmw_user_surface_lookup_handle(dev_priv, tfile, + handle, &surface); if (!ret) { if (!surface->snooper.image) { DRM_ERROR("surface not suitable for cursor\n"); @@ -704,8 +704,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, struct vmw_dma_buffer *bo = NULL; int ret; - ret = vmw_user_surface_lookup(dev_priv, tfile, - mode_cmd->handle, &surface); + ret = vmw_user_surface_lookup_handle(dev_priv, tfile, + mode_cmd->handle, &surface); if (ret) goto try_dmabuf; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index a1ceed0c8e0..c012d5927f6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -488,28 +488,44 @@ static void vmw_user_surface_free(struct vmw_resource *res) kfree(user_srf); } -int vmw_user_surface_lookup(struct vmw_private *dev_priv, - struct ttm_object_file *tfile, - int sid, struct vmw_surface **out) +int vmw_user_surface_lookup_handle(struct vmw_private *dev_priv, + struct ttm_object_file *tfile, + uint32_t handle, struct vmw_surface **out) { struct vmw_resource *res; struct vmw_surface *srf; struct vmw_user_surface *user_srf; + struct ttm_base_object *base; + int ret = -EINVAL; - res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, sid); - if (unlikely(res == NULL)) + base = ttm_base_object_lookup(tfile, handle); + if (unlikely(base == NULL)) return -EINVAL; - if (res->res_free != &vmw_user_surface_free) - return -EINVAL; + if (unlikely(base->object_type != VMW_RES_SURFACE)) + goto out_bad_resource; - srf = container_of(res, struct vmw_surface, res); - user_srf = container_of(srf, struct vmw_user_surface, srf); - if (user_srf->base.tfile != tfile && !user_srf->base.shareable) - return -EPERM; + user_srf = container_of(base, struct vmw_user_surface, base); + srf = &user_srf->srf; + res = &srf->res; + + read_lock(&dev_priv->resource_lock); + + if (!res->avail || res->res_free != &vmw_user_surface_free) { + read_unlock(&dev_priv->resource_lock); + goto out_bad_resource; + } + + kref_get(&res->kref); + read_unlock(&dev_priv->resource_lock); *out = srf; - return 0; + ret = 0; + +out_bad_resource: + ttm_base_object_unref(&base); + + return ret; } static void vmw_user_surface_base_release(struct ttm_base_object **p_base) @@ -526,35 +542,10 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base) int vmw_surface_destroy_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct vmw_private *dev_priv = vmw_priv(dev); - struct vmw_resource *res; - struct vmw_surface *srf; - struct vmw_user_surface *user_srf; struct drm_vmw_surface_arg *arg = (struct drm_vmw_surface_arg *)data; struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - int ret = 0; - - res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, arg->sid); - if (unlikely(res == NULL)) - return -EINVAL; - - if (res->res_free != &vmw_user_surface_free) { - ret = -EINVAL; - goto out; - } - srf = container_of(res, struct vmw_surface, res); - user_srf = container_of(srf, struct vmw_user_surface, srf); - if (user_srf->base.tfile != tfile && !user_srf->base.shareable) { - ret = -EPERM; - goto out; - } - - ttm_ref_object_base_unref(tfile, user_srf->base.hash.key, - TTM_REF_USAGE); -out: - vmw_resource_unreference(&res); - return ret; + return ttm_ref_object_base_unref(tfile, arg->sid, TTM_REF_USAGE); } int vmw_surface_define_ioctl(struct drm_device *dev, void *data, @@ -649,7 +640,10 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, } srf->snooper.crtc = NULL; - rep->sid = res->id; + rep->sid = user_srf->base.hash.key; + if (rep->sid == SVGA3D_INVALID_ID) + DRM_ERROR("Created bad Surface ID.\n"); + vmw_resource_unreference(&res); return 0; out_err1: @@ -662,39 +656,33 @@ out_err0: int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct vmw_private *dev_priv = vmw_priv(dev); union drm_vmw_surface_reference_arg *arg = (union drm_vmw_surface_reference_arg *)data; struct drm_vmw_surface_arg *req = &arg->req; struct drm_vmw_surface_create_req *rep = &arg->rep; struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - struct vmw_resource *res; struct vmw_surface *srf; struct vmw_user_surface *user_srf; struct drm_vmw_size __user *user_sizes; - int ret; + struct ttm_base_object *base; + int ret = -EINVAL; - res = vmw_resource_lookup(dev_priv, &dev_priv->surface_idr, req->sid); - if (unlikely(res == NULL)) + base = ttm_base_object_lookup(tfile, req->sid); + if (unlikely(base == NULL)) { + DRM_ERROR("Could not find surface to reference.\n"); return -EINVAL; - - if (res->res_free != &vmw_user_surface_free) { - ret = -EINVAL; - goto out; } - srf = container_of(res, struct vmw_surface, res); - user_srf = container_of(srf, struct vmw_user_surface, srf); - if (user_srf->base.tfile != tfile && !user_srf->base.shareable) { - DRM_ERROR("Tried to reference none shareable surface\n"); - ret = -EPERM; - goto out; - } + if (unlikely(base->object_type != VMW_RES_SURFACE)) + goto out_bad_resource; + + user_srf = container_of(base, struct vmw_user_surface, base); + srf = &user_srf->srf; ret = ttm_ref_object_add(tfile, &user_srf->base, TTM_REF_USAGE, NULL); if (unlikely(ret != 0)) { DRM_ERROR("Could not add a reference to a surface.\n"); - goto out; + goto out_no_reference; } rep->flags = srf->flags; @@ -706,40 +694,43 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data, if (user_sizes) ret = copy_to_user(user_sizes, srf->sizes, srf->num_sizes * sizeof(*srf->sizes)); - if (unlikely(ret != 0)) { + if (unlikely(ret != 0)) DRM_ERROR("copy_to_user failed %p %u\n", user_sizes, srf->num_sizes); - /** - * FIXME: Unreference surface here? - */ - goto out; - } -out: - vmw_resource_unreference(&res); +out_bad_resource: +out_no_reference: + ttm_base_object_unref(&base); + return ret; } int vmw_surface_check(struct vmw_private *dev_priv, struct ttm_object_file *tfile, - int id) + uint32_t handle, int *id) { - struct vmw_resource *res; - int ret = 0; + struct ttm_base_object *base; + struct vmw_user_surface *user_srf; - read_lock(&dev_priv->resource_lock); - res = idr_find(&dev_priv->surface_idr, id); - if (res && res->avail) { - struct vmw_surface *srf = - container_of(res, struct vmw_surface, res); - struct vmw_user_surface *usrf = - container_of(srf, struct vmw_user_surface, srf); + int ret = -EPERM; - if (usrf->base.tfile != tfile && !usrf->base.shareable) - ret = -EPERM; - } else - ret = -EINVAL; - read_unlock(&dev_priv->resource_lock); + base = ttm_base_object_lookup(tfile, handle); + if (unlikely(base == NULL)) + return -EINVAL; + + if (unlikely(base->object_type != VMW_RES_SURFACE)) + goto out_bad_surface; + user_srf = container_of(base, struct vmw_user_surface, base); + *id = user_srf->srf.res.id; + ret = 0; + +out_bad_surface: + /** + * FIXME: May deadlock here when called from the + * command parsing code. + */ + + ttm_base_object_unref(&base); return ret; } -- cgit v1.2.3-70-g09d2 From e2108eb1f66d77b4af77caf282cab1d47e3f4831 Mon Sep 17 00:00:00 2001 From: Bob Gleitsmann Date: Mon, 21 Dec 2009 13:52:09 +1000 Subject: drm/mm: fix logic for selection of best fit block This is from bug 25728. [airlied: I'm just forwarding the patch for review, Thomas, ickle?] Acked-by: Jerome Glisse Acked-by: Thomas Hellstrom Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_mm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index d7d7eac3ddd..cdec3297712 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -358,7 +358,7 @@ struct drm_mm_node *drm_mm_search_free(const struct drm_mm *mm, if (entry->size >= size + wasted) { if (!best_match) return entry; - if (size < best_size) { + if (entry->size < best_size) { best = entry; best_size = entry->size; } @@ -408,7 +408,7 @@ struct drm_mm_node *drm_mm_search_free_in_range(const struct drm_mm *mm, if (entry->size >= size + wasted) { if (!best_match) return entry; - if (size < best_size) { + if (entry->size < best_size) { best = entry; best_size = entry->size; } -- cgit v1.2.3-70-g09d2 From 29ebdf925c2c45f6531a953c6c5c8e4d3b4ac2dc Mon Sep 17 00:00:00 2001 From: Marin Mitov Date: Sun, 20 Dec 2009 09:03:27 +0200 Subject: drm/kms: silencing a false positive warning. warning: 'width' may be used uninitialized in this function drivers/gpu/drm/drm_edid.c Signed-off-by: Marin Mitov Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_edid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c39b26f1abe..5c9f79877cb 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -913,7 +913,7 @@ static int drm_cvt_modes(struct drm_connector *connector, const int rates[] = { 60, 85, 75, 60, 50 }; for (i = 0; i < 4; i++) { - int width, height; + int uninitialized_var(width), height; cvt = &(timing->data.other_data.data.cvt[i]); height = (cvt->code[0] + ((cvt->code[1] & 0xf0) << 8) + 1) * 2; -- cgit v1.2.3-70-g09d2 From edc664e314d5dadc326cfc15a536fe906d652204 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 17 Dec 2009 11:22:01 -0500 Subject: drm/radeon/kms/atom: fill in proper defines for digital setup Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 0d1d908e522..547fe105e19 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -495,9 +495,9 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) args.v1.ucMisc |= PANEL_ENCODER_MISC_HDMI_TYPE; args.v1.usPixelClock = cpu_to_le16(radeon_encoder->pixel_clock / 10); if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { - if (dig->lvds_misc & (1 << 0)) + if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) args.v1.ucMisc |= PANEL_ENCODER_MISC_DUAL; - if (dig->lvds_misc & (1 << 1)) + if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) args.v1.ucMisc |= (1 << 1); } else { if (dig_connector->linkb) @@ -524,18 +524,18 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) args.v2.ucTemporal = 0; args.v2.ucFRC = 0; if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) { - if (dig->lvds_misc & (1 << 0)) + if (dig->lvds_misc & ATOM_PANEL_MISC_DUAL) args.v2.ucMisc |= PANEL_ENCODER_MISC_DUAL; - if (dig->lvds_misc & (1 << 5)) { + if (dig->lvds_misc & ATOM_PANEL_MISC_SPATIAL) { args.v2.ucSpatial = PANEL_ENCODER_SPATIAL_DITHER_EN; - if (dig->lvds_misc & (1 << 1)) + if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) args.v2.ucSpatial |= PANEL_ENCODER_SPATIAL_DITHER_DEPTH; } - if (dig->lvds_misc & (1 << 6)) { + if (dig->lvds_misc & ATOM_PANEL_MISC_TEMPORAL) { args.v2.ucTemporal = PANEL_ENCODER_TEMPORAL_DITHER_EN; - if (dig->lvds_misc & (1 << 1)) + if (dig->lvds_misc & ATOM_PANEL_MISC_888RGB) args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_DITHER_DEPTH; - if (((dig->lvds_misc >> 2) & 0x3) == 2) + if (((dig->lvds_misc >> ATOM_PANEL_MISC_GREY_LEVEL_SHIFT) & 0x3) == 2) args.v2.ucTemporal |= PANEL_ENCODER_TEMPORAL_LEVEL_4; } } else { -- cgit v1.2.3-70-g09d2 From 310a82c8c5fc431913fe34a17251118e71c2c876 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 17 Dec 2009 01:24:59 -0500 Subject: drm/radeon/kms: fix legacy rmx This makes 640x480 on my R100 work again, both in aspect and centered mode. Signed-off-by: Alex Deucher Tested-by: Dave Airlie Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_encoders.c | 2 ++ drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 5 ++--- drivers/gpu/drm/radeon/radeon_legacy_encoders.c | 2 ++ 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c index 547fe105e19..ccba95f83d1 100644 --- a/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_encoders.c @@ -233,6 +233,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, if (!ASIC_IS_AVIVO(rdev)) { adjusted_mode->hdisplay = mode->hdisplay; adjusted_mode->vdisplay = mode->vdisplay; + adjusted_mode->crtc_hdisplay = mode->hdisplay; + adjusted_mode->crtc_vdisplay = mode->vdisplay; } adjusted_mode->base.id = mode_id; } diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index b82ede98e15..cc27485a07a 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -43,8 +43,7 @@ static void radeon_overscan_setup(struct drm_crtc *crtc, } static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) + struct drm_display_mode *mode) { struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; @@ -1059,7 +1058,7 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, radeon_set_pll(crtc, adjusted_mode); radeon_overscan_setup(crtc, adjusted_mode); if (radeon_crtc->crtc_id == 0) { - radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode); + radeon_legacy_rmx_mode_set(crtc, adjusted_mode); } else { if (radeon_crtc->rmx_type != RMX_OFF) { /* FIXME: only first crtc has rmx what should we diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index df00515e81f..981508ff703 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -207,6 +207,8 @@ static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder, *adjusted_mode = *native_mode; adjusted_mode->hdisplay = mode->hdisplay; adjusted_mode->vdisplay = mode->vdisplay; + adjusted_mode->crtc_hdisplay = mode->hdisplay; + adjusted_mode->crtc_vdisplay = mode->vdisplay; adjusted_mode->base.id = mode_id; } -- cgit v1.2.3-70-g09d2 From d79766fab9975c6414ebab7d2abf017834a48c35 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Thu, 17 Dec 2009 19:00:29 -0500 Subject: drm/radeon/kms: set proper default tv standard we were just using 1 before. reported on irc by soreau Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 56 ++++++++++++++++++++++++++++++ drivers/gpu/drm/radeon/radeon_combios.c | 9 +++-- drivers/gpu/drm/radeon/radeon_connectors.c | 4 +-- drivers/gpu/drm/radeon/radeon_display.c | 2 +- drivers/gpu/drm/radeon/radeon_mode.h | 6 ++++ 5 files changed, 69 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 12a0c760e7f..b5912c26b1d 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1234,6 +1234,61 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index, return true; } +enum radeon_tv_std +radeon_atombios_get_tv_info(struct radeon_device *rdev) +{ + struct radeon_mode_info *mode_info = &rdev->mode_info; + int index = GetIndexIntoMasterTable(DATA, AnalogTV_Info); + uint16_t data_offset; + uint8_t frev, crev; + struct _ATOM_ANALOG_TV_INFO *tv_info; + enum radeon_tv_std tv_std = TV_STD_NTSC; + + atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset); + + tv_info = (struct _ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset); + + switch (tv_info->ucTV_BootUpDefaultStandard) { + case ATOM_TV_NTSC: + tv_std = TV_STD_NTSC; + DRM_INFO("Default TV standard: NTSC\n"); + break; + case ATOM_TV_NTSCJ: + tv_std = TV_STD_NTSC_J; + DRM_INFO("Default TV standard: NTSC-J\n"); + break; + case ATOM_TV_PAL: + tv_std = TV_STD_PAL; + DRM_INFO("Default TV standard: PAL\n"); + break; + case ATOM_TV_PALM: + tv_std = TV_STD_PAL_M; + DRM_INFO("Default TV standard: PAL-M\n"); + break; + case ATOM_TV_PALN: + tv_std = TV_STD_PAL_N; + DRM_INFO("Default TV standard: PAL-N\n"); + break; + case ATOM_TV_PALCN: + tv_std = TV_STD_PAL_CN; + DRM_INFO("Default TV standard: PAL-CN\n"); + break; + case ATOM_TV_PAL60: + tv_std = TV_STD_PAL_60; + DRM_INFO("Default TV standard: PAL-60\n"); + break; + case ATOM_TV_SECAM: + tv_std = TV_STD_SECAM; + DRM_INFO("Default TV standard: SECAM\n"); + break; + default: + tv_std = TV_STD_NTSC; + DRM_INFO("Unknown TV standard; defaulting to NTSC\n"); + break; + } + return tv_std; +} + struct radeon_encoder_tv_dac * radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) { @@ -1269,6 +1324,7 @@ radeon_atombios_get_tv_dac_info(struct radeon_encoder *encoder) dac = dac_info->ucDAC2_NTSC_DAC_Adjustment; tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); + tv_dac->tv_std = radeon_atombios_get_tv_info(rdev); } return tv_dac; } diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index c5021a3445d..fd94dbca33a 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -634,11 +634,10 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct return p_dac; } -static enum radeon_tv_std -radeon_combios_get_tv_info(struct radeon_encoder *encoder) +enum radeon_tv_std +radeon_combios_get_tv_info(struct radeon_device *rdev) { - struct drm_device *dev = encoder->base.dev; - struct radeon_device *rdev = dev->dev_private; + struct drm_device *dev = rdev->ddev; uint16_t tv_info; enum radeon_tv_std tv_std = TV_STD_NTSC; @@ -779,7 +778,7 @@ struct radeon_encoder_tv_dac *radeon_combios_get_tv_dac_info(struct tv_dac->ntsc_tvdac_adj = (bg << 16) | (dac << 20); found = 1; } - tv_dac->tv_std = radeon_combios_get_tv_info(encoder); + tv_dac->tv_std = radeon_combios_get_tv_info(rdev); } if (!found) { /* then check CRT table */ diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 5eece186e03..8da06e17ff2 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -1171,7 +1171,7 @@ radeon_add_atom_connector(struct drm_device *dev, 1); drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.tv_std_property, - 1); + radeon_atombios_get_tv_info(rdev)); } break; case DRM_MODE_CONNECTOR_LVDS: @@ -1315,7 +1315,7 @@ radeon_add_legacy_connector(struct drm_device *dev, 1); drm_connector_attach_property(&radeon_connector->base, rdev->mode_info.tv_std_property, - 1); + radeon_combios_get_tv_info(rdev)); } break; case DRM_MODE_CONNECTOR_LVDS: diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index a133b833e45..91d72b70abc 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -739,7 +739,7 @@ static struct drm_prop_enum_list radeon_tv_std_enum_list[] = { TV_STD_SECAM, "secam" }, }; -int radeon_modeset_create_props(struct radeon_device *rdev) +static int radeon_modeset_create_props(struct radeon_device *rdev) { int i, sz; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 3dcbe130c42..402369db5ba 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -88,6 +88,7 @@ enum radeon_tv_std { TV_STD_SCART_PAL, TV_STD_SECAM, TV_STD_PAL_CN, + TV_STD_PAL_N, }; /* radeon gpio-based i2c @@ -395,6 +396,11 @@ struct radeon_framebuffer { struct drm_gem_object *obj; }; +extern enum radeon_tv_std +radeon_combios_get_tv_info(struct radeon_device *rdev); +extern enum radeon_tv_std +radeon_atombios_get_tv_info(struct radeon_device *rdev); + extern void radeon_connector_hotplug(struct drm_connector *connector); extern bool radeon_dp_needs_link_train(struct radeon_connector *radeon_connector); extern int radeon_dp_mode_valid_helper(struct radeon_connector *radeon_connector, -- cgit v1.2.3-70-g09d2 From c31ad97f1886a2ff0f3356dc31d50c57944365da Mon Sep 17 00:00:00 2001 From: RafaÅ‚ MiÅ‚ecki Date: Thu, 17 Dec 2009 00:00:46 +0100 Subject: drm/radeon/kms: prevent parallel AtomBIOS calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This just adds a mutex around the atombios table execution so we don't call it from two contexts at once. Signed-off-by: RafaÅ‚ MiÅ‚ecki Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atom.c | 12 ++++++++++-- drivers/gpu/drm/radeon/atom.h | 1 + drivers/gpu/drm/radeon/radeon_device.c | 1 + 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 6578d19dff9..388140a7e65 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -58,6 +58,7 @@ typedef struct { } atom_exec_context; int atom_debug = 0; +static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params); void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params); static uint32_t atom_arg_mask[8] = @@ -573,7 +574,7 @@ static void atom_op_calltable(atom_exec_context *ctx, int *ptr, int arg) else SDEBUG(" table: %d\n", idx); if (U16(ctx->ctx->cmd_table + 4 + 2 * idx)) - atom_execute_table(ctx->ctx, idx, ctx->ps + ctx->ps_shift); + atom_execute_table_locked(ctx->ctx, idx, ctx->ps + ctx->ps_shift); } static void atom_op_clear(atom_exec_context *ctx, int *ptr, int arg) @@ -1040,7 +1041,7 @@ static struct { atom_op_shr, ATOM_ARG_MC}, { atom_op_debug, 0},}; -void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) +static void atom_execute_table_locked(struct atom_context *ctx, int index, uint32_t * params) { int base = CU16(ctx->cmd_table + 4 + 2 * index); int len, ws, ps, ptr; @@ -1092,6 +1093,13 @@ void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) kfree(ectx.ws); } +void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) +{ + mutex_lock(&ctx->mutex); + atom_execute_table_locked(ctx, index, params); + mutex_unlock(&ctx->mutex); +} + static int atom_iio_len[] = { 1, 2, 3, 3, 3, 3, 4, 4, 4, 3 }; static void atom_index_iio(struct atom_context *ctx, int base) diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index 6671848e5ea..47fd943f6d1 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h @@ -120,6 +120,7 @@ struct card_info { struct atom_context { struct card_info *card; + struct mutex mutex; void *bios; uint32_t cmd_table, data_table; uint16_t *iio; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 02bcdb1240c..99b95ca42a7 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -481,6 +481,7 @@ int radeon_atombios_init(struct radeon_device *rdev) atom_card_info->pll_write = cail_pll_write; rdev->mode_info.atom_context = atom_parse(atom_card_info, rdev->bios); + mutex_init(&rdev->mode_info.atom_context->mutex); radeon_atom_initialize_bios_scratch_regs(rdev->ddev); atom_allocate_fb_scratch(rdev->mode_info.atom_context); return 0; -- cgit v1.2.3-70-g09d2 From 5ea597f3764880ab3a67fe2246218634a8c12778 Mon Sep 17 00:00:00 2001 From: RafaÅ‚ MiÅ‚ecki Date: Thu, 17 Dec 2009 13:50:09 +0100 Subject: drm/radeon/kms: enable memory clock reading on legacy (V2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit V2: detect IGP cards (which don't have own memory) Signed-off-by: RafaÅ‚ MiÅ‚ecki Acked-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_asic.h | 7 ++++--- drivers/gpu/drm/radeon/radeon_clocks.c | 2 +- drivers/gpu/drm/radeon/radeon_device.c | 6 ++++++ 3 files changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 636116bedcb..eb29217bbf1 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -33,6 +33,7 @@ */ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev); void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock); +uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev); void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev); @@ -106,7 +107,7 @@ static struct radeon_asic r100_asic = { .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, - .get_memory_clock = NULL, + .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, @@ -166,7 +167,7 @@ static struct radeon_asic r300_asic = { .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, - .get_memory_clock = NULL, + .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_legacy_set_clock_gating, @@ -259,7 +260,7 @@ static struct radeon_asic rs400_asic = { .copy = &r100_copy_blit, .get_engine_clock = &radeon_legacy_get_engine_clock, .set_engine_clock = &radeon_legacy_set_engine_clock, - .get_memory_clock = NULL, + .get_memory_clock = &radeon_legacy_get_memory_clock, .set_memory_clock = NULL, .set_pcie_lanes = NULL, .set_clock_gating = &radeon_legacy_set_clock_gating, diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index b062109efbe..812f24dbc2a 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c @@ -62,7 +62,7 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) } /* 10 khz */ -static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) +uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) { struct radeon_pll *mpll = &rdev->clock.mpll; uint32_t fb_div, ref_div, post_div, mclk; diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 99b95ca42a7..14df3ad64f9 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -391,6 +391,12 @@ int radeon_asic_init(struct radeon_device *rdev) /* FIXME: not supported yet */ return -EINVAL; } + + if (rdev->flags & RADEON_IS_IGP) { + rdev->asic->get_memory_clock = NULL; + rdev->asic->set_memory_clock = NULL; + } + return 0; } -- cgit v1.2.3-70-g09d2 From 46c64d4bfa01cda7d58c514164f8b127ab6741b7 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Thu, 17 Dec 2009 06:02:28 +0100 Subject: drm/radeon/kms: allow rendering while no colorbuffer is set on r300 Because hardware cannot disable all colorbuffers directly to do depth-only rendering, a user should: - disable reading from a colorbuffer in blending - disable fastfill - set the color channel mask to 0 to prevent writing to a colorbuffer Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r100.c | 4 ++++ drivers/gpu/drm/radeon/r100_track.h | 4 +++- drivers/gpu/drm/radeon/r300.c | 12 ++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 84e5df766d3..71727460968 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -2881,6 +2881,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) for (i = 0; i < track->num_cb; i++) { if (track->cb[i].robj == NULL) { + if (!(track->fastfill || track->color_channel_mask || + track->blend_read_enable)) { + continue; + } DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); return -EINVAL; } diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h index 7188c3778ee..b27a6999d21 100644 --- a/drivers/gpu/drm/radeon/r100_track.h +++ b/drivers/gpu/drm/radeon/r100_track.h @@ -67,13 +67,15 @@ struct r100_cs_track { unsigned immd_dwords; unsigned num_arrays; unsigned max_indx; + unsigned color_channel_mask; struct r100_cs_track_array arrays[11]; struct r100_cs_track_cb cb[R300_MAX_CB]; struct r100_cs_track_cb zb; struct r100_cs_track_texture textures[R300_TRACK_MAX_TEXTURE]; bool z_enabled; bool separate_cube; - + bool fastfill; + bool blend_read_enable; }; int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track); diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 83490c2b506..6a5d1177afa 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -992,6 +992,18 @@ static int r300_packet0_check(struct radeon_cs_parser *p, } ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); break; + case 0x4e0c: + /* RB3D_COLOR_CHANNEL_MASK */ + track->color_channel_mask = idx_value; + break; + case 0x4d1c: + /* ZB_BW_CNTL */ + track->fastfill = !!(idx_value & (1 << 2)); + break; + case 0x4e04: + /* RB3D_BLENDCNTL */ + track->blend_read_enable = !!(idx_value & (1 << 2)); + break; case 0x4be8: /* valid register only on RV530 */ if (p->rdev->family == CHIP_RV530) -- cgit v1.2.3-70-g09d2 From 512889f450c1851d9e3628f1894b9b64b0701eac Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Sat, 19 Dec 2009 00:23:00 +0100 Subject: drm/radeon/kms: add 3DC compression support There are 2 formats: ATI1N: 64 bits per 4x4 block, one-channel format ATI2N: 128 bits per 4x4 block, two-channel format Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300.c | 18 ++++++++++++++++++ drivers/gpu/drm/radeon/r300_reg.h | 1 + 2 files changed, 19 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index 6a5d1177afa..3f2cc9e2e8d 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -887,6 +887,14 @@ static int r300_packet0_check(struct radeon_cs_parser *p, track->textures[i].cpp = 1; track->textures[i].compress_format = R100_TRACK_COMP_DXT1; break; + case R300_TX_FORMAT_ATI2N: + if (p->rdev->family < CHIP_R420) { + DRM_ERROR("Invalid texture format %u\n", + (idx_value & 0x1F)); + return -EINVAL; + } + /* The same rules apply as for DXT3/5. */ + /* Pass through. */ case R300_TX_FORMAT_DXT3: case R300_TX_FORMAT_DXT5: track->textures[i].cpp = 1; @@ -951,6 +959,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p, track->textures[i].width_11 = tmp; tmp = ((idx_value >> 16) & 1) << 11; track->textures[i].height_11 = tmp; + + /* ATI1N */ + if (idx_value & (1 << 14)) { + /* The same rules apply as for DXT1. */ + track->textures[i].compress_format = + R100_TRACK_COMP_DXT1; + } + } else if (idx_value & (1 << 14)) { + DRM_ERROR("Forbidden bit TXFORMAT_MSB\n"); + return -EINVAL; } break; case 0x4480: diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index 4b7afef35a6..1735a2b6958 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h @@ -900,6 +900,7 @@ # define R300_TX_FORMAT_FL_I32 0x1B # define R300_TX_FORMAT_FL_I32A32 0x1C # define R300_TX_FORMAT_FL_R32G32B32A32 0x1D +# define R300_TX_FORMAT_ATI2N 0x1F /* alpha modes, convenience mostly */ /* if you have alpha, pick constant appropriate to the number of channels (1 for I8, 2 for I8A8, 4 for R8G8B8A8, etc */ -- cgit v1.2.3-70-g09d2 From d2efdf6d6f425950a61fa5cc3aa22e6718e7f3c8 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Tue, 22 Dec 2009 10:06:49 -0500 Subject: drm/radeon/kms: add cvt mode if we only have lvds w/h and no edid (v4) This fixes LVDS on some mac laptops without a panel edid. v2 - Set proper mode type flags v3 - Note that this is not neceesarily the exact panel mode, but an approximation based on the cvt formula. For these systems we should ideally read the mode info out of the registers or add a mode table, but this works and is much simpler. v4 - Update comments and debug message. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_connectors.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 8da06e17ff2..20161567dbf 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -208,6 +208,18 @@ static struct drm_display_mode *radeon_fp_native_mode(struct drm_encoder *encode drm_mode_set_name(mode); DRM_DEBUG("Adding native panel mode %s\n", mode->name); + } else if (native_mode->hdisplay != 0 && + native_mode->vdisplay != 0) { + /* mac laptops without an edid */ + /* Note that this is not necessarily the exact panel mode, + * but an approximation based on the cvt formula. For these + * systems we should ideally read the mode info out of the + * registers or add a mode table, but this works and is much + * simpler. + */ + mode = drm_cvt_mode(dev, native_mode->hdisplay, native_mode->vdisplay, 60, true, false, false); + mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + DRM_DEBUG("Adding cvt approximation of native panel mode %s\n", mode->name); } return mode; } -- cgit v1.2.3-70-g09d2 From 0a0c7596c643239e8d4c3eaaba43b74a96f2411e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 11 Dec 2009 20:36:19 +0100 Subject: drm/radeon/kms: Avoid crash when trying to cleanup uninitialized structure Add boolean to record if some part of the driver are initialized or not this allow to avoid a crash when trying to cleanup uninitialized structure members. Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon.h | 4 +++- drivers/gpu/drm/radeon/radeon_fence.c | 9 ++++++--- drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++++ 3 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index cd650fd3964..53b55608102 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -162,6 +162,7 @@ struct radeon_fence_driver { struct list_head created; struct list_head emited; struct list_head signaled; + bool initialized; }; struct radeon_fence { @@ -202,8 +203,9 @@ struct radeon_surface_reg { struct radeon_mman { struct ttm_bo_global_ref bo_global_ref; struct ttm_global_reference mem_global_ref; - bool mem_global_referenced; struct ttm_bo_device bdev; + bool mem_global_referenced; + bool initialized; }; struct radeon_bo { diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index cb4cd97ae39..4cdd8b4f754 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -324,7 +324,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev) write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); r = radeon_scratch_get(rdev, &rdev->fence_drv.scratch_reg); if (r) { - DRM_ERROR("Fence failed to get a scratch register."); + dev_err(rdev->dev, "fence failed to get scratch register\n"); write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); return r; } @@ -335,9 +335,10 @@ int radeon_fence_driver_init(struct radeon_device *rdev) INIT_LIST_HEAD(&rdev->fence_drv.signaled); rdev->fence_drv.count_timeout = 0; init_waitqueue_head(&rdev->fence_drv.queue); + rdev->fence_drv.initialized = true; write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); if (radeon_debugfs_fence_init(rdev)) { - DRM_ERROR("Failed to register debugfs file for fence !\n"); + dev_err(rdev->dev, "fence debugfs file creation failed\n"); } return 0; } @@ -346,11 +347,13 @@ void radeon_fence_driver_fini(struct radeon_device *rdev) { unsigned long irq_flags; + if (!rdev->fence_drv.initialized) + return; wake_up_all(&rdev->fence_drv.queue); write_lock_irqsave(&rdev->fence_drv.lock, irq_flags); radeon_scratch_free(rdev, rdev->fence_drv.scratch_reg); write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags); - DRM_INFO("radeon: fence finalized\n"); + rdev->fence_drv.initialized = false; } diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 7bed4122528..a00450743d6 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -494,6 +494,7 @@ int radeon_ttm_init(struct radeon_device *rdev) DRM_ERROR("failed initializing buffer object driver(%d).\n", r); return r; } + rdev->mman.initialized = true; r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, rdev->mc.real_vram_size >> PAGE_SHIFT); if (r) { @@ -541,6 +542,8 @@ void radeon_ttm_fini(struct radeon_device *rdev) { int r; + if (!rdev->mman.initialized) + return; if (rdev->stollen_vga_memory) { r = radeon_bo_reserve(rdev->stollen_vga_memory, false); if (r == 0) { @@ -554,6 +557,7 @@ void radeon_ttm_fini(struct radeon_device *rdev) ttm_bo_device_release(&rdev->mman.bdev); radeon_gart_fini(rdev); radeon_ttm_global_fini(rdev); + rdev->mman.initialized = false; DRM_INFO("radeon: ttm finalized\n"); } -- cgit v1.2.3-70-g09d2 From 3642133816f9f25065e3ca310f0720574bcdcc52 Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Fri, 11 Dec 2009 21:18:34 +0100 Subject: drm/radeon/kms: Check module arguments to be valid V2 This patch add a function which check module argument to be valid. On invalid argument it prints a warning and setback the default value. V2: Allow 0 for vram limit & agp mode which are the default value Signed-off-by: Jerome Glisse Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_device.c | 73 +++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 14df3ad64f9..7c6848096bc 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -546,9 +546,72 @@ void radeon_agp_disable(struct radeon_device *rdev) } } -/* - * Radeon device. - */ +void radeon_check_arguments(struct radeon_device *rdev) +{ + /* vramlimit must be a power of two */ + switch (radeon_vram_limit) { + case 0: + case 4: + case 8: + case 16: + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + break; + default: + dev_warn(rdev->dev, "vram limit (%d) must be a power of 2\n", + radeon_vram_limit); + radeon_vram_limit = 0; + break; + } + radeon_vram_limit = radeon_vram_limit << 20; + /* gtt size must be power of two and greater or equal to 32M */ + switch (radeon_gart_size) { + case 4: + case 8: + case 16: + dev_warn(rdev->dev, "gart size (%d) too small forcing to 512M\n", + radeon_gart_size); + radeon_gart_size = 512; + break; + case 32: + case 64: + case 128: + case 256: + case 512: + case 1024: + case 2048: + case 4096: + break; + default: + dev_warn(rdev->dev, "gart size (%d) must be a power of 2\n", + radeon_gart_size); + radeon_gart_size = 512; + break; + } + rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; + /* AGP mode can only be -1, 1, 2, 4, 8 */ + switch (radeon_agpmode) { + case -1: + case 0: + case 1: + case 2: + case 4: + case 8: + break; + default: + dev_warn(rdev->dev, "invalid AGP mode %d (valid mode: " + "-1, 0, 1, 2, 4, 8)\n", radeon_agpmode); + radeon_agpmode = 0; + break; + } +} + int radeon_device_init(struct radeon_device *rdev, struct drm_device *ddev, struct pci_dev *pdev, @@ -587,9 +650,9 @@ int radeon_device_init(struct radeon_device *rdev, /* Set asic functions */ r = radeon_asic_init(rdev); - if (r) { + if (r) return r; - } + radeon_check_arguments(rdev); if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) { radeon_agp_disable(rdev); -- cgit v1.2.3-70-g09d2 From f56cd64f5f713a3013c4d980a5695c198d839671 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 18 Dec 2009 11:28:22 -0500 Subject: drm/radeon/kms: never combine LVDS with another encoder When linking multiple encoders to a connector, make sure to not link LVDS with another connector. Some bioses have the same i2c line for LVDS and VGA. Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/radeon_atombios.c | 49 +++++++++++++++----------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index b5912c26b1d..321044bef71 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -745,8 +745,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct else radeon_add_legacy_encoder(dev, radeon_get_encoder_id(dev, - (1 << - i), + (1 << i), dac), (1 << i)); } @@ -758,32 +757,30 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct if (bios_connectors[j].valid && (i != j)) { if (bios_connectors[i].line_mux == bios_connectors[j].line_mux) { - if (((bios_connectors[i]. - devices & - (ATOM_DEVICE_DFP_SUPPORT)) - && (bios_connectors[j]. - devices & - (ATOM_DEVICE_CRT_SUPPORT))) - || - ((bios_connectors[j]. - devices & - (ATOM_DEVICE_DFP_SUPPORT)) - && (bios_connectors[i]. - devices & - (ATOM_DEVICE_CRT_SUPPORT)))) { - bios_connectors[i]. - devices |= - bios_connectors[j]. - devices; - bios_connectors[i]. - connector_type = - DRM_MODE_CONNECTOR_DVII; - if (bios_connectors[j].devices & - (ATOM_DEVICE_DFP_SUPPORT)) + /* make sure not to combine LVDS */ + if (bios_connectors[i].devices & (ATOM_DEVICE_LCD_SUPPORT)) { + bios_connectors[i].line_mux = 53; + bios_connectors[i].ddc_bus.valid = false; + continue; + } + if (bios_connectors[j].devices & (ATOM_DEVICE_LCD_SUPPORT)) { + bios_connectors[j].line_mux = 53; + bios_connectors[j].ddc_bus.valid = false; + continue; + } + /* combine analog and digital for DVI-I */ + if (((bios_connectors[i].devices & (ATOM_DEVICE_DFP_SUPPORT)) && + (bios_connectors[j].devices & (ATOM_DEVICE_CRT_SUPPORT))) || + ((bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) && + (bios_connectors[i].devices & (ATOM_DEVICE_CRT_SUPPORT)))) { + bios_connectors[i].devices |= + bios_connectors[j].devices; + bios_connectors[i].connector_type = + DRM_MODE_CONNECTOR_DVII; + if (bios_connectors[j].devices & (ATOM_DEVICE_DFP_SUPPORT)) bios_connectors[i].hpd = bios_connectors[j].hpd; - bios_connectors[j]. - valid = false; + bios_connectors[j].valid = false; } } } -- cgit v1.2.3-70-g09d2 From 0786201d8cd0730e72b0e087484dd47cc5f58409 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Sat, 19 Dec 2009 12:45:12 -0500 Subject: drm/radeon/kms: add definitions for v4 power tables [airlied: just adding this for completeness to avoid drift between public atombios.h files] Signed-off-by: Alex Deucher Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/atombios.h | 199 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h index e83927644de..8e28842080d 100644 --- a/drivers/gpu/drm/radeon/atombios.h +++ b/drivers/gpu/drm/radeon/atombios.h @@ -4690,6 +4690,205 @@ typedef struct _ATOM_POWERPLAY_INFO_V3 { ATOM_POWERMODE_INFO_V3 asPowerPlayInfo[ATOM_MAX_NUMBEROF_POWER_BLOCK]; } ATOM_POWERPLAY_INFO_V3; +/* New PPlib */ +/**************************************************************************/ +typedef struct _ATOM_PPLIB_THERMALCONTROLLER + +{ + UCHAR ucType; // one of ATOM_PP_THERMALCONTROLLER_* + UCHAR ucI2cLine; // as interpreted by DAL I2C + UCHAR ucI2cAddress; + UCHAR ucFanParameters; // Fan Control Parameters. + UCHAR ucFanMinRPM; // Fan Minimum RPM (hundreds) -- for display purposes only. + UCHAR ucFanMaxRPM; // Fan Maximum RPM (hundreds) -- for display purposes only. + UCHAR ucReserved; // ---- + UCHAR ucFlags; // to be defined +} ATOM_PPLIB_THERMALCONTROLLER; + +#define ATOM_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_PP_FANPARAMETERS_NOFAN 0x80 // No fan is connected to this controller. + +#define ATOM_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_PP_THERMALCONTROLLER_LM63 1 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1032 2 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_ADM1030 3 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_MUA6649 4 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_LM64 5 +#define ATOM_PP_THERMALCONTROLLER_F75375 6 // Not used by PPLib +#define ATOM_PP_THERMALCONTROLLER_RV6xx 7 +#define ATOM_PP_THERMALCONTROLLER_RV770 8 +#define ATOM_PP_THERMALCONTROLLER_ADT7473 9 + +typedef struct _ATOM_PPLIB_STATE +{ + UCHAR ucNonClockStateIndex; + UCHAR ucClockStateIndices[1]; // variable-sized +} ATOM_PPLIB_STATE; + +//// ATOM_PPLIB_POWERPLAYTABLE::ulPlatformCaps +#define ATOM_PP_PLATFORM_CAP_BACKBIAS 1 +#define ATOM_PP_PLATFORM_CAP_POWERPLAY 2 +#define ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 4 +#define ATOM_PP_PLATFORM_CAP_ASPM_L0s 8 +#define ATOM_PP_PLATFORM_CAP_ASPM_L1 16 +#define ATOM_PP_PLATFORM_CAP_HARDWAREDC 32 +#define ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY 64 +#define ATOM_PP_PLATFORM_CAP_STEPVDDC 128 +#define ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL 256 +#define ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL 512 +#define ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 1024 +#define ATOM_PP_PLATFORM_CAP_HTLINKCONTROL 2048 + +typedef struct _ATOM_PPLIB_POWERPLAYTABLE +{ + ATOM_COMMON_TABLE_HEADER sHeader; + + UCHAR ucDataRevision; + + UCHAR ucNumStates; + UCHAR ucStateEntrySize; + UCHAR ucClockInfoSize; + UCHAR ucNonClockSize; + + // offset from start of this table to array of ucNumStates ATOM_PPLIB_STATE structures + USHORT usStateArrayOffset; + + // offset from start of this table to array of ASIC-specific structures, + // currently ATOM_PPLIB_CLOCK_INFO. + USHORT usClockInfoArrayOffset; + + // offset from start of this table to array of ATOM_PPLIB_NONCLOCK_INFO + USHORT usNonClockInfoArrayOffset; + + USHORT usBackbiasTime; // in microseconds + USHORT usVoltageTime; // in microseconds + USHORT usTableSize; //the size of this structure, or the extended structure + + ULONG ulPlatformCaps; // See ATOM_PPLIB_CAPS_* + + ATOM_PPLIB_THERMALCONTROLLER sThermalController; + + USHORT usBootClockInfoOffset; + USHORT usBootNonClockInfoOffset; + +} ATOM_PPLIB_POWERPLAYTABLE; + +//// ATOM_PPLIB_NONCLOCK_INFO::usClassification +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +// 2, 4, 6, 7 are reserved + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE 0x0100 +#define ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE 0x0200 +#define ATOM_PPLIB_CLASSIFICATION_UVDSTATE 0x0400 +#define ATOM_PPLIB_CLASSIFICATION_3DLOW 0x0800 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 +// remaining 3 bits are reserved + +//// ATOM_PPLIB_NONCLOCK_INFO::ulCapsAndSettings +#define ATOM_PPLIB_SINGLE_DISPLAY_ONLY 0x00000001 +#define ATOM_PPLIB_SUPPORTS_VIDEO_PLAYBACK 0x00000002 + +// 0 is 2.5Gb/s, 1 is 5Gb/s +#define ATOM_PPLIB_PCIE_LINK_SPEED_MASK 0x00000004 +#define ATOM_PPLIB_PCIE_LINK_SPEED_SHIFT 2 + +// lanes - 1: 1, 2, 4, 8, 12, 16 permitted by PCIE spec +#define ATOM_PPLIB_PCIE_LINK_WIDTH_MASK 0x000000F8 +#define ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT 3 + +// lookup into reduced refresh-rate table +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK 0x00000F00 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT 8 + +#define ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED 0 +#define ATOM_PPLIB_LIMITED_REFRESHRATE_50HZ 1 +// 2-15 TBD as needed. + +#define ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING 0x00001000 +#define ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS 0x00002000 +#define ATOM_PPLIB_ENABLE_VARIBRIGHT 0x00008000 + +#define ATOM_PPLIB_DISALLOW_ON_DC 0x00004000 + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usNonClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE_INFO::ucNonClockStateIndex +typedef struct _ATOM_PPLIB_NONCLOCK_INFO +{ + USHORT usClassification; + UCHAR ucMinTemperature; + UCHAR ucMaxTemperature; + ULONG ulCapsAndSettings; + UCHAR ucRequiredPower; + UCHAR ucUnused1[3]; +} ATOM_PPLIB_NONCLOCK_INFO; + +// Contained in an array starting at the offset +// in ATOM_PPLIB_POWERPLAYTABLE::usClockInfoArrayOffset. +// referenced from ATOM_PPLIB_STATE::ucClockStateIndices +typedef struct _ATOM_PPLIB_R600_CLOCK_INFO +{ + USHORT usEngineClockLow; + UCHAR ucEngineClockHigh; + + USHORT usMemoryClockLow; + UCHAR ucMemoryClockHigh; + + USHORT usVDDC; + USHORT usUnused1; + USHORT usUnused2; + + ULONG ulFlags; // ATOM_PPLIB_R600_FLAGS_* + +} ATOM_PPLIB_R600_CLOCK_INFO; + +// ulFlags in ATOM_PPLIB_R600_CLOCK_INFO +#define ATOM_PPLIB_R600_FLAGS_PCIEGEN2 1 +#define ATOM_PPLIB_R600_FLAGS_UVDSAFE 2 +#define ATOM_PPLIB_R600_FLAGS_BACKBIASENABLE 4 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_ODT_OFF 8 +#define ATOM_PPLIB_R600_FLAGS_MEMORY_DLL_OFF 16 + +typedef struct _ATOM_PPLIB_RS780_CLOCK_INFO + +{ + USHORT usLowEngineClockLow; // Low Engine clock in MHz (the same way as on the R600). + UCHAR ucLowEngineClockHigh; + USHORT usHighEngineClockLow; // High Engine clock in MHz. + UCHAR ucHighEngineClockHigh; + USHORT usMemoryClockLow; // For now one of the ATOM_PPLIB_RS780_SPMCLK_XXXX constants. + UCHAR ucMemoryClockHigh; // Currentyl unused. + UCHAR ucPadding; // For proper alignment and size. + USHORT usVDDC; // For the 780, use: None, Low, High, Variable + UCHAR ucMaxHTLinkWidth; // From SBIOS - {2, 4, 8, 16} + UCHAR ucMinHTLinkWidth; // From SBIOS - {2, 4, 8, 16}. Effective only if CDLW enabled. Minimum down stream width could be bigger as display BW requriement. + USHORT usHTLinkFreq; // See definition ATOM_PPLIB_RS780_HTLINKFREQ_xxx or in MHz(>=200). + ULONG ulFlags; +} ATOM_PPLIB_RS780_CLOCK_INFO; + +#define ATOM_PPLIB_RS780_VOLTAGE_NONE 0 +#define ATOM_PPLIB_RS780_VOLTAGE_LOW 1 +#define ATOM_PPLIB_RS780_VOLTAGE_HIGH 2 +#define ATOM_PPLIB_RS780_VOLTAGE_VARIABLE 3 + +#define ATOM_PPLIB_RS780_SPMCLK_NONE 0 // We cannot change the side port memory clock, leave it as it is. +#define ATOM_PPLIB_RS780_SPMCLK_LOW 1 +#define ATOM_PPLIB_RS780_SPMCLK_HIGH 2 + +#define ATOM_PPLIB_RS780_HTLINKFREQ_NONE 0 +#define ATOM_PPLIB_RS780_HTLINKFREQ_LOW 1 +#define ATOM_PPLIB_RS780_HTLINKFREQ_HIGH 2 + /**************************************************************************/ /* Following definitions are for compatiblity issue in different SW components. */ -- cgit v1.2.3-70-g09d2 From 3b1c37cab3765b87efbd4ed40301ceaf72b9f5c2 Mon Sep 17 00:00:00 2001 From: Jonathan Woithe Date: Wed, 23 Dec 2009 09:19:42 +1030 Subject: fujitu-laptop: fix tests of acpi_evaluate_integer() return value Fix tests on return value from acpi_evaluate_integer(). Based on a patch by Roel Kluin and incorporating suggestions from Len Brown . Signed-off-by: Roel Kluin Signed-off-by: Jonathan Woithe Signed-off-by: Len Brown --- drivers/platform/x86/fujitsu-laptop.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/fujitsu-laptop.c b/drivers/platform/x86/fujitsu-laptop.c index bcd4ba8be7d..3c2d0384b43 100644 --- a/drivers/platform/x86/fujitsu-laptop.c +++ b/drivers/platform/x86/fujitsu-laptop.c @@ -376,8 +376,8 @@ static int get_lcd_level(void) status = acpi_evaluate_integer(fujitsu->acpi_handle, "GBLL", NULL, &state); - if (status < 0) - return status; + if (ACPI_FAILURE(status)) + return 0; fujitsu->brightness_level = state & 0x0fffffff; @@ -398,8 +398,8 @@ static int get_max_brightness(void) status = acpi_evaluate_integer(fujitsu->acpi_handle, "RBLL", NULL, &state); - if (status < 0) - return status; + if (ACPI_FAILURE(status)) + return -1; fujitsu->max_brightness = state; -- cgit v1.2.3-70-g09d2 From 119eecc831a42bd090543568932e440c6831f1bb Mon Sep 17 00:00:00 2001 From: Stefani Seibold Date: Wed, 23 Dec 2009 09:10:48 +0100 Subject: Fix usb_serial_probe() problem introduced by the recent kfifo changes The USB serial code was a new user of the kfifo API, and it was missed when porting things to the new kfifo API. Please make the write_fifo in place. Here is my patch to fix the regression and full ported version. Signed-off-by: Stefani Seibold Reported-and-tested-by: Rafael J. Wysocki Cc: Greg KH Cc: Andrew Morton Cc: Alan Stern Signed-off-by: Linus Torvalds --- drivers/usb/serial/generic.c | 12 ++++++------ drivers/usb/serial/usb-serial.c | 5 ++--- include/linux/usb/serial.h | 3 ++- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index b0f1183755c..f1ea3a33b6e 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -276,7 +276,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) if (port->write_urb_busy) start_io = false; else { - start_io = (kfifo_len(port->write_fifo) != 0); + start_io = (kfifo_len(&port->write_fifo) != 0); port->write_urb_busy = start_io; } spin_unlock_irqrestore(&port->lock, flags); @@ -285,7 +285,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) return 0; data = port->write_urb->transfer_buffer; - count = kfifo_out_locked(port->write_fifo, data, port->bulk_out_size, &port->lock); + count = kfifo_out_locked(&port->write_fifo, data, port->bulk_out_size, &port->lock); usb_serial_debug_data(debug, &port->dev, __func__, count, data); /* set up our urb */ @@ -345,7 +345,7 @@ int usb_serial_generic_write(struct tty_struct *tty, return usb_serial_multi_urb_write(tty, port, buf, count); - count = kfifo_in_locked(port->write_fifo, buf, count, &port->lock); + count = kfifo_in_locked(&port->write_fifo, buf, count, &port->lock); result = usb_serial_generic_write_start(port); if (result >= 0) @@ -370,7 +370,7 @@ int usb_serial_generic_write_room(struct tty_struct *tty) (serial->type->max_in_flight_urbs - port->urbs_in_flight); } else if (serial->num_bulk_out) - room = port->write_fifo->size - kfifo_len(port->write_fifo); + room = kfifo_avail(&port->write_fifo); spin_unlock_irqrestore(&port->lock, flags); dbg("%s - returns %d", __func__, room); @@ -391,7 +391,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) chars = port->tx_bytes_flight; spin_unlock_irqrestore(&port->lock, flags); } else if (serial->num_bulk_out) - chars = kfifo_len(port->write_fifo); + chars = kfifo_len(&port->write_fifo); dbg("%s - returns %d", __func__, chars); return chars; @@ -507,7 +507,7 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) if (status) { dbg("%s - nonzero multi-urb write bulk status " "received: %d", __func__, status); - kfifo_reset(port->write_fifo); + kfifo_reset_out(&port->write_fifo); } else usb_serial_generic_write_start(port); } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 636a4f23445..33c85f7084f 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -595,8 +595,7 @@ static void port_release(struct device *dev) usb_free_urb(port->write_urb); usb_free_urb(port->interrupt_in_urb); usb_free_urb(port->interrupt_out_urb); - if (!IS_ERR(port->write_fifo) && port->write_fifo) - kfifo_free(port->write_fifo); + kfifo_free(&port->write_fifo); kfree(port->bulk_in_buffer); kfree(port->bulk_out_buffer); kfree(port->interrupt_in_buffer); @@ -939,7 +938,7 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "No free urbs available\n"); goto probe_error; } - if (kfifo_alloc(port->write_fifo, PAGE_SIZE, GFP_KERNEL)) + if (kfifo_alloc(&port->write_fifo, PAGE_SIZE, GFP_KERNEL)) goto probe_error; buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->bulk_out_size = buffer_size; diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index acf6e457c04..1819396ed50 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -16,6 +16,7 @@ #include #include #include +#include #define SERIAL_TTY_MAJOR 188 /* Nice legal number now */ #define SERIAL_TTY_MINORS 254 /* loads of devices :) */ @@ -94,7 +95,7 @@ struct usb_serial_port { unsigned char *bulk_out_buffer; int bulk_out_size; struct urb *write_urb; - struct kfifo *write_fifo; + struct kfifo write_fifo; int write_urb_busy; __u8 bulk_out_endpointAddress; -- cgit v1.2.3-70-g09d2 From f1f76f865b5f66db5b5c7f2d19874f2bb9b43b8d Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 16 Dec 2009 21:31:33 +0000 Subject: devtmpfs: Convert dirlock to a mutex devtmpfs has a rw_lock dirlock which serializes delete_path and create_path. This code was obviously never tested with the usual set of debugging facilities enabled. In the dirlock held sections the code calls: - vfs functions which take mutexes - kmalloc(, GFP_KERNEL) In both code pathes the might sleep warning triggers and spams dmesg. Convert the rw_lock to a mutex. There is no reason why this needs to be a rwlock. Signed-off-by: Thomas Gleixner Cc: Kay Sievers Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 50375bb8e51..278371c7bf5 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -32,7 +32,7 @@ static int dev_mount = 1; static int dev_mount; #endif -static rwlock_t dirlock; +static DEFINE_MUTEX(dirlock); static int __init mount_param(char *str) { @@ -93,7 +93,7 @@ static int create_path(const char *nodepath) { int err; - read_lock(&dirlock); + mutex_lock(&dirlock); err = dev_mkdir(nodepath, 0755); if (err == -ENOENT) { char *path; @@ -117,7 +117,7 @@ static int create_path(const char *nodepath) } kfree(path); } - read_unlock(&dirlock); + mutex_unlock(&dirlock); return err; } @@ -229,7 +229,7 @@ static int delete_path(const char *nodepath) if (!path) return -ENOMEM; - write_lock(&dirlock); + mutex_lock(&dirlock); for (;;) { char *base; @@ -241,7 +241,7 @@ static int delete_path(const char *nodepath) if (err) break; } - write_unlock(&dirlock); + mutex_unlock(&dirlock); kfree(path); return err; @@ -352,8 +352,6 @@ int __init devtmpfs_init(void) int err; struct vfsmount *mnt; - rwlock_init(&dirlock); - err = register_filesystem(&dev_fs_type); if (err) { printk(KERN_ERR "devtmpfs: unable to register devtmpfs " -- cgit v1.2.3-70-g09d2 From 26579ab70aa0e0ea434e6e100279d2f67c094431 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Fri, 18 Dec 2009 15:34:19 +0200 Subject: Driver core: device_attribute parameters can often be const* Most device_attributes are const, and are begging to be put in a ro section. However, the create and remove file interfaces were failing to propagate the const promise which the only functions they call offer. Signed-off-by: Phil Carmody Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs.txt | 8 ++++---- drivers/base/core.c | 6 ++++-- include/linux/device.h | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index b245d524d56..a4ac2b98c61 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -91,8 +91,8 @@ struct device_attribute { const char *buf, size_t count); }; -int device_create_file(struct device *, struct device_attribute *); -void device_remove_file(struct device *, struct device_attribute *); +int device_create_file(struct device *, const struct device_attribute *); +void device_remove_file(struct device *, const struct device_attribute *); It also defines this helper for defining device attributes: @@ -316,8 +316,8 @@ DEVICE_ATTR(_name, _mode, _show, _store); Creation/Removal: -int device_create_file(struct device *device, struct device_attribute * attr); -void device_remove_file(struct device * dev, struct device_attribute * attr); +int device_create_file(struct device *dev, const struct device_attribute * attr); +void device_remove_file(struct device *dev, const struct device_attribute * attr); - bus drivers (include/linux/device.h) diff --git a/drivers/base/core.c b/drivers/base/core.c index f1290cbd135..2fd9e611f8a 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -446,7 +446,8 @@ struct kset *devices_kset; * @dev: device. * @attr: device attribute descriptor. */ -int device_create_file(struct device *dev, struct device_attribute *attr) +int device_create_file(struct device *dev, + const struct device_attribute *attr) { int error = 0; if (dev) @@ -459,7 +460,8 @@ int device_create_file(struct device *dev, struct device_attribute *attr) * @dev: device. * @attr: device attribute descriptor. */ -void device_remove_file(struct device *dev, struct device_attribute *attr) +void device_remove_file(struct device *dev, + const struct device_attribute *attr) { if (dev) sysfs_remove_file(&dev->kobj, &attr->attr); diff --git a/include/linux/device.h b/include/linux/device.h index 2a73d9bcbc9..aa5b3e66a14 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -319,9 +319,9 @@ struct device_attribute { struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) extern int __must_check device_create_file(struct device *device, - struct device_attribute *entry); + const struct device_attribute *entry); extern void device_remove_file(struct device *dev, - struct device_attribute *attr); + const struct device_attribute *attr); extern int __must_check device_create_bin_file(struct device *dev, struct bin_attribute *attr); extern void device_remove_bin_file(struct device *dev, -- cgit v1.2.3-70-g09d2 From 66ecb92be9eb579df93add22d19843e7869f168e Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Fri, 18 Dec 2009 15:34:20 +0200 Subject: Driver core: bin_attribute parameters can often be const* Many struct bin_attribute descriptors are purely read-only structures, and there's no need to change them. Therefore make the promise not to, which will let those descriptors be put in a ro section. Signed-off-by: Phil Carmody Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 6 ++++-- fs/sysfs/bin.c | 6 ++++-- include/linux/device.h | 6 +++--- include/linux/sysfs.h | 9 +++++---- 4 files changed, 16 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 2fd9e611f8a..83afc8b8f27 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -472,7 +472,8 @@ void device_remove_file(struct device *dev, * @dev: device. * @attr: device binary attribute descriptor. */ -int device_create_bin_file(struct device *dev, struct bin_attribute *attr) +int device_create_bin_file(struct device *dev, + const struct bin_attribute *attr) { int error = -EINVAL; if (dev) @@ -486,7 +487,8 @@ EXPORT_SYMBOL_GPL(device_create_bin_file); * @dev: device. * @attr: device binary attribute descriptor. */ -void device_remove_bin_file(struct device *dev, struct bin_attribute *attr) +void device_remove_bin_file(struct device *dev, + const struct bin_attribute *attr) { if (dev) sysfs_remove_bin_file(&dev->kobj, attr); diff --git a/fs/sysfs/bin.c b/fs/sysfs/bin.c index 60c702bc10a..a0a500af24a 100644 --- a/fs/sysfs/bin.c +++ b/fs/sysfs/bin.c @@ -483,7 +483,8 @@ void unmap_bin_file(struct sysfs_dirent *attr_sd) * @attr: attribute descriptor. */ -int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) +int sysfs_create_bin_file(struct kobject *kobj, + const struct bin_attribute *attr) { BUG_ON(!kobj || !kobj->sd || !attr); @@ -497,7 +498,8 @@ int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr) * @attr: attribute descriptor. */ -void sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr) +void sysfs_remove_bin_file(struct kobject *kobj, + const struct bin_attribute *attr) { sysfs_hash_and_remove(kobj->sd, attr->attr.name); } diff --git a/include/linux/device.h b/include/linux/device.h index aa5b3e66a14..10d74ce93a4 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -319,13 +319,13 @@ struct device_attribute { struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store) extern int __must_check device_create_file(struct device *device, - const struct device_attribute *entry); + const struct device_attribute *entry); extern void device_remove_file(struct device *dev, const struct device_attribute *attr); extern int __must_check device_create_bin_file(struct device *dev, - struct bin_attribute *attr); + const struct bin_attribute *attr); extern void device_remove_bin_file(struct device *dev, - struct bin_attribute *attr); + const struct bin_attribute *attr); extern int device_schedule_callback_owner(struct device *dev, void (*func)(struct device *dev), struct module *owner); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 9d68fed50f1..cfa83083a2d 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -99,8 +99,9 @@ int __must_check sysfs_chmod_file(struct kobject *kobj, struct attribute *attr, void sysfs_remove_file(struct kobject *kobj, const struct attribute *attr); int __must_check sysfs_create_bin_file(struct kobject *kobj, - struct bin_attribute *attr); -void sysfs_remove_bin_file(struct kobject *kobj, struct bin_attribute *attr); + const struct bin_attribute *attr); +void sysfs_remove_bin_file(struct kobject *kobj, + const struct bin_attribute *attr); int __must_check sysfs_create_link(struct kobject *kobj, struct kobject *target, const char *name); @@ -175,13 +176,13 @@ static inline void sysfs_remove_file(struct kobject *kobj, } static inline int sysfs_create_bin_file(struct kobject *kobj, - struct bin_attribute *attr) + const struct bin_attribute *attr) { return 0; } static inline void sysfs_remove_bin_file(struct kobject *kobj, - struct bin_attribute *attr) + const struct bin_attribute *attr) { } -- cgit v1.2.3-70-g09d2 From 099c2f21d8cf0724b85abb2c589d6276953781b7 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Fri, 18 Dec 2009 15:34:21 +0200 Subject: Driver core: driver_attribute parameters can often be const* Many struct driver_attribute descriptors are purely read-only structures, and there's no need to change them. Therefore make the promise not to, which will let those descriptors be put in a ro section. Signed-off-by: Phil Carmody Signed-off-by: Greg Kroah-Hartman --- Documentation/driver-model/driver.txt | 4 ++-- Documentation/filesystems/sysfs.txt | 4 ++-- drivers/base/driver.c | 4 ++-- include/linux/device.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/Documentation/driver-model/driver.txt b/Documentation/driver-model/driver.txt index 60120fb3b96..d2cd6fb8ba9 100644 --- a/Documentation/driver-model/driver.txt +++ b/Documentation/driver-model/driver.txt @@ -226,5 +226,5 @@ struct driver_attribute driver_attr_debug; This can then be used to add and remove the attribute from the driver's directory using: -int driver_create_file(struct device_driver *, struct driver_attribute *); -void driver_remove_file(struct device_driver *, struct driver_attribute *); +int driver_create_file(struct device_driver *, const struct driver_attribute *); +void driver_remove_file(struct device_driver *, const struct driver_attribute *); diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index a4ac2b98c61..931c806642c 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -358,7 +358,7 @@ DRIVER_ATTR(_name, _mode, _show, _store) Creation/Removal: -int driver_create_file(struct device_driver *, struct driver_attribute *); -void driver_remove_file(struct device_driver *, struct driver_attribute *); +int driver_create_file(struct device_driver *, const struct driver_attribute *); +void driver_remove_file(struct device_driver *, const struct driver_attribute *); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index f367885a764..90c9fff09ea 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -98,7 +98,7 @@ EXPORT_SYMBOL_GPL(driver_find_device); * @attr: driver attribute descriptor. */ int driver_create_file(struct device_driver *drv, - struct driver_attribute *attr) + const struct driver_attribute *attr) { int error; if (drv) @@ -115,7 +115,7 @@ EXPORT_SYMBOL_GPL(driver_create_file); * @attr: driver attribute descriptor. */ void driver_remove_file(struct device_driver *drv, - struct driver_attribute *attr) + const struct driver_attribute *attr) { if (drv) sysfs_remove_file(&drv->p->kobj, &attr->attr); diff --git a/include/linux/device.h b/include/linux/device.h index 10d74ce93a4..a62799f2ab0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -166,9 +166,9 @@ struct driver_attribute driver_attr_##_name = \ __ATTR(_name, _mode, _show, _store) extern int __must_check driver_create_file(struct device_driver *driver, - struct driver_attribute *attr); + const struct driver_attribute *attr); extern void driver_remove_file(struct device_driver *driver, - struct driver_attribute *attr); + const struct driver_attribute *attr); extern int __must_check driver_add_kobj(struct device_driver *drv, struct kobject *kobj, -- cgit v1.2.3-70-g09d2 From e6309e7568d4b9d62298a887b10de42df11cb8c1 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Thu, 10 Dec 2009 19:32:49 +0000 Subject: Driver-core: Fix bogus 0 error return in device_add() If device_add() is called with a device which does not have dev->p set up, then device_private_init() is called. If that succeeds, then the error variable is set to 0. Now if the dev_name(dev) check further down fails, then device_add() correctly terminates, but returns 0. That of course lets the driver progress. If later another driver uses this half set up device as parent then device_add() of the child device explodes and renders sysfs completely unusable. Set the error to -EINVAL if dev_name() check fails. Signed-off-by: Thomas Gleixner Cc: Kay Sievers Cc: "Hans J. Koch" Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 83afc8b8f27..28202577042 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -909,8 +909,10 @@ int device_add(struct device *dev) dev->init_name = NULL; } - if (!dev_name(dev)) + if (!dev_name(dev)) { + error = -EINVAL; goto name_error; + } pr_debug("device: '%s': %s\n", dev_name(dev), __func__); -- cgit v1.2.3-70-g09d2 From 99b28f1b4126582f87ce454d4affb823bddf2cd8 Mon Sep 17 00:00:00 2001 From: Phil Carmody Date: Mon, 14 Dec 2009 20:28:12 +0200 Subject: driver core: Prevent reference to freed memory on error path priv is drv->p. So only free drv->p after we've finished using priv. Found using a static code analysis tool Signed-off-by: Phil Carmody Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 63c143e54a5..c0c5a43d9fb 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -703,9 +703,9 @@ int bus_add_driver(struct device_driver *drv) return 0; out_unregister: + kobject_put(&priv->kobj); kfree(drv->p); drv->p = NULL; - kobject_put(&priv->kobj); out_put_bus: bus_put(bus); return error; -- cgit v1.2.3-70-g09d2 From 0787fdf70ba4c41a3350096ebaa347a17e900385 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Mon, 21 Dec 2009 11:41:08 -0500 Subject: Driver core: export platform_device_register_data as a GPL symbol This allows MFD's to register/bind drivers for their sub devices while still being compiled as a module. Signed-off-by: Michael Hennerich Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9d2ee25deaf..58efaf2f125 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -441,6 +441,7 @@ error: platform_device_put(pdev); return ERR_PTR(retval); } +EXPORT_SYMBOL_GPL(platform_device_register_data); static int platform_drv_probe(struct device *_dev) { -- cgit v1.2.3-70-g09d2 From 8042273801059884da2d53bbca34575d090b6f4e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 22 Dec 2009 22:25:16 +0100 Subject: devtmpfs: unlock mutex in case of string allocation error Reported-by: Kirill A. Shutemov Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/devtmpfs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c index 278371c7bf5..090dd485130 100644 --- a/drivers/base/devtmpfs.c +++ b/drivers/base/devtmpfs.c @@ -101,8 +101,10 @@ static int create_path(const char *nodepath) /* parent directories do not exist, create them */ path = kstrdup(nodepath, GFP_KERNEL); - if (!path) - return -ENOMEM; + if (!path) { + err = -ENOMEM; + goto out; + } s = path; for (;;) { s = strchr(s, '/'); @@ -117,6 +119,7 @@ static int create_path(const char *nodepath) } kfree(path); } +out: mutex_unlock(&dirlock); return err; } -- cgit v1.2.3-70-g09d2 From d7edf47947f9d921be6ca5fc8e83049124466f98 Mon Sep 17 00:00:00 2001 From: Wu Zhangjin Date: Mon, 23 Nov 2009 10:28:24 +0800 Subject: Staging: sm7xx: add a new framebuffer driver Yeeloong netbook has a sm712 video card, need this driver, but it is not ready to upstream yet, so, go to drivers/staing at first. This source code is originally from Silicon Motion Technology Corp, and maintained at http://dev.lemote.com/code/linux_loongson for YeeLoong netbook. I have done a lot of cleanups for it and merged it into my git repository at http://dev.lemote.com/code/rt4ls. Thanks to Simon for testing it on a little-endian x86 platform. Thanks to Olivier Croset for reporting the problem about __BIG_ENDIAN compiling problem and send a relative patch. The suspend/resume and blank support are contributed by Jason from Silicon Motion Technology. Tested-by: Simon Braunschmidt Signed-off-by: Wu Zhangjin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 + drivers/staging/Makefile | 1 + drivers/staging/sm7xx/Kconfig | 15 + drivers/staging/sm7xx/Makefile | 3 + drivers/staging/sm7xx/TODO | 10 + drivers/staging/sm7xx/smtc2d.c | 979 +++++++++++++++++++++++++++++++ drivers/staging/sm7xx/smtc2d.h | 530 +++++++++++++++++ drivers/staging/sm7xx/smtcfb.c | 1253 ++++++++++++++++++++++++++++++++++++++++ drivers/staging/sm7xx/smtcfb.h | 793 +++++++++++++++++++++++++ 9 files changed, 3586 insertions(+) create mode 100644 drivers/staging/sm7xx/Kconfig create mode 100644 drivers/staging/sm7xx/Makefile create mode 100644 drivers/staging/sm7xx/TODO create mode 100644 drivers/staging/sm7xx/smtc2d.c create mode 100644 drivers/staging/sm7xx/smtc2d.h create mode 100644 drivers/staging/sm7xx/smtcfb.c create mode 100644 drivers/staging/sm7xx/smtcfb.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 093f57af32d..db0de940949 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -145,5 +145,7 @@ source "drivers/staging/wavelan/Kconfig" source "drivers/staging/netwave/Kconfig" +source "drivers/staging/sm7xx/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 069864f4391..73c6a71155e 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -53,3 +53,4 @@ obj-$(CONFIG_ARLAN) += arlan/ obj-$(CONFIG_WAVELAN) += wavelan/ obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan/ obj-$(CONFIG_PCMCIA_NETWAVE) += netwave/ +obj-$(CONFIG_FB_SM7XX) += sm7xx/ diff --git a/drivers/staging/sm7xx/Kconfig b/drivers/staging/sm7xx/Kconfig new file mode 100644 index 00000000000..204dbfc3c38 --- /dev/null +++ b/drivers/staging/sm7xx/Kconfig @@ -0,0 +1,15 @@ +config FB_SM7XX + tristate "Silicon Motion SM7XX Frame Buffer Support" + depends on FB + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + Frame Buffer driver for the Silicon Motion SM7XX serial graphic card. + +config FB_SM7XX_ACCEL + bool "Siliconmotion Acceleration functions (EXPERIMENTAL)" + depends on FB_SM7XX && EXPERIMENTAL + help + This will compile the Trident frame buffer device with + acceleration functions. diff --git a/drivers/staging/sm7xx/Makefile b/drivers/staging/sm7xx/Makefile new file mode 100644 index 00000000000..f43cb910630 --- /dev/null +++ b/drivers/staging/sm7xx/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_FB_SM7XX) += sm7xx.o + +sm7xx-y := smtcfb.o diff --git a/drivers/staging/sm7xx/TODO b/drivers/staging/sm7xx/TODO new file mode 100644 index 00000000000..1f61f5e11cf --- /dev/null +++ b/drivers/staging/sm7xx/TODO @@ -0,0 +1,10 @@ +TODO: +- Dual head support +- use kernel coding style +- checkpatch.pl clean +- refine the code and remove unused code +- use kernel framebuffer mode setting instead of hard code +- move it to drivers/video/sm7xx/ or make it be drivers/video/sm7xxfb.c + +Please send any patches to Greg Kroah-Hartman and +Teddy Wang . diff --git a/drivers/staging/sm7xx/smtc2d.c b/drivers/staging/sm7xx/smtc2d.c new file mode 100644 index 00000000000..133b86c6a67 --- /dev/null +++ b/drivers/staging/sm7xx/smtc2d.c @@ -0,0 +1,979 @@ +/* + * Silicon Motion SM7XX 2D drawing engine functions. + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Author: Boyod boyod.yang@siliconmotion.com.cn + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Version 0.10.26192.21.01 + * - Add PowerPC support + * - Add 2D support for Lynx - + * Verified on 2.6.19.2 + * Boyod.yang + */ + +unsigned char smtc_de_busy; + +void SMTC_write2Dreg(unsigned long nOffset, unsigned long nData) +{ + writel(nData, smtc_2DBaseAddress + nOffset); +} + +unsigned long SMTC_read2Dreg(unsigned long nOffset) +{ + return readl(smtc_2DBaseAddress + nOffset); +} + +void SMTC_write2Ddataport(unsigned long nOffset, unsigned long nData) +{ + writel(nData, smtc_2Ddataport + nOffset); +} + +/********************************************************************** + * + * deInit + * + * Purpose + * Drawing engine initialization. + * + **********************************************************************/ + +void deInit(unsigned int nModeWidth, unsigned int nModeHeight, + unsigned int bpp) +{ + /* Get current power configuration. */ + unsigned char clock; + clock = smtc_seqr(0x21); + + /* initialize global 'mutex lock' variable */ + smtc_de_busy = 0; + + /* Enable 2D Drawing Engine */ + smtc_seqw(0x21, clock & 0xF8); + + SMTC_write2Dreg(DE_CLIP_TL, + FIELD_VALUE(0, DE_CLIP_TL, TOP, 0) | + FIELD_SET(0, DE_CLIP_TL, STATUS, DISABLE) | + FIELD_SET(0, DE_CLIP_TL, INHIBIT, OUTSIDE) | + FIELD_VALUE(0, DE_CLIP_TL, LEFT, 0)); + + if (bpp >= 24) { + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, + nModeWidth * 3) | FIELD_VALUE(0, + DE_PITCH, + SOURCE, + nModeWidth + * 3)); + } else { + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, + nModeWidth) | FIELD_VALUE(0, + DE_PITCH, + SOURCE, + nModeWidth)); + } + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + nModeWidth) | FIELD_VALUE(0, + DE_WINDOW_WIDTH, + SOURCE, + nModeWidth)); + + switch (bpp) { + case 8: + SMTC_write2Dreg(DE_STRETCH_FORMAT, + FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY, + NORMAL) | FIELD_VALUE(0, + DE_STRETCH_FORMAT, + PATTERN_Y, + 0) | + FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, + 0) | FIELD_SET(0, DE_STRETCH_FORMAT, + PIXEL_FORMAT, + 8) | FIELD_SET(0, + DE_STRETCH_FORMAT, + ADDRESSING, + XY) | + FIELD_VALUE(0, DE_STRETCH_FORMAT, + SOURCE_HEIGHT, 3)); + break; + case 24: + SMTC_write2Dreg(DE_STRETCH_FORMAT, + FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY, + NORMAL) | FIELD_VALUE(0, + DE_STRETCH_FORMAT, + PATTERN_Y, + 0) | + FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, + 0) | FIELD_SET(0, DE_STRETCH_FORMAT, + PIXEL_FORMAT, + 24) | FIELD_SET(0, + DE_STRETCH_FORMAT, + ADDRESSING, + XY) | + FIELD_VALUE(0, DE_STRETCH_FORMAT, + SOURCE_HEIGHT, 3)); + break; + case 16: + default: + SMTC_write2Dreg(DE_STRETCH_FORMAT, + FIELD_SET(0, DE_STRETCH_FORMAT, PATTERN_XY, + NORMAL) | FIELD_VALUE(0, + DE_STRETCH_FORMAT, + PATTERN_Y, + 0) | + FIELD_VALUE(0, DE_STRETCH_FORMAT, PATTERN_X, + 0) | FIELD_SET(0, DE_STRETCH_FORMAT, + PIXEL_FORMAT, + 16) | FIELD_SET(0, + DE_STRETCH_FORMAT, + ADDRESSING, + XY) | + FIELD_VALUE(0, DE_STRETCH_FORMAT, + SOURCE_HEIGHT, 3)); + break; + } + + SMTC_write2Dreg(DE_MASKS, + FIELD_VALUE(0, DE_MASKS, BYTE_MASK, 0xFFFF) | + FIELD_VALUE(0, DE_MASKS, BIT_MASK, 0xFFFF)); + SMTC_write2Dreg(DE_COLOR_COMPARE_MASK, + FIELD_VALUE(0, DE_COLOR_COMPARE_MASK, MASKS, \ + 0xFFFFFF)); + SMTC_write2Dreg(DE_COLOR_COMPARE, + FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, 0xFFFFFF)); +} + +void deVerticalLine(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long nX, + unsigned long nY, + unsigned long dst_height, unsigned long nColor) +{ + deWaitForNotBusy(); + + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, + dst_base)); + + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) | + FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch)); + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH, + SOURCE, + dst_pitch)); + + SMTC_write2Dreg(DE_FOREGROUND, + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); + + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | + FIELD_VALUE(0, DE_DESTINATION, X, nX) | + FIELD_VALUE(0, DE_DESTINATION, Y, nY)); + + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, 1) | + FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height)); + + SMTC_write2Dreg(DE_CONTROL, + FIELD_SET(0, DE_CONTROL, STATUS, START) | + FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) | + FIELD_SET(0, DE_CONTROL, MAJOR, Y) | + FIELD_SET(0, DE_CONTROL, STEP_X, NEGATIVE) | + FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) | + FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) | + FIELD_SET(0, DE_CONTROL, COMMAND, SHORT_STROKE) | + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | + FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C)); + + smtc_de_busy = 1; +} + +void deHorizontalLine(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long nX, + unsigned long nY, + unsigned long dst_width, unsigned long nColor) +{ + deWaitForNotBusy(); + + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, + dst_base)); + + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, dst_pitch) | + FIELD_VALUE(0, DE_PITCH, SOURCE, dst_pitch)); + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, DE_WINDOW_WIDTH, + SOURCE, + dst_pitch)); + SMTC_write2Dreg(DE_FOREGROUND, + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, + DISABLE) | FIELD_VALUE(0, DE_DESTINATION, X, + nX) | FIELD_VALUE(0, + DE_DESTINATION, + Y, + nY)); + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, + dst_width) | FIELD_VALUE(0, DE_DIMENSION, + Y_ET, 1)); + SMTC_write2Dreg(DE_CONTROL, + FIELD_SET(0, DE_CONTROL, STATUS, START) | FIELD_SET(0, + DE_CONTROL, + DIRECTION, + RIGHT_TO_LEFT) + | FIELD_SET(0, DE_CONTROL, MAJOR, X) | FIELD_SET(0, + DE_CONTROL, + STEP_X, + POSITIVE) + | FIELD_SET(0, DE_CONTROL, STEP_Y, + NEGATIVE) | FIELD_SET(0, DE_CONTROL, + LAST_PIXEL, + OFF) | FIELD_SET(0, + DE_CONTROL, + COMMAND, + SHORT_STROKE) + | FIELD_SET(0, DE_CONTROL, ROP_SELECT, + ROP2) | FIELD_VALUE(0, DE_CONTROL, ROP, + 0x0C)); + + smtc_de_busy = 1; +} + +void deLine(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long nX1, + unsigned long nY1, + unsigned long nX2, unsigned long nY2, unsigned long nColor) +{ + unsigned long nCommand = + FIELD_SET(0, DE_CONTROL, STATUS, START) | + FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) | + FIELD_SET(0, DE_CONTROL, MAJOR, X) | + FIELD_SET(0, DE_CONTROL, STEP_X, POSITIVE) | + FIELD_SET(0, DE_CONTROL, STEP_Y, POSITIVE) | + FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) | + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | + FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C); + unsigned long DeltaX; + unsigned long DeltaY; + + /* Calculate delta X */ + if (nX1 <= nX2) + DeltaX = nX2 - nX1; + else { + DeltaX = nX1 - nX2; + nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_X, NEGATIVE); + } + + /* Calculate delta Y */ + if (nY1 <= nY2) + DeltaY = nY2 - nY1; + else { + DeltaY = nY1 - nY2; + nCommand = FIELD_SET(nCommand, DE_CONTROL, STEP_Y, NEGATIVE); + } + + /* Determine the major axis */ + if (DeltaX < DeltaY) + nCommand = FIELD_SET(nCommand, DE_CONTROL, MAJOR, Y); + + /* Vertical line? */ + if (nX1 == nX2) + deVerticalLine(dst_base, dst_pitch, nX1, nY1, DeltaY, nColor); + + /* Horizontal line? */ + else if (nY1 == nY2) + deHorizontalLine(dst_base, dst_pitch, nX1, nY1, \ + DeltaX, nColor); + + /* Diagonal line? */ + else if (DeltaX == DeltaY) { + deWaitForNotBusy(); + + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, + ADDRESS, dst_base)); + + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_PITCH, + SOURCE, + dst_pitch)); + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_WINDOW_WIDTH, + SOURCE, + dst_pitch)); + + SMTC_write2Dreg(DE_FOREGROUND, + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); + + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | + FIELD_VALUE(0, DE_DESTINATION, X, 1) | + FIELD_VALUE(0, DE_DESTINATION, Y, nY1)); + + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, 1) | + FIELD_VALUE(0, DE_DIMENSION, Y_ET, DeltaX)); + + SMTC_write2Dreg(DE_CONTROL, + FIELD_SET(nCommand, DE_CONTROL, COMMAND, + SHORT_STROKE)); + } + + /* Generic line */ + else { + unsigned int k1, k2, et, w; + if (DeltaX < DeltaY) { + k1 = 2 * DeltaX; + et = k1 - DeltaY; + k2 = et - DeltaY; + w = DeltaY + 1; + } else { + k1 = 2 * DeltaY; + et = k1 - DeltaX; + k2 = et - DeltaX; + w = DeltaX + 1; + } + + deWaitForNotBusy(); + + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, + ADDRESS, dst_base)); + + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_PITCH, + SOURCE, + dst_pitch)); + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_WINDOW_WIDTH, + SOURCE, + dst_pitch)); + + SMTC_write2Dreg(DE_FOREGROUND, + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); + + SMTC_write2Dreg(DE_SOURCE, + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | + FIELD_VALUE(0, DE_SOURCE, X_K1, k1) | + FIELD_VALUE(0, DE_SOURCE, Y_K2, k2)); + + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | + FIELD_VALUE(0, DE_DESTINATION, X, nX1) | + FIELD_VALUE(0, DE_DESTINATION, Y, nY1)); + + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, w) | + FIELD_VALUE(0, DE_DIMENSION, Y_ET, et)); + + SMTC_write2Dreg(DE_CONTROL, + FIELD_SET(nCommand, DE_CONTROL, COMMAND, + LINE_DRAW)); + } + + smtc_de_busy = 1; +} + +void deFillRect(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long dst_X, + unsigned long dst_Y, + unsigned long dst_width, + unsigned long dst_height, unsigned long nColor) +{ + deWaitForNotBusy(); + + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, + dst_base)); + + if (dst_pitch) { + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_PITCH, + SOURCE, + dst_pitch)); + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_WINDOW_WIDTH, + SOURCE, + dst_pitch)); + } + + SMTC_write2Dreg(DE_FOREGROUND, + FIELD_VALUE(0, DE_FOREGROUND, COLOR, nColor)); + + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | + FIELD_VALUE(0, DE_DESTINATION, X, dst_X) | + FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y)); + + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, dst_width) | + FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height)); + + SMTC_write2Dreg(DE_CONTROL, + FIELD_SET(0, DE_CONTROL, STATUS, START) | + FIELD_SET(0, DE_CONTROL, DIRECTION, LEFT_TO_RIGHT) | + FIELD_SET(0, DE_CONTROL, LAST_PIXEL, OFF) | + FIELD_SET(0, DE_CONTROL, COMMAND, RECTANGLE_FILL) | + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | + FIELD_VALUE(0, DE_CONTROL, ROP, 0x0C)); + + smtc_de_busy = 1; +} + +/********************************************************************** + * + * deRotatePattern + * + * Purpose + * Rotate the given pattern if necessary + * + * Parameters + * [in] + * pPattern - Pointer to DE_SURFACE structure containing + * pattern attributes + * patternX - X position (0-7) of pattern origin + * patternY - Y position (0-7) of pattern origin + * + * [out] + * pattern_dstaddr - Pointer to pre-allocated buffer containing + * rotated pattern + * + **********************************************************************/ +void deRotatePattern(unsigned char *pattern_dstaddr, + unsigned long pattern_src_addr, + unsigned long pattern_BPP, + unsigned long pattern_stride, int patternX, int patternY) +{ + unsigned int i; + unsigned long pattern[PATTERN_WIDTH * PATTERN_HEIGHT]; + unsigned int x, y; + unsigned char *pjPatByte; + + if (pattern_dstaddr != NULL) { + deWaitForNotBusy(); + + if (patternX || patternY) { + /* Rotate pattern */ + pjPatByte = (unsigned char *)pattern; + + switch (pattern_BPP) { + case 8: + { + for (y = 0; y < 8; y++) { + unsigned char *pjBuffer = + pattern_dstaddr + + ((patternY + y) & 7) * 8; + for (x = 0; x < 8; x++) { + pjBuffer[(patternX + + x) & 7] = + pjPatByte[x]; + } + pjPatByte += pattern_stride; + } + break; + } + + case 16: + { + for (y = 0; y < 8; y++) { + unsigned short *pjBuffer = + (unsigned short *) + pattern_dstaddr + + ((patternY + y) & 7) * 8; + for (x = 0; x < 8; x++) { + pjBuffer[(patternX + + x) & 7] = + ((unsigned short *) + pjPatByte)[x]; + } + pjPatByte += pattern_stride; + } + break; + } + + case 32: + { + for (y = 0; y < 8; y++) { + unsigned long *pjBuffer = + (unsigned long *) + pattern_dstaddr + + ((patternY + y) & 7) * 8; + for (x = 0; x < 8; x++) { + pjBuffer[(patternX + + x) & 7] = + ((unsigned long *) + pjPatByte)[x]; + } + pjPatByte += pattern_stride; + } + break; + } + } + } else { + /*Don't rotate,just copy pattern into pattern_dstaddr*/ + for (i = 0; i < (pattern_BPP * 2); i++) { + ((unsigned long *)pattern_dstaddr)[i] = + pattern[i]; + } + } + + } +} + +/********************************************************************** + * + * deCopy + * + * Purpose + * Copy a rectangular area of the source surface to a destination surface + * + * Remarks + * Source bitmap must have the same color depth (BPP) as the destination + * bitmap. + * +**********************************************************************/ +void deCopy(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long dst_BPP, + unsigned long dst_X, + unsigned long dst_Y, + unsigned long dst_width, + unsigned long dst_height, + unsigned long src_base, + unsigned long src_pitch, + unsigned long src_X, + unsigned long src_Y, pTransparent pTransp, unsigned char nROP2) +{ + unsigned long nDirection = 0; + unsigned long nTransparent = 0; + /* Direction of ROP2 operation: + * 1 = Left to Right, + * (-1) = Right to Left + */ + unsigned long opSign = 1; + /* xWidth is in pixels */ + unsigned long xWidth = 192 / (dst_BPP / 8); + unsigned long de_ctrl = 0; + + deWaitForNotBusy(); + + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, + FIELD_VALUE(0, DE_WINDOW_DESTINATION_BASE, ADDRESS, + dst_base)); + + SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, + FIELD_VALUE(0, DE_WINDOW_SOURCE_BASE, ADDRESS, + src_base)); + + if (dst_pitch && src_pitch) { + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_PITCH, + SOURCE, + src_pitch)); + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + dst_pitch) | FIELD_VALUE(0, + DE_WINDOW_WIDTH, + SOURCE, + src_pitch)); + } + + /* Set transparent bits if necessary */ + if (pTransp != NULL) { + nTransparent = + pTransp->match | pTransp->select | pTransp->control; + + /* Set color compare register */ + SMTC_write2Dreg(DE_COLOR_COMPARE, + FIELD_VALUE(0, DE_COLOR_COMPARE, COLOR, + pTransp->color)); + } + + /* Determine direction of operation */ + if (src_Y < dst_Y) { + /* +----------+ + |S | + | +----------+ + | | | | + | | | | + +---|------+ | + | D | + +----------+ */ + + nDirection = BOTTOM_TO_TOP; + } else if (src_Y > dst_Y) { + /* +----------+ + |D | + | +----------+ + | | | | + | | | | + +---|------+ | + | S | + +----------+ */ + + nDirection = TOP_TO_BOTTOM; + } else { + /* src_Y == dst_Y */ + + if (src_X <= dst_X) { + /* +------+---+------+ + |S | | D| + | | | | + | | | | + | | | | + +------+---+------+ */ + + nDirection = RIGHT_TO_LEFT; + } else { + /* src_X > dst_X */ + + /* +------+---+------+ + |D | | S| + | | | | + | | | | + | | | | + +------+---+------+ */ + + nDirection = LEFT_TO_RIGHT; + } + } + + if ((nDirection == BOTTOM_TO_TOP) || (nDirection == RIGHT_TO_LEFT)) { + src_X += dst_width - 1; + src_Y += dst_height - 1; + dst_X += dst_width - 1; + dst_Y += dst_height - 1; + opSign = (-1); + } + + if (dst_BPP >= 24) { + src_X *= 3; + src_Y *= 3; + dst_X *= 3; + dst_Y *= 3; + dst_width *= 3; + if ((nDirection == BOTTOM_TO_TOP) + || (nDirection == RIGHT_TO_LEFT)) { + src_X += 2; + dst_X += 2; + } + } + + /* Workaround for 192 byte hw bug */ + if ((nROP2 != 0x0C) && ((dst_width * (dst_BPP / 8)) >= 192)) { + /* + * Perform the ROP2 operation in chunks of (xWidth * + * dst_height) + */ + while (1) { + deWaitForNotBusy(); + + SMTC_write2Dreg(DE_SOURCE, + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | + FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) | + FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y)); + + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, + DISABLE) | FIELD_VALUE(0, + DE_DESTINATION, + X, + dst_X) + | FIELD_VALUE(0, DE_DESTINATION, Y, + dst_Y)); + + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, + xWidth) | FIELD_VALUE(0, + DE_DIMENSION, + Y_ET, + dst_height)); + + de_ctrl = + FIELD_VALUE(0, DE_CONTROL, ROP, + nROP2) | nTransparent | FIELD_SET(0, + DE_CONTROL, + ROP_SELECT, + ROP2) + | FIELD_SET(0, DE_CONTROL, COMMAND, + BITBLT) | ((nDirection == + 1) ? FIELD_SET(0, + DE_CONTROL, + DIRECTION, + RIGHT_TO_LEFT) + : FIELD_SET(0, DE_CONTROL, + DIRECTION, + LEFT_TO_RIGHT)) | + FIELD_SET(0, DE_CONTROL, STATUS, START); + + SMTC_write2Dreg(DE_CONTROL, de_ctrl); + + src_X += (opSign * xWidth); + dst_X += (opSign * xWidth); + dst_width -= xWidth; + + if (dst_width <= 0) { + /* ROP2 operation is complete */ + break; + } + + if (xWidth > dst_width) + xWidth = dst_width; + } + } else { + deWaitForNotBusy(); + SMTC_write2Dreg(DE_SOURCE, + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | + FIELD_VALUE(0, DE_SOURCE, X_K1, src_X) | + FIELD_VALUE(0, DE_SOURCE, Y_K2, src_Y)); + + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | + FIELD_VALUE(0, DE_DESTINATION, X, dst_X) | + FIELD_VALUE(0, DE_DESTINATION, Y, dst_Y)); + + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, dst_width) | + FIELD_VALUE(0, DE_DIMENSION, Y_ET, dst_height)); + + de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, nROP2) | + nTransparent | + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | + FIELD_SET(0, DE_CONTROL, COMMAND, BITBLT) | + ((nDirection == 1) ? FIELD_SET(0, DE_CONTROL, DIRECTION, + RIGHT_TO_LEFT) + : FIELD_SET(0, DE_CONTROL, DIRECTION, + LEFT_TO_RIGHT)) | FIELD_SET(0, DE_CONTROL, + STATUS, START); + SMTC_write2Dreg(DE_CONTROL, de_ctrl); + } + + smtc_de_busy = 1; +} + +/* + * This function sets the pixel format that will apply to the 2D Engine. + */ +void deSetPixelFormat(unsigned long bpp) +{ + unsigned long de_format; + + de_format = SMTC_read2Dreg(DE_STRETCH_FORMAT); + + switch (bpp) { + case 8: + de_format = + FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 8); + break; + default: + case 16: + de_format = + FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 16); + break; + case 32: + de_format = + FIELD_SET(de_format, DE_STRETCH_FORMAT, PIXEL_FORMAT, 32); + break; + } + + SMTC_write2Dreg(DE_STRETCH_FORMAT, de_format); +} + +/* + * System memory to Video memory monochrome expansion. + * + * Source is monochrome image in system memory. This function expands the + * monochrome data to color image in video memory. + */ + +long deSystemMem2VideoMemMonoBlt(const char *pSrcbuf, + long srcDelta, + unsigned long startBit, + unsigned long dBase, + unsigned long dPitch, + unsigned long bpp, + unsigned long dx, unsigned long dy, + unsigned long width, unsigned long height, + unsigned long fColor, + unsigned long bColor, + unsigned long rop2) { + unsigned long bytePerPixel; + unsigned long ulBytesPerScan; + unsigned long ul4BytesPerScan; + unsigned long ulBytesRemain; + unsigned long de_ctrl = 0; + unsigned char ajRemain[4]; + long i, j; + + bytePerPixel = bpp / 8; + + /* Just make sure the start bit is within legal range */ + startBit &= 7; + + ulBytesPerScan = (width + startBit + 7) / 8; + ul4BytesPerScan = ulBytesPerScan & ~3; + ulBytesRemain = ulBytesPerScan & 3; + + if (smtc_de_busy) + deWaitForNotBusy(); + + /* + * 2D Source Base. Use 0 for HOST Blt. + */ + + SMTC_write2Dreg(DE_WINDOW_SOURCE_BASE, 0); + + /* + * 2D Destination Base. + * + * It is an address offset (128 bit aligned) from the beginning of + * frame buffer. + */ + + SMTC_write2Dreg(DE_WINDOW_DESTINATION_BASE, dBase); + + if (dPitch) { + + /* + * Program pitch (distance between the 1st points of two + * adjacent lines). + * + * Note that input pitch is BYTE value, but the 2D Pitch + * register uses pixel values. Need Byte to pixel convertion. + */ + + SMTC_write2Dreg(DE_PITCH, + FIELD_VALUE(0, DE_PITCH, DESTINATION, + dPitch / + bytePerPixel) | FIELD_VALUE(0, + DE_PITCH, + SOURCE, + dPitch / + bytePerPixel)); + + /* Screen Window width in Pixels. + * + * 2D engine uses this value to calculate the linear address in + * frame buffer for a given point. + */ + + SMTC_write2Dreg(DE_WINDOW_WIDTH, + FIELD_VALUE(0, DE_WINDOW_WIDTH, DESTINATION, + (dPitch / + bytePerPixel)) | FIELD_VALUE(0, + DE_WINDOW_WIDTH, + SOURCE, + (dPitch + / + bytePerPixel))); + } + /* Note: For 2D Source in Host Write, only X_K1 field is needed, and + * Y_K2 field is not used. For mono bitmap, use startBit for X_K1. + */ + + SMTC_write2Dreg(DE_SOURCE, + FIELD_SET(0, DE_SOURCE, WRAP, DISABLE) | + FIELD_VALUE(0, DE_SOURCE, X_K1, startBit) | + FIELD_VALUE(0, DE_SOURCE, Y_K2, 0)); + + SMTC_write2Dreg(DE_DESTINATION, + FIELD_SET(0, DE_DESTINATION, WRAP, DISABLE) | + FIELD_VALUE(0, DE_DESTINATION, X, dx) | + FIELD_VALUE(0, DE_DESTINATION, Y, dy)); + + SMTC_write2Dreg(DE_DIMENSION, + FIELD_VALUE(0, DE_DIMENSION, X, width) | + FIELD_VALUE(0, DE_DIMENSION, Y_ET, height)); + + SMTC_write2Dreg(DE_FOREGROUND, fColor); + SMTC_write2Dreg(DE_BACKGROUND, bColor); + + if (bpp) + deSetPixelFormat(bpp); + /* Set the pixel format of the destination */ + + de_ctrl = FIELD_VALUE(0, DE_CONTROL, ROP, rop2) | + FIELD_SET(0, DE_CONTROL, ROP_SELECT, ROP2) | + FIELD_SET(0, DE_CONTROL, COMMAND, HOST_WRITE) | + FIELD_SET(0, DE_CONTROL, HOST, MONO) | + FIELD_SET(0, DE_CONTROL, STATUS, START); + + SMTC_write2Dreg(DE_CONTROL, de_ctrl | deGetTransparency()); + + /* Write MONO data (line by line) to 2D Engine data port */ + for (i = 0; i < height; i++) { + /* For each line, send the data in chunks of 4 bytes */ + for (j = 0; j < (ul4BytesPerScan / 4); j++) + SMTC_write2Ddataport(0, + *(unsigned long *)(pSrcbuf + + (j * 4))); + + if (ulBytesRemain) { + memcpy(ajRemain, pSrcbuf + ul4BytesPerScan, + ulBytesRemain); + SMTC_write2Ddataport(0, *(unsigned long *)ajRemain); + } + + pSrcbuf += srcDelta; + } + smtc_de_busy = 1; + + return 0; +} + +/* + * This function gets the transparency status from DE_CONTROL register. + * It returns a double word with the transparent fields properly set, + * while other fields are 0. + */ +unsigned long deGetTransparency(void) +{ + unsigned long de_ctrl; + + de_ctrl = SMTC_read2Dreg(DE_CONTROL); + + de_ctrl &= + FIELD_MASK(DE_CONTROL_TRANSPARENCY_MATCH) | + FIELD_MASK(DE_CONTROL_TRANSPARENCY_SELECT) | + FIELD_MASK(DE_CONTROL_TRANSPARENCY); + + return de_ctrl; +} diff --git a/drivers/staging/sm7xx/smtc2d.h b/drivers/staging/sm7xx/smtc2d.h new file mode 100644 index 00000000000..38d0c335322 --- /dev/null +++ b/drivers/staging/sm7xx/smtc2d.h @@ -0,0 +1,530 @@ +/* + * Silicon Motion SM712 2D drawing engine functions. + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Author: Ge Wang, gewang@siliconmotion.com + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#ifndef NULL +#define NULL 0 +#endif + +/* Internal macros */ + +#define _F_START(f) (0 ? f) +#define _F_END(f) (1 ? f) +#define _F_SIZE(f) (1 + _F_END(f) - _F_START(f)) +#define _F_MASK(f) (((1ULL << _F_SIZE(f)) - 1) << _F_START(f)) +#define _F_NORMALIZE(v, f) (((v) & _F_MASK(f)) >> _F_START(f)) +#define _F_DENORMALIZE(v, f) (((v) << _F_START(f)) & _F_MASK(f)) + +/* Global macros */ + +#define FIELD_GET(x, reg, field) \ +( \ + _F_NORMALIZE((x), reg ## _ ## field) \ +) + +#define FIELD_SET(x, reg, field, value) \ +( \ + (x & ~_F_MASK(reg ## _ ## field)) \ + | _F_DENORMALIZE(reg ## _ ## field ## _ ## value, reg ## _ ## field) \ +) + +#define FIELD_VALUE(x, reg, field, value) \ +( \ + (x & ~_F_MASK(reg ## _ ## field)) \ + | _F_DENORMALIZE(value, reg ## _ ## field) \ +) + +#define FIELD_CLEAR(reg, field) \ +( \ + ~_F_MASK(reg ## _ ## field) \ +) + +/* Field Macros */ + +#define FIELD_START(field) (0 ? field) +#define FIELD_END(field) (1 ? field) +#define FIELD_SIZE(field) \ + (1 + FIELD_END(field) - FIELD_START(field)) + +#define FIELD_MASK(field) \ + (((1 << (FIELD_SIZE(field)-1)) \ + | ((1 << (FIELD_SIZE(field)-1)) - 1)) \ + << FIELD_START(field)) + +#define FIELD_NORMALIZE(reg, field) \ + (((reg) & FIELD_MASK(field)) >> FIELD_START(field)) + +#define FIELD_DENORMALIZE(field, value) \ + (((value) << FIELD_START(field)) & FIELD_MASK(field)) + +#define FIELD_INIT(reg, field, value) \ + FIELD_DENORMALIZE(reg ## _ ## field, \ + reg ## _ ## field ## _ ## value) + +#define FIELD_INIT_VAL(reg, field, value) \ + (FIELD_DENORMALIZE(reg ## _ ## field, value)) + +#define FIELD_VAL_SET(x, r, f, v) ({ \ + x = (x & ~FIELD_MASK(r ## _ ## f)) \ + | FIELD_DENORMALIZE(r ## _ ## f, r ## _ ## f ## _ ## v) \ +}) + +#define RGB(r, g, b) ((unsigned long)(((r) << 16) | ((g) << 8) | (b))) + +/* Transparent info definition */ +typedef struct { + unsigned long match; /* Matching pixel is OPAQUE/TRANSPARENT */ + unsigned long select; /* Transparency controlled by SRC/DST */ + unsigned long control; /* ENABLE/DISABLE transparency */ + unsigned long color; /* Transparent color */ +} Transparent, *pTransparent; + +#define PIXEL_DEPTH_1_BP 0 /* 1 bit per pixel */ +#define PIXEL_DEPTH_8_BPP 1 /* 8 bits per pixel */ +#define PIXEL_DEPTH_16_BPP 2 /* 16 bits per pixel */ +#define PIXEL_DEPTH_32_BPP 3 /* 32 bits per pixel */ +#define PIXEL_DEPTH_YUV422 8 /* 16 bits per pixel YUV422 */ +#define PIXEL_DEPTH_YUV420 9 /* 16 bits per pixel YUV420 */ + +#define PATTERN_WIDTH 8 +#define PATTERN_HEIGHT 8 + +#define TOP_TO_BOTTOM 0 +#define BOTTOM_TO_TOP 1 +#define RIGHT_TO_LEFT BOTTOM_TO_TOP +#define LEFT_TO_RIGHT TOP_TO_BOTTOM + +/* Constants used in Transparent structure */ +#define MATCH_OPAQUE 0x00000000 +#define MATCH_TRANSPARENT 0x00000400 +#define SOURCE 0x00000000 +#define DESTINATION 0x00000200 + +/* 2D registers. */ + +#define DE_SOURCE 0x000000 +#define DE_SOURCE_WRAP 31 : 31 +#define DE_SOURCE_WRAP_DISABLE 0 +#define DE_SOURCE_WRAP_ENABLE 1 +#define DE_SOURCE_X_K1 29 : 16 +#define DE_SOURCE_Y_K2 15 : 0 + +#define DE_DESTINATION 0x000004 +#define DE_DESTINATION_WRAP 31 : 31 +#define DE_DESTINATION_WRAP_DISABLE 0 +#define DE_DESTINATION_WRAP_ENABLE 1 +#define DE_DESTINATION_X 28 : 16 +#define DE_DESTINATION_Y 15 : 0 + +#define DE_DIMENSION 0x000008 +#define DE_DIMENSION_X 28 : 16 +#define DE_DIMENSION_Y_ET 15 : 0 + +#define DE_CONTROL 0x00000C +#define DE_CONTROL_STATUS 31 : 31 +#define DE_CONTROL_STATUS_STOP 0 +#define DE_CONTROL_STATUS_START 1 +#define DE_CONTROL_PATTERN 30 : 30 +#define DE_CONTROL_PATTERN_MONO 0 +#define DE_CONTROL_PATTERN_COLOR 1 +#define DE_CONTROL_UPDATE_DESTINATION_X 29 : 29 +#define DE_CONTROL_UPDATE_DESTINATION_X_DISABLE 0 +#define DE_CONTROL_UPDATE_DESTINATION_X_ENABLE 1 +#define DE_CONTROL_QUICK_START 28 : 28 +#define DE_CONTROL_QUICK_START_DISABLE 0 +#define DE_CONTROL_QUICK_START_ENABLE 1 +#define DE_CONTROL_DIRECTION 27 : 27 +#define DE_CONTROL_DIRECTION_LEFT_TO_RIGHT 0 +#define DE_CONTROL_DIRECTION_RIGHT_TO_LEFT 1 +#define DE_CONTROL_MAJOR 26 : 26 +#define DE_CONTROL_MAJOR_X 0 +#define DE_CONTROL_MAJOR_Y 1 +#define DE_CONTROL_STEP_X 25 : 25 +#define DE_CONTROL_STEP_X_POSITIVE 1 +#define DE_CONTROL_STEP_X_NEGATIVE 0 +#define DE_CONTROL_STEP_Y 24 : 24 +#define DE_CONTROL_STEP_Y_POSITIVE 1 +#define DE_CONTROL_STEP_Y_NEGATIVE 0 +#define DE_CONTROL_STRETCH 23 : 23 +#define DE_CONTROL_STRETCH_DISABLE 0 +#define DE_CONTROL_STRETCH_ENABLE 1 +#define DE_CONTROL_HOST 22 : 22 +#define DE_CONTROL_HOST_COLOR 0 +#define DE_CONTROL_HOST_MONO 1 +#define DE_CONTROL_LAST_PIXEL 21 : 21 +#define DE_CONTROL_LAST_PIXEL_OFF 0 +#define DE_CONTROL_LAST_PIXEL_ON 1 +#define DE_CONTROL_COMMAND 20 : 16 +#define DE_CONTROL_COMMAND_BITBLT 0 +#define DE_CONTROL_COMMAND_RECTANGLE_FILL 1 +#define DE_CONTROL_COMMAND_DE_TILE 2 +#define DE_CONTROL_COMMAND_TRAPEZOID_FILL 3 +#define DE_CONTROL_COMMAND_ALPHA_BLEND 4 +#define DE_CONTROL_COMMAND_RLE_STRIP 5 +#define DE_CONTROL_COMMAND_SHORT_STROKE 6 +#define DE_CONTROL_COMMAND_LINE_DRAW 7 +#define DE_CONTROL_COMMAND_HOST_WRITE 8 +#define DE_CONTROL_COMMAND_HOST_READ 9 +#define DE_CONTROL_COMMAND_HOST_WRITE_BOTTOM_UP 10 +#define DE_CONTROL_COMMAND_ROTATE 11 +#define DE_CONTROL_COMMAND_FONT 12 +#define DE_CONTROL_COMMAND_TEXTURE_LOAD 15 +#define DE_CONTROL_ROP_SELECT 15 : 15 +#define DE_CONTROL_ROP_SELECT_ROP3 0 +#define DE_CONTROL_ROP_SELECT_ROP2 1 +#define DE_CONTROL_ROP2_SOURCE 14 : 14 +#define DE_CONTROL_ROP2_SOURCE_BITMAP 0 +#define DE_CONTROL_ROP2_SOURCE_PATTERN 1 +#define DE_CONTROL_MONO_DATA 13 : 12 +#define DE_CONTROL_MONO_DATA_NOT_PACKED 0 +#define DE_CONTROL_MONO_DATA_8_PACKED 1 +#define DE_CONTROL_MONO_DATA_16_PACKED 2 +#define DE_CONTROL_MONO_DATA_32_PACKED 3 +#define DE_CONTROL_REPEAT_ROTATE 11 : 11 +#define DE_CONTROL_REPEAT_ROTATE_DISABLE 0 +#define DE_CONTROL_REPEAT_ROTATE_ENABLE 1 +#define DE_CONTROL_TRANSPARENCY_MATCH 10 : 10 +#define DE_CONTROL_TRANSPARENCY_MATCH_OPAQUE 0 +#define DE_CONTROL_TRANSPARENCY_MATCH_TRANSPARENT 1 +#define DE_CONTROL_TRANSPARENCY_SELECT 9 : 9 +#define DE_CONTROL_TRANSPARENCY_SELECT_SOURCE 0 +#define DE_CONTROL_TRANSPARENCY_SELECT_DESTINATION 1 +#define DE_CONTROL_TRANSPARENCY 8 : 8 +#define DE_CONTROL_TRANSPARENCY_DISABLE 0 +#define DE_CONTROL_TRANSPARENCY_ENABLE 1 +#define DE_CONTROL_ROP 7 : 0 + +/* Pseudo fields. */ + +#define DE_CONTROL_SHORT_STROKE_DIR 27 : 24 +#define DE_CONTROL_SHORT_STROKE_DIR_225 0 +#define DE_CONTROL_SHORT_STROKE_DIR_135 1 +#define DE_CONTROL_SHORT_STROKE_DIR_315 2 +#define DE_CONTROL_SHORT_STROKE_DIR_45 3 +#define DE_CONTROL_SHORT_STROKE_DIR_270 4 +#define DE_CONTROL_SHORT_STROKE_DIR_90 5 +#define DE_CONTROL_SHORT_STROKE_DIR_180 8 +#define DE_CONTROL_SHORT_STROKE_DIR_0 10 +#define DE_CONTROL_ROTATION 25 : 24 +#define DE_CONTROL_ROTATION_0 0 +#define DE_CONTROL_ROTATION_270 1 +#define DE_CONTROL_ROTATION_90 2 +#define DE_CONTROL_ROTATION_180 3 + +#define DE_PITCH 0x000010 +#define DE_PITCH_DESTINATION 28 : 16 +#define DE_PITCH_SOURCE 12 : 0 + +#define DE_FOREGROUND 0x000014 +#define DE_FOREGROUND_COLOR 31 : 0 + +#define DE_BACKGROUND 0x000018 +#define DE_BACKGROUND_COLOR 31 : 0 + +#define DE_STRETCH_FORMAT 0x00001C +#define DE_STRETCH_FORMAT_PATTERN_XY 30 : 30 +#define DE_STRETCH_FORMAT_PATTERN_XY_NORMAL 0 +#define DE_STRETCH_FORMAT_PATTERN_XY_OVERWRITE 1 +#define DE_STRETCH_FORMAT_PATTERN_Y 29 : 27 +#define DE_STRETCH_FORMAT_PATTERN_X 25 : 23 +#define DE_STRETCH_FORMAT_PIXEL_FORMAT 21 : 20 +#define DE_STRETCH_FORMAT_PIXEL_FORMAT_8 0 +#define DE_STRETCH_FORMAT_PIXEL_FORMAT_16 1 +#define DE_STRETCH_FORMAT_PIXEL_FORMAT_24 3 +#define DE_STRETCH_FORMAT_PIXEL_FORMAT_32 2 +#define DE_STRETCH_FORMAT_ADDRESSING 19 : 16 +#define DE_STRETCH_FORMAT_ADDRESSING_XY 0 +#define DE_STRETCH_FORMAT_ADDRESSING_LINEAR 15 +#define DE_STRETCH_FORMAT_SOURCE_HEIGHT 11 : 0 + +#define DE_COLOR_COMPARE 0x000020 +#define DE_COLOR_COMPARE_COLOR 23 : 0 + +#define DE_COLOR_COMPARE_MASK 0x000024 +#define DE_COLOR_COMPARE_MASK_MASKS 23 : 0 + +#define DE_MASKS 0x000028 +#define DE_MASKS_BYTE_MASK 31 : 16 +#define DE_MASKS_BIT_MASK 15 : 0 + +#define DE_CLIP_TL 0x00002C +#define DE_CLIP_TL_TOP 31 : 16 +#define DE_CLIP_TL_STATUS 13 : 13 +#define DE_CLIP_TL_STATUS_DISABLE 0 +#define DE_CLIP_TL_STATUS_ENABLE 1 +#define DE_CLIP_TL_INHIBIT 12 : 12 +#define DE_CLIP_TL_INHIBIT_OUTSIDE 0 +#define DE_CLIP_TL_INHIBIT_INSIDE 1 +#define DE_CLIP_TL_LEFT 11 : 0 + +#define DE_CLIP_BR 0x000030 +#define DE_CLIP_BR_BOTTOM 31 : 16 +#define DE_CLIP_BR_RIGHT 12 : 0 + +#define DE_MONO_PATTERN_LOW 0x000034 +#define DE_MONO_PATTERN_LOW_PATTERN 31 : 0 + +#define DE_MONO_PATTERN_HIGH 0x000038 +#define DE_MONO_PATTERN_HIGH_PATTERN 31 : 0 + +#define DE_WINDOW_WIDTH 0x00003C +#define DE_WINDOW_WIDTH_DESTINATION 28 : 16 +#define DE_WINDOW_WIDTH_SOURCE 12 : 0 + +#define DE_WINDOW_SOURCE_BASE 0x000040 +#define DE_WINDOW_SOURCE_BASE_EXT 27 : 27 +#define DE_WINDOW_SOURCE_BASE_EXT_LOCAL 0 +#define DE_WINDOW_SOURCE_BASE_EXT_EXTERNAL 1 +#define DE_WINDOW_SOURCE_BASE_CS 26 : 26 +#define DE_WINDOW_SOURCE_BASE_CS_0 0 +#define DE_WINDOW_SOURCE_BASE_CS_1 1 +#define DE_WINDOW_SOURCE_BASE_ADDRESS 25 : 0 + +#define DE_WINDOW_DESTINATION_BASE 0x000044 +#define DE_WINDOW_DESTINATION_BASE_EXT 27 : 27 +#define DE_WINDOW_DESTINATION_BASE_EXT_LOCAL 0 +#define DE_WINDOW_DESTINATION_BASE_EXT_EXTERNAL 1 +#define DE_WINDOW_DESTINATION_BASE_CS 26 : 26 +#define DE_WINDOW_DESTINATION_BASE_CS_0 0 +#define DE_WINDOW_DESTINATION_BASE_CS_1 1 +#define DE_WINDOW_DESTINATION_BASE_ADDRESS 25 : 0 + +#define DE_ALPHA 0x000048 +#define DE_ALPHA_VALUE 7 : 0 + +#define DE_WRAP 0x00004C +#define DE_WRAP_X 31 : 16 +#define DE_WRAP_Y 15 : 0 + +#define DE_STATUS 0x000050 +#define DE_STATUS_CSC 1 : 1 +#define DE_STATUS_CSC_CLEAR 0 +#define DE_STATUS_CSC_NOT_ACTIVE 0 +#define DE_STATUS_CSC_ACTIVE 1 +#define DE_STATUS_2D 0 : 0 +#define DE_STATUS_2D_CLEAR 0 +#define DE_STATUS_2D_NOT_ACTIVE 0 +#define DE_STATUS_2D_ACTIVE 1 + +/* Color Space Conversion registers. */ + +#define CSC_Y_SOURCE_BASE 0x0000C8 +#define CSC_Y_SOURCE_BASE_EXT 27 : 27 +#define CSC_Y_SOURCE_BASE_EXT_LOCAL 0 +#define CSC_Y_SOURCE_BASE_EXT_EXTERNAL 1 +#define CSC_Y_SOURCE_BASE_CS 26 : 26 +#define CSC_Y_SOURCE_BASE_CS_0 0 +#define CSC_Y_SOURCE_BASE_CS_1 1 +#define CSC_Y_SOURCE_BASE_ADDRESS 25 : 0 + +#define CSC_CONSTANTS 0x0000CC +#define CSC_CONSTANTS_Y 31 : 24 +#define CSC_CONSTANTS_R 23 : 16 +#define CSC_CONSTANTS_G 15 : 8 +#define CSC_CONSTANTS_B 7 : 0 + +#define CSC_Y_SOURCE_X 0x0000D0 +#define CSC_Y_SOURCE_X_INTEGER 26 : 16 +#define CSC_Y_SOURCE_X_FRACTION 15 : 3 + +#define CSC_Y_SOURCE_Y 0x0000D4 +#define CSC_Y_SOURCE_Y_INTEGER 27 : 16 +#define CSC_Y_SOURCE_Y_FRACTION 15 : 3 + +#define CSC_U_SOURCE_BASE 0x0000D8 +#define CSC_U_SOURCE_BASE_EXT 27 : 27 +#define CSC_U_SOURCE_BASE_EXT_LOCAL 0 +#define CSC_U_SOURCE_BASE_EXT_EXTERNAL 1 +#define CSC_U_SOURCE_BASE_CS 26 : 26 +#define CSC_U_SOURCE_BASE_CS_0 0 +#define CSC_U_SOURCE_BASE_CS_1 1 +#define CSC_U_SOURCE_BASE_ADDRESS 25 : 0 + +#define CSC_V_SOURCE_BASE 0x0000DC +#define CSC_V_SOURCE_BASE_EXT 27 : 27 +#define CSC_V_SOURCE_BASE_EXT_LOCAL 0 +#define CSC_V_SOURCE_BASE_EXT_EXTERNAL 1 +#define CSC_V_SOURCE_BASE_CS 26 : 26 +#define CSC_V_SOURCE_BASE_CS_0 0 +#define CSC_V_SOURCE_BASE_CS_1 1 +#define CSC_V_SOURCE_BASE_ADDRESS 25 : 0 + +#define CSC_SOURCE_DIMENSION 0x0000E0 +#define CSC_SOURCE_DIMENSION_X 31 : 16 +#define CSC_SOURCE_DIMENSION_Y 15 : 0 + +#define CSC_SOURCE_PITCH 0x0000E4 +#define CSC_SOURCE_PITCH_Y 31 : 16 +#define CSC_SOURCE_PITCH_UV 15 : 0 + +#define CSC_DESTINATION 0x0000E8 +#define CSC_DESTINATION_WRAP 31 : 31 +#define CSC_DESTINATION_WRAP_DISABLE 0 +#define CSC_DESTINATION_WRAP_ENABLE 1 +#define CSC_DESTINATION_X 27 : 16 +#define CSC_DESTINATION_Y 11 : 0 + +#define CSC_DESTINATION_DIMENSION 0x0000EC +#define CSC_DESTINATION_DIMENSION_X 31 : 16 +#define CSC_DESTINATION_DIMENSION_Y 15 : 0 + +#define CSC_DESTINATION_PITCH 0x0000F0 +#define CSC_DESTINATION_PITCH_X 31 : 16 +#define CSC_DESTINATION_PITCH_Y 15 : 0 + +#define CSC_SCALE_FACTOR 0x0000F4 +#define CSC_SCALE_FACTOR_HORIZONTAL 31 : 16 +#define CSC_SCALE_FACTOR_VERTICAL 15 : 0 + +#define CSC_DESTINATION_BASE 0x0000F8 +#define CSC_DESTINATION_BASE_EXT 27 : 27 +#define CSC_DESTINATION_BASE_EXT_LOCAL 0 +#define CSC_DESTINATION_BASE_EXT_EXTERNAL 1 +#define CSC_DESTINATION_BASE_CS 26 : 26 +#define CSC_DESTINATION_BASE_CS_0 0 +#define CSC_DESTINATION_BASE_CS_1 1 +#define CSC_DESTINATION_BASE_ADDRESS 25 : 0 + +#define CSC_CONTROL 0x0000FC +#define CSC_CONTROL_STATUS 31 : 31 +#define CSC_CONTROL_STATUS_STOP 0 +#define CSC_CONTROL_STATUS_START 1 +#define CSC_CONTROL_SOURCE_FORMAT 30 : 28 +#define CSC_CONTROL_SOURCE_FORMAT_YUV422 0 +#define CSC_CONTROL_SOURCE_FORMAT_YUV420I 1 +#define CSC_CONTROL_SOURCE_FORMAT_YUV420 2 +#define CSC_CONTROL_SOURCE_FORMAT_YVU9 3 +#define CSC_CONTROL_SOURCE_FORMAT_IYU1 4 +#define CSC_CONTROL_SOURCE_FORMAT_IYU2 5 +#define CSC_CONTROL_SOURCE_FORMAT_RGB565 6 +#define CSC_CONTROL_SOURCE_FORMAT_RGB8888 7 +#define CSC_CONTROL_DESTINATION_FORMAT 27 : 26 +#define CSC_CONTROL_DESTINATION_FORMAT_RGB565 0 +#define CSC_CONTROL_DESTINATION_FORMAT_RGB8888 1 +#define CSC_CONTROL_HORIZONTAL_FILTER 25 : 25 +#define CSC_CONTROL_HORIZONTAL_FILTER_DISABLE 0 +#define CSC_CONTROL_HORIZONTAL_FILTER_ENABLE 1 +#define CSC_CONTROL_VERTICAL_FILTER 24 : 24 +#define CSC_CONTROL_VERTICAL_FILTER_DISABLE 0 +#define CSC_CONTROL_VERTICAL_FILTER_ENABLE 1 +#define CSC_CONTROL_BYTE_ORDER 23 : 23 +#define CSC_CONTROL_BYTE_ORDER_YUYV 0 +#define CSC_CONTROL_BYTE_ORDER_UYVY 1 + +#define DE_DATA_PORT_501 0x110000 +#define DE_DATA_PORT_712 0x400000 +#define DE_DATA_PORT_722 0x6000 + +/* point to virtual Memory Map IO starting address */ +extern char *smtc_RegBaseAddress; +/* point to virtual video memory starting address */ +extern char *smtc_VRAMBaseAddress; +extern unsigned char smtc_de_busy; + +extern unsigned long memRead32(unsigned long nOffset); +extern void memWrite32(unsigned long nOffset, unsigned long nData); +extern unsigned long SMTC_read2Dreg(unsigned long nOffset); + +/* 2D functions */ +extern void deInit(unsigned int nModeWidth, unsigned int nModeHeight, + unsigned int bpp); + +extern void deWaitForNotBusy(void); + +extern void deVerticalLine(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long nX, + unsigned long nY, + unsigned long dst_height, + unsigned long nColor); + +extern void deHorizontalLine(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long nX, + unsigned long nY, + unsigned long dst_width, + unsigned long nColor); + +extern void deLine(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long nX1, + unsigned long nY1, + unsigned long nX2, + unsigned long nY2, + unsigned long nColor); + +extern void deFillRect(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long dst_X, + unsigned long dst_Y, + unsigned long dst_width, + unsigned long dst_height, + unsigned long nColor); + +extern void deRotatePattern(unsigned char *pattern_dstaddr, + unsigned long pattern_src_addr, + unsigned long pattern_BPP, + unsigned long pattern_stride, + int patternX, + int patternY); + +extern void deCopy(unsigned long dst_base, + unsigned long dst_pitch, + unsigned long dst_BPP, + unsigned long dst_X, + unsigned long dst_Y, + unsigned long dst_width, + unsigned long dst_height, + unsigned long src_base, + unsigned long src_pitch, + unsigned long src_X, + unsigned long src_Y, + pTransparent pTransp, + unsigned char nROP2); + +/* + * System memory to Video memory monochrome expansion. + * + * Source is monochrome image in system memory. This function expands the + * monochrome data to color image in video memory. + * + * @pSrcbuf: pointer to start of source buffer in system memory + * @srcDelta: Pitch value (in bytes) of the source buffer, +ive means top + * down and -ive mean button up + * @startBit: Mono data can start at any bit in a byte, this value should + * be 0 to 7 + * @dBase: Address of destination : offset in frame buffer + * @dPitch: Pitch value of destination surface in BYTE + * @bpp: Color depth of destination surface + * @dx, dy: Starting coordinate of destination surface + * @width, height: width and height of rectange in pixel value + * @fColor,bColor: Foreground, Background color (corresponding to a 1, 0 in + * the monochrome data) + * @rop2: ROP value + */ + +extern long deSystemMem2VideoMemMonoBlt( + const char *pSrcbuf, + long srcDelta, + unsigned long startBit, + unsigned long dBase, + unsigned long dPitch, + unsigned long bpp, + unsigned long dx, unsigned long dy, + unsigned long width, unsigned long height, + unsigned long fColor, + unsigned long bColor, + unsigned long rop2); + +extern unsigned long deGetTransparency(void); +extern void deSetPixelFormat(unsigned long bpp); diff --git a/drivers/staging/sm7xx/smtcfb.c b/drivers/staging/sm7xx/smtcfb.c new file mode 100644 index 00000000000..161dbc9c139 --- /dev/null +++ b/drivers/staging/sm7xx/smtcfb.c @@ -0,0 +1,1253 @@ +/* + * Silicon Motion SM7XX frame buffer device + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Authors: Ge Wang, gewang@siliconmotion.com + * Boyod boyod.yang@siliconmotion.com.cn + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + * + * Version 0.10.26192.21.01 + * - Add PowerPC/Big endian support + * - Add 2D support for Lynx + * - Verified on2.6.19.2 Boyod.yang + * + * Version 0.09.2621.00.01 + * - Only support Linux Kernel's version 2.6.21. + * Boyod.yang + * + * Version 0.09 + * - Only support Linux Kernel's version 2.6.12. + * Boyod.yang + */ + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_PM +#include +#endif + +struct screen_info smtc_screen_info; + +#include "smtcfb.h" +#include "smtc2d.h" + +#ifdef DEBUG +#define smdbg(format, arg...) printk(KERN_DEBUG format , ## arg) +#else +#define smdbg(format, arg...) +#endif + +/* +* Private structure +*/ +struct smtcfb_info { + /* + * The following is a pointer to be passed into the + * functions below. The modules outside the main + * voyager.c driver have no knowledge as to what + * is within this structure. + */ + struct fb_info fb; + struct display_switch *dispsw; + struct pci_dev *dev; + signed int currcon; + + struct { + u8 red, green, blue; + } palette[NR_RGB]; + + u_int palette_size; +}; + +struct par_info { + /* + * Hardware + */ + u16 chipID; + unsigned char __iomem *m_pMMIO; + char __iomem *m_pLFB; + char *m_pDPR; + char *m_pVPR; + char *m_pCPR; + + u_int width; + u_int height; + u_int hz; + u_long BaseAddressInVRAM; + u8 chipRevID; +}; + +struct vesa_mode_table { + char mode_index[6]; + u16 lfb_width; + u16 lfb_height; + u16 lfb_depth; +}; + +static struct vesa_mode_table vesa_mode[] = { + {"0x301", 640, 480, 8}, + {"0x303", 800, 600, 8}, + {"0x305", 1024, 768, 8}, + {"0x307", 1280, 1024, 8}, + + {"0x311", 640, 480, 16}, + {"0x314", 800, 600, 16}, + {"0x317", 1024, 768, 16}, + {"0x31A", 1280, 1024, 16}, + + {"0x312", 640, 480, 24}, + {"0x315", 800, 600, 24}, + {"0x318", 1024, 768, 24}, + {"0x31B", 1280, 1024, 24}, +}; + +char __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ +char __iomem *smtc_VRAMBaseAddress; /* video memory starting address */ + +char *smtc_2DBaseAddress; /* 2D engine starting address */ +char *smtc_2Ddataport; /* 2D data port offset */ +short smtc_2Dacceleration; + +static u32 colreg[17]; +static struct par_info hw; /* hardware information */ + +u16 smtc_ChipIDs[] = { + 0x710, + 0x712, + 0x720 +}; + +#define numSMTCchipIDs (sizeof(smtc_ChipIDs) / sizeof(u16)) + +void deWaitForNotBusy(void) +{ + unsigned long i = 0x1000000; + while (i--) { + if ((smtc_seqr(0x16) & 0x18) == 0x10) + break; + } + smtc_de_busy = 0; +} + +static void sm712_set_timing(struct smtcfb_info *sfb, + struct par_info *ppar_info) +{ + int i = 0, j = 0; + u32 m_nScreenStride; + + smdbg("\nppar_info->width = %d ppar_info->height = %d" + "sfb->fb.var.bits_per_pixel = %d ppar_info->hz = %d\n", + ppar_info->width, ppar_info->height, + sfb->fb.var.bits_per_pixel, ppar_info->hz); + + for (j = 0; j < numVGAModes; j++) { + if (VGAMode[j].mmSizeX == ppar_info->width && + VGAMode[j].mmSizeY == ppar_info->height && + VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && + VGAMode[j].hz == ppar_info->hz) { + + smdbg("\nVGAMode[j].mmSizeX = %d VGAMode[j].mmSizeY =" + "%d VGAMode[j].bpp = %d" + "VGAMode[j].hz=%d\n", + VGAMode[j].mmSizeX, VGAMode[j].mmSizeY, + VGAMode[j].bpp, VGAMode[j].hz); + + smdbg("VGAMode index=%d\n", j); + + smtc_mmiowb(0x0, 0x3c6); + + smtc_seqw(0, 0x1); + + smtc_mmiowb(VGAMode[j].Init_MISC, 0x3c2); + + /* init SEQ register SR00 - SR04 */ + for (i = 0; i < SIZE_SR00_SR04; i++) + smtc_seqw(i, VGAMode[j].Init_SR00_SR04[i]); + + /* init SEQ register SR10 - SR24 */ + for (i = 0; i < SIZE_SR10_SR24; i++) + smtc_seqw(i + 0x10, + VGAMode[j].Init_SR10_SR24[i]); + + /* init SEQ register SR30 - SR75 */ + for (i = 0; i < SIZE_SR30_SR75; i++) + if (((i + 0x30) != 0x62) \ + && ((i + 0x30) != 0x6a) \ + && ((i + 0x30) != 0x6b)) + smtc_seqw(i + 0x30, + VGAMode[j].Init_SR30_SR75[i]); + + /* init SEQ register SR80 - SR93 */ + for (i = 0; i < SIZE_SR80_SR93; i++) + smtc_seqw(i + 0x80, + VGAMode[j].Init_SR80_SR93[i]); + + /* init SEQ register SRA0 - SRAF */ + for (i = 0; i < SIZE_SRA0_SRAF; i++) + smtc_seqw(i + 0xa0, + VGAMode[j].Init_SRA0_SRAF[i]); + + /* init Graphic register GR00 - GR08 */ + for (i = 0; i < SIZE_GR00_GR08; i++) + smtc_grphw(i, VGAMode[j].Init_GR00_GR08[i]); + + /* init Attribute register AR00 - AR14 */ + for (i = 0; i < SIZE_AR00_AR14; i++) + smtc_attrw(i, VGAMode[j].Init_AR00_AR14[i]); + + /* init CRTC register CR00 - CR18 */ + for (i = 0; i < SIZE_CR00_CR18; i++) + smtc_crtcw(i, VGAMode[j].Init_CR00_CR18[i]); + + /* init CRTC register CR30 - CR4D */ + for (i = 0; i < SIZE_CR30_CR4D; i++) + smtc_crtcw(i + 0x30, + VGAMode[j].Init_CR30_CR4D[i]); + + /* init CRTC register CR90 - CRA7 */ + for (i = 0; i < SIZE_CR90_CRA7; i++) + smtc_crtcw(i + 0x90, + VGAMode[j].Init_CR90_CRA7[i]); + } + } + smtc_mmiowb(0x67, 0x3c2); + + /* set VPR registers */ + writel(0x0, ppar_info->m_pVPR + 0x0C); + writel(0x0, ppar_info->m_pVPR + 0x40); + + /* set data width */ + m_nScreenStride = + (ppar_info->width * sfb->fb.var.bits_per_pixel) / 64; + switch (sfb->fb.var.bits_per_pixel) { + case 8: + writel(0x0, ppar_info->m_pVPR + 0x0); + break; + case 16: + writel(0x00020000, ppar_info->m_pVPR + 0x0); + break; + case 24: + writel(0x00040000, ppar_info->m_pVPR + 0x0); + break; + case 32: + writel(0x00030000, ppar_info->m_pVPR + 0x0); + break; + } + writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), + ppar_info->m_pVPR + 0x10); + +} + +static void sm712_setpalette(int regno, unsigned red, unsigned green, + unsigned blue, struct fb_info *info) +{ + struct par_info *cur_par = (struct par_info *)info->par; + + if (cur_par->BaseAddressInVRAM) + /* + * second display palette for dual head. Enable CRT RAM, 6-bit + * RAM + */ + smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x20); + else + /* primary display palette. Enable LCD RAM only, 6-bit RAM */ + smtc_seqw(0x66, (smtc_seqr(0x66) & 0xC3) | 0x10); + smtc_mmiowb(regno, dac_reg); + smtc_mmiowb(red >> 10, dac_val); + smtc_mmiowb(green >> 10, dac_val); + smtc_mmiowb(blue >> 10, dac_val); +} + +static void smtc_set_timing(struct smtcfb_info *sfb, struct par_info + *ppar_info) +{ + switch (ppar_info->chipID) { + case 0x710: + case 0x712: + case 0x720: + sm712_set_timing(sfb, ppar_info); + break; + } +} + +static struct fb_var_screeninfo smtcfb_var = { + .xres = 1024, + .yres = 600, + .xres_virtual = 1024, + .yres_virtual = 600, + .bits_per_pixel = 16, + .red = {16, 8, 0}, + .green = {8, 8, 0}, + .blue = {0, 8, 0}, + .activate = FB_ACTIVATE_NOW, + .height = -1, + .width = -1, + .vmode = FB_VMODE_NONINTERLACED, +}; + +static struct fb_fix_screeninfo smtcfb_fix = { + .id = "sm712fb", + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .line_length = 800 * 3, + .accel = FB_ACCEL_SMI_LYNX, +}; + +/* chan_to_field + * + * convert a colour value into a field position + * + * from pxafb.c + */ + +static inline unsigned int chan_to_field(unsigned int chan, + struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int smtcfb_blank(int blank_mode, struct fb_info *info) +{ + /* clear DPMS setting */ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + /* Screen On: HSync: On, VSync : On */ + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) & 0x77)); + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); + smtc_seqw(0x31, (smtc_seqr(0x31) | 0x03)); + break; + case FB_BLANK_NORMAL: + /* Screen Off: HSync: On, VSync : On Soft blank */ + smtc_seqw(0x01, (smtc_seqr(0x01) & (~0x20))); + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x22, (smtc_seqr(0x22) & (~0x30))); + smtc_seqw(0x23, (smtc_seqr(0x23) & (~0xc0))); + smtc_seqw(0x24, (smtc_seqr(0x24) | 0x01)); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + break; + case FB_BLANK_VSYNC_SUSPEND: + /* Screen On: HSync: On, VSync : Off */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x20)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0x20)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + case FB_BLANK_HSYNC_SUSPEND: + /* Screen On: HSync: Off, VSync : On */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x10)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + case FB_BLANK_POWERDOWN: + /* Screen On: HSync: Off, VSync : Off */ + smtc_seqw(0x01, (smtc_seqr(0x01) | 0x20)); + smtc_seqw(0x20, (smtc_seqr(0x20) & (~0xB0))); + smtc_seqw(0x6a, 0x0c); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x21, (smtc_seqr(0x21) | 0x88)); + smtc_seqw(0x22, ((smtc_seqr(0x22) & (~0x30)) | 0x30)); + smtc_seqw(0x23, ((smtc_seqr(0x23) & (~0xc0)) | 0xD8)); + smtc_seqw(0x24, (smtc_seqr(0x24) & (~0x01))); + smtc_seqw(0x31, ((smtc_seqr(0x31) & (~0x07)) | 0x00)); + smtc_seqw(0x34, (smtc_seqr(0x34) | 0x80)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int smtc_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned trans, struct fb_info *info) +{ + struct smtcfb_info *sfb = (struct smtcfb_info *)info; + u32 val; + + if (regno > 255) + return 1; + + switch (sfb->fb.fix.visual) { + case FB_VISUAL_DIRECTCOLOR: + case FB_VISUAL_TRUECOLOR: + /* + * 16/32 bit true-colour, use pseuo-palette for 16 base color + */ + if (regno < 16) { + if (sfb->fb.var.bits_per_pixel == 16) { + u32 *pal = sfb->fb.pseudo_palette; + val = chan_to_field(red, &sfb->fb.var.red); + val |= chan_to_field(green, \ + &sfb->fb.var.green); + val |= chan_to_field(blue, &sfb->fb.var.blue); +#ifdef __BIG_ENDIAN + pal[regno] = + ((red & 0xf800) >> 8) | + ((green & 0xe000) >> 13) | + ((green & 0x1c00) << 3) | + ((blue & 0xf800) >> 3); +#else + pal[regno] = val; +#endif + } else { + u32 *pal = sfb->fb.pseudo_palette; + val = chan_to_field(red, &sfb->fb.var.red); + val |= chan_to_field(green, \ + &sfb->fb.var.green); + val |= chan_to_field(blue, &sfb->fb.var.blue); +#ifdef __BIG_ENDIAN + val = + (val & 0xff00ff00 >> 8) | + (val & 0x00ff00ff << 8); +#endif + pal[regno] = val; + } + } + break; + + case FB_VISUAL_PSEUDOCOLOR: + /* color depth 8 bit */ + sm712_setpalette(regno, red, green, blue, info); + break; + + default: + return 1; /* unknown type */ + } + + return 0; + +} + +#ifdef __BIG_ENDIAN +static ssize_t smtcfb_read(struct fb_info *info, char __user * buf, size_t + count, loff_t *ppos) +{ + unsigned long p = *ppos; + + u32 *buffer, *dst; + u32 __iomem *src; + int c, i, cnt = 0, err = 0; + unsigned long total_size; + + if (!info || !info->screen_base) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p >= total_size) + return 0; + + if (count >= total_size) + count = total_size; + + if (count + p > total_size) + count = total_size - p; + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + src = (u32 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + dst = buffer; + for (i = c >> 2; i--;) { + *dst = fb_readl(src++); + *dst = + (*dst & 0xff00ff00 >> 8) | + (*dst & 0x00ff00ff << 8); + dst++; + } + if (c & 3) { + u8 *dst8 = (u8 *) dst; + u8 __iomem *src8 = (u8 __iomem *) src; + + for (i = c & 3; i--;) { + if (i & 1) { + *dst8++ = fb_readb(++src8); + } else { + *dst8++ = fb_readb(--src8); + src8 += 2; + } + } + src = (u32 __iomem *) src8; + } + + if (copy_to_user(buf, buffer, c)) { + err = -EFAULT; + break; + } + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (err) ? err : cnt; +} + +static ssize_t +smtcfb_write(struct fb_info *info, const char __user *buf, size_t count, + loff_t *ppos) +{ + unsigned long p = *ppos; + + u32 *buffer, *src; + u32 __iomem *dst; + int c, i, cnt = 0, err = 0; + unsigned long total_size; + + if (!info || !info->screen_base) + return -ENODEV; + + if (info->state != FBINFO_STATE_RUNNING) + return -EPERM; + + total_size = info->screen_size; + + if (total_size == 0) + total_size = info->fix.smem_len; + + if (p > total_size) + return -EFBIG; + + if (count > total_size) { + err = -EFBIG; + count = total_size; + } + + if (count + p > total_size) { + if (!err) + err = -ENOSPC; + + count = total_size - p; + } + + buffer = kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count, GFP_KERNEL); + if (!buffer) + return -ENOMEM; + + dst = (u32 __iomem *) (info->screen_base + p); + + if (info->fbops->fb_sync) + info->fbops->fb_sync(info); + + while (count) { + c = (count > PAGE_SIZE) ? PAGE_SIZE : count; + src = buffer; + + if (copy_from_user(src, buf, c)) { + err = -EFAULT; + break; + } + + for (i = c >> 2; i--;) { + fb_writel((*src & 0xff00ff00 >> 8) | + (*src & 0x00ff00ff << 8), dst++); + src++; + } + if (c & 3) { + u8 *src8 = (u8 *) src; + u8 __iomem *dst8 = (u8 __iomem *) dst; + + for (i = c & 3; i--;) { + if (i & 1) { + fb_writeb(*src8++, ++dst8); + } else { + fb_writeb(*src8++, --dst8); + dst8 += 2; + } + } + dst = (u32 __iomem *) dst8; + } + + *ppos += c; + buf += c; + cnt += c; + count -= c; + } + + kfree(buffer); + + return (cnt) ? cnt : err; +} +#endif /* ! __BIG_ENDIAN */ + +#include "smtc2d.c" + +void smtcfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct par_info *p = (struct par_info *)info->par; + + if (smtc_2Dacceleration) { + if (!area->width || !area->height) + return; + + deCopy(p->BaseAddressInVRAM, 0, info->var.bits_per_pixel, + area->dx, area->dy, area->width, area->height, + p->BaseAddressInVRAM, 0, area->sx, area->sy, 0, 0xC); + + } else + cfb_copyarea(info, area); +} + +void smtcfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) +{ + struct par_info *p = (struct par_info *)info->par; + + if (smtc_2Dacceleration) { + if (!rect->width || !rect->height) + return; + if (info->var.bits_per_pixel >= 24) + deFillRect(p->BaseAddressInVRAM, 0, rect->dx * 3, + rect->dy * 3, rect->width * 3, rect->height, + rect->color); + else + deFillRect(p->BaseAddressInVRAM, 0, rect->dx, rect->dy, + rect->width, rect->height, rect->color); + } else + cfb_fillrect(info, rect); +} + +void smtcfb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct par_info *p = (struct par_info *)info->par; + u32 bg_col = 0, fg_col = 0; + + if ((smtc_2Dacceleration) && (image->depth == 1)) { + if (smtc_de_busy) + deWaitForNotBusy(); + + switch (info->var.bits_per_pixel) { + case 8: + bg_col = image->bg_color; + fg_col = image->fg_color; + break; + case 16: + bg_col = + ((u32 *) (info->pseudo_palette))[image->bg_color]; + fg_col = + ((u32 *) (info->pseudo_palette))[image->fg_color]; + break; + case 32: + bg_col = + ((u32 *) (info->pseudo_palette))[image->bg_color]; + fg_col = + ((u32 *) (info->pseudo_palette))[image->fg_color]; + break; + } + + deSystemMem2VideoMemMonoBlt( + image->data, + image->width / 8, + 0, + p->BaseAddressInVRAM, + 0, + 0, + image->dx, image->dy, + image->width, image->height, + fg_col, bg_col, + 0x0C); + + } else + cfb_imageblit(info, image); +} + +static struct fb_ops smtcfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = smtc_setcolreg, + .fb_blank = smtcfb_blank, + .fb_fillrect = smtcfb_fillrect, + .fb_imageblit = smtcfb_imageblit, + .fb_copyarea = smtcfb_copyarea, +#ifdef __BIG_ENDIAN + .fb_read = smtcfb_read, + .fb_write = smtcfb_write, +#endif + +}; + +void smtcfb_setmode(struct smtcfb_info *sfb) +{ + switch (sfb->fb.var.bits_per_pixel) { + case 32: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 4; + sfb->fb.var.red.length = 8; + sfb->fb.var.green.length = 8; + sfb->fb.var.blue.length = 8; + sfb->fb.var.red.offset = 16; + sfb->fb.var.green.offset = 8; + sfb->fb.var.blue.offset = 0; + + break; + case 8: + sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres; + sfb->fb.var.red.offset = 5; + sfb->fb.var.red.length = 3; + sfb->fb.var.green.offset = 2; + sfb->fb.var.green.length = 3; + sfb->fb.var.blue.offset = 0; + sfb->fb.var.blue.length = 2; + break; + case 24: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 3; + sfb->fb.var.red.length = 8; + sfb->fb.var.green.length = 8; + sfb->fb.var.blue.length = 8; + + sfb->fb.var.red.offset = 16; + sfb->fb.var.green.offset = 8; + sfb->fb.var.blue.offset = 0; + + break; + case 16: + default: + sfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + sfb->fb.fix.line_length = sfb->fb.var.xres * 2; + + sfb->fb.var.red.length = 5; + sfb->fb.var.green.length = 6; + sfb->fb.var.blue.length = 5; + + sfb->fb.var.red.offset = 11; + sfb->fb.var.green.offset = 5; + sfb->fb.var.blue.offset = 0; + + break; + } + + hw.width = sfb->fb.var.xres; + hw.height = sfb->fb.var.yres; + hw.hz = 60; + smtc_set_timing(sfb, &hw); + if (smtc_2Dacceleration) { + printk("2D acceleration enabled!\n"); + /* Init smtc drawing engine */ + deInit(sfb->fb.var.xres, sfb->fb.var.yres, + sfb->fb.var.bits_per_pixel); + } +} + +/* + * Alloc struct smtcfb_info and assign the default value + */ +static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *dev, + char *name) +{ + struct smtcfb_info *sfb; + + sfb = kmalloc(sizeof(struct smtcfb_info), GFP_KERNEL); + + if (!sfb) + return NULL; + + memset(sfb, 0, sizeof(struct smtcfb_info)); + + sfb->currcon = -1; + sfb->dev = dev; + + /*** Init sfb->fb with default value ***/ + sfb->fb.flags = FBINFO_FLAG_DEFAULT; + sfb->fb.fbops = &smtcfb_ops; + sfb->fb.var = smtcfb_var; + sfb->fb.fix = smtcfb_fix; + + strcpy(sfb->fb.fix.id, name); + + sfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + sfb->fb.fix.type_aux = 0; + sfb->fb.fix.xpanstep = 0; + sfb->fb.fix.ypanstep = 0; + sfb->fb.fix.ywrapstep = 0; + sfb->fb.fix.accel = FB_ACCEL_SMI_LYNX; + + sfb->fb.var.nonstd = 0; + sfb->fb.var.activate = FB_ACTIVATE_NOW; + sfb->fb.var.height = -1; + sfb->fb.var.width = -1; + /* text mode acceleration */ + sfb->fb.var.accel_flags = FB_ACCELF_TEXT; + sfb->fb.var.vmode = FB_VMODE_NONINTERLACED; + sfb->fb.par = &hw; + sfb->fb.pseudo_palette = colreg; + + return sfb; +} + +/* + * Unmap in the memory mapped IO registers + */ + +static void smtc_unmap_mmio(struct smtcfb_info *sfb) +{ + if (sfb && smtc_RegBaseAddress) + smtc_RegBaseAddress = NULL; +} + +/* + * Map in the screen memory + */ + +static int smtc_map_smem(struct smtcfb_info *sfb, + struct pci_dev *dev, u_long smem_len) +{ + if (sfb->fb.var.bits_per_pixel == 32) { +#ifdef __BIG_ENDIAN + sfb->fb.fix.smem_start = pci_resource_start(dev, 0) + + 0x800000; +#else + sfb->fb.fix.smem_start = pci_resource_start(dev, 0); +#endif + } else { + sfb->fb.fix.smem_start = pci_resource_start(dev, 0); + } + + sfb->fb.fix.smem_len = smem_len; + + sfb->fb.screen_base = smtc_VRAMBaseAddress; + + if (!sfb->fb.screen_base) { + printk(KERN_INFO "%s: unable to map screen memory\n", + sfb->fb.fix.id); + return -ENOMEM; + } + + return 0; +} + +/* + * Unmap in the screen memory + * + */ +static void smtc_unmap_smem(struct smtcfb_info *sfb) +{ + if (sfb && sfb->fb.screen_base) { + iounmap(sfb->fb.screen_base); + sfb->fb.screen_base = NULL; + } +} + +/* + * We need to wake up the LynxEM+, and make sure its in linear memory mode. + */ +static inline void sm7xx_init_hw(void) +{ + outb_p(0x18, 0x3c4); + outb_p(0x11, 0x3c5); +} + +static void smtc_free_fb_info(struct smtcfb_info *sfb) +{ + if (sfb) { + fb_alloc_cmap(&sfb->fb.cmap, 0, 0); + kfree(sfb); + } +} + +/* + * sm712vga_setup - process command line options, get vga parameter + * @options: string of options + * Returns zero. + * + */ +static int __init __maybe_unused sm712vga_setup(char *options) +{ + int index; + + if (!options || !*options) { + smdbg("\n No vga parameter\n"); + return -EINVAL; + } + + smtc_screen_info.lfb_width = 0; + smtc_screen_info.lfb_height = 0; + smtc_screen_info.lfb_depth = 0; + + smdbg("\nsm712vga_setup = %s\n", options); + + for (index = 0; + index < (sizeof(vesa_mode) / sizeof(struct vesa_mode_table)); + index++) { + if (strstr(options, vesa_mode[index].mode_index)) { + smtc_screen_info.lfb_width = vesa_mode[index].lfb_width; + smtc_screen_info.lfb_height = + vesa_mode[index].lfb_height; + smtc_screen_info.lfb_depth = vesa_mode[index].lfb_depth; + return 0; + } + } + + return -1; +} +__setup("vga=", sm712vga_setup); + +/* Jason (08/13/2009) + * Original init function changed to probe method to be used by pci_drv + * process used to detect chips replaced with kernel process in pci_drv + */ +static int __init smtcfb_pci_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct smtcfb_info *sfb; + u_long smem_size = 0x00800000; /* default 8MB */ + char name[16]; + int err; + unsigned long pFramebufferPhysical; + + printk(KERN_INFO + "Silicon Motion display driver " SMTC_LINUX_FB_VERSION "\n"); + + err = pci_enable_device(pdev); /* enable SMTC chip */ + + if (err) + return err; + err = -ENOMEM; + + hw.chipID = ent->device; + sprintf(name, "sm%Xfb", hw.chipID); + + sfb = smtc_alloc_fb_info(pdev, name); + + if (!sfb) + goto failed; + /* Jason (08/13/2009) + * Store fb_info to be further used when suspending and resuming + */ + pci_set_drvdata(pdev, sfb); + + sm7xx_init_hw(); + + /*get mode parameter from smtc_screen_info */ + if (smtc_screen_info.lfb_width != 0) { + sfb->fb.var.xres = smtc_screen_info.lfb_width; + sfb->fb.var.yres = smtc_screen_info.lfb_height; + sfb->fb.var.bits_per_pixel = smtc_screen_info.lfb_depth; + } else { + /* default resolution 1024x600 16bit mode */ + sfb->fb.var.xres = SCREEN_X_RES; + sfb->fb.var.yres = SCREEN_Y_RES; + sfb->fb.var.bits_per_pixel = SCREEN_BPP; + } + +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 24) + sfb->fb.var.bits_per_pixel = (smtc_screen_info.lfb_depth = 32); +#endif + /* Map address and memory detection */ + pFramebufferPhysical = pci_resource_start(pdev, 0); + pci_read_config_byte(pdev, PCI_REVISION_ID, &hw.chipRevID); + + switch (hw.chipID) { + case 0x710: + case 0x712: + sfb->fb.fix.mmio_start = pFramebufferPhysical + 0x00400000; + sfb->fb.fix.mmio_len = 0x00400000; + smem_size = SM712_VIDEOMEMORYSIZE; +#ifdef __BIG_ENDIAN + hw.m_pLFB = (smtc_VRAMBaseAddress = + ioremap(pFramebufferPhysical, 0x00c00000)); +#else + hw.m_pLFB = (smtc_VRAMBaseAddress = + ioremap(pFramebufferPhysical, 0x00800000)); +#endif + hw.m_pMMIO = (smtc_RegBaseAddress = + smtc_VRAMBaseAddress + 0x00700000); + smtc_2DBaseAddress = (hw.m_pDPR = + smtc_VRAMBaseAddress + 0x00408000); + smtc_2Ddataport = smtc_VRAMBaseAddress + DE_DATA_PORT_712; + hw.m_pVPR = hw.m_pLFB + 0x0040c000; +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) { + smtc_VRAMBaseAddress += 0x800000; + hw.m_pLFB += 0x800000; + printk(KERN_INFO + "\nsmtc_VRAMBaseAddress=%p hw.m_pLFB=%p\n", + smtc_VRAMBaseAddress, hw.m_pLFB); + } +#endif + if (!smtc_RegBaseAddress) { + printk(KERN_INFO + "%s: unable to map memory mapped IO\n", + sfb->fb.fix.id); + return -ENOMEM; + } + + /* set MCLK = 14.31818 * (0x16 / 0x2) */ + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x62, 0x3e); + /* enable PCI burst */ + smtc_seqw(0x17, 0x20); + /* enable word swap */ +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + smtc_seqw(0x17, 0x30); +#endif +#ifdef CONFIG_FB_SM7XX_ACCEL + smtc_2Dacceleration = 1; +#endif + break; + case 0x720: + sfb->fb.fix.mmio_start = pFramebufferPhysical; + sfb->fb.fix.mmio_len = 0x00200000; + smem_size = SM722_VIDEOMEMORYSIZE; + smtc_2DBaseAddress = (hw.m_pDPR = + ioremap(pFramebufferPhysical, 0x00a00000)); + hw.m_pLFB = (smtc_VRAMBaseAddress = + smtc_2DBaseAddress + 0x00200000); + hw.m_pMMIO = (smtc_RegBaseAddress = + smtc_2DBaseAddress + 0x000c0000); + smtc_2Ddataport = smtc_2DBaseAddress + DE_DATA_PORT_722; + hw.m_pVPR = smtc_2DBaseAddress + 0x800; + + smtc_seqw(0x62, 0xff); + smtc_seqw(0x6a, 0x0d); + smtc_seqw(0x6b, 0x02); + smtc_2Dacceleration = 0; + break; + default: + printk(KERN_INFO + "No valid Silicon Motion display chip was detected!\n"); + + smtc_free_fb_info(sfb); + return err; + } + + /* can support 32 bpp */ + if (15 == sfb->fb.var.bits_per_pixel) + sfb->fb.var.bits_per_pixel = 16; + + sfb->fb.var.xres_virtual = sfb->fb.var.xres; + sfb->fb.var.yres_virtual = sfb->fb.var.yres; + err = smtc_map_smem(sfb, pdev, smem_size); + if (err) + goto failed; + + smtcfb_setmode(sfb); + /* Primary display starting from 0 postion */ + hw.BaseAddressInVRAM = 0; + sfb->fb.par = &hw; + + err = register_framebuffer(&sfb->fb); + if (err < 0) + goto failed; + + printk(KERN_INFO "Silicon Motion SM%X Rev%X primary display mode" + "%dx%d-%d Init Complete.\n", hw.chipID, hw.chipRevID, + sfb->fb.var.xres, sfb->fb.var.yres, + sfb->fb.var.bits_per_pixel); + + return 0; + + failed: + printk(KERN_INFO "Silicon Motion, Inc. primary display init fail\n"); + + smtc_unmap_smem(sfb); + smtc_unmap_mmio(sfb); + smtc_free_fb_info(sfb); + + return err; +} + + +/* Jason (08/11/2009) PCI_DRV wrapper essential structs */ +static struct pci_device_id smtcfb_pci_table[] = { + {0x126f, 0x710, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x126f, 0x712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x126f, 0x720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} +}; + + +/* Jason (08/14/2009) + * do some clean up when the driver module is removed + */ +static void __devexit smtcfb_pci_remove(struct pci_dev *pdev) +{ + struct smtcfb_info *sfb; + + sfb = pci_get_drvdata(pdev); + pci_set_drvdata(pdev, NULL); + smtc_unmap_smem(sfb); + smtc_unmap_mmio(sfb); + unregister_framebuffer(&sfb->fb); + smtc_free_fb_info(sfb); +} + +/* Jason (08/14/2009) + * suspend function, called when the suspend event is triggered + */ +static int __maybe_unused smtcfb_suspend(struct pci_dev *pdev, pm_message_t msg) +{ + struct smtcfb_info *sfb; + int retv; + + sfb = pci_get_drvdata(pdev); + + /* set the hw in sleep mode use externel clock and self memory refresh + * so that we can turn off internal PLLs later on + */ + smtc_seqw(0x20, (smtc_seqr(0x20) | 0xc0)); + smtc_seqw(0x69, (smtc_seqr(0x69) & 0xf7)); + + switch (msg.event) { + case PM_EVENT_FREEZE: + case PM_EVENT_PRETHAW: + pdev->dev.power.power_state = msg; + return 0; + } + + /* when doing suspend, call fb apis and pci apis */ + if (msg.event == PM_EVENT_SUSPEND) { + acquire_console_sem(); + fb_set_suspend(&sfb->fb, 1); + release_console_sem(); + retv = pci_save_state(pdev); + pci_disable_device(pdev); + retv = pci_choose_state(pdev, msg); + retv = pci_set_power_state(pdev, retv); + } + + pdev->dev.power.power_state = msg; + + /* additionaly turn off all function blocks including internal PLLs */ + smtc_seqw(0x21, 0xff); + + return 0; +} + +static int __maybe_unused smtcfb_resume(struct pci_dev *pdev) +{ + struct smtcfb_info *sfb; + int retv; + + sfb = pci_get_drvdata(pdev); + + /* when resuming, restore pci data and fb cursor */ + if (pdev->dev.power.power_state.event != PM_EVENT_FREEZE) { + retv = pci_set_power_state(pdev, PCI_D0); + retv = pci_restore_state(pdev); + if (pci_enable_device(pdev)) + return -1; + pci_set_master(pdev); + } + + /* reinit hardware */ + sm7xx_init_hw(); + switch (hw.chipID) { + case 0x710: + case 0x712: + /* set MCLK = 14.31818 * (0x16 / 0x2) */ + smtc_seqw(0x6a, 0x16); + smtc_seqw(0x6b, 0x02); + smtc_seqw(0x62, 0x3e); + /* enable PCI burst */ + smtc_seqw(0x17, 0x20); +#ifdef __BIG_ENDIAN + if (sfb->fb.var.bits_per_pixel == 32) + smtc_seqw(0x17, 0x30); +#endif + break; + case 0x720: + smtc_seqw(0x62, 0xff); + smtc_seqw(0x6a, 0x0d); + smtc_seqw(0x6b, 0x02); + break; + } + + smtc_seqw(0x34, (smtc_seqr(0x34) | 0xc0)); + smtc_seqw(0x33, ((smtc_seqr(0x33) | 0x08) & 0xfb)); + + smtcfb_setmode(sfb); + + acquire_console_sem(); + fb_set_suspend(&sfb->fb, 0); + release_console_sem(); + + return 0; +} + +/* Jason (08/13/2009) + * pci_driver struct used to wrap the original driver + * so that it can be registered into the kernel and + * the proper method would be called when suspending and resuming + */ +static struct pci_driver smtcfb_driver = { + .name = "smtcfb", + .id_table = smtcfb_pci_table, + .probe = smtcfb_pci_probe, + .remove = __devexit_p(smtcfb_pci_remove), +#ifdef CONFIG_PM + .suspend = smtcfb_suspend, + .resume = smtcfb_resume, +#endif +}; + +static int __init smtcfb_init(void) +{ + return pci_register_driver(&smtcfb_driver); +} + +static void __exit smtcfb_exit(void) +{ + pci_unregister_driver(&smtcfb_driver); +} + +module_init(smtcfb_init); +module_exit(smtcfb_exit); + +MODULE_AUTHOR("Siliconmotion "); +MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/staging/sm7xx/smtcfb.h b/drivers/staging/sm7xx/smtcfb.h new file mode 100644 index 00000000000..7f2c3413821 --- /dev/null +++ b/drivers/staging/sm7xx/smtcfb.h @@ -0,0 +1,793 @@ +/* + * Silicon Motion SM712 frame buffer device + * + * Copyright (C) 2006 Silicon Motion Technology Corp. + * Authors: Ge Wang, gewang@siliconmotion.com + * Boyod boyod.yang@siliconmotion.com.cn + * + * Copyright (C) 2009 Lemote, Inc. + * Author: Wu Zhangjin, wuzj@lemote.com + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ + +#define SMTC_LINUX_FB_VERSION "version 0.11.2619.21.01 July 27, 2008" + +#define NR_PALETTE 256 +#define NR_RGB 2 + +#define FB_ACCEL_SMI_LYNX 88 + +#ifdef __BIG_ENDIAN +#define PC_VGA 0 +#else +#define PC_VGA 1 +#endif + +#define SCREEN_X_RES 1024 +#define SCREEN_Y_RES 600 +#define SCREEN_BPP 16 + +#ifndef FIELD_OFFSET +#define FIELD_OFSFET(type, field) \ + ((unsigned long) (PUCHAR) & (((type *)0)->field)) +#endif + +/*Assume SM712 graphics chip has 4MB VRAM */ +#define SM712_VIDEOMEMORYSIZE 0x00400000 +/*Assume SM722 graphics chip has 8MB VRAM */ +#define SM722_VIDEOMEMORYSIZE 0x00800000 + +#define dac_reg (0x3c8) +#define dac_val (0x3c9) + +extern char *smtc_RegBaseAddress; +#define smtc_mmiowb(dat, reg) writeb(dat, smtc_RegBaseAddress + reg) +#define smtc_mmioww(dat, reg) writew(dat, smtc_RegBaseAddress + reg) +#define smtc_mmiowl(dat, reg) writel(dat, smtc_RegBaseAddress + reg) + +#define smtc_mmiorb(reg) readb(smtc_RegBaseAddress + reg) +#define smtc_mmiorw(reg) readw(smtc_RegBaseAddress + reg) +#define smtc_mmiorl(reg) readl(smtc_RegBaseAddress + reg) + +#define SIZE_SR00_SR04 (0x04 - 0x00 + 1) +#define SIZE_SR10_SR24 (0x24 - 0x10 + 1) +#define SIZE_SR30_SR75 (0x75 - 0x30 + 1) +#define SIZE_SR80_SR93 (0x93 - 0x80 + 1) +#define SIZE_SRA0_SRAF (0xAF - 0xA0 + 1) +#define SIZE_GR00_GR08 (0x08 - 0x00 + 1) +#define SIZE_AR00_AR14 (0x14 - 0x00 + 1) +#define SIZE_CR00_CR18 (0x18 - 0x00 + 1) +#define SIZE_CR30_CR4D (0x4D - 0x30 + 1) +#define SIZE_CR90_CRA7 (0xA7 - 0x90 + 1) +#define SIZE_VPR (0x6C + 1) +#define SIZE_DPR (0x44 + 1) + +static inline void smtc_crtcw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3d4); + smtc_mmiowb(val, 0x3d5); +} + +static inline unsigned int smtc_crtcr(int reg) +{ + smtc_mmiowb(reg, 0x3d4); + return smtc_mmiorb(0x3d5); +} + +static inline void smtc_grphw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3ce); + smtc_mmiowb(val, 0x3cf); +} + +static inline unsigned int smtc_grphr(int reg) +{ + smtc_mmiowb(reg, 0x3ce); + return smtc_mmiorb(0x3cf); +} + +static inline void smtc_attrw(int reg, int val) +{ + smtc_mmiorb(0x3da); + smtc_mmiowb(reg, 0x3c0); + smtc_mmiorb(0x3c1); + smtc_mmiowb(val, 0x3c0); +} + +static inline void smtc_seqw(int reg, int val) +{ + smtc_mmiowb(reg, 0x3c4); + smtc_mmiowb(val, 0x3c5); +} + +static inline unsigned int smtc_seqr(int reg) +{ + smtc_mmiowb(reg, 0x3c4); + return smtc_mmiorb(0x3c5); +} + +/* The next structure holds all information relevant for a specific video mode. + */ + +struct ModeInit { + int mmSizeX; + int mmSizeY; + int bpp; + int hz; + unsigned char Init_MISC; + unsigned char Init_SR00_SR04[SIZE_SR00_SR04]; + unsigned char Init_SR10_SR24[SIZE_SR10_SR24]; + unsigned char Init_SR30_SR75[SIZE_SR30_SR75]; + unsigned char Init_SR80_SR93[SIZE_SR80_SR93]; + unsigned char Init_SRA0_SRAF[SIZE_SRA0_SRAF]; + unsigned char Init_GR00_GR08[SIZE_GR00_GR08]; + unsigned char Init_AR00_AR14[SIZE_AR00_AR14]; + unsigned char Init_CR00_CR18[SIZE_CR00_CR18]; + unsigned char Init_CR30_CR4D[SIZE_CR30_CR4D]; + unsigned char Init_CR90_CRA7[SIZE_CR90_CRA7]; +}; + +/********************************************************************** + SM712 Mode table. + **********************************************************************/ +struct ModeInit VGAMode[] = { + { + /* mode#0: 640 x 480 16Bpp 60Hz */ + 640, 480, 16, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + { + /* mode#1: 640 x 480 24Bpp 60Hz */ + 640, 480, 24, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + { + /* mode#0: 640 x 480 32Bpp 60Hz */ + 640, 480, 32, 60, + /* Init_MISC */ + 0xE3, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEF, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x32, 0x03, 0xA0, 0x09, 0xC0, 0x32, 0x32, 0x32, + 0x32, 0x32, 0x32, 0x32, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x32, 0x32, 0x32, + 0x04, 0x24, 0x63, 0x4F, 0x52, 0x0B, 0xDF, 0xEA, + 0x04, 0x50, 0x19, 0x32, 0x32, 0x00, 0x00, 0x32, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x07, 0x82, 0x07, 0x04, + 0x00, 0x45, 0x30, 0x30, 0x40, 0x30, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x32, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x32, 0x32, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xFF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x5F, 0x4F, 0x4F, 0x00, 0x53, 0x1F, 0x0B, 0x3E, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x0C, 0xDF, 0x50, 0x40, 0xDF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xFF, 0xFD, + 0x5F, 0x4F, 0x00, 0x54, 0x00, 0x0B, 0xDF, 0x00, + 0xEA, 0x0C, 0x2E, 0x00, 0x4F, 0xDF, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0xDD, 0x5E, 0xEA, 0x87, 0x44, 0x8F, 0x55, + 0x0A, 0x8F, 0x55, 0x0A, 0x00, 0x00, 0x18, 0x00, + 0x11, 0x10, 0x0B, 0x0A, 0x0A, 0x0A, 0x0A, 0x00, + }, + }, + + { /* mode#2: 800 x 600 16Bpp 60Hz */ + 800, 600, 16, 60, + /* Init_MISC */ + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + { /* mode#3: 800 x 600 24Bpp 60Hz */ + 800, 600, 24, 60, + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x36, 0x03, 0x20, 0x09, 0xC0, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x36, 0x36, 0x36, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x36, 0x36, 0x00, 0x00, 0x36, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x36, + 0xF7, 0x00, 0x00, 0x00, 0xEF, 0xFF, 0x36, 0x36, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + { /* mode#7: 800 x 600 32Bpp 60Hz */ + 800, 600, 32, 60, + /* Init_MISC */ + 0x2B, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xFF, 0xBE, 0xEE, 0xFF, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x34, 0x03, 0x20, 0x09, 0xC0, 0x24, 0x24, 0x24, + 0x24, 0x24, 0x24, 0x24, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x38, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x24, 0x24, 0x24, + 0x04, 0x48, 0x83, 0x63, 0x68, 0x72, 0x57, 0x58, + 0x04, 0x55, 0x59, 0x24, 0x24, 0x00, 0x00, 0x24, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x1C, 0x85, 0x35, 0x13, + 0x02, 0x45, 0x30, 0x35, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0x00, 0x00, 0x00, 0x6F, 0x7F, 0x7F, 0xFF, 0x24, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x24, 0x24, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFF, 0xBF, 0xFF, 0xFF, 0xED, 0xED, 0xED, + 0x7B, 0xFF, 0xFF, 0xFF, 0xBF, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0x7F, 0x63, 0x63, 0x00, 0x68, 0x18, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x0C, 0x57, 0x64, 0x40, 0x57, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x03, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xE7, 0xBF, 0xFD, + 0x7F, 0x63, 0x00, 0x69, 0x18, 0x72, 0x57, 0x00, + 0x58, 0x0C, 0xE0, 0x20, 0x63, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x56, 0x4B, 0x5E, 0x55, 0x86, 0x9D, 0x8E, 0xAA, + 0xDB, 0x2A, 0xDF, 0x33, 0x00, 0x00, 0x18, 0x00, + 0x20, 0x1F, 0x1A, 0x19, 0x0F, 0x0F, 0x0F, 0x00, + }, + }, + /* We use 1024x768 table to light 1024x600 panel for lemote */ + { /* mode#4: 1024 x 600 16Bpp 60Hz */ + 1024, 600, 16, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xC8, 0x40, 0x14, 0x60, 0x00, 0x0A, 0x17, 0x20, + 0x51, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x00, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x22, 0x03, 0x24, 0x09, 0xC0, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x22, 0x22, 0x22, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x22, 0x22, 0x00, 0x00, 0x22, + 0x01, 0x80, 0x7A, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x16, 0x02, 0x0D, 0x82, 0x09, 0x02, + 0x04, 0x45, 0x3F, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x82, 0x0b, 0x6f, 0x57, 0x00, + 0x5c, 0x0f, 0xE0, 0xe0, 0x7F, 0x57, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#5: 1024 x 768 24Bpp 60Hz */ + 1024, 768, 24, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x30, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#4: 1024 x 768 32Bpp 60Hz */ + 1024, 768, 32, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x3B, 0x0D, 0x09, 0x02, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0xA3, 0x7F, 0x00, 0x86, 0x15, 0x24, 0xFF, 0x00, + 0x01, 0x07, 0xE5, 0x20, 0x7F, 0xFF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + { /* mode#6: 320 x 240 16Bpp 60Hz */ + 320, 240, 16, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, + + { /* mode#8: 320 x 240 32Bpp 60Hz */ + 320, 240, 32, 60, + /* Init_MISC */ + 0xEB, + { /* Init_SR0_SR4 */ + 0x03, 0x01, 0x0F, 0x03, 0x0E, + }, + { /* Init_SR10_SR24 */ + 0xF3, 0xB6, 0xC0, 0xDD, 0x00, 0x0E, 0x17, 0x2C, + 0x99, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC4, 0x32, 0x02, 0x01, 0x01, + }, + { /* Init_SR30_SR75 */ + 0x38, 0x03, 0x20, 0x09, 0xC0, 0x3A, 0x3A, 0x3A, + 0x3A, 0x3A, 0x3A, 0x3A, 0x00, 0x00, 0x03, 0xFF, + 0x00, 0xFC, 0x00, 0x00, 0x20, 0x18, 0x00, 0xFC, + 0x20, 0x0C, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3A, + 0x06, 0x68, 0xA7, 0x7F, 0x83, 0x24, 0xFF, 0x03, + 0x00, 0x60, 0x59, 0x3A, 0x3A, 0x00, 0x00, 0x3A, + 0x01, 0x80, 0x7E, 0x1A, 0x1A, 0x00, 0x00, 0x00, + 0x50, 0x03, 0x74, 0x14, 0x08, 0x43, 0x08, 0x43, + 0x04, 0x45, 0x30, 0x30, 0x40, 0x20, + }, + { /* Init_SR80_SR93 */ + 0xFF, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3A, + 0xF7, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x3A, 0x3A, + 0x00, 0x00, 0x00, 0x00, + }, + { /* Init_SRA0_SRAF */ + 0x00, 0xFB, 0x9F, 0x01, 0x00, 0xED, 0xED, 0xED, + 0x7B, 0xFB, 0xFF, 0xFF, 0x97, 0xEF, 0xBF, 0xDF, + }, + { /* Init_GR00_GR08 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, + 0xFF, + }, + { /* Init_AR00_AR14 */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00, + }, + { /* Init_CR00_CR18 */ + 0xA3, 0x7F, 0x7F, 0x00, 0x85, 0x16, 0x24, 0xF5, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0x09, 0xFF, 0x80, 0x40, 0xFF, 0x00, 0xE3, + 0xFF, + }, + { /* Init_CR30_CR4D */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x20, + 0x00, 0x00, 0x30, 0x40, 0x00, 0xFF, 0xBF, 0xFF, + 0x2E, 0x27, 0x00, 0x2b, 0x0c, 0x0F, 0xEF, 0x00, + 0xFe, 0x0f, 0x01, 0xC0, 0x27, 0xEF, + }, + { /* Init_CR90_CRA7 */ + 0x55, 0xD9, 0x5D, 0xE1, 0x86, 0x1B, 0x8E, 0x26, + 0xDA, 0x8D, 0xDE, 0x94, 0x00, 0x00, 0x18, 0x00, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x15, 0x03, + }, + }, +}; + +#define numVGAModes (sizeof(VGAMode) / sizeof(struct ModeInit)) -- cgit v1.2.3-70-g09d2 From 29d249ed80c80b479df78e456e6809223c648505 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 18 Dec 2009 09:59:48 -0800 Subject: Staging: dst: remove from the tree DST is dead, no one is using it and upstream has abandoned it, so remove it from the tree because it is not going anywhere. Acked-by: Evgeniy Polyakov Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/dst/Kconfig | 67 --- drivers/staging/dst/Makefile | 3 - drivers/staging/dst/crypto.c | 733 ----------------------------- drivers/staging/dst/dcore.c | 968 -------------------------------------- drivers/staging/dst/export.c | 660 -------------------------- drivers/staging/dst/state.c | 844 --------------------------------- drivers/staging/dst/thread_pool.c | 348 -------------- drivers/staging/dst/trans.c | 337 ------------- include/linux/dst.h | 587 ----------------------- 11 files changed, 4550 deletions(-) delete mode 100644 drivers/staging/dst/Kconfig delete mode 100644 drivers/staging/dst/Makefile delete mode 100644 drivers/staging/dst/crypto.c delete mode 100644 drivers/staging/dst/dcore.c delete mode 100644 drivers/staging/dst/export.c delete mode 100644 drivers/staging/dst/state.c delete mode 100644 drivers/staging/dst/thread_pool.c delete mode 100644 drivers/staging/dst/trans.c delete mode 100644 include/linux/dst.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index db0de940949..94eb86319ff 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -87,8 +87,6 @@ source "drivers/staging/frontier/Kconfig" source "drivers/staging/dream/Kconfig" -source "drivers/staging/dst/Kconfig" - source "drivers/staging/pohmelfs/Kconfig" source "drivers/staging/b3dfg/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 73c6a71155e..b5e67b889f6 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_RTL8192E) += rtl8192e/ obj-$(CONFIG_INPUT_MIMIO) += mimio/ obj-$(CONFIG_TRANZPORT) += frontier/ obj-$(CONFIG_DREAM) += dream/ -obj-$(CONFIG_DST) += dst/ obj-$(CONFIG_POHMELFS) += pohmelfs/ obj-$(CONFIG_B3DFG) += b3dfg/ obj-$(CONFIG_IDE_PHISON) += phison/ diff --git a/drivers/staging/dst/Kconfig b/drivers/staging/dst/Kconfig deleted file mode 100644 index 448d342ac2a..00000000000 --- a/drivers/staging/dst/Kconfig +++ /dev/null @@ -1,67 +0,0 @@ -config DST - tristate "Distributed storage" - depends on NET && CRYPTO && SYSFS && BLK_DEV - select CONNECTOR - ---help--- - DST is a network block device storage, which can be used to organize - exported storage on the remote nodes into the local block device. - - DST works on top of any network media and protocol; it is just a matter - of configuration utility to understand the correct addresses. The most - common example is TCP over IP, which allows to pass through firewalls and - create remote backup storage in a different datacenter. DST requires - single port to be enabled on the exporting node and outgoing connections - on the local node. - - DST works with in-kernel client and server, which improves performance by - eliminating unneded data copies and by not depending on the version - of the external IO components. It requires userspace configuration utility - though. - - DST uses transaction model, when each store has to be explicitly acked - from the remote node to be considered as successfully written. There - may be lots of in-flight transactions. When remote host does not ack - the transaction it will be resent predefined number of times with specified - timeouts between them. All those parameters are configurable. Transactions - are marked as failed after all resends complete unsuccessfully; having - long enough resend timeout and/or large number of resends allows not to - return error to the higher (FS usually) layer in case of short network - problems or remote node outages. In case of network RAID setup this means - that storage will not degrade until transactions are marked as failed, and - thus will not force checksum recalculation and data rebuild. In case of - connection failure DST will try to reconnect to the remote node automatically. - DST sends ping commands at idle time to detect if remote node is alive. - - Because of transactional model it is possible to use zero-copy sending - without worry of data corruption (which in turn could be detected by the - strong checksums though). - - DST may fully encrypt the data channel in case of untrusted channel and implement - strong checksum of the transferred data. It is possible to configure algorithms - and crypto keys; they should match on both sides of the network channel. - Crypto processing does not introduce noticeble performance overhead, since DST - uses configurable pool of threads to perform crypto processing. - - DST utilizes memory pool model of all its transaction allocations (it is the - only additional allocation on the client) and server allocations (bio pools, - while pages are allocated from the slab). - - At startup DST performs a simple negotiation with the export node to determine - access permissions and size of the exported storage. It can be extended if - new parameters should be autonegotiated. - - DST carries block IO flags in the protocol, which allows to transparently implement - barriers and sync/flush operations. Those flags are used in the export node where - IO against the local storage is performed, which means that sync write will be sync - on the remote node too, which in turn improves data integrity and improved resistance - to errors and data corruption during power outages or storage damages. - - Homepage: http://www.ioremap.net/projects/dst - Userspace configuration utility and the latest releases: http://www.ioremap.net/archive/dst/ - -config DST_DEBUG - bool "DST debug" - depends on DST - ---help--- - This option will enable HEAVY debugging of the DST. - Turn it on ONLY if you have to debug some really obscure problem. diff --git a/drivers/staging/dst/Makefile b/drivers/staging/dst/Makefile deleted file mode 100644 index 3a8b0cf9643..00000000000 --- a/drivers/staging/dst/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-$(CONFIG_DST) += nst.o - -nst-y := dcore.o state.o export.o thread_pool.o crypto.o trans.o diff --git a/drivers/staging/dst/crypto.c b/drivers/staging/dst/crypto.c deleted file mode 100644 index 351295c97a4..00000000000 --- a/drivers/staging/dst/crypto.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov - * All rights reserved. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include - -/* - * Tricky bastard, but IV can be more complex with time... - */ -static inline u64 dst_gen_iv(struct dst_trans *t) -{ - return t->gen; -} - -/* - * Crypto machinery: hash/cipher support for the given crypto controls. - */ -static struct crypto_hash *dst_init_hash(struct dst_crypto_ctl *ctl, u8 *key) -{ - int err; - struct crypto_hash *hash; - - hash = crypto_alloc_hash(ctl->hash_algo, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(hash)) { - err = PTR_ERR(hash); - dprintk("%s: failed to allocate hash '%s', err: %d.\n", - __func__, ctl->hash_algo, err); - goto err_out_exit; - } - - ctl->crypto_attached_size = crypto_hash_digestsize(hash); - - if (!ctl->hash_keysize) - return hash; - - err = crypto_hash_setkey(hash, key, ctl->hash_keysize); - if (err) { - dprintk("%s: failed to set key for hash '%s', err: %d.\n", - __func__, ctl->hash_algo, err); - goto err_out_free; - } - - return hash; - -err_out_free: - crypto_free_hash(hash); -err_out_exit: - return ERR_PTR(err); -} - -static struct crypto_ablkcipher *dst_init_cipher(struct dst_crypto_ctl *ctl, - u8 *key) -{ - int err = -EINVAL; - struct crypto_ablkcipher *cipher; - - if (!ctl->cipher_keysize) - goto err_out_exit; - - cipher = crypto_alloc_ablkcipher(ctl->cipher_algo, 0, 0); - if (IS_ERR(cipher)) { - err = PTR_ERR(cipher); - dprintk("%s: failed to allocate cipher '%s', err: %d.\n", - __func__, ctl->cipher_algo, err); - goto err_out_exit; - } - - crypto_ablkcipher_clear_flags(cipher, ~0); - - err = crypto_ablkcipher_setkey(cipher, key, ctl->cipher_keysize); - if (err) { - dprintk("%s: failed to set key for cipher '%s', err: %d.\n", - __func__, ctl->cipher_algo, err); - goto err_out_free; - } - - return cipher; - -err_out_free: - crypto_free_ablkcipher(cipher); -err_out_exit: - return ERR_PTR(err); -} - -/* - * Crypto engine has a pool of pages to encrypt data into before sending - * it over the network. This pool is freed/allocated here. - */ -static void dst_crypto_pages_free(struct dst_crypto_engine *e) -{ - unsigned int i; - - for (i = 0; i < e->page_num; ++i) - __free_page(e->pages[i]); - kfree(e->pages); -} - -static int dst_crypto_pages_alloc(struct dst_crypto_engine *e, int num) -{ - int i; - - e->pages = kmalloc(num * sizeof(struct page **), GFP_KERNEL); - if (!e->pages) - return -ENOMEM; - - for (i = 0; i < num; ++i) { - e->pages[i] = alloc_page(GFP_KERNEL); - if (!e->pages[i]) - goto err_out_free_pages; - } - - e->page_num = num; - return 0; - -err_out_free_pages: - while (--i >= 0) - __free_page(e->pages[i]); - - kfree(e->pages); - return -ENOMEM; -} - -/* - * Initialize crypto engine for given node. - * Setup cipher/hash, keys, pool of threads and private data. - */ -static int dst_crypto_engine_init(struct dst_crypto_engine *e, - struct dst_node *n) -{ - int err; - struct dst_crypto_ctl *ctl = &n->crypto; - - err = dst_crypto_pages_alloc(e, n->max_pages); - if (err) - goto err_out_exit; - - e->size = PAGE_SIZE; - e->data = kmalloc(e->size, GFP_KERNEL); - if (!e->data) { - err = -ENOMEM; - goto err_out_free_pages; - } - - if (ctl->hash_algo[0]) { - e->hash = dst_init_hash(ctl, n->hash_key); - if (IS_ERR(e->hash)) { - err = PTR_ERR(e->hash); - e->hash = NULL; - goto err_out_free; - } - } - - if (ctl->cipher_algo[0]) { - e->cipher = dst_init_cipher(ctl, n->cipher_key); - if (IS_ERR(e->cipher)) { - err = PTR_ERR(e->cipher); - e->cipher = NULL; - goto err_out_free_hash; - } - } - - return 0; - -err_out_free_hash: - crypto_free_hash(e->hash); -err_out_free: - kfree(e->data); -err_out_free_pages: - dst_crypto_pages_free(e); -err_out_exit: - return err; -} - -static void dst_crypto_engine_exit(struct dst_crypto_engine *e) -{ - if (e->hash) - crypto_free_hash(e->hash); - if (e->cipher) - crypto_free_ablkcipher(e->cipher); - dst_crypto_pages_free(e); - kfree(e->data); -} - -/* - * Waiting for cipher processing to be completed. - */ -struct dst_crypto_completion { - struct completion complete; - int error; -}; - -static void dst_crypto_complete(struct crypto_async_request *req, int err) -{ - struct dst_crypto_completion *c = req->data; - - if (err == -EINPROGRESS) - return; - - dprintk("%s: req: %p, err: %d.\n", __func__, req, err); - c->error = err; - complete(&c->complete); -} - -static int dst_crypto_process(struct ablkcipher_request *req, - struct scatterlist *sg_dst, struct scatterlist *sg_src, - void *iv, int enc, unsigned long timeout) -{ - struct dst_crypto_completion c; - int err; - - init_completion(&c.complete); - c.error = -EINPROGRESS; - - ablkcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, - dst_crypto_complete, &c); - - ablkcipher_request_set_crypt(req, sg_src, sg_dst, sg_src->length, iv); - - if (enc) - err = crypto_ablkcipher_encrypt(req); - else - err = crypto_ablkcipher_decrypt(req); - - switch (err) { - case -EINPROGRESS: - case -EBUSY: - err = wait_for_completion_interruptible_timeout(&c.complete, - timeout); - if (!err) - err = -ETIMEDOUT; - else - err = c.error; - break; - default: - break; - } - - return err; -} - -/* - * DST uses generic iteration approach for data crypto processing. - * Single block IO request is switched into array of scatterlists, - * which are submitted to the crypto processing iterator. - * - * Input and output iterator initialization are different, since - * in output case we can not encrypt data in-place and need a - * temporary storage, which is then being sent to the remote peer. - */ -static int dst_trans_iter_out(struct bio *bio, struct dst_crypto_engine *e, - int (*iterator) (struct dst_crypto_engine *e, - struct scatterlist *dst, - struct scatterlist *src)) -{ - struct bio_vec *bv; - int err, i; - - sg_init_table(e->src, bio->bi_vcnt); - sg_init_table(e->dst, bio->bi_vcnt); - - bio_for_each_segment(bv, bio, i) { - sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset); - sg_set_page(&e->dst[i], e->pages[i], bv->bv_len, bv->bv_offset); - - err = iterator(e, &e->dst[i], &e->src[i]); - if (err) - return err; - } - - return 0; -} - -static int dst_trans_iter_in(struct bio *bio, struct dst_crypto_engine *e, - int (*iterator) (struct dst_crypto_engine *e, - struct scatterlist *dst, - struct scatterlist *src)) -{ - struct bio_vec *bv; - int err, i; - - sg_init_table(e->src, bio->bi_vcnt); - sg_init_table(e->dst, bio->bi_vcnt); - - bio_for_each_segment(bv, bio, i) { - sg_set_page(&e->src[i], bv->bv_page, bv->bv_len, bv->bv_offset); - sg_set_page(&e->dst[i], bv->bv_page, bv->bv_len, bv->bv_offset); - - err = iterator(e, &e->dst[i], &e->src[i]); - if (err) - return err; - } - - return 0; -} - -static int dst_crypt_iterator(struct dst_crypto_engine *e, - struct scatterlist *sg_dst, struct scatterlist *sg_src) -{ - struct ablkcipher_request *req = e->data; - u8 iv[32]; - - memset(iv, 0, sizeof(iv)); - - memcpy(iv, &e->iv, sizeof(e->iv)); - - return dst_crypto_process(req, sg_dst, sg_src, iv, e->enc, e->timeout); -} - -static int dst_crypt(struct dst_crypto_engine *e, struct bio *bio) -{ - struct ablkcipher_request *req = e->data; - - memset(req, 0, sizeof(struct ablkcipher_request)); - ablkcipher_request_set_tfm(req, e->cipher); - - if (e->enc) - return dst_trans_iter_out(bio, e, dst_crypt_iterator); - else - return dst_trans_iter_in(bio, e, dst_crypt_iterator); -} - -static int dst_hash_iterator(struct dst_crypto_engine *e, - struct scatterlist *sg_dst, struct scatterlist *sg_src) -{ - return crypto_hash_update(e->data, sg_src, sg_src->length); -} - -static int dst_hash(struct dst_crypto_engine *e, struct bio *bio, void *dst) -{ - struct hash_desc *desc = e->data; - int err; - - desc->tfm = e->hash; - desc->flags = 0; - - err = crypto_hash_init(desc); - if (err) - return err; - - err = dst_trans_iter_in(bio, e, dst_hash_iterator); - if (err) - return err; - - err = crypto_hash_final(desc, dst); - if (err) - return err; - - return 0; -} - -/* - * Initialize/cleanup a crypto thread. The only thing it should - * do is to allocate a pool of pages as temporary storage. - * And to setup cipher and/or hash. - */ -static void *dst_crypto_thread_init(void *data) -{ - struct dst_node *n = data; - struct dst_crypto_engine *e; - int err = -ENOMEM; - - e = kzalloc(sizeof(struct dst_crypto_engine), GFP_KERNEL); - if (!e) - goto err_out_exit; - e->src = kcalloc(2 * n->max_pages, sizeof(struct scatterlist), - GFP_KERNEL); - if (!e->src) - goto err_out_free; - - e->dst = e->src + n->max_pages; - - err = dst_crypto_engine_init(e, n); - if (err) - goto err_out_free_all; - - return e; - -err_out_free_all: - kfree(e->src); -err_out_free: - kfree(e); -err_out_exit: - return ERR_PTR(err); -} - -static void dst_crypto_thread_cleanup(void *private) -{ - struct dst_crypto_engine *e = private; - - dst_crypto_engine_exit(e); - kfree(e->src); - kfree(e); -} - -/* - * Initialize crypto engine for given node: store keys, create pool - * of threads, initialize each one. - * - * Each thread has unique ID, but 0 and 1 are reserved for receiving and - * accepting threads (if export node), so IDs could start from 2, but starting - * them from 10 allows easily understand what this thread is for. - */ -int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl) -{ - void *key = (ctl + 1); - int err = -ENOMEM, i; - char name[32]; - - if (ctl->hash_keysize) { - n->hash_key = kmalloc(ctl->hash_keysize, GFP_KERNEL); - if (!n->hash_key) - goto err_out_exit; - memcpy(n->hash_key, key, ctl->hash_keysize); - } - - if (ctl->cipher_keysize) { - n->cipher_key = kmalloc(ctl->cipher_keysize, GFP_KERNEL); - if (!n->cipher_key) - goto err_out_free_hash; - memcpy(n->cipher_key, key, ctl->cipher_keysize); - } - memcpy(&n->crypto, ctl, sizeof(struct dst_crypto_ctl)); - - for (i = 0; i < ctl->thread_num; ++i) { - snprintf(name, sizeof(name), "%s-crypto-%d", n->name, i); - /* Unique ids... */ - err = thread_pool_add_worker(n->pool, name, i + 10, - dst_crypto_thread_init, dst_crypto_thread_cleanup, n); - if (err) - goto err_out_free_threads; - } - - return 0; - -err_out_free_threads: - while (--i >= 0) - thread_pool_del_worker_id(n->pool, i+10); - - if (ctl->cipher_keysize) - kfree(n->cipher_key); - ctl->cipher_keysize = 0; -err_out_free_hash: - if (ctl->hash_keysize) - kfree(n->hash_key); - ctl->hash_keysize = 0; -err_out_exit: - return err; -} - -void dst_node_crypto_exit(struct dst_node *n) -{ - struct dst_crypto_ctl *ctl = &n->crypto; - - if (ctl->cipher_algo[0] || ctl->hash_algo[0]) { - kfree(n->hash_key); - kfree(n->cipher_key); - } -} - -/* - * Thrad pool setup callback. Just stores a transaction in private data. - */ -static int dst_trans_crypto_setup(void *crypto_engine, void *trans) -{ - struct dst_crypto_engine *e = crypto_engine; - - e->private = trans; - return 0; -} - -#if 0 -static void dst_dump_bio(struct bio *bio) -{ - u8 *p; - struct bio_vec *bv; - int i; - - bio_for_each_segment(bv, bio, i) { - dprintk("%s: %llu/%u: size: %u, offset: %u, data: ", - __func__, bio->bi_sector, bio->bi_size, - bv->bv_len, bv->bv_offset); - - p = kmap(bv->bv_page) + bv->bv_offset; - for (i = 0; i < bv->bv_len; ++i) - printk(KERN_DEBUG "%02x ", p[i]); - kunmap(bv->bv_page); - printk("\n"); - } -} -#endif - -/* - * Encrypt/hash data and send it to the network. - */ -static int dst_crypto_process_sending(struct dst_crypto_engine *e, - struct bio *bio, u8 *hash) -{ - int err; - - if (e->cipher) { - err = dst_crypt(e, bio); - if (err) - goto err_out_exit; - } - - if (e->hash) { - err = dst_hash(e, bio, hash); - if (err) - goto err_out_exit; - -#ifdef CONFIG_DST_DEBUG - { - unsigned int i; - - /* dst_dump_bio(bio); */ - - printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash: ", - __func__, (u64)bio->bi_sector, - bio->bi_size, bio_data_dir(bio)); - for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) - printk("%02x ", hash[i]); - printk("\n"); - } -#endif - } - - return 0; - -err_out_exit: - return err; -} - -/* - * Check if received data is valid. Decipher if it is. - */ -static int dst_crypto_process_receiving(struct dst_crypto_engine *e, - struct bio *bio, u8 *hash, u8 *recv_hash) -{ - int err; - - if (e->hash) { - int mismatch; - - err = dst_hash(e, bio, hash); - if (err) - goto err_out_exit; - - mismatch = !!memcmp(recv_hash, hash, - crypto_hash_digestsize(e->hash)); -#ifdef CONFIG_DST_DEBUG - /* dst_dump_bio(bio); */ - - printk(KERN_DEBUG "%s: bio: %llu/%u, rw: %lu, hash mismatch: %d", - __func__, (u64)bio->bi_sector, bio->bi_size, - bio_data_dir(bio), mismatch); - if (mismatch) { - unsigned int i; - - printk(", recv/calc: "); - for (i = 0; i < crypto_hash_digestsize(e->hash); ++i) - printk("%02x/%02x ", recv_hash[i], hash[i]); - - } - printk("\n"); -#endif - err = -1; - if (mismatch) - goto err_out_exit; - } - - if (e->cipher) { - err = dst_crypt(e, bio); - if (err) - goto err_out_exit; - } - - return 0; - -err_out_exit: - return err; -} - -/* - * Thread pool callback to encrypt data and send it to the netowork. - */ -static int dst_trans_crypto_action(void *crypto_engine, void *schedule_data) -{ - struct dst_crypto_engine *e = crypto_engine; - struct dst_trans *t = schedule_data; - struct bio *bio = t->bio; - int err; - - dprintk("%s: t: %p, gen: %llu, cipher: %p, hash: %p.\n", - __func__, t, t->gen, e->cipher, e->hash); - - e->enc = t->enc; - e->iv = dst_gen_iv(t); - - if (bio_data_dir(bio) == WRITE) { - err = dst_crypto_process_sending(e, bio, t->cmd.hash); - if (err) - goto err_out_exit; - - if (e->hash) { - t->cmd.csize = crypto_hash_digestsize(e->hash); - t->cmd.size += t->cmd.csize; - } - - return dst_trans_send(t); - } else { - u8 *hash = e->data + e->size/2; - - err = dst_crypto_process_receiving(e, bio, hash, t->cmd.hash); - if (err) - goto err_out_exit; - - dst_trans_remove(t); - dst_trans_put(t); - } - - return 0; - -err_out_exit: - t->error = err; - dst_trans_put(t); - return err; -} - -/* - * Schedule crypto processing for given transaction. - */ -int dst_trans_crypto(struct dst_trans *t) -{ - struct dst_node *n = t->n; - int err; - - err = thread_pool_schedule(n->pool, - dst_trans_crypto_setup, dst_trans_crypto_action, - t, MAX_SCHEDULE_TIMEOUT); - if (err) - goto err_out_exit; - - return 0; - -err_out_exit: - dst_trans_put(t); - return err; -} - -/* - * Crypto machinery for the export node. - */ -static int dst_export_crypto_setup(void *crypto_engine, void *bio) -{ - struct dst_crypto_engine *e = crypto_engine; - - e->private = bio; - return 0; -} - -static int dst_export_crypto_action(void *crypto_engine, void *schedule_data) -{ - struct dst_crypto_engine *e = crypto_engine; - struct bio *bio = schedule_data; - struct dst_export_priv *p = bio->bi_private; - int err; - - dprintk("%s: e: %p, data: %p, bio: %llu/%u, dir: %lu.\n", - __func__, e, e->data, (u64)bio->bi_sector, - bio->bi_size, bio_data_dir(bio)); - - e->enc = (bio_data_dir(bio) == READ); - e->iv = p->cmd.id; - - if (bio_data_dir(bio) == WRITE) { - u8 *hash = e->data + e->size/2; - - err = dst_crypto_process_receiving(e, bio, hash, p->cmd.hash); - if (err) - goto err_out_exit; - - generic_make_request(bio); - } else { - err = dst_crypto_process_sending(e, bio, p->cmd.hash); - if (err) - goto err_out_exit; - - if (e->hash) { - p->cmd.csize = crypto_hash_digestsize(e->hash); - p->cmd.size += p->cmd.csize; - } - - err = dst_export_send_bio(bio); - } - return 0; - -err_out_exit: - bio_put(bio); - return err; -} - -int dst_export_crypto(struct dst_node *n, struct bio *bio) -{ - int err; - - err = thread_pool_schedule(n->pool, - dst_export_crypto_setup, dst_export_crypto_action, - bio, MAX_SCHEDULE_TIMEOUT); - if (err) - goto err_out_exit; - - return 0; - -err_out_exit: - bio_put(bio); - return err; -} diff --git a/drivers/staging/dst/dcore.c b/drivers/staging/dst/dcore.c deleted file mode 100644 index c83ca7e3d04..00000000000 --- a/drivers/staging/dst/dcore.c +++ /dev/null @@ -1,968 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov - * All rights reserved. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -static int dst_major; - -static DEFINE_MUTEX(dst_hash_lock); -static struct list_head *dst_hashtable; -static unsigned int dst_hashtable_size = 128; -module_param(dst_hashtable_size, uint, 0644); - -static char dst_name[] = "Dementianting goldfish"; - -static DEFINE_IDR(dst_index_idr); -static struct cb_id cn_dst_id = { CN_DST_IDX, CN_DST_VAL }; - -/* - * DST sysfs tree for device called 'storage': - * - * /sys/bus/dst/devices/storage/ - * /sys/bus/dst/devices/storage/type : 192.168.4.80:1025 - * /sys/bus/dst/devices/storage/size : 800 - * /sys/bus/dst/devices/storage/name : storage - */ - -static int dst_dev_match(struct device *dev, struct device_driver *drv) -{ - return 1; -} - -static struct bus_type dst_dev_bus_type = { - .name = "dst", - .match = &dst_dev_match, -}; - -static void dst_node_release(struct device *dev) -{ - struct dst_info *info = container_of(dev, struct dst_info, device); - - kfree(info); -} - -static struct device dst_node_dev = { - .bus = &dst_dev_bus_type, - .release = &dst_node_release -}; - -/* - * Setting size of the node after it was changed. - */ -static void dst_node_set_size(struct dst_node *n) -{ - struct block_device *bdev; - - set_capacity(n->disk, n->size >> 9); - - bdev = bdget_disk(n->disk, 0); - if (bdev) { - mutex_lock(&bdev->bd_inode->i_mutex); - i_size_write(bdev->bd_inode, n->size); - mutex_unlock(&bdev->bd_inode->i_mutex); - bdput(bdev); - } -} - -/* - * Distributed storage request processing function. - */ -static int dst_request(struct request_queue *q, struct bio *bio) -{ - struct dst_node *n = q->queuedata; - int err = -EIO; - - if (bio_empty_barrier(bio) && !blk_queue_discard(q)) { - /* - * This is a dirty^Wnice hack, but if we complete this - * operation with -EOPNOTSUPP like intended, XFS - * will stuck and freeze the machine. This may be - * not particulary XFS problem though, but it is the - * only FS which sends empty barrier at umount time - * I worked with. - * - * Empty barriers are not allowed anyway, see 51fd77bd9f512 - * for example, although later it was changed to - * bio_rw_flagged(bio, BIO_RW_DISCARD) only, which does not - * work in this case. - */ - /* err = -EOPNOTSUPP; */ - err = 0; - goto end_io; - } - - bio_get(bio); - - return dst_process_bio(n, bio); - -end_io: - bio_endio(bio, err); - return err; -} - -/* - * Open/close callbacks for appropriate block device. - */ -static int dst_bdev_open(struct block_device *bdev, fmode_t mode) -{ - struct dst_node *n = bdev->bd_disk->private_data; - - dst_node_get(n); - return 0; -} - -static int dst_bdev_release(struct gendisk *disk, fmode_t mode) -{ - struct dst_node *n = disk->private_data; - - dst_node_put(n); - return 0; -} - -static struct block_device_operations dst_blk_ops = { - .open = dst_bdev_open, - .release = dst_bdev_release, - .owner = THIS_MODULE, -}; - -/* - * Block layer binding - disk is created when array is fully configured - * by userspace request. - */ -static int dst_node_create_disk(struct dst_node *n) -{ - int err = -ENOMEM; - u32 index = 0; - - n->queue = blk_init_queue(NULL, NULL); - if (!n->queue) - goto err_out_exit; - - n->queue->queuedata = n; - blk_queue_make_request(n->queue, dst_request); - blk_queue_max_phys_segments(n->queue, n->max_pages); - blk_queue_max_hw_segments(n->queue, n->max_pages); - - err = -ENOMEM; - n->disk = alloc_disk(1); - if (!n->disk) - goto err_out_free_queue; - - if (!(n->state->permissions & DST_PERM_WRITE)) { - printk(KERN_INFO "DST node %s attached read-only.\n", n->name); - set_disk_ro(n->disk, 1); - } - - if (!idr_pre_get(&dst_index_idr, GFP_KERNEL)) - goto err_out_put; - - mutex_lock(&dst_hash_lock); - err = idr_get_new(&dst_index_idr, NULL, &index); - mutex_unlock(&dst_hash_lock); - if (err) - goto err_out_put; - - n->disk->major = dst_major; - n->disk->first_minor = index; - n->disk->fops = &dst_blk_ops; - n->disk->queue = n->queue; - n->disk->private_data = n; - snprintf(n->disk->disk_name, sizeof(n->disk->disk_name), - "dst-%s", n->name); - - return 0; - -err_out_put: - put_disk(n->disk); -err_out_free_queue: - blk_cleanup_queue(n->queue); -err_out_exit: - return err; -} - -/* - * Sysfs machinery: show device's size. - */ -static ssize_t dst_show_size(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dst_info *info = container_of(dev, struct dst_info, device); - - return sprintf(buf, "%llu\n", info->size); -} - -/* - * Show local exported device. - */ -static ssize_t dst_show_local(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dst_info *info = container_of(dev, struct dst_info, device); - - return sprintf(buf, "%s\n", info->local); -} - -/* - * Shows type of the remote node - device major/minor number - * for local nodes and address (af_inet ipv4/ipv6 only) for remote nodes. - */ -static ssize_t dst_show_type(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct dst_info *info = container_of(dev, struct dst_info, device); - int family = info->net.addr.sa_family; - - if (family == AF_INET) { - struct sockaddr_in *sin = (struct sockaddr_in *)&info->net.addr; - return sprintf(buf, "%u.%u.%u.%u:%d\n", - NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); - } else if (family == AF_INET6) { - struct sockaddr_in6 *sin = (struct sockaddr_in6 *) - &info->net.addr; - return sprintf(buf, - "%pi6:%d\n", - &sin->sin6_addr, ntohs(sin->sin6_port)); - } else { - int i, sz = PAGE_SIZE - 2; /* 0 symbol and '\n' below */ - int size, addrlen = info->net.addr.sa_data_len; - unsigned char *a = (unsigned char *)&info->net.addr.sa_data; - char *buf_orig = buf; - - size = snprintf(buf, sz, "family: %d, addrlen: %u, addr: ", - family, addrlen); - sz -= size; - buf += size; - - for (i = 0; i < addrlen; ++i) { - if (sz < 3) - break; - - size = snprintf(buf, sz, "%02x ", a[i]); - sz -= size; - buf += size; - } - buf += sprintf(buf, "\n"); - - return buf - buf_orig; - } - return 0; -} - -static struct device_attribute dst_node_attrs[] = { - __ATTR(size, 0444, dst_show_size, NULL), - __ATTR(type, 0444, dst_show_type, NULL), - __ATTR(local, 0444, dst_show_local, NULL), -}; - -static int dst_create_node_attributes(struct dst_node *n) -{ - int err, i; - - for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i) { - err = device_create_file(&n->info->device, - &dst_node_attrs[i]); - if (err) - goto err_out_remove_all; - } - return 0; - -err_out_remove_all: - while (--i >= 0) - device_remove_file(&n->info->device, - &dst_node_attrs[i]); - - return err; -} - -static void dst_remove_node_attributes(struct dst_node *n) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dst_node_attrs); ++i) - device_remove_file(&n->info->device, - &dst_node_attrs[i]); -} - -/* - * Sysfs cleanup and initialization. - * Shows number of useful parameters. - */ -static void dst_node_sysfs_exit(struct dst_node *n) -{ - if (n->info) { - dst_remove_node_attributes(n); - device_unregister(&n->info->device); - n->info = NULL; - } -} - -static int dst_node_sysfs_init(struct dst_node *n) -{ - int err; - - n->info = kzalloc(sizeof(struct dst_info), GFP_KERNEL); - if (!n->info) - return -ENOMEM; - - memcpy(&n->info->device, &dst_node_dev, sizeof(struct device)); - n->info->size = n->size; - - dev_set_name(&n->info->device, "dst-%s", n->name); - err = device_register(&n->info->device); - if (err) { - dprintk(KERN_ERR "Failed to register node '%s', err: %d.\n", - n->name, err); - goto err_out_exit; - } - - dst_create_node_attributes(n); - - return 0; - -err_out_exit: - kfree(n->info); - n->info = NULL; - return err; -} - -/* - * DST node hash tables machinery. - */ -static inline unsigned int dst_hash(char *str, unsigned int size) -{ - return jhash(str, size, 0) % dst_hashtable_size; -} - -static void dst_node_remove(struct dst_node *n) -{ - mutex_lock(&dst_hash_lock); - list_del_init(&n->node_entry); - mutex_unlock(&dst_hash_lock); -} - -static void dst_node_add(struct dst_node *n) -{ - unsigned hash = dst_hash(n->name, sizeof(n->name)); - - mutex_lock(&dst_hash_lock); - list_add_tail(&n->node_entry, &dst_hashtable[hash]); - mutex_unlock(&dst_hash_lock); -} - -/* - * Cleaning node when it is about to be freed. - * There are still users of the socket though, - * so connection cleanup should be protected. - */ -static void dst_node_cleanup(struct dst_node *n) -{ - struct dst_state *st = n->state; - - if (!st) - return; - - if (n->queue) { - blk_cleanup_queue(n->queue); - - mutex_lock(&dst_hash_lock); - idr_remove(&dst_index_idr, n->disk->first_minor); - mutex_unlock(&dst_hash_lock); - - put_disk(n->disk); - } - - if (n->bdev) { - sync_blockdev(n->bdev); - close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE); - } - - dst_state_lock(st); - st->need_exit = 1; - dst_state_exit_connected(st); - dst_state_unlock(st); - - wake_up(&st->thread_wait); - - dst_state_put(st); - n->state = NULL; -} - -/* - * Free security attributes attached to given node. - */ -static void dst_security_exit(struct dst_node *n) -{ - struct dst_secure *s, *tmp; - - list_for_each_entry_safe(s, tmp, &n->security_list, sec_entry) { - list_del(&s->sec_entry); - kfree(s); - } -} - -/* - * Free node when there are no more users. - * Actually node has to be freed on behalf od userspace process, - * since there are number of threads, which are embedded in the - * node, so they can not exit and free node from there, that is - * why there is a wakeup if reference counter is not equal to zero. - */ -void dst_node_put(struct dst_node *n) -{ - if (unlikely(!n)) - return; - - dprintk("%s: n: %p, refcnt: %d.\n", - __func__, n, atomic_read(&n->refcnt)); - - if (atomic_dec_and_test(&n->refcnt)) { - dst_node_remove(n); - n->trans_scan_timeout = 0; - dst_node_cleanup(n); - thread_pool_destroy(n->pool); - dst_node_sysfs_exit(n); - dst_node_crypto_exit(n); - dst_security_exit(n); - dst_node_trans_exit(n); - - kfree(n); - - dprintk("%s: freed n: %p.\n", __func__, n); - } else { - wake_up(&n->wait); - } -} - -/* - * Setting up export device: lookup by the name, get its size - * and setup listening socket, which will accept clients, which - * will submit IO for given storage. - */ -static int dst_setup_export(struct dst_node *n, struct dst_ctl *ctl, - struct dst_export_ctl *le) -{ - int err; - - snprintf(n->info->local, sizeof(n->info->local), "%s", le->device); - - n->bdev = open_bdev_exclusive(le->device, FMODE_READ|FMODE_WRITE, NULL); - if (IS_ERR(n->bdev)) - return PTR_ERR(n->bdev); - - if (n->size != 0) - n->size = min_t(loff_t, n->bdev->bd_inode->i_size, n->size); - else - n->size = n->bdev->bd_inode->i_size; - - n->info->size = n->size; - err = dst_node_init_listened(n, le); - if (err) - goto err_out_cleanup; - - return 0; - -err_out_cleanup: - close_bdev_exclusive(n->bdev, FMODE_READ|FMODE_WRITE); - n->bdev = NULL; - - return err; -} - -/* Empty thread pool callbacks for the network processing threads. */ -static inline void *dst_thread_network_init(void *data) -{ - dprintk("%s: data: %p.\n", __func__, data); - return data; -} - -static inline void dst_thread_network_cleanup(void *data) -{ - dprintk("%s: data: %p.\n", __func__, data); -} - -/* - * Allocate DST node and initialize some of its parameters. - */ -static struct dst_node *dst_alloc_node(struct dst_ctl *ctl, - int (*start)(struct dst_node *), - int num) -{ - struct dst_node *n; - int err; - - n = kzalloc(sizeof(struct dst_node), GFP_KERNEL); - if (!n) - return NULL; - - INIT_LIST_HEAD(&n->node_entry); - - INIT_LIST_HEAD(&n->security_list); - mutex_init(&n->security_lock); - - init_waitqueue_head(&n->wait); - - n->trans_scan_timeout = msecs_to_jiffies(ctl->trans_scan_timeout); - if (!n->trans_scan_timeout) - n->trans_scan_timeout = HZ; - - n->trans_max_retries = ctl->trans_max_retries; - if (!n->trans_max_retries) - n->trans_max_retries = 10; - - /* - * Pretty much arbitrary default numbers. - * 32 matches maximum number of pages in bio originated from ext3 (31). - */ - n->max_pages = ctl->max_pages; - if (!n->max_pages) - n->max_pages = 32; - - if (n->max_pages > 1024) - n->max_pages = 1024; - - n->start = start; - n->size = ctl->size; - - atomic_set(&n->refcnt, 1); - atomic_long_set(&n->gen, 0); - snprintf(n->name, sizeof(n->name), "%s", ctl->name); - - err = dst_node_sysfs_init(n); - if (err) - goto err_out_free; - - n->pool = thread_pool_create(num, n->name, dst_thread_network_init, - dst_thread_network_cleanup, n); - if (IS_ERR(n->pool)) { - err = PTR_ERR(n->pool); - goto err_out_sysfs_exit; - } - - dprintk("%s: n: %p, name: %s.\n", __func__, n, n->name); - - return n; - -err_out_sysfs_exit: - dst_node_sysfs_exit(n); -err_out_free: - kfree(n); - return NULL; -} - -/* - * Starting a node, connected to the remote server: - * register block device and initialize transaction mechanism. - * In revers order though. - * - * It will autonegotiate some parameters with the remote node - * and update local if needed. - * - * Transaction initialization should be the last thing before - * starting the node, since transaction should include not only - * block IO, but also crypto related data (if any), which are - * initialized separately. - */ -static int dst_start_remote(struct dst_node *n) -{ - int err; - - err = dst_node_trans_init(n, sizeof(struct dst_trans)); - if (err) - return err; - - err = dst_node_create_disk(n); - if (err) - return err; - - dst_node_set_size(n); - add_disk(n->disk); - - dprintk("DST: started remote node '%s', minor: %d.\n", - n->name, n->disk->first_minor); - - return 0; -} - -/* - * Adding remote node and initialize connection. - */ -static int dst_add_remote(struct dst_node *n, struct dst_ctl *ctl, - void *data, unsigned int size) -{ - int err; - struct dst_network_ctl *rctl = data; - - if (n) - return -EEXIST; - - if (size != sizeof(struct dst_network_ctl)) - return -EINVAL; - - n = dst_alloc_node(ctl, dst_start_remote, 1); - if (!n) - return -ENOMEM; - - memcpy(&n->info->net, rctl, sizeof(struct dst_network_ctl)); - err = dst_node_init_connected(n, rctl); - if (err) - goto err_out_free; - - dst_node_add(n); - - return 0; - -err_out_free: - dst_node_put(n); - return err; -} - -/* - * Adding export node: initializing block device and listening socket. - */ -static int dst_add_export(struct dst_node *n, struct dst_ctl *ctl, - void *data, unsigned int size) -{ - int err; - struct dst_export_ctl *le = data; - - if (n) - return -EEXIST; - - if (size != sizeof(struct dst_export_ctl)) - return -EINVAL; - - n = dst_alloc_node(ctl, dst_start_export, 2); - if (!n) - return -EINVAL; - - err = dst_setup_export(n, ctl, le); - if (err) - goto err_out_free; - - dst_node_add(n); - - return 0; - -err_out_free: - dst_node_put(n); - return err; -} - -static int dst_node_remove_unload(struct dst_node *n) -{ - printk(KERN_INFO "STOPPED name: '%s', size: %llu.\n", - n->name, n->size); - - if (n->disk) - del_gendisk(n->disk); - - dst_node_remove(n); - dst_node_sysfs_exit(n); - - /* - * This is not a hack. Really. - * Node's reference counter allows to implement fine grained - * node freeing, but since all transactions (which hold node's - * reference counter) are processed in the dedicated thread, - * it is possible that reference will hit zero in that thread, - * so we will not be able to exit thread and cleanup the node. - * - * So, we remove disk, so no new activity is possible, and - * wait until all pending transaction are completed (either - * in receiving thread or by timeout in workqueue), in this - * case reference counter will be less or equal to 2 (once set in - * dst_alloc_node() and then in connector message parser; - * or when we force module unloading, and connector message - * parser does not hold a reference, in this case reference - * counter will be equal to 1), - * and subsequent dst_node_put() calls will free the node. - */ - dprintk("%s: going to sleep with %d refcnt.\n", - __func__, atomic_read(&n->refcnt)); - wait_event(n->wait, atomic_read(&n->refcnt) <= 2); - - dst_node_put(n); - return 0; -} - -/* - * Remove node from the hash table. - */ -static int dst_del_node(struct dst_node *n, struct dst_ctl *ctl, - void *data, unsigned int size) -{ - if (!n) - return -ENODEV; - - return dst_node_remove_unload(n); -} - -/* - * Initialize crypto processing for given node. - */ -static int dst_crypto_init(struct dst_node *n, struct dst_ctl *ctl, - void *data, unsigned int size) -{ - struct dst_crypto_ctl *crypto = data; - - if (!n) - return -ENODEV; - - if (size != sizeof(struct dst_crypto_ctl) + crypto->hash_keysize + - crypto->cipher_keysize) - return -EINVAL; - - if (n->trans_cache) - return -EEXIST; - - return dst_node_crypto_init(n, crypto); -} - -/* - * Security attributes for given node. - */ -static int dst_security_init(struct dst_node *n, struct dst_ctl *ctl, - void *data, unsigned int size) -{ - struct dst_secure *s; - - if (!n) - return -ENODEV; - - if (size != sizeof(struct dst_secure_user)) - return -EINVAL; - - s = kmalloc(sizeof(struct dst_secure), GFP_KERNEL); - if (!s) - return -ENOMEM; - - memcpy(&s->sec, data, size); - - mutex_lock(&n->security_lock); - list_add_tail(&s->sec_entry, &n->security_list); - mutex_unlock(&n->security_lock); - - return 0; -} - -/* - * Kill'em all! - */ -static int dst_start_node(struct dst_node *n, struct dst_ctl *ctl, - void *data, unsigned int size) -{ - int err; - - if (!n) - return -ENODEV; - - if (n->trans_cache) - return 0; - - err = n->start(n); - if (err) - return err; - - printk(KERN_INFO "STARTED name: '%s', size: %llu.\n", n->name, n->size); - return 0; -} - -typedef int (*dst_command_func)(struct dst_node *n, struct dst_ctl *ctl, - void *data, unsigned int size); - -/* - * List of userspace commands. - */ -static dst_command_func dst_commands[] = { - [DST_ADD_REMOTE] = &dst_add_remote, - [DST_ADD_EXPORT] = &dst_add_export, - [DST_DEL_NODE] = &dst_del_node, - [DST_CRYPTO] = &dst_crypto_init, - [DST_SECURITY] = &dst_security_init, - [DST_START] = &dst_start_node, -}; - -/* - * Configuration parser. - */ -static void cn_dst_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp) -{ - struct dst_ctl *ctl; - int err; - struct dst_ctl_ack ack; - struct dst_node *n = NULL, *tmp; - unsigned int hash; - - if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) { - err = -EPERM; - goto out; - } - - if (msg->len < sizeof(struct dst_ctl)) { - err = -EBADMSG; - goto out; - } - - ctl = (struct dst_ctl *)msg->data; - - if (ctl->cmd >= DST_CMD_MAX) { - err = -EINVAL; - goto out; - } - hash = dst_hash(ctl->name, sizeof(ctl->name)); - - mutex_lock(&dst_hash_lock); - list_for_each_entry(tmp, &dst_hashtable[hash], node_entry) { - if (!memcmp(tmp->name, ctl->name, sizeof(tmp->name))) { - n = tmp; - dst_node_get(n); - break; - } - } - mutex_unlock(&dst_hash_lock); - - err = dst_commands[ctl->cmd](n, ctl, msg->data + sizeof(struct dst_ctl), - msg->len - sizeof(struct dst_ctl)); - - dst_node_put(n); -out: - memcpy(&ack.msg, msg, sizeof(struct cn_msg)); - - ack.msg.ack = msg->ack + 1; - ack.msg.len = sizeof(struct dst_ctl_ack) - sizeof(struct cn_msg); - - ack.error = err; - - cn_netlink_send(&ack.msg, 0, GFP_KERNEL); -} - -/* - * Global initialization: sysfs, hash table, block device registration, - * connector and various caches. - */ -static int __init dst_sysfs_init(void) -{ - return bus_register(&dst_dev_bus_type); -} - -static void dst_sysfs_exit(void) -{ - bus_unregister(&dst_dev_bus_type); -} - -static int __init dst_hashtable_init(void) -{ - unsigned int i; - - dst_hashtable = kcalloc(dst_hashtable_size, sizeof(struct list_head), - GFP_KERNEL); - if (!dst_hashtable) - return -ENOMEM; - - for (i = 0; i < dst_hashtable_size; ++i) - INIT_LIST_HEAD(&dst_hashtable[i]); - - return 0; -} - -static void dst_hashtable_exit(void) -{ - unsigned int i; - struct dst_node *n, *tmp; - - for (i = 0; i < dst_hashtable_size; ++i) { - list_for_each_entry_safe(n, tmp, &dst_hashtable[i], node_entry) { - dst_node_remove_unload(n); - } - } - - kfree(dst_hashtable); -} - -static int __init dst_sys_init(void) -{ - int err = -ENOMEM; - - err = dst_hashtable_init(); - if (err) - goto err_out_exit; - - err = dst_export_init(); - if (err) - goto err_out_hashtable_exit; - - err = register_blkdev(dst_major, DST_NAME); - if (err < 0) - goto err_out_export_exit; - if (err) - dst_major = err; - - err = dst_sysfs_init(); - if (err) - goto err_out_unregister; - - err = cn_add_callback(&cn_dst_id, "DST", cn_dst_callback); - if (err) - goto err_out_sysfs_exit; - - printk(KERN_INFO "Distributed storage, '%s' release.\n", dst_name); - - return 0; - -err_out_sysfs_exit: - dst_sysfs_exit(); -err_out_unregister: - unregister_blkdev(dst_major, DST_NAME); -err_out_export_exit: - dst_export_exit(); -err_out_hashtable_exit: - dst_hashtable_exit(); -err_out_exit: - return err; -} - -static void __exit dst_sys_exit(void) -{ - cn_del_callback(&cn_dst_id); - unregister_blkdev(dst_major, DST_NAME); - dst_hashtable_exit(); - dst_sysfs_exit(); - dst_export_exit(); -} - -module_init(dst_sys_init); -module_exit(dst_sys_exit); - -MODULE_DESCRIPTION("Distributed storage"); -MODULE_AUTHOR("Evgeniy Polyakov "); -MODULE_LICENSE("GPL"); diff --git a/drivers/staging/dst/export.c b/drivers/staging/dst/export.c deleted file mode 100644 index c324230e8b6..00000000000 --- a/drivers/staging/dst/export.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov - * All rights reserved. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * Export bioset is used for server block IO requests. - */ -static struct bio_set *dst_bio_set; - -int __init dst_export_init(void) -{ - int err = -ENOMEM; - - dst_bio_set = bioset_create(32, sizeof(struct dst_export_priv)); - if (!dst_bio_set) - goto err_out_exit; - - return 0; - -err_out_exit: - return err; -} - -void dst_export_exit(void) -{ - bioset_free(dst_bio_set); -} - -/* - * When client connects and autonegotiates with the server node, - * its permissions are checked in a security attributes and sent - * back. - */ -static unsigned int dst_check_permissions(struct dst_state *main, - struct dst_state *st) -{ - struct dst_node *n = main->node; - struct dst_secure *sentry; - struct dst_secure_user *s; - struct saddr *sa = &st->ctl.addr; - unsigned int perm = 0; - - mutex_lock(&n->security_lock); - list_for_each_entry(sentry, &n->security_list, sec_entry) { - s = &sentry->sec; - - if (s->addr.sa_family != sa->sa_family) - continue; - - if (s->addr.sa_data_len != sa->sa_data_len) - continue; - - /* - * This '2' below is a port field. This may be very wrong to do - * in atalk for example though. If there will be any need - * to extent protocol to something else, I can create - * per-family helpers and use them instead of this memcmp. - */ - if (memcmp(s->addr.sa_data + 2, sa->sa_data + 2, - sa->sa_data_len - 2)) - continue; - - perm = s->permissions; - } - mutex_unlock(&n->security_lock); - - return perm; -} - -/* - * Accept new client: allocate appropriate network state and check permissions. - */ -static struct dst_state *dst_accept_client(struct dst_state *st) -{ - unsigned int revents = 0; - unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; - unsigned int mask = err_mask | POLLIN; - struct dst_node *n = st->node; - int err = 0; - struct socket *sock = NULL; - struct dst_state *new; - - while (!err && !sock) { - revents = dst_state_poll(st); - - if (!(revents & mask)) { - DEFINE_WAIT(wait); - - for (;;) { - prepare_to_wait(&st->thread_wait, - &wait, TASK_INTERRUPTIBLE); - if (!n->trans_scan_timeout || st->need_exit) - break; - - revents = dst_state_poll(st); - - if (revents & mask) - break; - - if (signal_pending(current)) - break; - - /* - * Magic HZ? Polling check above is not safe in - * all cases (like socket reset in BH context), - * so it is simpler just to postpone it to the - * process context instead of implementing - * special locking there. - */ - schedule_timeout(HZ); - } - finish_wait(&st->thread_wait, &wait); - } - - err = -ECONNRESET; - dst_state_lock(st); - - dprintk("%s: st: %p, revents: %x [err: %d, in: %d].\n", - __func__, st, revents, revents & err_mask, - revents & POLLIN); - - if (revents & err_mask) { - dprintk("%s: revents: %x, socket: %p, err: %d.\n", - __func__, revents, st->socket, err); - err = -ECONNRESET; - } - - if (!n->trans_scan_timeout || st->need_exit) - err = -ENODEV; - - if (st->socket && (revents & POLLIN)) - err = kernel_accept(st->socket, &sock, 0); - - dst_state_unlock(st); - } - - if (err) - goto err_out_exit; - - new = dst_state_alloc(st->node); - if (IS_ERR(new)) { - err = -ENOMEM; - goto err_out_release; - } - new->socket = sock; - - new->ctl.addr.sa_data_len = sizeof(struct sockaddr); - err = kernel_getpeername(sock, (struct sockaddr *)&new->ctl.addr, - (int *)&new->ctl.addr.sa_data_len); - if (err) - goto err_out_put; - - new->permissions = dst_check_permissions(st, new); - if (new->permissions == 0) { - err = -EPERM; - dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr, - "Client is not allowed to connect"); - goto err_out_put; - } - - err = dst_poll_init(new); - if (err) - goto err_out_put; - - dst_dump_addr(sock, (struct sockaddr *)&new->ctl.addr, - "Connected client"); - - return new; - -err_out_put: - dst_state_put(new); -err_out_release: - sock_release(sock); -err_out_exit: - return ERR_PTR(err); -} - -/* - * Each server's block request sometime finishes. - * Usually it happens in hard irq context of the appropriate controller, - * so to play good with all cases we just queue BIO into the queue - * and wake up processing thread, which gets completed request and - * send (encrypting if needed) it back to the client (if it was a read - * request), or sends back reply that writing successfully completed. - */ -static int dst_export_process_request_queue(struct dst_state *st) -{ - unsigned long flags; - struct dst_export_priv *p = NULL; - struct bio *bio; - int err = 0; - - while (!list_empty(&st->request_list)) { - spin_lock_irqsave(&st->request_lock, flags); - if (!list_empty(&st->request_list)) { - p = list_first_entry(&st->request_list, - struct dst_export_priv, request_entry); - list_del(&p->request_entry); - } - spin_unlock_irqrestore(&st->request_lock, flags); - - if (!p) - break; - - bio = p->bio; - - if (dst_need_crypto(st->node) && (bio_data_dir(bio) == READ)) - err = dst_export_crypto(st->node, bio); - else - err = dst_export_send_bio(bio); - - if (err) - break; - } - - return err; -} - -/* - * Cleanup export state. - * It has to wait until all requests are finished, - * and then free them all. - */ -static void dst_state_cleanup_export(struct dst_state *st) -{ - struct dst_export_priv *p; - unsigned long flags; - - /* - * This loop waits for all pending bios to be completed and freed. - */ - while (atomic_read(&st->refcnt) > 1) { - dprintk("%s: st: %p, refcnt: %d, list_empty: %d.\n", - __func__, st, atomic_read(&st->refcnt), - list_empty(&st->request_list)); - wait_event_timeout(st->thread_wait, - (atomic_read(&st->refcnt) == 1) || - !list_empty(&st->request_list), - HZ/2); - - while (!list_empty(&st->request_list)) { - p = NULL; - spin_lock_irqsave(&st->request_lock, flags); - if (!list_empty(&st->request_list)) { - p = list_first_entry(&st->request_list, - struct dst_export_priv, request_entry); - list_del(&p->request_entry); - } - spin_unlock_irqrestore(&st->request_lock, flags); - - if (p) - bio_put(p->bio); - - dprintk("%s: st: %p, refcnt: %d, list_empty: %d, p: " - "%p.\n", __func__, st, atomic_read(&st->refcnt), - list_empty(&st->request_list), p); - } - } - - dst_state_put(st); -} - -/* - * Client accepting thread. - * Not only accepts new connection, but also schedules receiving thread - * and performs request completion described above. - */ -static int dst_accept(void *init_data, void *schedule_data) -{ - struct dst_state *main_st = schedule_data; - struct dst_node *n = init_data; - struct dst_state *st; - int err; - - while (n->trans_scan_timeout && !main_st->need_exit) { - dprintk("%s: main_st: %p, n: %p.\n", __func__, main_st, n); - st = dst_accept_client(main_st); - if (IS_ERR(st)) - continue; - - err = dst_state_schedule_receiver(st); - if (!err) { - while (n->trans_scan_timeout) { - err = wait_event_interruptible_timeout(st->thread_wait, - !list_empty(&st->request_list) || - !n->trans_scan_timeout || - st->need_exit, - HZ); - - if (!n->trans_scan_timeout || st->need_exit) - break; - - if (list_empty(&st->request_list)) - continue; - - err = dst_export_process_request_queue(st); - if (err) - break; - } - - st->need_exit = 1; - wake_up(&st->thread_wait); - } - - dst_state_cleanup_export(st); - } - - dprintk("%s: freeing listening socket st: %p.\n", __func__, main_st); - - dst_state_lock(main_st); - dst_poll_exit(main_st); - dst_state_socket_release(main_st); - dst_state_unlock(main_st); - dst_state_put(main_st); - dprintk("%s: freed listening socket st: %p.\n", __func__, main_st); - - return 0; -} - -int dst_start_export(struct dst_node *n) -{ - if (list_empty(&n->security_list)) { - printk(KERN_ERR "You are trying to export node '%s' " - "without security attributes.\nNo clients will " - "be allowed to connect. Exiting.\n", n->name); - return -EINVAL; - } - return dst_node_trans_init(n, sizeof(struct dst_export_priv)); -} - -/* - * Initialize listening state and schedule accepting thread. - */ -int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le) -{ - struct dst_state *st; - int err = -ENOMEM; - struct dst_network_ctl *ctl = &le->ctl; - - memcpy(&n->info->net, ctl, sizeof(struct dst_network_ctl)); - - st = dst_state_alloc(n); - if (IS_ERR(st)) { - err = PTR_ERR(st); - goto err_out_exit; - } - memcpy(&st->ctl, ctl, sizeof(struct dst_network_ctl)); - - err = dst_state_socket_create(st); - if (err) - goto err_out_put; - - st->socket->sk->sk_reuse = 1; - - err = kernel_bind(st->socket, (struct sockaddr *)&ctl->addr, - ctl->addr.sa_data_len); - if (err) - goto err_out_socket_release; - - err = kernel_listen(st->socket, 1024); - if (err) - goto err_out_socket_release; - n->state = st; - - err = dst_poll_init(st); - if (err) - goto err_out_socket_release; - - dst_state_get(st); - - err = thread_pool_schedule(n->pool, dst_thread_setup, - dst_accept, st, MAX_SCHEDULE_TIMEOUT); - if (err) - goto err_out_poll_exit; - - return 0; - -err_out_poll_exit: - dst_poll_exit(st); -err_out_socket_release: - dst_state_socket_release(st); -err_out_put: - dst_state_put(st); -err_out_exit: - n->state = NULL; - return err; -} - -/* - * Free bio and related private data. - * Also drop a reference counter for appropriate state, - * which waits when there are no more block IOs in-flight. - */ -static void dst_bio_destructor(struct bio *bio) -{ - struct bio_vec *bv; - struct dst_export_priv *priv = bio->bi_private; - int i; - - bio_for_each_segment(bv, bio, i) { - if (!bv->bv_page) - break; - - __free_page(bv->bv_page); - } - - if (priv) - dst_state_put(priv->state); - bio_free(bio, dst_bio_set); -} - -/* - * Block IO completion. Queue request to be sent back to - * the client (or just confirmation). - */ -static void dst_bio_end_io(struct bio *bio, int err) -{ - struct dst_export_priv *p = bio->bi_private; - struct dst_state *st = p->state; - unsigned long flags; - - spin_lock_irqsave(&st->request_lock, flags); - list_add_tail(&p->request_entry, &st->request_list); - spin_unlock_irqrestore(&st->request_lock, flags); - - wake_up(&st->thread_wait); -} - -/* - * Allocate read request for the server. - */ -static int dst_export_read_request(struct bio *bio, unsigned int total_size) -{ - unsigned int size; - struct page *page; - int err; - - while (total_size) { - err = -ENOMEM; - page = alloc_page(GFP_KERNEL); - if (!page) - goto err_out_exit; - - size = min_t(unsigned int, PAGE_SIZE, total_size); - - err = bio_add_page(bio, page, size, 0); - dprintk("%s: bio: %llu/%u, size: %u, err: %d.\n", - __func__, (u64)bio->bi_sector, bio->bi_size, - size, err); - if (err <= 0) - goto err_out_free_page; - - total_size -= size; - } - - return 0; - -err_out_free_page: - __free_page(page); -err_out_exit: - return err; -} - -/* - * Allocate write request for the server. - * Should not only get pages, but also read data from the network. - */ -static int dst_export_write_request(struct dst_state *st, - struct bio *bio, unsigned int total_size) -{ - unsigned int size; - struct page *page; - void *data; - int err; - - while (total_size) { - err = -ENOMEM; - page = alloc_page(GFP_KERNEL); - if (!page) - goto err_out_exit; - - data = kmap(page); - if (!data) - goto err_out_free_page; - - size = min_t(unsigned int, PAGE_SIZE, total_size); - - err = dst_data_recv(st, data, size); - if (err) - goto err_out_unmap_page; - - err = bio_add_page(bio, page, size, 0); - if (err <= 0) - goto err_out_unmap_page; - - kunmap(page); - - total_size -= size; - } - - return 0; - -err_out_unmap_page: - kunmap(page); -err_out_free_page: - __free_page(page); -err_out_exit: - return err; -} - -/* - * Groovy, we've gotten an IO request from the client. - * Allocate BIO from the bioset, private data from the mempool - * and lots of pages for IO. - */ -int dst_process_io(struct dst_state *st) -{ - struct dst_node *n = st->node; - struct dst_cmd *cmd = st->data; - struct bio *bio; - struct dst_export_priv *priv; - int err = -ENOMEM; - - if (unlikely(!n->bdev)) { - err = -EINVAL; - goto err_out_exit; - } - - bio = bio_alloc_bioset(GFP_KERNEL, - PAGE_ALIGN(cmd->size) >> PAGE_SHIFT, - dst_bio_set); - if (!bio) - goto err_out_exit; - - priv = (struct dst_export_priv *)(((void *)bio) - - sizeof (struct dst_export_priv)); - - priv->state = dst_state_get(st); - priv->bio = bio; - - bio->bi_private = priv; - bio->bi_end_io = dst_bio_end_io; - bio->bi_destructor = dst_bio_destructor; - bio->bi_bdev = n->bdev; - - /* - * Server side is only interested in two low bits: - * uptodate (set by itself actually) and rw block - */ - bio->bi_flags |= cmd->flags & 3; - - bio->bi_rw = cmd->rw; - bio->bi_size = 0; - bio->bi_sector = cmd->sector; - - dst_bio_to_cmd(bio, &priv->cmd, DST_IO_RESPONSE, cmd->id); - - priv->cmd.flags = 0; - priv->cmd.size = cmd->size; - - if (bio_data_dir(bio) == WRITE) { - err = dst_recv_cdata(st, priv->cmd.hash); - if (err) - goto err_out_free; - - err = dst_export_write_request(st, bio, cmd->size); - if (err) - goto err_out_free; - - if (dst_need_crypto(n)) - return dst_export_crypto(n, bio); - } else { - err = dst_export_read_request(bio, cmd->size); - if (err) - goto err_out_free; - } - - dprintk("%s: bio: %llu/%u, rw: %lu, dir: %lu, flags: %lx, phys: %d.\n", - __func__, (u64)bio->bi_sector, bio->bi_size, - bio->bi_rw, bio_data_dir(bio), - bio->bi_flags, bio->bi_phys_segments); - - generic_make_request(bio); - - return 0; - -err_out_free: - bio_put(bio); -err_out_exit: - return err; -} - -/* - * Ok, block IO is ready, let's send it back to the client... - */ -int dst_export_send_bio(struct bio *bio) -{ - struct dst_export_priv *p = bio->bi_private; - struct dst_state *st = p->state; - struct dst_cmd *cmd = &p->cmd; - int err; - - dprintk("%s: id: %llu, bio: %llu/%u, csize: %u, flags: %lu, rw: %lu.\n", - __func__, cmd->id, (u64)bio->bi_sector, bio->bi_size, - cmd->csize, bio->bi_flags, bio->bi_rw); - - dst_convert_cmd(cmd); - - dst_state_lock(st); - if (!st->socket) { - err = -ECONNRESET; - goto err_out_unlock; - } - - if (bio_data_dir(bio) == WRITE) { - /* ... or just confirmation that writing has completed. */ - cmd->size = cmd->csize = 0; - err = dst_data_send_header(st->socket, cmd, - sizeof(struct dst_cmd), 0); - if (err) - goto err_out_unlock; - } else { - err = dst_send_bio(st, cmd, bio); - if (err) - goto err_out_unlock; - } - - dst_state_unlock(st); - - bio_put(bio); - return 0; - -err_out_unlock: - dst_state_unlock(st); - - bio_put(bio); - return err; -} diff --git a/drivers/staging/dst/state.c b/drivers/staging/dst/state.c deleted file mode 100644 index 02a05e6c48c..00000000000 --- a/drivers/staging/dst/state.c +++ /dev/null @@ -1,844 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov - * All rights reserved. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* - * Polling machinery. - */ - -struct dst_poll_helper { - poll_table pt; - struct dst_state *st; -}; - -static int dst_queue_wake(wait_queue_t *wait, unsigned mode, - int sync, void *key) -{ - struct dst_state *st = container_of(wait, struct dst_state, wait); - - wake_up(&st->thread_wait); - return 1; -} - -static void dst_queue_func(struct file *file, wait_queue_head_t *whead, - poll_table *pt) -{ - struct dst_state *st = container_of(pt, struct dst_poll_helper, pt)->st; - - st->whead = whead; - init_waitqueue_func_entry(&st->wait, dst_queue_wake); - add_wait_queue(whead, &st->wait); -} - -void dst_poll_exit(struct dst_state *st) -{ - if (st->whead) { - remove_wait_queue(st->whead, &st->wait); - st->whead = NULL; - } -} - -int dst_poll_init(struct dst_state *st) -{ - struct dst_poll_helper ph; - - ph.st = st; - init_poll_funcptr(&ph.pt, &dst_queue_func); - - st->socket->ops->poll(NULL, st->socket, &ph.pt); - return 0; -} - -/* - * Header receiving function - may block. - */ -static int dst_data_recv_header(struct socket *sock, - void *data, unsigned int size, int block) -{ - struct msghdr msg; - struct kvec iov; - int err; - - iov.iov_base = data; - iov.iov_len = size; - - msg.msg_iov = (struct iovec *)&iov; - msg.msg_iovlen = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = (block) ? MSG_WAITALL : MSG_DONTWAIT; - - err = kernel_recvmsg(sock, &msg, &iov, 1, iov.iov_len, - msg.msg_flags); - if (err != size) - return -1; - - return 0; -} - -/* - * Header sending function - may block. - */ -int dst_data_send_header(struct socket *sock, - void *data, unsigned int size, int more) -{ - struct msghdr msg; - struct kvec iov; - int err; - - iov.iov_base = data; - iov.iov_len = size; - - msg.msg_iov = (struct iovec *)&iov; - msg.msg_iovlen = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_WAITALL | (more ? MSG_MORE : 0); - - err = kernel_sendmsg(sock, &msg, &iov, 1, iov.iov_len); - if (err != size) { - dprintk("%s: size: %u, more: %d, err: %d.\n", - __func__, size, more, err); - return -1; - } - - return 0; -} - -/* - * Block autoconfiguration: request size of the storage and permissions. - */ -static int dst_request_remote_config(struct dst_state *st) -{ - struct dst_node *n = st->node; - int err = -EINVAL; - struct dst_cmd *cmd = st->data; - - memset(cmd, 0, sizeof(struct dst_cmd)); - cmd->cmd = DST_CFG; - - dst_convert_cmd(cmd); - - err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); - if (err) - goto out; - - err = dst_data_recv_header(st->socket, cmd, sizeof(struct dst_cmd), 1); - if (err) - goto out; - - dst_convert_cmd(cmd); - - if (cmd->cmd != DST_CFG) { - err = -EINVAL; - dprintk("%s: checking result: cmd: %d, size reported: %llu.\n", - __func__, cmd->cmd, cmd->sector); - goto out; - } - - if (n->size != 0) - n->size = min_t(loff_t, n->size, cmd->sector); - else - n->size = cmd->sector; - - n->info->size = n->size; - st->permissions = cmd->rw; - -out: - dprintk("%s: n: %p, err: %d, size: %llu, permission: %x.\n", - __func__, n, err, n->size, st->permissions); - return err; -} - -/* - * Socket machinery. - */ - -#define DST_DEFAULT_TIMEO 20000 - -int dst_state_socket_create(struct dst_state *st) -{ - int err; - struct socket *sock; - struct dst_network_ctl *ctl = &st->ctl; - - err = sock_create(ctl->addr.sa_family, ctl->type, ctl->proto, &sock); - if (err < 0) - return err; - - sock->sk->sk_sndtimeo = sock->sk->sk_rcvtimeo = - msecs_to_jiffies(DST_DEFAULT_TIMEO); - sock->sk->sk_allocation = GFP_NOIO; - - st->socket = st->read_socket = sock; - return 0; -} - -void dst_state_socket_release(struct dst_state *st) -{ - dprintk("%s: st: %p, socket: %p, n: %p.\n", - __func__, st, st->socket, st->node); - if (st->socket) { - sock_release(st->socket); - st->socket = NULL; - st->read_socket = NULL; - } -} - -void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str) -{ - if (sk->ops->family == AF_INET) { - struct sockaddr_in *sin = (struct sockaddr_in *)sa; - printk(KERN_INFO "%s %u.%u.%u.%u:%d.\n", str, - NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); - } else if (sk->ops->family == AF_INET6) { - struct sockaddr_in6 *sin = (struct sockaddr_in6 *)sa; - printk(KERN_INFO "%s %pi6:%d", - str, &sin->sin6_addr, ntohs(sin->sin6_port)); - } -} - -void dst_state_exit_connected(struct dst_state *st) -{ - if (st->socket) { - dst_poll_exit(st); - st->socket->ops->shutdown(st->socket, 2); - - dst_dump_addr(st->socket, (struct sockaddr *)&st->ctl.addr, - "Disconnected peer"); - dst_state_socket_release(st); - } -} - -static int dst_state_init_connected(struct dst_state *st) -{ - int err; - struct dst_network_ctl *ctl = &st->ctl; - - err = dst_state_socket_create(st); - if (err) - goto err_out_exit; - - err = kernel_connect(st->socket, (struct sockaddr *)&st->ctl.addr, - st->ctl.addr.sa_data_len, 0); - if (err) - goto err_out_release; - - err = dst_poll_init(st); - if (err) - goto err_out_release; - - dst_dump_addr(st->socket, (struct sockaddr *)&ctl->addr, - "Connected to peer"); - - return 0; - -err_out_release: - dst_state_socket_release(st); -err_out_exit: - return err; -} - -/* - * State reset is used to reconnect to the remote peer. - * May fail, but who cares, we will try again later. - */ -static inline void dst_state_reset_nolock(struct dst_state *st) -{ - dst_state_exit_connected(st); - dst_state_init_connected(st); -} - -static inline void dst_state_reset(struct dst_state *st) -{ - dst_state_lock(st); - dst_state_reset_nolock(st); - dst_state_unlock(st); -} - -/* - * Basic network sending/receiving functions. - * Blocked mode is used. - */ -static int dst_data_recv_raw(struct dst_state *st, void *buf, u64 size) -{ - struct msghdr msg; - struct kvec iov; - int err; - - BUG_ON(!size); - - iov.iov_base = buf; - iov.iov_len = size; - - msg.msg_iov = (struct iovec *)&iov; - msg.msg_iovlen = 1; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = MSG_DONTWAIT; - - err = kernel_recvmsg(st->socket, &msg, &iov, 1, iov.iov_len, - msg.msg_flags); - if (err <= 0) { - dprintk("%s: failed to recv data: size: %llu, err: %d.\n", - __func__, size, err); - if (err == 0) - err = -ECONNRESET; - - dst_state_exit_connected(st); - } - - return err; -} - -/* - * Ping command to early detect failed nodes. - */ -static int dst_send_ping(struct dst_state *st) -{ - struct dst_cmd *cmd = st->data; - int err = -ECONNRESET; - - dst_state_lock(st); - if (st->socket) { - memset(cmd, 0, sizeof(struct dst_cmd)); - - cmd->cmd = __cpu_to_be32(DST_PING); - - err = dst_data_send_header(st->socket, cmd, - sizeof(struct dst_cmd), 0); - } - dprintk("%s: st: %p, socket: %p, err: %d.\n", __func__, - st, st->socket, err); - dst_state_unlock(st); - - return err; -} - -/* - * Receiving function, which should either return error or read - * whole block request. If there was no traffic for a one second, - * send a ping, since remote node may die. - */ -int dst_data_recv(struct dst_state *st, void *data, unsigned int size) -{ - unsigned int revents = 0; - unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP; - unsigned int mask = err_mask | POLLIN; - struct dst_node *n = st->node; - int err = 0; - - while (size && !err) { - revents = dst_state_poll(st); - - if (!(revents & mask)) { - DEFINE_WAIT(wait); - - for (;;) { - prepare_to_wait(&st->thread_wait, &wait, - TASK_INTERRUPTIBLE); - if (!n->trans_scan_timeout || st->need_exit) - break; - - revents = dst_state_poll(st); - - if (revents & mask) - break; - - if (signal_pending(current)) - break; - - if (!schedule_timeout(HZ)) { - err = dst_send_ping(st); - if (err) - return err; - } - - continue; - } - finish_wait(&st->thread_wait, &wait); - } - - err = -ECONNRESET; - dst_state_lock(st); - - if (st->socket && (st->read_socket == st->socket) && - (revents & POLLIN)) { - err = dst_data_recv_raw(st, data, size); - if (err > 0) { - data += err; - size -= err; - err = 0; - } - } - - if (revents & err_mask || !st->socket) { - dprintk("%s: revents: %x, socket: %p, size: %u, " - "err: %d.\n", __func__, revents, - st->socket, size, err); - err = -ECONNRESET; - } - - dst_state_unlock(st); - - if (!n->trans_scan_timeout) - err = -ENODEV; - } - - return err; -} - -/* - * Send block autoconf reply. - */ -static int dst_process_cfg(struct dst_state *st) -{ - struct dst_node *n = st->node; - struct dst_cmd *cmd = st->data; - int err; - - cmd->sector = n->size; - cmd->rw = st->permissions; - - dst_convert_cmd(cmd); - - dst_state_lock(st); - err = dst_data_send_header(st->socket, cmd, sizeof(struct dst_cmd), 0); - dst_state_unlock(st); - - return err; -} - -/* - * Receive block IO from the network. - */ -static int dst_recv_bio(struct dst_state *st, struct bio *bio, - unsigned int total_size) -{ - struct bio_vec *bv; - int i, err; - void *data; - unsigned int sz; - - bio_for_each_segment(bv, bio, i) { - sz = min(total_size, bv->bv_len); - - dprintk("%s: bio: %llu/%u, total: %u, len: %u, sz: %u, " - "off: %u.\n", __func__, (u64)bio->bi_sector, - bio->bi_size, total_size, bv->bv_len, sz, - bv->bv_offset); - - data = kmap(bv->bv_page) + bv->bv_offset; - err = dst_data_recv(st, data, sz); - kunmap(bv->bv_page); - - bv->bv_len = sz; - - if (err) - return err; - - total_size -= sz; - if (total_size == 0) - break; - } - - return 0; -} - -/* - * Our block IO has just completed and arrived: get it. - */ -static int dst_process_io_response(struct dst_state *st) -{ - struct dst_node *n = st->node; - struct dst_cmd *cmd = st->data; - struct dst_trans *t; - int err = 0; - struct bio *bio; - - mutex_lock(&n->trans_lock); - t = dst_trans_search(n, cmd->id); - mutex_unlock(&n->trans_lock); - - if (!t) - goto err_out_exit; - - bio = t->bio; - - dprintk("%s: bio: %llu/%u, cmd_size: %u, csize: %u, dir: %lu.\n", - __func__, (u64)bio->bi_sector, bio->bi_size, cmd->size, - cmd->csize, bio_data_dir(bio)); - - if (bio_data_dir(bio) == READ) { - if (bio->bi_size != cmd->size - cmd->csize) - goto err_out_exit; - - if (dst_need_crypto(n)) { - err = dst_recv_cdata(st, t->cmd.hash); - if (err) - goto err_out_exit; - } - - err = dst_recv_bio(st, t->bio, bio->bi_size); - if (err) - goto err_out_exit; - - if (dst_need_crypto(n)) - return dst_trans_crypto(t); - } else { - err = -EBADMSG; - if (cmd->size || cmd->csize) - goto err_out_exit; - } - - dst_trans_remove(t); - dst_trans_put(t); - - return 0; - -err_out_exit: - return err; -} - -/* - * Receive crypto data. - */ -int dst_recv_cdata(struct dst_state *st, void *cdata) -{ - struct dst_cmd *cmd = st->data; - struct dst_node *n = st->node; - struct dst_crypto_ctl *c = &n->crypto; - int err; - - if (cmd->csize != c->crypto_attached_size) { - dprintk("%s: cmd: cmd: %u, sector: %llu, size: %u, " - "csize: %u != digest size %u.\n", - __func__, cmd->cmd, cmd->sector, cmd->size, - cmd->csize, c->crypto_attached_size); - err = -EINVAL; - goto err_out_exit; - } - - err = dst_data_recv(st, cdata, cmd->csize); - if (err) - goto err_out_exit; - - cmd->size -= cmd->csize; - return 0; - -err_out_exit: - return err; -} - -/* - * Receive the command and start its processing. - */ -static int dst_recv_processing(struct dst_state *st) -{ - int err = -EINTR; - struct dst_cmd *cmd = st->data; - - /* - * If socket will be reset after this statement, then - * dst_data_recv() will just fail and loop will - * start again, so it can be done without any locks. - * - * st->read_socket is needed to prevents state machine - * breaking between this data reading and subsequent one - * in protocol specific functions during connection reset. - * In case of reset we have to read next command and do - * not expect data for old command to magically appear in - * new connection. - */ - st->read_socket = st->socket; - err = dst_data_recv(st, cmd, sizeof(struct dst_cmd)); - if (err) - goto out_exit; - - dst_convert_cmd(cmd); - - dprintk("%s: cmd: %u, size: %u, csize: %u, id: %llu, " - "sector: %llu, flags: %llx, rw: %llx.\n", - __func__, cmd->cmd, cmd->size, - cmd->csize, cmd->id, cmd->sector, - cmd->flags, cmd->rw); - - /* - * This should catch protocol breakage and random garbage - * instead of commands. - */ - if (unlikely(cmd->csize > st->size - sizeof(struct dst_cmd))) { - err = -EBADMSG; - goto out_exit; - } - - err = -EPROTO; - switch (cmd->cmd) { - case DST_IO_RESPONSE: - err = dst_process_io_response(st); - break; - case DST_IO: - err = dst_process_io(st); - break; - case DST_CFG: - err = dst_process_cfg(st); - break; - case DST_PING: - err = 0; - break; - default: - break; - } - -out_exit: - return err; -} - -/* - * Receiving thread. For the client node we should try to reconnect, - * for accepted client we just drop the state and expect it to reconnect. - */ -static int dst_recv(void *init_data, void *schedule_data) -{ - struct dst_state *st = schedule_data; - struct dst_node *n = init_data; - int err = 0; - - dprintk("%s: start st: %p, n: %p, scan: %lu, need_exit: %d.\n", - __func__, st, n, n->trans_scan_timeout, st->need_exit); - - while (n->trans_scan_timeout && !st->need_exit) { - err = dst_recv_processing(st); - if (err < 0) { - if (!st->ctl.type) - break; - - if (!n->trans_scan_timeout || st->need_exit) - break; - - dst_state_reset(st); - msleep(1000); - } - } - - st->need_exit = 1; - wake_up(&st->thread_wait); - - dprintk("%s: freeing receiving socket st: %p.\n", __func__, st); - dst_state_lock(st); - dst_state_exit_connected(st); - dst_state_unlock(st); - dst_state_put(st); - - dprintk("%s: freed receiving socket st: %p.\n", __func__, st); - - return err; -} - -/* - * Network state dies here and borns couple of lines below. - * This object is the main network state processing engine: - * sending, receiving, reconnections, all network related - * tasks are handled on behalf of the state. - */ -static void dst_state_free(struct dst_state *st) -{ - dprintk("%s: st: %p.\n", __func__, st); - if (st->cleanup) - st->cleanup(st); - kfree(st->data); - kfree(st); -} - -struct dst_state *dst_state_alloc(struct dst_node *n) -{ - struct dst_state *st; - int err = -ENOMEM; - - st = kzalloc(sizeof(struct dst_state), GFP_KERNEL); - if (!st) - goto err_out_exit; - - st->node = n; - st->need_exit = 0; - - st->size = PAGE_SIZE; - st->data = kmalloc(st->size, GFP_KERNEL); - if (!st->data) - goto err_out_free; - - spin_lock_init(&st->request_lock); - INIT_LIST_HEAD(&st->request_list); - - mutex_init(&st->state_lock); - init_waitqueue_head(&st->thread_wait); - - /* - * One for processing thread, another one for node itself. - */ - atomic_set(&st->refcnt, 2); - - dprintk("%s: st: %p, n: %p.\n", __func__, st, st->node); - - return st; - -err_out_free: - kfree(st); -err_out_exit: - return ERR_PTR(err); -} - -int dst_state_schedule_receiver(struct dst_state *st) -{ - return thread_pool_schedule_private(st->node->pool, dst_thread_setup, - dst_recv, st, MAX_SCHEDULE_TIMEOUT, st->node); -} - -/* - * Initialize client's connection to the remote peer: allocate state, - * connect and perform block IO autoconfiguration. - */ -int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r) -{ - struct dst_state *st; - int err = -ENOMEM; - - st = dst_state_alloc(n); - if (IS_ERR(st)) { - err = PTR_ERR(st); - goto err_out_exit; - } - memcpy(&st->ctl, r, sizeof(struct dst_network_ctl)); - - err = dst_state_init_connected(st); - if (err) - goto err_out_free_data; - - err = dst_request_remote_config(st); - if (err) - goto err_out_exit_connected; - n->state = st; - - err = dst_state_schedule_receiver(st); - if (err) - goto err_out_exit_connected; - - return 0; - -err_out_exit_connected: - dst_state_exit_connected(st); -err_out_free_data: - dst_state_free(st); -err_out_exit: - n->state = NULL; - return err; -} - -void dst_state_put(struct dst_state *st) -{ - dprintk("%s: st: %p, refcnt: %d.\n", - __func__, st, atomic_read(&st->refcnt)); - if (atomic_dec_and_test(&st->refcnt)) - dst_state_free(st); -} - -/* - * Send block IO to the network one by one using zero-copy ->sendpage(). - */ -int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio) -{ - struct bio_vec *bv; - struct dst_crypto_ctl *c = &st->node->crypto; - int err, i = 0; - int flags = MSG_WAITALL; - - err = dst_data_send_header(st->socket, cmd, - sizeof(struct dst_cmd) + c->crypto_attached_size, bio->bi_vcnt); - if (err) - goto err_out_exit; - - bio_for_each_segment(bv, bio, i) { - if (i < bio->bi_vcnt - 1) - flags |= MSG_MORE; - - err = kernel_sendpage(st->socket, bv->bv_page, bv->bv_offset, - bv->bv_len, flags); - if (err <= 0) - goto err_out_exit; - } - - return 0; - -err_out_exit: - dprintk("%s: %d/%d, flags: %x, err: %d.\n", - __func__, i, bio->bi_vcnt, flags, err); - return err; -} - -/* - * Send transaction to the remote peer. - */ -int dst_trans_send(struct dst_trans *t) -{ - int err; - struct dst_state *st = t->n->state; - struct bio *bio = t->bio; - - dst_convert_cmd(&t->cmd); - - dst_state_lock(st); - if (!st->socket) { - err = dst_state_init_connected(st); - if (err) - goto err_out_unlock; - } - - if (bio_data_dir(bio) == WRITE) { - err = dst_send_bio(st, &t->cmd, t->bio); - } else { - err = dst_data_send_header(st->socket, &t->cmd, - sizeof(struct dst_cmd), 0); - } - if (err) - goto err_out_reset; - - dst_state_unlock(st); - return 0; - -err_out_reset: - dst_state_reset_nolock(st); -err_out_unlock: - dst_state_unlock(st); - - return err; -} diff --git a/drivers/staging/dst/thread_pool.c b/drivers/staging/dst/thread_pool.c deleted file mode 100644 index 29a82b2602f..00000000000 --- a/drivers/staging/dst/thread_pool.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov - * All rights reserved. - * - * 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. - */ - -#include -#include -#include -#include - -/* - * Thread pool abstraction allows to schedule a work to be performed - * on behalf of kernel thread. One does not operate with threads itself, - * instead user provides setup and cleanup callbacks for thread pool itself, - * and action and cleanup callbacks for each submitted work. - * - * Each worker has private data initialized at creation time and data, - * provided by user at scheduling time. - * - * When action is being performed, thread can not be used by other users, - * instead they will sleep until there is free thread to pick their work. - */ -struct thread_pool_worker { - struct list_head worker_entry; - - struct task_struct *thread; - - struct thread_pool *pool; - - int error; - int has_data; - int need_exit; - unsigned int id; - - wait_queue_head_t wait; - - void *private; - void *schedule_data; - - int (*action)(void *private, void *schedule_data); - void (*cleanup)(void *private); -}; - -static void thread_pool_exit_worker(struct thread_pool_worker *w) -{ - kthread_stop(w->thread); - - w->cleanup(w->private); - kfree(w); -} - -/* - * Called to mark thread as ready and allow users to schedule new work. - */ -static void thread_pool_worker_make_ready(struct thread_pool_worker *w) -{ - struct thread_pool *p = w->pool; - - mutex_lock(&p->thread_lock); - - if (!w->need_exit) { - list_move_tail(&w->worker_entry, &p->ready_list); - w->has_data = 0; - mutex_unlock(&p->thread_lock); - - wake_up(&p->wait); - } else { - p->thread_num--; - list_del(&w->worker_entry); - mutex_unlock(&p->thread_lock); - - thread_pool_exit_worker(w); - } -} - -/* - * Thread action loop: waits until there is new work. - */ -static int thread_pool_worker_func(void *data) -{ - struct thread_pool_worker *w = data; - - while (!kthread_should_stop()) { - wait_event_interruptible(w->wait, - kthread_should_stop() || w->has_data); - - if (kthread_should_stop()) - break; - - if (!w->has_data) - continue; - - w->action(w->private, w->schedule_data); - thread_pool_worker_make_ready(w); - } - - return 0; -} - -/* - * Remove single worker without specifying which one. - */ -void thread_pool_del_worker(struct thread_pool *p) -{ - struct thread_pool_worker *w = NULL; - - while (!w && p->thread_num) { - wait_event(p->wait, !list_empty(&p->ready_list) || - !p->thread_num); - - dprintk("%s: locking list_empty: %d, thread_num: %d.\n", - __func__, list_empty(&p->ready_list), - p->thread_num); - - mutex_lock(&p->thread_lock); - if (!list_empty(&p->ready_list)) { - w = list_first_entry(&p->ready_list, - struct thread_pool_worker, - worker_entry); - - dprintk("%s: deleting w: %p, thread_num: %d, " - "list: %p [%p.%p].\n", __func__, - w, p->thread_num, &p->ready_list, - p->ready_list.prev, p->ready_list.next); - - p->thread_num--; - list_del(&w->worker_entry); - } - mutex_unlock(&p->thread_lock); - } - - if (w) - thread_pool_exit_worker(w); - dprintk("%s: deleted w: %p, thread_num: %d.\n", - __func__, w, p->thread_num); -} - -/* - * Remove a worker with given ID. - */ -void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id) -{ - struct thread_pool_worker *w; - int found = 0; - - mutex_lock(&p->thread_lock); - list_for_each_entry(w, &p->ready_list, worker_entry) { - if (w->id == id) { - found = 1; - p->thread_num--; - list_del(&w->worker_entry); - break; - } - } - - if (!found) { - list_for_each_entry(w, &p->active_list, worker_entry) { - if (w->id == id) { - w->need_exit = 1; - break; - } - } - } - mutex_unlock(&p->thread_lock); - - if (found) - thread_pool_exit_worker(w); -} - -/* - * Add new worker thread with given parameters. - * If initialization callback fails, return error. - */ -int thread_pool_add_worker(struct thread_pool *p, - char *name, - unsigned int id, - void *(*init)(void *private), - void (*cleanup)(void *private), - void *private) -{ - struct thread_pool_worker *w; - int err = -ENOMEM; - - w = kzalloc(sizeof(struct thread_pool_worker), GFP_KERNEL); - if (!w) - goto err_out_exit; - - w->pool = p; - init_waitqueue_head(&w->wait); - w->cleanup = cleanup; - w->id = id; - - w->thread = kthread_run(thread_pool_worker_func, w, "%s", name); - if (IS_ERR(w->thread)) { - err = PTR_ERR(w->thread); - goto err_out_free; - } - - w->private = init(private); - if (IS_ERR(w->private)) { - err = PTR_ERR(w->private); - goto err_out_stop_thread; - } - - mutex_lock(&p->thread_lock); - list_add_tail(&w->worker_entry, &p->ready_list); - p->thread_num++; - mutex_unlock(&p->thread_lock); - - return 0; - -err_out_stop_thread: - kthread_stop(w->thread); -err_out_free: - kfree(w); -err_out_exit: - return err; -} - -/* - * Destroy the whole pool. - */ -void thread_pool_destroy(struct thread_pool *p) -{ - while (p->thread_num) { - dprintk("%s: num: %d.\n", __func__, p->thread_num); - thread_pool_del_worker(p); - } - - kfree(p); -} - -/* - * Create a pool with given number of threads. - * They will have sequential IDs started from zero. - */ -struct thread_pool *thread_pool_create(int num, char *name, - void *(*init)(void *private), - void (*cleanup)(void *private), - void *private) -{ - struct thread_pool_worker *w, *tmp; - struct thread_pool *p; - int err = -ENOMEM; - int i; - - p = kzalloc(sizeof(struct thread_pool), GFP_KERNEL); - if (!p) - goto err_out_exit; - - init_waitqueue_head(&p->wait); - mutex_init(&p->thread_lock); - INIT_LIST_HEAD(&p->ready_list); - INIT_LIST_HEAD(&p->active_list); - p->thread_num = 0; - - for (i = 0; i < num; ++i) { - err = thread_pool_add_worker(p, name, i, init, - cleanup, private); - if (err) - goto err_out_free_all; - } - - return p; - -err_out_free_all: - list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) { - list_del(&w->worker_entry); - thread_pool_exit_worker(w); - } - kfree(p); -err_out_exit: - return ERR_PTR(err); -} - -/* - * Schedule execution of the action on a given thread, - * provided ID pointer has to match previously stored - * private data. - */ -int thread_pool_schedule_private(struct thread_pool *p, - int (*setup)(void *private, void *data), - int (*action)(void *private, void *data), - void *data, long timeout, void *id) -{ - struct thread_pool_worker *w, *tmp, *worker = NULL; - int err = 0; - - while (!worker && !err) { - timeout = wait_event_interruptible_timeout(p->wait, - !list_empty(&p->ready_list), - timeout); - - if (!timeout) { - err = -ETIMEDOUT; - break; - } - - worker = NULL; - mutex_lock(&p->thread_lock); - list_for_each_entry_safe(w, tmp, &p->ready_list, worker_entry) { - if (id && id != w->private) - continue; - - worker = w; - - list_move_tail(&w->worker_entry, &p->active_list); - - err = setup(w->private, data); - if (!err) { - w->schedule_data = data; - w->action = action; - w->has_data = 1; - wake_up(&w->wait); - } else { - list_move_tail(&w->worker_entry, - &p->ready_list); - } - - break; - } - mutex_unlock(&p->thread_lock); - } - - return err; -} - -/* - * Schedule execution on arbitrary thread from the pool. - */ -int thread_pool_schedule(struct thread_pool *p, - int (*setup)(void *private, void *data), - int (*action)(void *private, void *data), - void *data, long timeout) -{ - return thread_pool_schedule_private(p, setup, - action, data, timeout, NULL); -} diff --git a/drivers/staging/dst/trans.c b/drivers/staging/dst/trans.c deleted file mode 100644 index 1c36a6bc31d..00000000000 --- a/drivers/staging/dst/trans.c +++ /dev/null @@ -1,337 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov - * All rights reserved. - * - * 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. - */ - -#include -#include -#include -#include - -/* - * Transaction memory pool size. - */ -static int dst_mempool_num = 32; -module_param(dst_mempool_num, int, 0644); - -/* - * Transaction tree management. - */ -static inline int dst_trans_cmp(dst_gen_t gen, dst_gen_t new) -{ - if (gen < new) - return 1; - if (gen > new) - return -1; - return 0; -} - -struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen) -{ - struct rb_root *root = &node->trans_root; - struct rb_node *n = root->rb_node; - struct dst_trans *t, *ret = NULL; - int cmp; - - while (n) { - t = rb_entry(n, struct dst_trans, trans_entry); - - cmp = dst_trans_cmp(t->gen, gen); - if (cmp < 0) - n = n->rb_left; - else if (cmp > 0) - n = n->rb_right; - else { - ret = t; - break; - } - } - - dprintk("%s: %s transaction: id: %llu.\n", __func__, - (ret) ? "found" : "not found", gen); - - return ret; -} - -static int dst_trans_insert(struct dst_trans *new) -{ - struct rb_root *root = &new->n->trans_root; - struct rb_node **n = &root->rb_node, *parent = NULL; - struct dst_trans *ret = NULL, *t; - int cmp; - - while (*n) { - parent = *n; - - t = rb_entry(parent, struct dst_trans, trans_entry); - - cmp = dst_trans_cmp(t->gen, new->gen); - if (cmp < 0) - n = &parent->rb_left; - else if (cmp > 0) - n = &parent->rb_right; - else { - ret = t; - break; - } - } - - new->send_time = jiffies; - if (ret) { - printk(KERN_DEBUG "%s: exist: old: gen: %llu, bio: %llu/%u, " - "send_time: %lu, new: gen: %llu, bio: %llu/%u, " - "send_time: %lu.\n", __func__, - ret->gen, (u64)ret->bio->bi_sector, - ret->bio->bi_size, ret->send_time, - new->gen, (u64)new->bio->bi_sector, - new->bio->bi_size, new->send_time); - return -EEXIST; - } - - rb_link_node(&new->trans_entry, parent, n); - rb_insert_color(&new->trans_entry, root); - - dprintk("%s: inserted: gen: %llu, bio: %llu/%u, send_time: %lu.\n", - __func__, new->gen, (u64)new->bio->bi_sector, - new->bio->bi_size, new->send_time); - - return 0; -} - -int dst_trans_remove_nolock(struct dst_trans *t) -{ - struct dst_node *n = t->n; - - if (t->trans_entry.rb_parent_color) { - rb_erase(&t->trans_entry, &n->trans_root); - t->trans_entry.rb_parent_color = 0; - } - return 0; -} - -int dst_trans_remove(struct dst_trans *t) -{ - int ret; - struct dst_node *n = t->n; - - mutex_lock(&n->trans_lock); - ret = dst_trans_remove_nolock(t); - mutex_unlock(&n->trans_lock); - - return ret; -} - -/* - * When transaction is completed and there are no more users, - * we complete appriate block IO request with given error status. - */ -void dst_trans_put(struct dst_trans *t) -{ - if (atomic_dec_and_test(&t->refcnt)) { - struct bio *bio = t->bio; - - dprintk("%s: completed t: %p, gen: %llu, bio: %p.\n", - __func__, t, t->gen, bio); - - bio_endio(bio, t->error); - bio_put(bio); - - dst_node_put(t->n); - mempool_free(t, t->n->trans_pool); - } -} - -/* - * Process given block IO request: allocate transaction, insert it into the tree - * and send/schedule crypto processing. - */ -int dst_process_bio(struct dst_node *n, struct bio *bio) -{ - struct dst_trans *t; - int err = -ENOMEM; - - t = mempool_alloc(n->trans_pool, GFP_NOFS); - if (!t) - goto err_out_exit; - - t->n = dst_node_get(n); - t->bio = bio; - t->error = 0; - t->retries = 0; - atomic_set(&t->refcnt, 1); - t->gen = atomic_long_inc_return(&n->gen); - - t->enc = bio_data_dir(bio); - dst_bio_to_cmd(bio, &t->cmd, DST_IO, t->gen); - - mutex_lock(&n->trans_lock); - err = dst_trans_insert(t); - mutex_unlock(&n->trans_lock); - if (err) - goto err_out_free; - - dprintk("%s: gen: %llu, bio: %llu/%u, dir/enc: %d, need_crypto: %d.\n", - __func__, t->gen, (u64)bio->bi_sector, - bio->bi_size, t->enc, dst_need_crypto(n)); - - if (dst_need_crypto(n) && t->enc) - dst_trans_crypto(t); - else - dst_trans_send(t); - - return 0; - -err_out_free: - dst_node_put(n); - mempool_free(t, n->trans_pool); -err_out_exit: - bio_endio(bio, err); - bio_put(bio); - return err; -} - -/* - * Scan for timeout/stale transactions. - * Each transaction is being resent multiple times before error completion. - */ -static void dst_trans_scan(struct work_struct *work) -{ - struct dst_node *n = container_of(work, struct dst_node, - trans_work.work); - struct rb_node *rb_node; - struct dst_trans *t; - unsigned long timeout = n->trans_scan_timeout; - int num = 10 * n->trans_max_retries; - - mutex_lock(&n->trans_lock); - - for (rb_node = rb_first(&n->trans_root); rb_node; ) { - t = rb_entry(rb_node, struct dst_trans, trans_entry); - - if (timeout && time_after(t->send_time + timeout, jiffies) - && t->retries == 0) - break; -#if 0 - dprintk("%s: t: %p, gen: %llu, n: %s, retries: %u, max: %u.\n", - __func__, t, t->gen, n->name, - t->retries, n->trans_max_retries); -#endif - if (--num == 0) - break; - - dst_trans_get(t); - - rb_node = rb_next(rb_node); - - if (timeout && (++t->retries < n->trans_max_retries)) { - dst_trans_send(t); - } else { - t->error = -ETIMEDOUT; - dst_trans_remove_nolock(t); - dst_trans_put(t); - } - - dst_trans_put(t); - } - - mutex_unlock(&n->trans_lock); - - /* - * If no timeout specified then system is in the middle of exiting - * process, so no need to reschedule scanning process again. - */ - if (timeout) { - if (!num) - timeout = HZ; - schedule_delayed_work(&n->trans_work, timeout); - } -} - -/* - * Flush all transactions and mark them as timed out. - * Destroy transaction pools. - */ -void dst_node_trans_exit(struct dst_node *n) -{ - struct dst_trans *t; - struct rb_node *rb_node; - - if (!n->trans_cache) - return; - - dprintk("%s: n: %p, cancelling the work.\n", __func__, n); - cancel_delayed_work_sync(&n->trans_work); - flush_scheduled_work(); - dprintk("%s: n: %p, work has been cancelled.\n", __func__, n); - - for (rb_node = rb_first(&n->trans_root); rb_node; ) { - t = rb_entry(rb_node, struct dst_trans, trans_entry); - - dprintk("%s: t: %p, gen: %llu, n: %s.\n", - __func__, t, t->gen, n->name); - - rb_node = rb_next(rb_node); - - t->error = -ETIMEDOUT; - dst_trans_remove_nolock(t); - dst_trans_put(t); - } - - mempool_destroy(n->trans_pool); - kmem_cache_destroy(n->trans_cache); -} - -/* - * Initialize transaction storage for given node. - * Transaction stores not only control information, - * but also network command and crypto data (if needed) - * to reduce number of allocations. Thus transaction size - * differs from node to node. - */ -int dst_node_trans_init(struct dst_node *n, unsigned int size) -{ - /* - * We need this, since node with given name can be dropped from the - * hash table, but be still alive, so subsequent creation of the node - * with the same name may collide with existing cache name. - */ - - snprintf(n->cache_name, sizeof(n->cache_name), "%s-%p", n->name, n); - - n->trans_cache = kmem_cache_create(n->cache_name, - size + n->crypto.crypto_attached_size, - 0, 0, NULL); - if (!n->trans_cache) - goto err_out_exit; - - n->trans_pool = mempool_create_slab_pool(dst_mempool_num, - n->trans_cache); - if (!n->trans_pool) - goto err_out_cache_destroy; - - mutex_init(&n->trans_lock); - n->trans_root = RB_ROOT; - - INIT_DELAYED_WORK(&n->trans_work, dst_trans_scan); - schedule_delayed_work(&n->trans_work, n->trans_scan_timeout); - - dprintk("%s: n: %p, size: %u, crypto: %u.\n", - __func__, n, size, n->crypto.crypto_attached_size); - - return 0; - -err_out_cache_destroy: - kmem_cache_destroy(n->trans_cache); -err_out_exit: - return -ENOMEM; -} diff --git a/include/linux/dst.h b/include/linux/dst.h deleted file mode 100644 index e26fed84b1a..00000000000 --- a/include/linux/dst.h +++ /dev/null @@ -1,587 +0,0 @@ -/* - * 2007+ Copyright (c) Evgeniy Polyakov - * All rights reserved. - * - * 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. - */ - -#ifndef __DST_H -#define __DST_H - -#include -#include - -#define DST_NAMELEN 32 -#define DST_NAME "dst" - -enum { - /* Remove node with given id from storage */ - DST_DEL_NODE = 0, - /* Add remote node with given id to the storage */ - DST_ADD_REMOTE, - /* Add local node with given id to the storage to be exported and used by remote peers */ - DST_ADD_EXPORT, - /* Crypto initialization command (hash/cipher used to protect the connection) */ - DST_CRYPTO, - /* Security attributes for given connection (permissions for example) */ - DST_SECURITY, - /* Register given node in the block layer subsystem */ - DST_START, - DST_CMD_MAX -}; - -struct dst_ctl -{ - /* Storage name */ - char name[DST_NAMELEN]; - /* Command flags */ - __u32 flags; - /* Command itself (see above) */ - __u32 cmd; - /* Maximum number of pages per single request in this device */ - __u32 max_pages; - /* Stale/error transaction scanning timeout in milliseconds */ - __u32 trans_scan_timeout; - /* Maximum number of retry sends before completing transaction as broken */ - __u32 trans_max_retries; - /* Storage size */ - __u64 size; -}; - -/* Reply command carries completion status */ -struct dst_ctl_ack -{ - struct cn_msg msg; - int error; - int unused[3]; -}; - -/* - * Unfortunaltely socket address structure is not exported to userspace - * and is redefined there. - */ -#define SADDR_MAX_DATA 128 - -struct saddr { - /* address family, AF_xxx */ - unsigned short sa_family; - /* 14 bytes of protocol address */ - char sa_data[SADDR_MAX_DATA]; - /* Number of bytes used in sa_data */ - unsigned short sa_data_len; -}; - -/* Address structure */ -struct dst_network_ctl -{ - /* Socket type: datagram, stream...*/ - unsigned int type; - /* Let me guess, is it a Jupiter diameter? */ - unsigned int proto; - /* Peer's address */ - struct saddr addr; -}; - -struct dst_crypto_ctl -{ - /* Cipher and hash names */ - char cipher_algo[DST_NAMELEN]; - char hash_algo[DST_NAMELEN]; - - /* Key sizes. Can be zero for digest for example */ - unsigned int cipher_keysize, hash_keysize; - /* Alignment. Calculated by the DST itself. */ - unsigned int crypto_attached_size; - /* Number of threads to perform crypto operations */ - int thread_num; -}; - -/* Export security attributes have this bits checked in when client connects */ -#define DST_PERM_READ (1<<0) -#define DST_PERM_WRITE (1<<1) - -/* - * Right now it is simple model, where each remote address - * is assigned to set of permissions it is allowed to perform. - * In real world block device does not know anything but - * reading and writing, so it should be more than enough. - */ -struct dst_secure_user -{ - unsigned int permissions; - struct saddr addr; -}; - -/* - * Export control command: device to export and network address to accept - * clients to work with given device - */ -struct dst_export_ctl -{ - char device[DST_NAMELEN]; - struct dst_network_ctl ctl; -}; - -enum { - DST_CFG = 1, /* Request remote configuration */ - DST_IO, /* IO command */ - DST_IO_RESPONSE, /* IO response */ - DST_PING, /* Keepalive message */ - DST_NCMD_MAX, -}; - -struct dst_cmd -{ - /* Network command itself, see above */ - __u32 cmd; - /* - * Size of the attached data - * (in most cases, for READ command it means how many bytes were requested) - */ - __u32 size; - /* Crypto size: number of attached bytes with digest/hmac */ - __u32 csize; - /* Here we can carry secret data */ - __u32 reserved; - /* Read/write bits, see how they are encoded in bio structure */ - __u64 rw; - /* BIO flags */ - __u64 flags; - /* Unique command id (like transaction ID) */ - __u64 id; - /* Sector to start IO from */ - __u64 sector; - /* Hash data is placed after this header */ - __u8 hash[0]; -}; - -/* - * Convert command to/from network byte order. - * We do not use hton*() functions, since there is - * no 64-bit implementation. - */ -static inline void dst_convert_cmd(struct dst_cmd *c) -{ - c->cmd = __cpu_to_be32(c->cmd); - c->csize = __cpu_to_be32(c->csize); - c->size = __cpu_to_be32(c->size); - c->sector = __cpu_to_be64(c->sector); - c->id = __cpu_to_be64(c->id); - c->flags = __cpu_to_be64(c->flags); - c->rw = __cpu_to_be64(c->rw); -} - -/* Transaction id */ -typedef __u64 dst_gen_t; - -#ifdef __KERNEL__ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_DST_DEBUG -#define dprintk(f, a...) printk(KERN_NOTICE f, ##a) -#else -static inline void __attribute__ ((format (printf, 1, 2))) - dprintk(const char *fmt, ...) {} -#endif - -struct dst_node; - -struct dst_trans -{ - /* DST node we are working with */ - struct dst_node *n; - - /* Entry inside transaction tree */ - struct rb_node trans_entry; - - /* Merlin kills this transaction when this memory cell equals zero */ - atomic_t refcnt; - - /* How this transaction should be processed by crypto engine */ - short enc; - /* How many times this transaction was resent */ - short retries; - /* Completion status */ - int error; - - /* When did we send it to the remote peer */ - long send_time; - - /* My name is... - * Well, computers does not speak, they have unique id instead */ - dst_gen_t gen; - - /* Block IO we are working with */ - struct bio *bio; - - /* Network command for above block IO request */ - struct dst_cmd cmd; -}; - -struct dst_crypto_engine -{ - /* What should we do with all block requests */ - struct crypto_hash *hash; - struct crypto_ablkcipher *cipher; - - /* Pool of pages used to encrypt data into before sending */ - int page_num; - struct page **pages; - - /* What to do with current request */ - int enc; - /* Who we are and where do we go */ - struct scatterlist *src, *dst; - - /* Maximum timeout waiting for encryption to be completed */ - long timeout; - /* IV is a 64-bit sequential counter */ - u64 iv; - - /* Secret data */ - void *private; - - /* Cached temporary data lives here */ - int size; - void *data; -}; - -struct dst_state -{ - /* The main state protection */ - struct mutex state_lock; - - /* Polling machinery for sockets */ - wait_queue_t wait; - wait_queue_head_t *whead; - /* Most of events are being waited here */ - wait_queue_head_t thread_wait; - - /* Who owns this? */ - struct dst_node *node; - - /* Network address for this state */ - struct dst_network_ctl ctl; - - /* Permissions to work with: read-only or rw connection */ - u32 permissions; - - /* Called when we need to clean private data */ - void (* cleanup)(struct dst_state *st); - - /* Used by the server: BIO completion queues BIOs here */ - struct list_head request_list; - spinlock_t request_lock; - - /* Guess what? No, it is not number of planets */ - atomic_t refcnt; - - /* This flags is set when connection should be dropped */ - int need_exit; - - /* - * Socket to work with. Second pointer is used for - * lockless check if socket was changed before performing - * next action (like working with cached polling result) - */ - struct socket *socket, *read_socket; - - /* Cached preallocated data */ - void *data; - unsigned int size; - - /* Currently processed command */ - struct dst_cmd cmd; -}; - -struct dst_info -{ - /* Device size */ - u64 size; - - /* Local device name for export devices */ - char local[DST_NAMELEN]; - - /* Network setup */ - struct dst_network_ctl net; - - /* Sysfs bits use this */ - struct device device; -}; - -struct dst_node -{ - struct list_head node_entry; - - /* Hi, my name is stored here */ - char name[DST_NAMELEN]; - /* My cache name is stored here */ - char cache_name[DST_NAMELEN]; - - /* Block device attached to given node. - * Only valid for exporting nodes */ - struct block_device *bdev; - /* Network state machine for given peer */ - struct dst_state *state; - - /* Block IO machinery */ - struct request_queue *queue; - struct gendisk *disk; - - /* Number of threads in processing pool */ - int thread_num; - /* Maximum number of pages in single IO */ - int max_pages; - - /* I'm that big in bytes */ - loff_t size; - - /* Exported to userspace node information */ - struct dst_info *info; - - /* - * Security attribute list. - * Used only by exporting node currently. - */ - struct list_head security_list; - struct mutex security_lock; - - /* - * When this unerflows below zero, university collapses. - * But this will not happen, since node will be freed, - * when reference counter reaches zero. - */ - atomic_t refcnt; - - /* How precisely should I be started? */ - int (*start)(struct dst_node *); - - /* Crypto capabilities */ - struct dst_crypto_ctl crypto; - u8 *hash_key; - u8 *cipher_key; - - /* Pool of processing thread */ - struct thread_pool *pool; - - /* Transaction IDs live here */ - atomic_long_t gen; - - /* - * How frequently and how many times transaction - * tree should be scanned to drop stale objects. - */ - long trans_scan_timeout; - int trans_max_retries; - - /* Small gnomes live here */ - struct rb_root trans_root; - struct mutex trans_lock; - - /* - * Transaction cache/memory pool. - * It is big enough to contain not only transaction - * itself, but additional crypto data (digest/hmac). - */ - struct kmem_cache *trans_cache; - mempool_t *trans_pool; - - /* This entity scans transaction tree */ - struct delayed_work trans_work; - - wait_queue_head_t wait; -}; - -/* Kernel representation of the security attribute */ -struct dst_secure -{ - struct list_head sec_entry; - struct dst_secure_user sec; -}; - -int dst_process_bio(struct dst_node *n, struct bio *bio); - -int dst_node_init_connected(struct dst_node *n, struct dst_network_ctl *r); -int dst_node_init_listened(struct dst_node *n, struct dst_export_ctl *le); - -static inline struct dst_state *dst_state_get(struct dst_state *st) -{ - BUG_ON(atomic_read(&st->refcnt) == 0); - atomic_inc(&st->refcnt); - return st; -} - -void dst_state_put(struct dst_state *st); - -struct dst_state *dst_state_alloc(struct dst_node *n); -int dst_state_socket_create(struct dst_state *st); -void dst_state_socket_release(struct dst_state *st); - -void dst_state_exit_connected(struct dst_state *st); - -int dst_state_schedule_receiver(struct dst_state *st); - -void dst_dump_addr(struct socket *sk, struct sockaddr *sa, char *str); - -static inline void dst_state_lock(struct dst_state *st) -{ - mutex_lock(&st->state_lock); -} - -static inline void dst_state_unlock(struct dst_state *st) -{ - mutex_unlock(&st->state_lock); -} - -void dst_poll_exit(struct dst_state *st); -int dst_poll_init(struct dst_state *st); - -static inline unsigned int dst_state_poll(struct dst_state *st) -{ - unsigned int revents = POLLHUP | POLLERR; - - dst_state_lock(st); - if (st->socket) - revents = st->socket->ops->poll(NULL, st->socket, NULL); - dst_state_unlock(st); - - return revents; -} - -static inline int dst_thread_setup(void *private, void *data) -{ - return 0; -} - -void dst_node_put(struct dst_node *n); - -static inline struct dst_node *dst_node_get(struct dst_node *n) -{ - atomic_inc(&n->refcnt); - return n; -} - -int dst_data_recv(struct dst_state *st, void *data, unsigned int size); -int dst_recv_cdata(struct dst_state *st, void *cdata); -int dst_data_send_header(struct socket *sock, - void *data, unsigned int size, int more); - -int dst_send_bio(struct dst_state *st, struct dst_cmd *cmd, struct bio *bio); - -int dst_process_io(struct dst_state *st); -int dst_export_crypto(struct dst_node *n, struct bio *bio); -int dst_export_send_bio(struct bio *bio); -int dst_start_export(struct dst_node *n); - -int __init dst_export_init(void); -void dst_export_exit(void); - -/* Private structure for export block IO requests */ -struct dst_export_priv -{ - struct list_head request_entry; - struct dst_state *state; - struct bio *bio; - struct dst_cmd cmd; -}; - -static inline void dst_trans_get(struct dst_trans *t) -{ - atomic_inc(&t->refcnt); -} - -struct dst_trans *dst_trans_search(struct dst_node *node, dst_gen_t gen); -int dst_trans_remove(struct dst_trans *t); -int dst_trans_remove_nolock(struct dst_trans *t); -void dst_trans_put(struct dst_trans *t); - -/* - * Convert bio into network command. - */ -static inline void dst_bio_to_cmd(struct bio *bio, struct dst_cmd *cmd, - u32 command, u64 id) -{ - cmd->cmd = command; - cmd->flags = (bio->bi_flags << BIO_POOL_BITS) >> BIO_POOL_BITS; - cmd->rw = bio->bi_rw; - cmd->size = bio->bi_size; - cmd->csize = 0; - cmd->id = id; - cmd->sector = bio->bi_sector; -}; - -int dst_trans_send(struct dst_trans *t); -int dst_trans_crypto(struct dst_trans *t); - -int dst_node_crypto_init(struct dst_node *n, struct dst_crypto_ctl *ctl); -void dst_node_crypto_exit(struct dst_node *n); - -static inline int dst_need_crypto(struct dst_node *n) -{ - struct dst_crypto_ctl *c = &n->crypto; - /* - * Logical OR is appropriate here, but boolean one produces - * more optimal code, so it is used instead. - */ - return (c->hash_algo[0] | c->cipher_algo[0]); -} - -int dst_node_trans_init(struct dst_node *n, unsigned int size); -void dst_node_trans_exit(struct dst_node *n); - -/* - * Pool of threads. - * Ready list contains threads currently free to be used, - * active one contains threads with some work scheduled for them. - * Caller can wait in given queue when thread is ready. - */ -struct thread_pool -{ - int thread_num; - struct mutex thread_lock; - struct list_head ready_list, active_list; - - wait_queue_head_t wait; -}; - -void thread_pool_del_worker(struct thread_pool *p); -void thread_pool_del_worker_id(struct thread_pool *p, unsigned int id); -int thread_pool_add_worker(struct thread_pool *p, - char *name, - unsigned int id, - void *(* init)(void *data), - void (* cleanup)(void *data), - void *data); - -void thread_pool_destroy(struct thread_pool *p); -struct thread_pool *thread_pool_create(int num, char *name, - void *(* init)(void *data), - void (* cleanup)(void *data), - void *data); - -int thread_pool_schedule(struct thread_pool *p, - int (* setup)(void *stored_private, void *setup_data), - int (* action)(void *stored_private, void *setup_data), - void *setup_data, long timeout); -int thread_pool_schedule_private(struct thread_pool *p, - int (* setup)(void *private, void *data), - int (* action)(void *private, void *data), - void *data, long timeout, void *id); - -#endif /* __KERNEL__ */ -#endif /* __DST_H */ -- cgit v1.2.3-70-g09d2 From d4c3a56587af3edbe5f618b20e800e9f9fde13cb Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Fri, 27 Nov 2009 12:00:53 +0000 Subject: Staging: comedi: usbdux.c: fix locking up of the driver when the comedi ringbuffer runs empty Jan-Matthias Braun spotted a bug which locks up the driver when the comedi ring buffer runs empty and provided a patch. The driver would still send the data to comedi but the reader won't wake up any more. What's required is setting the flag COMEDI_CB_BLOCK after new data has arrived which wakes up the reader and therefore the read() command. Signed-off-by: Bernd Porr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/usbdux.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 06c02046629..9a1b559c4b0 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c @@ -1,4 +1,4 @@ -#define DRIVER_VERSION "v2.3" +#define DRIVER_VERSION "v2.4" #define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" #define DRIVER_DESC "Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com" /* @@ -81,6 +81,8 @@ sampling rate. If you sample two channels you get 4kHz and so on. * 2.1: changed PWM API * 2.2: added firmware kernel request to fix an udev problem * 2.3: corrected a bug in bulk timeouts which were far too short + * 2.4: fixed a bug which causes the driver to hang when it ran out of data. + * Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it. * */ @@ -532,6 +534,7 @@ static void usbduxsub_ai_IsocIrq(struct urb *urb) } } /* tell comedi that data is there */ + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; comedi_event(this_usbduxsub->comedidev, s); } -- cgit v1.2.3-70-g09d2 From d103bef45180892515345e761f42db5601de9846 Mon Sep 17 00:00:00 2001 From: Bernd Porr Date: Fri, 27 Nov 2009 12:07:48 +0000 Subject: Staging: comedi: removed "depricated" from COMEDI_CB_BLOCK The flag COMEDI_CB_BLOCK was marked as "depricated in the header file". However, this flag is important to wake up the data-reader (and writer) after new data has arrived from(for) the DAQ card. Signed-off-by: Bernd Porr Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/comedi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index ccc5cdc008c..b559a9c2f85 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -451,7 +451,7 @@ #define COMEDI_CB_EOS 1 /* end of scan */ #define COMEDI_CB_EOA 2 /* end of acquisition */ -#define COMEDI_CB_BLOCK 4 /* DEPRECATED: convenient block size */ +#define COMEDI_CB_BLOCK 4 /* data has arrived: wakes up read() / write() */ #define COMEDI_CB_EOBUF 8 /* DEPRECATED: end of buffer */ #define COMEDI_CB_ERROR 16 /* card error during acquisition */ #define COMEDI_CB_OVERFLOW 32 /* buffer overflow/underflow */ -- cgit v1.2.3-70-g09d2 From fa5c5f4ce0c9ba03a670c640cad17e14cb35678b Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Mon, 30 Nov 2009 10:59:27 +0000 Subject: Staging: comedi: jr3_pci: Don't ioremap too much space. Check result. For the JR3/PCI cards, the size of the PCIBAR0 region depends on the number of channels. Don't try and ioremap space for 4 channels if the card has fewer channels. Also check for ioremap failure. Thanks to Anders Blomdell for input and Sami Hussein for testing. Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/jr3_pci.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 0d2c2eb23b2..bd397840dcb 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -849,8 +849,11 @@ static int jr3_pci_attach(struct comedi_device *dev, } devpriv->pci_enabled = 1; - devpriv->iobase = - ioremap(pci_resource_start(card, 0), sizeof(struct jr3_t)); + devpriv->iobase = ioremap(pci_resource_start(card, 0), + offsetof(struct jr3_t, channel[devpriv->n_channels])); + if (!devpriv->iobase) + return -ENOMEM; + result = alloc_subdevices(dev, devpriv->n_channels); if (result < 0) goto out; -- cgit v1.2.3-70-g09d2 From aad445f8ccd554cd3013af7bd0a6cfae599a2505 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 20 Nov 2009 20:12:33 +0100 Subject: Staging: rtl8192su: fix test for negative error in rtl8192_rx_isr() The error tested for is negative Signed-off-by: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192su/r8192U_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index 66274d7666f..b492ff588b8 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -1501,7 +1501,7 @@ static void rtl8192_rx_isr(struct urb *urb) urb->context = skb; skb_queue_tail(&priv->rx_queue, skb); err = usb_submit_urb(urb, GFP_ATOMIC); - if(err && err != EPERM) + if(err && err != -EPERM) printk("can not submit rxurb, err is %x,URB status is %x\n",err,urb->status); } -- cgit v1.2.3-70-g09d2 From df574b8ecfb3a84af96229f336a6be88ca4a7055 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 17 Dec 2009 01:16:00 +0200 Subject: Staging: fix rtl8187se compilation errors with mac80211 This patch fixes compilation problems that were caused by function naming conflicts between the rtl8187se driver and the mac80211 stack. Signed-off-by: George Kadianakis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8187se/ieee80211/ieee80211.h | 10 +++++----- drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c | 2 +- drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c | 14 +++++++------- drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c | 2 +- drivers/staging/rtl8187se/r8180_core.c | 10 +++++----- drivers/staging/rtl8187se/r8180_wx.c | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211.h b/drivers/staging/rtl8187se/ieee80211/ieee80211.h index 3222c22152f..0d490c164db 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211.h @@ -1318,13 +1318,13 @@ extern int ieee80211_encrypt_fragment( struct sk_buff *frag, int hdr_len); -extern int ieee80211_xmit(struct sk_buff *skb, +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_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +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, @@ -1376,8 +1376,8 @@ 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_wake_queue(struct ieee80211_device *ieee); -extern void ieee80211_stop_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); @@ -1385,7 +1385,7 @@ extern int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct 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_start_scan(struct ieee80211_device *ieee); +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, diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c index f882dd8cf9b..9128c181bc7 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_rx.c @@ -469,7 +469,7 @@ drop: /* 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_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c index 1fe19c39d70..c7c645af0eb 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c @@ -689,7 +689,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee) } /* called with ieee->lock held */ -void ieee80211_start_scan(struct ieee80211_device *ieee) +void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) { if(IS_DOT11D_ENABLE(ieee) ) { @@ -1196,7 +1196,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee) } } -void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) +void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) { u8 *c; struct sk_buff *skb; @@ -1898,7 +1898,7 @@ associate_complete: ieee80211_associate_step2(ieee); }else{ - ieee80211_auth_challenge(ieee, challenge, chlen); + ieee80211_rtl_auth_challenge(ieee, challenge, chlen); } }else{ ieee->softmac_stats.rx_auth_rs_err++; @@ -2047,7 +2047,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee) } -void ieee80211_wake_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) { unsigned long flags; @@ -2089,7 +2089,7 @@ exit : } -void ieee80211_stop_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) { //unsigned long flags; //spin_lock_irqsave(&ieee->lock,flags); @@ -2301,7 +2301,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee) //#else if (ieee->state == IEEE80211_NOLINK){ ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } //#endif spin_unlock_irqrestore(&ieee->lock, flags); @@ -2357,7 +2357,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work) if(ieee->state == IEEE80211_NOLINK){ ieee->beinretry = false; ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } //YJ,add,080828, notify os here if(ieee->state == IEEE80211_NOLINK) diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c index dde1f2e0cf3..69bd02164b0 100644 --- a/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_tx.c @@ -304,7 +304,7 @@ ieee80211_classify(struct sk_buff *skb, struct ieee80211_network *network) } /* SKBs are added to the ieee->tx_queue. */ -int ieee80211_xmit(struct sk_buff *skb, +int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_device *ieee = netdev_priv(dev); diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index 57c62b0a402..e0f13efdb15 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c @@ -1811,7 +1811,7 @@ void rtl8180_rx(struct net_device *dev) if(priv->rx_skb->len > 4) skb_trim(priv->rx_skb,priv->rx_skb->len-4); #ifndef RX_DONT_PASS_UL - if(!ieee80211_rx(priv->ieee80211, + if(!ieee80211_rtl_rx(priv->ieee80211, priv->rx_skb, &stats)){ #endif // RX_DONT_PASS_UL @@ -1917,11 +1917,11 @@ rate) 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_stop_queue(priv->ieee80211); + 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_stop_queue(priv->ieee80211); + ieee80211_rtl_stop_queue(priv->ieee80211); spin_unlock_irqrestore(&priv->tx_lock,flags); } @@ -3680,7 +3680,7 @@ static const struct net_device_ops rtl8180_netdev_ops = { .ndo_set_mac_address = r8180_set_mac_adr, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, - .ndo_start_xmit = ieee80211_xmit, + .ndo_start_xmit = ieee80211_rtl_xmit, }; static int __devinit rtl8180_pci_probe(struct pci_dev *pdev, @@ -3900,7 +3900,7 @@ void rtl8180_try_wake_queue(struct net_device *dev, int pri) spin_unlock_irqrestore(&priv->tx_lock,flags); if(enough_desc) - ieee80211_wake_queue(priv->ieee80211); + ieee80211_rtl_wake_queue(priv->ieee80211); } void rtl8180_tx_isr(struct net_device *dev, int pri,short error) diff --git a/drivers/staging/rtl8187se/r8180_wx.c b/drivers/staging/rtl8187se/r8180_wx.c index 536cb6e8e79..124cde356cb 100644 --- a/drivers/staging/rtl8187se/r8180_wx.c +++ b/drivers/staging/rtl8187se/r8180_wx.c @@ -377,7 +377,7 @@ static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a, // queue_work(priv->ieee80211->wq, &priv->ieee80211->wx_sync_scan_wq); //printk("start scan============================>\n"); ieee80211_softmac_ips_scan_syncro(priv->ieee80211); -//ieee80211_start_scan(priv->ieee80211); +//ieee80211_rtl_start_scan(priv->ieee80211); /* intentionally forget to up sem */ // up(&priv->ieee80211->wx_sem); ret = 0; -- cgit v1.2.3-70-g09d2 From fb5fe2776d1e2a0645d8aa3286a1d5ddd95b0723 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 17 Dec 2009 01:18:08 +0200 Subject: staging: fix rtl8192e compilation errors with mac80211 This patch series fixes compilation problems that were caused by function naming conflicts between the rtl8192e driver and the mac80211 stack. Signed-off-by: George Kadianakis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/ieee80211.h | 12 +++++------ drivers/staging/rtl8192e/ieee80211/ieee80211.h | 12 +++++------ .../staging/rtl8192e/ieee80211/ieee80211_module.c | 10 ++++----- drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c | 2 +- .../staging/rtl8192e/ieee80211/ieee80211_softmac.c | 24 +++++++++++----------- drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c | 2 +- drivers/staging/rtl8192e/r8192E_core.c | 14 ++++++------- 7 files changed, 38 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/ieee80211.h b/drivers/staging/rtl8192e/ieee80211.h index 97137ddefff..3ba9e9e90bd 100644 --- a/drivers/staging/rtl8192e/ieee80211.h +++ b/drivers/staging/rtl8192e/ieee80211.h @@ -303,8 +303,8 @@ enum _ReasonCode{ #define ieee80211_rx_mgt ieee80211_rx_mgt_rsl #define ieee80211_get_beacon ieee80211_get_beacon_rsl -#define ieee80211_wake_queue ieee80211_wake_queue_rsl -#define ieee80211_stop_queue ieee80211_stop_queue_rsl +#define ieee80211_rtl_wake_queue ieee80211_rtl_wake_queue_rsl +#define ieee80211_rtl_stop_queue ieee80211_rtl_stop_queue_rsl #define ieee80211_reset_queue ieee80211_reset_queue_rsl #define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl @@ -2435,13 +2435,13 @@ extern int ieee80211_encrypt_fragment( struct sk_buff *frag, int hdr_len); -extern int ieee80211_xmit(struct sk_buff *skb, +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_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +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, @@ -2502,8 +2502,8 @@ 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_wake_queue(struct ieee80211_device *ieee); -extern void ieee80211_stop_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); diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211.h b/drivers/staging/rtl8192e/ieee80211/ieee80211.h index 83c8452de37..aa76390487b 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211.h @@ -333,8 +333,8 @@ enum _ReasonCode{ #define ieee80211_rx_mgt ieee80211_rx_mgt_rsl #define ieee80211_get_beacon ieee80211_get_beacon_rsl -#define ieee80211_wake_queue ieee80211_wake_queue_rsl -#define ieee80211_stop_queue ieee80211_stop_queue_rsl +#define ieee80211_rtl_wake_queue ieee80211_rtl_wake_queue_rsl +#define ieee80211_rtl_stop_queue ieee80211_rtl_stop_queue_rsl #define ieee80211_reset_queue ieee80211_reset_queue_rsl #define ieee80211_softmac_stop_protocol ieee80211_softmac_stop_protocol_rsl #define ieee80211_softmac_start_protocol ieee80211_softmac_start_protocol_rsl @@ -2546,13 +2546,13 @@ extern int ieee80211_encrypt_fragment( struct sk_buff *frag, int hdr_len); -extern int ieee80211_xmit(struct sk_buff *skb, +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_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +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, @@ -2613,8 +2613,8 @@ 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_wake_queue(struct ieee80211_device *ieee); -extern void ieee80211_stop_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); diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c index 2644155737a..f43a7db5c78 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c @@ -119,7 +119,7 @@ struct net_device *alloc_ieee80211(int sizeof_priv) ieee = (struct ieee80211_device *)dev->priv; #endif #if 0 - dev->hard_start_xmit = ieee80211_xmit; + dev->hard_start_xmit = ieee80211_rtl_xmit; #endif memset(ieee, 0, sizeof(struct ieee80211_device)+sizeof_priv); @@ -333,7 +333,7 @@ extern void ieee80211_crypto_ccmp_exit(void); extern int ieee80211_crypto_wep_init(void); extern void ieee80211_crypto_wep_exit(void); -int __init ieee80211_init(void) +int __init ieee80211_rtl_init(void) { struct proc_dir_entry *e; int retval; @@ -389,7 +389,7 @@ int __init ieee80211_init(void) return 0; } -void __exit ieee80211_exit(void) +void __exit ieee80211_rtl_exit(void) { if (ieee80211_proc) { remove_proc_entry("debug_level", ieee80211_proc); @@ -412,8 +412,8 @@ module_param(debug, int, 0444); MODULE_PARM_DESC(debug, "debug output mask"); -//module_exit(ieee80211_exit); -//module_init(ieee80211_init); +//module_exit(ieee80211_rtl_exit); +//module_init(ieee80211_rtl_init); #endif #endif diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c index 5dc478b8637..06d91715143 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_rx.c @@ -923,7 +923,7 @@ u8 parse_subframe(struct sk_buff *skb, /* 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_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c index 593d2282518..6d1ddec39f0 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c @@ -684,7 +684,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee) } /* called with ieee->lock held */ -void ieee80211_start_scan(struct ieee80211_device *ieee) +void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) { #ifdef ENABLE_DOT11D if(IS_DOT11D_ENABLE(ieee) ) @@ -1430,7 +1430,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee) } } -void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) +void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) { u8 *c; struct sk_buff *skb; @@ -2262,7 +2262,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, ieee80211_associate_step2(ieee); }else{ - ieee80211_auth_challenge(ieee, challenge, chlen); + ieee80211_rtl_auth_challenge(ieee, challenge, chlen); } }else{ ieee->softmac_stats.rx_auth_rs_err++; @@ -2376,7 +2376,7 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device * * to check it any more. * */ //printk("error:no descriptor left@queue_index %d\n", queue_index); - //ieee80211_stop_queue(ieee); + //ieee80211_rtl_stop_queue(ieee); #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]); #else @@ -2440,7 +2440,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee) } -void ieee80211_wake_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) { unsigned long flags; @@ -2481,7 +2481,7 @@ exit : } -void ieee80211_stop_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) { //unsigned long flags; //spin_lock_irqsave(&ieee->lock,flags); @@ -2706,7 +2706,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee) if (ieee->state == IEEE80211_NOLINK){ ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } spin_unlock_irqrestore(&ieee->lock, flags); } @@ -2775,7 +2775,7 @@ void ieee80211_associate_retry_wq(struct ieee80211_device *ieee) { ieee->is_roaming= false; ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } spin_unlock_irqrestore(&ieee->lock, flags); @@ -3497,8 +3497,8 @@ void notify_wx_assoc_event(struct ieee80211_device *ieee) #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) //EXPORT_SYMBOL(ieee80211_get_beacon); -//EXPORT_SYMBOL(ieee80211_wake_queue); -//EXPORT_SYMBOL(ieee80211_stop_queue); +//EXPORT_SYMBOL(ieee80211_rtl_wake_queue); +//EXPORT_SYMBOL(ieee80211_rtl_stop_queue); //EXPORT_SYMBOL(ieee80211_reset_queue); //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol); //EXPORT_SYMBOL(ieee80211_softmac_start_protocol); @@ -3518,8 +3518,8 @@ void notify_wx_assoc_event(struct ieee80211_device *ieee) //EXPORT_SYMBOL(ieee80211_start_scan_syncro); #else EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon); -EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue); -EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue); +EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue); +EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue); EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue); EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol); EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol); diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c index 103b33c093f..798fb4154c2 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_tx.c @@ -604,7 +604,7 @@ void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u } } -int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) +int ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)) struct ieee80211_device *ieee = netdev_priv(dev); diff --git a/drivers/staging/rtl8192e/r8192E_core.c b/drivers/staging/rtl8192e/r8192E_core.c index ff8fe7e32a9..0ca5d8b4f74 100644 --- a/drivers/staging/rtl8192e/r8192E_core.c +++ b/drivers/staging/rtl8192e/r8192E_core.c @@ -5795,7 +5795,7 @@ static void rtl8192_rx(struct net_device *dev) stats.fragoffset = 0; stats.ntotalfrag = 1; - if(!ieee80211_rx(priv->ieee80211, skb, &stats)){ + if(!ieee80211_rtl_rx(priv->ieee80211, skb, &stats)){ dev_kfree_skb_any(skb); } else { priv->stats.rxok++; @@ -5837,7 +5837,7 @@ static const struct net_device_ops rtl8192_netdev_ops = { .ndo_do_ioctl = rtl8192_ioctl, .ndo_set_multicast_list = r8192_set_multicast, .ndo_set_mac_address = r8192_set_mac_adr, - .ndo_start_xmit = ieee80211_xmit, + .ndo_start_xmit = ieee80211_rtl_xmit, }; /**************************************************************************** @@ -6121,14 +6121,14 @@ static void __devexit rtl8192_pci_disconnect(struct pci_dev *pdev) RT_TRACE(COMP_DOWN, "wlan driver removed\n"); } -extern int ieee80211_init(void); -extern void ieee80211_exit(void); +extern int ieee80211_rtl_init(void); +extern void ieee80211_rtl_exit(void); static int __init rtl8192_pci_module_init(void) { int retval; - retval = ieee80211_init(); + retval = ieee80211_rtl_init(); if (retval) return retval; @@ -6153,7 +6153,7 @@ static void __exit rtl8192_pci_module_exit(void) RT_TRACE(COMP_DOWN, "Exiting"); rtl8192_proc_module_remove(); - ieee80211_exit(); + ieee80211_rtl_exit(); } //warning message WB @@ -6313,7 +6313,7 @@ void rtl8192_try_wake_queue(struct net_device *dev, int pri) spin_unlock_irqrestore(&priv->tx_lock,flags); if(enough_desc) - ieee80211_wake_queue(priv->ieee80211); + ieee80211_rtl_wake_queue(priv->ieee80211); #endif } -- cgit v1.2.3-70-g09d2 From 55c7d5fc185e592c317e7cb175f91ee6b9d6c637 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 17 Dec 2009 01:19:13 +0200 Subject: staging: fix rtl8192su compilation errors with mac80211 This patch series fixes compilation problems that were caused by function naming conflicts between the rtl8192su driver and the mac80211 stack. Signed-off-by: George Kadianakis Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192su/ieee80211/ieee80211.h | 8 ++++---- drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c | 6 +++--- drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c | 16 ++++++++-------- drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c | 2 +- drivers/staging/rtl8192su/r8192U_core.c | 6 +++--- 5 files changed, 19 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211.h b/drivers/staging/rtl8192su/ieee80211/ieee80211.h index f22d024b1c3..9a4c858b066 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211.h +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211.h @@ -1721,13 +1721,13 @@ extern int ieee80211_encrypt_fragment( struct sk_buff *frag, int hdr_len); -extern int rtl8192_ieee80211_xmit(struct sk_buff *skb, +extern int rtl8192_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_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +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, @@ -1783,8 +1783,8 @@ 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_wake_queue(struct ieee80211_device *ieee); -extern void ieee80211_stop_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); diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c index ac223cef1d3..fecfa120ff4 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_rx.c @@ -208,7 +208,7 @@ static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee, * * Responsible for handling management control frames * - * Called by ieee80211_rx */ + * Called by ieee80211_rtl_rx */ static inline int ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats, u16 type, @@ -289,7 +289,7 @@ static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee, return 0; } -/* Called only as a tasklet (software IRQ), by ieee80211_rx */ +/* Called only as a tasklet (software IRQ), by ieee80211_rtl_rx */ static inline int ieee80211_rx_frame_decrypt(struct ieee80211_device* ieee, struct sk_buff *skb, struct ieee80211_crypt_data *crypt) @@ -858,7 +858,7 @@ u8 parse_subframe(struct sk_buff *skb, /* 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_rx(struct ieee80211_device *ieee, struct sk_buff *skb, +int ieee80211_rtl_rx(struct ieee80211_device *ieee, struct sk_buff *skb, struct ieee80211_rx_stats *rx_stats) { struct net_device *dev = ieee->dev; diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c index 203c0a5cc8c..95d4f84dcf3 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c @@ -610,7 +610,7 @@ void ieee80211_stop_scan(struct ieee80211_device *ieee) } /* called with ieee->lock held */ -void ieee80211_start_scan(struct ieee80211_device *ieee) +void ieee80211_rtl_start_scan(struct ieee80211_device *ieee) { if(IS_DOT11D_ENABLE(ieee) ) { @@ -1281,7 +1281,7 @@ void ieee80211_associate_step1(struct ieee80211_device *ieee) } } -void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) +void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) { u8 *c; struct sk_buff *skb; @@ -2054,7 +2054,7 @@ ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, ieee80211_associate_step2(ieee); }else{ - ieee80211_auth_challenge(ieee, challenge, chlen); + ieee80211_rtl_auth_challenge(ieee, challenge, chlen); } }else{ ieee->softmac_stats.rx_auth_rs_err++; @@ -2162,7 +2162,7 @@ void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device * * to check it any more. * */ //printk("error:no descriptor left@queue_index %d, %d, %d\n", queue_index, skb_queue_len(&ieee->skb_waitQ[queue_index]), ieee->check_nic_enough_desc(ieee->dev,queue_index)); - //ieee80211_stop_queue(ieee); + //ieee80211_rtl_stop_queue(ieee); skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]); }else{ ieee->softmac_data_hard_start_xmit( @@ -2222,7 +2222,7 @@ void ieee80211_reset_queue(struct ieee80211_device *ieee) } -void ieee80211_wake_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee) { unsigned long flags; @@ -2263,7 +2263,7 @@ exit : } -void ieee80211_stop_queue(struct ieee80211_device *ieee) +void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee) { //unsigned long flags; //spin_lock_irqsave(&ieee->lock,flags); @@ -2479,7 +2479,7 @@ void ieee80211_start_bss(struct ieee80211_device *ieee) if (ieee->state == IEEE80211_NOLINK){ ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } spin_unlock_irqrestore(&ieee->lock, flags); } @@ -2552,7 +2552,7 @@ void ieee80211_associate_retry_wq(struct work_struct *work) if(ieee->state == IEEE80211_NOLINK) { ieee->actscanning = true; - ieee80211_start_scan(ieee); + ieee80211_rtl_start_scan(ieee); } spin_unlock_irqrestore(&ieee->lock, flags); diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c index 60621d6b2a6..4d54e1e62d2 100644 --- a/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c +++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_tx.c @@ -604,7 +604,7 @@ void ieee80211_query_seqnum(struct ieee80211_device*ieee, struct sk_buff* skb, u } } -int rtl8192_ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) +int rtl8192_ieee80211_rtl_xmit(struct sk_buff *skb, struct net_device *dev) { struct ieee80211_device *ieee = netdev_priv(dev); struct ieee80211_txb *txb = NULL; diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index b492ff588b8..b06fca05c50 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -7155,7 +7155,7 @@ void rtl8192SU_rx_nomal(struct sk_buff* skb) unicast_packet = true; } - if(!ieee80211_rx(priv->ieee80211,skb, &stats)) { + if(!ieee80211_rtl_rx(priv->ieee80211,skb, &stats)) { dev_kfree_skb_any(skb); } else { // priv->stats.rxoktotal++; //YJ,test,090108 @@ -7426,7 +7426,7 @@ static const struct net_device_ops rtl8192_netdev_ops = { .ndo_set_mac_address = r8192_set_mac_adr, .ndo_validate_addr = eth_validate_addr, .ndo_change_mtu = eth_change_mtu, - .ndo_start_xmit = rtl8192_ieee80211_xmit, + .ndo_start_xmit = rtl8192_ieee80211_rtl_xmit, }; static int __devinit rtl8192_usb_probe(struct usb_interface *intf, @@ -7619,7 +7619,7 @@ void rtl8192_try_wake_queue(struct net_device *dev, int pri) spin_unlock_irqrestore(&priv->tx_lock,flags); if(enough_desc) - ieee80211_wake_queue(priv->ieee80211); + ieee80211_rtl_wake_queue(priv->ieee80211); } void EnableHWSecurityConfig8192(struct net_device *dev) -- cgit v1.2.3-70-g09d2 From 488d3749620779ab2668c0dba2962836e51e3cd6 Mon Sep 17 00:00:00 2001 From: Stephane Glondu Date: Thu, 17 Dec 2009 15:41:23 +0100 Subject: staging: rtl8192su: add USB VID/PID for HWNUm-300 The Hercules Wireless N USB mini (HWNUm-300) uses the RTL8191S chipset and seems to work with this driver. Signed-off-by: Stephane Glondu Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192su/r8192U_core.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/staging/rtl8192su/r8192U_core.c b/drivers/staging/rtl8192su/r8192U_core.c index b06fca05c50..ccb9d5b8cd4 100644 --- a/drivers/staging/rtl8192su/r8192U_core.c +++ b/drivers/staging/rtl8192su/r8192U_core.c @@ -126,6 +126,8 @@ static struct usb_device_id rtl8192_usb_id_tbl[] = { {USB_DEVICE(0x2001, 0x3301)}, /* Zinwell */ {USB_DEVICE(0x5a57, 0x0290)}, + /* Guillemot */ + {USB_DEVICE(0x06f8, 0xe031)}, //92SU {USB_DEVICE(0x0bda, 0x8172)}, {} -- cgit v1.2.3-70-g09d2 From 4068fe8b2aa3e12643db0ad5dd4bcf6755a7320f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 9 Dec 2009 20:25:04 +0100 Subject: Staging: wlan-ng: fix Correct size given to memset Memset should be given the size of the structure, not the size of the pointer. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ type T; T *x; expression E; @@ memset(x, E, sizeof( + * x)) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/staging/wlan-ng/prism2fw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/wlan-ng/prism2fw.c b/drivers/staging/wlan-ng/prism2fw.c index 7d76a7f92a3..aaa70ed5771 100644 --- a/drivers/staging/wlan-ng/prism2fw.c +++ b/drivers/staging/wlan-ng/prism2fw.c @@ -439,7 +439,7 @@ void free_chunks(imgchunk_t *fchunk, unsigned int *nfchunks) } } *nfchunks = 0; - memset(fchunk, 0, sizeof(fchunk)); + memset(fchunk, 0, sizeof(*fchunk)); } -- cgit v1.2.3-70-g09d2 From 3d8affc001a37664b2f5cb29aa12cf8f6c582d52 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 24 Nov 2009 12:13:55 -0800 Subject: Staging: rtl8192x: fix printk formats Fix printk format warnings in rtl8192[eu]: drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c:979: warning: format '%d' expects type 'int', but argument 2 has type 'size_t' drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c:385: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c:484: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c:614: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c:848: warning: format '%d' expects type 'int', but argument 2 has type 'size_t' drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c:343: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c:442: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c:572: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c | 2 +- drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c | 6 +++--- drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c | 2 +- drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c index 4e34a1f4c66..3441b72dd8f 100644 --- a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c @@ -976,7 +976,7 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) { if (len != ie[1]+2) { - printk("len:%d, ie:%d\n", len, ie[1]); + printk("len:%zu, ie:%d\n", len, ie[1]); return -EINVAL; } buf = kmalloc(len, GFP_KERNEL); diff --git a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c index 98b3bb6b6d6..e41e8a0c739 100644 --- a/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192e/ieee80211/rtl819x_BAProc.c @@ -382,7 +382,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb) if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); return -1; } @@ -481,7 +481,7 @@ int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb) if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); return -1; } rsp = ( struct ieee80211_hdr_3addr*)skb->data; @@ -611,7 +611,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb) if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); return -1; } diff --git a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c index d397f1d68eb..5f12d62658c 100644 --- a/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c +++ b/drivers/staging/rtl8192u/ieee80211/ieee80211_wx.c @@ -845,7 +845,7 @@ int ieee80211_wx_set_gen_ie(struct ieee80211_device *ieee, u8 *ie, size_t len) { if (len != ie[1]+2) { - printk("len:%d, ie:%d\n", len, ie[1]); + printk("len:%zu, ie:%d\n", len, ie[1]); return -EINVAL; } buf = kmalloc(len, GFP_KERNEL); diff --git a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c index 26af43bb839..512a57aebde 100644 --- a/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c +++ b/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c @@ -340,7 +340,7 @@ int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb) if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); return -1; } @@ -439,7 +439,7 @@ int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb) if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9)); return -1; } rsp = ( struct ieee80211_hdr_3addr*)skb->data; @@ -569,7 +569,7 @@ int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb) if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6) { - IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %d)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); + IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6)); return -1; } -- cgit v1.2.3-70-g09d2 From 30fb8a7141e906116bb536dd54be99480b8fd238 Mon Sep 17 00:00:00 2001 From: Nitin Gupta Date: Sat, 12 Dec 2009 11:44:46 +0530 Subject: Staging: ramzswap: remove ARM specific d-cache hack Remove d-cache hack in ramzswap driver that was needed to workaround a bug in ARM version of update_mmu_cache() which caused stale data in d-cache to be transferred to userspace. This bug was fixed by git commit: 787b2faadc4356b6c2c71feb42fb944fece9a12f This also brings down one entry in TODO file. Signed-off-by: Nitin Gupta Acked-by: Pekka Enberg Signed-off-by: Greg Kroah-Hartman --- drivers/staging/ramzswap/TODO | 1 - drivers/staging/ramzswap/ramzswap_drv.c | 28 +++------------------------- 2 files changed, 3 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/ramzswap/TODO b/drivers/staging/ramzswap/TODO index bac40d6cb9f..8d64e28fac0 100644 --- a/drivers/staging/ramzswap/TODO +++ b/drivers/staging/ramzswap/TODO @@ -1,6 +1,5 @@ TODO: - Add support for swap notifiers - - Remove CONFIG_ARM hack Please send patches to Greg Kroah-Hartman and Nitin Gupta diff --git a/drivers/staging/ramzswap/ramzswap_drv.c b/drivers/staging/ramzswap/ramzswap_drv.c index b839f05efbc..989fac5b01b 100644 --- a/drivers/staging/ramzswap/ramzswap_drv.c +++ b/drivers/staging/ramzswap/ramzswap_drv.c @@ -222,28 +222,6 @@ out: return ret; } -static void ramzswap_flush_dcache_page(struct page *page) -{ -#ifdef CONFIG_ARM - int flag = 0; - /* - * Ugly hack to get flush_dcache_page() work on ARM. - * page_mapping(page) == NULL after clearing this swap cache flag. - * Without clearing this flag, flush_dcache_page() will simply set - * "PG_dcache_dirty" bit and return. - */ - if (PageSwapCache(page)) { - flag = 1; - ClearPageSwapCache(page); - } -#endif - flush_dcache_page(page); -#ifdef CONFIG_ARM - if (flag) - SetPageSwapCache(page); -#endif -} - void ramzswap_ioctl_get_stats(struct ramzswap *rzs, struct ramzswap_ioctl_stats *s) { @@ -655,7 +633,7 @@ static int handle_zero_page(struct bio *bio) memset(user_mem, 0, PAGE_SIZE); kunmap_atomic(user_mem, KM_USER0); - ramzswap_flush_dcache_page(page); + flush_dcache_page(page); set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); @@ -679,7 +657,7 @@ static int handle_uncompressed_page(struct ramzswap *rzs, struct bio *bio) kunmap_atomic(user_mem, KM_USER0); kunmap_atomic(cmem, KM_USER1); - ramzswap_flush_dcache_page(page); + flush_dcache_page(page); set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); @@ -779,7 +757,7 @@ static int ramzswap_read(struct ramzswap *rzs, struct bio *bio) goto out; } - ramzswap_flush_dcache_page(page); + flush_dcache_page(page); set_bit(BIO_UPTODATE, &bio->bi_flags); bio_endio(bio, 0); -- cgit v1.2.3-70-g09d2 From a6a6c90804f657a91fb080c7a525a8f90bc38867 Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 15 Dec 2009 06:21:45 +0100 Subject: Staging: panel: Fix compilation error with custom lcd charset When compiling panel.c with a DEFAULT_LCD_CHARSET it fails to compile with the following error message: drivers/staging/panel/panel.c: In function >>lcd_init<<: drivers/staging/panel/panel.c:1396: error: expected expression before >>;<< token drivers/staging/panel/panel.c:1475: error: expected expression before >>;<< token make[3]: *** [drivers/staging/panel/panel.o] error 1 make[2]: *** [drivers/staging/panel] error 2 make[1]: *** [drivers/staging] error 2 The config used was: CONFIG_PANEL=m CONFIG_PANEL_PARPORT=0 CONFIG_PANEL_PROFILE=0 CONFIG_PANEL_KEYPAD=0 CONFIG_PANEL_LCD=1 CONFIG_PANEL_LCD_HEIGHT=2 CONFIG_PANEL_LCD_WIDTH=20 CONFIG_PANEL_LCD_BWIDTH=40 CONFIG_PANEL_LCD_HWIDTH=64 CONFIG_PANEL_LCD_CHARSET=0 CONFIG_PANEL_LCD_PROTO=0 CONFIG_PANEL_LCD_PIN_E=14 CONFIG_PANEL_LCD_PIN_RS=17 CONFIG_PANEL_LCD_PIN_RW=16 CONFIG_PANEL_LCD_PIN_BL=0 This patch fixes both errors, as it fixes the define Patch against current linux-next tree at Tue Dec 15 06:07:01 2009 +0100 Signed-off-by: Peter Huewe Acked-by: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c index f98a52448ea..95c93e82cce 100644 --- a/drivers/staging/panel/panel.c +++ b/drivers/staging/panel/panel.c @@ -378,7 +378,7 @@ static unsigned char lcd_bits[LCD_PORTS][LCD_BITS][BIT_STATES]; #ifdef CONFIG_PANEL_LCD_CHARSET #undef DEFAULT_LCD_CHARSET -#define DEFAULT_LCD_CHARSET +#define DEFAULT_LCD_CHARSET CONFIG_PANEL_LCD_CHARSET #endif #endif /* DEFAULT_PROFILE == 0 */ -- cgit v1.2.3-70-g09d2 From ae08961a99853c5b930845b00e3e609ad13dd61a Mon Sep 17 00:00:00 2001 From: Peter Huewe Date: Tue, 15 Dec 2009 06:37:36 +0100 Subject: Staging: panel: Adjust range for PANEL_KEYPAD in Kconfig In panel.c there are only the values 0-3 defined. So 4 is invalid: Signed-off-by: Peter Huewe Cc: Willy Tarreau Signed-off-by: Greg Kroah-Hartman --- drivers/staging/panel/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/panel/Kconfig b/drivers/staging/panel/Kconfig index 3abe7c9d558..3defa0133f2 100644 --- a/drivers/staging/panel/Kconfig +++ b/drivers/staging/panel/Kconfig @@ -47,7 +47,7 @@ config PANEL_PROFILE config PANEL_KEYPAD depends on PANEL && PANEL_PROFILE="0" int "Keypad type (0=none, 1=old 6 keys, 2=new 6 keys, 3=Nexcom 4 keys)" - range 0 4 + range 0 3 default 0 ---help--- This enables and configures a keypad connected to the parallel port. -- cgit v1.2.3-70-g09d2 From ae67491ea085529759ab7475f73e7f3f1e825704 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sat, 12 Dec 2009 23:39:47 +0100 Subject: Staging: batman-adv: Add Kconfig dependancies on PROC_FS and PACKET. Signed-off-by: Andrew Lunn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/Kconfig b/drivers/staging/batman-adv/Kconfig index 7632f576006..1d74dabf951 100644 --- a/drivers/staging/batman-adv/Kconfig +++ b/drivers/staging/batman-adv/Kconfig @@ -4,6 +4,7 @@ config BATMAN_ADV tristate "B.A.T.M.A.N. Advanced Meshing Protocol" + depends on PROC_FS && PACKET default n ---help--- -- cgit v1.2.3-70-g09d2 From e281cf8966fa723d067343364ba576fb736bfa13 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 13 Dec 2009 14:11:39 +0100 Subject: Staging: batman-adv: introduce missing kfree Error handling code following a kzalloc should free the allocated data. Similarly for usb-alloc urb. The semantic match that finds the first problem is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; statement S; expression E; identifier f,f1,l; position p1,p2; expression *ptr != NULL; @@ x@p1 = \(kmalloc\|kzalloc\|kcalloc\)(...); ... if (x == NULL) S <... when != x when != if (...) { <+...x...+> } ( x->f1 = E | (x->f1 == NULL || ...) | f(...,x->f1,...) ) ...> ( return \(0\|<+...x...+>\|ptr\); | return@p2 ...; ) @script:python@ p1 << r.p1; p2 << r.p2; @@ print "* file: %s kmalloc %s return %s" % (p1[0].file,p1[0].line,p2[0].line) // Signed-off-by: Julia Lawall Cc: Andrew Lunn Signed-off-by: Greg Kroah-Hartman --- drivers/staging/batman-adv/send.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/staging/batman-adv/send.c b/drivers/staging/batman-adv/send.c index d724798278d..eb617508cca 100644 --- a/drivers/staging/batman-adv/send.c +++ b/drivers/staging/batman-adv/send.c @@ -363,8 +363,10 @@ void add_bcast_packet_to_list(unsigned char *packet_buff, int packet_len) return; forw_packet->packet_buff = kmalloc(packet_len, GFP_ATOMIC); - if (!forw_packet->packet_buff) + if (!forw_packet->packet_buff) { + kfree(forw_packet); return; + } forw_packet->packet_len = packet_len; memcpy(forw_packet->packet_buff, packet_buff, forw_packet->packet_len); -- cgit v1.2.3-70-g09d2 From b2cd41496c70a1653f28c6d07b61cbdd25167679 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 14 Dec 2009 08:44:46 -0800 Subject: Staging/vt66*: kconfig, depends on WLAN The vt665[56] drivers can be built when CONFIG_NET=n & CONFIG_NETDEVICES=n or just when CONFIG_WLAN=n. This leads to build failures. Prevent this by making them depend on WLAN. [This patch was lost in a dualing trees merge; still needs to be re-applied.] Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/staging/vt6655/Kconfig | 2 +- drivers/staging/vt6656/Kconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig index 825bbc4fc3f..061e730df2d 100644 --- a/drivers/staging/vt6655/Kconfig +++ b/drivers/staging/vt6655/Kconfig @@ -1,6 +1,6 @@ config VT6655 tristate "VIA Technologies VT6655 support" - depends on PCI + depends on PCI && WLAN select WIRELESS_EXT select WEXT_PRIV ---help--- diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig index 87bcd269310..1055b526c53 100644 --- a/drivers/staging/vt6656/Kconfig +++ b/drivers/staging/vt6656/Kconfig @@ -1,6 +1,6 @@ config VT6656 tristate "VIA Technologies VT6656 support" - depends on USB + depends on USB && WLAN select WIRELESS_EXT select WEXT_PRIV ---help--- -- cgit v1.2.3-70-g09d2 From 8d8558d10806b7e805cb80df867ebb0a453d4765 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 8 Dec 2009 15:50:41 -0500 Subject: USB: rename usb_configure_device This patch (as1314) renames usb_configure_device() and usb_configure_device_otg() in the hub driver. Neither name is appropriate because these routines enumerate devices, they don't configure them. That's handled by usb_choose_configuration() and usb_set_configuration(). Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 06af970e106..28738fa17af 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1658,12 +1658,12 @@ static inline void announce_device(struct usb_device *udev) { } #endif /** - * usb_configure_device_otg - FIXME (usbcore-internal) + * usb_enumerate_device_otg - FIXME (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * - * Do configuration for On-The-Go devices + * Finish enumeration for On-The-Go devices */ -static int usb_configure_device_otg(struct usb_device *udev) +static int usb_enumerate_device_otg(struct usb_device *udev) { int err = 0; @@ -1734,7 +1734,7 @@ fail: /** - * usb_configure_device - Detect and probe device intfs/otg (usbcore-internal) + * usb_enumerate_device - Read device configs/intfs/otg (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * * This is only called by usb_new_device() and usb_authorize_device() @@ -1745,7 +1745,7 @@ fail: * the string descriptors, as they will be errored out by the device * until it has been authorized. */ -static int usb_configure_device(struct usb_device *udev) +static int usb_enumerate_device(struct usb_device *udev) { int err; @@ -1769,7 +1769,7 @@ static int usb_configure_device(struct usb_device *udev) udev->descriptor.iManufacturer); udev->serial = usb_cache_string(udev, udev->descriptor.iSerialNumber); } - err = usb_configure_device_otg(udev); + err = usb_enumerate_device_otg(udev); fail: return err; } @@ -1779,8 +1779,8 @@ fail: * usb_new_device - perform initial device setup (usbcore-internal) * @udev: newly addressed device (in ADDRESS state) * - * This is called with devices which have been enumerated, but not yet - * configured. The device descriptor is available, but not descriptors + * This is called with devices which have been detected but not fully + * enumerated. The device descriptor is available, but not descriptors * for any device configuration. The caller must have locked either * the parent hub (if udev is a normal device) or else the * usb_bus_list_lock (if udev is a root hub). The parent's pointer to @@ -1803,8 +1803,8 @@ int usb_new_device(struct usb_device *udev) if (udev->parent) usb_autoresume_device(udev->parent); - usb_detect_quirks(udev); /* Determine quirks */ - err = usb_configure_device(udev); /* detect & probe dev/intfs */ + usb_detect_quirks(udev); + err = usb_enumerate_device(udev); /* Read descriptors */ if (err < 0) goto fail; dev_dbg(&udev->dev, "udev %d, busnum %d, minor = %d\n", @@ -1895,9 +1895,9 @@ int usb_authorize_device(struct usb_device *usb_dev) goto error_device_descriptor; } usb_dev->authorized = 1; - result = usb_configure_device(usb_dev); + result = usb_enumerate_device(usb_dev); if (result < 0) - goto error_configure; + goto error_enumerate; /* Choose and set the configuration. This registers the interfaces * with the driver core and lets interface drivers bind to them. */ @@ -1912,7 +1912,7 @@ int usb_authorize_device(struct usb_device *usb_dev) } } dev_info(&usb_dev->dev, "authorized to connect\n"); -error_configure: +error_enumerate: error_device_descriptor: error_autoresume: out_authorized: -- cgit v1.2.3-70-g09d2 From da307123c621b01cce147a4be313d8a754674f63 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 8 Dec 2009 15:54:44 -0500 Subject: USB: fix bugs in usb_(de)authorize_device This patch (as1315) fixes some bugs in the USB core authorization code: usb_deauthorize_device() should deallocate the device strings instead of leaking them, and it should invoke usb_destroy_configuration() (which does proper reference counting) instead of freeing the config information directly. usb_authorize_device() shouldn't change the device strings until it knows that the authorization will succeed, and it should autosuspend the device at the end (having autoresumed the device at the start). Because the device strings can be changed, the sysfs routines to display the strings must protect the string pointers by locking the device. Signed-off-by: Alan Stern CC: Inaky Perez-Gonzalez Acked-by: David Vrabel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 32 ++++++++++++++++++++------------ drivers/usb/core/sysfs.c | 6 +++++- 2 files changed, 25 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 28738fa17af..0cec6caf6e9 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1849,21 +1849,23 @@ fail: */ int usb_deauthorize_device(struct usb_device *usb_dev) { - unsigned cnt; usb_lock_device(usb_dev); if (usb_dev->authorized == 0) goto out_unauthorized; + usb_dev->authorized = 0; usb_set_configuration(usb_dev, -1); + + kfree(usb_dev->product); usb_dev->product = kstrdup("n/a (unauthorized)", GFP_KERNEL); + kfree(usb_dev->manufacturer); usb_dev->manufacturer = kstrdup("n/a (unauthorized)", GFP_KERNEL); + kfree(usb_dev->serial); usb_dev->serial = kstrdup("n/a (unauthorized)", GFP_KERNEL); - kfree(usb_dev->config); - usb_dev->config = NULL; - for (cnt = 0; cnt < usb_dev->descriptor.bNumConfigurations; cnt++) - kfree(usb_dev->rawdescriptors[cnt]); + + usb_destroy_configuration(usb_dev); usb_dev->descriptor.bNumConfigurations = 0; - kfree(usb_dev->rawdescriptors); + out_unauthorized: usb_unlock_device(usb_dev); return 0; @@ -1873,15 +1875,11 @@ out_unauthorized: int usb_authorize_device(struct usb_device *usb_dev) { int result = 0, c; + usb_lock_device(usb_dev); if (usb_dev->authorized == 1) goto out_authorized; - kfree(usb_dev->product); - usb_dev->product = NULL; - kfree(usb_dev->manufacturer); - usb_dev->manufacturer = NULL; - kfree(usb_dev->serial); - usb_dev->serial = NULL; + result = usb_autoresume_device(usb_dev); if (result < 0) { dev_err(&usb_dev->dev, @@ -1894,6 +1892,14 @@ int usb_authorize_device(struct usb_device *usb_dev) "authorization: %d\n", result); goto error_device_descriptor; } + + kfree(usb_dev->product); + usb_dev->product = NULL; + kfree(usb_dev->manufacturer); + usb_dev->manufacturer = NULL; + kfree(usb_dev->serial); + usb_dev->serial = NULL; + usb_dev->authorized = 1; result = usb_enumerate_device(usb_dev); if (result < 0) @@ -1912,8 +1918,10 @@ int usb_authorize_device(struct usb_device *usb_dev) } } dev_info(&usb_dev->dev, "authorized to connect\n"); + error_enumerate: error_device_descriptor: + usb_autosuspend_device(usb_dev); error_autoresume: out_authorized: usb_unlock_device(usb_dev); // complements locktree diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 15477008b63..485edf937f2 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -82,9 +82,13 @@ static ssize_t show_##name(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct usb_device *udev; \ + int retval; \ \ udev = to_usb_device(dev); \ - return sprintf(buf, "%s\n", udev->name); \ + usb_lock_device(udev); \ + retval = sprintf(buf, "%s\n", udev->name); \ + usb_unlock_device(udev); \ + return retval; \ } \ static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL); -- cgit v1.2.3-70-g09d2 From ff3b968ceeb73c037cf4759d21923943970f9a7a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 9 Dec 2009 14:23:32 +0100 Subject: USB: gadget: Use ERR_PTR/IS_ERR Use ERR_PTR and IS_ERR rather than mixing integers and pointers. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression *E; @@ * E < 0 // Signed-off-by: Julia Lawall Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_audio.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c index c43c89ffa2c..0f2eee12ee9 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_audio.c @@ -252,12 +252,12 @@ static struct f_audio_buf *f_audio_buffer_alloc(int buf_size) copy_buf = kzalloc(sizeof *copy_buf, GFP_ATOMIC); if (!copy_buf) - return (struct f_audio_buf *)-ENOMEM; + return ERR_PTR(-ENOMEM); copy_buf->buf = kzalloc(buf_size, GFP_ATOMIC); if (!copy_buf->buf) { kfree(copy_buf); - return (struct f_audio_buf *)-ENOMEM; + return ERR_PTR(-ENOMEM); } return copy_buf; @@ -332,7 +332,7 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req) list_add_tail(©_buf->list, &audio->play_queue); schedule_work(&audio->playback_work); copy_buf = f_audio_buffer_alloc(audio_buf_size); - if (copy_buf < 0) + if (IS_ERR(copy_buf)) return -ENOMEM; } @@ -576,6 +576,8 @@ static int f_audio_set_alt(struct usb_function *f, unsigned intf, unsigned alt) usb_ep_enable(out_ep, audio->out_desc); out_ep->driver_data = audio; audio->copy_buf = f_audio_buffer_alloc(audio_buf_size); + if (IS_ERR(audio->copy_buf)) + return -ENOMEM; /* * allocate a bunch of read buffers -- cgit v1.2.3-70-g09d2 From 179192d38e8906f00479ec944c15b685400232b0 Mon Sep 17 00:00:00 2001 From: Bill Gatliff Date: Fri, 18 Dec 2009 09:57:22 -0600 Subject: USB: Fix double-linking of drivers/usb/otg when ULPI is selected This patch corrects a problem where drivers/usb/otg is linked twice if CONFIG_USB_ULPI is selected, resulting in a build error (symbol conflict). The files in that directory are properly linked already as part of CONFIG_USB, and need not be indicated specifically for CONFIG_USB_ULPI. Signed-off-by: Bill Gatliff Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 473aa1a20de..be3c9b80bc9 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -44,5 +44,3 @@ obj-y += early/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ - -obj-$(CONFIG_USB_ULPI) += otg/ -- cgit v1.2.3-70-g09d2 From 27f1281d5f72e4f161e215ccad3d7d86b9e624a9 Mon Sep 17 00:00:00 2001 From: Blaise Gassend Date: Fri, 18 Dec 2009 15:23:38 -0800 Subject: USB: serial: Extra device/vendor ID for mos7840 driver Signed-off-by: Blaise Gassend Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/mos7840.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 485fa9c5b10..2cfe2451ed9 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -127,8 +127,9 @@ #define BANDB_DEVICE_ID_US9ML2_4 0xAC30 #define BANDB_DEVICE_ID_USPTL4_2 0xAC31 #define BANDB_DEVICE_ID_USPTL4_4 0xAC32 -#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 -#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 +#define BANDB_DEVICE_ID_USOPTL4_2 0xAC42 +#define BANDB_DEVICE_ID_USOPTL4_4 0xAC44 +#define BANDB_DEVICE_ID_USOPTL2_4 0xAC24 /* This driver also supports * ATEN UC2324 device using Moschip MCS7840 @@ -191,6 +192,7 @@ static struct usb_device_id moschip_port_id_table[] = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ @@ -207,6 +209,7 @@ static __devinitdata struct usb_device_id moschip_id_table_combined[] = { {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USPTL4_4)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_2)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL4_4)}, + {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USOPTL2_4)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2324)}, {USB_DEVICE(USB_VENDOR_ID_ATENINTL, ATENINTL_DEVICE_ID_UC2322)}, {} /* terminating entry */ -- cgit v1.2.3-70-g09d2 From ac06c06770bb8761b1f1f9bdf2f5420fa6d3e9fa Mon Sep 17 00:00:00 2001 From: Clemens Ladisch Date: Mon, 21 Dec 2009 15:36:44 -0800 Subject: USB: emi62: fix crash when trying to load EMI 6|2 firmware While converting emi62 to use request_firmware(), the driver was also changed to use the ihex helper functions. However, this broke the loading of the FPGA firmware because the code tries to access the addr field of the EOF record which works with a plain array that has an empty last record but not with the ihex helper functions where the end of the data is signaled with a NULL record pointer, resulting in: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] emi62_load_firmware+0x33c/0x740 [emi62] This can be fixed by changing the loop condition to test the return value of ihex_next_binrec() directly (like in emi26.c). Signed-off-by: Clemens Ladisch Reported-and-tested-by: Der Mickster Acked-by: David Woodhouse Cc: stable Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/emi62.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 602ee05ba9f..59860b32853 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -167,7 +167,7 @@ static int emi62_load_firmware (struct usb_device *dev) err("%s - error loading firmware: error = %d", __func__, err); goto wraperr; } - } while (i > 0); + } while (rec); /* Assert reset (stop the CPU in the EMI) */ err = emi62_set_reset(dev,1); -- cgit v1.2.3-70-g09d2 From 40b52371be92cf9990de162e4c7b4fd9160150a7 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 20 Nov 2009 13:50:53 +0000 Subject: USB: fix section mismatch in early ehci dbgp Commit 917778267fbe67703ab7d5c6f0b7a05d4c3df485 removed __init from ehci_wait_for_port(), but left it in place on ehci_reset_port(), which is being called from the former function. Signed-off-by: Jan Beulich Acked-by: Jason Wessel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/early/ehci-dbgp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 1206a26ef89..2958a1271b2 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -613,7 +613,7 @@ err: } EXPORT_SYMBOL_GPL(dbgp_external_startup); -static int __init ehci_reset_port(int port) +static int ehci_reset_port(int port) { u32 portsc; u32 delay_time, delay; -- cgit v1.2.3-70-g09d2 From 4b372072b554723b508e53249dd1b594ad93fbc2 Mon Sep 17 00:00:00 2001 From: pancho horrillo Date: Wed, 2 Dec 2009 20:19:42 +0100 Subject: USB: add device ID for Apple Cinema Display 23in 2007 Hi! $ lsusb -v Bus 001 Device 008: ID 05ac:921c Apple, Inc. Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x05ac Apple, Inc. idProduct 0x921c bcdDevice 1.15 iManufacturer 1 iProduct 2 iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 34 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xe0 Self Powered Remote Wakeup MaxPower 2mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 0 No Subclass bInterfaceProtocol 0 None iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.11 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 92 Report Descriptors: ** UNAVAILABLE ** Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 16 Signed-off-by: pancho horrillo Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/appledisplay.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 1d8e39a557d..8dc4afa38b8 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -60,6 +60,7 @@ static struct usb_device_id appledisplay_table [] = { { APPLEDISPLAY_DEVICE(0x9218) }, { APPLEDISPLAY_DEVICE(0x9219) }, + { APPLEDISPLAY_DEVICE(0x921c) }, { APPLEDISPLAY_DEVICE(0x921d) }, /* Terminating entry */ -- cgit v1.2.3-70-g09d2 From 70445ae6c669865e464307a155e881096e4a0ae7 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 13 Dec 2009 10:17:16 -0800 Subject: USB core: fix recent kernel-doc warnings Fix new kernel-doc warnings in usb core: Warning(drivers/usb/core/usb.c:79): No description found for parameter 'config' Warning(drivers/usb/core/usb.c:79): No description found for parameter 'iface_num' Warning(drivers/usb/core/usb.c:79): No description found for parameter 'alt_num' Warning(drivers/usb/core/hcd.c:1622): No description found for parameter 'udev' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 4 +++- drivers/usb/core/usb.c | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6dac3b802d4..0495fa65122 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1597,7 +1597,9 @@ rescan: } /** - * Check whether a new bandwidth setting exceeds the bus bandwidth. + * usb_hcd_alloc_bandwidth - check whether a new bandwidth setting exceeds + * the bus bandwidth + * @udev: target &usb_device * @new_config: new configuration to install * @cur_alt: the current alternate interface setting * @new_alt: alternate interface setting that is being installed diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 2fb42043b30..0daff0d968b 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -66,9 +66,9 @@ MODULE_PARM_DESC(autosuspend, "default autosuspend delay"); /** * usb_find_alt_setting() - Given a configuration, find the alternate setting * for the given interface. - * @config - the configuration to search (not necessarily the current config). - * @iface_num - interface number to search in - * @alt_num - alternate interface setting number to search for. + * @config: the configuration to search (not necessarily the current config). + * @iface_num: interface number to search in + * @alt_num: alternate interface setting number to search for. * * Search the configuration's interface cache for the given alt setting. */ -- cgit v1.2.3-70-g09d2 From 31844d55800e1b93fe75c4d6188a4a44db2e1bbe Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Wed, 16 Dec 2009 21:45:10 +0100 Subject: USB: ftdi_sio: isolate all device IDs to new ftdi_sio_ids.h header This is a strictly move-only patch to relocate all FTDI device product ID definitions to their own ftdi_sio_ids.h header (following the usual *_ids.h kernel tree convention, too), thus correcting the slightly too messy appearance (crucial driver defines were stuck somewhere in the decaying middle swamp of the huge existing header). Compile-tested, based on latest mainline git. Signed-off-by: Andreas Mohr Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio.h | 959 +------------------------------------- drivers/usb/serial/ftdi_sio_ids.h | 959 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 964 insertions(+), 955 deletions(-) create mode 100644 drivers/usb/serial/ftdi_sio_ids.h (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f99498fca99..216f187582a 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -44,6 +44,7 @@ #include #include #include "ftdi_sio.h" +#include "ftdi_sio_ids.h" /* * Version Information diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 4586a24fafb..b0e0d64f822 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -1,7 +1,10 @@ /* - * Definitions for the FTDI USB Single Port Serial Converter - + * Driver definitions for the FTDI USB Single Port Serial Converter - * known as FTDI_SIO (Serial Input/Output application of the chipset) * + * For USB vendor/product IDs (VID/PID), please see ftdi_sio_ids.h + * + * * The example I have is known as the USC-1000 which is available from * http://www.dse.co.nz - cat no XH4214 It looks similar to this: * http://www.dansdata.com/usbser.htm but I can't be sure There are other @@ -17,880 +20,7 @@ * Bill Ryder - bryder@sgi.com formerly of Silicon Graphics, Inc.- wrote the * FTDI_SIO implementation. * - * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais - * from Rudolf Gugler - * - */ - -#define FTDI_VID 0x0403 /* Vendor Id */ -#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ -#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ -#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ -#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ -#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ -#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ -#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ -#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ -#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ -#define FTDI_USBX_707_PID 0xF857 /* ADSTech IR Blaster USBX-707 */ - -/* Larsen and Brusgaard AltiTrack/USBtrack */ -#define LARSENBRUSGAARD_VID 0x0FD8 -#define LB_ALTITRACK_PID 0x0001 - -/* www.canusb.com Lawicel CANUSB device */ -#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ - -/* AlphaMicro Components AMC-232USB01 device */ -#define FTDI_AMC232_PID 0xFF00 /* Product Id */ - -/* www.candapter.com Ewert Energy Systems CANdapter device */ -#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ - -/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ -/* the VID is the standard ftdi vid (FTDI_VID) */ -#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ -#define FTDI_SCS_DEVICE_1_PID 0xD011 /* SCS Tracker / DSP TNC */ -#define FTDI_SCS_DEVICE_2_PID 0xD012 -#define FTDI_SCS_DEVICE_3_PID 0xD013 -#define FTDI_SCS_DEVICE_4_PID 0xD014 -#define FTDI_SCS_DEVICE_5_PID 0xD015 -#define FTDI_SCS_DEVICE_6_PID 0xD016 -#define FTDI_SCS_DEVICE_7_PID 0xD017 - -/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */ -#define FTDI_ACTZWAVE_PID 0xF2D0 - - -/* www.starting-point-systems.com µChameleon device */ -#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */ - -/* www.irtrans.de device */ -#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ - - -/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ -#define FTDI_TTUSB_PID 0xFF20 /* Product Id */ - -/* iPlus device */ -#define FTDI_IPLUS_PID 0xD070 /* Product Id */ -#define FTDI_IPLUS2_PID 0xD071 /* Product Id */ - -/* DMX4ALL DMX Interfaces */ -#define FTDI_DMX4ALL 0xC850 - -/* OpenDCC (www.opendcc.de) product id */ -#define FTDI_OPENDCC_PID 0xBFD8 -#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 -#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA -#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB - -/* Sprog II (Andrew Crosland's SprogII DCC interface) */ -#define FTDI_SPROG_II 0xF0C8 - -/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ -/* they use the ftdi chipset for the USB interface and the vendor id is the same */ -#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ -#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */ -#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */ -#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */ -#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */ -#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */ -#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */ -#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */ - -/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */ -/* broadband internet service. The following PID is exhibited by the usb device supplied */ -/* (the VID is the standard ftdi vid (FTDI_VID) */ -#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ - -/* - * PCDJ use ftdi based dj-controllers. The following PID is for their DAC-2 device - * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen) - * (the VID is the standard ftdi vid (FTDI_VID) */ -#define FTDI_PCDJ_DAC2_PID 0xFA88 - -/* - * The following are the values for the Matrix Orbital LCD displays, - * which are the FT232BM ( similar to the 8U232AM ) - */ -#define FTDI_MTXORB_0_PID 0xFA00 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_1_PID 0xFA01 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_2_PID 0xFA02 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_3_PID 0xFA03 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_4_PID 0xFA04 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */ - -/* OOCDlink by Joern Kaipf - * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ -#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ - -/* - * The following are the values for the Matrix Orbital FTDI Range - * Anything in this range will use an FT232RL. - */ -#define MTXORB_VID 0x1B3D -#define MTXORB_FTDI_RANGE_0100_PID 0x0100 -#define MTXORB_FTDI_RANGE_0101_PID 0x0101 -#define MTXORB_FTDI_RANGE_0102_PID 0x0102 -#define MTXORB_FTDI_RANGE_0103_PID 0x0103 -#define MTXORB_FTDI_RANGE_0104_PID 0x0104 -#define MTXORB_FTDI_RANGE_0105_PID 0x0105 -#define MTXORB_FTDI_RANGE_0106_PID 0x0106 -#define MTXORB_FTDI_RANGE_0107_PID 0x0107 -#define MTXORB_FTDI_RANGE_0108_PID 0x0108 -#define MTXORB_FTDI_RANGE_0109_PID 0x0109 -#define MTXORB_FTDI_RANGE_010A_PID 0x010A -#define MTXORB_FTDI_RANGE_010B_PID 0x010B -#define MTXORB_FTDI_RANGE_010C_PID 0x010C -#define MTXORB_FTDI_RANGE_010D_PID 0x010D -#define MTXORB_FTDI_RANGE_010E_PID 0x010E -#define MTXORB_FTDI_RANGE_010F_PID 0x010F -#define MTXORB_FTDI_RANGE_0110_PID 0x0110 -#define MTXORB_FTDI_RANGE_0111_PID 0x0111 -#define MTXORB_FTDI_RANGE_0112_PID 0x0112 -#define MTXORB_FTDI_RANGE_0113_PID 0x0113 -#define MTXORB_FTDI_RANGE_0114_PID 0x0114 -#define MTXORB_FTDI_RANGE_0115_PID 0x0115 -#define MTXORB_FTDI_RANGE_0116_PID 0x0116 -#define MTXORB_FTDI_RANGE_0117_PID 0x0117 -#define MTXORB_FTDI_RANGE_0118_PID 0x0118 -#define MTXORB_FTDI_RANGE_0119_PID 0x0119 -#define MTXORB_FTDI_RANGE_011A_PID 0x011A -#define MTXORB_FTDI_RANGE_011B_PID 0x011B -#define MTXORB_FTDI_RANGE_011C_PID 0x011C -#define MTXORB_FTDI_RANGE_011D_PID 0x011D -#define MTXORB_FTDI_RANGE_011E_PID 0x011E -#define MTXORB_FTDI_RANGE_011F_PID 0x011F -#define MTXORB_FTDI_RANGE_0120_PID 0x0120 -#define MTXORB_FTDI_RANGE_0121_PID 0x0121 -#define MTXORB_FTDI_RANGE_0122_PID 0x0122 -#define MTXORB_FTDI_RANGE_0123_PID 0x0123 -#define MTXORB_FTDI_RANGE_0124_PID 0x0124 -#define MTXORB_FTDI_RANGE_0125_PID 0x0125 -#define MTXORB_FTDI_RANGE_0126_PID 0x0126 -#define MTXORB_FTDI_RANGE_0127_PID 0x0127 -#define MTXORB_FTDI_RANGE_0128_PID 0x0128 -#define MTXORB_FTDI_RANGE_0129_PID 0x0129 -#define MTXORB_FTDI_RANGE_012A_PID 0x012A -#define MTXORB_FTDI_RANGE_012B_PID 0x012B -#define MTXORB_FTDI_RANGE_012C_PID 0x012C -#define MTXORB_FTDI_RANGE_012D_PID 0x012D -#define MTXORB_FTDI_RANGE_012E_PID 0x012E -#define MTXORB_FTDI_RANGE_012F_PID 0x012F -#define MTXORB_FTDI_RANGE_0130_PID 0x0130 -#define MTXORB_FTDI_RANGE_0131_PID 0x0131 -#define MTXORB_FTDI_RANGE_0132_PID 0x0132 -#define MTXORB_FTDI_RANGE_0133_PID 0x0133 -#define MTXORB_FTDI_RANGE_0134_PID 0x0134 -#define MTXORB_FTDI_RANGE_0135_PID 0x0135 -#define MTXORB_FTDI_RANGE_0136_PID 0x0136 -#define MTXORB_FTDI_RANGE_0137_PID 0x0137 -#define MTXORB_FTDI_RANGE_0138_PID 0x0138 -#define MTXORB_FTDI_RANGE_0139_PID 0x0139 -#define MTXORB_FTDI_RANGE_013A_PID 0x013A -#define MTXORB_FTDI_RANGE_013B_PID 0x013B -#define MTXORB_FTDI_RANGE_013C_PID 0x013C -#define MTXORB_FTDI_RANGE_013D_PID 0x013D -#define MTXORB_FTDI_RANGE_013E_PID 0x013E -#define MTXORB_FTDI_RANGE_013F_PID 0x013F -#define MTXORB_FTDI_RANGE_0140_PID 0x0140 -#define MTXORB_FTDI_RANGE_0141_PID 0x0141 -#define MTXORB_FTDI_RANGE_0142_PID 0x0142 -#define MTXORB_FTDI_RANGE_0143_PID 0x0143 -#define MTXORB_FTDI_RANGE_0144_PID 0x0144 -#define MTXORB_FTDI_RANGE_0145_PID 0x0145 -#define MTXORB_FTDI_RANGE_0146_PID 0x0146 -#define MTXORB_FTDI_RANGE_0147_PID 0x0147 -#define MTXORB_FTDI_RANGE_0148_PID 0x0148 -#define MTXORB_FTDI_RANGE_0149_PID 0x0149 -#define MTXORB_FTDI_RANGE_014A_PID 0x014A -#define MTXORB_FTDI_RANGE_014B_PID 0x014B -#define MTXORB_FTDI_RANGE_014C_PID 0x014C -#define MTXORB_FTDI_RANGE_014D_PID 0x014D -#define MTXORB_FTDI_RANGE_014E_PID 0x014E -#define MTXORB_FTDI_RANGE_014F_PID 0x014F -#define MTXORB_FTDI_RANGE_0150_PID 0x0150 -#define MTXORB_FTDI_RANGE_0151_PID 0x0151 -#define MTXORB_FTDI_RANGE_0152_PID 0x0152 -#define MTXORB_FTDI_RANGE_0153_PID 0x0153 -#define MTXORB_FTDI_RANGE_0154_PID 0x0154 -#define MTXORB_FTDI_RANGE_0155_PID 0x0155 -#define MTXORB_FTDI_RANGE_0156_PID 0x0156 -#define MTXORB_FTDI_RANGE_0157_PID 0x0157 -#define MTXORB_FTDI_RANGE_0158_PID 0x0158 -#define MTXORB_FTDI_RANGE_0159_PID 0x0159 -#define MTXORB_FTDI_RANGE_015A_PID 0x015A -#define MTXORB_FTDI_RANGE_015B_PID 0x015B -#define MTXORB_FTDI_RANGE_015C_PID 0x015C -#define MTXORB_FTDI_RANGE_015D_PID 0x015D -#define MTXORB_FTDI_RANGE_015E_PID 0x015E -#define MTXORB_FTDI_RANGE_015F_PID 0x015F -#define MTXORB_FTDI_RANGE_0160_PID 0x0160 -#define MTXORB_FTDI_RANGE_0161_PID 0x0161 -#define MTXORB_FTDI_RANGE_0162_PID 0x0162 -#define MTXORB_FTDI_RANGE_0163_PID 0x0163 -#define MTXORB_FTDI_RANGE_0164_PID 0x0164 -#define MTXORB_FTDI_RANGE_0165_PID 0x0165 -#define MTXORB_FTDI_RANGE_0166_PID 0x0166 -#define MTXORB_FTDI_RANGE_0167_PID 0x0167 -#define MTXORB_FTDI_RANGE_0168_PID 0x0168 -#define MTXORB_FTDI_RANGE_0169_PID 0x0169 -#define MTXORB_FTDI_RANGE_016A_PID 0x016A -#define MTXORB_FTDI_RANGE_016B_PID 0x016B -#define MTXORB_FTDI_RANGE_016C_PID 0x016C -#define MTXORB_FTDI_RANGE_016D_PID 0x016D -#define MTXORB_FTDI_RANGE_016E_PID 0x016E -#define MTXORB_FTDI_RANGE_016F_PID 0x016F -#define MTXORB_FTDI_RANGE_0170_PID 0x0170 -#define MTXORB_FTDI_RANGE_0171_PID 0x0171 -#define MTXORB_FTDI_RANGE_0172_PID 0x0172 -#define MTXORB_FTDI_RANGE_0173_PID 0x0173 -#define MTXORB_FTDI_RANGE_0174_PID 0x0174 -#define MTXORB_FTDI_RANGE_0175_PID 0x0175 -#define MTXORB_FTDI_RANGE_0176_PID 0x0176 -#define MTXORB_FTDI_RANGE_0177_PID 0x0177 -#define MTXORB_FTDI_RANGE_0178_PID 0x0178 -#define MTXORB_FTDI_RANGE_0179_PID 0x0179 -#define MTXORB_FTDI_RANGE_017A_PID 0x017A -#define MTXORB_FTDI_RANGE_017B_PID 0x017B -#define MTXORB_FTDI_RANGE_017C_PID 0x017C -#define MTXORB_FTDI_RANGE_017D_PID 0x017D -#define MTXORB_FTDI_RANGE_017E_PID 0x017E -#define MTXORB_FTDI_RANGE_017F_PID 0x017F -#define MTXORB_FTDI_RANGE_0180_PID 0x0180 -#define MTXORB_FTDI_RANGE_0181_PID 0x0181 -#define MTXORB_FTDI_RANGE_0182_PID 0x0182 -#define MTXORB_FTDI_RANGE_0183_PID 0x0183 -#define MTXORB_FTDI_RANGE_0184_PID 0x0184 -#define MTXORB_FTDI_RANGE_0185_PID 0x0185 -#define MTXORB_FTDI_RANGE_0186_PID 0x0186 -#define MTXORB_FTDI_RANGE_0187_PID 0x0187 -#define MTXORB_FTDI_RANGE_0188_PID 0x0188 -#define MTXORB_FTDI_RANGE_0189_PID 0x0189 -#define MTXORB_FTDI_RANGE_018A_PID 0x018A -#define MTXORB_FTDI_RANGE_018B_PID 0x018B -#define MTXORB_FTDI_RANGE_018C_PID 0x018C -#define MTXORB_FTDI_RANGE_018D_PID 0x018D -#define MTXORB_FTDI_RANGE_018E_PID 0x018E -#define MTXORB_FTDI_RANGE_018F_PID 0x018F -#define MTXORB_FTDI_RANGE_0190_PID 0x0190 -#define MTXORB_FTDI_RANGE_0191_PID 0x0191 -#define MTXORB_FTDI_RANGE_0192_PID 0x0192 -#define MTXORB_FTDI_RANGE_0193_PID 0x0193 -#define MTXORB_FTDI_RANGE_0194_PID 0x0194 -#define MTXORB_FTDI_RANGE_0195_PID 0x0195 -#define MTXORB_FTDI_RANGE_0196_PID 0x0196 -#define MTXORB_FTDI_RANGE_0197_PID 0x0197 -#define MTXORB_FTDI_RANGE_0198_PID 0x0198 -#define MTXORB_FTDI_RANGE_0199_PID 0x0199 -#define MTXORB_FTDI_RANGE_019A_PID 0x019A -#define MTXORB_FTDI_RANGE_019B_PID 0x019B -#define MTXORB_FTDI_RANGE_019C_PID 0x019C -#define MTXORB_FTDI_RANGE_019D_PID 0x019D -#define MTXORB_FTDI_RANGE_019E_PID 0x019E -#define MTXORB_FTDI_RANGE_019F_PID 0x019F -#define MTXORB_FTDI_RANGE_01A0_PID 0x01A0 -#define MTXORB_FTDI_RANGE_01A1_PID 0x01A1 -#define MTXORB_FTDI_RANGE_01A2_PID 0x01A2 -#define MTXORB_FTDI_RANGE_01A3_PID 0x01A3 -#define MTXORB_FTDI_RANGE_01A4_PID 0x01A4 -#define MTXORB_FTDI_RANGE_01A5_PID 0x01A5 -#define MTXORB_FTDI_RANGE_01A6_PID 0x01A6 -#define MTXORB_FTDI_RANGE_01A7_PID 0x01A7 -#define MTXORB_FTDI_RANGE_01A8_PID 0x01A8 -#define MTXORB_FTDI_RANGE_01A9_PID 0x01A9 -#define MTXORB_FTDI_RANGE_01AA_PID 0x01AA -#define MTXORB_FTDI_RANGE_01AB_PID 0x01AB -#define MTXORB_FTDI_RANGE_01AC_PID 0x01AC -#define MTXORB_FTDI_RANGE_01AD_PID 0x01AD -#define MTXORB_FTDI_RANGE_01AE_PID 0x01AE -#define MTXORB_FTDI_RANGE_01AF_PID 0x01AF -#define MTXORB_FTDI_RANGE_01B0_PID 0x01B0 -#define MTXORB_FTDI_RANGE_01B1_PID 0x01B1 -#define MTXORB_FTDI_RANGE_01B2_PID 0x01B2 -#define MTXORB_FTDI_RANGE_01B3_PID 0x01B3 -#define MTXORB_FTDI_RANGE_01B4_PID 0x01B4 -#define MTXORB_FTDI_RANGE_01B5_PID 0x01B5 -#define MTXORB_FTDI_RANGE_01B6_PID 0x01B6 -#define MTXORB_FTDI_RANGE_01B7_PID 0x01B7 -#define MTXORB_FTDI_RANGE_01B8_PID 0x01B8 -#define MTXORB_FTDI_RANGE_01B9_PID 0x01B9 -#define MTXORB_FTDI_RANGE_01BA_PID 0x01BA -#define MTXORB_FTDI_RANGE_01BB_PID 0x01BB -#define MTXORB_FTDI_RANGE_01BC_PID 0x01BC -#define MTXORB_FTDI_RANGE_01BD_PID 0x01BD -#define MTXORB_FTDI_RANGE_01BE_PID 0x01BE -#define MTXORB_FTDI_RANGE_01BF_PID 0x01BF -#define MTXORB_FTDI_RANGE_01C0_PID 0x01C0 -#define MTXORB_FTDI_RANGE_01C1_PID 0x01C1 -#define MTXORB_FTDI_RANGE_01C2_PID 0x01C2 -#define MTXORB_FTDI_RANGE_01C3_PID 0x01C3 -#define MTXORB_FTDI_RANGE_01C4_PID 0x01C4 -#define MTXORB_FTDI_RANGE_01C5_PID 0x01C5 -#define MTXORB_FTDI_RANGE_01C6_PID 0x01C6 -#define MTXORB_FTDI_RANGE_01C7_PID 0x01C7 -#define MTXORB_FTDI_RANGE_01C8_PID 0x01C8 -#define MTXORB_FTDI_RANGE_01C9_PID 0x01C9 -#define MTXORB_FTDI_RANGE_01CA_PID 0x01CA -#define MTXORB_FTDI_RANGE_01CB_PID 0x01CB -#define MTXORB_FTDI_RANGE_01CC_PID 0x01CC -#define MTXORB_FTDI_RANGE_01CD_PID 0x01CD -#define MTXORB_FTDI_RANGE_01CE_PID 0x01CE -#define MTXORB_FTDI_RANGE_01CF_PID 0x01CF -#define MTXORB_FTDI_RANGE_01D0_PID 0x01D0 -#define MTXORB_FTDI_RANGE_01D1_PID 0x01D1 -#define MTXORB_FTDI_RANGE_01D2_PID 0x01D2 -#define MTXORB_FTDI_RANGE_01D3_PID 0x01D3 -#define MTXORB_FTDI_RANGE_01D4_PID 0x01D4 -#define MTXORB_FTDI_RANGE_01D5_PID 0x01D5 -#define MTXORB_FTDI_RANGE_01D6_PID 0x01D6 -#define MTXORB_FTDI_RANGE_01D7_PID 0x01D7 -#define MTXORB_FTDI_RANGE_01D8_PID 0x01D8 -#define MTXORB_FTDI_RANGE_01D9_PID 0x01D9 -#define MTXORB_FTDI_RANGE_01DA_PID 0x01DA -#define MTXORB_FTDI_RANGE_01DB_PID 0x01DB -#define MTXORB_FTDI_RANGE_01DC_PID 0x01DC -#define MTXORB_FTDI_RANGE_01DD_PID 0x01DD -#define MTXORB_FTDI_RANGE_01DE_PID 0x01DE -#define MTXORB_FTDI_RANGE_01DF_PID 0x01DF -#define MTXORB_FTDI_RANGE_01E0_PID 0x01E0 -#define MTXORB_FTDI_RANGE_01E1_PID 0x01E1 -#define MTXORB_FTDI_RANGE_01E2_PID 0x01E2 -#define MTXORB_FTDI_RANGE_01E3_PID 0x01E3 -#define MTXORB_FTDI_RANGE_01E4_PID 0x01E4 -#define MTXORB_FTDI_RANGE_01E5_PID 0x01E5 -#define MTXORB_FTDI_RANGE_01E6_PID 0x01E6 -#define MTXORB_FTDI_RANGE_01E7_PID 0x01E7 -#define MTXORB_FTDI_RANGE_01E8_PID 0x01E8 -#define MTXORB_FTDI_RANGE_01E9_PID 0x01E9 -#define MTXORB_FTDI_RANGE_01EA_PID 0x01EA -#define MTXORB_FTDI_RANGE_01EB_PID 0x01EB -#define MTXORB_FTDI_RANGE_01EC_PID 0x01EC -#define MTXORB_FTDI_RANGE_01ED_PID 0x01ED -#define MTXORB_FTDI_RANGE_01EE_PID 0x01EE -#define MTXORB_FTDI_RANGE_01EF_PID 0x01EF -#define MTXORB_FTDI_RANGE_01F0_PID 0x01F0 -#define MTXORB_FTDI_RANGE_01F1_PID 0x01F1 -#define MTXORB_FTDI_RANGE_01F2_PID 0x01F2 -#define MTXORB_FTDI_RANGE_01F3_PID 0x01F3 -#define MTXORB_FTDI_RANGE_01F4_PID 0x01F4 -#define MTXORB_FTDI_RANGE_01F5_PID 0x01F5 -#define MTXORB_FTDI_RANGE_01F6_PID 0x01F6 -#define MTXORB_FTDI_RANGE_01F7_PID 0x01F7 -#define MTXORB_FTDI_RANGE_01F8_PID 0x01F8 -#define MTXORB_FTDI_RANGE_01F9_PID 0x01F9 -#define MTXORB_FTDI_RANGE_01FA_PID 0x01FA -#define MTXORB_FTDI_RANGE_01FB_PID 0x01FB -#define MTXORB_FTDI_RANGE_01FC_PID 0x01FC -#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD -#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE -#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF - - - -/* Interbiometrics USB I/O Board */ -/* Developed for Interbiometrics by Rudolf Gugler */ -#define INTERBIOMETRICS_VID 0x1209 -#define INTERBIOMETRICS_IOBOARD_PID 0x1002 -#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006 - -/* - * The following are the values for the Perle Systems - * UltraPort USB serial converters - */ -#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0 /* Perle UltraPort Product Id */ - -/* - * The following are the values for the Sealevel SeaLINK+ adapters. - * (Original list sent by Tuan Hoang. Ian Abbott renamed the macros and - * removed some PIDs that don't seem to match any existing products.) - */ -#define SEALEVEL_VID 0x0c52 /* Sealevel Vendor ID */ -#define SEALEVEL_2101_PID 0x2101 /* SeaLINK+232 (2101/2105) */ -#define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ -#define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ -#define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ -#define SEALEVEL_2106_PID 0x9020 /* SeaLINK+422 (2106) */ -#define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ -#define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ -#define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ -#define SEALEVEL_2202_2_PID 0x2222 /* SeaPORT+2/485 (2202) Port 2 */ -#define SEALEVEL_2203_1_PID 0x2213 /* SeaPORT+2 (2203) Port 1 */ -#define SEALEVEL_2203_2_PID 0x2223 /* SeaPORT+2 (2203) Port 2 */ -#define SEALEVEL_2401_1_PID 0x2411 /* SeaPORT+4/232 (2401) Port 1 */ -#define SEALEVEL_2401_2_PID 0x2421 /* SeaPORT+4/232 (2401) Port 2 */ -#define SEALEVEL_2401_3_PID 0x2431 /* SeaPORT+4/232 (2401) Port 3 */ -#define SEALEVEL_2401_4_PID 0x2441 /* SeaPORT+4/232 (2401) Port 4 */ -#define SEALEVEL_2402_1_PID 0x2412 /* SeaPORT+4/485 (2402) Port 1 */ -#define SEALEVEL_2402_2_PID 0x2422 /* SeaPORT+4/485 (2402) Port 2 */ -#define SEALEVEL_2402_3_PID 0x2432 /* SeaPORT+4/485 (2402) Port 3 */ -#define SEALEVEL_2402_4_PID 0x2442 /* SeaPORT+4/485 (2402) Port 4 */ -#define SEALEVEL_2403_1_PID 0x2413 /* SeaPORT+4 (2403) Port 1 */ -#define SEALEVEL_2403_2_PID 0x2423 /* SeaPORT+4 (2403) Port 2 */ -#define SEALEVEL_2403_3_PID 0x2433 /* SeaPORT+4 (2403) Port 3 */ -#define SEALEVEL_2403_4_PID 0x2443 /* SeaPORT+4 (2403) Port 4 */ -#define SEALEVEL_2801_1_PID 0X2811 /* SeaLINK+8/232 (2801) Port 1 */ -#define SEALEVEL_2801_2_PID 0X2821 /* SeaLINK+8/232 (2801) Port 2 */ -#define SEALEVEL_2801_3_PID 0X2831 /* SeaLINK+8/232 (2801) Port 3 */ -#define SEALEVEL_2801_4_PID 0X2841 /* SeaLINK+8/232 (2801) Port 4 */ -#define SEALEVEL_2801_5_PID 0X2851 /* SeaLINK+8/232 (2801) Port 5 */ -#define SEALEVEL_2801_6_PID 0X2861 /* SeaLINK+8/232 (2801) Port 6 */ -#define SEALEVEL_2801_7_PID 0X2871 /* SeaLINK+8/232 (2801) Port 7 */ -#define SEALEVEL_2801_8_PID 0X2881 /* SeaLINK+8/232 (2801) Port 8 */ -#define SEALEVEL_2802_1_PID 0X2812 /* SeaLINK+8/485 (2802) Port 1 */ -#define SEALEVEL_2802_2_PID 0X2822 /* SeaLINK+8/485 (2802) Port 2 */ -#define SEALEVEL_2802_3_PID 0X2832 /* SeaLINK+8/485 (2802) Port 3 */ -#define SEALEVEL_2802_4_PID 0X2842 /* SeaLINK+8/485 (2802) Port 4 */ -#define SEALEVEL_2802_5_PID 0X2852 /* SeaLINK+8/485 (2802) Port 5 */ -#define SEALEVEL_2802_6_PID 0X2862 /* SeaLINK+8/485 (2802) Port 6 */ -#define SEALEVEL_2802_7_PID 0X2872 /* SeaLINK+8/485 (2802) Port 7 */ -#define SEALEVEL_2802_8_PID 0X2882 /* SeaLINK+8/485 (2802) Port 8 */ -#define SEALEVEL_2803_1_PID 0X2813 /* SeaLINK+8 (2803) Port 1 */ -#define SEALEVEL_2803_2_PID 0X2823 /* SeaLINK+8 (2803) Port 2 */ -#define SEALEVEL_2803_3_PID 0X2833 /* SeaLINK+8 (2803) Port 3 */ -#define SEALEVEL_2803_4_PID 0X2843 /* SeaLINK+8 (2803) Port 4 */ -#define SEALEVEL_2803_5_PID 0X2853 /* SeaLINK+8 (2803) Port 5 */ -#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ -#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ -#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ - -/* - * The following are the values for two KOBIL chipcard terminals. - */ -#define KOBIL_VID 0x0d46 /* KOBIL Vendor ID */ -#define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */ -#define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ - -/* - * Icom ID-1 digital transceiver - */ - -#define ICOM_ID1_VID 0x0C26 -#define ICOM_ID1_PID 0x0004 - -/* - * ASK.fr devices - */ -#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */ - -/* - * FTDI USB UART chips used in construction projects from the - * Elektor Electronics magazine (http://elektor-electronics.co.uk) - */ -#define ELEKTOR_VID 0x0C7D -#define ELEKTOR_FT323R_PID 0x0005 /* RFID-Reader, issue 09-2006 */ - -/* - * DSS-20 Sync Station for Sony Ericsson P800 - */ -#define FTDI_DSS20_PID 0xFC82 - -/* - * Home Electronics (www.home-electro.com) USB gadgets - */ -#define FTDI_HE_TIRA1_PID 0xFA78 /* Tira-1 IR transceiver */ - -/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */ -/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ -#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ - -/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ - -#define FTDI_TNC_X_PID 0xEBE0 - -/* - * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). - * All of these devices use FTDI's vendor ID (0x0403). - * - * The previously included PID for the UO 100 module was incorrect. - * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58). - * - * Armin Laeuger originally sent the PID for the UM 100 module. - */ -#define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG */ -#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ -#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ -#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ -#define FTDI_ELV_ALC8500_PID 0xF06E /* ALC 8500 Expert */ -/* Additional ELV PIDs that default to using the FTDI D2XX drivers on - * MS Windows, rather than the FTDI Virtual Com Port drivers. - * Maybe these will be easier to use with the libftdi/libusb user-space - * drivers, or possibly the Comedi drivers in some cases. */ -#define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */ -#define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */ -#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperartur-Feuchte Messgeraet (TFM 100) */ -#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkurh (UDF 77) */ -#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */ -#define FTDI_ELV_UAD8_PID 0xF068 /* USB-AD-Wandler (UAD 8) */ -#define FTDI_ELV_UDA7_PID 0xF069 /* USB-DA-Wandler (UDA 7) */ -#define FTDI_ELV_USI2_PID 0xF06A /* USB-Schrittmotoren-Interface (USI 2) */ -#define FTDI_ELV_T1100_PID 0xF06B /* Thermometer (T 1100) */ -#define FTDI_ELV_PCD200_PID 0xF06C /* PC-Datenlogger (PCD 200) */ -#define FTDI_ELV_ULA200_PID 0xF06D /* USB-LCD-Ansteuerung (ULA 200) */ -#define FTDI_ELV_FHZ1000PC_PID 0xF06F /* FHZ 1000 PC */ -#define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */ -#define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */ -#define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */ -#define FTDI_ELV_RFP500_PID 0xE0F3 /* HF-Leistungsmesser (RFP 500) */ -#define FTDI_ELV_FS20SIG_PID 0xE0F4 /* Signalgeber (FS 20 SIG) */ -#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */ -#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */ -#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */ -#define FTDI_ELV_HS485_PID 0xE0EA /* USB to RS-485 adapter */ -#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Engery monitor EM 1010 PC */ -#define FTDI_PHI_FISCO_PID 0xE40B /* PHI Fisco USB to Serial cable */ - -/* - * Definitions for ID TECH (www.idt-net.com) devices - */ -#define IDTECH_VID 0x0ACD /* ID TECH Vendor ID */ -#define IDTECH_IDT1221U_PID 0x0300 /* IDT1221U USB to RS-232 adapter */ - -/* - * Definitions for Omnidirectional Control Technology, Inc. devices - */ -#define OCT_VID 0x0B39 /* OCT vendor ID */ -/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ -/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ -/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ -#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ - -/* an infrared receiver for user access control with IR tags */ -#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ - -/* - * Definitions for Artemis astronomical USB based cameras - * Check it at http://www.artemisccd.co.uk/ - */ -#define FTDI_ARTEMIS_PID 0xDF28 /* All Artemis Cameras */ - -/* - * Definitions for ATIK Instruments astronomical USB based cameras - * Check it at http://www.atik-instruments.com/ - */ -#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Grayscale Camera */ -#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */ -#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */ -#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */ -#define FTDI_ATIK_ATK16IC_PID 0xDF35 /* ATIK ATK-16IC Grayscale Camera */ - -/* - * Protego product ids - */ -#define PROTEGO_SPECIAL_1 0xFC70 /* special/unknown device */ -#define PROTEGO_R2X0 0xFC71 /* R200-USB TRNG unit (R210, R220, and R230) */ -#define PROTEGO_SPECIAL_3 0xFC72 /* special/unknown device */ -#define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */ - -/* - * Gude Analog- und Digitalsysteme GmbH - */ -#define FTDI_GUDEADS_E808_PID 0xE808 -#define FTDI_GUDEADS_E809_PID 0xE809 -#define FTDI_GUDEADS_E80A_PID 0xE80A -#define FTDI_GUDEADS_E80B_PID 0xE80B -#define FTDI_GUDEADS_E80C_PID 0xE80C -#define FTDI_GUDEADS_E80D_PID 0xE80D -#define FTDI_GUDEADS_E80E_PID 0xE80E -#define FTDI_GUDEADS_E80F_PID 0xE80F -#define FTDI_GUDEADS_E888_PID 0xE888 /* Expert ISDN Control USB */ -#define FTDI_GUDEADS_E889_PID 0xE889 /* USB RS-232 OptoBridge */ -#define FTDI_GUDEADS_E88A_PID 0xE88A -#define FTDI_GUDEADS_E88B_PID 0xE88B -#define FTDI_GUDEADS_E88C_PID 0xE88C -#define FTDI_GUDEADS_E88D_PID 0xE88D -#define FTDI_GUDEADS_E88E_PID 0xE88E -#define FTDI_GUDEADS_E88F_PID 0xE88F - -/* - * Linx Technologies product ids - */ -#define LINX_SDMUSBQSS_PID 0xF448 /* Linx SDM-USB-QS-S */ -#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ -#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ -#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ -#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ - -/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */ -/* unit for PIC16's/PIC18's */ -#define FTDI_CCSICDU20_0_PID 0xF9D0 -#define FTDI_CCSICDU40_1_PID 0xF9D1 -#define FTDI_CCSMACHX_2_PID 0xF9D2 -#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3 -#define FTDI_CCSICDU64_4_PID 0xF9D4 -#define FTDI_CCSPRIME8_5_PID 0xF9D5 - -/* Inside Accesso contactless reader (http://www.insidefr.com) */ -#define INSIDE_ACCESSO 0xFAD0 - -/* - * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI - */ -#define INTREPID_VID 0x093C -#define INTREPID_VALUECAN_PID 0x0601 -#define INTREPID_NEOVI_PID 0x0701 - -/* - * Falcom Wireless Communications GmbH - */ -#define FALCOM_VID 0x0F94 /* Vendor Id */ -#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */ -#define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */ - -/* - * SUUNTO product ids - */ -#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ - -/* - * Oceanic product ids - */ -#define FTDI_OCEANIC_PID 0xF460 /* Oceanic dive instrument */ - -/* - * TTi (Thurlby Thandar Instruments) - */ -#define TTI_VID 0x103E /* Vendor Id */ -#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ - -/* - * Definitions for B&B Electronics products. - */ -#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ -#define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ -#define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ -#define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ -#define BANDB_USOPTL4_PID 0xAC11 -#define BANDB_USPTL4_PID 0xAC12 -#define BANDB_USO9ML2DR_2_PID 0xAC16 -#define BANDB_USO9ML2DR_PID 0xAC17 -#define BANDB_USOPTL4DR2_PID 0xAC18 /* USOPTL4R-2 2-port Isolated RS-232 Converter */ -#define BANDB_USOPTL4DR_PID 0xAC19 -#define BANDB_485USB9F_2W_PID 0xAC25 -#define BANDB_485USB9F_4W_PID 0xAC26 -#define BANDB_232USB9M_PID 0xAC27 -#define BANDB_485USBTB_2W_PID 0xAC33 -#define BANDB_485USBTB_4W_PID 0xAC34 -#define BANDB_TTL5USB9M_PID 0xAC49 -#define BANDB_TTL3USB9M_PID 0xAC50 -#define BANDB_ZZ_PROG1_USB_PID 0xBA02 - -/* - * RM Michaelides CANview USB (http://www.rmcan.com) - * CAN fieldbus interface adapter, added by port GmbH www.port.de) - * Ian Abbott changed the macro names for consistency. - */ -#define FTDI_RM_CANVIEW_PID 0xfd60 /* Product Id */ - -/* - * EVER Eco Pro UPS (http://www.ever.com.pl/) - */ - -#define EVER_ECO_PRO_CDS 0xe520 /* RS-232 converter */ - -/* - * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485, - * USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices - * and I'm not entirely sure which are used by which. - */ -#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 -#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 - -/* - * Mobility Electronics products. - */ -#define MOBILITY_VID 0x1342 -#define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ - -/* - * microHAM product IDs (http://www.microham.com). - * Submitted by Justin Burket (KL1RL) - * and Mike Studer (K6EEP) . - * Ian Abbott added a few more from the driver INF file. - */ -#define FTDI_MHAM_KW_PID 0xEEE8 /* USB-KW interface */ -#define FTDI_MHAM_YS_PID 0xEEE9 /* USB-YS interface */ -#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */ -#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */ -#define FTDI_MHAM_IC_PID 0xEEEC /* USB-IC interface */ -#define FTDI_MHAM_DB9_PID 0xEEED /* USB-DB9 interface */ -#define FTDI_MHAM_RS232_PID 0xEEEE /* USB-RS232 interface */ -#define FTDI_MHAM_Y9_PID 0xEEEF /* USB-Y9 interface */ - -/* - * Active Robots product ids. - */ -#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ - -/* - * Xsens Technologies BV products (http://www.xsens.com). - */ -#define XSENS_CONVERTER_0_PID 0xD388 -#define XSENS_CONVERTER_1_PID 0xD389 -#define XSENS_CONVERTER_2_PID 0xD38A -#define XSENS_CONVERTER_3_PID 0xD38B -#define XSENS_CONVERTER_4_PID 0xD38C -#define XSENS_CONVERTER_5_PID 0xD38D -#define XSENS_CONVERTER_6_PID 0xD38E -#define XSENS_CONVERTER_7_PID 0xD38F - -/* - * Teratronik product ids. - * Submitted by O. Wölfelschneider. - */ -#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */ -#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */ - -/* - * Evolution Robotics products (http://www.evolution.com/). - * Submitted by Shawn M. Lavelle. - */ -#define EVOLUTION_VID 0xDEEE /* Vendor ID */ -#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ -#define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/ -#define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/ -#define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */ - -/* Pyramid Computer GmbH */ -#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ - -/* - * NDI (www.ndigital.com) product ids - */ -#define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ -#define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ -#define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ -#define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ -#define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ - -/* - * Posiflex inc retail equipment (http://www.posiflex.com.tw) - */ -#define POSIFLEX_VID 0x0d3a /* Vendor ID */ -#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */ - -/* - * Westrex International devices submitted by Cory Lee - */ -#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ -#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ - -/* - * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) - */ -#define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */ - -/* - * Eclo (http://www.eclo.pt/) product IDs. - * PID 0xEA90 submitted by Martin Grill. - */ -#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */ - -/* - * Papouch products (http://www.papouch.com/) - * Submitted by Folkert van Heusden - */ - -#define PAPOUCH_VID 0x5050 /* Vendor ID */ -#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ -#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */ - -/* - * ACG Identification Technologies GmbH products (http://www.acg.de/). - * Submitted by anton -at- goto10 -dot- org. */ -#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ - -/* - * Yost Engineering, Inc. products (www.yostengineering.com). - * PID 0xE050 submitted by Aaron Prose. - */ -#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ - -/* - * ThorLabs USB motor drivers - */ -#define FTDI_THORLABS_PID 0xfaf0 /* ThorLabs USB motor drivers */ - -/* - * Testo products (http://www.testo.com/) - * Submitted by Colin Leroy - */ -#define TESTO_VID 0x128D -#define TESTO_USB_INTERFACE_PID 0x0001 - -/* - * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com. - */ -#define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ - -/* - * Tactrix OpenPort (ECU) devices. - * OpenPort 1.3M submitted by Donour Sizemore. - * OpenPort 1.3S and 1.3U submitted by Ian Abbott. - */ -#define FTDI_TACTRIX_OPENPORT_13M_PID 0xCC48 /* OpenPort 1.3 Mitsubishi */ -#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ -#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ - -/* - * Telldus Technologies - */ -#define TELLDUS_VID 0x1781 /* Vendor ID */ -#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ - -/* - * IBS elektronik product ids - * Submitted by Thomas Schleusener - */ -#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */ -#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */ -#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */ -#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */ -#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */ -#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */ -#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ -#define FTDI_IBS_PROD_PID 0xff3f /* future device */ - -/* - * MaxStream devices www.maxstream.net - */ -#define FTDI_MAXSTREAM_PID 0xEE18 /* Xbee PKG-U Module */ - -/* Olimex */ -#define OLIMEX_VID 0x15BA -#define OLIMEX_ARM_USB_OCD_PID 0x0003 - -/* Luminary Micro Stellaris Boards, VID = FTDI_VID */ -/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */ -#define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8 -#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9 - -/* www.elsterelectricity.com Elster Unicom III Optical Probe */ -#define FTDI_ELSTER_UNICOM_PID 0xE700 /* Product Id */ - -/* - * The Mobility Lab (TML) - * Submitted by Pierre Castella - */ -#define TML_VID 0x1B91 /* Vendor ID */ -#define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ - -/* Propox devices */ -#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 - -/* Rig Expert Ukraine devices */ -#define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */ - -/* Domintell products http://www.domintell.com */ -#define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ -#define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ - -/* Alti-2 products http://www.alti-2.com */ -#define ALTI2_VID 0x1BC9 -#define ALTI2_N3_PID 0x6001 /* Neptune 3 */ /* Commands */ #define FTDI_SIO_RESET 0 /* Reset the port */ @@ -910,86 +40,6 @@ #define INTERFACE_C 3 #define INTERFACE_D 4 -/* - * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3 - * Submitted by Harald Welte - */ -#define FIC_VID 0x1457 -#define FIC_NEO1973_DEBUG_PID 0x5118 - -/* - * RATOC REX-USB60F - */ -#define RATOC_VENDOR_ID 0x0584 -#define RATOC_PRODUCT_ID_USB60F 0xb020 - -/* - * DIEBOLD BCS SE923 - */ -#define DIEBOLD_BCS_SE923_PID 0xfb99 - -/* - * Atmel STK541 - */ -#define ATMEL_VID 0x03eb /* Vendor ID */ -#define STK541_PID 0x2109 /* Zigbee Controller */ - -/* - * Dresden Elektronic Sensor Terminal Board - */ -#define DE_VID 0x1cf1 /* Vendor ID */ -#define STB_PID 0x0001 /* Sensor Terminal Board */ -#define WHT_PID 0x0004 /* Wireless Handheld Terminal */ - -/* - * Blackfin gnICE JTAG - * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice - */ -#define ADI_VID 0x0456 -#define ADI_GNICE_PID 0xF000 -#define ADI_GNICEPLUS_PID 0xF001 - -/* - * JETI SPECTROMETER SPECBOS 1201 - * http://www.jeti.com/products/sys/scb/scb1201.php - */ -#define JETI_VID 0x0c6c -#define JETI_SPC1201_PID 0x04b2 - -/* - * Marvell SheevaPlug - */ -#define MARVELL_VID 0x9e88 -#define MARVELL_SHEEVAPLUG_PID 0x9e8f - -#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ - -/* - * GN Otometrics (http://www.otometrics.com) - * Submitted by Ville Sundberg. - */ -#define GN_OTOMETRICS_VID 0x0c33 /* Vendor ID */ -#define AURICAL_USB_PID 0x0010 /* Aurical USB Audiometer */ - -/* - * Bayer Ascensia Contour blood glucose meter USB-converter cable. - * http://winglucofacts.com/cables/ - */ -#define BAYER_VID 0x1A79 -#define BAYER_CONTOUR_CABLE_PID 0x6001 - -/* - * Marvell OpenRD Base, Client - * http://www.open-rd.org - * OpenRD Base, Client use VID 0x0403 - */ -#define MARVELL_OPENRD_PID 0x9e90 - -/* - * Hameg HO820 and HO870 interface (using VID 0x0403) - */ -#define HAMEG_HO820_PID 0xed74 -#define HAMEG_HO870_PID 0xed71 /* * BmRequestType: 1100 0000b @@ -1504,4 +554,3 @@ typedef enum { * B2..7 Length of message - (not including Byte 0) * */ - diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h new file mode 100644 index 00000000000..2b5017bd453 --- /dev/null +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -0,0 +1,959 @@ +/* + * vendor/product IDs (VID/PID) of devices using FTDI USB serial converters. + * + * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais + * from Rudolf Gugler + * + */ + +#define FTDI_VID 0x0403 /* Vendor Id */ +#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ +#define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ +#define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ +#define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ +#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ +#define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ +#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ +#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ +#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ +#define FTDI_USBX_707_PID 0xF857 /* ADSTech IR Blaster USBX-707 */ + +/* Larsen and Brusgaard AltiTrack/USBtrack */ +#define LARSENBRUSGAARD_VID 0x0FD8 +#define LB_ALTITRACK_PID 0x0001 + +/* www.canusb.com Lawicel CANUSB device */ +#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ + +/* AlphaMicro Components AMC-232USB01 device */ +#define FTDI_AMC232_PID 0xFF00 /* Product Id */ + +/* www.candapter.com Ewert Energy Systems CANdapter device */ +#define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ + +/* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ +/* the VID is the standard ftdi vid (FTDI_VID) */ +#define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ +#define FTDI_SCS_DEVICE_1_PID 0xD011 /* SCS Tracker / DSP TNC */ +#define FTDI_SCS_DEVICE_2_PID 0xD012 +#define FTDI_SCS_DEVICE_3_PID 0xD013 +#define FTDI_SCS_DEVICE_4_PID 0xD014 +#define FTDI_SCS_DEVICE_5_PID 0xD015 +#define FTDI_SCS_DEVICE_6_PID 0xD016 +#define FTDI_SCS_DEVICE_7_PID 0xD017 + +/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */ +#define FTDI_ACTZWAVE_PID 0xF2D0 + + +/* www.starting-point-systems.com µChameleon device */ +#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */ + +/* www.irtrans.de device */ +#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ + + +/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ +#define FTDI_TTUSB_PID 0xFF20 /* Product Id */ + +/* iPlus device */ +#define FTDI_IPLUS_PID 0xD070 /* Product Id */ +#define FTDI_IPLUS2_PID 0xD071 /* Product Id */ + +/* DMX4ALL DMX Interfaces */ +#define FTDI_DMX4ALL 0xC850 + +/* OpenDCC (www.opendcc.de) product id */ +#define FTDI_OPENDCC_PID 0xBFD8 +#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 +#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA +#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB + +/* Sprog II (Andrew Crosland's SprogII DCC interface) */ +#define FTDI_SPROG_II 0xF0C8 + +/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ +/* they use the ftdi chipset for the USB interface and the vendor id is the same */ +#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ +#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */ +#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */ +#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */ +#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */ +#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */ +#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */ +#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */ + +/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */ +/* broadband internet service. The following PID is exhibited by the usb device supplied */ +/* (the VID is the standard ftdi vid (FTDI_VID) */ +#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ + +/* + * PCDJ use ftdi based dj-controllers. The following PID is for their DAC-2 device + * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen) + * (the VID is the standard ftdi vid (FTDI_VID) */ +#define FTDI_PCDJ_DAC2_PID 0xFA88 + +/* + * The following are the values for the Matrix Orbital LCD displays, + * which are the FT232BM ( similar to the 8U232AM ) + */ +#define FTDI_MTXORB_0_PID 0xFA00 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_1_PID 0xFA01 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_2_PID 0xFA02 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_3_PID 0xFA03 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_4_PID 0xFA04 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */ + +/* OOCDlink by Joern Kaipf + * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ +#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ + +/* + * The following are the values for the Matrix Orbital FTDI Range + * Anything in this range will use an FT232RL. + */ +#define MTXORB_VID 0x1B3D +#define MTXORB_FTDI_RANGE_0100_PID 0x0100 +#define MTXORB_FTDI_RANGE_0101_PID 0x0101 +#define MTXORB_FTDI_RANGE_0102_PID 0x0102 +#define MTXORB_FTDI_RANGE_0103_PID 0x0103 +#define MTXORB_FTDI_RANGE_0104_PID 0x0104 +#define MTXORB_FTDI_RANGE_0105_PID 0x0105 +#define MTXORB_FTDI_RANGE_0106_PID 0x0106 +#define MTXORB_FTDI_RANGE_0107_PID 0x0107 +#define MTXORB_FTDI_RANGE_0108_PID 0x0108 +#define MTXORB_FTDI_RANGE_0109_PID 0x0109 +#define MTXORB_FTDI_RANGE_010A_PID 0x010A +#define MTXORB_FTDI_RANGE_010B_PID 0x010B +#define MTXORB_FTDI_RANGE_010C_PID 0x010C +#define MTXORB_FTDI_RANGE_010D_PID 0x010D +#define MTXORB_FTDI_RANGE_010E_PID 0x010E +#define MTXORB_FTDI_RANGE_010F_PID 0x010F +#define MTXORB_FTDI_RANGE_0110_PID 0x0110 +#define MTXORB_FTDI_RANGE_0111_PID 0x0111 +#define MTXORB_FTDI_RANGE_0112_PID 0x0112 +#define MTXORB_FTDI_RANGE_0113_PID 0x0113 +#define MTXORB_FTDI_RANGE_0114_PID 0x0114 +#define MTXORB_FTDI_RANGE_0115_PID 0x0115 +#define MTXORB_FTDI_RANGE_0116_PID 0x0116 +#define MTXORB_FTDI_RANGE_0117_PID 0x0117 +#define MTXORB_FTDI_RANGE_0118_PID 0x0118 +#define MTXORB_FTDI_RANGE_0119_PID 0x0119 +#define MTXORB_FTDI_RANGE_011A_PID 0x011A +#define MTXORB_FTDI_RANGE_011B_PID 0x011B +#define MTXORB_FTDI_RANGE_011C_PID 0x011C +#define MTXORB_FTDI_RANGE_011D_PID 0x011D +#define MTXORB_FTDI_RANGE_011E_PID 0x011E +#define MTXORB_FTDI_RANGE_011F_PID 0x011F +#define MTXORB_FTDI_RANGE_0120_PID 0x0120 +#define MTXORB_FTDI_RANGE_0121_PID 0x0121 +#define MTXORB_FTDI_RANGE_0122_PID 0x0122 +#define MTXORB_FTDI_RANGE_0123_PID 0x0123 +#define MTXORB_FTDI_RANGE_0124_PID 0x0124 +#define MTXORB_FTDI_RANGE_0125_PID 0x0125 +#define MTXORB_FTDI_RANGE_0126_PID 0x0126 +#define MTXORB_FTDI_RANGE_0127_PID 0x0127 +#define MTXORB_FTDI_RANGE_0128_PID 0x0128 +#define MTXORB_FTDI_RANGE_0129_PID 0x0129 +#define MTXORB_FTDI_RANGE_012A_PID 0x012A +#define MTXORB_FTDI_RANGE_012B_PID 0x012B +#define MTXORB_FTDI_RANGE_012C_PID 0x012C +#define MTXORB_FTDI_RANGE_012D_PID 0x012D +#define MTXORB_FTDI_RANGE_012E_PID 0x012E +#define MTXORB_FTDI_RANGE_012F_PID 0x012F +#define MTXORB_FTDI_RANGE_0130_PID 0x0130 +#define MTXORB_FTDI_RANGE_0131_PID 0x0131 +#define MTXORB_FTDI_RANGE_0132_PID 0x0132 +#define MTXORB_FTDI_RANGE_0133_PID 0x0133 +#define MTXORB_FTDI_RANGE_0134_PID 0x0134 +#define MTXORB_FTDI_RANGE_0135_PID 0x0135 +#define MTXORB_FTDI_RANGE_0136_PID 0x0136 +#define MTXORB_FTDI_RANGE_0137_PID 0x0137 +#define MTXORB_FTDI_RANGE_0138_PID 0x0138 +#define MTXORB_FTDI_RANGE_0139_PID 0x0139 +#define MTXORB_FTDI_RANGE_013A_PID 0x013A +#define MTXORB_FTDI_RANGE_013B_PID 0x013B +#define MTXORB_FTDI_RANGE_013C_PID 0x013C +#define MTXORB_FTDI_RANGE_013D_PID 0x013D +#define MTXORB_FTDI_RANGE_013E_PID 0x013E +#define MTXORB_FTDI_RANGE_013F_PID 0x013F +#define MTXORB_FTDI_RANGE_0140_PID 0x0140 +#define MTXORB_FTDI_RANGE_0141_PID 0x0141 +#define MTXORB_FTDI_RANGE_0142_PID 0x0142 +#define MTXORB_FTDI_RANGE_0143_PID 0x0143 +#define MTXORB_FTDI_RANGE_0144_PID 0x0144 +#define MTXORB_FTDI_RANGE_0145_PID 0x0145 +#define MTXORB_FTDI_RANGE_0146_PID 0x0146 +#define MTXORB_FTDI_RANGE_0147_PID 0x0147 +#define MTXORB_FTDI_RANGE_0148_PID 0x0148 +#define MTXORB_FTDI_RANGE_0149_PID 0x0149 +#define MTXORB_FTDI_RANGE_014A_PID 0x014A +#define MTXORB_FTDI_RANGE_014B_PID 0x014B +#define MTXORB_FTDI_RANGE_014C_PID 0x014C +#define MTXORB_FTDI_RANGE_014D_PID 0x014D +#define MTXORB_FTDI_RANGE_014E_PID 0x014E +#define MTXORB_FTDI_RANGE_014F_PID 0x014F +#define MTXORB_FTDI_RANGE_0150_PID 0x0150 +#define MTXORB_FTDI_RANGE_0151_PID 0x0151 +#define MTXORB_FTDI_RANGE_0152_PID 0x0152 +#define MTXORB_FTDI_RANGE_0153_PID 0x0153 +#define MTXORB_FTDI_RANGE_0154_PID 0x0154 +#define MTXORB_FTDI_RANGE_0155_PID 0x0155 +#define MTXORB_FTDI_RANGE_0156_PID 0x0156 +#define MTXORB_FTDI_RANGE_0157_PID 0x0157 +#define MTXORB_FTDI_RANGE_0158_PID 0x0158 +#define MTXORB_FTDI_RANGE_0159_PID 0x0159 +#define MTXORB_FTDI_RANGE_015A_PID 0x015A +#define MTXORB_FTDI_RANGE_015B_PID 0x015B +#define MTXORB_FTDI_RANGE_015C_PID 0x015C +#define MTXORB_FTDI_RANGE_015D_PID 0x015D +#define MTXORB_FTDI_RANGE_015E_PID 0x015E +#define MTXORB_FTDI_RANGE_015F_PID 0x015F +#define MTXORB_FTDI_RANGE_0160_PID 0x0160 +#define MTXORB_FTDI_RANGE_0161_PID 0x0161 +#define MTXORB_FTDI_RANGE_0162_PID 0x0162 +#define MTXORB_FTDI_RANGE_0163_PID 0x0163 +#define MTXORB_FTDI_RANGE_0164_PID 0x0164 +#define MTXORB_FTDI_RANGE_0165_PID 0x0165 +#define MTXORB_FTDI_RANGE_0166_PID 0x0166 +#define MTXORB_FTDI_RANGE_0167_PID 0x0167 +#define MTXORB_FTDI_RANGE_0168_PID 0x0168 +#define MTXORB_FTDI_RANGE_0169_PID 0x0169 +#define MTXORB_FTDI_RANGE_016A_PID 0x016A +#define MTXORB_FTDI_RANGE_016B_PID 0x016B +#define MTXORB_FTDI_RANGE_016C_PID 0x016C +#define MTXORB_FTDI_RANGE_016D_PID 0x016D +#define MTXORB_FTDI_RANGE_016E_PID 0x016E +#define MTXORB_FTDI_RANGE_016F_PID 0x016F +#define MTXORB_FTDI_RANGE_0170_PID 0x0170 +#define MTXORB_FTDI_RANGE_0171_PID 0x0171 +#define MTXORB_FTDI_RANGE_0172_PID 0x0172 +#define MTXORB_FTDI_RANGE_0173_PID 0x0173 +#define MTXORB_FTDI_RANGE_0174_PID 0x0174 +#define MTXORB_FTDI_RANGE_0175_PID 0x0175 +#define MTXORB_FTDI_RANGE_0176_PID 0x0176 +#define MTXORB_FTDI_RANGE_0177_PID 0x0177 +#define MTXORB_FTDI_RANGE_0178_PID 0x0178 +#define MTXORB_FTDI_RANGE_0179_PID 0x0179 +#define MTXORB_FTDI_RANGE_017A_PID 0x017A +#define MTXORB_FTDI_RANGE_017B_PID 0x017B +#define MTXORB_FTDI_RANGE_017C_PID 0x017C +#define MTXORB_FTDI_RANGE_017D_PID 0x017D +#define MTXORB_FTDI_RANGE_017E_PID 0x017E +#define MTXORB_FTDI_RANGE_017F_PID 0x017F +#define MTXORB_FTDI_RANGE_0180_PID 0x0180 +#define MTXORB_FTDI_RANGE_0181_PID 0x0181 +#define MTXORB_FTDI_RANGE_0182_PID 0x0182 +#define MTXORB_FTDI_RANGE_0183_PID 0x0183 +#define MTXORB_FTDI_RANGE_0184_PID 0x0184 +#define MTXORB_FTDI_RANGE_0185_PID 0x0185 +#define MTXORB_FTDI_RANGE_0186_PID 0x0186 +#define MTXORB_FTDI_RANGE_0187_PID 0x0187 +#define MTXORB_FTDI_RANGE_0188_PID 0x0188 +#define MTXORB_FTDI_RANGE_0189_PID 0x0189 +#define MTXORB_FTDI_RANGE_018A_PID 0x018A +#define MTXORB_FTDI_RANGE_018B_PID 0x018B +#define MTXORB_FTDI_RANGE_018C_PID 0x018C +#define MTXORB_FTDI_RANGE_018D_PID 0x018D +#define MTXORB_FTDI_RANGE_018E_PID 0x018E +#define MTXORB_FTDI_RANGE_018F_PID 0x018F +#define MTXORB_FTDI_RANGE_0190_PID 0x0190 +#define MTXORB_FTDI_RANGE_0191_PID 0x0191 +#define MTXORB_FTDI_RANGE_0192_PID 0x0192 +#define MTXORB_FTDI_RANGE_0193_PID 0x0193 +#define MTXORB_FTDI_RANGE_0194_PID 0x0194 +#define MTXORB_FTDI_RANGE_0195_PID 0x0195 +#define MTXORB_FTDI_RANGE_0196_PID 0x0196 +#define MTXORB_FTDI_RANGE_0197_PID 0x0197 +#define MTXORB_FTDI_RANGE_0198_PID 0x0198 +#define MTXORB_FTDI_RANGE_0199_PID 0x0199 +#define MTXORB_FTDI_RANGE_019A_PID 0x019A +#define MTXORB_FTDI_RANGE_019B_PID 0x019B +#define MTXORB_FTDI_RANGE_019C_PID 0x019C +#define MTXORB_FTDI_RANGE_019D_PID 0x019D +#define MTXORB_FTDI_RANGE_019E_PID 0x019E +#define MTXORB_FTDI_RANGE_019F_PID 0x019F +#define MTXORB_FTDI_RANGE_01A0_PID 0x01A0 +#define MTXORB_FTDI_RANGE_01A1_PID 0x01A1 +#define MTXORB_FTDI_RANGE_01A2_PID 0x01A2 +#define MTXORB_FTDI_RANGE_01A3_PID 0x01A3 +#define MTXORB_FTDI_RANGE_01A4_PID 0x01A4 +#define MTXORB_FTDI_RANGE_01A5_PID 0x01A5 +#define MTXORB_FTDI_RANGE_01A6_PID 0x01A6 +#define MTXORB_FTDI_RANGE_01A7_PID 0x01A7 +#define MTXORB_FTDI_RANGE_01A8_PID 0x01A8 +#define MTXORB_FTDI_RANGE_01A9_PID 0x01A9 +#define MTXORB_FTDI_RANGE_01AA_PID 0x01AA +#define MTXORB_FTDI_RANGE_01AB_PID 0x01AB +#define MTXORB_FTDI_RANGE_01AC_PID 0x01AC +#define MTXORB_FTDI_RANGE_01AD_PID 0x01AD +#define MTXORB_FTDI_RANGE_01AE_PID 0x01AE +#define MTXORB_FTDI_RANGE_01AF_PID 0x01AF +#define MTXORB_FTDI_RANGE_01B0_PID 0x01B0 +#define MTXORB_FTDI_RANGE_01B1_PID 0x01B1 +#define MTXORB_FTDI_RANGE_01B2_PID 0x01B2 +#define MTXORB_FTDI_RANGE_01B3_PID 0x01B3 +#define MTXORB_FTDI_RANGE_01B4_PID 0x01B4 +#define MTXORB_FTDI_RANGE_01B5_PID 0x01B5 +#define MTXORB_FTDI_RANGE_01B6_PID 0x01B6 +#define MTXORB_FTDI_RANGE_01B7_PID 0x01B7 +#define MTXORB_FTDI_RANGE_01B8_PID 0x01B8 +#define MTXORB_FTDI_RANGE_01B9_PID 0x01B9 +#define MTXORB_FTDI_RANGE_01BA_PID 0x01BA +#define MTXORB_FTDI_RANGE_01BB_PID 0x01BB +#define MTXORB_FTDI_RANGE_01BC_PID 0x01BC +#define MTXORB_FTDI_RANGE_01BD_PID 0x01BD +#define MTXORB_FTDI_RANGE_01BE_PID 0x01BE +#define MTXORB_FTDI_RANGE_01BF_PID 0x01BF +#define MTXORB_FTDI_RANGE_01C0_PID 0x01C0 +#define MTXORB_FTDI_RANGE_01C1_PID 0x01C1 +#define MTXORB_FTDI_RANGE_01C2_PID 0x01C2 +#define MTXORB_FTDI_RANGE_01C3_PID 0x01C3 +#define MTXORB_FTDI_RANGE_01C4_PID 0x01C4 +#define MTXORB_FTDI_RANGE_01C5_PID 0x01C5 +#define MTXORB_FTDI_RANGE_01C6_PID 0x01C6 +#define MTXORB_FTDI_RANGE_01C7_PID 0x01C7 +#define MTXORB_FTDI_RANGE_01C8_PID 0x01C8 +#define MTXORB_FTDI_RANGE_01C9_PID 0x01C9 +#define MTXORB_FTDI_RANGE_01CA_PID 0x01CA +#define MTXORB_FTDI_RANGE_01CB_PID 0x01CB +#define MTXORB_FTDI_RANGE_01CC_PID 0x01CC +#define MTXORB_FTDI_RANGE_01CD_PID 0x01CD +#define MTXORB_FTDI_RANGE_01CE_PID 0x01CE +#define MTXORB_FTDI_RANGE_01CF_PID 0x01CF +#define MTXORB_FTDI_RANGE_01D0_PID 0x01D0 +#define MTXORB_FTDI_RANGE_01D1_PID 0x01D1 +#define MTXORB_FTDI_RANGE_01D2_PID 0x01D2 +#define MTXORB_FTDI_RANGE_01D3_PID 0x01D3 +#define MTXORB_FTDI_RANGE_01D4_PID 0x01D4 +#define MTXORB_FTDI_RANGE_01D5_PID 0x01D5 +#define MTXORB_FTDI_RANGE_01D6_PID 0x01D6 +#define MTXORB_FTDI_RANGE_01D7_PID 0x01D7 +#define MTXORB_FTDI_RANGE_01D8_PID 0x01D8 +#define MTXORB_FTDI_RANGE_01D9_PID 0x01D9 +#define MTXORB_FTDI_RANGE_01DA_PID 0x01DA +#define MTXORB_FTDI_RANGE_01DB_PID 0x01DB +#define MTXORB_FTDI_RANGE_01DC_PID 0x01DC +#define MTXORB_FTDI_RANGE_01DD_PID 0x01DD +#define MTXORB_FTDI_RANGE_01DE_PID 0x01DE +#define MTXORB_FTDI_RANGE_01DF_PID 0x01DF +#define MTXORB_FTDI_RANGE_01E0_PID 0x01E0 +#define MTXORB_FTDI_RANGE_01E1_PID 0x01E1 +#define MTXORB_FTDI_RANGE_01E2_PID 0x01E2 +#define MTXORB_FTDI_RANGE_01E3_PID 0x01E3 +#define MTXORB_FTDI_RANGE_01E4_PID 0x01E4 +#define MTXORB_FTDI_RANGE_01E5_PID 0x01E5 +#define MTXORB_FTDI_RANGE_01E6_PID 0x01E6 +#define MTXORB_FTDI_RANGE_01E7_PID 0x01E7 +#define MTXORB_FTDI_RANGE_01E8_PID 0x01E8 +#define MTXORB_FTDI_RANGE_01E9_PID 0x01E9 +#define MTXORB_FTDI_RANGE_01EA_PID 0x01EA +#define MTXORB_FTDI_RANGE_01EB_PID 0x01EB +#define MTXORB_FTDI_RANGE_01EC_PID 0x01EC +#define MTXORB_FTDI_RANGE_01ED_PID 0x01ED +#define MTXORB_FTDI_RANGE_01EE_PID 0x01EE +#define MTXORB_FTDI_RANGE_01EF_PID 0x01EF +#define MTXORB_FTDI_RANGE_01F0_PID 0x01F0 +#define MTXORB_FTDI_RANGE_01F1_PID 0x01F1 +#define MTXORB_FTDI_RANGE_01F2_PID 0x01F2 +#define MTXORB_FTDI_RANGE_01F3_PID 0x01F3 +#define MTXORB_FTDI_RANGE_01F4_PID 0x01F4 +#define MTXORB_FTDI_RANGE_01F5_PID 0x01F5 +#define MTXORB_FTDI_RANGE_01F6_PID 0x01F6 +#define MTXORB_FTDI_RANGE_01F7_PID 0x01F7 +#define MTXORB_FTDI_RANGE_01F8_PID 0x01F8 +#define MTXORB_FTDI_RANGE_01F9_PID 0x01F9 +#define MTXORB_FTDI_RANGE_01FA_PID 0x01FA +#define MTXORB_FTDI_RANGE_01FB_PID 0x01FB +#define MTXORB_FTDI_RANGE_01FC_PID 0x01FC +#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD +#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE +#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF + + + +/* Interbiometrics USB I/O Board */ +/* Developed for Interbiometrics by Rudolf Gugler */ +#define INTERBIOMETRICS_VID 0x1209 +#define INTERBIOMETRICS_IOBOARD_PID 0x1002 +#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006 + +/* + * The following are the values for the Perle Systems + * UltraPort USB serial converters + */ +#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0 /* Perle UltraPort Product Id */ + +/* + * The following are the values for the Sealevel SeaLINK+ adapters. + * (Original list sent by Tuan Hoang. Ian Abbott renamed the macros and + * removed some PIDs that don't seem to match any existing products.) + */ +#define SEALEVEL_VID 0x0c52 /* Sealevel Vendor ID */ +#define SEALEVEL_2101_PID 0x2101 /* SeaLINK+232 (2101/2105) */ +#define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ +#define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ +#define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ +#define SEALEVEL_2106_PID 0x9020 /* SeaLINK+422 (2106) */ +#define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ +#define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ +#define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ +#define SEALEVEL_2202_2_PID 0x2222 /* SeaPORT+2/485 (2202) Port 2 */ +#define SEALEVEL_2203_1_PID 0x2213 /* SeaPORT+2 (2203) Port 1 */ +#define SEALEVEL_2203_2_PID 0x2223 /* SeaPORT+2 (2203) Port 2 */ +#define SEALEVEL_2401_1_PID 0x2411 /* SeaPORT+4/232 (2401) Port 1 */ +#define SEALEVEL_2401_2_PID 0x2421 /* SeaPORT+4/232 (2401) Port 2 */ +#define SEALEVEL_2401_3_PID 0x2431 /* SeaPORT+4/232 (2401) Port 3 */ +#define SEALEVEL_2401_4_PID 0x2441 /* SeaPORT+4/232 (2401) Port 4 */ +#define SEALEVEL_2402_1_PID 0x2412 /* SeaPORT+4/485 (2402) Port 1 */ +#define SEALEVEL_2402_2_PID 0x2422 /* SeaPORT+4/485 (2402) Port 2 */ +#define SEALEVEL_2402_3_PID 0x2432 /* SeaPORT+4/485 (2402) Port 3 */ +#define SEALEVEL_2402_4_PID 0x2442 /* SeaPORT+4/485 (2402) Port 4 */ +#define SEALEVEL_2403_1_PID 0x2413 /* SeaPORT+4 (2403) Port 1 */ +#define SEALEVEL_2403_2_PID 0x2423 /* SeaPORT+4 (2403) Port 2 */ +#define SEALEVEL_2403_3_PID 0x2433 /* SeaPORT+4 (2403) Port 3 */ +#define SEALEVEL_2403_4_PID 0x2443 /* SeaPORT+4 (2403) Port 4 */ +#define SEALEVEL_2801_1_PID 0X2811 /* SeaLINK+8/232 (2801) Port 1 */ +#define SEALEVEL_2801_2_PID 0X2821 /* SeaLINK+8/232 (2801) Port 2 */ +#define SEALEVEL_2801_3_PID 0X2831 /* SeaLINK+8/232 (2801) Port 3 */ +#define SEALEVEL_2801_4_PID 0X2841 /* SeaLINK+8/232 (2801) Port 4 */ +#define SEALEVEL_2801_5_PID 0X2851 /* SeaLINK+8/232 (2801) Port 5 */ +#define SEALEVEL_2801_6_PID 0X2861 /* SeaLINK+8/232 (2801) Port 6 */ +#define SEALEVEL_2801_7_PID 0X2871 /* SeaLINK+8/232 (2801) Port 7 */ +#define SEALEVEL_2801_8_PID 0X2881 /* SeaLINK+8/232 (2801) Port 8 */ +#define SEALEVEL_2802_1_PID 0X2812 /* SeaLINK+8/485 (2802) Port 1 */ +#define SEALEVEL_2802_2_PID 0X2822 /* SeaLINK+8/485 (2802) Port 2 */ +#define SEALEVEL_2802_3_PID 0X2832 /* SeaLINK+8/485 (2802) Port 3 */ +#define SEALEVEL_2802_4_PID 0X2842 /* SeaLINK+8/485 (2802) Port 4 */ +#define SEALEVEL_2802_5_PID 0X2852 /* SeaLINK+8/485 (2802) Port 5 */ +#define SEALEVEL_2802_6_PID 0X2862 /* SeaLINK+8/485 (2802) Port 6 */ +#define SEALEVEL_2802_7_PID 0X2872 /* SeaLINK+8/485 (2802) Port 7 */ +#define SEALEVEL_2802_8_PID 0X2882 /* SeaLINK+8/485 (2802) Port 8 */ +#define SEALEVEL_2803_1_PID 0X2813 /* SeaLINK+8 (2803) Port 1 */ +#define SEALEVEL_2803_2_PID 0X2823 /* SeaLINK+8 (2803) Port 2 */ +#define SEALEVEL_2803_3_PID 0X2833 /* SeaLINK+8 (2803) Port 3 */ +#define SEALEVEL_2803_4_PID 0X2843 /* SeaLINK+8 (2803) Port 4 */ +#define SEALEVEL_2803_5_PID 0X2853 /* SeaLINK+8 (2803) Port 5 */ +#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ +#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ +#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ + +/* + * The following are the values for two KOBIL chipcard terminals. + */ +#define KOBIL_VID 0x0d46 /* KOBIL Vendor ID */ +#define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */ +#define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ + +/* + * Icom ID-1 digital transceiver + */ + +#define ICOM_ID1_VID 0x0C26 +#define ICOM_ID1_PID 0x0004 + +/* + * ASK.fr devices + */ +#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */ + +/* + * FTDI USB UART chips used in construction projects from the + * Elektor Electronics magazine (http://elektor-electronics.co.uk) + */ +#define ELEKTOR_VID 0x0C7D +#define ELEKTOR_FT323R_PID 0x0005 /* RFID-Reader, issue 09-2006 */ + +/* + * DSS-20 Sync Station for Sony Ericsson P800 + */ +#define FTDI_DSS20_PID 0xFC82 + +/* + * Home Electronics (www.home-electro.com) USB gadgets + */ +#define FTDI_HE_TIRA1_PID 0xFA78 /* Tira-1 IR transceiver */ + +/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */ +/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ +#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ + +/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ + +#define FTDI_TNC_X_PID 0xEBE0 + +/* + * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). + * All of these devices use FTDI's vendor ID (0x0403). + * + * The previously included PID for the UO 100 module was incorrect. + * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58). + * + * Armin Laeuger originally sent the PID for the UM 100 module. + */ +#define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG */ +#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ +#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ +#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ +#define FTDI_ELV_ALC8500_PID 0xF06E /* ALC 8500 Expert */ +/* Additional ELV PIDs that default to using the FTDI D2XX drivers on + * MS Windows, rather than the FTDI Virtual Com Port drivers. + * Maybe these will be easier to use with the libftdi/libusb user-space + * drivers, or possibly the Comedi drivers in some cases. */ +#define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */ +#define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */ +#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperartur-Feuchte Messgeraet (TFM 100) */ +#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkurh (UDF 77) */ +#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */ +#define FTDI_ELV_UAD8_PID 0xF068 /* USB-AD-Wandler (UAD 8) */ +#define FTDI_ELV_UDA7_PID 0xF069 /* USB-DA-Wandler (UDA 7) */ +#define FTDI_ELV_USI2_PID 0xF06A /* USB-Schrittmotoren-Interface (USI 2) */ +#define FTDI_ELV_T1100_PID 0xF06B /* Thermometer (T 1100) */ +#define FTDI_ELV_PCD200_PID 0xF06C /* PC-Datenlogger (PCD 200) */ +#define FTDI_ELV_ULA200_PID 0xF06D /* USB-LCD-Ansteuerung (ULA 200) */ +#define FTDI_ELV_FHZ1000PC_PID 0xF06F /* FHZ 1000 PC */ +#define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */ +#define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */ +#define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */ +#define FTDI_ELV_RFP500_PID 0xE0F3 /* HF-Leistungsmesser (RFP 500) */ +#define FTDI_ELV_FS20SIG_PID 0xE0F4 /* Signalgeber (FS 20 SIG) */ +#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */ +#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */ +#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */ +#define FTDI_ELV_HS485_PID 0xE0EA /* USB to RS-485 adapter */ +#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Engery monitor EM 1010 PC */ +#define FTDI_PHI_FISCO_PID 0xE40B /* PHI Fisco USB to Serial cable */ + +/* + * Definitions for ID TECH (www.idt-net.com) devices + */ +#define IDTECH_VID 0x0ACD /* ID TECH Vendor ID */ +#define IDTECH_IDT1221U_PID 0x0300 /* IDT1221U USB to RS-232 adapter */ + +/* + * Definitions for Omnidirectional Control Technology, Inc. devices + */ +#define OCT_VID 0x0B39 /* OCT vendor ID */ +/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ +/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ +/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ +#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ + +/* an infrared receiver for user access control with IR tags */ +#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ + +/* + * Definitions for Artemis astronomical USB based cameras + * Check it at http://www.artemisccd.co.uk/ + */ +#define FTDI_ARTEMIS_PID 0xDF28 /* All Artemis Cameras */ + +/* + * Definitions for ATIK Instruments astronomical USB based cameras + * Check it at http://www.atik-instruments.com/ + */ +#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Grayscale Camera */ +#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */ +#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */ +#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */ +#define FTDI_ATIK_ATK16IC_PID 0xDF35 /* ATIK ATK-16IC Grayscale Camera */ + +/* + * Protego product ids + */ +#define PROTEGO_SPECIAL_1 0xFC70 /* special/unknown device */ +#define PROTEGO_R2X0 0xFC71 /* R200-USB TRNG unit (R210, R220, and R230) */ +#define PROTEGO_SPECIAL_3 0xFC72 /* special/unknown device */ +#define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */ + +/* + * Gude Analog- und Digitalsysteme GmbH + */ +#define FTDI_GUDEADS_E808_PID 0xE808 +#define FTDI_GUDEADS_E809_PID 0xE809 +#define FTDI_GUDEADS_E80A_PID 0xE80A +#define FTDI_GUDEADS_E80B_PID 0xE80B +#define FTDI_GUDEADS_E80C_PID 0xE80C +#define FTDI_GUDEADS_E80D_PID 0xE80D +#define FTDI_GUDEADS_E80E_PID 0xE80E +#define FTDI_GUDEADS_E80F_PID 0xE80F +#define FTDI_GUDEADS_E888_PID 0xE888 /* Expert ISDN Control USB */ +#define FTDI_GUDEADS_E889_PID 0xE889 /* USB RS-232 OptoBridge */ +#define FTDI_GUDEADS_E88A_PID 0xE88A +#define FTDI_GUDEADS_E88B_PID 0xE88B +#define FTDI_GUDEADS_E88C_PID 0xE88C +#define FTDI_GUDEADS_E88D_PID 0xE88D +#define FTDI_GUDEADS_E88E_PID 0xE88E +#define FTDI_GUDEADS_E88F_PID 0xE88F + +/* + * Linx Technologies product ids + */ +#define LINX_SDMUSBQSS_PID 0xF448 /* Linx SDM-USB-QS-S */ +#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ +#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ +#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ +#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ + +/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */ +/* unit for PIC16's/PIC18's */ +#define FTDI_CCSICDU20_0_PID 0xF9D0 +#define FTDI_CCSICDU40_1_PID 0xF9D1 +#define FTDI_CCSMACHX_2_PID 0xF9D2 +#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3 +#define FTDI_CCSICDU64_4_PID 0xF9D4 +#define FTDI_CCSPRIME8_5_PID 0xF9D5 + +/* Inside Accesso contactless reader (http://www.insidefr.com) */ +#define INSIDE_ACCESSO 0xFAD0 + +/* + * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI + */ +#define INTREPID_VID 0x093C +#define INTREPID_VALUECAN_PID 0x0601 +#define INTREPID_NEOVI_PID 0x0701 + +/* + * Falcom Wireless Communications GmbH + */ +#define FALCOM_VID 0x0F94 /* Vendor Id */ +#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */ +#define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */ + +/* + * SUUNTO product ids + */ +#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ + +/* + * Oceanic product ids + */ +#define FTDI_OCEANIC_PID 0xF460 /* Oceanic dive instrument */ + +/* + * TTi (Thurlby Thandar Instruments) + */ +#define TTI_VID 0x103E /* Vendor Id */ +#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ + +/* + * Definitions for B&B Electronics products. + */ +#define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ +#define BANDB_USOTL4_PID 0xAC01 /* USOTL4 Isolated RS-485 Converter */ +#define BANDB_USTL4_PID 0xAC02 /* USTL4 RS-485 Converter */ +#define BANDB_USO9ML2_PID 0xAC03 /* USO9ML2 Isolated RS-232 Converter */ +#define BANDB_USOPTL4_PID 0xAC11 +#define BANDB_USPTL4_PID 0xAC12 +#define BANDB_USO9ML2DR_2_PID 0xAC16 +#define BANDB_USO9ML2DR_PID 0xAC17 +#define BANDB_USOPTL4DR2_PID 0xAC18 /* USOPTL4R-2 2-port Isolated RS-232 Converter */ +#define BANDB_USOPTL4DR_PID 0xAC19 +#define BANDB_485USB9F_2W_PID 0xAC25 +#define BANDB_485USB9F_4W_PID 0xAC26 +#define BANDB_232USB9M_PID 0xAC27 +#define BANDB_485USBTB_2W_PID 0xAC33 +#define BANDB_485USBTB_4W_PID 0xAC34 +#define BANDB_TTL5USB9M_PID 0xAC49 +#define BANDB_TTL3USB9M_PID 0xAC50 +#define BANDB_ZZ_PROG1_USB_PID 0xBA02 + +/* + * RM Michaelides CANview USB (http://www.rmcan.com) + * CAN fieldbus interface adapter, added by port GmbH www.port.de) + * Ian Abbott changed the macro names for consistency. + */ +#define FTDI_RM_CANVIEW_PID 0xfd60 /* Product Id */ + +/* + * EVER Eco Pro UPS (http://www.ever.com.pl/) + */ + +#define EVER_ECO_PRO_CDS 0xe520 /* RS-232 converter */ + +/* + * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485, + * USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices + * and I'm not entirely sure which are used by which. + */ +#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 +#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 + +/* + * Mobility Electronics products. + */ +#define MOBILITY_VID 0x1342 +#define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ + +/* + * microHAM product IDs (http://www.microham.com). + * Submitted by Justin Burket (KL1RL) + * and Mike Studer (K6EEP) . + * Ian Abbott added a few more from the driver INF file. + */ +#define FTDI_MHAM_KW_PID 0xEEE8 /* USB-KW interface */ +#define FTDI_MHAM_YS_PID 0xEEE9 /* USB-YS interface */ +#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */ +#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */ +#define FTDI_MHAM_IC_PID 0xEEEC /* USB-IC interface */ +#define FTDI_MHAM_DB9_PID 0xEEED /* USB-DB9 interface */ +#define FTDI_MHAM_RS232_PID 0xEEEE /* USB-RS232 interface */ +#define FTDI_MHAM_Y9_PID 0xEEEF /* USB-Y9 interface */ + +/* + * Active Robots product ids. + */ +#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ + +/* + * Xsens Technologies BV products (http://www.xsens.com). + */ +#define XSENS_CONVERTER_0_PID 0xD388 +#define XSENS_CONVERTER_1_PID 0xD389 +#define XSENS_CONVERTER_2_PID 0xD38A +#define XSENS_CONVERTER_3_PID 0xD38B +#define XSENS_CONVERTER_4_PID 0xD38C +#define XSENS_CONVERTER_5_PID 0xD38D +#define XSENS_CONVERTER_6_PID 0xD38E +#define XSENS_CONVERTER_7_PID 0xD38F + +/* + * Teratronik product ids. + * Submitted by O. Wölfelschneider. + */ +#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */ +#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */ + +/* + * Evolution Robotics products (http://www.evolution.com/). + * Submitted by Shawn M. Lavelle. + */ +#define EVOLUTION_VID 0xDEEE /* Vendor ID */ +#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ +#define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/ +#define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/ +#define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */ + +/* Pyramid Computer GmbH */ +#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ + +/* + * NDI (www.ndigital.com) product ids + */ +#define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ +#define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ +#define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ +#define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ +#define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ + +/* + * Posiflex inc retail equipment (http://www.posiflex.com.tw) + */ +#define POSIFLEX_VID 0x0d3a /* Vendor ID */ +#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */ + +/* + * Westrex International devices submitted by Cory Lee + */ +#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ +#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ + +/* + * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) + */ +#define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */ + +/* + * Eclo (http://www.eclo.pt/) product IDs. + * PID 0xEA90 submitted by Martin Grill. + */ +#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */ + +/* + * Papouch products (http://www.papouch.com/) + * Submitted by Folkert van Heusden + */ + +#define PAPOUCH_VID 0x5050 /* Vendor ID */ +#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ +#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */ + +/* + * ACG Identification Technologies GmbH products (http://www.acg.de/). + * Submitted by anton -at- goto10 -dot- org. + */ +#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ + +/* + * Yost Engineering, Inc. products (www.yostengineering.com). + * PID 0xE050 submitted by Aaron Prose. + */ +#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ + +/* + * ThorLabs USB motor drivers + */ +#define FTDI_THORLABS_PID 0xfaf0 /* ThorLabs USB motor drivers */ + +/* + * Testo products (http://www.testo.com/) + * Submitted by Colin Leroy + */ +#define TESTO_VID 0x128D +#define TESTO_USB_INTERFACE_PID 0x0001 + +/* + * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com. + */ +#define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ + +/* + * Tactrix OpenPort (ECU) devices. + * OpenPort 1.3M submitted by Donour Sizemore. + * OpenPort 1.3S and 1.3U submitted by Ian Abbott. + */ +#define FTDI_TACTRIX_OPENPORT_13M_PID 0xCC48 /* OpenPort 1.3 Mitsubishi */ +#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ +#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ + +/* + * Telldus Technologies + */ +#define TELLDUS_VID 0x1781 /* Vendor ID */ +#define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ + +/* + * IBS elektronik product ids + * Submitted by Thomas Schleusener + */ +#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */ +#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */ +#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */ +#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */ +#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */ +#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */ +#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ +#define FTDI_IBS_PROD_PID 0xff3f /* future device */ + +/* + * MaxStream devices www.maxstream.net + */ +#define FTDI_MAXSTREAM_PID 0xEE18 /* Xbee PKG-U Module */ + +/* Olimex */ +#define OLIMEX_VID 0x15BA +#define OLIMEX_ARM_USB_OCD_PID 0x0003 + +/* Luminary Micro Stellaris Boards, VID = FTDI_VID */ +/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */ +#define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8 +#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9 + +/* www.elsterelectricity.com Elster Unicom III Optical Probe */ +#define FTDI_ELSTER_UNICOM_PID 0xE700 /* Product Id */ + +/* + * The Mobility Lab (TML) + * Submitted by Pierre Castella + */ +#define TML_VID 0x1B91 /* Vendor ID */ +#define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ + +/* Propox devices */ +#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 + +/* Rig Expert Ukraine devices */ +#define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */ + +/* Domintell products http://www.domintell.com */ +#define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ +#define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ + +/* Alti-2 products http://www.alti-2.com */ +#define ALTI2_VID 0x1BC9 +#define ALTI2_N3_PID 0x6001 /* Neptune 3 */ + +/* + * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3 + * Submitted by Harald Welte + */ +#define FIC_VID 0x1457 +#define FIC_NEO1973_DEBUG_PID 0x5118 + +/* + * RATOC REX-USB60F + */ +#define RATOC_VENDOR_ID 0x0584 +#define RATOC_PRODUCT_ID_USB60F 0xb020 + +/* + * DIEBOLD BCS SE923 + */ +#define DIEBOLD_BCS_SE923_PID 0xfb99 + +/* + * Atmel STK541 + */ +#define ATMEL_VID 0x03eb /* Vendor ID */ +#define STK541_PID 0x2109 /* Zigbee Controller */ + +/* + * Dresden Elektronic Sensor Terminal Board + */ +#define DE_VID 0x1cf1 /* Vendor ID */ +#define STB_PID 0x0001 /* Sensor Terminal Board */ +#define WHT_PID 0x0004 /* Wireless Handheld Terminal */ + +/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +#define ADI_VID 0x0456 +#define ADI_GNICE_PID 0xF000 +#define ADI_GNICEPLUS_PID 0xF001 + +/* + * JETI SPECTROMETER SPECBOS 1201 + * http://www.jeti.com/products/sys/scb/scb1201.php + */ +#define JETI_VID 0x0c6c +#define JETI_SPC1201_PID 0x04b2 + +/* + * Marvell SheevaPlug + */ +#define MARVELL_VID 0x9e88 +#define MARVELL_SHEEVAPLUG_PID 0x9e8f + +#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ + +/* + * GN Otometrics (http://www.otometrics.com) + * Submitted by Ville Sundberg. + */ +#define GN_OTOMETRICS_VID 0x0c33 /* Vendor ID */ +#define AURICAL_USB_PID 0x0010 /* Aurical USB Audiometer */ + +/* + * Bayer Ascensia Contour blood glucose meter USB-converter cable. + * http://winglucofacts.com/cables/ + */ +#define BAYER_VID 0x1A79 +#define BAYER_CONTOUR_CABLE_PID 0x6001 + +/* + * Marvell OpenRD Base, Client + * http://www.open-rd.org + * OpenRD Base, Client use VID 0x0403 + */ +#define MARVELL_OPENRD_PID 0x9e90 + +/* + * Hameg HO820 and HO870 interface (using VID 0x0403) + */ +#define HAMEG_HO820_PID 0xed74 +#define HAMEG_HO870_PID 0xed71 + -- cgit v1.2.3-70-g09d2 From 4e092d110fe931db3878865db185be1c9df3e182 Mon Sep 17 00:00:00 2001 From: Andreas Mohr Date: Thu, 17 Dec 2009 11:56:09 +0100 Subject: USB: ftdi_sio: sort PID/VID entries in new ftdi_sio_ids.h header This is a (almost) sort-only patch to sort FTDI device product ID definitions in new ftdi_sio_ids.h header. Advantage is that new device ID submissions will now have a specific (sorted) position - less future merge conflicts. Compile-tested, based on _current_ mainline git. Minor checkpatch.pl warnings were eliminated whereever it made sense, very minor text changes. Signed-off-by: Andreas Mohr Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio_ids.h | 1487 +++++++++++++++++++------------------ 1 file changed, 757 insertions(+), 730 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 2b5017bd453..da92b4952ff 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1,36 +1,85 @@ /* * vendor/product IDs (VID/PID) of devices using FTDI USB serial converters. + * Please keep numerically sorted within individual areas, thanks! * * Philipp Gühring - pg@futureware.at - added the Device ID of the USB relais * from Rudolf Gugler * */ + +/**********************************/ +/***** devices using FTDI VID *****/ +/**********************************/ + + #define FTDI_VID 0x0403 /* Vendor Id */ -#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ + + +/*** "original" FTDI device PIDs ***/ + #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */ -#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */ -#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ -#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ -#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ -#define FTDI_USBX_707_PID 0xF857 /* ADSTech IR Blaster USBX-707 */ +#define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */ +#define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */ -/* Larsen and Brusgaard AltiTrack/USBtrack */ -#define LARSENBRUSGAARD_VID 0x0FD8 -#define LB_ALTITRACK_PID 0x0001 -/* www.canusb.com Lawicel CANUSB device */ -#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ +/*** third-party PIDs (using FTDI_VID) ***/ -/* AlphaMicro Components AMC-232USB01 device */ -#define FTDI_AMC232_PID 0xFF00 /* Product Id */ +/* + * Marvell OpenRD Base, Client + * http://www.open-rd.org + * OpenRD Base, Client use VID 0x0403 + */ +#define MARVELL_OPENRD_PID 0x9e90 /* www.candapter.com Ewert Energy Systems CANdapter device */ #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ +/* OOCDlink by Joern Kaipf + * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ +#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ + +/* Luminary Micro Stellaris Boards, VID = FTDI_VID */ +/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */ +#define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8 +#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9 + +#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ + +/* OpenDCC (www.opendcc.de) product id */ +#define FTDI_OPENDCC_PID 0xBFD8 +#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 +#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA +#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB + +/* + * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) + */ +#define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */ + +/* DMX4ALL DMX Interfaces */ +#define FTDI_DMX4ALL 0xC850 + +/* + * ASK.fr devices + */ +#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */ + +/* www.starting-point-systems.com µChameleon device */ +#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */ + +/* + * Tactrix OpenPort (ECU) devices. + * OpenPort 1.3M submitted by Donour Sizemore. + * OpenPort 1.3S and 1.3U submitted by Ian Abbott. + */ +#define FTDI_TACTRIX_OPENPORT_13M_PID 0xCC48 /* OpenPort 1.3 Mitsubishi */ +#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ +#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ + /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ /* the VID is the standard ftdi vid (FTDI_VID) */ #define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ @@ -42,523 +91,280 @@ #define FTDI_SCS_DEVICE_6_PID 0xD016 #define FTDI_SCS_DEVICE_7_PID 0xD017 -/* ACT Solutions HomePro ZWave interface (http://www.act-solutions.com/HomePro.htm) */ -#define FTDI_ACTZWAVE_PID 0xF2D0 +/* iPlus device */ +#define FTDI_IPLUS_PID 0xD070 /* Product Id */ +#define FTDI_IPLUS2_PID 0xD071 /* Product Id */ +/* + * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com. + */ +#define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ -/* www.starting-point-systems.com µChameleon device */ -#define FTDI_MICRO_CHAMELEON_PID 0xCAA0 /* Product Id */ +/* Propox devices */ +#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 -/* www.irtrans.de device */ -#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ +/* + * Xsens Technologies BV products (http://www.xsens.com). + */ +#define XSENS_CONVERTER_0_PID 0xD388 +#define XSENS_CONVERTER_1_PID 0xD389 +#define XSENS_CONVERTER_2_PID 0xD38A +#define XSENS_CONVERTER_3_PID 0xD38B +#define XSENS_CONVERTER_4_PID 0xD38C +#define XSENS_CONVERTER_5_PID 0xD38D +#define XSENS_CONVERTER_6_PID 0xD38E +#define XSENS_CONVERTER_7_PID 0xD38F +/* + * NDI (www.ndigital.com) product ids + */ +#define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ +#define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ +#define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ +#define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ +#define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ -/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ -#define FTDI_TTUSB_PID 0xFF20 /* Product Id */ +/* + * Westrex International devices submitted by Cory Lee + */ +#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ +#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ -/* iPlus device */ -#define FTDI_IPLUS_PID 0xD070 /* Product Id */ -#define FTDI_IPLUS2_PID 0xD071 /* Product Id */ +/* + * ACG Identification Technologies GmbH products (http://www.acg.de/). + * Submitted by anton -at- goto10 -dot- org. + */ +#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ -/* DMX4ALL DMX Interfaces */ -#define FTDI_DMX4ALL 0xC850 +/* + * Definitions for Artemis astronomical USB based cameras + * Check it at http://www.artemisccd.co.uk/ + */ +#define FTDI_ARTEMIS_PID 0xDF28 /* All Artemis Cameras */ -/* OpenDCC (www.opendcc.de) product id */ -#define FTDI_OPENDCC_PID 0xBFD8 -#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 -#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA -#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB +/* + * Definitions for ATIK Instruments astronomical USB based cameras + * Check it at http://www.atik-instruments.com/ + */ +#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Grayscale Camera */ +#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */ +#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */ +#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */ +#define FTDI_ATIK_ATK16IC_PID 0xDF35 /* ATIK ATK-16IC Grayscale Camera */ -/* Sprog II (Andrew Crosland's SprogII DCC interface) */ -#define FTDI_SPROG_II 0xF0C8 +/* + * Yost Engineering, Inc. products (www.yostengineering.com). + * PID 0xE050 submitted by Aaron Prose. + */ +#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ -/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ -/* they use the ftdi chipset for the USB interface and the vendor id is the same */ -#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ -#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */ -#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */ -#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */ -#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */ -#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */ -#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */ -#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */ +/* + * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). + * All of these devices use FTDI's vendor ID (0x0403). + * + * The previously included PID for the UO 100 module was incorrect. + * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58). + * + * Armin Laeuger originally sent the PID for the UM 100 module. + */ +#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */ +#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */ +#define FTDI_ELV_HS485_PID 0xE0EA /* USB to RS-485 adapter */ +#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Engery monitor EM 1010 PC */ +#define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */ +#define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */ +#define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */ +#define FTDI_ELV_RFP500_PID 0xE0F3 /* HF-Leistungsmesser (RFP 500) */ +#define FTDI_ELV_FS20SIG_PID 0xE0F4 /* Signalgeber (FS 20 SIG) */ +#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */ +#define FTDI_PHI_FISCO_PID 0xE40B /* PHI Fisco USB to Serial cable */ +#define FTDI_ELV_UAD8_PID 0xF068 /* USB-AD-Wandler (UAD 8) */ +#define FTDI_ELV_UDA7_PID 0xF069 /* USB-DA-Wandler (UDA 7) */ +#define FTDI_ELV_USI2_PID 0xF06A /* USB-Schrittmotoren-Interface (USI 2) */ +#define FTDI_ELV_T1100_PID 0xF06B /* Thermometer (T 1100) */ +#define FTDI_ELV_PCD200_PID 0xF06C /* PC-Datenlogger (PCD 200) */ +#define FTDI_ELV_ULA200_PID 0xF06D /* USB-LCD-Ansteuerung (ULA 200) */ +#define FTDI_ELV_ALC8500_PID 0xF06E /* ALC 8500 Expert */ +#define FTDI_ELV_FHZ1000PC_PID 0xF06F /* FHZ 1000 PC */ +#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ +#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ +#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ +/* Additional ELV PIDs that default to using the FTDI D2XX drivers on + * MS Windows, rather than the FTDI Virtual Com Port drivers. + * Maybe these will be easier to use with the libftdi/libusb user-space + * drivers, or possibly the Comedi drivers in some cases. */ +#define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */ +#define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */ +#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperartur-Feuchte Messgeraet (TFM 100) */ +#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkurh (UDF 77) */ +#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */ -/* Video Networks Limited / Homechoice in the UK use an ftdi-based device for their 1Mb */ -/* broadband internet service. The following PID is exhibited by the usb device supplied */ -/* (the VID is the standard ftdi vid (FTDI_VID) */ -#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ +/* + * EVER Eco Pro UPS (http://www.ever.com.pl/) + */ + +#define EVER_ECO_PRO_CDS 0xe520 /* RS-232 converter */ /* - * PCDJ use ftdi based dj-controllers. The following PID is for their DAC-2 device - * http://www.pcdjhardware.com/DAC2.asp (PID sent by Wouter Paesen) - * (the VID is the standard ftdi vid (FTDI_VID) */ -#define FTDI_PCDJ_DAC2_PID 0xFA88 + * Active Robots product ids. + */ +#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ + +/* Pyramid Computer GmbH */ +#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ + +/* www.elsterelectricity.com Elster Unicom III Optical Probe */ +#define FTDI_ELSTER_UNICOM_PID 0xE700 /* Product Id */ /* - * The following are the values for the Matrix Orbital LCD displays, - * which are the FT232BM ( similar to the 8U232AM ) + * Gude Analog- und Digitalsysteme GmbH */ -#define FTDI_MTXORB_0_PID 0xFA00 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_1_PID 0xFA01 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_2_PID 0xFA02 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_3_PID 0xFA03 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_4_PID 0xFA04 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */ -#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */ +#define FTDI_GUDEADS_E808_PID 0xE808 +#define FTDI_GUDEADS_E809_PID 0xE809 +#define FTDI_GUDEADS_E80A_PID 0xE80A +#define FTDI_GUDEADS_E80B_PID 0xE80B +#define FTDI_GUDEADS_E80C_PID 0xE80C +#define FTDI_GUDEADS_E80D_PID 0xE80D +#define FTDI_GUDEADS_E80E_PID 0xE80E +#define FTDI_GUDEADS_E80F_PID 0xE80F +#define FTDI_GUDEADS_E888_PID 0xE888 /* Expert ISDN Control USB */ +#define FTDI_GUDEADS_E889_PID 0xE889 /* USB RS-232 OptoBridge */ +#define FTDI_GUDEADS_E88A_PID 0xE88A +#define FTDI_GUDEADS_E88B_PID 0xE88B +#define FTDI_GUDEADS_E88C_PID 0xE88C +#define FTDI_GUDEADS_E88D_PID 0xE88D +#define FTDI_GUDEADS_E88E_PID 0xE88E +#define FTDI_GUDEADS_E88F_PID 0xE88F -/* OOCDlink by Joern Kaipf - * (http://www.joernonline.de/dw/doku.php?id=start&idx=projects:oocdlink) */ -#define FTDI_OOCDLINK_PID 0xbaf8 /* Amontec JTAGkey */ +/* + * Eclo (http://www.eclo.pt/) product IDs. + * PID 0xEA90 submitted by Martin Grill. + */ +#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */ + +/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ +#define FTDI_TNC_X_PID 0xEBE0 /* - * The following are the values for the Matrix Orbital FTDI Range - * Anything in this range will use an FT232RL. + * Teratronik product ids. + * Submitted by O. Wölfelschneider. */ -#define MTXORB_VID 0x1B3D -#define MTXORB_FTDI_RANGE_0100_PID 0x0100 -#define MTXORB_FTDI_RANGE_0101_PID 0x0101 -#define MTXORB_FTDI_RANGE_0102_PID 0x0102 -#define MTXORB_FTDI_RANGE_0103_PID 0x0103 -#define MTXORB_FTDI_RANGE_0104_PID 0x0104 -#define MTXORB_FTDI_RANGE_0105_PID 0x0105 -#define MTXORB_FTDI_RANGE_0106_PID 0x0106 -#define MTXORB_FTDI_RANGE_0107_PID 0x0107 -#define MTXORB_FTDI_RANGE_0108_PID 0x0108 -#define MTXORB_FTDI_RANGE_0109_PID 0x0109 -#define MTXORB_FTDI_RANGE_010A_PID 0x010A -#define MTXORB_FTDI_RANGE_010B_PID 0x010B -#define MTXORB_FTDI_RANGE_010C_PID 0x010C -#define MTXORB_FTDI_RANGE_010D_PID 0x010D -#define MTXORB_FTDI_RANGE_010E_PID 0x010E -#define MTXORB_FTDI_RANGE_010F_PID 0x010F -#define MTXORB_FTDI_RANGE_0110_PID 0x0110 -#define MTXORB_FTDI_RANGE_0111_PID 0x0111 -#define MTXORB_FTDI_RANGE_0112_PID 0x0112 -#define MTXORB_FTDI_RANGE_0113_PID 0x0113 -#define MTXORB_FTDI_RANGE_0114_PID 0x0114 -#define MTXORB_FTDI_RANGE_0115_PID 0x0115 -#define MTXORB_FTDI_RANGE_0116_PID 0x0116 -#define MTXORB_FTDI_RANGE_0117_PID 0x0117 -#define MTXORB_FTDI_RANGE_0118_PID 0x0118 -#define MTXORB_FTDI_RANGE_0119_PID 0x0119 -#define MTXORB_FTDI_RANGE_011A_PID 0x011A -#define MTXORB_FTDI_RANGE_011B_PID 0x011B -#define MTXORB_FTDI_RANGE_011C_PID 0x011C -#define MTXORB_FTDI_RANGE_011D_PID 0x011D -#define MTXORB_FTDI_RANGE_011E_PID 0x011E -#define MTXORB_FTDI_RANGE_011F_PID 0x011F -#define MTXORB_FTDI_RANGE_0120_PID 0x0120 -#define MTXORB_FTDI_RANGE_0121_PID 0x0121 -#define MTXORB_FTDI_RANGE_0122_PID 0x0122 -#define MTXORB_FTDI_RANGE_0123_PID 0x0123 -#define MTXORB_FTDI_RANGE_0124_PID 0x0124 -#define MTXORB_FTDI_RANGE_0125_PID 0x0125 -#define MTXORB_FTDI_RANGE_0126_PID 0x0126 -#define MTXORB_FTDI_RANGE_0127_PID 0x0127 -#define MTXORB_FTDI_RANGE_0128_PID 0x0128 -#define MTXORB_FTDI_RANGE_0129_PID 0x0129 -#define MTXORB_FTDI_RANGE_012A_PID 0x012A -#define MTXORB_FTDI_RANGE_012B_PID 0x012B -#define MTXORB_FTDI_RANGE_012C_PID 0x012C -#define MTXORB_FTDI_RANGE_012D_PID 0x012D -#define MTXORB_FTDI_RANGE_012E_PID 0x012E -#define MTXORB_FTDI_RANGE_012F_PID 0x012F -#define MTXORB_FTDI_RANGE_0130_PID 0x0130 -#define MTXORB_FTDI_RANGE_0131_PID 0x0131 -#define MTXORB_FTDI_RANGE_0132_PID 0x0132 -#define MTXORB_FTDI_RANGE_0133_PID 0x0133 -#define MTXORB_FTDI_RANGE_0134_PID 0x0134 -#define MTXORB_FTDI_RANGE_0135_PID 0x0135 -#define MTXORB_FTDI_RANGE_0136_PID 0x0136 -#define MTXORB_FTDI_RANGE_0137_PID 0x0137 -#define MTXORB_FTDI_RANGE_0138_PID 0x0138 -#define MTXORB_FTDI_RANGE_0139_PID 0x0139 -#define MTXORB_FTDI_RANGE_013A_PID 0x013A -#define MTXORB_FTDI_RANGE_013B_PID 0x013B -#define MTXORB_FTDI_RANGE_013C_PID 0x013C -#define MTXORB_FTDI_RANGE_013D_PID 0x013D -#define MTXORB_FTDI_RANGE_013E_PID 0x013E -#define MTXORB_FTDI_RANGE_013F_PID 0x013F -#define MTXORB_FTDI_RANGE_0140_PID 0x0140 -#define MTXORB_FTDI_RANGE_0141_PID 0x0141 -#define MTXORB_FTDI_RANGE_0142_PID 0x0142 -#define MTXORB_FTDI_RANGE_0143_PID 0x0143 -#define MTXORB_FTDI_RANGE_0144_PID 0x0144 -#define MTXORB_FTDI_RANGE_0145_PID 0x0145 -#define MTXORB_FTDI_RANGE_0146_PID 0x0146 -#define MTXORB_FTDI_RANGE_0147_PID 0x0147 -#define MTXORB_FTDI_RANGE_0148_PID 0x0148 -#define MTXORB_FTDI_RANGE_0149_PID 0x0149 -#define MTXORB_FTDI_RANGE_014A_PID 0x014A -#define MTXORB_FTDI_RANGE_014B_PID 0x014B -#define MTXORB_FTDI_RANGE_014C_PID 0x014C -#define MTXORB_FTDI_RANGE_014D_PID 0x014D -#define MTXORB_FTDI_RANGE_014E_PID 0x014E -#define MTXORB_FTDI_RANGE_014F_PID 0x014F -#define MTXORB_FTDI_RANGE_0150_PID 0x0150 -#define MTXORB_FTDI_RANGE_0151_PID 0x0151 -#define MTXORB_FTDI_RANGE_0152_PID 0x0152 -#define MTXORB_FTDI_RANGE_0153_PID 0x0153 -#define MTXORB_FTDI_RANGE_0154_PID 0x0154 -#define MTXORB_FTDI_RANGE_0155_PID 0x0155 -#define MTXORB_FTDI_RANGE_0156_PID 0x0156 -#define MTXORB_FTDI_RANGE_0157_PID 0x0157 -#define MTXORB_FTDI_RANGE_0158_PID 0x0158 -#define MTXORB_FTDI_RANGE_0159_PID 0x0159 -#define MTXORB_FTDI_RANGE_015A_PID 0x015A -#define MTXORB_FTDI_RANGE_015B_PID 0x015B -#define MTXORB_FTDI_RANGE_015C_PID 0x015C -#define MTXORB_FTDI_RANGE_015D_PID 0x015D -#define MTXORB_FTDI_RANGE_015E_PID 0x015E -#define MTXORB_FTDI_RANGE_015F_PID 0x015F -#define MTXORB_FTDI_RANGE_0160_PID 0x0160 -#define MTXORB_FTDI_RANGE_0161_PID 0x0161 -#define MTXORB_FTDI_RANGE_0162_PID 0x0162 -#define MTXORB_FTDI_RANGE_0163_PID 0x0163 -#define MTXORB_FTDI_RANGE_0164_PID 0x0164 -#define MTXORB_FTDI_RANGE_0165_PID 0x0165 -#define MTXORB_FTDI_RANGE_0166_PID 0x0166 -#define MTXORB_FTDI_RANGE_0167_PID 0x0167 -#define MTXORB_FTDI_RANGE_0168_PID 0x0168 -#define MTXORB_FTDI_RANGE_0169_PID 0x0169 -#define MTXORB_FTDI_RANGE_016A_PID 0x016A -#define MTXORB_FTDI_RANGE_016B_PID 0x016B -#define MTXORB_FTDI_RANGE_016C_PID 0x016C -#define MTXORB_FTDI_RANGE_016D_PID 0x016D -#define MTXORB_FTDI_RANGE_016E_PID 0x016E -#define MTXORB_FTDI_RANGE_016F_PID 0x016F -#define MTXORB_FTDI_RANGE_0170_PID 0x0170 -#define MTXORB_FTDI_RANGE_0171_PID 0x0171 -#define MTXORB_FTDI_RANGE_0172_PID 0x0172 -#define MTXORB_FTDI_RANGE_0173_PID 0x0173 -#define MTXORB_FTDI_RANGE_0174_PID 0x0174 -#define MTXORB_FTDI_RANGE_0175_PID 0x0175 -#define MTXORB_FTDI_RANGE_0176_PID 0x0176 -#define MTXORB_FTDI_RANGE_0177_PID 0x0177 -#define MTXORB_FTDI_RANGE_0178_PID 0x0178 -#define MTXORB_FTDI_RANGE_0179_PID 0x0179 -#define MTXORB_FTDI_RANGE_017A_PID 0x017A -#define MTXORB_FTDI_RANGE_017B_PID 0x017B -#define MTXORB_FTDI_RANGE_017C_PID 0x017C -#define MTXORB_FTDI_RANGE_017D_PID 0x017D -#define MTXORB_FTDI_RANGE_017E_PID 0x017E -#define MTXORB_FTDI_RANGE_017F_PID 0x017F -#define MTXORB_FTDI_RANGE_0180_PID 0x0180 -#define MTXORB_FTDI_RANGE_0181_PID 0x0181 -#define MTXORB_FTDI_RANGE_0182_PID 0x0182 -#define MTXORB_FTDI_RANGE_0183_PID 0x0183 -#define MTXORB_FTDI_RANGE_0184_PID 0x0184 -#define MTXORB_FTDI_RANGE_0185_PID 0x0185 -#define MTXORB_FTDI_RANGE_0186_PID 0x0186 -#define MTXORB_FTDI_RANGE_0187_PID 0x0187 -#define MTXORB_FTDI_RANGE_0188_PID 0x0188 -#define MTXORB_FTDI_RANGE_0189_PID 0x0189 -#define MTXORB_FTDI_RANGE_018A_PID 0x018A -#define MTXORB_FTDI_RANGE_018B_PID 0x018B -#define MTXORB_FTDI_RANGE_018C_PID 0x018C -#define MTXORB_FTDI_RANGE_018D_PID 0x018D -#define MTXORB_FTDI_RANGE_018E_PID 0x018E -#define MTXORB_FTDI_RANGE_018F_PID 0x018F -#define MTXORB_FTDI_RANGE_0190_PID 0x0190 -#define MTXORB_FTDI_RANGE_0191_PID 0x0191 -#define MTXORB_FTDI_RANGE_0192_PID 0x0192 -#define MTXORB_FTDI_RANGE_0193_PID 0x0193 -#define MTXORB_FTDI_RANGE_0194_PID 0x0194 -#define MTXORB_FTDI_RANGE_0195_PID 0x0195 -#define MTXORB_FTDI_RANGE_0196_PID 0x0196 -#define MTXORB_FTDI_RANGE_0197_PID 0x0197 -#define MTXORB_FTDI_RANGE_0198_PID 0x0198 -#define MTXORB_FTDI_RANGE_0199_PID 0x0199 -#define MTXORB_FTDI_RANGE_019A_PID 0x019A -#define MTXORB_FTDI_RANGE_019B_PID 0x019B -#define MTXORB_FTDI_RANGE_019C_PID 0x019C -#define MTXORB_FTDI_RANGE_019D_PID 0x019D -#define MTXORB_FTDI_RANGE_019E_PID 0x019E -#define MTXORB_FTDI_RANGE_019F_PID 0x019F -#define MTXORB_FTDI_RANGE_01A0_PID 0x01A0 -#define MTXORB_FTDI_RANGE_01A1_PID 0x01A1 -#define MTXORB_FTDI_RANGE_01A2_PID 0x01A2 -#define MTXORB_FTDI_RANGE_01A3_PID 0x01A3 -#define MTXORB_FTDI_RANGE_01A4_PID 0x01A4 -#define MTXORB_FTDI_RANGE_01A5_PID 0x01A5 -#define MTXORB_FTDI_RANGE_01A6_PID 0x01A6 -#define MTXORB_FTDI_RANGE_01A7_PID 0x01A7 -#define MTXORB_FTDI_RANGE_01A8_PID 0x01A8 -#define MTXORB_FTDI_RANGE_01A9_PID 0x01A9 -#define MTXORB_FTDI_RANGE_01AA_PID 0x01AA -#define MTXORB_FTDI_RANGE_01AB_PID 0x01AB -#define MTXORB_FTDI_RANGE_01AC_PID 0x01AC -#define MTXORB_FTDI_RANGE_01AD_PID 0x01AD -#define MTXORB_FTDI_RANGE_01AE_PID 0x01AE -#define MTXORB_FTDI_RANGE_01AF_PID 0x01AF -#define MTXORB_FTDI_RANGE_01B0_PID 0x01B0 -#define MTXORB_FTDI_RANGE_01B1_PID 0x01B1 -#define MTXORB_FTDI_RANGE_01B2_PID 0x01B2 -#define MTXORB_FTDI_RANGE_01B3_PID 0x01B3 -#define MTXORB_FTDI_RANGE_01B4_PID 0x01B4 -#define MTXORB_FTDI_RANGE_01B5_PID 0x01B5 -#define MTXORB_FTDI_RANGE_01B6_PID 0x01B6 -#define MTXORB_FTDI_RANGE_01B7_PID 0x01B7 -#define MTXORB_FTDI_RANGE_01B8_PID 0x01B8 -#define MTXORB_FTDI_RANGE_01B9_PID 0x01B9 -#define MTXORB_FTDI_RANGE_01BA_PID 0x01BA -#define MTXORB_FTDI_RANGE_01BB_PID 0x01BB -#define MTXORB_FTDI_RANGE_01BC_PID 0x01BC -#define MTXORB_FTDI_RANGE_01BD_PID 0x01BD -#define MTXORB_FTDI_RANGE_01BE_PID 0x01BE -#define MTXORB_FTDI_RANGE_01BF_PID 0x01BF -#define MTXORB_FTDI_RANGE_01C0_PID 0x01C0 -#define MTXORB_FTDI_RANGE_01C1_PID 0x01C1 -#define MTXORB_FTDI_RANGE_01C2_PID 0x01C2 -#define MTXORB_FTDI_RANGE_01C3_PID 0x01C3 -#define MTXORB_FTDI_RANGE_01C4_PID 0x01C4 -#define MTXORB_FTDI_RANGE_01C5_PID 0x01C5 -#define MTXORB_FTDI_RANGE_01C6_PID 0x01C6 -#define MTXORB_FTDI_RANGE_01C7_PID 0x01C7 -#define MTXORB_FTDI_RANGE_01C8_PID 0x01C8 -#define MTXORB_FTDI_RANGE_01C9_PID 0x01C9 -#define MTXORB_FTDI_RANGE_01CA_PID 0x01CA -#define MTXORB_FTDI_RANGE_01CB_PID 0x01CB -#define MTXORB_FTDI_RANGE_01CC_PID 0x01CC -#define MTXORB_FTDI_RANGE_01CD_PID 0x01CD -#define MTXORB_FTDI_RANGE_01CE_PID 0x01CE -#define MTXORB_FTDI_RANGE_01CF_PID 0x01CF -#define MTXORB_FTDI_RANGE_01D0_PID 0x01D0 -#define MTXORB_FTDI_RANGE_01D1_PID 0x01D1 -#define MTXORB_FTDI_RANGE_01D2_PID 0x01D2 -#define MTXORB_FTDI_RANGE_01D3_PID 0x01D3 -#define MTXORB_FTDI_RANGE_01D4_PID 0x01D4 -#define MTXORB_FTDI_RANGE_01D5_PID 0x01D5 -#define MTXORB_FTDI_RANGE_01D6_PID 0x01D6 -#define MTXORB_FTDI_RANGE_01D7_PID 0x01D7 -#define MTXORB_FTDI_RANGE_01D8_PID 0x01D8 -#define MTXORB_FTDI_RANGE_01D9_PID 0x01D9 -#define MTXORB_FTDI_RANGE_01DA_PID 0x01DA -#define MTXORB_FTDI_RANGE_01DB_PID 0x01DB -#define MTXORB_FTDI_RANGE_01DC_PID 0x01DC -#define MTXORB_FTDI_RANGE_01DD_PID 0x01DD -#define MTXORB_FTDI_RANGE_01DE_PID 0x01DE -#define MTXORB_FTDI_RANGE_01DF_PID 0x01DF -#define MTXORB_FTDI_RANGE_01E0_PID 0x01E0 -#define MTXORB_FTDI_RANGE_01E1_PID 0x01E1 -#define MTXORB_FTDI_RANGE_01E2_PID 0x01E2 -#define MTXORB_FTDI_RANGE_01E3_PID 0x01E3 -#define MTXORB_FTDI_RANGE_01E4_PID 0x01E4 -#define MTXORB_FTDI_RANGE_01E5_PID 0x01E5 -#define MTXORB_FTDI_RANGE_01E6_PID 0x01E6 -#define MTXORB_FTDI_RANGE_01E7_PID 0x01E7 -#define MTXORB_FTDI_RANGE_01E8_PID 0x01E8 -#define MTXORB_FTDI_RANGE_01E9_PID 0x01E9 -#define MTXORB_FTDI_RANGE_01EA_PID 0x01EA -#define MTXORB_FTDI_RANGE_01EB_PID 0x01EB -#define MTXORB_FTDI_RANGE_01EC_PID 0x01EC -#define MTXORB_FTDI_RANGE_01ED_PID 0x01ED -#define MTXORB_FTDI_RANGE_01EE_PID 0x01EE -#define MTXORB_FTDI_RANGE_01EF_PID 0x01EF -#define MTXORB_FTDI_RANGE_01F0_PID 0x01F0 -#define MTXORB_FTDI_RANGE_01F1_PID 0x01F1 -#define MTXORB_FTDI_RANGE_01F2_PID 0x01F2 -#define MTXORB_FTDI_RANGE_01F3_PID 0x01F3 -#define MTXORB_FTDI_RANGE_01F4_PID 0x01F4 -#define MTXORB_FTDI_RANGE_01F5_PID 0x01F5 -#define MTXORB_FTDI_RANGE_01F6_PID 0x01F6 -#define MTXORB_FTDI_RANGE_01F7_PID 0x01F7 -#define MTXORB_FTDI_RANGE_01F8_PID 0x01F8 -#define MTXORB_FTDI_RANGE_01F9_PID 0x01F9 -#define MTXORB_FTDI_RANGE_01FA_PID 0x01FA -#define MTXORB_FTDI_RANGE_01FB_PID 0x01FB -#define MTXORB_FTDI_RANGE_01FC_PID 0x01FC -#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD -#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE -#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF - - - -/* Interbiometrics USB I/O Board */ -/* Developed for Interbiometrics by Rudolf Gugler */ -#define INTERBIOMETRICS_VID 0x1209 -#define INTERBIOMETRICS_IOBOARD_PID 0x1002 -#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006 - -/* - * The following are the values for the Perle Systems - * UltraPort USB serial converters - */ -#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0 /* Perle UltraPort Product Id */ - -/* - * The following are the values for the Sealevel SeaLINK+ adapters. - * (Original list sent by Tuan Hoang. Ian Abbott renamed the macros and - * removed some PIDs that don't seem to match any existing products.) - */ -#define SEALEVEL_VID 0x0c52 /* Sealevel Vendor ID */ -#define SEALEVEL_2101_PID 0x2101 /* SeaLINK+232 (2101/2105) */ -#define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ -#define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ -#define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ -#define SEALEVEL_2106_PID 0x9020 /* SeaLINK+422 (2106) */ -#define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ -#define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ -#define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ -#define SEALEVEL_2202_2_PID 0x2222 /* SeaPORT+2/485 (2202) Port 2 */ -#define SEALEVEL_2203_1_PID 0x2213 /* SeaPORT+2 (2203) Port 1 */ -#define SEALEVEL_2203_2_PID 0x2223 /* SeaPORT+2 (2203) Port 2 */ -#define SEALEVEL_2401_1_PID 0x2411 /* SeaPORT+4/232 (2401) Port 1 */ -#define SEALEVEL_2401_2_PID 0x2421 /* SeaPORT+4/232 (2401) Port 2 */ -#define SEALEVEL_2401_3_PID 0x2431 /* SeaPORT+4/232 (2401) Port 3 */ -#define SEALEVEL_2401_4_PID 0x2441 /* SeaPORT+4/232 (2401) Port 4 */ -#define SEALEVEL_2402_1_PID 0x2412 /* SeaPORT+4/485 (2402) Port 1 */ -#define SEALEVEL_2402_2_PID 0x2422 /* SeaPORT+4/485 (2402) Port 2 */ -#define SEALEVEL_2402_3_PID 0x2432 /* SeaPORT+4/485 (2402) Port 3 */ -#define SEALEVEL_2402_4_PID 0x2442 /* SeaPORT+4/485 (2402) Port 4 */ -#define SEALEVEL_2403_1_PID 0x2413 /* SeaPORT+4 (2403) Port 1 */ -#define SEALEVEL_2403_2_PID 0x2423 /* SeaPORT+4 (2403) Port 2 */ -#define SEALEVEL_2403_3_PID 0x2433 /* SeaPORT+4 (2403) Port 3 */ -#define SEALEVEL_2403_4_PID 0x2443 /* SeaPORT+4 (2403) Port 4 */ -#define SEALEVEL_2801_1_PID 0X2811 /* SeaLINK+8/232 (2801) Port 1 */ -#define SEALEVEL_2801_2_PID 0X2821 /* SeaLINK+8/232 (2801) Port 2 */ -#define SEALEVEL_2801_3_PID 0X2831 /* SeaLINK+8/232 (2801) Port 3 */ -#define SEALEVEL_2801_4_PID 0X2841 /* SeaLINK+8/232 (2801) Port 4 */ -#define SEALEVEL_2801_5_PID 0X2851 /* SeaLINK+8/232 (2801) Port 5 */ -#define SEALEVEL_2801_6_PID 0X2861 /* SeaLINK+8/232 (2801) Port 6 */ -#define SEALEVEL_2801_7_PID 0X2871 /* SeaLINK+8/232 (2801) Port 7 */ -#define SEALEVEL_2801_8_PID 0X2881 /* SeaLINK+8/232 (2801) Port 8 */ -#define SEALEVEL_2802_1_PID 0X2812 /* SeaLINK+8/485 (2802) Port 1 */ -#define SEALEVEL_2802_2_PID 0X2822 /* SeaLINK+8/485 (2802) Port 2 */ -#define SEALEVEL_2802_3_PID 0X2832 /* SeaLINK+8/485 (2802) Port 3 */ -#define SEALEVEL_2802_4_PID 0X2842 /* SeaLINK+8/485 (2802) Port 4 */ -#define SEALEVEL_2802_5_PID 0X2852 /* SeaLINK+8/485 (2802) Port 5 */ -#define SEALEVEL_2802_6_PID 0X2862 /* SeaLINK+8/485 (2802) Port 6 */ -#define SEALEVEL_2802_7_PID 0X2872 /* SeaLINK+8/485 (2802) Port 7 */ -#define SEALEVEL_2802_8_PID 0X2882 /* SeaLINK+8/485 (2802) Port 8 */ -#define SEALEVEL_2803_1_PID 0X2813 /* SeaLINK+8 (2803) Port 1 */ -#define SEALEVEL_2803_2_PID 0X2823 /* SeaLINK+8 (2803) Port 2 */ -#define SEALEVEL_2803_3_PID 0X2833 /* SeaLINK+8 (2803) Port 3 */ -#define SEALEVEL_2803_4_PID 0X2843 /* SeaLINK+8 (2803) Port 4 */ -#define SEALEVEL_2803_5_PID 0X2853 /* SeaLINK+8 (2803) Port 5 */ -#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ -#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ -#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ +#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */ +#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */ -/* - * The following are the values for two KOBIL chipcard terminals. - */ -#define KOBIL_VID 0x0d46 /* KOBIL Vendor ID */ -#define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */ -#define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ +/* Rig Expert Ukraine devices */ +#define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */ /* - * Icom ID-1 digital transceiver + * Hameg HO820 and HO870 interface (using VID 0x0403) */ - -#define ICOM_ID1_VID 0x0C26 -#define ICOM_ID1_PID 0x0004 +#define HAMEG_HO820_PID 0xed74 +#define HAMEG_HO870_PID 0xed71 /* - * ASK.fr devices + * MaxStream devices www.maxstream.net */ -#define FTDI_ASK_RDR400_PID 0xC991 /* ASK RDR 400 series card reader */ +#define FTDI_MAXSTREAM_PID 0xEE18 /* Xbee PKG-U Module */ /* - * FTDI USB UART chips used in construction projects from the - * Elektor Electronics magazine (http://elektor-electronics.co.uk) + * microHAM product IDs (http://www.microham.com). + * Submitted by Justin Burket (KL1RL) + * and Mike Studer (K6EEP) . + * Ian Abbott added a few more from the driver INF file. */ -#define ELEKTOR_VID 0x0C7D -#define ELEKTOR_FT323R_PID 0x0005 /* RFID-Reader, issue 09-2006 */ +#define FTDI_MHAM_KW_PID 0xEEE8 /* USB-KW interface */ +#define FTDI_MHAM_YS_PID 0xEEE9 /* USB-YS interface */ +#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */ +#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */ +#define FTDI_MHAM_IC_PID 0xEEEC /* USB-IC interface */ +#define FTDI_MHAM_DB9_PID 0xEEED /* USB-DB9 interface */ +#define FTDI_MHAM_RS232_PID 0xEEEE /* USB-RS232 interface */ +#define FTDI_MHAM_Y9_PID 0xEEEF /* USB-Y9 interface */ -/* - * DSS-20 Sync Station for Sony Ericsson P800 - */ -#define FTDI_DSS20_PID 0xFC82 +/* Domintell products http://www.domintell.com */ +#define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ +#define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ /* - * Home Electronics (www.home-electro.com) USB gadgets + * The following are the values for the Perle Systems + * UltraPort USB serial converters */ -#define FTDI_HE_TIRA1_PID 0xFA78 /* Tira-1 IR transceiver */ +#define FTDI_PERLE_ULTRAPORT_PID 0xF0C0 /* Perle UltraPort Product Id */ -/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */ -/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ -#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ +/* Sprog II (Andrew Crosland's SprogII DCC interface) */ +#define FTDI_SPROG_II 0xF0C8 -/* TNC-X USB-to-packet-radio adapter, versions prior to 3.0 (DLP module) */ +/* an infrared receiver for user access control with IR tags */ +#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ -#define FTDI_TNC_X_PID 0xEBE0 +/* ACT Solutions HomePro ZWave interface + (http://www.act-solutions.com/HomePro.htm) */ +#define FTDI_ACTZWAVE_PID 0xF2D0 -/* - * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). - * All of these devices use FTDI's vendor ID (0x0403). - * - * The previously included PID for the UO 100 module was incorrect. - * In fact, that PID was for ELV's UR 100 USB-RS232 converter (0xFB58). - * - * Armin Laeuger originally sent the PID for the UM 100 module. - */ -#define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG */ -#define FTDI_ELV_UR100_PID 0xFB58 /* USB-RS232-Umsetzer (UR 100) */ -#define FTDI_ELV_UM100_PID 0xFB5A /* USB-Modul UM 100 */ -#define FTDI_ELV_UO100_PID 0xFB5B /* USB-Modul UO 100 */ -#define FTDI_ELV_ALC8500_PID 0xF06E /* ALC 8500 Expert */ -/* Additional ELV PIDs that default to using the FTDI D2XX drivers on - * MS Windows, rather than the FTDI Virtual Com Port drivers. - * Maybe these will be easier to use with the libftdi/libusb user-space - * drivers, or possibly the Comedi drivers in some cases. */ -#define FTDI_ELV_CLI7000_PID 0xFB59 /* Computer-Light-Interface (CLI 7000) */ -#define FTDI_ELV_PPS7330_PID 0xFB5C /* Processor-Power-Supply (PPS 7330) */ -#define FTDI_ELV_TFM100_PID 0xFB5D /* Temperartur-Feuchte Messgeraet (TFM 100) */ -#define FTDI_ELV_UDF77_PID 0xFB5E /* USB DCF Funkurh (UDF 77) */ -#define FTDI_ELV_UIO88_PID 0xFB5F /* USB-I/O Interface (UIO 88) */ -#define FTDI_ELV_UAD8_PID 0xF068 /* USB-AD-Wandler (UAD 8) */ -#define FTDI_ELV_UDA7_PID 0xF069 /* USB-DA-Wandler (UDA 7) */ -#define FTDI_ELV_USI2_PID 0xF06A /* USB-Schrittmotoren-Interface (USI 2) */ -#define FTDI_ELV_T1100_PID 0xF06B /* Thermometer (T 1100) */ -#define FTDI_ELV_PCD200_PID 0xF06C /* PC-Datenlogger (PCD 200) */ -#define FTDI_ELV_ULA200_PID 0xF06D /* USB-LCD-Ansteuerung (ULA 200) */ -#define FTDI_ELV_FHZ1000PC_PID 0xF06F /* FHZ 1000 PC */ -#define FTDI_ELV_CSI8_PID 0xE0F0 /* Computer-Schalt-Interface (CSI 8) */ -#define FTDI_ELV_EM1000DL_PID 0xE0F1 /* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */ -#define FTDI_ELV_PCK100_PID 0xE0F2 /* PC-Kabeltester (PCK 100) */ -#define FTDI_ELV_RFP500_PID 0xE0F3 /* HF-Leistungsmesser (RFP 500) */ -#define FTDI_ELV_FS20SIG_PID 0xE0F4 /* Signalgeber (FS 20 SIG) */ -#define FTDI_ELV_WS300PC_PID 0xE0F6 /* PC-Wetterstation (WS 300 PC) */ -#define FTDI_ELV_FHZ1300PC_PID 0xE0E8 /* FHZ 1300 PC */ -#define FTDI_ELV_WS500_PID 0xE0E9 /* PC-Wetterstation (WS 500) */ -#define FTDI_ELV_HS485_PID 0xE0EA /* USB to RS-485 adapter */ -#define FTDI_ELV_EM1010PC_PID 0xE0EF /* Engery monitor EM 1010 PC */ -#define FTDI_PHI_FISCO_PID 0xE40B /* PHI Fisco USB to Serial cable */ +/* + * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485, + * USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices + * and I'm not entirely sure which are used by which. + */ +#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 +#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 /* - * Definitions for ID TECH (www.idt-net.com) devices + * Linx Technologies product ids */ -#define IDTECH_VID 0x0ACD /* ID TECH Vendor ID */ -#define IDTECH_IDT1221U_PID 0x0300 /* IDT1221U USB to RS-232 adapter */ +#define LINX_SDMUSBQSS_PID 0xF448 /* Linx SDM-USB-QS-S */ +#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ +#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ +#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ +#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ /* - * Definitions for Omnidirectional Control Technology, Inc. devices + * Oceanic product ids */ -#define OCT_VID 0x0B39 /* OCT vendor ID */ -/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ -/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ -/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ -#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ +#define FTDI_OCEANIC_PID 0xF460 /* Oceanic dive instrument */ -/* an infrared receiver for user access control with IR tags */ -#define FTDI_PIEGROUP_PID 0xF208 /* Product Id */ +/* + * SUUNTO product ids + */ +#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ + +/* USB-UIRT - An infrared receiver and transmitter using the 8U232AM chip */ +/* http://home.earthlink.net/~jrhees/USBUIRT/index.htm */ +#define FTDI_USB_UIRT_PID 0xF850 /* Product Id */ + +/* CCS Inc. ICDU/ICDU40 product ID - + * the FT232BM is used in an in-circuit-debugger unit for PIC16's/PIC18's */ +#define FTDI_CCSICDU20_0_PID 0xF9D0 +#define FTDI_CCSICDU40_1_PID 0xF9D1 +#define FTDI_CCSMACHX_2_PID 0xF9D2 +#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3 +#define FTDI_CCSICDU64_4_PID 0xF9D4 +#define FTDI_CCSPRIME8_5_PID 0xF9D5 /* - * Definitions for Artemis astronomical USB based cameras - * Check it at http://www.artemisccd.co.uk/ + * The following are the values for the Matrix Orbital LCD displays, + * which are the FT232BM ( similar to the 8U232AM ) */ -#define FTDI_ARTEMIS_PID 0xDF28 /* All Artemis Cameras */ +#define FTDI_MTXORB_0_PID 0xFA00 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_1_PID 0xFA01 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_2_PID 0xFA02 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_3_PID 0xFA03 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_4_PID 0xFA04 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_5_PID 0xFA05 /* Matrix Orbital Product Id */ +#define FTDI_MTXORB_6_PID 0xFA06 /* Matrix Orbital Product Id */ /* - * Definitions for ATIK Instruments astronomical USB based cameras - * Check it at http://www.atik-instruments.com/ + * Home Electronics (www.home-electro.com) USB gadgets */ -#define FTDI_ATIK_ATK16_PID 0xDF30 /* ATIK ATK-16 Grayscale Camera */ -#define FTDI_ATIK_ATK16C_PID 0xDF32 /* ATIK ATK-16C Colour Camera */ -#define FTDI_ATIK_ATK16HR_PID 0xDF31 /* ATIK ATK-16HR Grayscale Camera */ -#define FTDI_ATIK_ATK16HRC_PID 0xDF33 /* ATIK ATK-16HRC Colour Camera */ -#define FTDI_ATIK_ATK16IC_PID 0xDF35 /* ATIK ATK-16IC Grayscale Camera */ +#define FTDI_HE_TIRA1_PID 0xFA78 /* Tira-1 IR transceiver */ + +/* Inside Accesso contactless reader (http://www.insidefr.com) */ +#define INSIDE_ACCESSO 0xFAD0 + +/* + * ThorLabs USB motor drivers + */ +#define FTDI_THORLABS_PID 0xfaf0 /* ThorLabs USB motor drivers */ /* * Protego product ids @@ -569,75 +375,106 @@ #define PROTEGO_SPECIAL_4 0xFC73 /* special/unknown device */ /* - * Gude Analog- und Digitalsysteme GmbH + * DSS-20 Sync Station for Sony Ericsson P800 */ -#define FTDI_GUDEADS_E808_PID 0xE808 -#define FTDI_GUDEADS_E809_PID 0xE809 -#define FTDI_GUDEADS_E80A_PID 0xE80A -#define FTDI_GUDEADS_E80B_PID 0xE80B -#define FTDI_GUDEADS_E80C_PID 0xE80C -#define FTDI_GUDEADS_E80D_PID 0xE80D -#define FTDI_GUDEADS_E80E_PID 0xE80E -#define FTDI_GUDEADS_E80F_PID 0xE80F -#define FTDI_GUDEADS_E888_PID 0xE888 /* Expert ISDN Control USB */ -#define FTDI_GUDEADS_E889_PID 0xE889 /* USB RS-232 OptoBridge */ -#define FTDI_GUDEADS_E88A_PID 0xE88A -#define FTDI_GUDEADS_E88B_PID 0xE88B -#define FTDI_GUDEADS_E88C_PID 0xE88C -#define FTDI_GUDEADS_E88D_PID 0xE88D -#define FTDI_GUDEADS_E88E_PID 0xE88E -#define FTDI_GUDEADS_E88F_PID 0xE88F +#define FTDI_DSS20_PID 0xFC82 + +/* www.irtrans.de device */ +#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ /* - * Linx Technologies product ids + * RM Michaelides CANview USB (http://www.rmcan.com) (FTDI_VID) + * CAN fieldbus interface adapter, added by port GmbH www.port.de) + * Ian Abbott changed the macro names for consistency. */ -#define LINX_SDMUSBQSS_PID 0xF448 /* Linx SDM-USB-QS-S */ -#define LINX_MASTERDEVEL2_PID 0xF449 /* Linx Master Development 2.0 */ -#define LINX_FUTURE_0_PID 0xF44A /* Linx future device */ -#define LINX_FUTURE_1_PID 0xF44B /* Linx future device */ -#define LINX_FUTURE_2_PID 0xF44C /* Linx future device */ +#define FTDI_RM_CANVIEW_PID 0xfd60 /* Product Id */ +/* www.thoughttechnology.com/ TT-USB provide with procomp use ftdi_sio */ +#define FTDI_TTUSB_PID 0xFF20 /* Product Id */ -/* CCS Inc. ICDU/ICDU40 product ID - the FT232BM is used in an in-circuit-debugger */ -/* unit for PIC16's/PIC18's */ -#define FTDI_CCSICDU20_0_PID 0xF9D0 -#define FTDI_CCSICDU40_1_PID 0xF9D1 -#define FTDI_CCSMACHX_2_PID 0xF9D2 -#define FTDI_CCSLOAD_N_GO_3_PID 0xF9D3 -#define FTDI_CCSICDU64_4_PID 0xF9D4 -#define FTDI_CCSPRIME8_5_PID 0xF9D5 +#define FTDI_USBX_707_PID 0xF857 /* ADSTech IR Blaster USBX-707 (FTDI_VID) */ -/* Inside Accesso contactless reader (http://www.insidefr.com) */ -#define INSIDE_ACCESSO 0xFAD0 +#define FTDI_RELAIS_PID 0xFA10 /* Relais device from Rudolf Gugler */ /* - * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI + * PCDJ use ftdi based dj-controllers. The following PID is + * for their DAC-2 device http://www.pcdjhardware.com/DAC2.asp + * (the VID is the standard ftdi vid (FTDI_VID), PID sent by Wouter Paesen) */ -#define INTREPID_VID 0x093C -#define INTREPID_VALUECAN_PID 0x0601 -#define INTREPID_NEOVI_PID 0x0701 +#define FTDI_PCDJ_DAC2_PID 0xFA88 + +#define FTDI_R2000KU_TRUE_RNG 0xFB80 /* R2000KU TRUE RNG (FTDI_VID) */ /* - * Falcom Wireless Communications GmbH + * DIEBOLD BCS SE923 (FTDI_VID) */ -#define FALCOM_VID 0x0F94 /* Vendor Id */ -#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */ -#define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */ +#define DIEBOLD_BCS_SE923_PID 0xfb99 + +/* www.crystalfontz.com devices + * - thanx for providing free devices for evaluation ! + * they use the ftdi chipset for the USB interface + * and the vendor id is the same + */ +#define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ +#define FTDI_XF_634_PID 0xFC09 /* 634: 20x4 Character Display */ +#define FTDI_XF_547_PID 0xFC0A /* 547: Two line Display */ +#define FTDI_XF_633_PID 0xFC0B /* 633: 16x2 Character Display with Keys */ +#define FTDI_XF_631_PID 0xFC0C /* 631: 20x2 Character Display */ +#define FTDI_XF_635_PID 0xFC0D /* 635: 20x4 Character Display */ +#define FTDI_XF_640_PID 0xFC0E /* 640: Two line Display */ +#define FTDI_XF_642_PID 0xFC0F /* 642: Two line Display */ /* - * SUUNTO product ids + * Video Networks Limited / Homechoice in the UK use an ftdi-based device + * for their 1Mb broadband internet service. The following PID is exhibited + * by the usb device supplied (the VID is the standard ftdi vid (FTDI_VID) */ -#define FTDI_SUUNTO_SPORTS_PID 0xF680 /* Suunto Sports instrument */ +#define FTDI_VNHCPCUSB_D_PID 0xfe38 /* Product Id */ + +/* AlphaMicro Components AMC-232USB01 device (FTDI_VID) */ +#define FTDI_AMC232_PID 0xFF00 /* Product Id */ /* - * Oceanic product ids + * IBS elektronik product ids (FTDI_VID) + * Submitted by Thomas Schleusener */ -#define FTDI_OCEANIC_PID 0xF460 /* Oceanic dive instrument */ +#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */ +#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */ +#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */ +#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */ +#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */ +#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */ +#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ +#define FTDI_IBS_PROD_PID 0xff3f /* future device */ +/* www.canusb.com Lawicel CANUSB device (FTDI_VID) */ +#define FTDI_CANUSB_PID 0xFFA8 /* Product Id */ + + + +/********************************/ +/** third-party VID/PID combos **/ +/********************************/ + + /* - * TTi (Thurlby Thandar Instruments) + * Atmel STK541 */ -#define TTI_VID 0x103E /* Vendor Id */ -#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ +#define ATMEL_VID 0x03eb /* Vendor ID */ +#define STK541_PID 0x2109 /* Zigbee Controller */ + +/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +#define ADI_VID 0x0456 +#define ADI_GNICE_PID 0xF000 +#define ADI_GNICEPLUS_PID 0xF001 + +/* + * RATOC REX-USB60F + */ +#define RATOC_VENDOR_ID 0x0584 +#define RATOC_PRODUCT_ID_USB60F 0xb020 /* * Definitions for B&B Electronics products. @@ -662,141 +499,147 @@ #define BANDB_ZZ_PROG1_USB_PID 0xBA02 /* - * RM Michaelides CANview USB (http://www.rmcan.com) - * CAN fieldbus interface adapter, added by port GmbH www.port.de) - * Ian Abbott changed the macro names for consistency. - */ -#define FTDI_RM_CANVIEW_PID 0xfd60 /* Product Id */ - -/* - * EVER Eco Pro UPS (http://www.ever.com.pl/) - */ - -#define EVER_ECO_PRO_CDS 0xe520 /* RS-232 converter */ - -/* - * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485, - * USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices - * and I'm not entirely sure which are used by which. - */ -#define FTDI_4N_GALAXY_DE_1_PID 0xF3C0 -#define FTDI_4N_GALAXY_DE_2_PID 0xF3C1 - -/* - * Mobility Electronics products. - */ -#define MOBILITY_VID 0x1342 -#define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ - -/* - * microHAM product IDs (http://www.microham.com). - * Submitted by Justin Burket (KL1RL) - * and Mike Studer (K6EEP) . - * Ian Abbott added a few more from the driver INF file. - */ -#define FTDI_MHAM_KW_PID 0xEEE8 /* USB-KW interface */ -#define FTDI_MHAM_YS_PID 0xEEE9 /* USB-YS interface */ -#define FTDI_MHAM_Y6_PID 0xEEEA /* USB-Y6 interface */ -#define FTDI_MHAM_Y8_PID 0xEEEB /* USB-Y8 interface */ -#define FTDI_MHAM_IC_PID 0xEEEC /* USB-IC interface */ -#define FTDI_MHAM_DB9_PID 0xEEED /* USB-DB9 interface */ -#define FTDI_MHAM_RS232_PID 0xEEEE /* USB-RS232 interface */ -#define FTDI_MHAM_Y9_PID 0xEEEF /* USB-Y9 interface */ - -/* - * Active Robots product ids. - */ -#define FTDI_ACTIVE_ROBOTS_PID 0xE548 /* USB comms board */ - -/* - * Xsens Technologies BV products (http://www.xsens.com). + * Intrepid Control Systems (http://www.intrepidcs.com/) ValueCAN and NeoVI */ -#define XSENS_CONVERTER_0_PID 0xD388 -#define XSENS_CONVERTER_1_PID 0xD389 -#define XSENS_CONVERTER_2_PID 0xD38A -#define XSENS_CONVERTER_3_PID 0xD38B -#define XSENS_CONVERTER_4_PID 0xD38C -#define XSENS_CONVERTER_5_PID 0xD38D -#define XSENS_CONVERTER_6_PID 0xD38E -#define XSENS_CONVERTER_7_PID 0xD38F +#define INTREPID_VID 0x093C +#define INTREPID_VALUECAN_PID 0x0601 +#define INTREPID_NEOVI_PID 0x0701 /* - * Teratronik product ids. - * Submitted by O. Wölfelschneider. + * Definitions for ID TECH (www.idt-net.com) devices */ -#define FTDI_TERATRONIK_VCP_PID 0xEC88 /* Teratronik device (preferring VCP driver on windows) */ -#define FTDI_TERATRONIK_D2XX_PID 0xEC89 /* Teratronik device (preferring D2XX driver on windows) */ +#define IDTECH_VID 0x0ACD /* ID TECH Vendor ID */ +#define IDTECH_IDT1221U_PID 0x0300 /* IDT1221U USB to RS-232 adapter */ /* - * Evolution Robotics products (http://www.evolution.com/). - * Submitted by Shawn M. Lavelle. + * Definitions for Omnidirectional Control Technology, Inc. devices */ -#define EVOLUTION_VID 0xDEEE /* Vendor ID */ -#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ -#define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/ -#define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/ -#define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */ - -/* Pyramid Computer GmbH */ -#define FTDI_PYRAMID_PID 0xE6C8 /* Pyramid Appliance Display */ +#define OCT_VID 0x0B39 /* OCT vendor ID */ +/* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */ +/* Also rebadged as Dick Smith Electronics (Aus) XH6451 */ +/* Also rebadged as SIIG Inc. model US2308 hardware version 1 */ +#define OCT_US101_PID 0x0421 /* OCT US101 USB to RS-232 */ /* - * NDI (www.ndigital.com) product ids + * Icom ID-1 digital transceiver */ -#define FTDI_NDI_HUC_PID 0xDA70 /* NDI Host USB Converter */ -#define FTDI_NDI_SPECTRA_SCU_PID 0xDA71 /* NDI Spectra SCU */ -#define FTDI_NDI_FUTURE_2_PID 0xDA72 /* NDI future device #2 */ -#define FTDI_NDI_FUTURE_3_PID 0xDA73 /* NDI future device #3 */ -#define FTDI_NDI_AURORA_SCU_PID 0xDA74 /* NDI Aurora SCU */ + +#define ICOM_ID1_VID 0x0C26 +#define ICOM_ID1_PID 0x0004 /* - * Posiflex inc retail equipment (http://www.posiflex.com.tw) + * GN Otometrics (http://www.otometrics.com) + * Submitted by Ville Sundberg. */ -#define POSIFLEX_VID 0x0d3a /* Vendor ID */ -#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */ +#define GN_OTOMETRICS_VID 0x0c33 /* Vendor ID */ +#define AURICAL_USB_PID 0x0010 /* Aurical USB Audiometer */ /* - * Westrex International devices submitted by Cory Lee + * The following are the values for the Sealevel SeaLINK+ adapters. + * (Original list sent by Tuan Hoang. Ian Abbott renamed the macros and + * removed some PIDs that don't seem to match any existing products.) */ -#define FTDI_WESTREX_MODEL_777_PID 0xDC00 /* Model 777 */ -#define FTDI_WESTREX_MODEL_8900F_PID 0xDC01 /* Model 8900F */ +#define SEALEVEL_VID 0x0c52 /* Sealevel Vendor ID */ +#define SEALEVEL_2101_PID 0x2101 /* SeaLINK+232 (2101/2105) */ +#define SEALEVEL_2102_PID 0x2102 /* SeaLINK+485 (2102) */ +#define SEALEVEL_2103_PID 0x2103 /* SeaLINK+232I (2103) */ +#define SEALEVEL_2104_PID 0x2104 /* SeaLINK+485I (2104) */ +#define SEALEVEL_2106_PID 0x9020 /* SeaLINK+422 (2106) */ +#define SEALEVEL_2201_1_PID 0x2211 /* SeaPORT+2/232 (2201) Port 1 */ +#define SEALEVEL_2201_2_PID 0x2221 /* SeaPORT+2/232 (2201) Port 2 */ +#define SEALEVEL_2202_1_PID 0x2212 /* SeaPORT+2/485 (2202) Port 1 */ +#define SEALEVEL_2202_2_PID 0x2222 /* SeaPORT+2/485 (2202) Port 2 */ +#define SEALEVEL_2203_1_PID 0x2213 /* SeaPORT+2 (2203) Port 1 */ +#define SEALEVEL_2203_2_PID 0x2223 /* SeaPORT+2 (2203) Port 2 */ +#define SEALEVEL_2401_1_PID 0x2411 /* SeaPORT+4/232 (2401) Port 1 */ +#define SEALEVEL_2401_2_PID 0x2421 /* SeaPORT+4/232 (2401) Port 2 */ +#define SEALEVEL_2401_3_PID 0x2431 /* SeaPORT+4/232 (2401) Port 3 */ +#define SEALEVEL_2401_4_PID 0x2441 /* SeaPORT+4/232 (2401) Port 4 */ +#define SEALEVEL_2402_1_PID 0x2412 /* SeaPORT+4/485 (2402) Port 1 */ +#define SEALEVEL_2402_2_PID 0x2422 /* SeaPORT+4/485 (2402) Port 2 */ +#define SEALEVEL_2402_3_PID 0x2432 /* SeaPORT+4/485 (2402) Port 3 */ +#define SEALEVEL_2402_4_PID 0x2442 /* SeaPORT+4/485 (2402) Port 4 */ +#define SEALEVEL_2403_1_PID 0x2413 /* SeaPORT+4 (2403) Port 1 */ +#define SEALEVEL_2403_2_PID 0x2423 /* SeaPORT+4 (2403) Port 2 */ +#define SEALEVEL_2403_3_PID 0x2433 /* SeaPORT+4 (2403) Port 3 */ +#define SEALEVEL_2403_4_PID 0x2443 /* SeaPORT+4 (2403) Port 4 */ +#define SEALEVEL_2801_1_PID 0X2811 /* SeaLINK+8/232 (2801) Port 1 */ +#define SEALEVEL_2801_2_PID 0X2821 /* SeaLINK+8/232 (2801) Port 2 */ +#define SEALEVEL_2801_3_PID 0X2831 /* SeaLINK+8/232 (2801) Port 3 */ +#define SEALEVEL_2801_4_PID 0X2841 /* SeaLINK+8/232 (2801) Port 4 */ +#define SEALEVEL_2801_5_PID 0X2851 /* SeaLINK+8/232 (2801) Port 5 */ +#define SEALEVEL_2801_6_PID 0X2861 /* SeaLINK+8/232 (2801) Port 6 */ +#define SEALEVEL_2801_7_PID 0X2871 /* SeaLINK+8/232 (2801) Port 7 */ +#define SEALEVEL_2801_8_PID 0X2881 /* SeaLINK+8/232 (2801) Port 8 */ +#define SEALEVEL_2802_1_PID 0X2812 /* SeaLINK+8/485 (2802) Port 1 */ +#define SEALEVEL_2802_2_PID 0X2822 /* SeaLINK+8/485 (2802) Port 2 */ +#define SEALEVEL_2802_3_PID 0X2832 /* SeaLINK+8/485 (2802) Port 3 */ +#define SEALEVEL_2802_4_PID 0X2842 /* SeaLINK+8/485 (2802) Port 4 */ +#define SEALEVEL_2802_5_PID 0X2852 /* SeaLINK+8/485 (2802) Port 5 */ +#define SEALEVEL_2802_6_PID 0X2862 /* SeaLINK+8/485 (2802) Port 6 */ +#define SEALEVEL_2802_7_PID 0X2872 /* SeaLINK+8/485 (2802) Port 7 */ +#define SEALEVEL_2802_8_PID 0X2882 /* SeaLINK+8/485 (2802) Port 8 */ +#define SEALEVEL_2803_1_PID 0X2813 /* SeaLINK+8 (2803) Port 1 */ +#define SEALEVEL_2803_2_PID 0X2823 /* SeaLINK+8 (2803) Port 2 */ +#define SEALEVEL_2803_3_PID 0X2833 /* SeaLINK+8 (2803) Port 3 */ +#define SEALEVEL_2803_4_PID 0X2843 /* SeaLINK+8 (2803) Port 4 */ +#define SEALEVEL_2803_5_PID 0X2853 /* SeaLINK+8 (2803) Port 5 */ +#define SEALEVEL_2803_6_PID 0X2863 /* SeaLINK+8 (2803) Port 6 */ +#define SEALEVEL_2803_7_PID 0X2873 /* SeaLINK+8 (2803) Port 7 */ +#define SEALEVEL_2803_8_PID 0X2883 /* SeaLINK+8 (2803) Port 8 */ /* - * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) + * JETI SPECTROMETER SPECBOS 1201 + * http://www.jeti.com/products/sys/scb/scb1201.php */ -#define FTDI_RRCIRKITS_LOCOBUFFER_PID 0xc7d0 /* LocoBuffer USB */ +#define JETI_VID 0x0c6c +#define JETI_SPC1201_PID 0x04b2 /* - * Eclo (http://www.eclo.pt/) product IDs. - * PID 0xEA90 submitted by Martin Grill. + * FTDI USB UART chips used in construction projects from the + * Elektor Electronics magazine (http://elektor-electronics.co.uk) */ -#define FTDI_ECLO_COM_1WIRE_PID 0xEA90 /* COM to 1-Wire USB adaptor */ +#define ELEKTOR_VID 0x0C7D +#define ELEKTOR_FT323R_PID 0x0005 /* RFID-Reader, issue 09-2006 */ /* - * Papouch products (http://www.papouch.com/) - * Submitted by Folkert van Heusden + * Posiflex inc retail equipment (http://www.posiflex.com.tw) */ - -#define PAPOUCH_VID 0x5050 /* Vendor ID */ -#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ -#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */ +#define POSIFLEX_VID 0x0d3a /* Vendor ID */ +#define POSIFLEX_PP7000_PID 0x0300 /* PP-7000II thermal printer */ /* - * ACG Identification Technologies GmbH products (http://www.acg.de/). - * Submitted by anton -at- goto10 -dot- org. + * The following are the values for two KOBIL chipcard terminals. */ -#define FTDI_ACG_HFDUAL_PID 0xDD20 /* HF Dual ISO Reader (RFID) */ +#define KOBIL_VID 0x0d46 /* KOBIL Vendor ID */ +#define KOBIL_CONV_B1_PID 0x2020 /* KOBIL Konverter for B1 */ +#define KOBIL_CONV_KAAN_PID 0x2021 /* KOBIL_Konverter for KAAN */ + +#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ +#define FTDI_NF_RIC_PID 0x0001 /* Product Id */ /* - * Yost Engineering, Inc. products (www.yostengineering.com). - * PID 0xE050 submitted by Aaron Prose. + * Falcom Wireless Communications GmbH */ -#define FTDI_YEI_SERVOCENTER31_PID 0xE050 /* YEI ServoCenter3.1 USB */ +#define FALCOM_VID 0x0F94 /* Vendor Id */ +#define FALCOM_TWIST_PID 0x0001 /* Falcom Twist USB GPRS modem */ +#define FALCOM_SAMBA_PID 0x0005 /* Falcom Samba USB GPRS modem */ + +/* Larsen and Brusgaard AltiTrack/USBtrack */ +#define LARSENBRUSGAARD_VID 0x0FD8 +#define LB_ALTITRACK_PID 0x0001 /* - * ThorLabs USB motor drivers + * TTi (Thurlby Thandar Instruments) */ -#define FTDI_THORLABS_PID 0xfaf0 /* ThorLabs USB motor drivers */ +#define TTI_VID 0x103E /* Vendor Id */ +#define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ + +/* Interbiometrics USB I/O Board */ +/* Developed for Interbiometrics by Rudolf Gugler */ +#define INTERBIOMETRICS_VID 0x1209 +#define INTERBIOMETRICS_IOBOARD_PID 0x1002 +#define INTERBIOMETRICS_MINI_IOBOARD_PID 0x1006 /* * Testo products (http://www.testo.com/) @@ -806,18 +649,21 @@ #define TESTO_USB_INTERFACE_PID 0x0001 /* - * Gamma Scout (http://gamma-scout.com/). Submitted by rsc@runtux.com. + * Mobility Electronics products. */ -#define FTDI_GAMMA_SCOUT_PID 0xD678 /* Gamma Scout online */ +#define MOBILITY_VID 0x1342 +#define MOBILITY_USB_SERIAL_PID 0x0202 /* EasiDock USB 200 serial */ /* - * Tactrix OpenPort (ECU) devices. - * OpenPort 1.3M submitted by Donour Sizemore. - * OpenPort 1.3S and 1.3U submitted by Ian Abbott. + * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3 + * Submitted by Harald Welte */ -#define FTDI_TACTRIX_OPENPORT_13M_PID 0xCC48 /* OpenPort 1.3 Mitsubishi */ -#define FTDI_TACTRIX_OPENPORT_13S_PID 0xCC49 /* OpenPort 1.3 Subaru */ -#define FTDI_TACTRIX_OPENPORT_13U_PID 0xCC4A /* OpenPort 1.3 Universal */ +#define FIC_VID 0x1457 +#define FIC_NEO1973_DEBUG_PID 0x5118 + +/* Olimex */ +#define OLIMEX_VID 0x15BA +#define OLIMEX_ARM_USB_OCD_PID 0x0003 /* * Telldus Technologies @@ -826,34 +672,275 @@ #define TELLDUS_TELLSTICK_PID 0x0C30 /* RF control dongle 433 MHz using FT232RL */ /* - * IBS elektronik product ids - * Submitted by Thomas Schleusener + * Bayer Ascensia Contour blood glucose meter USB-converter cable. + * http://winglucofacts.com/cables/ */ -#define FTDI_IBS_US485_PID 0xff38 /* IBS US485 (USB<-->RS422/485 interface) */ -#define FTDI_IBS_PICPRO_PID 0xff39 /* IBS PIC-Programmer */ -#define FTDI_IBS_PCMCIA_PID 0xff3a /* IBS Card reader for PCMCIA SRAM-cards */ -#define FTDI_IBS_PK1_PID 0xff3b /* IBS PK1 - Particel counter */ -#define FTDI_IBS_RS232MON_PID 0xff3c /* IBS RS232 - Monitor */ -#define FTDI_IBS_APP70_PID 0xff3d /* APP 70 (dust monitoring system) */ -#define FTDI_IBS_PEDO_PID 0xff3e /* IBS PEDO-Modem (RF modem 868.35 MHz) */ -#define FTDI_IBS_PROD_PID 0xff3f /* future device */ +#define BAYER_VID 0x1A79 +#define BAYER_CONTOUR_CABLE_PID 0x6001 /* - * MaxStream devices www.maxstream.net + * The following are the values for the Matrix Orbital FTDI Range + * Anything in this range will use an FT232RL. */ -#define FTDI_MAXSTREAM_PID 0xEE18 /* Xbee PKG-U Module */ - -/* Olimex */ -#define OLIMEX_VID 0x15BA -#define OLIMEX_ARM_USB_OCD_PID 0x0003 +#define MTXORB_VID 0x1B3D +#define MTXORB_FTDI_RANGE_0100_PID 0x0100 +#define MTXORB_FTDI_RANGE_0101_PID 0x0101 +#define MTXORB_FTDI_RANGE_0102_PID 0x0102 +#define MTXORB_FTDI_RANGE_0103_PID 0x0103 +#define MTXORB_FTDI_RANGE_0104_PID 0x0104 +#define MTXORB_FTDI_RANGE_0105_PID 0x0105 +#define MTXORB_FTDI_RANGE_0106_PID 0x0106 +#define MTXORB_FTDI_RANGE_0107_PID 0x0107 +#define MTXORB_FTDI_RANGE_0108_PID 0x0108 +#define MTXORB_FTDI_RANGE_0109_PID 0x0109 +#define MTXORB_FTDI_RANGE_010A_PID 0x010A +#define MTXORB_FTDI_RANGE_010B_PID 0x010B +#define MTXORB_FTDI_RANGE_010C_PID 0x010C +#define MTXORB_FTDI_RANGE_010D_PID 0x010D +#define MTXORB_FTDI_RANGE_010E_PID 0x010E +#define MTXORB_FTDI_RANGE_010F_PID 0x010F +#define MTXORB_FTDI_RANGE_0110_PID 0x0110 +#define MTXORB_FTDI_RANGE_0111_PID 0x0111 +#define MTXORB_FTDI_RANGE_0112_PID 0x0112 +#define MTXORB_FTDI_RANGE_0113_PID 0x0113 +#define MTXORB_FTDI_RANGE_0114_PID 0x0114 +#define MTXORB_FTDI_RANGE_0115_PID 0x0115 +#define MTXORB_FTDI_RANGE_0116_PID 0x0116 +#define MTXORB_FTDI_RANGE_0117_PID 0x0117 +#define MTXORB_FTDI_RANGE_0118_PID 0x0118 +#define MTXORB_FTDI_RANGE_0119_PID 0x0119 +#define MTXORB_FTDI_RANGE_011A_PID 0x011A +#define MTXORB_FTDI_RANGE_011B_PID 0x011B +#define MTXORB_FTDI_RANGE_011C_PID 0x011C +#define MTXORB_FTDI_RANGE_011D_PID 0x011D +#define MTXORB_FTDI_RANGE_011E_PID 0x011E +#define MTXORB_FTDI_RANGE_011F_PID 0x011F +#define MTXORB_FTDI_RANGE_0120_PID 0x0120 +#define MTXORB_FTDI_RANGE_0121_PID 0x0121 +#define MTXORB_FTDI_RANGE_0122_PID 0x0122 +#define MTXORB_FTDI_RANGE_0123_PID 0x0123 +#define MTXORB_FTDI_RANGE_0124_PID 0x0124 +#define MTXORB_FTDI_RANGE_0125_PID 0x0125 +#define MTXORB_FTDI_RANGE_0126_PID 0x0126 +#define MTXORB_FTDI_RANGE_0127_PID 0x0127 +#define MTXORB_FTDI_RANGE_0128_PID 0x0128 +#define MTXORB_FTDI_RANGE_0129_PID 0x0129 +#define MTXORB_FTDI_RANGE_012A_PID 0x012A +#define MTXORB_FTDI_RANGE_012B_PID 0x012B +#define MTXORB_FTDI_RANGE_012C_PID 0x012C +#define MTXORB_FTDI_RANGE_012D_PID 0x012D +#define MTXORB_FTDI_RANGE_012E_PID 0x012E +#define MTXORB_FTDI_RANGE_012F_PID 0x012F +#define MTXORB_FTDI_RANGE_0130_PID 0x0130 +#define MTXORB_FTDI_RANGE_0131_PID 0x0131 +#define MTXORB_FTDI_RANGE_0132_PID 0x0132 +#define MTXORB_FTDI_RANGE_0133_PID 0x0133 +#define MTXORB_FTDI_RANGE_0134_PID 0x0134 +#define MTXORB_FTDI_RANGE_0135_PID 0x0135 +#define MTXORB_FTDI_RANGE_0136_PID 0x0136 +#define MTXORB_FTDI_RANGE_0137_PID 0x0137 +#define MTXORB_FTDI_RANGE_0138_PID 0x0138 +#define MTXORB_FTDI_RANGE_0139_PID 0x0139 +#define MTXORB_FTDI_RANGE_013A_PID 0x013A +#define MTXORB_FTDI_RANGE_013B_PID 0x013B +#define MTXORB_FTDI_RANGE_013C_PID 0x013C +#define MTXORB_FTDI_RANGE_013D_PID 0x013D +#define MTXORB_FTDI_RANGE_013E_PID 0x013E +#define MTXORB_FTDI_RANGE_013F_PID 0x013F +#define MTXORB_FTDI_RANGE_0140_PID 0x0140 +#define MTXORB_FTDI_RANGE_0141_PID 0x0141 +#define MTXORB_FTDI_RANGE_0142_PID 0x0142 +#define MTXORB_FTDI_RANGE_0143_PID 0x0143 +#define MTXORB_FTDI_RANGE_0144_PID 0x0144 +#define MTXORB_FTDI_RANGE_0145_PID 0x0145 +#define MTXORB_FTDI_RANGE_0146_PID 0x0146 +#define MTXORB_FTDI_RANGE_0147_PID 0x0147 +#define MTXORB_FTDI_RANGE_0148_PID 0x0148 +#define MTXORB_FTDI_RANGE_0149_PID 0x0149 +#define MTXORB_FTDI_RANGE_014A_PID 0x014A +#define MTXORB_FTDI_RANGE_014B_PID 0x014B +#define MTXORB_FTDI_RANGE_014C_PID 0x014C +#define MTXORB_FTDI_RANGE_014D_PID 0x014D +#define MTXORB_FTDI_RANGE_014E_PID 0x014E +#define MTXORB_FTDI_RANGE_014F_PID 0x014F +#define MTXORB_FTDI_RANGE_0150_PID 0x0150 +#define MTXORB_FTDI_RANGE_0151_PID 0x0151 +#define MTXORB_FTDI_RANGE_0152_PID 0x0152 +#define MTXORB_FTDI_RANGE_0153_PID 0x0153 +#define MTXORB_FTDI_RANGE_0154_PID 0x0154 +#define MTXORB_FTDI_RANGE_0155_PID 0x0155 +#define MTXORB_FTDI_RANGE_0156_PID 0x0156 +#define MTXORB_FTDI_RANGE_0157_PID 0x0157 +#define MTXORB_FTDI_RANGE_0158_PID 0x0158 +#define MTXORB_FTDI_RANGE_0159_PID 0x0159 +#define MTXORB_FTDI_RANGE_015A_PID 0x015A +#define MTXORB_FTDI_RANGE_015B_PID 0x015B +#define MTXORB_FTDI_RANGE_015C_PID 0x015C +#define MTXORB_FTDI_RANGE_015D_PID 0x015D +#define MTXORB_FTDI_RANGE_015E_PID 0x015E +#define MTXORB_FTDI_RANGE_015F_PID 0x015F +#define MTXORB_FTDI_RANGE_0160_PID 0x0160 +#define MTXORB_FTDI_RANGE_0161_PID 0x0161 +#define MTXORB_FTDI_RANGE_0162_PID 0x0162 +#define MTXORB_FTDI_RANGE_0163_PID 0x0163 +#define MTXORB_FTDI_RANGE_0164_PID 0x0164 +#define MTXORB_FTDI_RANGE_0165_PID 0x0165 +#define MTXORB_FTDI_RANGE_0166_PID 0x0166 +#define MTXORB_FTDI_RANGE_0167_PID 0x0167 +#define MTXORB_FTDI_RANGE_0168_PID 0x0168 +#define MTXORB_FTDI_RANGE_0169_PID 0x0169 +#define MTXORB_FTDI_RANGE_016A_PID 0x016A +#define MTXORB_FTDI_RANGE_016B_PID 0x016B +#define MTXORB_FTDI_RANGE_016C_PID 0x016C +#define MTXORB_FTDI_RANGE_016D_PID 0x016D +#define MTXORB_FTDI_RANGE_016E_PID 0x016E +#define MTXORB_FTDI_RANGE_016F_PID 0x016F +#define MTXORB_FTDI_RANGE_0170_PID 0x0170 +#define MTXORB_FTDI_RANGE_0171_PID 0x0171 +#define MTXORB_FTDI_RANGE_0172_PID 0x0172 +#define MTXORB_FTDI_RANGE_0173_PID 0x0173 +#define MTXORB_FTDI_RANGE_0174_PID 0x0174 +#define MTXORB_FTDI_RANGE_0175_PID 0x0175 +#define MTXORB_FTDI_RANGE_0176_PID 0x0176 +#define MTXORB_FTDI_RANGE_0177_PID 0x0177 +#define MTXORB_FTDI_RANGE_0178_PID 0x0178 +#define MTXORB_FTDI_RANGE_0179_PID 0x0179 +#define MTXORB_FTDI_RANGE_017A_PID 0x017A +#define MTXORB_FTDI_RANGE_017B_PID 0x017B +#define MTXORB_FTDI_RANGE_017C_PID 0x017C +#define MTXORB_FTDI_RANGE_017D_PID 0x017D +#define MTXORB_FTDI_RANGE_017E_PID 0x017E +#define MTXORB_FTDI_RANGE_017F_PID 0x017F +#define MTXORB_FTDI_RANGE_0180_PID 0x0180 +#define MTXORB_FTDI_RANGE_0181_PID 0x0181 +#define MTXORB_FTDI_RANGE_0182_PID 0x0182 +#define MTXORB_FTDI_RANGE_0183_PID 0x0183 +#define MTXORB_FTDI_RANGE_0184_PID 0x0184 +#define MTXORB_FTDI_RANGE_0185_PID 0x0185 +#define MTXORB_FTDI_RANGE_0186_PID 0x0186 +#define MTXORB_FTDI_RANGE_0187_PID 0x0187 +#define MTXORB_FTDI_RANGE_0188_PID 0x0188 +#define MTXORB_FTDI_RANGE_0189_PID 0x0189 +#define MTXORB_FTDI_RANGE_018A_PID 0x018A +#define MTXORB_FTDI_RANGE_018B_PID 0x018B +#define MTXORB_FTDI_RANGE_018C_PID 0x018C +#define MTXORB_FTDI_RANGE_018D_PID 0x018D +#define MTXORB_FTDI_RANGE_018E_PID 0x018E +#define MTXORB_FTDI_RANGE_018F_PID 0x018F +#define MTXORB_FTDI_RANGE_0190_PID 0x0190 +#define MTXORB_FTDI_RANGE_0191_PID 0x0191 +#define MTXORB_FTDI_RANGE_0192_PID 0x0192 +#define MTXORB_FTDI_RANGE_0193_PID 0x0193 +#define MTXORB_FTDI_RANGE_0194_PID 0x0194 +#define MTXORB_FTDI_RANGE_0195_PID 0x0195 +#define MTXORB_FTDI_RANGE_0196_PID 0x0196 +#define MTXORB_FTDI_RANGE_0197_PID 0x0197 +#define MTXORB_FTDI_RANGE_0198_PID 0x0198 +#define MTXORB_FTDI_RANGE_0199_PID 0x0199 +#define MTXORB_FTDI_RANGE_019A_PID 0x019A +#define MTXORB_FTDI_RANGE_019B_PID 0x019B +#define MTXORB_FTDI_RANGE_019C_PID 0x019C +#define MTXORB_FTDI_RANGE_019D_PID 0x019D +#define MTXORB_FTDI_RANGE_019E_PID 0x019E +#define MTXORB_FTDI_RANGE_019F_PID 0x019F +#define MTXORB_FTDI_RANGE_01A0_PID 0x01A0 +#define MTXORB_FTDI_RANGE_01A1_PID 0x01A1 +#define MTXORB_FTDI_RANGE_01A2_PID 0x01A2 +#define MTXORB_FTDI_RANGE_01A3_PID 0x01A3 +#define MTXORB_FTDI_RANGE_01A4_PID 0x01A4 +#define MTXORB_FTDI_RANGE_01A5_PID 0x01A5 +#define MTXORB_FTDI_RANGE_01A6_PID 0x01A6 +#define MTXORB_FTDI_RANGE_01A7_PID 0x01A7 +#define MTXORB_FTDI_RANGE_01A8_PID 0x01A8 +#define MTXORB_FTDI_RANGE_01A9_PID 0x01A9 +#define MTXORB_FTDI_RANGE_01AA_PID 0x01AA +#define MTXORB_FTDI_RANGE_01AB_PID 0x01AB +#define MTXORB_FTDI_RANGE_01AC_PID 0x01AC +#define MTXORB_FTDI_RANGE_01AD_PID 0x01AD +#define MTXORB_FTDI_RANGE_01AE_PID 0x01AE +#define MTXORB_FTDI_RANGE_01AF_PID 0x01AF +#define MTXORB_FTDI_RANGE_01B0_PID 0x01B0 +#define MTXORB_FTDI_RANGE_01B1_PID 0x01B1 +#define MTXORB_FTDI_RANGE_01B2_PID 0x01B2 +#define MTXORB_FTDI_RANGE_01B3_PID 0x01B3 +#define MTXORB_FTDI_RANGE_01B4_PID 0x01B4 +#define MTXORB_FTDI_RANGE_01B5_PID 0x01B5 +#define MTXORB_FTDI_RANGE_01B6_PID 0x01B6 +#define MTXORB_FTDI_RANGE_01B7_PID 0x01B7 +#define MTXORB_FTDI_RANGE_01B8_PID 0x01B8 +#define MTXORB_FTDI_RANGE_01B9_PID 0x01B9 +#define MTXORB_FTDI_RANGE_01BA_PID 0x01BA +#define MTXORB_FTDI_RANGE_01BB_PID 0x01BB +#define MTXORB_FTDI_RANGE_01BC_PID 0x01BC +#define MTXORB_FTDI_RANGE_01BD_PID 0x01BD +#define MTXORB_FTDI_RANGE_01BE_PID 0x01BE +#define MTXORB_FTDI_RANGE_01BF_PID 0x01BF +#define MTXORB_FTDI_RANGE_01C0_PID 0x01C0 +#define MTXORB_FTDI_RANGE_01C1_PID 0x01C1 +#define MTXORB_FTDI_RANGE_01C2_PID 0x01C2 +#define MTXORB_FTDI_RANGE_01C3_PID 0x01C3 +#define MTXORB_FTDI_RANGE_01C4_PID 0x01C4 +#define MTXORB_FTDI_RANGE_01C5_PID 0x01C5 +#define MTXORB_FTDI_RANGE_01C6_PID 0x01C6 +#define MTXORB_FTDI_RANGE_01C7_PID 0x01C7 +#define MTXORB_FTDI_RANGE_01C8_PID 0x01C8 +#define MTXORB_FTDI_RANGE_01C9_PID 0x01C9 +#define MTXORB_FTDI_RANGE_01CA_PID 0x01CA +#define MTXORB_FTDI_RANGE_01CB_PID 0x01CB +#define MTXORB_FTDI_RANGE_01CC_PID 0x01CC +#define MTXORB_FTDI_RANGE_01CD_PID 0x01CD +#define MTXORB_FTDI_RANGE_01CE_PID 0x01CE +#define MTXORB_FTDI_RANGE_01CF_PID 0x01CF +#define MTXORB_FTDI_RANGE_01D0_PID 0x01D0 +#define MTXORB_FTDI_RANGE_01D1_PID 0x01D1 +#define MTXORB_FTDI_RANGE_01D2_PID 0x01D2 +#define MTXORB_FTDI_RANGE_01D3_PID 0x01D3 +#define MTXORB_FTDI_RANGE_01D4_PID 0x01D4 +#define MTXORB_FTDI_RANGE_01D5_PID 0x01D5 +#define MTXORB_FTDI_RANGE_01D6_PID 0x01D6 +#define MTXORB_FTDI_RANGE_01D7_PID 0x01D7 +#define MTXORB_FTDI_RANGE_01D8_PID 0x01D8 +#define MTXORB_FTDI_RANGE_01D9_PID 0x01D9 +#define MTXORB_FTDI_RANGE_01DA_PID 0x01DA +#define MTXORB_FTDI_RANGE_01DB_PID 0x01DB +#define MTXORB_FTDI_RANGE_01DC_PID 0x01DC +#define MTXORB_FTDI_RANGE_01DD_PID 0x01DD +#define MTXORB_FTDI_RANGE_01DE_PID 0x01DE +#define MTXORB_FTDI_RANGE_01DF_PID 0x01DF +#define MTXORB_FTDI_RANGE_01E0_PID 0x01E0 +#define MTXORB_FTDI_RANGE_01E1_PID 0x01E1 +#define MTXORB_FTDI_RANGE_01E2_PID 0x01E2 +#define MTXORB_FTDI_RANGE_01E3_PID 0x01E3 +#define MTXORB_FTDI_RANGE_01E4_PID 0x01E4 +#define MTXORB_FTDI_RANGE_01E5_PID 0x01E5 +#define MTXORB_FTDI_RANGE_01E6_PID 0x01E6 +#define MTXORB_FTDI_RANGE_01E7_PID 0x01E7 +#define MTXORB_FTDI_RANGE_01E8_PID 0x01E8 +#define MTXORB_FTDI_RANGE_01E9_PID 0x01E9 +#define MTXORB_FTDI_RANGE_01EA_PID 0x01EA +#define MTXORB_FTDI_RANGE_01EB_PID 0x01EB +#define MTXORB_FTDI_RANGE_01EC_PID 0x01EC +#define MTXORB_FTDI_RANGE_01ED_PID 0x01ED +#define MTXORB_FTDI_RANGE_01EE_PID 0x01EE +#define MTXORB_FTDI_RANGE_01EF_PID 0x01EF +#define MTXORB_FTDI_RANGE_01F0_PID 0x01F0 +#define MTXORB_FTDI_RANGE_01F1_PID 0x01F1 +#define MTXORB_FTDI_RANGE_01F2_PID 0x01F2 +#define MTXORB_FTDI_RANGE_01F3_PID 0x01F3 +#define MTXORB_FTDI_RANGE_01F4_PID 0x01F4 +#define MTXORB_FTDI_RANGE_01F5_PID 0x01F5 +#define MTXORB_FTDI_RANGE_01F6_PID 0x01F6 +#define MTXORB_FTDI_RANGE_01F7_PID 0x01F7 +#define MTXORB_FTDI_RANGE_01F8_PID 0x01F8 +#define MTXORB_FTDI_RANGE_01F9_PID 0x01F9 +#define MTXORB_FTDI_RANGE_01FA_PID 0x01FA +#define MTXORB_FTDI_RANGE_01FB_PID 0x01FB +#define MTXORB_FTDI_RANGE_01FC_PID 0x01FC +#define MTXORB_FTDI_RANGE_01FD_PID 0x01FD +#define MTXORB_FTDI_RANGE_01FE_PID 0x01FE +#define MTXORB_FTDI_RANGE_01FF_PID 0x01FF -/* Luminary Micro Stellaris Boards, VID = FTDI_VID */ -/* FTDI 2332C Dual channel device, side A=245 FIFO (JTAG), Side B=RS232 UART */ -#define LMI_LM3S_DEVEL_BOARD_PID 0xbcd8 -#define LMI_LM3S_EVAL_BOARD_PID 0xbcd9 -/* www.elsterelectricity.com Elster Unicom III Optical Probe */ -#define FTDI_ELSTER_UNICOM_PID 0xE700 /* Product Id */ /* * The Mobility Lab (TML) @@ -862,44 +949,10 @@ #define TML_VID 0x1B91 /* Vendor ID */ #define TML_USB_SERIAL_PID 0x0064 /* USB - Serial Converter */ -/* Propox devices */ -#define FTDI_PROPOX_JTAGCABLEII_PID 0xD738 - -/* Rig Expert Ukraine devices */ -#define FTDI_REU_TINY_PID 0xED22 /* RigExpert Tiny */ - -/* Domintell products http://www.domintell.com */ -#define FTDI_DOMINTELL_DGQG_PID 0xEF50 /* Master */ -#define FTDI_DOMINTELL_DUSB_PID 0xEF51 /* DUSB01 module */ - /* Alti-2 products http://www.alti-2.com */ #define ALTI2_VID 0x1BC9 #define ALTI2_N3_PID 0x6001 /* Neptune 3 */ -/* - * FIC / OpenMoko, Inc. http://wiki.openmoko.org/wiki/Neo1973_Debug_Board_v3 - * Submitted by Harald Welte - */ -#define FIC_VID 0x1457 -#define FIC_NEO1973_DEBUG_PID 0x5118 - -/* - * RATOC REX-USB60F - */ -#define RATOC_VENDOR_ID 0x0584 -#define RATOC_PRODUCT_ID_USB60F 0xb020 - -/* - * DIEBOLD BCS SE923 - */ -#define DIEBOLD_BCS_SE923_PID 0xfb99 - -/* - * Atmel STK541 - */ -#define ATMEL_VID 0x03eb /* Vendor ID */ -#define STK541_PID 0x2109 /* Zigbee Controller */ - /* * Dresden Elektronic Sensor Terminal Board */ @@ -908,19 +961,13 @@ #define WHT_PID 0x0004 /* Wireless Handheld Terminal */ /* - * Blackfin gnICE JTAG - * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + * Papouch products (http://www.papouch.com/) + * Submitted by Folkert van Heusden */ -#define ADI_VID 0x0456 -#define ADI_GNICE_PID 0xF000 -#define ADI_GNICEPLUS_PID 0xF001 -/* - * JETI SPECTROMETER SPECBOS 1201 - * http://www.jeti.com/products/sys/scb/scb1201.php - */ -#define JETI_VID 0x0c6c -#define JETI_SPC1201_PID 0x04b2 +#define PAPOUCH_VID 0x5050 /* Vendor ID */ +#define PAPOUCH_TMU_PID 0x0400 /* TMU USB Thermometer */ +#define PAPOUCH_QUIDO4x4_PID 0x0900 /* Quido 4/4 Module */ /* * Marvell SheevaPlug @@ -928,32 +975,12 @@ #define MARVELL_VID 0x9e88 #define MARVELL_SHEEVAPLUG_PID 0x9e8f -#define FTDI_TURTELIZER_PID 0xBDC8 /* JTAG/RS-232 adapter by egnite GmBH */ - /* - * GN Otometrics (http://www.otometrics.com) - * Submitted by Ville Sundberg. - */ -#define GN_OTOMETRICS_VID 0x0c33 /* Vendor ID */ -#define AURICAL_USB_PID 0x0010 /* Aurical USB Audiometer */ - -/* - * Bayer Ascensia Contour blood glucose meter USB-converter cable. - * http://winglucofacts.com/cables/ - */ -#define BAYER_VID 0x1A79 -#define BAYER_CONTOUR_CABLE_PID 0x6001 - -/* - * Marvell OpenRD Base, Client - * http://www.open-rd.org - * OpenRD Base, Client use VID 0x0403 - */ -#define MARVELL_OPENRD_PID 0x9e90 - -/* - * Hameg HO820 and HO870 interface (using VID 0x0403) + * Evolution Robotics products (http://www.evolution.com/). + * Submitted by Shawn M. Lavelle. */ -#define HAMEG_HO820_PID 0xed74 -#define HAMEG_HO870_PID 0xed71 - +#define EVOLUTION_VID 0xDEEE /* Vendor ID */ +#define EVOLUTION_ER1_PID 0x0300 /* ER1 Control Module */ +#define EVO_8U232AM_PID 0x02FF /* Evolution robotics RCM2 (FT232AM)*/ +#define EVO_HYBRID_PID 0x0302 /* Evolution robotics RCM4 PID (FT232BM)*/ +#define EVO_RCM4_PID 0x0303 /* Evolution robotics RCM4 PID */ -- cgit v1.2.3-70-g09d2 From 95962a773ca5c1e52305fd1003d3bda59abbf371 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Wed, 16 Dec 2009 20:38:31 +0300 Subject: USB: musb_gadget: fix kernel oops in txstate() Commit 7723de7e19b744144975a09c81777ec0f14ac5b3 (USB: musb_gadget: remove pointless loop) included uncalled for (and incorrect) optimization that might cause a kernel oops in txstate() -- undo it. Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index c49b9ba025a..4dea1460925 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -515,12 +515,12 @@ void musb_g_tx(struct musb *musb, u8 epnum) if (csr & MUSB_TXCSR_FIFONOTEMPTY) return; - if (!musb_ep->desc) { + request = musb_ep->desc ? next_request(musb_ep) : NULL; + if (!request) { DBG(4, "%s idle now\n", musb_ep->end_point.name); return; - } else - request = next_request(musb_ep); + } } txstate(musb, to_musb_request(request)); -- cgit v1.2.3-70-g09d2 From e3060b175c1bd60586f51482464530dd1b37f3cf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 15 Dec 2009 11:08:41 +0200 Subject: USB: musb: move musb_remove to __exit probe() already was on __init, so moving remove() to __exit. Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index bfe08f4975a..1041bb734bb 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2139,7 +2139,7 @@ static int __init musb_probe(struct platform_device *pdev) return musb_init_controller(dev, irq, base); } -static int __devexit musb_remove(struct platform_device *pdev) +static int __exit musb_remove(struct platform_device *pdev) { struct musb *musb = dev_to_musb(&pdev->dev); void __iomem *ctrl_base = musb->ctrl_base; @@ -2231,7 +2231,7 @@ static struct platform_driver musb_driver = { .owner = THIS_MODULE, .pm = MUSB_DEV_PM_OPS, }, - .remove = __devexit_p(musb_remove), + .remove = __exit_p(musb_remove), .shutdown = musb_shutdown, }; -- cgit v1.2.3-70-g09d2 From f95c4c0186aa94ad41681d8f0ecd79cc45f92bda Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Tue, 15 Dec 2009 11:08:44 +0200 Subject: USB: musb: fix compiling warning with min() macro Current musb gadget dma code produces the warning: drivers/usb/musb/musb_gadget.c: In function 'txstate': drivers/usb/musb/musb_gadget.c:312: warning: comparison of distinct pointer types lacks a cast So switch to min_t(size_t, ...). Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 4dea1460925..0c36925c593 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -309,7 +309,7 @@ static void txstate(struct musb *musb, struct musb_request *req) size_t request_size; /* setup DMA, then program endpoint CSR */ - request_size = min(request->length, + request_size = min_t(size_t, request->length, musb_ep->dma->max_len); if (request_size < musb_ep->packet_sz) musb_ep->dma->desired_mode = 0; -- cgit v1.2.3-70-g09d2 From a2396a32b848a9864f933ced860192c72c769aca Mon Sep 17 00:00:00 2001 From: Swaminathan S Date: Tue, 15 Dec 2009 13:29:57 +0200 Subject: USB: musb: Populate the VBUS GPIO with the correct GPIO number This fixes a null-pointer dereference bug. Signed-off-by: Swaminathan S Cc: David Brownell Acked-by: Sergei Shtylyov Acked-by: Anand Gadiyar Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/davinci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index e16ff605c45..66913811af5 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -42,7 +42,7 @@ #include "musb_core.h" #ifdef CONFIG_MACH_DAVINCI_EVM -#define GPIO_nVBUS_DRV 144 +#define GPIO_nVBUS_DRV 160 #endif #include "davinci.h" -- cgit v1.2.3-70-g09d2 From d4c433fe6f04195a1a0d2146d9f11ad45eecef86 Mon Sep 17 00:00:00 2001 From: Arnaud Mandy Date: Tue, 15 Dec 2009 13:29:58 +0200 Subject: USB: musb: gadget: set otg tranceiver to idle when registering gadget When registering gadget driver, the state of the transceiver must be set from undefined (no gadget) to b_idle. Module unload sets the transceiver state to undefined state. After the first load/unload pair, the reset irq will be lost. Signed-off-by: Arnaud Mandy Signed-off-by: Felipe Balbi Cc: David Brownell Acked-by: Anand Gadiyar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 0c36925c593..e164999bd36 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1731,6 +1731,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) spin_lock_irqsave(&musb->lock, flags); otg_set_peripheral(musb->xceiv, &musb->g); + musb->xceiv->state = OTG_STATE_B_IDLE; musb->is_active = 1; /* FIXME this ignores the softconnect flag. Drivers are -- cgit v1.2.3-70-g09d2 From cd42fef0a0b061817904fd6feb0de66830794857 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 15 Dec 2009 13:47:30 +0200 Subject: USB: musb: do not work if no gadget driver is loaded On OTG and gadget-only configurations, we need a gadget driver in order to work properly, so avoid changing operation modes when there's no gadget driver loaded. Signed-off-by: Felipe Balbi Cc: David Brownell Acked-by: Anand Gadiyar Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 1041bb734bb..24ff09754e0 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1521,6 +1521,14 @@ irqreturn_t musb_interrupt(struct musb *musb) (devctl & MUSB_DEVCTL_HM) ? "host" : "peripheral", musb->int_usb, musb->int_tx, musb->int_rx); +#ifdef CONFIG_USB_GADGET_MUSB_HDRC + if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) + if (!musb->gadget_driver) { + DBG(5, "No gadget driver loaded\n"); + return IRQ_HANDLED; + } +#endif + /* the core can interrupt us for multiple reasons; docs have * a generic interrupt flowchart to follow */ -- cgit v1.2.3-70-g09d2 From 93aa3dab008421789aa0f8865a62a52ae13269a3 Mon Sep 17 00:00:00 2001 From: Swaminathan S Date: Tue, 15 Dec 2009 13:30:00 +0200 Subject: USB: musb: fix for crash in DM646x USB when (CPPI)DMA is enabled Race condition exists between the cppi_interrupt handler and davinci_interrupt handler w.r.t completing a TX IO. Since DM646x has seperate DMA and USB endpoint interrupts cppi_interrupt handler needs to hold the lock while operating on the endpoint. Update over previous patch to avoid taking the lock if already taken. Tested on DM644x, DM355 and DM646x platforms. Signed-off-by: Swaminathan S Acked-by: Sergei Shtylyov Acked-by: Anand Gadiyar Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/cppi_dma.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index ef2332a9941..a44a450c860 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1154,8 +1154,11 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) struct musb_hw_ep *hw_ep = NULL; u32 rx, tx; int i, index; + unsigned long flags; cppi = container_of(musb->dma_controller, struct cppi, controller); + if (cppi->irq) + spin_lock_irqsave(&musb->lock, flags); tibase = musb->ctrl_base; @@ -1285,6 +1288,9 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) /* write to CPPI EOI register to re-enable interrupts */ musb_writel(tibase, DAVINCI_CPPI_EOI_REG, 0); + if (cppi->irq) + spin_unlock_irqrestore(&musb->lock, flags); + return IRQ_HANDLED; } -- cgit v1.2.3-70-g09d2 From 17be5c5f5ef99c94374e07f71effa78e93a20eda Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 15 Dec 2009 13:30:01 +0200 Subject: USB: musb: gadget_ep0: avoid SetupEnd interrupt Gadget stalling a zero-length SETUP request results in this error message: SetupEnd came in a wrong ep0stage idle In order to avoid it, always set the CSR0.DataEnd bit after detecting a zero- length request. Add the missing '\n' to the error message itself as well... Signed-off-by: Sergei Shtylyov Acked-by: Anand Gadiyar Cc: stable Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget_ep0.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 8fba3f11e47..53d06451f82 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -664,7 +664,7 @@ irqreturn_t musb_g_ep0_irq(struct musb *musb) musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; break; default: - ERR("SetupEnd came in a wrong ep0stage %s", + ERR("SetupEnd came in a wrong ep0stage %s\n", decode_ep0stage(musb->ep0_state)); } csr = musb_readw(regs, MUSB_CSR0); @@ -787,12 +787,18 @@ setup: handled = service_zero_data_request( musb, &setup); + /* + * We're expecting no data in any case, so + * always set the DATAEND bit -- doing this + * here helps avoid SetupEnd interrupt coming + * in the idle stage when we're stalling... + */ + musb->ackpend |= MUSB_CSR0_P_DATAEND; + /* status stage might be immediate */ - if (handled > 0) { - musb->ackpend |= MUSB_CSR0_P_DATAEND; + if (handled > 0) musb->ep0_state = MUSB_EP0_STAGE_STATUSIN; - } break; /* sequence #1 (IN to host), includes GET_STATUS -- cgit v1.2.3-70-g09d2 From 796a83fa039de50133171221ac102a2310e81ffd Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Mon, 21 Dec 2009 21:18:02 -0500 Subject: USB: musb: correct DMA address for tx Since a DMA transfer may need to be kicked off several times to complete, the DMA start must include the length that has already been transferred. Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index e164999bd36..ac306985a8a 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -319,7 +319,7 @@ static void txstate(struct musb *musb, struct musb_request *req) use_dma = use_dma && c->channel_program( musb_ep->dma, musb_ep->packet_sz, musb_ep->dma->desired_mode, - request->dma, request_size); + request->dma + request->actual, request_size); if (use_dma) { if (musb_ep->dma->desired_mode == 0) { /* -- cgit v1.2.3-70-g09d2 From 0abdc36f066ae20521b8c8d306725dd59a0d50aa Mon Sep 17 00:00:00 2001 From: Maulik Mankad Date: Tue, 22 Dec 2009 16:18:19 +0530 Subject: USB: musb: Fix null pointer dereference issue This patch fixes the following NULL pointer dereference issue. Pointer 'request' returned from call to function 'next_request' at line 748 may be NULL and may be dereferenced at line 792. ============ Code Snippet ============ 748: request = next_request(musb_ep); 785: if (dma && (csr & MUSB_RXCSR_DMAENAB)) { csr &= ~(MUSB_RXCSR_AUTOCLEAR | MUSB_RXCSR_DMAENAB | MUSB_RXCSR_DMAMODE); musb_writew(epio, MUSB_RXCSR, MUSB_RXCSR_P_WZC_BITS | csr); 792: request->actual += musb_ep->dma->actual_len; Signed-off-by: Maulik Mankad Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index ac306985a8a..cbcf14a236e 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -746,6 +746,8 @@ void musb_g_rx(struct musb *musb, u8 epnum) musb_ep_select(mbase, epnum); request = next_request(musb_ep); + if (!request) + return; csr = musb_readw(epio, MUSB_RXCSR); dma = is_dma_capable() ? musb_ep->dma : NULL; -- cgit v1.2.3-70-g09d2 From 0ea52ff44f7a30781881ca2debf35e47b2676171 Mon Sep 17 00:00:00 2001 From: Maulik Mankad Date: Tue, 22 Dec 2009 16:19:53 +0530 Subject: USB: musb: Fix array index out of bounds issue This patch fixes the below array index out of bounds issue. Buffer overflow, array index of 'aInfo' may be out of bounds. Array 'aInfo' of size 78 may use index value(s) 6..84 The data stored in 'aInfo' array exceeds the array size of 78. This patch increases the size of this array to hold the string correctly without any memory corruption. This issue was reported by Klockwork tool. Signed-off-by: Maulik Mankad Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 24ff09754e0..5eb9318cff7 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1319,7 +1319,7 @@ static int __init musb_core_init(u16 musb_type, struct musb *musb) #endif u8 reg; char *type; - char aInfo[78], aRevision[32], aDate[12]; + char aInfo[90], aRevision[32], aDate[12]; void __iomem *mbase = musb->mregs; int status = 0; int i; -- cgit v1.2.3-70-g09d2 From 1c4bdc01b8a5cf6c54e5eb8bf9a727e38f0176cc Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Mon, 21 Dec 2009 09:49:52 -0500 Subject: USB: musb: workaround Blackfin FIFO anomalies Some of these workarounds are already in place, but labeled as affecting all BF52x parts. Since we have official anomaly numbers now, use those defines. And since writing to the FIFO has a similar hang issue as reading from the FIFO, implement the workaround there too when necessary. Signed-off-by: Bryan Wu Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/blackfin.c | 134 ++++++++++++++++++++++++++++++-------------- drivers/usb/musb/blackfin.h | 2 - 2 files changed, 91 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index fe4934d9602..ad26e656966 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -29,6 +29,8 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) { void __iomem *fifo = hw_ep->fifo; void __iomem *epio = hw_ep->regs; + u8 epnum = hw_ep->epnum; + u16 dma_reg = 0; prefetch((u8 *)src); @@ -39,67 +41,113 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) dump_fifo_data(src, len); - if (unlikely((unsigned long)src & 0x01)) - outsw_8((unsigned long)fifo, src, - len & 0x01 ? (len >> 1) + 1 : len >> 1); - else - outsw((unsigned long)fifo, src, - len & 0x01 ? (len >> 1) + 1 : len >> 1); -} + if (!ANOMALY_05000380 && epnum != 0) { + flush_dcache_range((unsigned int)src, + (unsigned int)(src + len)); + + /* Setup DMA address register */ + dma_reg = (u16) ((u32) src & 0xFFFF); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); + SSYNC(); + + dma_reg = (u16) (((u32) src >> 16) & 0xFFFF); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); + SSYNC(); + + /* Setup DMA count register */ + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); + SSYNC(); + + /* Enable the DMA */ + dma_reg = (epnum << 4) | DMA_ENA | INT_ENA | DIRECTION; + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); + SSYNC(); + + /* Wait for compelete */ + while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) + cpu_relax(); + + /* acknowledge dma interrupt */ + bfin_write_USB_DMA_INTERRUPT(1 << epnum); + SSYNC(); + + /* Reset DMA */ + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); + SSYNC(); + } else { + SSYNC(); + + if (unlikely((unsigned long)src & 0x01)) + outsw_8((unsigned long)fifo, src, + len & 0x01 ? (len >> 1) + 1 : len >> 1); + else + outsw((unsigned long)fifo, src, + len & 0x01 ? (len >> 1) + 1 : len >> 1); + } +} /* * Unload an endpoint's FIFO */ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) { void __iomem *fifo = hw_ep->fifo; - -#ifdef CONFIG_BF52x u8 epnum = hw_ep->epnum; u16 dma_reg = 0; - invalidate_dcache_range((unsigned int)dst, - (unsigned int)(dst + len)); + if (ANOMALY_05000467 && epnum != 0) { - /* Setup DMA address register */ - dma_reg = (u16) ((u32) dst & 0xFFFF); - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); - SSYNC(); + invalidate_dcache_range((unsigned int)dst, + (unsigned int)(dst + len)); - dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF); - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); - SSYNC(); + /* Setup DMA address register */ + dma_reg = (u16) ((u32) dst & 0xFFFF); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_LOW), dma_reg); + SSYNC(); - /* Setup DMA count register */ - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); - SSYNC(); + dma_reg = (u16) (((u32) dst >> 16) & 0xFFFF); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_ADDR_HIGH), dma_reg); + SSYNC(); - /* Enable the DMA */ - dma_reg = (epnum << 4) | DMA_ENA | INT_ENA; - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); - SSYNC(); + /* Setup DMA count register */ + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_LOW), len); + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_COUNT_HIGH), 0); + SSYNC(); - /* Wait for compelete */ - while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) - cpu_relax(); + /* Enable the DMA */ + dma_reg = (epnum << 4) | DMA_ENA | INT_ENA; + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), dma_reg); + SSYNC(); - /* acknowledge dma interrupt */ - bfin_write_USB_DMA_INTERRUPT(1 << epnum); - SSYNC(); + /* Wait for compelete */ + while (!(bfin_read_USB_DMA_INTERRUPT() & (1 << epnum))) + cpu_relax(); - /* Reset DMA */ - bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); - SSYNC(); -#else - if (unlikely((unsigned long)dst & 0x01)) - insw_8((unsigned long)fifo, dst, - len & 0x01 ? (len >> 1) + 1 : len >> 1); - else - insw((unsigned long)fifo, dst, - len & 0x01 ? (len >> 1) + 1 : len >> 1); -#endif + /* acknowledge dma interrupt */ + bfin_write_USB_DMA_INTERRUPT(1 << epnum); + SSYNC(); + /* Reset DMA */ + bfin_write16(USB_DMA_REG(epnum, USB_DMAx_CTRL), 0); + SSYNC(); + } else { + SSYNC(); + /* Read the last byte of packet with odd size from address fifo + 4 + * to trigger 1 byte access to EP0 FIFO. + */ + if (len == 1) + *dst = (u8)inw((unsigned long)fifo + 4); + else { + if (unlikely((unsigned long)dst & 0x01)) + insw_8((unsigned long)fifo, dst, len >> 1); + else + insw((unsigned long)fifo, dst, len >> 1); + + if (len & 0x01) + *(dst + len - 1) = (u8)inw((unsigned long)fifo + 4); + } + } DBG(4, "%cX ep%d fifo %p count %d buf %p\n", 'R', hw_ep->epnum, fifo, len, dst); diff --git a/drivers/usb/musb/blackfin.h b/drivers/usb/musb/blackfin.h index 10b7d7584f4..bd9352a2ef2 100644 --- a/drivers/usb/musb/blackfin.h +++ b/drivers/usb/musb/blackfin.h @@ -69,7 +69,6 @@ static void dump_fifo_data(u8 *buf, u16 len) #define dump_fifo_data(buf, len) do {} while (0) #endif -#ifdef CONFIG_BF52x #define USB_DMA_BASE USB_DMA_INTERRUPT #define USB_DMAx_CTRL 0x04 @@ -79,7 +78,6 @@ static void dump_fifo_data(u8 *buf, u16 len) #define USB_DMAx_COUNT_HIGH 0x14 #define USB_DMA_REG(ep, reg) (USB_DMA_BASE + 0x20 * ep + reg) -#endif /* Almost 1 second */ #define TIMER_DELAY (1 * HZ) -- cgit v1.2.3-70-g09d2 From 465f8294eea1ea206e3a008e7bfe0e8fd53991fc Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 15 Dec 2009 23:19:52 +0200 Subject: usb: otg: isp1301_omap: fix compile error commit 91c8a5a9985d5bf9c55f6f82f183f57b050b2a3a broke compilation of this driver after it introduced otg_init() as a static inline in Reported-by: Tony Lindgren Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/isp1301_omap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c index d54460a8817..78a20970926 100644 --- a/drivers/usb/otg/isp1301_omap.c +++ b/drivers/usb/otg/isp1301_omap.c @@ -843,7 +843,7 @@ static irqreturn_t omap_otg_irq(int irq, void *_isp) static struct platform_device *otg_dev; -static int otg_init(struct isp1301 *isp) +static int isp1301_otg_init(struct isp1301 *isp) { u32 l; @@ -1275,7 +1275,7 @@ static int __exit isp1301_remove(struct i2c_client *i2c) static int isp1301_otg_enable(struct isp1301 *isp) { power_up(isp); - otg_init(isp); + isp1301_otg_init(isp); /* NOTE: since we don't change this, this provides * a few more interrupts than are strictly needed. -- cgit v1.2.3-70-g09d2 From d16f172622a7941c4fca09724ce16df5348af5fb Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Wed, 9 Dec 2009 22:21:12 -0500 Subject: USB: audio gadget: fix wTotalLength calculation The wTotalLength should contain the sum of the interface and unit descriptor sizes per the Audio Device Class specification 1.0. Reported-by: Sergey Lapin Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_audio.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c index 0f2eee12ee9..1ff420b7d72 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_audio.c @@ -56,13 +56,16 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = { DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); #define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES) +/* 1 input terminal, 1 output terminal and 1 feature unit */ +#define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \ + + UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0)) /* B.3.2 Class-Specific AC Interface Descriptor */ static struct uac_ac_header_descriptor_2 ac_header_desc = { .bLength = UAC_DT_AC_HEADER_LENGTH, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = UAC_HEADER, .bcdADC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(UAC_DT_AC_HEADER_LENGTH), + .wTotalLength = __constant_cpu_to_le16(UAC_DT_TOTAL_LENGTH), .bInCollection = F_AUDIO_NUM_INTERFACES, .baInterfaceNr = { [0] = F_AUDIO_AC_INTERFACE, -- cgit v1.2.3-70-g09d2 From feef1d952ee1e9ac074640d7029dbbe8501725c2 Mon Sep 17 00:00:00 2001 From: Cliff Cai Date: Wed, 9 Dec 2009 22:28:39 -0500 Subject: USB: audio gadget: free alsa devices when unloading Signed-off-by: Cliff Cai Signed-off-by: Mike Frysinger Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/audio.c | 1 + drivers/usb/gadget/f_audio.c | 2 +- drivers/usb/gadget/u_audio.c | 12 +++++++++--- drivers/usb/gadget/u_audio.h | 2 +- 4 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 58f22032384..a62af7b5909 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -158,6 +158,7 @@ fail: static int __exit audio_unbind(struct usb_composite_dev *cdev) { + gaudio_cleanup(); return 0; } diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c index 1ff420b7d72..df77f6131c7 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_audio.c @@ -792,7 +792,7 @@ int __init audio_bind_config(struct usb_configuration *c) return status; add_fail: - gaudio_cleanup(&audio->card); + gaudio_cleanup(); setup_fail: kfree(audio); return status; diff --git a/drivers/usb/gadget/u_audio.c b/drivers/usb/gadget/u_audio.c index 8252595d619..35e0930f5bb 100644 --- a/drivers/usb/gadget/u_audio.c +++ b/drivers/usb/gadget/u_audio.c @@ -288,6 +288,7 @@ static int gaudio_close_snd_dev(struct gaudio *gau) return 0; } +static struct gaudio *the_card; /** * gaudio_setup - setup ALSA interface and preparing for USB transfer * @@ -303,6 +304,9 @@ int __init gaudio_setup(struct gaudio *card) if (ret) ERROR(card, "we need at least one control device\n"); + if (!the_card) + the_card = card; + return ret; } @@ -312,9 +316,11 @@ int __init gaudio_setup(struct gaudio *card) * * This is called to free all resources allocated by @gaudio_setup(). */ -void gaudio_cleanup(struct gaudio *card) +void gaudio_cleanup(void) { - if (card) - gaudio_close_snd_dev(card); + if (the_card) { + gaudio_close_snd_dev(the_card); + the_card = NULL; + } } diff --git a/drivers/usb/gadget/u_audio.h b/drivers/usb/gadget/u_audio.h index cc8d159c648..08ffce3298e 100644 --- a/drivers/usb/gadget/u_audio.h +++ b/drivers/usb/gadget/u_audio.h @@ -51,6 +51,6 @@ struct gaudio { }; int gaudio_setup(struct gaudio *card); -void gaudio_cleanup(struct gaudio *card); +void gaudio_cleanup(void); #endif /* __U_AUDIO_H */ -- cgit v1.2.3-70-g09d2 From c983202bd03eb82394ef1dce5906702fcbc7bb80 Mon Sep 17 00:00:00 2001 From: Donny Kurnia Date: Wed, 23 Dec 2009 19:03:12 +0700 Subject: USB: option: support hi speed for modem Haier CE100 I made this patch for usbserial driver to add the support for EVDO modem Haier CE100. The bugs report for this is here: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/490068 This patch based on these post: http://blankblondtank.wordpress.com/2009/09/04/mengoptimalkan-koneksi-modem-haier-ce-100-cdma-di-linux/ http://tantos.web.id/blogs/how-to-internet-connection-using-cdma-evdo-modem-and-karmic-koala-ubuntu-9-10 I hope this patch can help other that have the Haier C100 modem, mostly in my country, Indonesia. Signed-off-by: Donny Kurnia Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9a2b903492e..6e94a6711f0 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -340,6 +340,10 @@ static int option_resume(struct usb_serial *serial); #define FOUR_G_SYSTEMS_VENDOR_ID 0x1c9e #define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603 +/* Haier products */ +#define HAIER_VENDOR_ID 0x201e +#define HAIER_PRODUCT_CE100 0x2009 + static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -641,6 +645,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(FOUR_G_SYSTEMS_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14) }, + { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.2.3-70-g09d2 From 37e9066b2f85480d99d3795373f5ef0b00ac1189 Mon Sep 17 00:00:00 2001 From: pancho horrillo Date: Wed, 23 Dec 2009 11:09:13 +0100 Subject: USB: Fix a bug on appledisplay.c regarding signedness brightness status is reported by the Apple Cinema Displays as an 'unsigned char' (u8) value, but the code used 'char' instead. Note that he driver was developed on the PowerPC architecture, where the two types are synonymous, which is not always the case. Fixed that. Otherwise the driver will interpret brightness levels > 127 as negative, and fail to load. Signed-off-by: pancho horrillo Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/appledisplay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index 8dc4afa38b8..1eb9e4162cc 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -73,8 +73,8 @@ struct appledisplay { struct usb_device *udev; /* usb device */ struct urb *urb; /* usb request block */ struct backlight_device *bd; /* backlight device */ - char *urbdata; /* interrupt URB data buffer */ - char *msgdata; /* control message data buffer */ + u8 *urbdata; /* interrupt URB data buffer */ + u8 *msgdata; /* control message data buffer */ struct delayed_work work; int button_pressed; -- cgit v1.2.3-70-g09d2 From 4946f8353da9d3038e2a9d0295d5dfeee4cee5c5 Mon Sep 17 00:00:00 2001 From: Imre Kaloz Date: Mon, 7 Dec 2009 20:42:26 +0100 Subject: [WATCHDOG] iTCO_wdt: add PCI ID for the Intel EP80579 (Tolapai) SoC add PCI ID for the Intel EP80579 (Tolapai) SoC Signed-off-by: Imre Kaloz Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/iTCO_wdt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index e44fbb31bc6..c8a3bec2683 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -30,6 +30,7 @@ * document number 316972-004, 316973-012: 82801I (ICH9) * document number 319973-002, 319974-002: 82801J (ICH10) * document number 322169-001, 322170-001: 5 Series, 3400 Series (PCH) + * document number 320066-003, 320257-008: EP80597 (IICH) */ /* @@ -100,6 +101,7 @@ enum iTCO_chipsets { TCO_PCH, /* PCH Desktop Full Featured */ TCO_PCHM, /* PCH Mobile Full Featured */ TCO_PCHMSFF, /* PCH Mobile SFF Full Featured */ + TCO_EP80579, /* EP80579 */ }; static struct { @@ -143,6 +145,7 @@ static struct { {"PCH Desktop Full Featured", 2}, {"PCH Mobile Full Featured", 2}, {"PCH Mobile SFF Full Featured", 2}, + {"EP80579", 2}, {NULL, 0} }; @@ -214,6 +217,7 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { { ITCO_PCI_DEVICE(0x3b00, TCO_PCH)}, { ITCO_PCI_DEVICE(0x3b01, TCO_PCHM)}, { ITCO_PCI_DEVICE(0x3b0d, TCO_PCHMSFF)}, + { ITCO_PCI_DEVICE(0x5031, TCO_EP80579)}, { 0, }, /* End of list */ }; MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); -- cgit v1.2.3-70-g09d2 From b782a563758ac963c794d9fbaaff494140c28fd6 Mon Sep 17 00:00:00 2001 From: H Hartley Sweeten Date: Fri, 4 Dec 2009 12:24:04 -0500 Subject: [WATCHDOG] use resource_size() Use resource_size(). Signed-off-by: H Hartley Sweeten Cc: Kevin Hilman Cc: Kevin Hilman Cc: Ulrik Bech Hald Cc: Henrique de Moraes Holschuh Cc: Ming Lei Cc: Vincent Sanders Acked-by: Thierry Reding Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/adx_wdt.c | 4 ++-- drivers/watchdog/at32ap700x_wdt.c | 2 +- drivers/watchdog/davinci_wdt.c | 2 +- drivers/watchdog/mpcore_wdt.c | 2 +- drivers/watchdog/mv64x60_wdt.c | 2 +- drivers/watchdog/omap_wdt.c | 9 ++++----- drivers/watchdog/pnx4008_wdt.c | 2 +- drivers/watchdog/s3c2410_wdt.c | 2 +- drivers/watchdog/txx9wdt.c | 6 ++---- 9 files changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/adx_wdt.c b/drivers/watchdog/adx_wdt.c index 9c6594473d3..9d7d155364f 100644 --- a/drivers/watchdog/adx_wdt.c +++ b/drivers/watchdog/adx_wdt.c @@ -242,14 +242,14 @@ static int __devinit adx_wdt_probe(struct platform_device *pdev) } res = devm_request_mem_region(&pdev->dev, res->start, - res->end - res->start + 1, res->name); + resource_size(res), res->name); if (!res) { dev_err(&pdev->dev, "cannot request I/O memory region\n"); return -ENXIO; } wdt->base = devm_ioremap_nocache(&pdev->dev, res->start, - res->end - res->start + 1); + resource_size(res)); if (!wdt->base) { dev_err(&pdev->dev, "cannot remap I/O memory region\n"); return -ENXIO; diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index e8ae638e580..037847923dc 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c @@ -326,7 +326,7 @@ static int __init at32_wdt_probe(struct platform_device *pdev) return -ENOMEM; } - wdt->regs = ioremap(regs->start, regs->end - regs->start + 1); + wdt->regs = ioremap(regs->start, resource_size(regs)); if (!wdt->regs) { ret = -ENOMEM; dev_dbg(&pdev->dev, "could not map I/O memory\n"); diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 9d7520fa9e9..887136de185 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c @@ -221,7 +221,7 @@ static int __devinit davinci_wdt_probe(struct platform_device *pdev) return -ENOENT; } - size = res->end - res->start + 1; + size = resource_size(res); wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 83fa34b214b..a2dc07c2ed4 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c @@ -350,7 +350,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) ret = -ENXIO; goto err_free; } - wdt->base = ioremap(res->start, res->end - res->start + 1); + wdt->base = ioremap(res->start, resource_size(res)); if (!wdt->base) { ret = -ENOMEM; goto err_free; diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index acf589dc057..a51dbe4c43d 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c @@ -275,7 +275,7 @@ static int __devinit mv64x60_wdt_probe(struct platform_device *dev) if (!r) return -ENODEV; - mv64x60_wdt_regs = ioremap(r->start, r->end - r->start + 1); + mv64x60_wdt_regs = ioremap(r->start, resource_size(r)); if (mv64x60_wdt_regs == NULL) return -ENOMEM; diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 429ea99eaee..c6aaf284574 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -277,8 +277,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) goto err_busy; } - mem = request_mem_region(res->start, res->end - res->start + 1, - pdev->name); + mem = request_mem_region(res->start, resource_size(res), pdev->name); if (!mem) { ret = -EBUSY; goto err_busy; @@ -306,7 +305,7 @@ static int __devinit omap_wdt_probe(struct platform_device *pdev) goto err_clk; } - wdev->base = ioremap(res->start, res->end - res->start + 1); + wdev->base = ioremap(res->start, resource_size(res)); if (!wdev->base) { ret = -ENOMEM; goto err_ioremap; @@ -358,7 +357,7 @@ err_clk: kfree(wdev); err_kzalloc: - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); err_busy: err_get_resource: @@ -383,7 +382,7 @@ static int __devexit omap_wdt_remove(struct platform_device *pdev) return -ENOENT; misc_deregister(&(wdev->omap_wdt_miscdev)); - release_mem_region(res->start, res->end - res->start + 1); + release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); clk_put(wdev->ick); diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index 4d227b15200..430a5848a9a 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c @@ -264,7 +264,7 @@ static int __devinit pnx4008_wdt_probe(struct platform_device *pdev) return -ENOENT; } - size = res->end - res->start + 1; + size = resource_size(res); wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 85b93e15d01..8760a26ab2a 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -421,7 +421,7 @@ static int __devinit s3c2410wdt_probe(struct platform_device *pdev) return -ENOENT; } - size = (res->end - res->start) + 1; + size = resource_size(res); wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { dev_err(dev, "failed to get memory region\n"); diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 6adab77fbbb..d635566e930 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c @@ -214,12 +214,10 @@ static int __init txx9wdt_probe(struct platform_device *dev) res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!res) goto exit_busy; - if (!devm_request_mem_region(&dev->dev, - res->start, res->end - res->start + 1, + if (!devm_request_mem_region(&dev->dev, res->start, resource_size(res), "txx9wdt")) goto exit_busy; - txx9wdt_reg = devm_ioremap(&dev->dev, - res->start, res->end - res->start + 1); + txx9wdt_reg = devm_ioremap(&dev->dev, res->start, resource_size(res)); if (!txx9wdt_reg) goto exit_busy; -- cgit v1.2.3-70-g09d2 From 9dc130fccb874f2959ef313d7922d306dc6d4f75 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Wed, 23 Dec 2009 17:04:11 +0800 Subject: ACPI: fix OSC regression that caused aer and pciehp not to load Executing _OSC returns a buffer, which has an acpi object in it. Don't directly returns the buffer, instead, we return the acpi object's buffer. This fixes a regression since caller of acpi_run_osc expects an acpi object's buffer returned. Tested-by: Yinghai Lu Signed-off-by: Shaohua Li Signed-off-by: Len Brown --- drivers/acpi/bus.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 65f7e335f12..0c1ad3105da 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -397,6 +397,7 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) union acpi_object *out_obj; u8 uuid[16]; u32 errors; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; if (!context) return AE_ERROR; @@ -419,16 +420,16 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) in_params[3].buffer.length = context->cap.length; in_params[3].buffer.pointer = context->cap.pointer; - status = acpi_evaluate_object(handle, "_OSC", &input, &context->ret); + status = acpi_evaluate_object(handle, "_OSC", &input, &output); if (ACPI_FAILURE(status)) return status; - /* return buffer should have the same length as cap buffer */ - if (context->ret.length != context->cap.length) + if (!output.length) return AE_NULL_OBJECT; - out_obj = context->ret.pointer; - if (out_obj->type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER + || out_obj->buffer.length != context->cap.length) { acpi_print_osc_error(handle, context, "_OSC evaluation returned wrong type"); status = AE_TYPE; @@ -457,11 +458,20 @@ acpi_status acpi_run_osc(acpi_handle handle, struct acpi_osc_context *context) goto out_kfree; } out_success: - return AE_OK; + context->ret.length = out_obj->buffer.length; + context->ret.pointer = kmalloc(context->ret.length, GFP_KERNEL); + if (!context->ret.pointer) { + status = AE_NO_MEMORY; + goto out_kfree; + } + memcpy(context->ret.pointer, out_obj->buffer.pointer, + context->ret.length); + status = AE_OK; out_kfree: - kfree(context->ret.pointer); - context->ret.pointer = NULL; + kfree(output.pointer); + if (status != AE_OK) + context->ret.pointer = NULL; return status; } EXPORT_SYMBOL(acpi_run_osc); -- cgit v1.2.3-70-g09d2 From ac07fb4dc1908d300f50fa711982c9d750eb59f7 Mon Sep 17 00:00:00 2001 From: Sonic Zhang Date: Mon, 21 Dec 2009 09:28:30 -0500 Subject: i2c-bfin-twi: fix CLKDIV calculation Calculation of the CLKDIV speed setting should be done using base 10 math rather than base 2. We also avoid exceeding the spec due to integer truncation and a 50% duty cycle. Signed-off-by: Sonic Zhang Signed-off-by: Mike Frysinger Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-bfin-twi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-bfin-twi.c b/drivers/i2c/busses/i2c-bfin-twi.c index b309ac2c3d5..fe3fb567317 100644 --- a/drivers/i2c/busses/i2c-bfin-twi.c +++ b/drivers/i2c/busses/i2c-bfin-twi.c @@ -693,13 +693,13 @@ static int i2c_bfin_twi_probe(struct platform_device *pdev) } /* Set TWI internal clock as 10MHz */ - write_CONTROL(iface, ((get_sclk() / 1024 / 1024 + 5) / 10) & 0x7F); + write_CONTROL(iface, ((get_sclk() / 1000 / 1000 + 5) / 10) & 0x7F); /* * We will not end up with a CLKDIV=0 because no one will specify - * 20kHz SCL or less in Kconfig now. (5 * 1024 / 20 = 0x100) + * 20kHz SCL or less in Kconfig now. (5 * 1000 / 20 = 250) */ - clkhilow = 5 * 1024 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ; + clkhilow = ((10 * 1000 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) + 1) / 2; /* Set Twi interface clock as specified */ write_CLKDIV(iface, (clkhilow << 8) | clkhilow); -- cgit v1.2.3-70-g09d2 From 07ac31f6f4cd558e53f6705dbe3033a7f0237eb8 Mon Sep 17 00:00:00 2001 From: Cory Maccarrone Date: Tue, 22 Dec 2009 18:06:13 -0700 Subject: i2c-omap: Don't write IE state in unidle if 0 Commit ef871432... (i2c-omap: OMAP3: PM: (re)init for every transfer to support off-mode) introduced a change which make the dev->iestate contents be written to the OMAP_I2C_IE_REG every time omap_i2c_unidle is called. Previously, the state was only written if it wasn't equal to zero. In omap_i2c_probe, omap_i2c_unidle() is called prior to omap_i2c_init(), in which case dev->iestate has not yet been initialized and will be set to zero. Having this value written to the registers causes deadlock while booting. As such, this change restores the original functionality. Signed-off-by: Cory Maccarrone Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 75bf3ad1809..a64a192c44a 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -247,7 +247,13 @@ static void omap_i2c_unidle(struct omap_i2c_dev *dev) omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); } dev->idle = 0; - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); + + /* + * Don't write to this register if the IE state is 0 as it can + * cause deadlock. + */ + if (dev->iestate) + omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); } static void omap_i2c_idle(struct omap_i2c_dev *dev) -- cgit v1.2.3-70-g09d2 From 57eb81b14e35a14df64ac3597bc90c26ce04a9b4 Mon Sep 17 00:00:00 2001 From: Manjunatha GK Date: Fri, 11 Dec 2009 11:09:08 +0530 Subject: i2c-omap: OMAP3: Fix I2C lockup during timeout/error cases Current OMAP3 I2C driver code does not follow the correct sequence for soft reset. Due to this, lock up issues are reported during timeout/error cases. This patch fixes above issue by disabling I2C controller as per OMAP3430 TRM for soft reset. As per TRM, I2C controller needs to be disabled as a first step during soft reset. Here is correct soft reset sequence: a. Ensure that the module is disabled (clear the I2Ci.I2C_CON[15] I2C_EN bit to 0). b. Set the I2Ci.I2C_SYSC[1] SRST bit to 1. c. Enable the module by setting I2Ci.I2C_CON[15] I2C_EN bit to 1. d. Check the I2Ci.I2C_SYSS[0] RDONE bit until it is set to 1 to indicate the software reset is complete. Tested on Zoom2, Zoom3, 3430SDP and 3630SDP Signed-off-by: Manjunatha GK Signed-off-by: George, Harith Acked-by: Varadarajan, Charu Latha Signed-off-by: Ben Dooks --- drivers/i2c/busses/i2c-omap.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index a64a192c44a..0037e31076b 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -286,6 +286,11 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) unsigned long internal_clk = 0; if (dev->rev >= OMAP_I2C_REV_2) { + /* Disable I2C controller before soft reset */ + omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, + omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) & + ~(OMAP_I2C_CON_EN)); + omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); /* For some reason we need to set the EN bit before the * reset done bit gets set. */ -- cgit v1.2.3-70-g09d2 From d5a664a311c1957a75bec1808cae0f10d606c378 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 17 Dec 2009 00:08:35 +0900 Subject: sony-laptop: rfkill support for newer models Vaio Type X and possibly other new models use F135 as the radio frequency controlling function attached to the SNC device. In the indexed table this corresponds to 0x0135 (surpise!). Signed-off-by: Mattia Dongili Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 9710f70040b..1144686a33f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -131,6 +131,7 @@ enum sony_nc_rfkill { N_SONY_RFKILL, }; +static int sony_rfkill_handle; static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; static void sony_nc_rfkill_update(void); @@ -965,7 +966,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) else sony_laptop_report_input_event(ev); } - } else if (sony_find_snc_handle(0x124) == ev) { + } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) { sony_nc_rfkill_update(); return; } @@ -1071,7 +1072,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) if (!blocked) argument |= 0xff0000; - return sony_call_snc_handle(0x124, argument, &result); + return sony_call_snc_handle(sony_rfkill_handle, argument, &result); } static const struct rfkill_ops sony_rfkill_ops = { @@ -1114,7 +1115,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, if (!rfk) return -ENOMEM; - sony_call_snc_handle(0x124, 0x200, &result); + sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); hwblock = !(result & 0x1); rfkill_set_hw_state(rfk, hwblock); @@ -1133,7 +1134,7 @@ static void sony_nc_rfkill_update() int result; bool hwblock; - sony_call_snc_handle(0x124, 0x200, &result); + sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); hwblock = !(result & 0x1); for (i = 0; i < N_SONY_RFKILL; i++) { @@ -1149,7 +1150,7 @@ static void sony_nc_rfkill_update() continue; } - sony_call_snc_handle(0x124, argument, &result); + sony_call_snc_handle(sony_rfkill_handle, argument, &result); rfkill_set_states(sony_rfkill_devices[i], !(result & 0xf), false); } @@ -1159,10 +1160,15 @@ static int sony_nc_rfkill_setup(struct acpi_device *device) { int result, ret; - if (sony_find_snc_handle(0x124) == -1) - return -1; + if (sony_find_snc_handle(0x124) == -1) { + if (sony_find_snc_handle(0x135) == -1) + return -1; + else + sony_rfkill_handle = 0x135; + } else + sony_rfkill_handle = 0x124; - ret = sony_call_snc_handle(0x124, 0xb00, &result); + ret = sony_call_snc_handle(sony_rfkill_handle, 0xb00, &result); if (ret) { printk(KERN_INFO DRV_PFX "Unable to enumerate rfkill devices: %x\n", ret); -- cgit v1.2.3-70-g09d2 From 528809c35faebd8c50a4722c85ab8610725875cc Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Thu, 17 Dec 2009 00:08:36 +0900 Subject: sony-laptop: enumerate rfkill devices using SN06 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SN06 makes sure we get back a longer buffer which seems to be necessary going forward as the SNC devices describes more and more devices (or features more precisely). Moreover SN06 should be called with only the descriptor offset to make sure we hit the rfkill controlling function (F124 or F135) with a 0 argument to get a full list of features. Signed-off-by: Mattia Dongili Tested-by: Miguel Rodríguez Pérez Signed-off-by: Len Brown --- drivers/platform/x86/sony-laptop.c | 76 ++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 1144686a33f..49f3fe0ac59 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1156,35 +1156,73 @@ static void sony_nc_rfkill_update() } } -static int sony_nc_rfkill_setup(struct acpi_device *device) +static void sony_nc_rfkill_setup(struct acpi_device *device) { - int result, ret; + int offset; + u8 dev_code, i; + acpi_status status; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *device_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (sony_find_snc_handle(0x124) == -1) { - if (sony_find_snc_handle(0x135) == -1) - return -1; + offset = sony_find_snc_handle(0x124); + if (offset == -1) { + offset = sony_find_snc_handle(0x135); + if (offset == -1) + return; else sony_rfkill_handle = 0x135; } else sony_rfkill_handle = 0x124; + dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle); - ret = sony_call_snc_handle(sony_rfkill_handle, 0xb00, &result); - if (ret) { - printk(KERN_INFO DRV_PFX - "Unable to enumerate rfkill devices: %x\n", ret); - return ret; + /* need to read the whole buffer returned by the acpi call to SN06 + * here otherwise we may miss some features + */ + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = offset; + status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) { + dprintk("Radio device enumeration failed\n"); + return; } - if (result & 0x1) - sony_nc_setup_rfkill(device, SONY_WIFI); - if (result & 0x2) - sony_nc_setup_rfkill(device, SONY_BLUETOOTH); - if (result & 0x1c) - sony_nc_setup_rfkill(device, SONY_WWAN); - if (result & 0x20) - sony_nc_setup_rfkill(device, SONY_WIMAX); + device_enum = (union acpi_object *) buffer.pointer; + if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) { + printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n", + device_enum->type); + goto out_no_enum; + } - return 0; + /* the buffer is filled with magic numbers describing the devices + * available, 0xff terminates the enumeration + */ + while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && + i < device_enum->buffer.length) { + i++; + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); + + if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) + sony_nc_setup_rfkill(device, SONY_WIFI); + + if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) + sony_nc_setup_rfkill(device, SONY_BLUETOOTH); + + if ((0xf0 & dev_code) == 0x20 && + !sony_rfkill_devices[SONY_WWAN]) + sony_nc_setup_rfkill(device, SONY_WWAN); + + if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) + sony_nc_setup_rfkill(device, SONY_WIMAX); + } + +out_no_enum: + kfree(buffer.pointer); + return; } static int sony_nc_add(struct acpi_device *device) -- cgit v1.2.3-70-g09d2 From 2370b5ed03030d554adb345778d5edecab7a510c Mon Sep 17 00:00:00 2001 From: "Carlos R. Mafra" Date: Tue, 22 Dec 2009 13:45:39 -0800 Subject: ACPI: do not select ACPI_DOCK from ATA_ACPI In March 2008 commit 0ac4a3c2fbbcadc3e96e4dc47d4ae802d66e6f67 ("ACPI: fix ATA_ACPI build") made CONFIG_ACPI_DOCK be selected by CONFIG_ATA_ACPI because of a build error when CONFIG_ATA_ACPI=y and CONFIG_ACPI_DOCK=m. However, in September 2008 commit 898b054f3eec5921320ae8614b5bdd7b07ea5b43 ("dock: make dock driver not a module") removed the possibility of having CONFIG_ACPI_DOCK=m and therefore there is no need for selecting it when CONFIG_ATA_ACPI=y. This makes the kernel ~5 Kb smaller for people who don't have a dock by allowing them to not have ACPI_DOCK compiled-in because of ATA_ACPI=y. Signed-off-by: Carlos R. Mafra Cc: Shaohua Li Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/ata/Kconfig | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 85844d05384..56c6374a398 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -40,7 +40,6 @@ config ATA_VERBOSE_ERROR config ATA_ACPI bool "ATA ACPI Support" depends on ACPI && PCI - select ACPI_DOCK default y help This option adds support for ATA-related ACPI objects. -- cgit v1.2.3-70-g09d2 From ff93be5dea548f16dcfe7b73ce5df7666efba92d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 21 Dec 2009 16:20:01 -0800 Subject: asus_acpi: convert to seq_file Signed-off-by: Alexey Dobriyan Cc: Corentin Chary Cc: Karol Kozimor Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/asus_acpi.c | 321 +++++++++++++++++++++++---------------- 1 file changed, 194 insertions(+), 127 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus_acpi.c b/drivers/platform/x86/asus_acpi.c index 0c9c53111a2..c1d2aeeea94 100644 --- a/drivers/platform/x86/asus_acpi.c +++ b/drivers/platform/x86/asus_acpi.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -513,26 +514,12 @@ static int read_acpi_int(acpi_handle handle, const char *method, int *val) return (status == AE_OK) && (out_obj.type == ACPI_TYPE_INTEGER); } -/* - * We write our info in page, we begin at offset off and cannot write more - * than count bytes. We set eof to 1 if we handle those 2 values. We return the - * number of bytes written in page - */ -static int -proc_read_info(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int asus_info_proc_show(struct seq_file *m, void *v) { - int len = 0; int temp; - char buf[16]; /* enough for all info */ - /* - * We use the easy way, we don't care of off and count, - * so we don't set eof to 1 - */ - len += sprintf(page, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); - len += sprintf(page + len, "Model reference : %s\n", - hotk->methods->name); + seq_printf(m, ACPI_HOTK_NAME " " ASUS_ACPI_VERSION "\n"); + seq_printf(m, "Model reference : %s\n", hotk->methods->name); /* * The SFUN method probably allows the original driver to get the list * of features supported by a given model. For now, 0x0100 or 0x0800 @@ -540,8 +527,7 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, * The significance of others is yet to be found. */ if (read_acpi_int(hotk->handle, "SFUN", &temp)) - len += - sprintf(page + len, "SFUN value : 0x%04x\n", temp); + seq_printf(m, "SFUN value : 0x%04x\n", temp); /* * Another value for userspace: the ASYM method returns 0x02 for * battery low and 0x04 for battery critical, its readings tend to be @@ -550,30 +536,34 @@ proc_read_info(char *page, char **start, off_t off, int count, int *eof, * silently ignored. */ if (read_acpi_int(hotk->handle, "ASYM", &temp)) - len += - sprintf(page + len, "ASYM value : 0x%04x\n", temp); + seq_printf(m, "ASYM value : 0x%04x\n", temp); if (asus_info) { - snprintf(buf, 16, "%d", asus_info->length); - len += sprintf(page + len, "DSDT length : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->checksum); - len += sprintf(page + len, "DSDT checksum : %s\n", buf); - snprintf(buf, 16, "%d", asus_info->revision); - len += sprintf(page + len, "DSDT revision : %s\n", buf); - snprintf(buf, 7, "%s", asus_info->oem_id); - len += sprintf(page + len, "OEM id : %s\n", buf); - snprintf(buf, 9, "%s", asus_info->oem_table_id); - len += sprintf(page + len, "OEM table id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->oem_revision); - len += sprintf(page + len, "OEM revision : 0x%s\n", buf); - snprintf(buf, 5, "%s", asus_info->asl_compiler_id); - len += sprintf(page + len, "ASL comp vendor id : %s\n", buf); - snprintf(buf, 16, "%x", asus_info->asl_compiler_revision); - len += sprintf(page + len, "ASL comp revision : 0x%s\n", buf); + seq_printf(m, "DSDT length : %d\n", asus_info->length); + seq_printf(m, "DSDT checksum : %d\n", asus_info->checksum); + seq_printf(m, "DSDT revision : %d\n", asus_info->revision); + seq_printf(m, "OEM id : %.*s\n", ACPI_OEM_ID_SIZE, asus_info->oem_id); + seq_printf(m, "OEM table id : %.*s\n", ACPI_OEM_TABLE_ID_SIZE, asus_info->oem_table_id); + seq_printf(m, "OEM revision : 0x%x\n", asus_info->oem_revision); + seq_printf(m, "ASL comp vendor id : %.*s\n", ACPI_NAME_SIZE, asus_info->asl_compiler_id); + seq_printf(m, "ASL comp revision : 0x%x\n", asus_info->asl_compiler_revision); } - return len; + return 0; +} + +static int asus_info_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, asus_info_proc_show, NULL); } +static const struct file_operations asus_info_proc_fops = { + .owner = THIS_MODULE, + .open = asus_info_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* * /proc handlers * We write our info in page, we begin at offset off and cannot write more @@ -639,34 +629,48 @@ write_led(const char __user *buffer, unsigned long count, /* * Proc handlers for MLED */ -static int -proc_read_mled(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int mled_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", - read_led(hotk->methods->mled_status, MLED_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->mled_status, MLED_ON)); + return 0; } -static int -proc_write_mled(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int mled_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, mled_proc_show, NULL); +} + +static ssize_t mled_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { return write_led(buffer, count, hotk->methods->mt_mled, MLED_ON, 1); } +static const struct file_operations mled_proc_fops = { + .owner = THIS_MODULE, + .open = mled_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = mled_proc_write, +}; + /* * Proc handlers for LED display */ -static int -proc_read_ledd(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int ledd_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "0x%08x\n", hotk->ledd_status); + seq_printf(m, "0x%08x\n", hotk->ledd_status); + return 0; } -static int -proc_write_ledd(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int ledd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ledd_proc_show, NULL); +} + +static ssize_t ledd_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -682,61 +686,104 @@ proc_write_ledd(struct file *file, const char __user *buffer, return rv; } +static const struct file_operations ledd_proc_fops = { + .owner = THIS_MODULE, + .open = ledd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = ledd_proc_write, +}; + /* * Proc handlers for WLED */ -static int -proc_read_wled(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int wled_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", - read_led(hotk->methods->wled_status, WLED_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->wled_status, WLED_ON)); + return 0; } -static int -proc_write_wled(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int wled_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, wled_proc_show, NULL); +} + +static ssize_t wled_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { return write_led(buffer, count, hotk->methods->mt_wled, WLED_ON, 0); } +static const struct file_operations wled_proc_fops = { + .owner = THIS_MODULE, + .open = wled_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = wled_proc_write, +}; + /* * Proc handlers for Bluetooth */ -static int -proc_read_bluetooth(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int bluetooth_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", read_led(hotk->methods->bt_status, BT_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->bt_status, BT_ON)); + return 0; } -static int -proc_write_bluetooth(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int bluetooth_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, bluetooth_proc_show, NULL); +} + +static ssize_t bluetooth_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *pos) { /* Note: mt_bt_switch controls both internal Bluetooth adapter's presence and its LED */ return write_led(buffer, count, hotk->methods->mt_bt_switch, BT_ON, 0); } +static const struct file_operations bluetooth_proc_fops = { + .owner = THIS_MODULE, + .open = bluetooth_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = bluetooth_proc_write, +}; + /* * Proc handlers for TLED */ -static int -proc_read_tled(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int tled_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", - read_led(hotk->methods->tled_status, TLED_ON)); + seq_printf(m, "%d\n", read_led(hotk->methods->tled_status, TLED_ON)); + return 0; } -static int -proc_write_tled(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int tled_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, tled_proc_show, NULL); +} + +static ssize_t tled_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { return write_led(buffer, count, hotk->methods->mt_tled, TLED_ON, 0); } +static const struct file_operations tled_proc_fops = { + .owner = THIS_MODULE, + .open = tled_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = tled_proc_write, +}; + static int get_lcd_state(void) { int lcd = 0; @@ -829,16 +876,19 @@ static int set_lcd_state(int value) } -static int -proc_read_lcd(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int lcd_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", get_lcd_state()); + seq_printf(m, "%d\n", get_lcd_state()); + return 0; } -static int -proc_write_lcd(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int lcd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, lcd_proc_show, NULL); +} + +static ssize_t lcd_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -848,6 +898,15 @@ proc_write_lcd(struct file *file, const char __user *buffer, return rv; } +static const struct file_operations lcd_proc_fops = { + .owner = THIS_MODULE, + .open = lcd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = lcd_proc_write, +}; + static int read_brightness(struct backlight_device *bd) { int value; @@ -907,16 +966,19 @@ static int set_brightness_status(struct backlight_device *bd) return set_brightness(bd->props.brightness); } -static int -proc_read_brn(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int brn_proc_show(struct seq_file *m, void *v) { - return sprintf(page, "%d\n", read_brightness(NULL)); + seq_printf(m, "%d\n", read_brightness(NULL)); + return 0; } -static int -proc_write_brn(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static int brn_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, brn_proc_show, NULL); +} + +static ssize_t brn_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -929,6 +991,15 @@ proc_write_brn(struct file *file, const char __user *buffer, return rv; } +static const struct file_operations brn_proc_fops = { + .owner = THIS_MODULE, + .open = brn_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = brn_proc_write, +}; + static void set_display(int value) { /* no sanity check needed for now */ @@ -942,9 +1013,7 @@ static void set_display(int value) * Now, *this* one could be more user-friendly, but so far, no-one has * complained. The significance of bits is the same as in proc_write_disp() */ -static int -proc_read_disp(char *page, char **start, off_t off, int count, int *eof, - void *data) +static int disp_proc_show(struct seq_file *m, void *v) { int value = 0; @@ -952,7 +1021,13 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, printk(KERN_WARNING "Asus ACPI: Error reading display status\n"); value &= 0x07; /* needed for some models, shouldn't hurt others */ - return sprintf(page, "%d\n", value); + seq_printf(m, "%d\n", value); + return 0; +} + +static int disp_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, disp_proc_show, NULL); } /* @@ -961,9 +1036,8 @@ proc_read_disp(char *page, char **start, off_t off, int count, int *eof, * (bitwise) of these will suffice. I never actually tested 3 displays hooked * up simultaneously, so be warned. See the acpi4asus README for more info. */ -static int -proc_write_disp(struct file *file, const char __user *buffer, - unsigned long count, void *data) +static ssize_t disp_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *pos) { int rv, value; @@ -973,25 +1047,27 @@ proc_write_disp(struct file *file, const char __user *buffer, return rv; } -typedef int (proc_readfunc) (char *page, char **start, off_t off, int count, - int *eof, void *data); -typedef int (proc_writefunc) (struct file *file, const char __user *buffer, - unsigned long count, void *data); +static const struct file_operations disp_proc_fops = { + .owner = THIS_MODULE, + .open = disp_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = disp_proc_write, +}; static int -asus_proc_add(char *name, proc_writefunc *writefunc, - proc_readfunc *readfunc, mode_t mode, +asus_proc_add(char *name, const struct file_operations *proc_fops, mode_t mode, struct acpi_device *device) { - struct proc_dir_entry *proc = - create_proc_entry(name, mode, acpi_device_dir(device)); + struct proc_dir_entry *proc; + + proc = proc_create_data(name, mode, acpi_device_dir(device), + proc_fops, acpi_driver_data(device)); if (!proc) { printk(KERN_WARNING " Unable to create %s fs entry\n", name); return -1; } - proc->write_proc = writefunc; - proc->read_proc = readfunc; - proc->data = acpi_driver_data(device); proc->uid = asus_uid; proc->gid = asus_gid; return 0; @@ -1020,10 +1096,9 @@ static int asus_hotk_add_fs(struct acpi_device *device) if (!acpi_device_dir(device)) return -ENODEV; - proc = create_proc_entry(PROC_INFO, mode, acpi_device_dir(device)); + proc = proc_create(PROC_INFO, mode, acpi_device_dir(device), + &asus_info_proc_fops); if (proc) { - proc->read_proc = proc_read_info; - proc->data = acpi_driver_data(device); proc->uid = asus_uid; proc->gid = asus_gid; } else { @@ -1032,28 +1107,23 @@ static int asus_hotk_add_fs(struct acpi_device *device) } if (hotk->methods->mt_wled) { - asus_proc_add(PROC_WLED, &proc_write_wled, &proc_read_wled, - mode, device); + asus_proc_add(PROC_WLED, &wled_proc_fops, mode, device); } if (hotk->methods->mt_ledd) { - asus_proc_add(PROC_LEDD, &proc_write_ledd, &proc_read_ledd, - mode, device); + asus_proc_add(PROC_LEDD, &ledd_proc_fops, mode, device); } if (hotk->methods->mt_mled) { - asus_proc_add(PROC_MLED, &proc_write_mled, &proc_read_mled, - mode, device); + asus_proc_add(PROC_MLED, &mled_proc_fops, mode, device); } if (hotk->methods->mt_tled) { - asus_proc_add(PROC_TLED, &proc_write_tled, &proc_read_tled, - mode, device); + asus_proc_add(PROC_TLED, &tled_proc_fops, mode, device); } if (hotk->methods->mt_bt_switch) { - asus_proc_add(PROC_BT, &proc_write_bluetooth, - &proc_read_bluetooth, mode, device); + asus_proc_add(PROC_BT, &bluetooth_proc_fops, mode, device); } /* @@ -1061,19 +1131,16 @@ static int asus_hotk_add_fs(struct acpi_device *device) * accessible from the keyboard */ if (hotk->methods->mt_lcd_switch && hotk->methods->lcd_status) { - asus_proc_add(PROC_LCD, &proc_write_lcd, &proc_read_lcd, mode, - device); + asus_proc_add(PROC_LCD, &lcd_proc_fops, mode, device); } if ((hotk->methods->brightness_up && hotk->methods->brightness_down) || (hotk->methods->brightness_get && hotk->methods->brightness_set)) { - asus_proc_add(PROC_BRN, &proc_write_brn, &proc_read_brn, mode, - device); + asus_proc_add(PROC_BRN, &brn_proc_fops, mode, device); } if (hotk->methods->display_set) { - asus_proc_add(PROC_DISP, &proc_write_disp, &proc_read_disp, - mode, device); + asus_proc_add(PROC_DISP, &disp_proc_fops, mode, device); } return 0; -- cgit v1.2.3-70-g09d2 From 936c8bcd7f5b418d0e040be539ceb4d2ac3bc0b8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 21 Dec 2009 16:20:02 -0800 Subject: toshiba_acpi: convert to seq_file Signed-off-by: Alexey Dobriyan Cc: John W. Linville Cc: Johannes Berg Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/toshiba_acpi.c | 259 ++++++++++++++++++++---------------- 1 file changed, 147 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 51c0a8bee41..77bf5d8f893 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -357,63 +358,6 @@ static int force_fan; static int last_key_event; static int key_event_valid; -typedef struct _ProcItem { - const char *name; - char *(*read_func) (char *); - unsigned long (*write_func) (const char *, unsigned long); -} ProcItem; - -/* proc file handlers - */ - -static int -dispatch_read(char *page, char **start, off_t off, int count, int *eof, - ProcItem * item) -{ - char *p = page; - int len; - - if (off == 0) - p = item->read_func(p); - - /* ISSUE: I don't understand this code */ - len = (p - page); - if (len <= off + count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -static int -dispatch_write(struct file *file, const char __user * buffer, - unsigned long count, ProcItem * item) -{ - int result; - char *tmp_buffer; - - /* Arg buffer points to userspace memory, which can't be accessed - * directly. Since we're making a copy, zero-terminate the - * destination so that sscanf can be used on it safely. - */ - tmp_buffer = kmalloc(count + 1, GFP_KERNEL); - if (!tmp_buffer) - return -ENOMEM; - - if (copy_from_user(tmp_buffer, buffer, count)) { - result = -EFAULT; - } else { - tmp_buffer[count] = 0; - result = item->write_func(tmp_buffer, count); - } - kfree(tmp_buffer); - return result; -} - static int get_lcd(struct backlight_device *bd) { u32 hci_result; @@ -426,19 +370,24 @@ static int get_lcd(struct backlight_device *bd) return -EFAULT; } -static char *read_lcd(char *p) +static int lcd_proc_show(struct seq_file *m, void *v) { int value = get_lcd(NULL); if (value >= 0) { - p += sprintf(p, "brightness: %d\n", value); - p += sprintf(p, "brightness_levels: %d\n", + seq_printf(m, "brightness: %d\n", value); + seq_printf(m, "brightness_levels: %d\n", HCI_LCD_BRIGHTNESS_LEVELS); } else { printk(MY_ERR "Error reading LCD brightness\n"); } - return p; + return 0; +} + +static int lcd_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, lcd_proc_show, NULL); } static int set_lcd(int value) @@ -458,12 +407,20 @@ static int set_lcd_status(struct backlight_device *bd) return set_lcd(bd->props.brightness); } -static unsigned long write_lcd(const char *buffer, unsigned long count) +static ssize_t lcd_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { + char cmd[42]; + size_t len; int value; int ret; - if (sscanf(buffer, " brightness : %i", &value) == 1 && + len = min(count, sizeof(cmd) - 1); + if (copy_from_user(cmd, buf, len)) + return -EFAULT; + cmd[len] = '\0'; + + if (sscanf(cmd, " brightness : %i", &value) == 1 && value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) { ret = set_lcd(value); if (ret == 0) @@ -474,7 +431,16 @@ static unsigned long write_lcd(const char *buffer, unsigned long count) return ret; } -static char *read_video(char *p) +static const struct file_operations lcd_proc_fops = { + .owner = THIS_MODULE, + .open = lcd_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = lcd_proc_write, +}; + +static int video_proc_show(struct seq_file *m, void *v) { u32 hci_result; u32 value; @@ -484,18 +450,25 @@ static char *read_video(char *p) int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0; int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0; int is_tv = (value & HCI_VIDEO_OUT_TV) ? 1 : 0; - p += sprintf(p, "lcd_out: %d\n", is_lcd); - p += sprintf(p, "crt_out: %d\n", is_crt); - p += sprintf(p, "tv_out: %d\n", is_tv); + seq_printf(m, "lcd_out: %d\n", is_lcd); + seq_printf(m, "crt_out: %d\n", is_crt); + seq_printf(m, "tv_out: %d\n", is_tv); } else { printk(MY_ERR "Error reading video out status\n"); } - return p; + return 0; } -static unsigned long write_video(const char *buffer, unsigned long count) +static int video_proc_open(struct inode *inode, struct file *file) { + return single_open(file, video_proc_show, NULL); +} + +static ssize_t video_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + char *cmd, *buffer; int value; int remain = count; int lcd_out = -1; @@ -504,6 +477,17 @@ static unsigned long write_video(const char *buffer, unsigned long count) u32 hci_result; u32 video_out; + cmd = kmalloc(count + 1, GFP_KERNEL); + if (!cmd) + return -ENOMEM; + if (copy_from_user(cmd, buf, count)) { + kfree(cmd); + return -EFAULT; + } + cmd[count] = '\0'; + + buffer = cmd; + /* scan expression. Multiple expressions may be delimited with ; * * NOTE: to keep scanning simple, invalid fields are ignored @@ -523,6 +507,8 @@ static unsigned long write_video(const char *buffer, unsigned long count) while (remain && *(buffer - 1) != ';'); } + kfree(cmd); + hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result); if (hci_result == HCI_SUCCESS) { unsigned int new_video_out = video_out; @@ -543,28 +529,50 @@ static unsigned long write_video(const char *buffer, unsigned long count) return count; } -static char *read_fan(char *p) +static const struct file_operations video_proc_fops = { + .owner = THIS_MODULE, + .open = video_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = video_proc_write, +}; + +static int fan_proc_show(struct seq_file *m, void *v) { u32 hci_result; u32 value; hci_read1(HCI_FAN, &value, &hci_result); if (hci_result == HCI_SUCCESS) { - p += sprintf(p, "running: %d\n", (value > 0)); - p += sprintf(p, "force_on: %d\n", force_fan); + seq_printf(m, "running: %d\n", (value > 0)); + seq_printf(m, "force_on: %d\n", force_fan); } else { printk(MY_ERR "Error reading fan status\n"); } - return p; + return 0; +} + +static int fan_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, fan_proc_show, NULL); } -static unsigned long write_fan(const char *buffer, unsigned long count) +static ssize_t fan_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { + char cmd[42]; + size_t len; int value; u32 hci_result; - if (sscanf(buffer, " force_on : %i", &value) == 1 && + len = min(count, sizeof(cmd) - 1); + if (copy_from_user(cmd, buf, len)) + return -EFAULT; + cmd[len] = '\0'; + + if (sscanf(cmd, " force_on : %i", &value) == 1 && value >= 0 && value <= 1) { hci_write1(HCI_FAN, value, &hci_result); if (hci_result != HCI_SUCCESS) @@ -578,7 +586,16 @@ static unsigned long write_fan(const char *buffer, unsigned long count) return count; } -static char *read_keys(char *p) +static const struct file_operations fan_proc_fops = { + .owner = THIS_MODULE, + .open = fan_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = fan_proc_write, +}; + +static int keys_proc_show(struct seq_file *m, void *v) { u32 hci_result; u32 value; @@ -602,18 +619,30 @@ static char *read_keys(char *p) } } - p += sprintf(p, "hotkey_ready: %d\n", key_event_valid); - p += sprintf(p, "hotkey: 0x%04x\n", last_key_event); + seq_printf(m, "hotkey_ready: %d\n", key_event_valid); + seq_printf(m, "hotkey: 0x%04x\n", last_key_event); +end: + return 0; +} - end: - return p; +static int keys_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, keys_proc_show, NULL); } -static unsigned long write_keys(const char *buffer, unsigned long count) +static ssize_t keys_proc_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) { + char cmd[42]; + size_t len; int value; - if (sscanf(buffer, " hotkey_ready : %i", &value) == 1 && value == 0) { + len = min(count, sizeof(cmd) - 1); + if (copy_from_user(cmd, buf, len)) + return -EFAULT; + cmd[len] = '\0'; + + if (sscanf(cmd, " hotkey_ready : %i", &value) == 1 && value == 0) { key_event_valid = 0; } else { return -EINVAL; @@ -622,52 +651,58 @@ static unsigned long write_keys(const char *buffer, unsigned long count) return count; } -static char *read_version(char *p) +static const struct file_operations keys_proc_fops = { + .owner = THIS_MODULE, + .open = keys_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = keys_proc_write, +}; + +static int version_proc_show(struct seq_file *m, void *v) { - p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION); - p += sprintf(p, "proc_interface: %d\n", - PROC_INTERFACE_VERSION); - return p; + seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION); + seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION); + return 0; } +static int version_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, version_proc_show, PDE(inode)->data); +} + +static const struct file_operations version_proc_fops = { + .owner = THIS_MODULE, + .open = version_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + /* proc and module init */ #define PROC_TOSHIBA "toshiba" -static ProcItem proc_items[] = { - {"lcd", read_lcd, write_lcd}, - {"video", read_video, write_video}, - {"fan", read_fan, write_fan}, - {"keys", read_keys, write_keys}, - {"version", read_version, NULL}, - {NULL} -}; - static acpi_status __init add_device(void) { - struct proc_dir_entry *proc; - ProcItem *item; - - for (item = proc_items; item->name; ++item) { - proc = create_proc_read_entry(item->name, - S_IFREG | S_IRUGO | S_IWUSR, - toshiba_proc_dir, - (read_proc_t *) dispatch_read, - item); - if (proc && item->write_func) - proc->write_proc = (write_proc_t *) dispatch_write; - } + proc_create("lcd", S_IRUGO | S_IWUSR, toshiba_proc_dir, &lcd_proc_fops); + proc_create("video", S_IRUGO | S_IWUSR, toshiba_proc_dir, &video_proc_fops); + proc_create("fan", S_IRUGO | S_IWUSR, toshiba_proc_dir, &fan_proc_fops); + proc_create("keys", S_IRUGO | S_IWUSR, toshiba_proc_dir, &keys_proc_fops); + proc_create("version", S_IRUGO, toshiba_proc_dir, &version_proc_fops); return AE_OK; } static acpi_status remove_device(void) { - ProcItem *item; - - for (item = proc_items; item->name; ++item) - remove_proc_entry(item->name, toshiba_proc_dir); + remove_proc_entry("lcd", toshiba_proc_dir); + remove_proc_entry("video", toshiba_proc_dir); + remove_proc_entry("fan", toshiba_proc_dir); + remove_proc_entry("keys", toshiba_proc_dir); + remove_proc_entry("version", toshiba_proc_dir); return AE_OK; } -- cgit v1.2.3-70-g09d2 From bdc731bc5fcd1794e9ac8ac80c389d302381c123 Mon Sep 17 00:00:00 2001 From: Stefan Bader Date: Mon, 21 Dec 2009 16:20:04 -0800 Subject: acerhdf: limit modalias matching to supported BugLink: https://bugs.launchpad.net/ubuntu/+bug/435958 The module alias currently matches any Acer computer but when loaded the BIOS checks will only succeed on Aspire One models. This causes a invalid BIOS warning for all other models (seen on Aspire 4810T). This is not fatal but worries users that see this message. Limiting the moule alias to models starting with AOA or DOA for Packard Bell. Signed-off-by: Stefan Bader Acked-by: Borislav Petkov Acked-by: Peter Feuerer Cc: Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/acerhdf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 79b15b9d9cf..007bc55b986 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -640,9 +640,10 @@ static void __exit acerhdf_exit(void) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Peter Feuerer"); MODULE_DESCRIPTION("Aspire One temperature and fan driver"); -MODULE_ALIAS("dmi:*:*Acer*:*:"); -MODULE_ALIAS("dmi:*:*Gateway*:*:"); -MODULE_ALIAS("dmi:*:*Packard Bell*:*:"); +MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); module_init(acerhdf_init); module_exit(acerhdf_exit); -- cgit v1.2.3-70-g09d2 From 94219d798e65dff1dac5f8f36f03a9bdb3105f91 Mon Sep 17 00:00:00 2001 From: Peter Feuerer Date: Mon, 21 Dec 2009 16:20:05 -0800 Subject: acerhdf: add new BIOS versions Add new BIOS versions for following netbooks: Aspire 1810xx, Packard Bell DOTMU. Signed-off-by: Peter Feuerer Cc: Borislav Petkov Cc: Andreas Mohr Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/acerhdf.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index 007bc55b986..a97fc4a7c60 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -52,7 +52,7 @@ */ #undef START_IN_KERNEL_MODE -#define DRV_VER "0.5.20" +#define DRV_VER "0.5.21" /* * According to the Atom N270 datasheet, @@ -156,7 +156,13 @@ static const struct bios_settings_t bios_tbl[] = { {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x20, 0x00} }, /* Acer 1410 */ {"Acer", "Aspire 1410", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, - /* special BIOS / other */ + {"Acer", "Aspire 1410", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + /* Acer 1810xx */ + {"Acer", "Aspire 1810TZ", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1810T", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Acer", "Aspire 1810TZ", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + /* Gateway */ {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, {"Gateway ", "LT31 ", "v1.3103 ", 0x55, 0x58, @@ -165,10 +171,13 @@ static const struct bios_settings_t bios_tbl[] = { {0x10, 0x0f, 0x00} }, {"Gateway ", "LT31 ", "v1.3302 ", 0x55, 0x58, {0x10, 0x0f, 0x00} }, + /* Packard Bell */ {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, + {"Packard Bell", "DOTMU", "v1.3303", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, + {"Packard Bell", "DOTMU", "v0.3120", 0x55, 0x58, {0x9e, 0x9e, 0x00} }, /* pewpew-terminator */ {"", "", "", 0, 0, {0, 0, 0} } }; @@ -641,9 +650,13 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Peter Feuerer"); MODULE_DESCRIPTION("Aspire One temperature and fan driver"); MODULE_ALIAS("dmi:*:*Acer*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1410*:"); +MODULE_ALIAS("dmi:*:*Acer*:pnAspire 1810*:"); MODULE_ALIAS("dmi:*:*Gateway*:pnAOA*:"); +MODULE_ALIAS("dmi:*:*Gateway*:pnLT31*:"); MODULE_ALIAS("dmi:*:*Packard Bell*:pnAOA*:"); MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOA*:"); +MODULE_ALIAS("dmi:*:*Packard Bell*:pnDOTMU*:"); module_init(acerhdf_init); module_exit(acerhdf_exit); -- cgit v1.2.3-70-g09d2 From dcbfb8156a2149fd6358a377aa9400e28ef43800 Mon Sep 17 00:00:00 2001 From: Peter Feuerer Date: Mon, 21 Dec 2009 16:20:06 -0800 Subject: drivers/platform/x86/acerhdf.c: check BIOS information whether it begins with string of table BIOS information is now checked whether it begins with the strings stored in the BIOS table. Previous method did a strcmp, what lead to problems if BIOS information has appended whitespaces. Signed-off-by: Peter Feuerer Cc: Borislav Petkov Cc: Andreas Mohr Cc: Ingo Molnar Cc: Thomas Gleixner Cc: "H. Peter Anvin" Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/acerhdf.c | 46 +++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acerhdf.c b/drivers/platform/x86/acerhdf.c index a97fc4a7c60..7b2384d674d 100644 --- a/drivers/platform/x86/acerhdf.c +++ b/drivers/platform/x86/acerhdf.c @@ -52,7 +52,7 @@ */ #undef START_IN_KERNEL_MODE -#define DRV_VER "0.5.21" +#define DRV_VER "0.5.22" /* * According to the Atom N270 datasheet, @@ -165,12 +165,9 @@ static const struct bios_settings_t bios_tbl[] = { /* Gateway */ {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x20, 0x00} }, - {"Gateway ", "LT31 ", "v1.3103 ", 0x55, 0x58, - {0x10, 0x0f, 0x00} }, - {"Gateway ", "LT31 ", "v1.3201 ", 0x55, 0x58, - {0x10, 0x0f, 0x00} }, - {"Gateway ", "LT31 ", "v1.3302 ", 0x55, 0x58, - {0x10, 0x0f, 0x00} }, + {"Gateway", "LT31", "v1.3103", 0x55, 0x58, {0x10, 0x0f, 0x00} }, + {"Gateway", "LT31", "v1.3201", 0x55, 0x58, {0x10, 0x0f, 0x00} }, + {"Gateway", "LT31", "v1.3302", 0x55, 0x58, {0x10, 0x0f, 0x00} }, /* Packard Bell */ {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x21, 0x00} }, {"Packard Bell", "DOA150", "v0.3105", 0x55, 0x58, {0x20, 0x20, 0x00} }, @@ -495,13 +492,26 @@ static struct platform_driver acerhdf_driver = { .remove = acerhdf_remove, }; +/* checks if str begins with start */ +static int str_starts_with(const char *str, const char *start) +{ + unsigned long str_len = 0, start_len = 0; + + str_len = strlen(str); + start_len = strlen(start); + + if (str_len >= start_len && + !strncmp(str, start, start_len)) + return 1; + + return 0; +} /* check hardware */ static int acerhdf_check_hardware(void) { char const *vendor, *version, *product; - int i; - unsigned long prod_len = 0; + const struct bios_settings_t *bt = NULL; /* get BIOS data */ vendor = dmi_get_system_info(DMI_SYS_VENDOR); @@ -523,20 +533,20 @@ static int acerhdf_check_hardware(void) kernelmode = 0; } - prod_len = strlen(product); - if (verbose) pr_info("BIOS info: %s %s, product: %s\n", vendor, version, product); /* search BIOS version and vendor in BIOS settings table */ - for (i = 0; bios_tbl[i].version[0]; i++) { - if (strlen(bios_tbl[i].product) >= prod_len && - !strncmp(bios_tbl[i].product, product, - strlen(bios_tbl[i].product)) && - !strcmp(bios_tbl[i].vendor, vendor) && - !strcmp(bios_tbl[i].version, version)) { - bios_cfg = &bios_tbl[i]; + for (bt = bios_tbl; bt->vendor[0]; bt++) { + /* + * check if actual hardware BIOS vendor, product and version + * IDs start with the strings of BIOS table entry + */ + if (str_starts_with(vendor, bt->vendor) && + str_starts_with(product, bt->product) && + str_starts_with(version, bt->version)) { + bios_cfg = bt; break; } } -- cgit v1.2.3-70-g09d2 From 3e9b988e4edf065d39c1343937f717319b1c1065 Mon Sep 17 00:00:00 2001 From: Anisse Astier Date: Fri, 4 Dec 2009 10:10:09 +0100 Subject: wmi: Free the allocated acpi objects through wmi_get_event_data These function allocate an acpi object by calling wmi_get_event_data, which then calls acpi_evaluate_object, and it is not freed afterwards. And kernel doc is fixed for parameters of wmi_get_event_data. Signed-off-by: Anisse Astier Acked-by: Randy Dunlap Acked-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/dell-wmi.c | 1 + drivers/platform/x86/hp-wmi.c | 2 ++ drivers/platform/x86/wmi.c | 4 ++-- 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 67f3fe71c50..6561dfc028e 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -238,6 +238,7 @@ static void dell_wmi_notify(u32 value, void *context) input_sync(dell_wmi_input_dev); } } + kfree(obj); } diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 63c3e658a88..db10c5d007e 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -381,6 +381,8 @@ static void hp_wmi_notify(u32 value, void *context) } else printk(KERN_INFO "HP WMI: Unknown key pressed - %x\n", eventcode); + + kfree(obj); } static int __init hp_wmi_input_setup(void) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index e425a868cd3..9f93d6c0f51 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -540,8 +540,8 @@ EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); /** * wmi_get_event_data - Get WMI data associated with an event * - * @event - Event to find - * &out - Buffer to hold event data + * @event: Event to find + * @out: Buffer to hold event data. out->pointer should be freed with kfree() * * Returns extra data associated with an event in WMI. */ -- cgit v1.2.3-70-g09d2 From 1fdd407f4e3f2ecb453954cbebb6c22491c61853 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Thu, 17 Dec 2009 22:19:42 -0800 Subject: dell-wmi: do not keep driver loaded on unsupported boxes There is no point in having the driver loaded in memory if we fail to locate particular WMI GUID. Signed-off-by: Dmitry Torokhov Acked-by: Matthew Garrett Signed-off-by: Len Brown --- drivers/platform/x86/dell-wmi.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 6561dfc028e..916ccb2b316 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -325,37 +325,34 @@ static int __init dell_wmi_init(void) int err; if (wmi_has_guid(DELL_EVENT_GUID)) { + printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); + return -ENODEV; + } - dmi_walk(find_hk_type, NULL); - - err = dell_wmi_input_setup(); - - if (err) - return err; - - err = wmi_install_notify_handler(DELL_EVENT_GUID, - dell_wmi_notify, NULL); - if (err) { - input_unregister_device(dell_wmi_input_dev); - printk(KERN_ERR "dell-wmi: Unable to register" - " notify handler - %d\n", err); - return err; - } + dmi_walk(find_hk_type, NULL); + acpi_video = acpi_video_backlight_support(); - acpi_video = acpi_video_backlight_support(); + err = dell_wmi_input_setup(); + if (err) + return err; - } else - printk(KERN_WARNING "dell-wmi: No known WMI GUID found\n"); + err = wmi_install_notify_handler(DELL_EVENT_GUID, + dell_wmi_notify, NULL); + if (err) { + input_unregister_device(dell_wmi_input_dev); + printk(KERN_ERR + "dell-wmi: Unable to register notify handler - %d\n", + err); + return err; + } return 0; } static void __exit dell_wmi_exit(void) { - if (wmi_has_guid(DELL_EVENT_GUID)) { - wmi_remove_notify_handler(DELL_EVENT_GUID); - input_unregister_device(dell_wmi_input_dev); - } + wmi_remove_notify_handler(DELL_EVENT_GUID); + input_unregister_device(dell_wmi_input_dev); } module_init(dell_wmi_init); -- cgit v1.2.3-70-g09d2 From 4d5f177caf1ef78f5e7eaee75b66b4d534445682 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 18 Dec 2009 15:29:22 +0100 Subject: acer-wmi, msi-wmi: Remove needless DMI MODULE_ALIAS Now that we have WMI autoloading the DMI matching is not needed anymore. Signed-off-by: Thomas Renninger Acked-by: Carlos Corbacho Acked-by: Anisse Astier Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 3 --- drivers/platform/x86/msi-wmi.c | 10 ---------- 2 files changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 454970d2d70..07d14dfdf0b 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -96,9 +96,6 @@ struct acer_quirks { MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB"); MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3"); -/* Temporary workaround until the WMI sysfs interface goes in */ -MODULE_ALIAS("dmi:*:*Acer*:*:"); - /* * Interface capability flags */ diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index 0c8fe145c4a..7f77f908bb0 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -34,16 +34,6 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("wmi:551A1F84-FBDD-4125-91DB-3EA8F44F1D45"); MODULE_ALIAS("wmi:B6F3EEF2-3D2F-49DC-9DE3-85BCE18C62F2"); -/* Temporary workaround until the WMI sysfs interface goes in - { "svn", DMI_SYS_VENDOR }, - { "pn", DMI_PRODUCT_NAME }, - { "pvr", DMI_PRODUCT_VERSION }, - { "rvn", DMI_BOARD_VENDOR }, - { "rn", DMI_BOARD_NAME }, -*/ - -MODULE_ALIAS("dmi:*:svnMICRO-STARINTERNATIONAL*:pnMS-6638:*"); - #define DRV_NAME "msi-wmi" #define DRV_PFX DRV_NAME ": " -- cgit v1.2.3-70-g09d2 From 154280fd0e890814a249bf4a79b4340fb367f1a7 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 22 Dec 2009 03:37:28 +0000 Subject: serial: sh-sci: earlyprintk zero uartclk fix This establishes a sensible max baud rate for the earlyprintk cases where the port's uartclk has not yet been determined. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 68c7f6cfd72..a8869905113 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -897,11 +897,21 @@ static void sci_shutdown(struct uart_port *port) static void sci_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { - unsigned int status, baud, smr_val; + unsigned int status, baud, smr_val, max_baud; int t = -1; - baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); - if (likely(baud)) + /* + * earlyprintk comes here early on with port->uartclk set to zero. + * the clock framework is not up and running at this point so here + * we assume that 115200 is the maximum baud rate. please note that + * the baud rate is not programmed during earlyprintk - it is assumed + * that the previous boot loader has enabled required clocks and + * setup the baud rate generator hardware for us already. + */ + max_baud = port->uartclk ? port->uartclk / 16 : 115200; + + baud = uart_get_baud_rate(port, termios, old, 0, max_baud); + if (likely(baud && port->uartclk)) t = SCBRR_VALUE(baud, port->uartclk); do { -- cgit v1.2.3-70-g09d2 From 32b53076c31ce9159740b744d5eb5d9505312add Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Thu, 24 Dec 2009 14:52:43 +0900 Subject: serial: sh-sci: Convert tremaining ctrl_xxx I/O routines to __raw_xxx. ctrl_xxx() is an antiquated SH interface, while __raw_xxx is the standard API that accomplishes the same thing. As such, this converts the remaining sh-sci straggles over, which enables the driver to be wired up for ARM SH-Mobile CPUs as well. Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 4 +- drivers/serial/sh-sci.h | 118 ++++++++++++++++++++++++------------------------ 2 files changed, 61 insertions(+), 61 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index a8869905113..37f0de9dd9c 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -222,9 +222,9 @@ static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) Set SCP6MD1,0 = {01} (output) */ __raw_writew((data & 0x0fcf) | 0x1000, SCPCR); - data = ctrl_inb(SCPDR); + data = __raw_readb(SCPDR); /* Set /RTS2 (bit6) = 0 */ - ctrl_outb(data & 0xbf, SCPDR); + __raw_writeb(data & 0xbf, SCPDR); } } #elif defined(CONFIG_CPU_SUBTYPE_SH7722) diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index a32094eeb42..0efcded59ae 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -517,20 +517,20 @@ static const struct __attribute__((packed)) { static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfffffe80) - return ctrl_inb(SCPDR)&0x01 ? 1 : 0; /* SCI */ + return __raw_readb(SCPDR)&0x01 ? 1 : 0; /* SCI */ if (port->mapbase == 0xa4000150) - return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ + return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xa4000140) - return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ + return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7705) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == SCIF0) - return ctrl_inb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ + return __raw_readb(SCPDR)&0x04 ? 1 : 0; /* IRDA */ if (port->mapbase == SCIF2) - return ctrl_inb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ + return __raw_readb(SCPDR)&0x10 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7710) || defined(CONFIG_CPU_SUBTYPE_SH7712) @@ -557,68 +557,68 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */ + return __raw_readb(SCSPTR1)&0x01 ? 1 : 0; /* SCI */ if (port->mapbase == 0xffe80000) - return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe80000) - return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7757) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfe4b0000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; if (port->mapbase == 0xfe4c0000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; if (port->mapbase == 0xfe4d0000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; } #elif defined(CONFIG_CPU_SUBTYPE_SH7760) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfe600000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfe610000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfe620000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7343) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe20000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe30000) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7366) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ + return __raw_readb(SCPDR0) & 0x0001 ? 1 : 0; /* SCIF0 */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7722) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(PSDR) & 0x02 ? 1 : 0; /* SCIF0 */ + return __raw_readb(PSDR) & 0x02 ? 1 : 0; /* SCIF0 */ if (port->mapbase == 0xffe10000) - return ctrl_inb(PADR) & 0x40 ? 1 : 0; /* SCIF1 */ + return __raw_readb(PADR) & 0x40 ? 1 : 0; /* SCIF1 */ if (port->mapbase == 0xffe20000) - return ctrl_inb(PWDR) & 0x04 ? 1 : 0; /* SCIF2 */ + return __raw_readb(PWDR) & 0x04 ? 1 : 0; /* SCIF2 */ return 1; } @@ -626,17 +626,17 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */ + return __raw_readb(SCSPTR0) & 0x0008 ? 1 : 0; /* SCIF0 */ if (port->mapbase == 0xffe10000) - return ctrl_inb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */ + return __raw_readb(SCSPTR1) & 0x0020 ? 1 : 0; /* SCIF1 */ if (port->mapbase == 0xffe20000) - return ctrl_inb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */ + return __raw_readb(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF2 */ if (port->mapbase == 0xa4e30000) - return ctrl_inb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */ + return __raw_readb(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF3 */ if (port->mapbase == 0xa4e40000) - return ctrl_inb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */ + return __raw_readb(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF4 */ if (port->mapbase == 0xa4e50000) - return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ + return __raw_readb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7724) @@ -645,9 +645,9 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->type == PORT_SCIF) - return ctrl_inw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0; + return __raw_readw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0; if (port->type == PORT_SCIFA) - return ctrl_inw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0; + return __raw_readw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0; return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) @@ -665,11 +665,11 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe08000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF/IRDA */ return 1; } @@ -677,20 +677,20 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xff923000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xff924000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xff925000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7780) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffe00000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffe10000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ @@ -698,17 +698,17 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffea0000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffeb0000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffec0000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffed0000) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffee0000) - return ctrl_inw(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR4) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffef0000) - return ctrl_inw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ @@ -718,22 +718,22 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfffe8000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffe8800) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffe9000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffe9800) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ #if defined(CONFIG_CPU_SUBTYPE_SH7201) if (port->mapbase == 0xfffeA000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffeA800) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffeB000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xfffeB800) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ #endif return 1; } @@ -741,24 +741,24 @@ static inline int sci_rxd_in(struct uart_port *port) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xf8400000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xf8410000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xf8420000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #elif defined(CONFIG_CPU_SUBTYPE_SHX3) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffc30000) - return ctrl_inw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR0) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffc40000) - return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffc50000) - return ctrl_inw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR2) & 0x0001 ? 1 : 0; /* SCIF */ if (port->mapbase == 0xffc60000) - return ctrl_inw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ + return __raw_readw(SCSPTR3) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } #endif -- cgit v1.2.3-70-g09d2 From 44ef00e6482e755f36629773abc2aee83a6f53e3 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Fri, 18 Dec 2009 15:29:23 +0100 Subject: hp-wmi: Fix two memleaks Signed-off-by: Thomas Renninger Signed-off-by: Len Brown --- drivers/platform/x86/hp-wmi.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index db10c5d007e..8781d8fa7a5 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -134,10 +134,15 @@ static int hp_wmi_perform_query(int query, int write, int value) obj = output.pointer; - if (!obj || obj->type != ACPI_TYPE_BUFFER) + if (!obj) return -EINVAL; + else if (obj->type != ACPI_TYPE_BUFFER) { + kfree(obj); + return -EINVAL; + } bios_return = *((struct bios_return *)obj->buffer.pointer); + kfree(obj); if (bios_return.return_code > 0) return bios_return.return_code * -1; else @@ -340,10 +345,12 @@ static void hp_wmi_notify(u32 value, void *context) if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { printk(KERN_INFO "HP WMI: Unknown response received\n"); + kfree(obj); return; } eventcode = *((u8 *) obj->buffer.pointer); + kfree(obj); if (eventcode == 0x4) eventcode = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0, 0); -- cgit v1.2.3-70-g09d2 From 529aa8cb0a59367d08883f818e8c47028e819d0d Mon Sep 17 00:00:00 2001 From: Thadeu Lima de Souza Cascardo Date: Mon, 21 Dec 2009 16:20:01 -0800 Subject: classmate-laptop: add support for Classmate PC ACPI devices This add supports for devices like keyboard, backlight, tablet and accelerometer. This work is supported by International Syst S/A. [randy.dunlap@oracle.com: cmpc_acpi: depends on ACPI] [akpm@linux-foundation.org: readability tweaks] [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Thadeu Lima de Souza Cascardo Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- MAINTAINERS | 6 + drivers/platform/x86/Kconfig | 12 + drivers/platform/x86/Makefile | 1 + drivers/platform/x86/classmate-laptop.c | 609 ++++++++++++++++++++++++++++++++ 4 files changed, 628 insertions(+) create mode 100644 drivers/platform/x86/classmate-laptop.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index efd2ef2c266..9ddfc97b1de 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1470,6 +1470,12 @@ L: linux-scsi@vger.kernel.org S: Supported F: drivers/scsi/fnic/ +CMPC ACPI DRIVER +M: Thadeu Lima de Souza Cascardo +M: Daniel Oliveira Nascimento +S: Supported +F: drivers/platform/x86/classmate-laptop.c + CODA FILE SYSTEM M: Jan Harkes M: coda@cs.cmu.edu diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index fc5bf9d2a3f..ec4faffe6b0 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -464,4 +464,16 @@ config TOSHIBA_BT_RFKILL If you have a modern Toshiba laptop with a Bluetooth and an RFKill switch (such as the Portege R500), say Y. + +config ACPI_CMPC + tristate "CMPC Laptop Extras" + depends on X86 && ACPI + select INPUT + select BACKLIGHT_CLASS_DEVICE + default n + help + Support for Intel Classmate PC ACPI devices, including some + keys as input device, backlight device, tablet and accelerometer + devices. + endif # X86_PLATFORM_DEVICES diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile index b7474b6a8bf..9cd9fa0a27e 100644 --- a/drivers/platform/x86/Makefile +++ b/drivers/platform/x86/Makefile @@ -5,6 +5,7 @@ obj-$(CONFIG_ASUS_LAPTOP) += asus-laptop.o obj-$(CONFIG_EEEPC_LAPTOP) += eeepc-laptop.o obj-$(CONFIG_MSI_LAPTOP) += msi-laptop.o +obj-$(CONFIG_ACPI_CMPC) += classmate-laptop.o obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o obj-$(CONFIG_DELL_WMI) += dell-wmi.o diff --git a/drivers/platform/x86/classmate-laptop.c b/drivers/platform/x86/classmate-laptop.c new file mode 100644 index 00000000000..ed90082cdf1 --- /dev/null +++ b/drivers/platform/x86/classmate-laptop.c @@ -0,0 +1,609 @@ +/* + * Copyright (C) 2009 Thadeu Lima de Souza Cascardo + * + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + + +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + + +struct cmpc_accel { + int sensitivity; +}; + +#define CMPC_ACCEL_SENSITIVITY_DEFAULT 5 + + +/* + * Generic input device code. + */ + +typedef void (*input_device_init)(struct input_dev *dev); + +static int cmpc_add_acpi_notify_device(struct acpi_device *acpi, char *name, + input_device_init idev_init) +{ + struct input_dev *inputdev; + int error; + + inputdev = input_allocate_device(); + if (!inputdev) + return -ENOMEM; + inputdev->name = name; + inputdev->dev.parent = &acpi->dev; + idev_init(inputdev); + error = input_register_device(inputdev); + if (error) { + input_free_device(inputdev); + return error; + } + dev_set_drvdata(&acpi->dev, inputdev); + return 0; +} + +static int cmpc_remove_acpi_notify_device(struct acpi_device *acpi) +{ + struct input_dev *inputdev = dev_get_drvdata(&acpi->dev); + input_unregister_device(inputdev); + return 0; +} + +/* + * Accelerometer code. + */ +static acpi_status cmpc_start_accel(acpi_handle handle) +{ + union acpi_object param[2]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x3; + param[1].type = ACPI_TYPE_INTEGER; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_stop_accel(acpi_handle handle) +{ + union acpi_object param[2]; + struct acpi_object_list input; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x4; + param[1].type = ACPI_TYPE_INTEGER; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, NULL); + return status; +} + +static acpi_status cmpc_accel_set_sensitivity(acpi_handle handle, int val) +{ + union acpi_object param[2]; + struct acpi_object_list input; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x02; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = val; + input.count = 2; + input.pointer = param; + return acpi_evaluate_object(handle, "ACMD", &input, NULL); +} + +static acpi_status cmpc_get_accel(acpi_handle handle, + unsigned char *x, + unsigned char *y, + unsigned char *z) +{ + union acpi_object param[2]; + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, 0 }; + unsigned char *locs; + acpi_status status; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0x01; + param[1].type = ACPI_TYPE_INTEGER; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_object(handle, "ACMD", &input, &output); + if (ACPI_SUCCESS(status)) { + union acpi_object *obj; + obj = output.pointer; + locs = obj->buffer.pointer; + *x = locs[0]; + *y = locs[1]; + *z = locs[2]; + kfree(output.pointer); + } + return status; +} + +static void cmpc_accel_handler(struct acpi_device *dev, u32 event) +{ + if (event == 0x81) { + unsigned char x, y, z; + acpi_status status; + + status = cmpc_get_accel(dev->handle, &x, &y, &z); + if (ACPI_SUCCESS(status)) { + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); + + input_report_abs(inputdev, ABS_X, x); + input_report_abs(inputdev, ABS_Y, y); + input_report_abs(inputdev, ABS_Z, z); + input_sync(inputdev); + } + } +} + +static ssize_t cmpc_accel_sensitivity_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + return sprintf(buf, "%d\n", accel->sensitivity); +} + +static ssize_t cmpc_accel_sensitivity_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct acpi_device *acpi; + struct input_dev *inputdev; + struct cmpc_accel *accel; + unsigned long sensitivity; + int r; + + acpi = to_acpi_device(dev); + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + r = strict_strtoul(buf, 0, &sensitivity); + if (r) + return r; + + accel->sensitivity = sensitivity; + cmpc_accel_set_sensitivity(acpi->handle, sensitivity); + + return strnlen(buf, count); +} + +struct device_attribute cmpc_accel_sensitivity_attr = { + .attr = { .name = "sensitivity", .mode = 0660 }, + .show = cmpc_accel_sensitivity_show, + .store = cmpc_accel_sensitivity_store +}; + +static int cmpc_accel_open(struct input_dev *input) +{ + struct acpi_device *acpi; + + acpi = to_acpi_device(input->dev.parent); + if (ACPI_SUCCESS(cmpc_start_accel(acpi->handle))) + return 0; + return -EIO; +} + +static void cmpc_accel_close(struct input_dev *input) +{ + struct acpi_device *acpi; + + acpi = to_acpi_device(input->dev.parent); + cmpc_stop_accel(acpi->handle); +} + +static void cmpc_accel_idev_init(struct input_dev *inputdev) +{ + set_bit(EV_ABS, inputdev->evbit); + input_set_abs_params(inputdev, ABS_X, 0, 255, 8, 0); + input_set_abs_params(inputdev, ABS_Y, 0, 255, 8, 0); + input_set_abs_params(inputdev, ABS_Z, 0, 255, 8, 0); + inputdev->open = cmpc_accel_open; + inputdev->close = cmpc_accel_close; +} + +static int cmpc_accel_add(struct acpi_device *acpi) +{ + int error; + struct input_dev *inputdev; + struct cmpc_accel *accel; + + accel = kmalloc(sizeof(*accel), GFP_KERNEL); + if (!accel) + return -ENOMEM; + + accel->sensitivity = CMPC_ACCEL_SENSITIVITY_DEFAULT; + cmpc_accel_set_sensitivity(acpi->handle, accel->sensitivity); + + error = device_create_file(&acpi->dev, &cmpc_accel_sensitivity_attr); + if (error) + goto failed_file; + + error = cmpc_add_acpi_notify_device(acpi, "cmpc_accel", + cmpc_accel_idev_init); + if (error) + goto failed_input; + + inputdev = dev_get_drvdata(&acpi->dev); + dev_set_drvdata(&inputdev->dev, accel); + + return 0; + +failed_input: + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr); +failed_file: + kfree(accel); + return error; +} + +static int cmpc_accel_remove(struct acpi_device *acpi, int type) +{ + struct input_dev *inputdev; + struct cmpc_accel *accel; + + inputdev = dev_get_drvdata(&acpi->dev); + accel = dev_get_drvdata(&inputdev->dev); + + device_remove_file(&acpi->dev, &cmpc_accel_sensitivity_attr); + return cmpc_remove_acpi_notify_device(acpi); +} + +static const struct acpi_device_id cmpc_accel_device_ids[] = { + {"ACCE0000", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_accel_device_ids); + +static struct acpi_driver cmpc_accel_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc_accel", + .class = "cmpc_accel", + .ids = cmpc_accel_device_ids, + .ops = { + .add = cmpc_accel_add, + .remove = cmpc_accel_remove, + .notify = cmpc_accel_handler, + } +}; + + +/* + * Tablet mode code. + */ +static acpi_status cmpc_get_tablet(acpi_handle handle, + unsigned long long *value) +{ + union acpi_object param; + struct acpi_object_list input; + unsigned long long output; + acpi_status status; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = 0x01; + input.count = 1; + input.pointer = ¶m; + status = acpi_evaluate_integer(handle, "TCMD", &input, &output); + if (ACPI_SUCCESS(status)) + *value = output; + return status; +} + +static void cmpc_tablet_handler(struct acpi_device *dev, u32 event) +{ + unsigned long long val = 0; + struct input_dev *inputdev = dev_get_drvdata(&dev->dev); + + if (event == 0x81) { + if (ACPI_SUCCESS(cmpc_get_tablet(dev->handle, &val))) + input_report_switch(inputdev, SW_TABLET_MODE, !val); + } +} + +static void cmpc_tablet_idev_init(struct input_dev *inputdev) +{ + unsigned long long val = 0; + struct acpi_device *acpi; + + set_bit(EV_SW, inputdev->evbit); + set_bit(SW_TABLET_MODE, inputdev->swbit); + + acpi = to_acpi_device(inputdev->dev.parent); + if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) + input_report_switch(inputdev, SW_TABLET_MODE, !val); +} + +static int cmpc_tablet_add(struct acpi_device *acpi) +{ + return cmpc_add_acpi_notify_device(acpi, "cmpc_tablet", + cmpc_tablet_idev_init); +} + +static int cmpc_tablet_remove(struct acpi_device *acpi, int type) +{ + return cmpc_remove_acpi_notify_device(acpi); +} + +static int cmpc_tablet_resume(struct acpi_device *acpi) +{ + struct input_dev *inputdev = dev_get_drvdata(&acpi->dev); + unsigned long long val = 0; + if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val))) + input_report_switch(inputdev, SW_TABLET_MODE, !val); + return 0; +} + +static const struct acpi_device_id cmpc_tablet_device_ids[] = { + {"TBLT0000", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_tablet_device_ids); + +static struct acpi_driver cmpc_tablet_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc_tablet", + .class = "cmpc_tablet", + .ids = cmpc_tablet_device_ids, + .ops = { + .add = cmpc_tablet_add, + .remove = cmpc_tablet_remove, + .resume = cmpc_tablet_resume, + .notify = cmpc_tablet_handler, + } +}; + + +/* + * Backlight code. + */ + +static acpi_status cmpc_get_brightness(acpi_handle handle, + unsigned long long *value) +{ + union acpi_object param; + struct acpi_object_list input; + unsigned long long output; + acpi_status status; + + param.type = ACPI_TYPE_INTEGER; + param.integer.value = 0xC0; + input.count = 1; + input.pointer = ¶m; + status = acpi_evaluate_integer(handle, "GRDI", &input, &output); + if (ACPI_SUCCESS(status)) + *value = output; + return status; +} + +static acpi_status cmpc_set_brightness(acpi_handle handle, + unsigned long long value) +{ + union acpi_object param[2]; + struct acpi_object_list input; + acpi_status status; + unsigned long long output; + + param[0].type = ACPI_TYPE_INTEGER; + param[0].integer.value = 0xC0; + param[1].type = ACPI_TYPE_INTEGER; + param[1].integer.value = value; + input.count = 2; + input.pointer = param; + status = acpi_evaluate_integer(handle, "GWRI", &input, &output); + return status; +} + +static int cmpc_bl_get_brightness(struct backlight_device *bd) +{ + acpi_status status; + acpi_handle handle; + unsigned long long brightness; + + handle = bl_get_data(bd); + status = cmpc_get_brightness(handle, &brightness); + if (ACPI_SUCCESS(status)) + return brightness; + else + return -1; +} + +static int cmpc_bl_update_status(struct backlight_device *bd) +{ + acpi_status status; + acpi_handle handle; + + handle = bl_get_data(bd); + status = cmpc_set_brightness(handle, bd->props.brightness); + if (ACPI_SUCCESS(status)) + return 0; + else + return -1; +} + +static struct backlight_ops cmpc_bl_ops = { + .get_brightness = cmpc_bl_get_brightness, + .update_status = cmpc_bl_update_status +}; + +static int cmpc_bl_add(struct acpi_device *acpi) +{ + struct backlight_device *bd; + + bd = backlight_device_register("cmpc_bl", &acpi->dev, + acpi->handle, &cmpc_bl_ops); + bd->props.max_brightness = 7; + dev_set_drvdata(&acpi->dev, bd); + return 0; +} + +static int cmpc_bl_remove(struct acpi_device *acpi, int type) +{ + struct backlight_device *bd; + + bd = dev_get_drvdata(&acpi->dev); + backlight_device_unregister(bd); + return 0; +} + +static const struct acpi_device_id cmpc_device_ids[] = { + {"IPML200", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_device_ids); + +static struct acpi_driver cmpc_bl_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc", + .class = "cmpc", + .ids = cmpc_device_ids, + .ops = { + .add = cmpc_bl_add, + .remove = cmpc_bl_remove + } +}; + + +/* + * Extra keys code. + */ +static int cmpc_keys_codes[] = { + KEY_UNKNOWN, + KEY_WLAN, + KEY_SWITCHVIDEOMODE, + KEY_BRIGHTNESSDOWN, + KEY_BRIGHTNESSUP, + KEY_VENDOR, + KEY_MAX +}; + +static void cmpc_keys_handler(struct acpi_device *dev, u32 event) +{ + struct input_dev *inputdev; + int code = KEY_MAX; + + if ((event & 0x0F) < ARRAY_SIZE(cmpc_keys_codes)) + code = cmpc_keys_codes[event & 0x0F]; + inputdev = dev_get_drvdata(&dev->dev);; + input_report_key(inputdev, code, !(event & 0x10)); +} + +static void cmpc_keys_idev_init(struct input_dev *inputdev) +{ + int i; + + set_bit(EV_KEY, inputdev->evbit); + for (i = 0; cmpc_keys_codes[i] != KEY_MAX; i++) + set_bit(cmpc_keys_codes[i], inputdev->keybit); +} + +static int cmpc_keys_add(struct acpi_device *acpi) +{ + return cmpc_add_acpi_notify_device(acpi, "cmpc_keys", + cmpc_keys_idev_init); +} + +static int cmpc_keys_remove(struct acpi_device *acpi, int type) +{ + return cmpc_remove_acpi_notify_device(acpi); +} + +static const struct acpi_device_id cmpc_keys_device_ids[] = { + {"FnBT0000", 0}, + {"", 0} +}; +MODULE_DEVICE_TABLE(acpi, cmpc_keys_device_ids); + +static struct acpi_driver cmpc_keys_acpi_driver = { + .owner = THIS_MODULE, + .name = "cmpc_keys", + .class = "cmpc_keys", + .ids = cmpc_keys_device_ids, + .ops = { + .add = cmpc_keys_add, + .remove = cmpc_keys_remove, + .notify = cmpc_keys_handler, + } +}; + + +/* + * General init/exit code. + */ + +static int cmpc_init(void) +{ + int r; + + r = acpi_bus_register_driver(&cmpc_keys_acpi_driver); + if (r) + goto failed_keys; + + r = acpi_bus_register_driver(&cmpc_bl_acpi_driver); + if (r) + goto failed_bl; + + r = acpi_bus_register_driver(&cmpc_tablet_acpi_driver); + if (r) + goto failed_tablet; + + r = acpi_bus_register_driver(&cmpc_accel_acpi_driver); + if (r) + goto failed_accel; + + return r; + +failed_accel: + acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); + +failed_tablet: + acpi_bus_unregister_driver(&cmpc_bl_acpi_driver); + +failed_bl: + acpi_bus_unregister_driver(&cmpc_keys_acpi_driver); + +failed_keys: + return r; +} + +static void cmpc_exit(void) +{ + acpi_bus_unregister_driver(&cmpc_accel_acpi_driver); + acpi_bus_unregister_driver(&cmpc_tablet_acpi_driver); + acpi_bus_unregister_driver(&cmpc_bl_acpi_driver); + acpi_bus_unregister_driver(&cmpc_keys_acpi_driver); +} + +module_init(cmpc_init); +module_exit(cmpc_exit); -- cgit v1.2.3-70-g09d2 From 603adaf6b3e37450235f0ddb5986b961b3146a79 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 14:52:53 +0100 Subject: amd64_edac: fix K8 chip select reporting Fix the case when amd64_debug_display_dimm_sizes() reports only half the amount of DRAM on it because it doesn't account for when the single DCT operates in 128-bit mode and merges chip selects from different DIMMs. Reported-by: Johannes Hirte LKML-Reference: <200912112202.48173.johannes.hirte@fem.tu-ilmenau.de> Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index df5b68433f3..784cc5a1ebc 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -1700,11 +1700,14 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, */ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) { - int dimm, size0, size1; + int dimm, size0, size1, factor = 0; u32 dbam; u32 *dcsb; if (boot_cpu_data.x86 == 0xf) { + if (pvt->dclr0 & F10_WIDTH_128) + factor = 1; + /* K8 families < revF not supported yet */ if (pvt->ext_model < K8_REV_F) return; @@ -1732,7 +1735,8 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); edac_printk(KERN_DEBUG, EDAC_MC, " %d: %5dMB %d: %5dMB\n", - dimm * 2, size0, dimm * 2 + 1, size1); + dimm * 2, size0 << factor, + dimm * 2 + 1, size1 << factor); } } -- cgit v1.2.3-70-g09d2 From 8f68ed9728193b1f2fb53ba06031b06bd8b3d1b4 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 15:15:59 +0100 Subject: amd64_edac: fix driver instance freeing Fix use-after-free errors by pushing all memory-freeing calls to the end of amd64_remove_one_instance(). Reported-by: Darren Jenkins LKML-Reference: <1261370306.11354.52.camel@ICE-BOX> Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 784cc5a1ebc..fb0d36b4741 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2929,16 +2929,15 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) amd64_free_mc_sibling_devices(pvt); - kfree(pvt); - mci->pvt_info = NULL; - - mci_lookup[pvt->mc_node_id] = NULL; - /* unregister from EDAC MCE */ amd_report_gart_errors(false); amd_unregister_ecc_decoder(amd64_decode_bus_error); /* Free the EDAC CORE resources */ + mci->pvt_info = NULL; + mci_lookup[pvt->mc_node_id] = NULL; + + kfree(pvt); edac_mc_free(mci); } -- cgit v1.2.3-70-g09d2 From 56b34b91e22313294154cee0c16e294cf8a45b61 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 18:13:01 +0100 Subject: amd64_edac: make driver loading more robust Currently, the module does not initialize fully when the DIMMs aren't ECC but remains still loaded. Propagate the error when no instance of the driver is properly initialized and prevent further loading. Reorganize and polish error handling in amd64_edac_init() while at it. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index fb0d36b4741..a8af27a7482 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -3014,25 +3014,29 @@ static void amd64_setup_pci_device(void) static int __init amd64_edac_init(void) { int nb, err = -ENODEV; + bool load_ok = false; edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); opstate_init(); if (cache_k8_northbridges() < 0) - return err; + goto err_ret; msrs = msrs_alloc(); + if (!msrs) + goto err_ret; err = pci_register_driver(&amd64_pci_driver); if (err) - return err; + goto err_pci; /* * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd * amd64_pvt structs. These will be used in the 2nd stage init function * to finish initialization of the MC instances. */ + err = -ENODEV; for (nb = 0; nb < num_k8_northbridges; nb++) { if (!pvt_lookup[nb]) continue; @@ -3040,16 +3044,21 @@ static int __init amd64_edac_init(void) err = amd64_init_2nd_stage(pvt_lookup[nb]); if (err) goto err_2nd_stage; - } - amd64_setup_pci_device(); + load_ok = true; + } - return 0; + if (load_ok) { + amd64_setup_pci_device(); + return 0; + } err_2nd_stage: - debugf0("2nd stage failed\n"); pci_unregister_driver(&amd64_pci_driver); - +err_pci: + msrs_free(msrs); + msrs = NULL; +err_ret: return err; } -- cgit v1.2.3-70-g09d2 From 43f5e68733cfe8bed3c30b5c14c4993dffb29766 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 18:55:18 +0100 Subject: amd64_edac: fix forcing module load/unload Clear the override flag after force-loading the module. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index a8af27a7482..63c04d31cd7 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2690,9 +2690,8 @@ static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) amd64_printk(KERN_WARNING, "%s", ecc_warning); return -ENODEV; } - } else - /* CLEAR the override, since BIOS controlled it */ ecc_enable_override = 0; + } return 0; } -- cgit v1.2.3-70-g09d2 From 92389102b6832fc779f5c37f1d9e3eaadea6e059 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 19:21:41 +0100 Subject: amd64_edac: restrict PCI config space access Do not access F2x19[0,4] on K8 since they're undefined there. Signed-off-by: Borislav Petkov --- drivers/edac/amd64_edac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 63c04d31cd7..c5facd951dd 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -2349,7 +2349,7 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); - if (!dct_ganging_enabled(pvt)) { + if (!dct_ganging_enabled(pvt) && boot_cpu_data.x86 >= 0x10) { amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1); } -- cgit v1.2.3-70-g09d2 From 5213c32f9d56db6a5e3ae8d2977a3961e98211fd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 21 Dec 2009 19:11:12 +0100 Subject: edac, pci: remove pesky debug printk Do not spam the logs needlessly with the sole info that edac_pci_dev_parity_clear is being called. Signed-off-by: Borislav Petkov --- drivers/edac/edac_pci_sysfs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 422728cfe99..fb60a877d76 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -534,8 +534,6 @@ static void edac_pci_dev_parity_clear(struct pci_dev *dev) { u8 header_type; - debugf0("%s()\n", __func__); - get_pci_parity_status(dev, 0); /* read the device TYPE, looking for bridges */ -- cgit v1.2.3-70-g09d2 From ed5a35acbb48d512332a53565e6341c65eecfa29 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 24 Dec 2009 13:36:21 +0000 Subject: VIDEO: cyberpro: pci_request_regions needs a persistent name Don't pass a name pointer from the kernel stack, it will not survive and will result in corrupted /proc/iomem output. Signed-off-by: Russell King --- drivers/video/cyber2000fb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index da7c01b39be..3a561df2e8a 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1573,15 +1573,15 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) if (err) return err; - err = pci_request_regions(dev, name); - if (err) - return err; - err = -ENOMEM; cfb = cyberpro_alloc_fb_info(id->driver_data, name); if (!cfb) goto failed_release; + err = pci_request_regions(dev, cfb->fb.fix.id); + if (err) + goto failed_regions; + cfb->dev = dev; cfb->region = pci_ioremap_bar(dev, 0); if (!cfb->region) @@ -1633,10 +1633,10 @@ cyberpro_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) failed: iounmap(cfb->region); failed_ioremap: + pci_release_regions(dev); +failed_regions: cyberpro_free_fb_info(cfb); failed_release: - pci_release_regions(dev); - return err; } -- cgit v1.2.3-70-g09d2