diff --git a/debian/changelog b/debian/changelog index f329e97f0..bd4ce6c04 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +linux (3.17~rc4-1~exp1) UNRELEASED; urgency=medium + + * New upstream release candidate + + -- Ben Hutchings Sat, 13 Sep 2014 06:42:35 +0100 + linux (3.16.2-3) unstable; urgency=medium [ Ben Hutchings ] diff --git a/debian/patches/bugfix/all/aio-fix-reqs_available-handling.patch b/debian/patches/bugfix/all/aio-fix-reqs_available-handling.patch deleted file mode 100644 index 72e156f6d..000000000 --- a/debian/patches/bugfix/all/aio-fix-reqs_available-handling.patch +++ /dev/null @@ -1,161 +0,0 @@ -From: Benjamin LaHaise -Date: Sun, 24 Aug 2014 13:14:05 -0400 -Subject: aio: fix reqs_available handling -Origin: https://git.kernel.org/linus/d856f32a86b2b015ab180ab7a55e455ed8d3ccc5 - -As reported by Dan Aloni, commit f8567a3845ac ("aio: fix aio request -leak when events are reaped by userspace") introduces a regression when -user code attempts to perform io_submit() with more events than are -available in the ring buffer. Reverting that commit would reintroduce a -regression when user space event reaping is used. - -Fixing this bug is a bit more involved than the previous attempts to fix -this regression. Since we do not have a single point at which we can -count events as being reaped by user space and io_getevents(), we have -to track event completion by looking at the number of events left in the -event ring. So long as there are as many events in the ring buffer as -there have been completion events generate, we cannot call -put_reqs_available(). The code to check for this is now placed in -refill_reqs_available(). - -A test program from Dan and modified by me for verifying this bug is available -at http://www.kvack.org/~bcrl/20140824-aio_bug.c . - -Reported-by: Dan Aloni -Signed-off-by: Benjamin LaHaise -Acked-by: Dan Aloni -Cc: Kent Overstreet -Cc: Mateusz Guzik -Cc: Petr Matousek -Cc: stable@vger.kernel.org # v3.16 and anything that f8567a3845ac was backported to -Signed-off-by: Linus Torvalds ---- - fs/aio.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 73 insertions(+), 4 deletions(-) - ---- a/fs/aio.c -+++ b/fs/aio.c -@@ -141,6 +141,7 @@ struct kioctx { - - struct { - unsigned tail; -+ unsigned completed_events; - spinlock_t completion_lock; - } ____cacheline_aligned_in_smp; - -@@ -880,6 +881,68 @@ out: - return ret; - } - -+/* refill_reqs_available -+ * Updates the reqs_available reference counts used for tracking the -+ * number of free slots in the completion ring. This can be called -+ * from aio_complete() (to optimistically update reqs_available) or -+ * from aio_get_req() (the we're out of events case). It must be -+ * called holding ctx->completion_lock. -+ */ -+static void refill_reqs_available(struct kioctx *ctx, unsigned head, -+ unsigned tail) -+{ -+ unsigned events_in_ring, completed; -+ -+ /* Clamp head since userland can write to it. */ -+ head %= ctx->nr_events; -+ if (head <= tail) -+ events_in_ring = tail - head; -+ else -+ events_in_ring = ctx->nr_events - (head - tail); -+ -+ completed = ctx->completed_events; -+ if (events_in_ring < completed) -+ completed -= events_in_ring; -+ else -+ completed = 0; -+ -+ if (!completed) -+ return; -+ -+ ctx->completed_events -= completed; -+ put_reqs_available(ctx, completed); -+} -+ -+/* user_refill_reqs_available -+ * Called to refill reqs_available when aio_get_req() encounters an -+ * out of space in the completion ring. -+ */ -+static void user_refill_reqs_available(struct kioctx *ctx) -+{ -+ spin_lock_irq(&ctx->completion_lock); -+ if (ctx->completed_events) { -+ struct aio_ring *ring; -+ unsigned head; -+ -+ /* Access of ring->head may race with aio_read_events_ring() -+ * here, but that's okay since whether we read the old version -+ * or the new version, and either will be valid. The important -+ * part is that head cannot pass tail since we prevent -+ * aio_complete() from updating tail by holding -+ * ctx->completion_lock. Even if head is invalid, the check -+ * against ctx->completed_events below will make sure we do the -+ * safe/right thing. -+ */ -+ ring = kmap_atomic(ctx->ring_pages[0]); -+ head = ring->head; -+ kunmap_atomic(ring); -+ -+ refill_reqs_available(ctx, head, ctx->tail); -+ } -+ -+ spin_unlock_irq(&ctx->completion_lock); -+} -+ - /* aio_get_req - * Allocate a slot for an aio request. - * Returns NULL if no requests are free. -@@ -888,8 +951,11 @@ static inline struct kiocb *aio_get_req( - { - struct kiocb *req; - -- if (!get_reqs_available(ctx)) -- return NULL; -+ if (!get_reqs_available(ctx)) { -+ user_refill_reqs_available(ctx); -+ if (!get_reqs_available(ctx)) -+ return NULL; -+ } - - req = kmem_cache_alloc(kiocb_cachep, GFP_KERNEL|__GFP_ZERO); - if (unlikely(!req)) -@@ -948,8 +1014,8 @@ void aio_complete(struct kiocb *iocb, lo - struct kioctx *ctx = iocb->ki_ctx; - struct aio_ring *ring; - struct io_event *ev_page, *event; -+ unsigned tail, pos, head; - unsigned long flags; -- unsigned tail, pos; - - /* - * Special case handling for sync iocbs: -@@ -1010,10 +1076,14 @@ void aio_complete(struct kiocb *iocb, lo - ctx->tail = tail; - - ring = kmap_atomic(ctx->ring_pages[0]); -+ head = ring->head; - ring->tail = tail; - kunmap_atomic(ring); - flush_dcache_page(ctx->ring_pages[0]); - -+ ctx->completed_events++; -+ if (ctx->completed_events > 1) -+ refill_reqs_available(ctx, head, tail); - spin_unlock_irqrestore(&ctx->completion_lock, flags); - - pr_debug("added to ring %p at [%u]\n", iocb, tail); -@@ -1028,7 +1098,6 @@ void aio_complete(struct kiocb *iocb, lo - - /* everything turned out well, dispose of the aiocb. */ - kiocb_free(iocb); -- put_reqs_available(ctx, 1); - - /* - * We have to order our ring_info tail store above and test diff --git a/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch b/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch index 95ebd9190..2e25e5a96 100644 --- a/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch +++ b/debian/patches/bugfix/all/firmware-remove-redundant-log-messages-from-drivers.patch @@ -96,8 +96,8 @@ upstream submission. fw_size = firmware->size / sizeof(u32); --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c -@@ -370,10 +370,8 @@ static int ath3k_load_patch(struct usb_d - le32_to_cpu(fw_version.rom_version)); +@@ -375,10 +375,8 @@ static int ath3k_load_patch(struct usb_d + le32_to_cpu(fw_version.rom_version)); ret = request_firmware(&firmware, filename, &udev->dev); - if (ret < 0) { @@ -106,9 +106,9 @@ upstream submission. return ret; - } - pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8); - pt_version.build_version = *(int *) -@@ -432,10 +430,8 @@ static int ath3k_load_syscfg(struct usb_ + pt_rom_version = get_unaligned_le32(firmware->data + + firmware->size - 8); +@@ -438,10 +436,8 @@ static int ath3k_load_syscfg(struct usb_ le32_to_cpu(fw_version.rom_version), clk_value, ".dfu"); ret = request_firmware(&firmware, filename, &udev->dev); @@ -168,7 +168,7 @@ upstream submission. --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c -@@ -288,8 +288,6 @@ static int btmrvl_sdio_download_helper(s +@@ -297,8 +297,6 @@ static int btmrvl_sdio_download_helper(s ret = request_firmware(&fw_helper, card->helper, &card->func->dev); if ((ret < 0) || !fw_helper) { @@ -177,7 +177,7 @@ upstream submission. ret = -ENOENT; goto done; } -@@ -388,8 +386,6 @@ static int btmrvl_sdio_download_fw_w_hel +@@ -397,8 +395,6 @@ static int btmrvl_sdio_download_fw_w_hel ret = request_firmware(&fw_firmware, card->firmware, &card->func->dev); if ((ret < 0) || !fw_firmware) { @@ -203,7 +203,7 @@ upstream submission. fw->size, fw_name); --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c -@@ -1269,10 +1269,8 @@ static void sdma_load_firmware(const str +@@ -1286,10 +1286,8 @@ static void sdma_load_firmware(const str const struct sdma_script_start_addrs *addr; unsigned short *ram_code; @@ -232,7 +232,7 @@ upstream submission. where = 0; --- a/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c -@@ -1221,10 +1221,8 @@ nvc0_graph_ctor_fw(struct nvc0_graph_pri +@@ -1496,10 +1496,8 @@ nvc0_graph_ctor_fw(struct nvc0_graph_pri if (ret) { snprintf(f, sizeof(f), "nouveau/%s", fwname); ret = request_firmware(&fw, f, nv_device_base(device)); @@ -274,7 +274,7 @@ upstream submission. release_firmware(rdev->me_fw); --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c -@@ -1036,10 +1036,7 @@ static int r100_cp_init_microcode(struct +@@ -1012,10 +1012,7 @@ static int r100_cp_init_microcode(struct } err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); @@ -288,7 +288,7 @@ upstream submission. rdev->me_fw->size, fw_name); --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c -@@ -2434,10 +2434,6 @@ int r600_init_microcode(struct radeon_de +@@ -2426,10 +2426,6 @@ int r600_init_microcode(struct radeon_de out: if (err) { @@ -342,7 +342,7 @@ upstream submission. ret = qib_ibsd_ucode_loaded(dd->pport, fw); --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c -@@ -1236,10 +1236,8 @@ static int mxt_load_fw(struct device *de +@@ -1932,10 +1932,8 @@ static int mxt_load_fw(struct device *de int ret; ret = request_firmware(&fw, fn, dev); @@ -381,7 +381,7 @@ upstream submission. } --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c -@@ -2256,12 +2256,9 @@ static int stk9090m_frontend_attach(stru +@@ -2372,12 +2372,9 @@ static int stk9090m_frontend_attach(stru dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80); @@ -396,7 +396,7 @@ upstream submission. stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size; stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data; -@@ -2322,12 +2319,9 @@ static int nim9090md_frontend_attach(str +@@ -2438,12 +2435,9 @@ static int nim9090md_frontend_attach(str msleep(20); dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1); @@ -468,7 +468,7 @@ upstream submission. p = kmalloc(fw->size, GFP_KERNEL); --- a/drivers/media/dvb-frontends/af9013.c +++ b/drivers/media/dvb-frontends/af9013.c -@@ -1373,16 +1373,8 @@ static int af9013_download_firmware(stru +@@ -1372,16 +1372,8 @@ static int af9013_download_firmware(stru /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, state->i2c->dev.parent); @@ -685,7 +685,7 @@ upstream submission. printk(KERN_INFO "tda1004x: please rename the firmware file to %s\n", --- a/drivers/media/dvb-frontends/tda10071.c +++ b/drivers/media/dvb-frontends/tda10071.c -@@ -952,12 +952,8 @@ static int tda10071_init(struct dvb_fron +@@ -956,12 +956,8 @@ static int tda10071_init(struct dvb_fron /* request the firmware, this will block and timeout */ ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent); @@ -701,7 +701,7 @@ upstream submission. for (i = 0; i < ARRAY_SIZE(tab2); i++) { --- a/drivers/media/pci/ngene/ngene-core.c +++ b/drivers/media/pci/ngene/ngene-core.c -@@ -1266,13 +1266,8 @@ static int ngene_load_firm(struct ngene +@@ -1262,13 +1262,8 @@ static int ngene_load_firm(struct ngene break; } @@ -716,7 +716,7 @@ upstream submission. if (size == 0) size = fw->size; if (size != fw->size) { -@@ -1280,8 +1275,6 @@ static int ngene_load_firm(struct ngene +@@ -1276,8 +1271,6 @@ static int ngene_load_firm(struct ngene ": Firmware %s has invalid size!", fw_name); err = -1; } else { @@ -791,7 +791,7 @@ upstream submission. b[0] = 0xaa; --- a/drivers/media/usb/ttusb-dec/ttusb_dec.c +++ b/drivers/media/usb/ttusb-dec/ttusb_dec.c -@@ -1302,11 +1302,8 @@ static int ttusb_dec_boot_dsp(struct ttu +@@ -1297,11 +1297,8 @@ static int ttusb_dec_boot_dsp(struct ttu dprintk("%s\n", __func__); result = request_firmware(&fw_entry, dec->firmware_name, &dec->udev->dev); @@ -835,7 +835,7 @@ upstream submission. fw_data = (void *)fw_entry->data; --- a/drivers/media/pci/bt8xx/bttv-cards.c +++ b/drivers/media/pci/bt8xx/bttv-cards.c -@@ -3814,10 +3814,8 @@ static int pvr_boot(struct bttv *btv) +@@ -3834,10 +3834,8 @@ static int pvr_boot(struct bttv *btv) int rc; rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); @@ -958,7 +958,7 @@ upstream submission. printk(KERN_ERR "ERROR: Firmware size mismatch " --- a/drivers/media/pci/cx23885/cx23885-cards.c +++ b/drivers/media/pci/cx23885/cx23885-cards.c -@@ -1905,11 +1905,7 @@ void cx23885_card_setup(struct cx23885_d +@@ -1958,11 +1958,7 @@ void cx23885_card_setup(struct cx23885_d cinfo.rev, filename); ret = request_firmware(&fw, filename, &dev->pci->dev); @@ -1061,7 +1061,7 @@ upstream submission. --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c -@@ -2306,10 +2306,8 @@ static int s2255_probe(struct usb_interf +@@ -2304,10 +2304,8 @@ static int s2255_probe(struct usb_interf } /* load the first chunk */ if (request_firmware(&dev->fw_data->fw, @@ -1075,22 +1075,10 @@ upstream submission. pdata = (__le32 *) &dev->fw_data->fw->data[fw_size - 8]; --- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c -@@ -86,10 +86,8 @@ int s5p_mfc_load_firmware(struct s5p_mfc +@@ -94,10 +94,8 @@ int s5p_mfc_load_firmware(struct s5p_mfc + } + } - err = request_firmware((const struct firmware **)&fw_blob, - dev->variant->fw_name, dev->v4l2_dev.dev); -- if (err != 0) { -- mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); -+ if (err != 0) - return -EINVAL; -- } - if (fw_blob->size > dev->fw_size) { - mfc_err("MFC firmware is too big to be loaded\n"); - release_firmware(fw_blob); -@@ -119,10 +117,8 @@ int s5p_mfc_reload_firmware(struct s5p_m - - err = request_firmware((const struct firmware **)&fw_blob, - dev->variant->fw_name, dev->v4l2_dev.dev); - if (err != 0) { - mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n"); + if (err != 0) @@ -1130,7 +1118,7 @@ upstream submission. --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c -@@ -301,11 +301,8 @@ static long download_firmware(struct kim +@@ -302,11 +302,8 @@ static long download_firmware(struct kim request_firmware(&kim_gdata->fw_entry, bts_scr_name, &kim_gdata->kim_pdev->dev); if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) || @@ -1218,7 +1206,7 @@ upstream submission. --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c -@@ -3700,16 +3700,13 @@ static int bnx2_request_uncached_firmwar +@@ -3701,16 +3701,13 @@ static int bnx2_request_uncached_firmwar } rc = request_firmware(&bp->mips_firmware, mips_fw_file, &bp->pdev->dev); @@ -1240,7 +1228,7 @@ upstream submission. if (bp->mips_firmware->size < sizeof(*mips_fw) || --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c -@@ -12775,11 +12775,8 @@ static int bnx2x_init_firmware(struct bn +@@ -12747,11 +12747,8 @@ static int bnx2x_init_firmware(struct bn BNX2X_DEV_INFO("Loading %s\n", fw_file_name); rc = request_firmware(&bp->firmware, fw_file_name, &bp->pdev->dev); @@ -1255,7 +1243,7 @@ upstream submission. if (rc) { --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c -@@ -11286,11 +11286,8 @@ static int tg3_request_firmware(struct t +@@ -11305,11 +11305,8 @@ static int tg3_request_firmware(struct t { const struct tg3_firmware_hdr *fw_hdr; @@ -1338,7 +1326,7 @@ upstream submission. netif_info(nic, probe, nic->netdev, --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c -@@ -600,8 +600,6 @@ static int myri10ge_load_hotplug_firmwar +@@ -601,8 +601,6 @@ static int myri10ge_load_hotplug_firmwar unsigned i; if ((status = request_firmware(&fw, mgp->fw_name, dev)) < 0) { @@ -1431,7 +1419,7 @@ upstream submission. } else --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c -@@ -1553,13 +1553,8 @@ static struct fwentry *at76_load_firmwar +@@ -1622,13 +1622,8 @@ static struct fwentry *at76_load_firmwar at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname); ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev); @@ -1464,7 +1452,7 @@ upstream submission. &hif_dev->udev->dev); --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c -@@ -1025,7 +1025,6 @@ static void carl9170_usb_firmware_step2( +@@ -1032,7 +1032,6 @@ static void carl9170_usb_firmware_step2( return; } @@ -1490,7 +1478,7 @@ upstream submission. int success = 0; --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c -@@ -2160,19 +2160,8 @@ int b43_do_request_fw(struct b43_request +@@ -2185,19 +2185,8 @@ int b43_do_request_fw(struct b43_request } err = request_firmware(&ctx->blob, ctx->fwname, ctx->dev->dev->dev); @@ -1552,7 +1540,7 @@ upstream submission. } --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c -@@ -8425,12 +8425,8 @@ static int ipw2100_get_firmware(struct i +@@ -8419,12 +8419,8 @@ static int ipw2100_get_firmware(struct i rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev); @@ -1592,7 +1580,7 @@ upstream submission. else --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c -@@ -979,13 +979,8 @@ static void iwl_req_fw_callback(const st +@@ -990,13 +990,8 @@ static void iwl_req_fw_callback(const st memset(&pieces, 0, sizeof(pieces)); @@ -1620,7 +1608,7 @@ upstream submission. } --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c -@@ -421,11 +421,8 @@ static void mwifiex_fw_dpc(const struct +@@ -427,11 +427,8 @@ static void mwifiex_fw_dpc(const struct bool init_failed = false; struct wireless_dev *wdev; @@ -1635,7 +1623,7 @@ upstream submission. adapter->firmware = firmware; --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c -@@ -5715,16 +5715,12 @@ static int mwl8k_firmware_load_success(s +@@ -5708,16 +5708,12 @@ static int mwl8k_firmware_load_success(s static void mwl8k_fw_state_machine(const struct firmware *fw, void *context) { struct mwl8k_priv *priv = context; @@ -1653,7 +1641,7 @@ upstream submission. priv->fw_helper = fw; rc = mwl8k_request_fw(priv, priv->fw_pref, &priv->fw_ucode, true); -@@ -5759,11 +5755,8 @@ static void mwl8k_fw_state_machine(const +@@ -5752,11 +5748,8 @@ static void mwl8k_fw_state_machine(const break; case FW_STATE_LOADING_ALT: @@ -1666,7 +1654,7 @@ upstream submission. priv->fw_ucode = fw; rc = mwl8k_firmware_load_success(priv); if (rc) -@@ -5801,10 +5794,8 @@ retry: +@@ -5794,10 +5787,8 @@ retry: /* Ask userland hotplug daemon for the device firmware */ rc = mwl8k_request_firmware(priv, fw_image, nowait); @@ -1714,7 +1702,7 @@ upstream submission. --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c -@@ -1690,7 +1690,6 @@ static int ezusb_probe(struct usb_interf +@@ -1675,7 +1675,6 @@ static int ezusb_probe(struct usb_interf if (ezusb_firmware_download(upriv, &firmware) < 0) goto error; } else { @@ -1835,7 +1823,7 @@ upstream submission. wl1251_error("nvs size is not multiple of 32 bits: %zu", --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c -@@ -748,10 +748,8 @@ static int wl12xx_fetch_firmware(struct +@@ -749,10 +749,8 @@ static int wl12xx_fetch_firmware(struct ret = request_firmware(&fw, fw_name, wl->dev); @@ -1944,7 +1932,7 @@ upstream submission. if (err) { --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c -@@ -1778,7 +1778,6 @@ bfad_read_firmware(struct pci_dev *pdev, +@@ -1766,7 +1766,6 @@ bfad_read_firmware(struct pci_dev *pdev, const struct firmware *fw; if (request_firmware(&fw, fw_name, &pdev->dev)) { @@ -1968,15 +1956,16 @@ upstream submission. --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c -@@ -676,9 +676,6 @@ static ssize_t pm8001_store_update_fw(st +@@ -687,10 +687,6 @@ static ssize_t pm8001_store_update_fw(st pm8001_ha->dev); - if (err) { + if (ret) { - PM8001_FAIL_DBG(pm8001_ha, -- pm8001_printk("Failed to load firmware image file %s," -- " error %d\n", filename_ptr, err)); - err = FAIL_OPEN_BIOS_FILE; - goto out1; +- pm8001_printk( +- "Failed to load firmware image file %s, error %d\n", +- filename_ptr, ret)); + pm8001_ha->fw_status = FAIL_OPEN_BIOS_FILE; + goto out; } --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -1991,7 +1980,7 @@ upstream submission. } --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c -@@ -5358,8 +5358,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha, +@@ -5350,8 +5350,6 @@ qla2x00_load_risc(scsi_qla_host_t *vha, /* Load firmware blob. */ blob = qla2x00_request_firmware(vha); if (!blob) { @@ -2000,7 +1989,7 @@ upstream submission. ql_log(ql_log_info, vha, 0x0084, "Firmware images can be retrieved from: "QLA_FW_URL ".\n"); return QLA_FUNCTION_FAILED; -@@ -5461,8 +5459,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t * +@@ -5453,8 +5451,6 @@ qla24xx_load_risc_blob(scsi_qla_host_t * /* Load firmware blob. */ blob = qla2x00_request_firmware(vha); if (!blob) { @@ -2011,7 +2000,7 @@ upstream submission. QLA_FW_URL ".\n"); --- a/drivers/scsi/qla2xxx/qla_nx.c +++ b/drivers/scsi/qla2xxx/qla_nx.c -@@ -2449,11 +2449,8 @@ try_blob_fw: +@@ -2459,11 +2459,8 @@ try_blob_fw: /* Load firmware blob. */ blob = ha->hablob = qla2x00_request_firmware(vha); @@ -2026,7 +2015,7 @@ upstream submission. if (qla82xx_validate_firmware_blob(vha, --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c -@@ -5393,8 +5393,6 @@ qla2x00_request_firmware(scsi_qla_host_t +@@ -5413,8 +5413,6 @@ qla2x00_request_firmware(scsi_qla_host_t goto out; if (request_firmware(&blob->fw, blob->name, &ha->pdev->dev)) { @@ -2052,7 +2041,7 @@ upstream submission. fw->size, fwname); --- a/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c +++ b/drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c -@@ -2233,16 +2233,12 @@ struct net_device *init_ft1000_card(stru +@@ -2230,16 +2230,12 @@ struct net_device *init_ft1000_card(stru info->AsicID = ft1000_read_reg(dev, FT1000_REG_ASIC_ID); if (info->AsicID == ELECTRABUZZ_ID) { DEBUG(0, "ft1000_hw: ELECTRABUZZ ASIC\n"); @@ -2113,9 +2102,9 @@ upstream submission. /* initiate firmware upload */ errno = as102_firmware_upload(bus_adap, cmd_buf, firmware); ---- a/drivers/staging/media/go7007/go7007-driver.c -+++ b/drivers/staging/media/go7007/go7007-driver.c -@@ -95,10 +95,8 @@ static int go7007_load_encoder(struct go +--- a/drivers/media/usb/go7007/go7007-driver.c ++++ b/drivers/media/usb/go7007/go7007-driver.c +@@ -92,10 +92,8 @@ static int go7007_load_encoder(struct go u16 intr_val, intr_data; if (go->boot_fw == NULL) { @@ -2127,8 +2116,8 @@ upstream submission. if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) { v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name); release_firmware(fw_entry); ---- a/drivers/staging/media/go7007/go7007-fw.c -+++ b/drivers/staging/media/go7007/go7007-fw.c +--- a/drivers/media/usb/go7007/go7007-fw.c ++++ b/drivers/media/usb/go7007/go7007-fw.c @@ -1570,12 +1570,8 @@ int go7007_construct_fw_image(struct go7 default: return -1; @@ -2143,9 +2132,9 @@ upstream submission. code = kzalloc(codespace * 2, GFP_KERNEL); if (code == NULL) goto fw_failed; ---- a/drivers/staging/media/go7007/go7007-loader.c -+++ b/drivers/staging/media/go7007/go7007-loader.c -@@ -79,11 +79,8 @@ static int go7007_loader_probe(struct us +--- a/drivers/media/usb/go7007/go7007-loader.c ++++ b/drivers/media/usb/go7007/go7007-loader.c +@@ -75,11 +75,8 @@ static int go7007_loader_probe(struct us dev_info(&interface->dev, "loading firmware %s\n", fw1); @@ -2158,7 +2147,7 @@ upstream submission. ret = cypress_load_firmware(usbdev, fw, CYPRESS_FX2); release_firmware(fw); if (0 != ret) { -@@ -94,11 +91,8 @@ static int go7007_loader_probe(struct us +@@ -90,11 +87,8 @@ static int go7007_loader_probe(struct us if (fw2 == NULL) return 0; @@ -2203,12 +2192,12 @@ upstream submission. struct usb_device *udev = padapter->dvobjpriv.pusbdev; struct usb_interface *pusb_intf = padapter->pusb_intf; - dev_err(&udev->dev, "r8712u: Firmware request failed\n"); - padapter->fw_found = false; usb_put_dev(udev); usb_set_intfdata(pusb_intf, NULL); + return; --- a/drivers/staging/slicoss/slicoss.c +++ b/drivers/staging/slicoss/slicoss.c -@@ -402,11 +402,8 @@ static int slic_card_download_gbrcv(stru +@@ -393,11 +393,8 @@ static int slic_card_download_gbrcv(stru } ret = request_firmware(&fw, file, &adapter->pcidev->dev); @@ -2221,7 +2210,7 @@ upstream submission. rcvucodelen = *(u32 *)(fw->data + index); index += 4; -@@ -480,11 +477,8 @@ static int slic_card_download(struct ada +@@ -471,11 +468,8 @@ static int slic_card_download(struct ada return -ENOENT; } ret = request_firmware(&fw, file, &adapter->pcidev->dev); @@ -2236,8 +2225,8 @@ upstream submission. for (i = 0; i < numsects; i++) { --- a/drivers/staging/vt6656/firmware.c +++ b/drivers/staging/vt6656/firmware.c -@@ -57,11 +57,8 @@ int FIRMWAREbDownload(struct vnt_private - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---->Download firmware\n"); +@@ -53,11 +53,8 @@ int vnt_download_firmware(struct vnt_pri + dev_dbg(dev, "---->Download firmware\n"); rc = request_firmware(&fw, FIRMWARE_NAME, dev); - if (rc) { @@ -2248,8 +2237,8 @@ upstream submission. + if (rc) + goto out; - pBuffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); - if (!pBuffer) + buffer = kmalloc(FIRMWARE_CHUNK_SIZE, GFP_KERNEL); + if (!buffer) --- a/drivers/tty/cyclades.c +++ b/drivers/tty/cyclades.c @@ -3522,10 +3522,8 @@ static int cyz_load_fw(struct pci_dev *p @@ -2309,7 +2298,7 @@ upstream submission. } --- a/drivers/tty/serial/ucc_uart.c +++ b/drivers/tty/serial/ucc_uart.c -@@ -1178,10 +1178,8 @@ static void uart_firmware_cont(const str +@@ -1167,10 +1167,8 @@ static void uart_firmware_cont(const str struct device *dev = context; int ret; @@ -2657,7 +2646,7 @@ upstream submission. filename, emu->firmware->size); --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c -@@ -1407,10 +1407,8 @@ static void azx_firmware_cb(const struct +@@ -1644,10 +1644,8 @@ static void azx_firmware_cb(const struct struct azx *chip = card->private_data; struct pci_dev *pci = chip->pci; @@ -2742,7 +2731,7 @@ upstream submission. "too short firmware size %d (expected %d)\n", --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c -@@ -891,10 +891,8 @@ static int wm2000_i2c_probe(struct i2c_c +@@ -889,10 +889,8 @@ static int wm2000_i2c_probe(struct i2c_c } ret = request_firmware(&fw, filename, &i2c->dev); diff --git a/debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch b/debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch index 3566be4e9..93ec08ec4 100644 --- a/debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch +++ b/debian/patches/bugfix/all/firmware_class-log-every-success-and-failure.patch @@ -20,7 +20,7 @@ This does not cover the case where we fall back to a user-mode helper --- --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c -@@ -344,17 +344,20 @@ static int fw_get_filesystem_firmware(st +@@ -340,17 +340,20 @@ static int fw_get_filesystem_firmware(st } rc = fw_read_file_contents(file, buf); fput(file); @@ -46,7 +46,7 @@ This does not cover the case where we fall back to a user-mode helper mutex_lock(&fw_lock); set_bit(FW_STATUS_DONE, &buf->status); complete_all(&buf->completion); -@@ -1007,7 +1010,8 @@ _request_firmware_prepare(struct firmwar +@@ -1026,7 +1029,8 @@ _request_firmware_prepare(struct firmwar } if (fw_get_builtin_firmware(firmware, name)) { @@ -56,7 +56,7 @@ This does not cover the case where we fall back to a user-mode helper return 0; /* assigned */ } -@@ -1090,7 +1094,7 @@ _request_firmware(const struct firmware +@@ -1109,7 +1113,7 @@ _request_firmware(const struct firmware if (opt_flags & FW_OPT_NOWAIT) { timeout = usermodehelper_read_lock_wait(timeout); if (!timeout) { diff --git a/debian/patches/bugfix/all/firmware_class-return-specific-errors-from-file-read.patch b/debian/patches/bugfix/all/firmware_class-return-specific-errors-from-file-read.patch index 45471b429..3d3c606c3 100644 --- a/debian/patches/bugfix/all/firmware_class-return-specific-errors-from-file-read.patch +++ b/debian/patches/bugfix/all/firmware_class-return-specific-errors-from-file-read.patch @@ -17,46 +17,25 @@ Signed-off-by: Ben Hutchings --- --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c -@@ -283,12 +283,15 @@ MODULE_PARM_DESC(path, "customized firmw - static noinline_for_stack int fw_file_size(struct file *file) - { - struct kstat st; -- if (vfs_getattr(&file->f_path, &st)) -- return -1; -+ int ret; -+ -+ ret = vfs_getattr(&file->f_path, &st); -+ if (ret) -+ return ret; - if (!S_ISREG(st.mode)) -- return -1; -+ return -ENOTTY; - if (st.size != (int)st.size) -- return -1; -+ return -EFBIG; - return st.size; - } - -@@ -299,14 +302,16 @@ static int fw_read_file_contents(struct +@@ -293,7 +293,7 @@ static int fw_read_file_contents(struct int rc; - size = fw_file_size(file); -- if (size <= 0) -+ if (size < 0) -+ return size; -+ if (size == 0) + if (!S_ISREG(file_inode(file)->i_mode)) +- return -EINVAL; ++ return -ENOTTY; + size = i_size_read(file_inode(file)); + if (size <= 0) return -EINVAL; - buf = vmalloc(size); - if (!buf) +@@ -302,7 +302,7 @@ static int fw_read_file_contents(struct return -ENOMEM; rc = kernel_read(file, 0, buf, size); if (rc != size) { - if (rc > 0) + if (rc >= 0) rc = -EIO; - vfree(buf); - return rc; -@@ -333,8 +338,10 @@ static int fw_get_filesystem_firmware(st + goto fail; + } +@@ -334,8 +334,10 @@ static int fw_get_filesystem_firmware(st snprintf(path, PATH_MAX, "%s/%s", fw_path[i], buf->fw_id); file = filp_open(path, O_RDONLY, 0); @@ -68,7 +47,7 @@ Signed-off-by: Ben Hutchings rc = fw_read_file_contents(file, buf); fput(file); if (rc) -@@ -950,13 +957,6 @@ static void kill_requests_without_uevent +@@ -974,13 +976,6 @@ static void kill_requests_without_uevent #endif #else /* CONFIG_FW_LOADER_USER_HELPER */ @@ -82,15 +61,15 @@ Signed-off-by: Ben Hutchings /* No abort during direct loading */ #define is_fw_load_aborted(buf) false -@@ -1105,6 +1105,7 @@ _request_firmware(const struct firmware +@@ -1129,6 +1124,7 @@ _request_firmware(const struct firmware } ret = fw_get_filesystem_firmware(device, fw->priv); +#ifdef CONFIG_FW_LOADER_USER_HELPER if (ret) { - if (opt_flags & FW_OPT_FALLBACK) { + if (!(opt_flags & FW_OPT_NO_WARN)) dev_warn(device, -@@ -1115,6 +1116,7 @@ _request_firmware(const struct firmware +@@ -1140,6 +1136,7 @@ _request_firmware(const struct firmware opt_flags, timeout); } } diff --git a/debian/patches/bugfix/all/kbuild-use-nostdinc-in-compile-tests.patch b/debian/patches/bugfix/all/kbuild-use-nostdinc-in-compile-tests.patch index 85de40f50..6d3ad89b8 100644 --- a/debian/patches/bugfix/all/kbuild-use-nostdinc-in-compile-tests.patch +++ b/debian/patches/bugfix/all/kbuild-use-nostdinc-in-compile-tests.patch @@ -15,7 +15,7 @@ the kernel. --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include -@@ -110,12 +110,12 @@ as-instr = $(call try-run,\ +@@ -111,12 +111,12 @@ as-instr = $(call try-run,\ # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) cc-option = $(call try-run,\ @@ -30,7 +30,7 @@ the kernel. # cc-option-align # Prefix align with either -falign or -malign -@@ -125,16 +125,17 @@ cc-option-align = $(subst -functions=0,, +@@ -126,16 +126,17 @@ cc-option-align = $(subst -functions=0,, # cc-disable-warning # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) cc-disable-warning = $(call try-run,\ @@ -51,7 +51,7 @@ the kernel. # cc-ifversion # Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1) -@@ -148,7 +149,7 @@ cc-ldoption = $(call try-run,\ +@@ -149,7 +150,7 @@ cc-ldoption = $(call try-run,\ # ld-option # Usage: LDFLAGS += $(call ld-option, -X) ld-option = $(call try-run,\ @@ -62,16 +62,16 @@ the kernel. # Usage: KBUILD_ARFLAGS := $(call ar-option,D) --- a/Makefile +++ b/Makefile -@@ -578,6 +578,8 @@ else +@@ -624,6 +624,8 @@ else KBUILD_CFLAGS += -O2 endif +NOSTDINC_FLAGS += -nostdinc + - ifdef CONFIG_READABLE_ASM - # Disable optimizations that make assembler listings hard to read. - # reorder blocks reorders the control in the function -@@ -646,7 +648,7 @@ KBUILD_CFLAGS += $(call cc-option, -fno- + # Tell gcc to never replace conditional load with a non-conditional one + KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0) + +@@ -750,7 +752,7 @@ KBUILD_CFLAGS += $(call cc-option, -fno- endif # arch Makefile may override CC so keep this after arch Makefile is included diff --git a/debian/patches/bugfix/all/libceph-add-process_one_ticket-helper.patch b/debian/patches/bugfix/all/libceph-add-process_one_ticket-helper.patch deleted file mode 100644 index 8d97981b1..000000000 --- a/debian/patches/bugfix/all/libceph-add-process_one_ticket-helper.patch +++ /dev/null @@ -1,275 +0,0 @@ -From: Ilya Dryomov -Date: Mon, 8 Sep 2014 17:25:34 +0400 -Subject: libceph: add process_one_ticket() helper -Origin: https://git.kernel.org/linus/597cda357716a3cf8d994cb11927af917c8d71fa - -Add a helper for processing individual cephx auth tickets. Needed for -the next commit, which deals with allocating ticket buffers. (Most of -the diff here is whitespace - view with git diff -b). - -Cc: stable@vger.kernel.org -Signed-off-by: Ilya Dryomov -Reviewed-by: Sage Weil ---- - net/ceph/auth_x.c | 228 +++++++++++++++++++++++++++++------------------------- - 1 file changed, 124 insertions(+), 104 deletions(-) - -diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c -index 96238ba..0eb146d 100644 ---- a/net/ceph/auth_x.c -+++ b/net/ceph/auth_x.c -@@ -129,17 +129,131 @@ static void remove_ticket_handler(struct ceph_auth_client *ac, - kfree(th); - } - -+static int process_one_ticket(struct ceph_auth_client *ac, -+ struct ceph_crypto_key *secret, -+ void **p, void *end, -+ void *dbuf, void *ticket_buf) -+{ -+ struct ceph_x_info *xi = ac->private; -+ int type; -+ u8 tkt_struct_v, blob_struct_v; -+ struct ceph_x_ticket_handler *th; -+ void *dp, *dend; -+ int dlen; -+ char is_enc; -+ struct timespec validity; -+ struct ceph_crypto_key old_key; -+ void *tp, *tpend; -+ struct ceph_timespec new_validity; -+ struct ceph_crypto_key new_session_key; -+ struct ceph_buffer *new_ticket_blob; -+ unsigned long new_expires, new_renew_after; -+ u64 new_secret_id; -+ int ret; -+ -+ ceph_decode_need(p, end, sizeof(u32) + 1, bad); -+ -+ type = ceph_decode_32(p); -+ dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); -+ -+ tkt_struct_v = ceph_decode_8(p); -+ if (tkt_struct_v != 1) -+ goto bad; -+ -+ th = get_ticket_handler(ac, type); -+ if (IS_ERR(th)) { -+ ret = PTR_ERR(th); -+ goto out; -+ } -+ -+ /* blob for me */ -+ dlen = ceph_x_decrypt(secret, p, end, dbuf, -+ TEMP_TICKET_BUF_LEN); -+ if (dlen <= 0) { -+ ret = dlen; -+ goto out; -+ } -+ dout(" decrypted %d bytes\n", dlen); -+ dp = dbuf; -+ dend = dp + dlen; -+ -+ tkt_struct_v = ceph_decode_8(&dp); -+ if (tkt_struct_v != 1) -+ goto bad; -+ -+ memcpy(&old_key, &th->session_key, sizeof(old_key)); -+ ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); -+ if (ret) -+ goto out; -+ -+ ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); -+ ceph_decode_timespec(&validity, &new_validity); -+ new_expires = get_seconds() + validity.tv_sec; -+ new_renew_after = new_expires - (validity.tv_sec / 4); -+ dout(" expires=%lu renew_after=%lu\n", new_expires, -+ new_renew_after); -+ -+ /* ticket blob for service */ -+ ceph_decode_8_safe(p, end, is_enc, bad); -+ tp = ticket_buf; -+ if (is_enc) { -+ /* encrypted */ -+ dout(" encrypted ticket\n"); -+ dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf, -+ TEMP_TICKET_BUF_LEN); -+ if (dlen < 0) { -+ ret = dlen; -+ goto out; -+ } -+ dlen = ceph_decode_32(&tp); -+ } else { -+ /* unencrypted */ -+ ceph_decode_32_safe(p, end, dlen, bad); -+ ceph_decode_need(p, end, dlen, bad); -+ ceph_decode_copy(p, ticket_buf, dlen); -+ } -+ tpend = tp + dlen; -+ dout(" ticket blob is %d bytes\n", dlen); -+ ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); -+ blob_struct_v = ceph_decode_8(&tp); -+ new_secret_id = ceph_decode_64(&tp); -+ ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); -+ if (ret) -+ goto out; -+ -+ /* all is well, update our ticket */ -+ ceph_crypto_key_destroy(&th->session_key); -+ if (th->ticket_blob) -+ ceph_buffer_put(th->ticket_blob); -+ th->session_key = new_session_key; -+ th->ticket_blob = new_ticket_blob; -+ th->validity = new_validity; -+ th->secret_id = new_secret_id; -+ th->expires = new_expires; -+ th->renew_after = new_renew_after; -+ dout(" got ticket service %d (%s) secret_id %lld len %d\n", -+ type, ceph_entity_type_name(type), th->secret_id, -+ (int)th->ticket_blob->vec.iov_len); -+ xi->have_keys |= th->service; -+ -+out: -+ return ret; -+ -+bad: -+ ret = -EINVAL; -+ goto out; -+} -+ - static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, - struct ceph_crypto_key *secret, - void *buf, void *end) - { -- struct ceph_x_info *xi = ac->private; -- int num; - void *p = buf; -- int ret; - char *dbuf; - char *ticket_buf; - u8 reply_struct_v; -+ u32 num; -+ int ret; - - dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); - if (!dbuf) -@@ -150,112 +264,18 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, - if (!ticket_buf) - goto out_dbuf; - -- ceph_decode_need(&p, end, 1 + sizeof(u32), bad); -- reply_struct_v = ceph_decode_8(&p); -+ ceph_decode_8_safe(&p, end, reply_struct_v, bad); - if (reply_struct_v != 1) -- goto bad; -- num = ceph_decode_32(&p); -- dout("%d tickets\n", num); -- while (num--) { -- int type; -- u8 tkt_struct_v, blob_struct_v; -- struct ceph_x_ticket_handler *th; -- void *dp, *dend; -- int dlen; -- char is_enc; -- struct timespec validity; -- struct ceph_crypto_key old_key; -- void *tp, *tpend; -- struct ceph_timespec new_validity; -- struct ceph_crypto_key new_session_key; -- struct ceph_buffer *new_ticket_blob; -- unsigned long new_expires, new_renew_after; -- u64 new_secret_id; -- -- ceph_decode_need(&p, end, sizeof(u32) + 1, bad); -- -- type = ceph_decode_32(&p); -- dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); -- -- tkt_struct_v = ceph_decode_8(&p); -- if (tkt_struct_v != 1) -- goto bad; -- -- th = get_ticket_handler(ac, type); -- if (IS_ERR(th)) { -- ret = PTR_ERR(th); -- goto out; -- } -- -- /* blob for me */ -- dlen = ceph_x_decrypt(secret, &p, end, dbuf, -- TEMP_TICKET_BUF_LEN); -- if (dlen <= 0) { -- ret = dlen; -- goto out; -- } -- dout(" decrypted %d bytes\n", dlen); -- dend = dbuf + dlen; -- dp = dbuf; -- -- tkt_struct_v = ceph_decode_8(&dp); -- if (tkt_struct_v != 1) -- goto bad; -+ return -EINVAL; - -- memcpy(&old_key, &th->session_key, sizeof(old_key)); -- ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); -- if (ret) -- goto out; -+ ceph_decode_32_safe(&p, end, num, bad); -+ dout("%d tickets\n", num); - -- ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); -- ceph_decode_timespec(&validity, &new_validity); -- new_expires = get_seconds() + validity.tv_sec; -- new_renew_after = new_expires - (validity.tv_sec / 4); -- dout(" expires=%lu renew_after=%lu\n", new_expires, -- new_renew_after); -- -- /* ticket blob for service */ -- ceph_decode_8_safe(&p, end, is_enc, bad); -- tp = ticket_buf; -- if (is_enc) { -- /* encrypted */ -- dout(" encrypted ticket\n"); -- dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf, -- TEMP_TICKET_BUF_LEN); -- if (dlen < 0) { -- ret = dlen; -- goto out; -- } -- dlen = ceph_decode_32(&tp); -- } else { -- /* unencrypted */ -- ceph_decode_32_safe(&p, end, dlen, bad); -- ceph_decode_need(&p, end, dlen, bad); -- ceph_decode_copy(&p, ticket_buf, dlen); -- } -- tpend = tp + dlen; -- dout(" ticket blob is %d bytes\n", dlen); -- ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); -- blob_struct_v = ceph_decode_8(&tp); -- new_secret_id = ceph_decode_64(&tp); -- ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); -+ while (num--) { -+ ret = process_one_ticket(ac, secret, &p, end, -+ dbuf, ticket_buf); - if (ret) - goto out; -- -- /* all is well, update our ticket */ -- ceph_crypto_key_destroy(&th->session_key); -- if (th->ticket_blob) -- ceph_buffer_put(th->ticket_blob); -- th->session_key = new_session_key; -- th->ticket_blob = new_ticket_blob; -- th->validity = new_validity; -- th->secret_id = new_secret_id; -- th->expires = new_expires; -- th->renew_after = new_renew_after; -- dout(" got ticket service %d (%s) secret_id %lld len %d\n", -- type, ceph_entity_type_name(type), th->secret_id, -- (int)th->ticket_blob->vec.iov_len); -- xi->have_keys |= th->service; - } - - ret = 0; diff --git a/debian/patches/bugfix/all/libceph-do-not-hard-code-max-auth-ticket-len.patch b/debian/patches/bugfix/all/libceph-do-not-hard-code-max-auth-ticket-len.patch deleted file mode 100644 index 2166f246b..000000000 --- a/debian/patches/bugfix/all/libceph-do-not-hard-code-max-auth-ticket-len.patch +++ /dev/null @@ -1,195 +0,0 @@ -From: Ilya Dryomov -Date: Tue, 9 Sep 2014 19:39:15 +0400 -Subject: libceph: do not hard code max auth ticket len -Origin: https://git.kernel.org/linus/c27a3e4d667fdcad3db7b104f75659478e0c68d8 - -We hard code cephx auth ticket buffer size to 256 bytes. This isn't -enough for any moderate setups and, in case tickets themselves are not -encrypted, leads to buffer overflows (ceph_x_decrypt() errors out, but -ceph_decode_copy() doesn't - it's just a memcpy() wrapper). Since the -buffer is allocated dynamically anyway, allocated it a bit later, at -the point where we know how much is going to be needed. - -Fixes: http://tracker.ceph.com/issues/8979 - -Cc: stable@vger.kernel.org -Signed-off-by: Ilya Dryomov -Reviewed-by: Sage Weil ---- - net/ceph/auth_x.c | 64 +++++++++++++++++++++++++------------------------------ - 1 file changed, 29 insertions(+), 35 deletions(-) - -diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c -index 0eb146d..de6662b 100644 ---- a/net/ceph/auth_x.c -+++ b/net/ceph/auth_x.c -@@ -13,8 +13,6 @@ - #include "auth_x.h" - #include "auth_x_protocol.h" - --#define TEMP_TICKET_BUF_LEN 256 -- - static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); - - static int ceph_x_is_authenticated(struct ceph_auth_client *ac) -@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, - } - - static int ceph_x_decrypt(struct ceph_crypto_key *secret, -- void **p, void *end, void *obuf, size_t olen) -+ void **p, void *end, void **obuf, size_t olen) - { - struct ceph_x_encrypt_header head; - size_t head_len = sizeof(head); -@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret, - return -EINVAL; - - dout("ceph_x_decrypt len %d\n", len); -- ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen, -- *p, len); -+ if (*obuf == NULL) { -+ *obuf = kmalloc(len, GFP_NOFS); -+ if (!*obuf) -+ return -ENOMEM; -+ olen = len; -+ } -+ -+ ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len); - if (ret) - return ret; - if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC) -@@ -131,18 +135,19 @@ static void remove_ticket_handler(struct ceph_auth_client *ac, - - static int process_one_ticket(struct ceph_auth_client *ac, - struct ceph_crypto_key *secret, -- void **p, void *end, -- void *dbuf, void *ticket_buf) -+ void **p, void *end) - { - struct ceph_x_info *xi = ac->private; - int type; - u8 tkt_struct_v, blob_struct_v; - struct ceph_x_ticket_handler *th; -+ void *dbuf = NULL; - void *dp, *dend; - int dlen; - char is_enc; - struct timespec validity; - struct ceph_crypto_key old_key; -+ void *ticket_buf = NULL; - void *tp, *tpend; - struct ceph_timespec new_validity; - struct ceph_crypto_key new_session_key; -@@ -167,8 +172,7 @@ static int process_one_ticket(struct ceph_auth_client *ac, - } - - /* blob for me */ -- dlen = ceph_x_decrypt(secret, p, end, dbuf, -- TEMP_TICKET_BUF_LEN); -+ dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0); - if (dlen <= 0) { - ret = dlen; - goto out; -@@ -195,20 +199,25 @@ static int process_one_ticket(struct ceph_auth_client *ac, - - /* ticket blob for service */ - ceph_decode_8_safe(p, end, is_enc, bad); -- tp = ticket_buf; - if (is_enc) { - /* encrypted */ - dout(" encrypted ticket\n"); -- dlen = ceph_x_decrypt(&old_key, p, end, ticket_buf, -- TEMP_TICKET_BUF_LEN); -+ dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0); - if (dlen < 0) { - ret = dlen; - goto out; - } -+ tp = ticket_buf; - dlen = ceph_decode_32(&tp); - } else { - /* unencrypted */ - ceph_decode_32_safe(p, end, dlen, bad); -+ ticket_buf = kmalloc(dlen, GFP_NOFS); -+ if (!ticket_buf) { -+ ret = -ENOMEM; -+ goto out; -+ } -+ tp = ticket_buf; - ceph_decode_need(p, end, dlen, bad); - ceph_decode_copy(p, ticket_buf, dlen); - } -@@ -237,6 +246,8 @@ static int process_one_ticket(struct ceph_auth_client *ac, - xi->have_keys |= th->service; - - out: -+ kfree(ticket_buf); -+ kfree(dbuf); - return ret; - - bad: -@@ -249,21 +260,10 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, - void *buf, void *end) - { - void *p = buf; -- char *dbuf; -- char *ticket_buf; - u8 reply_struct_v; - u32 num; - int ret; - -- dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); -- if (!dbuf) -- return -ENOMEM; -- -- ret = -ENOMEM; -- ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); -- if (!ticket_buf) -- goto out_dbuf; -- - ceph_decode_8_safe(&p, end, reply_struct_v, bad); - if (reply_struct_v != 1) - return -EINVAL; -@@ -272,22 +272,15 @@ static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, - dout("%d tickets\n", num); - - while (num--) { -- ret = process_one_ticket(ac, secret, &p, end, -- dbuf, ticket_buf); -+ ret = process_one_ticket(ac, secret, &p, end); - if (ret) -- goto out; -+ return ret; - } - -- ret = 0; --out: -- kfree(ticket_buf); --out_dbuf: -- kfree(dbuf); -- return ret; -+ return 0; - - bad: -- ret = -EINVAL; -- goto out; -+ return -EINVAL; - } - - static int ceph_x_build_authorizer(struct ceph_auth_client *ac, -@@ -603,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, - struct ceph_x_ticket_handler *th; - int ret = 0; - struct ceph_x_authorize_reply reply; -+ void *preply = &reply; - void *p = au->reply_buf; - void *end = p + sizeof(au->reply_buf); - - th = get_ticket_handler(ac, au->service); - if (IS_ERR(th)) - return PTR_ERR(th); -- ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply)); -+ ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply)); - if (ret < 0) - return ret; - if (ret != sizeof(reply)) diff --git a/debian/patches/bugfix/all/libceph-gracefully-handle-large-reply-messages-from-.patch b/debian/patches/bugfix/all/libceph-gracefully-handle-large-reply-messages-from-.patch deleted file mode 100644 index 1244951d2..000000000 --- a/debian/patches/bugfix/all/libceph-gracefully-handle-large-reply-messages-from-.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Sage Weil -Date: Mon, 4 Aug 2014 07:01:54 -0700 -Subject: libceph: gracefully handle large reply messages from the mon -Origin: https://git.kernel.org/linus/73c3d4812b4c755efeca0140f606f83772a39ce4 - -We preallocate a few of the message types we get back from the mon. If we -get a larger message than we are expecting, fall back to trying to allocate -a new one instead of blindly using the one we have. - -CC: stable@vger.kernel.org -Signed-off-by: Sage Weil -Reviewed-by: Ilya Dryomov ---- - net/ceph/mon_client.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c -index 067d3af..61fcfc3 100644 ---- a/net/ceph/mon_client.c -+++ b/net/ceph/mon_client.c -@@ -1181,7 +1181,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, - if (!m) { - pr_info("alloc_msg unknown type %d\n", type); - *skip = 1; -+ } else if (front_len > m->front_alloc_len) { -+ pr_warning("mon_alloc_msg front %d > prealloc %d (%u#%llu)\n", -+ front_len, m->front_alloc_len, -+ (unsigned int)con->peer_name.type, -+ le64_to_cpu(con->peer_name.num)); -+ ceph_msg_put(m); -+ m = ceph_msg_new(type, front_len, GFP_NOFS, false); - } -+ - return m; - } - diff --git a/debian/patches/bugfix/all/libceph-set-last_piece-in-ceph_msg_data_pages_cursor.patch b/debian/patches/bugfix/all/libceph-set-last_piece-in-ceph_msg_data_pages_cursor.patch deleted file mode 100644 index fda0fc14c..000000000 --- a/debian/patches/bugfix/all/libceph-set-last_piece-in-ceph_msg_data_pages_cursor.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: Ilya Dryomov -Date: Fri, 8 Aug 2014 12:43:39 +0400 -Subject: libceph: set last_piece in ceph_msg_data_pages_cursor_init() - correctly -Origin: https://git.kernel.org/linus/5f740d7e1531099b888410e6bab13f68da9b1a4d - -Determining ->last_piece based on the value of ->page_offset + length -is incorrect because length here is the length of the entire message. -->last_piece set to false even if page array data item length is <= -PAGE_SIZE, which results in invalid length passed to -ceph_tcp_{send,recv}page() and causes various asserts to fire. - - # cat pages-cursor-init.sh - #!/bin/bash - rbd create --size 10 --image-format 2 foo - FOO_DEV=$(rbd map foo) - dd if=/dev/urandom of=$FOO_DEV bs=1M &>/dev/null - rbd snap create foo@snap - rbd snap protect foo@snap - rbd clone foo@snap bar - # rbd_resize calls librbd rbd_resize(), size is in bytes - ./rbd_resize bar $(((4 << 20) + 512)) - rbd resize --size 10 bar - BAR_DEV=$(rbd map bar) - # trigger a 512-byte copyup -- 512-byte page array data item - dd if=/dev/urandom of=$BAR_DEV bs=1M count=1 seek=5 - -The problem exists only in ceph_msg_data_pages_cursor_init(), -ceph_msg_data_pages_advance() does the right thing. The size_t cast is -unnecessary. - -Cc: stable@vger.kernel.org # 3.10+ -Signed-off-by: Ilya Dryomov -Reviewed-by: Sage Weil -Reviewed-by: Alex Elder ---- - net/ceph/messenger.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/net/ceph/messenger.c -+++ b/net/ceph/messenger.c -@@ -900,7 +900,7 @@ static void ceph_msg_data_pages_cursor_i - BUG_ON(page_count > (int)USHRT_MAX); - cursor->page_count = (unsigned short)page_count; - BUG_ON(length > SIZE_MAX - cursor->page_offset); -- cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE; -+ cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE; - } - - static struct page * diff --git a/debian/patches/bugfix/all/mnt-Add-tests-for-unprivileged-remount-cases-that-ha.patch b/debian/patches/bugfix/all/mnt-Add-tests-for-unprivileged-remount-cases-that-ha.patch deleted file mode 100644 index e4460e8d6..000000000 --- a/debian/patches/bugfix/all/mnt-Add-tests-for-unprivileged-remount-cases-that-ha.patch +++ /dev/null @@ -1,315 +0,0 @@ -From: "Eric W. Biederman" -Date: Tue, 29 Jul 2014 15:50:44 -0700 -Subject: [5/5] mnt: Add tests for unprivileged remount cases that have found - to be faulty -Origin: https://git.kernel.org/linus/db181ce011e3c033328608299cd6fac06ea50130 - -Kenton Varda discovered that by remounting a -read-only bind mount read-only in a user namespace the -MNT_LOCK_READONLY bit would be cleared, allowing an unprivileged user -to the remount a read-only mount read-write. - -Upon review of the code in remount it was discovered that the code allowed -nosuid, noexec, and nodev to be cleared. It was also discovered that -the code was allowing the per mount atime flags to be changed. - -The first naive patch to fix these issues contained the flaw that using -default atime settings when remounting a filesystem could be disallowed. - -To avoid this problems in the future add tests to ensure unprivileged -remounts are succeeding and failing at the appropriate times. - -Cc: stable@vger.kernel.org -Acked-by: Serge E. Hallyn -Signed-off-by: "Eric W. Biederman" ---- - tools/testing/selftests/Makefile | 1 + - tools/testing/selftests/mount/Makefile | 17 ++ - .../selftests/mount/unprivileged-remount-test.c | 242 +++++++++++++++++++++ - 3 files changed, 260 insertions(+) - create mode 100644 tools/testing/selftests/mount/Makefile - create mode 100644 tools/testing/selftests/mount/unprivileged-remount-test.c - -diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile -index e66e710..0a8a9db 100644 ---- a/tools/testing/selftests/Makefile -+++ b/tools/testing/selftests/Makefile -@@ -4,6 +4,7 @@ TARGETS += efivarfs - TARGETS += kcmp - TARGETS += memory-hotplug - TARGETS += mqueue -+TARGETS += mount - TARGETS += net - TARGETS += ptrace - TARGETS += timers -diff --git a/tools/testing/selftests/mount/Makefile b/tools/testing/selftests/mount/Makefile -new file mode 100644 -index 0000000..337d853 ---- /dev/null -+++ b/tools/testing/selftests/mount/Makefile -@@ -0,0 +1,17 @@ -+# Makefile for mount selftests. -+ -+all: unprivileged-remount-test -+ -+unprivileged-remount-test: unprivileged-remount-test.c -+ gcc -Wall -O2 unprivileged-remount-test.c -o unprivileged-remount-test -+ -+# Allow specific tests to be selected. -+test_unprivileged_remount: unprivileged-remount-test -+ @if [ -f /proc/self/uid_map ] ; then ./unprivileged-remount-test ; fi -+ -+run_tests: all test_unprivileged_remount -+ -+clean: -+ rm -f unprivileged-remount-test -+ -+.PHONY: all test_unprivileged_remount -diff --git a/tools/testing/selftests/mount/unprivileged-remount-test.c b/tools/testing/selftests/mount/unprivileged-remount-test.c -new file mode 100644 -index 0000000..1b3ff2f ---- /dev/null -+++ b/tools/testing/selftests/mount/unprivileged-remount-test.c -@@ -0,0 +1,242 @@ -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef CLONE_NEWNS -+# define CLONE_NEWNS 0x00020000 -+#endif -+#ifndef CLONE_NEWUTS -+# define CLONE_NEWUTS 0x04000000 -+#endif -+#ifndef CLONE_NEWIPC -+# define CLONE_NEWIPC 0x08000000 -+#endif -+#ifndef CLONE_NEWNET -+# define CLONE_NEWNET 0x40000000 -+#endif -+#ifndef CLONE_NEWUSER -+# define CLONE_NEWUSER 0x10000000 -+#endif -+#ifndef CLONE_NEWPID -+# define CLONE_NEWPID 0x20000000 -+#endif -+ -+#ifndef MS_RELATIME -+#define MS_RELATIME (1 << 21) -+#endif -+#ifndef MS_STRICTATIME -+#define MS_STRICTATIME (1 << 24) -+#endif -+ -+static void die(char *fmt, ...) -+{ -+ va_list ap; -+ va_start(ap, fmt); -+ vfprintf(stderr, fmt, ap); -+ va_end(ap); -+ exit(EXIT_FAILURE); -+} -+ -+static void write_file(char *filename, char *fmt, ...) -+{ -+ char buf[4096]; -+ int fd; -+ ssize_t written; -+ int buf_len; -+ va_list ap; -+ -+ va_start(ap, fmt); -+ buf_len = vsnprintf(buf, sizeof(buf), fmt, ap); -+ va_end(ap); -+ if (buf_len < 0) { -+ die("vsnprintf failed: %s\n", -+ strerror(errno)); -+ } -+ if (buf_len >= sizeof(buf)) { -+ die("vsnprintf output truncated\n"); -+ } -+ -+ fd = open(filename, O_WRONLY); -+ if (fd < 0) { -+ die("open of %s failed: %s\n", -+ filename, strerror(errno)); -+ } -+ written = write(fd, buf, buf_len); -+ if (written != buf_len) { -+ if (written >= 0) { -+ die("short write to %s\n", filename); -+ } else { -+ die("write to %s failed: %s\n", -+ filename, strerror(errno)); -+ } -+ } -+ if (close(fd) != 0) { -+ die("close of %s failed: %s\n", -+ filename, strerror(errno)); -+ } -+} -+ -+static void create_and_enter_userns(void) -+{ -+ uid_t uid; -+ gid_t gid; -+ -+ uid = getuid(); -+ gid = getgid(); -+ -+ if (unshare(CLONE_NEWUSER) !=0) { -+ die("unshare(CLONE_NEWUSER) failed: %s\n", -+ strerror(errno)); -+ } -+ -+ write_file("/proc/self/uid_map", "0 %d 1", uid); -+ write_file("/proc/self/gid_map", "0 %d 1", gid); -+ -+ if (setgroups(0, NULL) != 0) { -+ die("setgroups failed: %s\n", -+ strerror(errno)); -+ } -+ if (setgid(0) != 0) { -+ die ("setgid(0) failed %s\n", -+ strerror(errno)); -+ } -+ if (setuid(0) != 0) { -+ die("setuid(0) failed %s\n", -+ strerror(errno)); -+ } -+} -+ -+static -+bool test_unpriv_remount(int mount_flags, int remount_flags, int invalid_flags) -+{ -+ pid_t child; -+ -+ child = fork(); -+ if (child == -1) { -+ die("fork failed: %s\n", -+ strerror(errno)); -+ } -+ if (child != 0) { /* parent */ -+ pid_t pid; -+ int status; -+ pid = waitpid(child, &status, 0); -+ if (pid == -1) { -+ die("waitpid failed: %s\n", -+ strerror(errno)); -+ } -+ if (pid != child) { -+ die("waited for %d got %d\n", -+ child, pid); -+ } -+ if (!WIFEXITED(status)) { -+ die("child did not terminate cleanly\n"); -+ } -+ return WEXITSTATUS(status) == EXIT_SUCCESS ? true : false; -+ } -+ -+ create_and_enter_userns(); -+ if (unshare(CLONE_NEWNS) != 0) { -+ die("unshare(CLONE_NEWNS) failed: %s\n", -+ strerror(errno)); -+ } -+ -+ if (mount("testing", "/tmp", "ramfs", mount_flags, NULL) != 0) { -+ die("mount of /tmp failed: %s\n", -+ strerror(errno)); -+ } -+ -+ create_and_enter_userns(); -+ -+ if (unshare(CLONE_NEWNS) != 0) { -+ die("unshare(CLONE_NEWNS) failed: %s\n", -+ strerror(errno)); -+ } -+ -+ if (mount("/tmp", "/tmp", "none", -+ MS_REMOUNT | MS_BIND | remount_flags, NULL) != 0) { -+ /* system("cat /proc/self/mounts"); */ -+ die("remount of /tmp failed: %s\n", -+ strerror(errno)); -+ } -+ -+ if (mount("/tmp", "/tmp", "none", -+ MS_REMOUNT | MS_BIND | invalid_flags, NULL) == 0) { -+ /* system("cat /proc/self/mounts"); */ -+ die("remount of /tmp with invalid flags " -+ "succeeded unexpectedly\n"); -+ } -+ exit(EXIT_SUCCESS); -+} -+ -+static bool test_unpriv_remount_simple(int mount_flags) -+{ -+ return test_unpriv_remount(mount_flags, mount_flags, 0); -+} -+ -+static bool test_unpriv_remount_atime(int mount_flags, int invalid_flags) -+{ -+ return test_unpriv_remount(mount_flags, mount_flags, invalid_flags); -+} -+ -+int main(int argc, char **argv) -+{ -+ if (!test_unpriv_remount_simple(MS_RDONLY|MS_NODEV)) { -+ die("MS_RDONLY malfunctions\n"); -+ } -+ if (!test_unpriv_remount_simple(MS_NODEV)) { -+ die("MS_NODEV malfunctions\n"); -+ } -+ if (!test_unpriv_remount_simple(MS_NOSUID|MS_NODEV)) { -+ die("MS_NOSUID malfunctions\n"); -+ } -+ if (!test_unpriv_remount_simple(MS_NOEXEC|MS_NODEV)) { -+ die("MS_NOEXEC malfunctions\n"); -+ } -+ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODEV, -+ MS_NOATIME|MS_NODEV)) -+ { -+ die("MS_RELATIME malfunctions\n"); -+ } -+ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODEV, -+ MS_NOATIME|MS_NODEV)) -+ { -+ die("MS_STRICTATIME malfunctions\n"); -+ } -+ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODEV, -+ MS_STRICTATIME|MS_NODEV)) -+ { -+ die("MS_RELATIME malfunctions\n"); -+ } -+ if (!test_unpriv_remount_atime(MS_RELATIME|MS_NODIRATIME|MS_NODEV, -+ MS_NOATIME|MS_NODEV)) -+ { -+ die("MS_RELATIME malfunctions\n"); -+ } -+ if (!test_unpriv_remount_atime(MS_STRICTATIME|MS_NODIRATIME|MS_NODEV, -+ MS_NOATIME|MS_NODEV)) -+ { -+ die("MS_RELATIME malfunctions\n"); -+ } -+ if (!test_unpriv_remount_atime(MS_NOATIME|MS_NODIRATIME|MS_NODEV, -+ MS_STRICTATIME|MS_NODEV)) -+ { -+ die("MS_RELATIME malfunctions\n"); -+ } -+ if (!test_unpriv_remount(MS_STRICTATIME|MS_NODEV, MS_NODEV, -+ MS_NOATIME|MS_NODEV)) -+ { -+ die("Default atime malfunctions\n"); -+ } -+ return EXIT_SUCCESS; -+} diff --git a/debian/patches/bugfix/all/mnt-Change-the-default-remount-atime-from-relatime-t.patch b/debian/patches/bugfix/all/mnt-Change-the-default-remount-atime-from-relatime-t.patch deleted file mode 100644 index be7082cab..000000000 --- a/debian/patches/bugfix/all/mnt-Change-the-default-remount-atime-from-relatime-t.patch +++ /dev/null @@ -1,53 +0,0 @@ -From: "Eric W. Biederman" -Date: Mon, 28 Jul 2014 17:36:04 -0700 -Subject: [4/5] mnt: Change the default remount atime from relatime to the - existing value -Origin: https://git.kernel.org/linus/ffbc6f0ead47fa5a1dc9642b0331cb75c20a640e - -Since March 2009 the kernel has treated the state that if no -MS_..ATIME flags are passed then the kernel defaults to relatime. - -Defaulting to relatime instead of the existing atime state during a -remount is silly, and causes problems in practice for people who don't -specify any MS_...ATIME flags and to get the default filesystem atime -setting. Those users may encounter a permission error because the -default atime setting does not work. - -A default that does not work and causes permission problems is -ridiculous, so preserve the existing value to have a default -atime setting that is always guaranteed to work. - -Using the default atime setting in this way is particularly -interesting for applications built to run in restricted userspace -environments without /proc mounted, as the existing atime mount -options of a filesystem can not be read from /proc/mounts. - -In practice this fixes user space that uses the default atime -setting on remount that are broken by the permission checks -keeping less privileged users from changing more privileged users -atime settings. - -Cc: stable@vger.kernel.org -Acked-by: Serge E. Hallyn -Signed-off-by: "Eric W. Biederman" ---- - fs/namespace.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -2475,6 +2475,14 @@ long do_mount(const char *dev_name, cons - if (flags & MS_RDONLY) - mnt_flags |= MNT_READONLY; - -+ /* The default atime for remount is preservation */ -+ if ((flags & MS_REMOUNT) && -+ ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME | -+ MS_STRICTATIME)) == 0)) { -+ mnt_flags &= ~MNT_ATIME_MASK; -+ mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK; -+ } -+ - flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | - MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | - MS_STRICTATIME); diff --git a/debian/patches/bugfix/all/mnt-Correct-permission-checks-in-do_remount.patch b/debian/patches/bugfix/all/mnt-Correct-permission-checks-in-do_remount.patch deleted file mode 100644 index 88be03a5a..000000000 --- a/debian/patches/bugfix/all/mnt-Correct-permission-checks-in-do_remount.patch +++ /dev/null @@ -1,125 +0,0 @@ -From: "Eric W. Biederman" -Date: Mon, 28 Jul 2014 17:26:07 -0700 -Subject: [3/5] mnt: Correct permission checks in do_remount -Origin: https://git.kernel.org/linus/9566d6742852c527bf5af38af5cbb878dad75705 - -While invesgiating the issue where in "mount --bind -oremount,ro ..." -would result in later "mount --bind -oremount,rw" succeeding even if -the mount started off locked I realized that there are several -additional mount flags that should be locked and are not. - -In particular MNT_NOSUID, MNT_NODEV, MNT_NOEXEC, and the atime -flags in addition to MNT_READONLY should all be locked. These -flags are all per superblock, can all be changed with MS_BIND, -and should not be changable if set by a more privileged user. - -The following additions to the current logic are added in this patch. -- nosuid may not be clearable by a less privileged user. -- nodev may not be clearable by a less privielged user. -- noexec may not be clearable by a less privileged user. -- atime flags may not be changeable by a less privileged user. - -The logic with atime is that always setting atime on access is a -global policy and backup software and auditing software could break if -atime bits are not updated (when they are configured to be updated), -and serious performance degradation could result (DOS attack) if atime -updates happen when they have been explicitly disabled. Therefore an -unprivileged user should not be able to mess with the atime bits set -by a more privileged user. - -The additional restrictions are implemented with the addition of -MNT_LOCK_NOSUID, MNT_LOCK_NODEV, MNT_LOCK_NOEXEC, and MNT_LOCK_ATIME -mnt flags. - -Taken together these changes and the fixes for MNT_LOCK_READONLY -should make it safe for an unprivileged user to create a user -namespace and to call "mount --bind -o remount,... ..." without -the danger of mount flags being changed maliciously. - -Cc: stable@vger.kernel.org -Acked-by: Serge E. Hallyn -Signed-off-by: "Eric W. Biederman" ---- - fs/namespace.c | 36 +++++++++++++++++++++++++++++++++--- - include/linux/mount.h | 5 +++++ - 2 files changed, 38 insertions(+), 3 deletions(-) - ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -891,8 +891,21 @@ static struct mount *clone_mnt(struct mo - - mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~(MNT_WRITE_HOLD|MNT_MARKED); - /* Don't allow unprivileged users to change mount flags */ -- if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY)) -- mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; -+ if (flag & CL_UNPRIVILEGED) { -+ mnt->mnt.mnt_flags |= MNT_LOCK_ATIME; -+ -+ if (mnt->mnt.mnt_flags & MNT_READONLY) -+ mnt->mnt.mnt_flags |= MNT_LOCK_READONLY; -+ -+ if (mnt->mnt.mnt_flags & MNT_NODEV) -+ mnt->mnt.mnt_flags |= MNT_LOCK_NODEV; -+ -+ if (mnt->mnt.mnt_flags & MNT_NOSUID) -+ mnt->mnt.mnt_flags |= MNT_LOCK_NOSUID; -+ -+ if (mnt->mnt.mnt_flags & MNT_NOEXEC) -+ mnt->mnt.mnt_flags |= MNT_LOCK_NOEXEC; -+ } - - /* Don't allow unprivileged users to reveal what is under a mount */ - if ((flag & CL_UNPRIVILEGED) && list_empty(&old->mnt_expire)) -@@ -1933,6 +1946,23 @@ static int do_remount(struct path *path, - !(mnt_flags & MNT_READONLY)) { - return -EPERM; - } -+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NODEV) && -+ !(mnt_flags & MNT_NODEV)) { -+ return -EPERM; -+ } -+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOSUID) && -+ !(mnt_flags & MNT_NOSUID)) { -+ return -EPERM; -+ } -+ if ((mnt->mnt.mnt_flags & MNT_LOCK_NOEXEC) && -+ !(mnt_flags & MNT_NOEXEC)) { -+ return -EPERM; -+ } -+ if ((mnt->mnt.mnt_flags & MNT_LOCK_ATIME) && -+ ((mnt->mnt.mnt_flags & MNT_ATIME_MASK) != (mnt_flags & MNT_ATIME_MASK))) { -+ return -EPERM; -+ } -+ - err = security_sb_remount(sb, data); - if (err) - return err; -@@ -2131,7 +2161,7 @@ static int do_new_mount(struct path *pat - */ - if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) { - flags |= MS_NODEV; -- mnt_flags |= MNT_NODEV; -+ mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV; - } - } - ---- a/include/linux/mount.h -+++ b/include/linux/mount.h -@@ -45,12 +45,17 @@ struct mnt_namespace; - #define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \ - | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \ - | MNT_READONLY) -+#define MNT_ATIME_MASK (MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME ) - - #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \ - MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED) - - #define MNT_INTERNAL 0x4000 - -+#define MNT_LOCK_ATIME 0x040000 -+#define MNT_LOCK_NOEXEC 0x080000 -+#define MNT_LOCK_NOSUID 0x100000 -+#define MNT_LOCK_NODEV 0x200000 - #define MNT_LOCK_READONLY 0x400000 - #define MNT_LOCKED 0x800000 - #define MNT_DOOMED 0x1000000 diff --git a/debian/patches/bugfix/all/mnt-Move-the-test-for-MNT_LOCK_READONLY-from-change_.patch b/debian/patches/bugfix/all/mnt-Move-the-test-for-MNT_LOCK_READONLY-from-change_.patch deleted file mode 100644 index c5f911701..000000000 --- a/debian/patches/bugfix/all/mnt-Move-the-test-for-MNT_LOCK_READONLY-from-change_.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: "Eric W. Biederman" -Date: Mon, 28 Jul 2014 17:10:56 -0700 -Subject: [2/5] mnt: Move the test for MNT_LOCK_READONLY from - change_mount_flags into do_remount -Origin: https://git.kernel.org/linus/07b645589dcda8b7a5249e096fece2a67556f0f4 - -There are no races as locked mount flags are guaranteed to never change. - -Moving the test into do_remount makes it more visible, and ensures all -filesystem remounts pass the MNT_LOCK_READONLY permission check. This -second case is not an issue today as filesystem remounts are guarded -by capable(CAP_DAC_ADMIN) and thus will always fail in less privileged -mount namespaces, but it could become an issue in the future. - -Cc: stable@vger.kernel.org -Acked-by: Serge E. Hallyn -Signed-off-by: "Eric W. Biederman" ---- - fs/namespace.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1898,9 +1898,6 @@ static int change_mount_flags(struct vfs - if (readonly_request == __mnt_is_readonly(mnt)) - return 0; - -- if (mnt->mnt_flags & MNT_LOCK_READONLY) -- return -EPERM; -- - if (readonly_request) - error = mnt_make_readonly(real_mount(mnt)); - else -@@ -1926,6 +1923,16 @@ static int do_remount(struct path *path, - if (path->dentry != path->mnt->mnt_root) - return -EINVAL; - -+ /* Don't allow changing of locked mnt flags. -+ * -+ * No locks need to be held here while testing the various -+ * MNT_LOCK flags because those flags can never be cleared -+ * once they are set. -+ */ -+ if ((mnt->mnt.mnt_flags & MNT_LOCK_READONLY) && -+ !(mnt_flags & MNT_READONLY)) { -+ return -EPERM; -+ } - err = security_sb_remount(sb, data); - if (err) - return err; diff --git a/debian/patches/bugfix/all/mnt-Only-change-user-settable-mount-flags-in-remount.patch b/debian/patches/bugfix/all/mnt-Only-change-user-settable-mount-flags-in-remount.patch deleted file mode 100644 index 87489f5c2..000000000 --- a/debian/patches/bugfix/all/mnt-Only-change-user-settable-mount-flags-in-remount.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: "Eric W. Biederman" -Date: Mon, 28 Jul 2014 16:26:53 -0700 -Subject: [1/5] mnt: Only change user settable mount flags in remount -Origin: https://git.kernel.org/linus/a6138db815df5ee542d848318e5dae681590fccd - -Kenton Varda discovered that by remounting a -read-only bind mount read-only in a user namespace the -MNT_LOCK_READONLY bit would be cleared, allowing an unprivileged user -to the remount a read-only mount read-write. - -Correct this by replacing the mask of mount flags to preserve -with a mask of mount flags that may be changed, and preserve -all others. This ensures that any future bugs with this mask and -remount will fail in an easy to detect way where new mount flags -simply won't change. - -Cc: stable@vger.kernel.org -Acked-by: Serge E. Hallyn -Signed-off-by: "Eric W. Biederman" ---- - fs/namespace.c | 2 +- - include/linux/mount.h | 4 +++- - 2 files changed, 4 insertions(+), 2 deletions(-) - ---- a/fs/namespace.c -+++ b/fs/namespace.c -@@ -1939,7 +1939,7 @@ static int do_remount(struct path *path, - err = do_remount_sb(sb, flags, data, 0); - if (!err) { - lock_mount_hash(); -- mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK; -+ mnt_flags |= mnt->mnt.mnt_flags & ~MNT_USER_SETTABLE_MASK; - mnt->mnt.mnt_flags = mnt_flags; - touch_mnt_namespace(mnt->mnt_ns); - unlock_mount_hash(); ---- a/include/linux/mount.h -+++ b/include/linux/mount.h -@@ -42,7 +42,9 @@ struct mnt_namespace; - * flag, consider how it interacts with shared mounts. - */ - #define MNT_SHARED_MASK (MNT_UNBINDABLE) --#define MNT_PROPAGATION_MASK (MNT_SHARED | MNT_UNBINDABLE) -+#define MNT_USER_SETTABLE_MASK (MNT_NOSUID | MNT_NODEV | MNT_NOEXEC \ -+ | MNT_NOATIME | MNT_NODIRATIME | MNT_RELATIME \ -+ | MNT_READONLY) - - #define MNT_INTERNAL_FLAGS (MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL | \ - MNT_DOOMED | MNT_SYNC_UMOUNT | MNT_MARKED) diff --git a/debian/patches/bugfix/mips/MIPS-O32-32-bit-Fix-bug-which-can-cause-incorrect-sy.patch b/debian/patches/bugfix/mips/MIPS-O32-32-bit-Fix-bug-which-can-cause-incorrect-sy.patch deleted file mode 100644 index 330613f1b..000000000 --- a/debian/patches/bugfix/mips/MIPS-O32-32-bit-Fix-bug-which-can-cause-incorrect-sy.patch +++ /dev/null @@ -1,61 +0,0 @@ -From: Alex Smith -Date: Wed, 23 Jul 2014 14:40:11 +0100 -Subject: MIPS: O32/32-bit: Fix bug which can cause incorrect system - call restarts -Origin: https://git.kernel.org/linus/e90e6fddc57055c4c6b57f92787fea1c065d440b - -On 32-bit/O32, pt_regs has a padding area at the beginning into which the -syscall arguments passed via the user stack are copied. 4 arguments -totalling 16 bytes are copied to offset 16 bytes into this area, however -the area is only 24 bytes long. This means the last 2 arguments overwrite -pt_regs->regs[{0,1}]. - -If a syscall function returns an error, handle_sys stores the original -syscall number in pt_regs->regs[0] for syscall restart. signal.c checks -whether regs[0] is non-zero, if it is it will check whether the syscall -return value is one of the ERESTART* codes to see if it must be -restarted. - -Should a syscall be made that results in a non-zero value being copied -off the user stack into regs[0], and then returns a positive (non-error) -value that matches one of the ERESTART* error codes, this can be mistaken -for requiring a syscall restart. - -While the possibility for this to occur has always existed, it is made -much more likely to occur by commit 46e12c07b3b9 ("MIPS: O32 / 32-bit: -Always copy 4 stack arguments."), since now every syscall will copy 4 -arguments and overwrite regs[0], rather than just those with 7 or 8 -arguments. - -Since that commit, booting Debian under a 32-bit MIPS kernel almost -always results in a hang early in boot, due to a wait4 syscall returning -a PID that matches one of the ERESTART* codes, which then causes an -incorrect restart of the syscall. - -The problem is fixed by increasing the size of the padding area so that -arguments copied off the stack will not overwrite pt_regs->regs[{0,1}]. - -Signed-off-by: Alex Smith -Cc: # v3.13+ -Tested-by: Aurelien Jarno -Reviewed-by: Aurelien Jarno ---- - arch/mips/include/asm/ptrace.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h -index 7e6e682..c301fa9 100644 ---- a/arch/mips/include/asm/ptrace.h -+++ b/arch/mips/include/asm/ptrace.h -@@ -23,7 +23,7 @@ - struct pt_regs { - #ifdef CONFIG_32BIT - /* Pad bytes for argument save space on the stack. */ -- unsigned long pad0[6]; -+ unsigned long pad0[8]; - #endif - - /* Saved main processor registers. */ --- -1.7.10.4 - diff --git a/debian/patches/bugfix/mips/MIPS-OCTEON-make-get_system_type-thread-safe.patch b/debian/patches/bugfix/mips/MIPS-OCTEON-make-get_system_type-thread-safe.patch deleted file mode 100644 index ae6514660..000000000 --- a/debian/patches/bugfix/mips/MIPS-OCTEON-make-get_system_type-thread-safe.patch +++ /dev/null @@ -1,66 +0,0 @@ -From: Aaro Koskinen -Date: Tue, 22 Jul 2014 14:51:08 +0300 -Subject: MIPS: OCTEON: make get_system_type() thread-safe -Origin: https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/?id=726d129dfdc9622197a8c3f5947ce09c1a4c935e - -get_system_type() is not thread-safe on OCTEON. It uses static data, -also more dangerous issue is that it's calling cvmx_fuse_read_byte() -every time without any synchronization. Currently it's possible to get -processes stuck looping forever in kernel simply by launching multiple -readers of /proc/cpuinfo: - - (while true; do cat /proc/cpuinfo > /dev/null; done) & - (while true; do cat /proc/cpuinfo > /dev/null; done) & - ... - -Fix by initializing the system type string only once during the early -boot. - -Signed-off-by: Aaro Koskinen -Cc: stable@vger.kernel.org -Reviewed-by: Markos Chandras -Patchwork: http://patchwork.linux-mips.org/patch/7437/ -Signed-off-by: James Hogan ---- - arch/mips/cavium-octeon/setup.c | 18 +++++++++++++----- - 1 file changed, 13 insertions(+), 5 deletions(-) - -diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c -index 008e9c8..c9d9c62 100644 ---- a/arch/mips/cavium-octeon/setup.c -+++ b/arch/mips/cavium-octeon/setup.c -@@ -458,6 +458,18 @@ static void octeon_halt(void) - octeon_kill_core(NULL); - } - -+static char __read_mostly octeon_system_type[80]; -+ -+static int __init init_octeon_system_type(void) -+{ -+ snprintf(octeon_system_type, sizeof(octeon_system_type), "%s (%s)", -+ cvmx_board_type_to_string(octeon_bootinfo->board_type), -+ octeon_model_get_string(read_c0_prid())); -+ -+ return 0; -+} -+early_initcall(init_octeon_system_type); -+ - /** - * Return a string representing the system type - * -@@ -465,11 +477,7 @@ static void octeon_halt(void) - */ - const char *octeon_board_type_string(void) - { -- static char name[80]; -- sprintf(name, "%s (%s)", -- cvmx_board_type_to_string(octeon_bootinfo->board_type), -- octeon_model_get_string(read_c0_prid())); -- return name; -+ return octeon_system_type; - } - - const char *get_system_type(void) --- -1.7.10.4 - diff --git a/debian/patches/bugfix/mips/MIPS-Remove-BUG_ON-is_fpu_owner-in-do_ade.patch b/debian/patches/bugfix/mips/MIPS-Remove-BUG_ON-is_fpu_owner-in-do_ade.patch deleted file mode 100644 index fbb0a3e0b..000000000 --- a/debian/patches/bugfix/mips/MIPS-Remove-BUG_ON-is_fpu_owner-in-do_ade.patch +++ /dev/null @@ -1,63 +0,0 @@ -From: Huacai Chen -Date: Wed, 16 Jul 2014 09:19:16 +0800 -Subject: MIPS: Remove BUG_ON(!is_fpu_owner()) in do_ade() -Origin: https://git.kernel.org/linus/2e5767a27337812f6850b3fa362419e2f085e5c3 - -In do_ade(), is_fpu_owner() isn't preempt-safe. For example, when an -unaligned ldc1 is executed, do_cpu() is called and then FPU will be -enabled (and TIF_USEDFPU will be set for the current process). Then, -do_ade() is called because the access is unaligned. If the current -process is preempted at this time, TIF_USEDFPU will be cleard. So when -the process is scheduled again, BUG_ON(!is_fpu_owner()) is triggered. - -This small program can trigger this BUG in a preemptible kernel: - -int main (int argc, char *argv[]) -{ - double u64[2]; - - while (1) { - asm volatile ( - ".set push \n\t" - ".set noreorder \n\t" - "ldc1 $f3, 4(%0) \n\t" - ".set pop \n\t" - ::"r"(u64): - ); - } - - return 0; -} - -V2: Remove the BUG_ON() unconditionally due to Paul's suggestion. - -Signed-off-by: Huacai Chen -Signed-off-by: Jie Chen -Signed-off-by: Rui Wang -Cc: -Cc: John Crispin -Cc: Steven J. Hill -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Cc: stable@vger.kernel.org -Signed-off-by: Ralf Baechle ---- - arch/mips/kernel/unaligned.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c -index 2b35172..e11906d 100644 ---- a/arch/mips/kernel/unaligned.c -+++ b/arch/mips/kernel/unaligned.c -@@ -690,7 +690,6 @@ static void emulate_load_store_insn(struct pt_regs *regs, - case sdc1_op: - die_if_kernel("Unaligned FP access in kernel code", regs); - BUG_ON(!used_math()); -- BUG_ON(!is_fpu_owner()); - - lose_fpu(1); /* Save FPU state for the emulator. */ - res = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1, --- -1.7.10.4 - diff --git a/debian/patches/bugfix/mips/MIPS-prevent-user-from-setting-FCSR-cause-bits.patch b/debian/patches/bugfix/mips/MIPS-prevent-user-from-setting-FCSR-cause-bits.patch deleted file mode 100644 index bcff7aaa3..000000000 --- a/debian/patches/bugfix/mips/MIPS-prevent-user-from-setting-FCSR-cause-bits.patch +++ /dev/null @@ -1,50 +0,0 @@ -From: Paul Burton -Date: Tue, 22 Jul 2014 14:21:21 +0100 -Subject: MIPS: prevent user from setting FCSR cause bits -Origin: https://git.kernel.org/linus/b1442d39fac2fcfbe6a4814979020e993ca59c9e - -If one or more matching FCSR cause & enable bits are set in saved thread -context then when that context is restored the kernel will take an FP -exception. This is of course undesirable and considered an oops, leading -to the kernel writing a backtrace to the console and potentially -rebooting depending upon the configuration. Thus the kernel avoids this -situation by clearing the cause bits of the FCSR register when handling -FP exceptions and after emulating FP instructions. - -However the kernel does not prevent userland from setting arbitrary FCSR -cause & enable bits via ptrace, using either the PTRACE_POKEUSR or -PTRACE_SETFPREGS requests. This means userland can trivially cause the -kernel to oops on any system with an FPU. Prevent this from happening -by clearing the cause bits when writing to the saved FCSR context via -ptrace. - -This problem appears to exist at least back to the beginning of the git -era in the PTRACE_POKEUSR case. - -Signed-off-by: Paul Burton -Cc: stable@vger.kernel.org -Patchwork: http://patchwork.linux-mips.org/patch/7438/ -Signed-off-by: James Hogan ---- - arch/mips/kernel/ptrace.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/arch/mips/kernel/ptrace.c -+++ b/arch/mips/kernel/ptrace.c -@@ -151,6 +151,7 @@ int ptrace_setfpregs(struct task_struct - } - - __get_user(child->thread.fpu.fcr31, data + 64); -+ child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; - - /* FIR may not be written. */ - -@@ -565,7 +566,7 @@ long arch_ptrace(struct task_struct *chi - break; - #endif - case FPC_CSR: -- child->thread.fpu.fcr31 = data; -+ child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X; - break; - case DSP_BASE ... DSP_BASE + 5: { - dspreg_t *dregs; diff --git a/debian/patches/bugfix/mips/MIPS-tlbex-fix-a-missing-statement-for-HUGETLB.patch b/debian/patches/bugfix/mips/MIPS-tlbex-fix-a-missing-statement-for-HUGETLB.patch deleted file mode 100644 index c9225b6c1..000000000 --- a/debian/patches/bugfix/mips/MIPS-tlbex-fix-a-missing-statement-for-HUGETLB.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Huacai Chen -Date: Tue, 29 Jul 2014 14:54:40 +0800 -Subject: MIPS: tlbex: fix a missing statement for HUGETLB -Origin: https://git.kernel.org/linus/8393c524a25609a30129e4a8975cf3b91f6c16a5 - -In commit 2c8c53e28f1 (MIPS: Optimize TLB handlers for Octeon CPUs) -build_r4000_tlb_refill_handler() is modified. But it doesn't compatible -with the original code in HUGETLB case. Because there is a copy & paste -error and one line of code is missing. It is very easy to produce a bug -with LTP's hugemmap05 test. - -Signed-off-by: Huacai Chen -Signed-off-by: Binbin Zhou -Cc: -Tested-by: Aurelien Jarno -Reviewed-by: Aurelien Jarno ---- - arch/mips/mm/tlbex.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c -index e80e10b..343fe0f 100644 ---- a/arch/mips/mm/tlbex.c -+++ b/arch/mips/mm/tlbex.c -@@ -1299,6 +1299,7 @@ static void build_r4000_tlb_refill_handler(void) - } - #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT - uasm_l_tlb_huge_update(&l, p); -+ UASM_i_LW(&p, K0, 0, K1); - build_huge_update_entries(&p, htlb_info.huge_pte, K1); - build_huge_tlb_write_entry(&p, &l, &r, K0, tlb_random, - htlb_info.restore_scratch); --- -1.7.10.4 - diff --git a/debian/patches/bugfix/mips/disable-advansys.patch b/debian/patches/bugfix/mips/disable-advansys.patch index 1c01959eb..d49cc6d89 100644 --- a/debian/patches/bugfix/mips/disable-advansys.patch +++ b/debian/patches/bugfix/mips/disable-advansys.patch @@ -12,13 +12,16 @@ make[5]: *** [__modpost] Error 1 But report: http://www.mail-archive.com/linux-scsi@vger.kernel.org/msg12773.html ---- a/drivers/scsi/Kconfig 2007-12-27 19:16:18.000000000 +0000 -+++ b/drivers/scsi/Kconfig 2007-12-27 19:16:58.000000000 +0000 -@@ -523,6 +523,7 @@ +[bwh: Upstream finally accepted this was broken on ARM! But MIPS has + the same problem still.] + +--- a/drivers/scsi/Kconfig ++++ b/drivers/scsi/Kconfig +@@ -495,6 +495,7 @@ config SCSI_ADVANSYS tristate "AdvanSys SCSI support" - depends on SCSI && VIRT_TO_BUS + depends on SCSI && VIRT_TO_BUS && !ARM depends on ISA || EISA || PCI -+ depends on (!MIPS && !ARM) || BROKEN ++ depends on !MIPS || BROKEN help This is a driver for all SCSI host adapters manufactured by AdvanSys. It is documented in the kernel source in diff --git a/debian/patches/bugfix/s390/s390-3215-fix-hanging-console-issue.patch b/debian/patches/bugfix/s390/s390-3215-fix-hanging-console-issue.patch deleted file mode 100644 index b9e7f5435..000000000 --- a/debian/patches/bugfix/s390/s390-3215-fix-hanging-console-issue.patch +++ /dev/null @@ -1,69 +0,0 @@ -From: Martin Schwidefsky -Date: Tue, 15 Jul 2014 17:53:12 +0200 -Subject: s390/3215: fix hanging console issue -Origin: https://git.kernel.org/cgit/linux/kernel/git/s390/linux.git/commit?id=26d766c60f4ea08cd14f0f3435a6db3d6cc2ae96 -Bug-Debian: https://bugs.debian.org/747922 - -The ccw_device_start in raw3215_start_io can fail. raw3215_try_io -does not check if the request could be started and removes any -pending timer. This can leave the system in a hanging state. -Check for pending request after raw3215_start_io and start a -timer if necessary. - -Signed-off-by: Martin Schwidefsky ---- - drivers/s390/char/con3215.c | 32 +++++++++++++++++--------------- - 1 file changed, 17 insertions(+), 15 deletions(-) - -diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c -index 5af7f0b..a6d47e5 100644 ---- a/drivers/s390/char/con3215.c -+++ b/drivers/s390/char/con3215.c -@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data) - unsigned long flags; - - spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); -- if (raw->flags & RAW3215_TIMER_RUNS) { -- del_timer(&raw->timer); -- raw->flags &= ~RAW3215_TIMER_RUNS; -- if (!(raw->port.flags & ASYNC_SUSPENDED)) { -- raw3215_mk_write_req(raw); -- raw3215_start_io(raw); -+ raw->flags &= ~RAW3215_TIMER_RUNS; -+ if (!(raw->port.flags & ASYNC_SUSPENDED)) { -+ raw3215_mk_write_req(raw); -+ raw3215_start_io(raw); -+ if ((raw->queued_read || raw->queued_write) && -+ !(raw->flags & RAW3215_WORKING) && -+ !(raw->flags & RAW3215_TIMER_RUNS)) { -+ raw->timer.expires = RAW3215_TIMEOUT + jiffies; -+ add_timer(&raw->timer); -+ raw->flags |= RAW3215_TIMER_RUNS; - } - } - spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); -@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw) - (raw->flags & RAW3215_FLUSHING)) { - /* execute write requests bigger than minimum size */ - raw3215_start_io(raw); -- if (raw->flags & RAW3215_TIMER_RUNS) { -- del_timer(&raw->timer); -- raw->flags &= ~RAW3215_TIMER_RUNS; -- } -- } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { -- /* delay small writes */ -- raw->timer.expires = RAW3215_TIMEOUT + jiffies; -- add_timer(&raw->timer); -- raw->flags |= RAW3215_TIMER_RUNS; - } - } -+ if ((raw->queued_read || raw->queued_write) && -+ !(raw->flags & RAW3215_WORKING) && -+ !(raw->flags & RAW3215_TIMER_RUNS)) { -+ raw->timer.expires = RAW3215_TIMEOUT + jiffies; -+ add_timer(&raw->timer); -+ raw->flags |= RAW3215_TIMER_RUNS; -+ } - } - - /* diff --git a/debian/patches/debian/dfsg/files-1 b/debian/patches/debian/dfsg/files-1 index b63ec91a9..ee68e8ad6 100644 --- a/debian/patches/debian/dfsg/files-1 +++ b/debian/patches/debian/dfsg/files-1 @@ -18,11 +18,6 @@ rm drivers/net/appletalk/cops_ltdrv.h rm drivers/staging/ft1000/ft1000-pcmcia/boot.h rm drivers/staging/ft1000/ft1000-*/*.img -rm drivers/staging/keucr/init.h - -rm drivers/staging/wlags49_h2/ap_*.c -rm drivers/staging/wlags49_h2/sta_*.c - # These include apparently obfuscated code rm drivers/video/fbdev/nvidia/ rm drivers/video/fbdev/riva/ diff --git a/debian/patches/debian/ia64-hardcode-arch-script-output.patch b/debian/patches/debian/ia64-hardcode-arch-script-output.patch index 756e1a43e..7c3201300 100644 --- a/debian/patches/debian/ia64-hardcode-arch-script-output.patch +++ b/debian/patches/debian/ia64-hardcode-arch-script-output.patch @@ -21,11 +21,9 @@ Including the scripts in linux-kbuild will avoid this manual step altogether, and allow for the possibility of other archs to provide their own scripts in the future. -diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile -index e7cbaa0..c8af869 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile -@@ -30,16 +30,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 -mfixed-range=f12-f15,f32-f127 \ +@@ -30,16 +30,7 @@ cflags-y := -pipe $(EXTRA) -ffixed-r13 - -falign-functions=32 -frename-registers -fno-optimize-sibling-calls KBUILD_CFLAGS_KERNEL := -mconstant-gp @@ -43,7 +41,7 @@ index e7cbaa0..c8af869 100644 KBUILD_CFLAGS += $(cflags-y) head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o -@@ -69,7 +60,7 @@ boot := arch/ia64/hp/sim/boot +@@ -66,7 +57,7 @@ boot := arch/ia64/hp/sim/boot PHONY += boot compressed check @@ -52,17 +50,17 @@ index e7cbaa0..c8af869 100644 compressed: vmlinux.gz -@@ -78,9 +69,6 @@ vmlinuz: vmlinux.gz +@@ -75,9 +66,6 @@ vmlinuz: vmlinux.gz vmlinux.gz: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ -unwcheck: vmlinux -- -$(Q)READELF=$(READELF) python $(srctree)/arch/ia64/scripts/unwcheck.py $< +- -$(Q)READELF=$(READELF) $(PYTHON) $(srctree)/arch/ia64/scripts/unwcheck.py $< - archclean: $(Q)$(MAKE) $(clean)=$(boot) -@@ -96,7 +84,6 @@ define archhelp +@@ -93,7 +81,6 @@ define archhelp echo '* compressed - Build compressed kernel image' echo ' install - Install compressed kernel image' echo ' boot - Build vmlinux and bootloader for Ski simulator' diff --git a/debian/patches/debian/revert-staging-sm7xxfb-remove-driver.patch b/debian/patches/debian/revert-staging-sm7xxfb-remove-driver.patch deleted file mode 100644 index 4dd832b79..000000000 --- a/debian/patches/debian/revert-staging-sm7xxfb-remove-driver.patch +++ /dev/null @@ -1,1906 +0,0 @@ -From db0cf7f2156da3cd1b6570f939f355eb20dca69b Mon Sep 17 00:00:00 2001 -From: Ben Hutchings -Date: Sun, 7 Sep 2014 20:31:52 +0100 -Subject: [PATCH] Revert "staging: sm7xxfb: remove driver" - -This reverts commit dc93c85235efa5201e9a3c116bc3fbd1afc1a182. -We're still attempting to support the Loongson 2F platform which -needs this. ---- - drivers/staging/Kconfig | 2 + - drivers/staging/Makefile | 1 + - drivers/staging/sm7xxfb/Kconfig | 13 + - drivers/staging/sm7xxfb/Makefile | 1 + - drivers/staging/sm7xxfb/TODO | 9 + - drivers/staging/sm7xxfb/sm7xx.h | 779 ++++++++++++++++++++++++++++ - drivers/staging/sm7xxfb/sm7xxfb.c | 1026 +++++++++++++++++++++++++++++++++++++ - 7 files changed, 1831 insertions(+) - create mode 100644 drivers/staging/sm7xxfb/Kconfig - create mode 100644 drivers/staging/sm7xxfb/Makefile - create mode 100644 drivers/staging/sm7xxfb/TODO - create mode 100644 drivers/staging/sm7xxfb/sm7xx.h - create mode 100644 drivers/staging/sm7xxfb/sm7xxfb.c - -diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig -index 4f38fc0..f57367c 100644 ---- a/drivers/staging/Kconfig -+++ b/drivers/staging/Kconfig -@@ -80,6 +80,8 @@ source "drivers/staging/wlags49_h2/Kconfig" - - source "drivers/staging/wlags49_h25/Kconfig" - -+source "drivers/staging/sm7xxfb/Kconfig" -+ - source "drivers/staging/crystalhd/Kconfig" - - source "drivers/staging/cxt1e1/Kconfig" -diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile -index 1e97ad2..65a1ff0 100644 ---- a/drivers/staging/Makefile -+++ b/drivers/staging/Makefile -@@ -34,6 +34,7 @@ obj-$(CONFIG_DX_SEP) += sep/ - obj-$(CONFIG_IIO) += iio/ - obj-$(CONFIG_WLAGS49_H2) += wlags49_h2/ - obj-$(CONFIG_WLAGS49_H25) += wlags49_h25/ -+obj-$(CONFIG_FB_SM7XX) += sm7xxfb/ - obj-$(CONFIG_CRYSTALHD) += crystalhd/ - obj-$(CONFIG_CXT1E1) += cxt1e1/ - obj-$(CONFIG_FB_XGI) += xgifb/ -diff --git a/drivers/staging/sm7xxfb/Kconfig b/drivers/staging/sm7xxfb/Kconfig -new file mode 100644 -index 0000000..e2922ae ---- /dev/null -+++ b/drivers/staging/sm7xxfb/Kconfig -@@ -0,0 +1,13 @@ -+config FB_SM7XX -+ tristate "Silicon Motion SM7XX framebuffer support" -+ depends on FB && PCI -+ select FB_CFB_FILLRECT -+ select FB_CFB_COPYAREA -+ select FB_CFB_IMAGEBLIT -+ help -+ Frame buffer driver for the Silicon Motion SM710, SM712, SM721 -+ and SM722 chips. -+ -+ This driver is also available as a module. The module will be -+ called sm7xxfb. If you want to compile it as a module, say M -+ here and read . -diff --git a/drivers/staging/sm7xxfb/Makefile b/drivers/staging/sm7xxfb/Makefile -new file mode 100644 -index 0000000..48f471c ---- /dev/null -+++ b/drivers/staging/sm7xxfb/Makefile -@@ -0,0 +1 @@ -+obj-$(CONFIG_FB_SM7XX) += sm7xxfb.o -diff --git a/drivers/staging/sm7xxfb/TODO b/drivers/staging/sm7xxfb/TODO -new file mode 100644 -index 0000000..1fcead5 ---- /dev/null -+++ b/drivers/staging/sm7xxfb/TODO -@@ -0,0 +1,9 @@ -+TODO: -+- Dual head support -+- 2D acceleration support -+- use kernel coding style -+- refine the code and remove unused code -+- move it to drivers/video/sm7xxfb.c -+ -+Please send any patches to Greg Kroah-Hartman and -+Teddy Wang . -diff --git a/drivers/staging/sm7xxfb/sm7xx.h b/drivers/staging/sm7xxfb/sm7xx.h -new file mode 100644 -index 0000000..8599861 ---- /dev/null -+++ b/drivers/staging/sm7xxfb/sm7xx.h -@@ -0,0 +1,779 @@ -+/* -+ * 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, wuzhangjin@gmail.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 NR_PALETTE 256 -+ -+#define FB_ACCEL_SMI_LYNX 88 -+ -+#define SCREEN_X_RES 1024 -+#define SCREEN_Y_RES 600 -+#define SCREEN_BPP 16 -+ -+/*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 void __iomem *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 ARRAY_SIZE(VGAMode) -diff --git a/drivers/staging/sm7xxfb/sm7xxfb.c b/drivers/staging/sm7xxfb/sm7xxfb.c -new file mode 100644 -index 0000000..c550b71 ---- /dev/null -+++ b/drivers/staging/sm7xxfb/sm7xxfb.c -@@ -0,0 +1,1026 @@ -+/* -+ * 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, wuzhangjin@gmail.com -+ * -+ * Copyright (C) 2011 Igalia, S.L. -+ * Author: Javier M. Mellid -+ * -+ * 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. -+ * -+ * Framebuffer driver for Silicon Motion SM710, SM712, SM721 and SM722 chips -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef CONFIG_PM -+#include -+#endif -+ -+#include "sm7xx.h" -+ -+/* -+* Private structure -+*/ -+struct smtcfb_info { -+ struct pci_dev *pdev; -+ struct fb_info fb; -+ u16 chip_id; -+ u8 chip_rev_id; -+ -+ void __iomem *lfb; /* linear frame buffer */ -+ void __iomem *dp_regs; /* drawing processor control regs */ -+ void __iomem *vp_regs; /* video processor control regs */ -+ void __iomem *cp_regs; /* capture processor control regs */ -+ void __iomem *mmio; /* memory map IO port */ -+ -+ u_int width; -+ u_int height; -+ u_int hz; -+ -+ u32 colreg[17]; -+}; -+ -+void __iomem *smtc_RegBaseAddress; /* Memory Map IO starting address */ -+ -+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, -+ .nonstd = 0, -+ .accel_flags = FB_ACCELF_TEXT, -+}; -+ -+static struct fb_fix_screeninfo smtcfb_fix = { -+ .id = "smXXXfb", -+ .type = FB_TYPE_PACKED_PIXELS, -+ .visual = FB_VISUAL_TRUECOLOR, -+ .line_length = 800 * 3, -+ .accel = FB_ACCEL_SMI_LYNX, -+ .type_aux = 0, -+ .xpanstep = 0, -+ .ypanstep = 0, -+ .ywrapstep = 0, -+}; -+ -+struct vesa_mode { -+ char index[6]; -+ u16 lfb_width; -+ u16 lfb_height; -+ u16 lfb_depth; -+}; -+ -+static struct vesa_mode vesa_mode_table[] = { -+ {"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}, -+}; -+ -+struct screen_info smtc_scr_info; -+ -+/* process command line options, get vga parameter */ -+static int __init sm7xx_vga_setup(char *options) -+{ -+ int i; -+ -+ if (!options || !*options) -+ return -EINVAL; -+ -+ smtc_scr_info.lfb_width = 0; -+ smtc_scr_info.lfb_height = 0; -+ smtc_scr_info.lfb_depth = 0; -+ -+ pr_debug("sm7xx_vga_setup = %s\n", options); -+ -+ for (i = 0; i < ARRAY_SIZE(vesa_mode_table); i++) { -+ if (strstr(options, vesa_mode_table[i].index)) { -+ smtc_scr_info.lfb_width = vesa_mode_table[i].lfb_width; -+ smtc_scr_info.lfb_height = -+ vesa_mode_table[i].lfb_height; -+ smtc_scr_info.lfb_depth = vesa_mode_table[i].lfb_depth; -+ return 0; -+ } -+ } -+ -+ return -1; -+} -+__setup("vga=", sm7xx_vga_setup); -+ -+static void sm712_setpalette(int regno, unsigned red, unsigned green, -+ unsigned blue, struct fb_info *info) -+{ -+ /* set bit 5:4 = 01 (write LCD RAM only) */ -+ 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); -+} -+ -+/* 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 smtc_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; -+ u32 val; -+ -+ sfb = info->par; -+ -+ if (regno > 255) -+ return 1; -+ -+ switch (sfb->fb.fix.visual) { -+ case FB_VISUAL_DIRECTCOLOR: -+ case FB_VISUAL_TRUECOLOR: -+ /* -+ * 16/32 bit true-colour, use pseudo-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 */ -+ -+static void sm7xx_set_timing(struct smtcfb_info *sfb) -+{ -+ int i = 0, j = 0; -+ u32 m_nScreenStride; -+ -+ dev_dbg(&sfb->pdev->dev, -+ "sfb->width=%d sfb->height=%d sfb->fb.var.bits_per_pixel=%d sfb->hz=%d\n", -+ sfb->width, sfb->height, sfb->fb.var.bits_per_pixel, sfb->hz); -+ -+ for (j = 0; j < numVGAModes; j++) { -+ if (VGAMode[j].mmSizeX == sfb->width && -+ VGAMode[j].mmSizeY == sfb->height && -+ VGAMode[j].bpp == sfb->fb.var.bits_per_pixel && -+ VGAMode[j].hz == sfb->hz) { -+ -+ dev_dbg(&sfb->pdev->dev, -+ "VGAMode[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); -+ -+ dev_dbg(&sfb->pdev->dev, "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, sfb->vp_regs + 0x0C); -+ writel(0x0, sfb->vp_regs + 0x40); -+ -+ /* set data width */ -+ m_nScreenStride = -+ (sfb->width * sfb->fb.var.bits_per_pixel) / 64; -+ switch (sfb->fb.var.bits_per_pixel) { -+ case 8: -+ writel(0x0, sfb->vp_regs + 0x0); -+ break; -+ case 16: -+ writel(0x00020000, sfb->vp_regs + 0x0); -+ break; -+ case 24: -+ writel(0x00040000, sfb->vp_regs + 0x0); -+ break; -+ case 32: -+ writel(0x00030000, sfb->vp_regs + 0x0); -+ break; -+ } -+ writel((u32) (((m_nScreenStride + 2) << 16) | m_nScreenStride), -+ sfb->vp_regs + 0x10); -+ -+} -+ -+static void smtc_set_timing(struct smtcfb_info *sfb) -+{ -+ switch (sfb->chip_id) { -+ case 0x710: -+ case 0x712: -+ case 0x720: -+ sm7xx_set_timing(sfb); -+ break; -+ } -+} -+ -+static 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 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 8: -+ sfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; -+ sfb->fb.fix.line_length = sfb->fb.var.xres; -+ sfb->fb.var.red.length = 3; -+ sfb->fb.var.green.length = 3; -+ sfb->fb.var.blue.length = 2; -+ sfb->fb.var.red.offset = 5; -+ sfb->fb.var.green.offset = 2; -+ 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; -+ } -+ -+ sfb->width = sfb->fb.var.xres; -+ sfb->height = sfb->fb.var.yres; -+ sfb->hz = 60; -+ smtc_set_timing(sfb); -+} -+ -+static int smtc_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -+{ -+ /* sanity checks */ -+ if (var->xres_virtual < var->xres) -+ var->xres_virtual = var->xres; -+ -+ if (var->yres_virtual < var->yres) -+ var->yres_virtual = var->yres; -+ -+ /* set valid default bpp */ -+ if ((var->bits_per_pixel != 8) && (var->bits_per_pixel != 16) && -+ (var->bits_per_pixel != 24) && (var->bits_per_pixel != 32)) -+ var->bits_per_pixel = 16; -+ -+ return 0; -+} -+ -+static int smtc_set_par(struct fb_info *info) -+{ -+ smtcfb_setmode(info->par); -+ -+ return 0; -+} -+ -+static struct fb_ops smtcfb_ops = { -+ .owner = THIS_MODULE, -+ .fb_check_var = smtc_check_var, -+ .fb_set_par = smtc_set_par, -+ .fb_setcolreg = smtc_setcolreg, -+ .fb_blank = smtc_blank, -+ .fb_fillrect = cfb_fillrect, -+ .fb_imageblit = cfb_imageblit, -+ .fb_copyarea = cfb_copyarea, -+#ifdef __BIG_ENDIAN -+ .fb_read = smtcfb_read, -+ .fb_write = smtcfb_write, -+#endif -+}; -+ -+/* -+ * alloc struct smtcfb_info and assign default values -+ */ -+static struct smtcfb_info *smtc_alloc_fb_info(struct pci_dev *pdev) -+{ -+ struct smtcfb_info *sfb; -+ -+ sfb = kzalloc(sizeof(*sfb), GFP_KERNEL); -+ -+ if (!sfb) -+ return NULL; -+ -+ sfb->pdev = pdev; -+ -+ sfb->fb.flags = FBINFO_FLAG_DEFAULT; -+ sfb->fb.fbops = &smtcfb_ops; -+ sfb->fb.fix = smtcfb_fix; -+ sfb->fb.var = smtcfb_var; -+ sfb->fb.pseudo_palette = sfb->colreg; -+ sfb->fb.par = sfb; -+ -+ return sfb; -+} -+ -+/* -+ * free struct smtcfb_info -+ */ -+static void smtc_free_fb_info(struct smtcfb_info *sfb) -+{ -+ kfree(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 *pdev, u_long smem_len) -+{ -+ -+ sfb->fb.fix.smem_start = pci_resource_start(pdev, 0); -+ -+#ifdef __BIG_ENDIAN -+ if (sfb->fb.var.bits_per_pixel == 32) -+ sfb->fb.fix.smem_start += 0x800000; -+#endif -+ -+ sfb->fb.fix.smem_len = smem_len; -+ -+ sfb->fb.screen_base = sfb->lfb; -+ -+ if (!sfb->fb.screen_base) { -+ dev_err(&pdev->dev, -+ "%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 device and make sure its in linear memory mode. -+ */ -+static inline void sm7xx_init_hw(void) -+{ -+ outb_p(0x18, 0x3c4); -+ outb_p(0x11, 0x3c5); -+} -+ -+static int smtcfb_pci_probe(struct pci_dev *pdev, -+ const struct pci_device_id *ent) -+{ -+ struct smtcfb_info *sfb; -+ u_long smem_size = 0x00800000; /* default 8MB */ -+ int err; -+ unsigned long mmio_base; -+ -+ dev_info(&pdev->dev, "Silicon Motion display driver."); -+ -+ err = pci_enable_device(pdev); /* enable SMTC chip */ -+ if (err) -+ return err; -+ -+ sprintf(smtcfb_fix.id, "sm%Xfb", ent->device); -+ -+ sfb = smtc_alloc_fb_info(pdev); -+ -+ if (!sfb) { -+ err = -ENOMEM; -+ goto failed_free; -+ } -+ -+ sfb->chip_id = ent->device; -+ -+ pci_set_drvdata(pdev, sfb); -+ -+ sm7xx_init_hw(); -+ -+ /* get mode parameter from smtc_scr_info */ -+ if (smtc_scr_info.lfb_width != 0) { -+ sfb->fb.var.xres = smtc_scr_info.lfb_width; -+ sfb->fb.var.yres = smtc_scr_info.lfb_height; -+ sfb->fb.var.bits_per_pixel = smtc_scr_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_scr_info.lfb_depth = 32); -+#endif -+ /* Map address and memory detection */ -+ mmio_base = pci_resource_start(pdev, 0); -+ pci_read_config_byte(pdev, PCI_REVISION_ID, &sfb->chip_rev_id); -+ -+ switch (sfb->chip_id) { -+ case 0x710: -+ case 0x712: -+ sfb->fb.fix.mmio_start = mmio_base + 0x00400000; -+ sfb->fb.fix.mmio_len = 0x00400000; -+ smem_size = SM712_VIDEOMEMORYSIZE; -+#ifdef __BIG_ENDIAN -+ sfb->lfb = ioremap(mmio_base, 0x00c00000); -+#else -+ sfb->lfb = ioremap(mmio_base, 0x00800000); -+#endif -+ sfb->mmio = (smtc_RegBaseAddress = -+ sfb->lfb + 0x00700000); -+ sfb->dp_regs = sfb->lfb + 0x00408000; -+ sfb->vp_regs = sfb->lfb + 0x0040c000; -+#ifdef __BIG_ENDIAN -+ if (sfb->fb.var.bits_per_pixel == 32) { -+ sfb->lfb += 0x800000; -+ dev_info(&pdev->dev, "sfb->lfb=%p", sfb->lfb); -+ } -+#endif -+ if (!smtc_RegBaseAddress) { -+ dev_err(&pdev->dev, -+ "%s: unable to map memory mapped IO!", -+ sfb->fb.fix.id); -+ err = -ENOMEM; -+ goto failed_fb; -+ } -+ -+ /* 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 -+ break; -+ case 0x720: -+ sfb->fb.fix.mmio_start = mmio_base; -+ sfb->fb.fix.mmio_len = 0x00200000; -+ smem_size = SM722_VIDEOMEMORYSIZE; -+ sfb->dp_regs = ioremap(mmio_base, 0x00a00000); -+ sfb->lfb = sfb->dp_regs + 0x00200000; -+ sfb->mmio = (smtc_RegBaseAddress = -+ sfb->dp_regs + 0x000c0000); -+ sfb->vp_regs = sfb->dp_regs + 0x800; -+ -+ smtc_seqw(0x62, 0xff); -+ smtc_seqw(0x6a, 0x0d); -+ smtc_seqw(0x6b, 0x02); -+ break; -+ default: -+ dev_err(&pdev->dev, -+ "No valid Silicon Motion display chip was detected!"); -+ -+ goto failed_fb; -+ } -+ -+ /* 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); -+ -+ err = register_framebuffer(&sfb->fb); -+ if (err < 0) -+ goto failed; -+ -+ dev_info(&pdev->dev, -+ "Silicon Motion SM%X Rev%X primary display mode %dx%d-%d Init Complete.", -+ sfb->chip_id, sfb->chip_rev_id, sfb->fb.var.xres, -+ sfb->fb.var.yres, sfb->fb.var.bits_per_pixel); -+ -+ return 0; -+ -+failed: -+ dev_err(&pdev->dev, "Silicon Motion, Inc. primary display init fail."); -+ -+ smtc_unmap_smem(sfb); -+ smtc_unmap_mmio(sfb); -+failed_fb: -+ smtc_free_fb_info(sfb); -+ -+failed_free: -+ pci_disable_device(pdev); -+ -+ return err; -+} -+ -+/* -+ * 0x710 (LynxEM) -+ * 0x712 (LynxEM+) -+ * 0x720 (Lynx3DM, Lynx3DM+) -+ */ -+static const struct pci_device_id smtcfb_pci_table[] = { -+ { PCI_DEVICE(0x126f, 0x710), }, -+ { PCI_DEVICE(0x126f, 0x712), }, -+ { PCI_DEVICE(0x126f, 0x720), }, -+ {0,} -+}; -+ -+static void smtcfb_pci_remove(struct pci_dev *pdev) -+{ -+ struct smtcfb_info *sfb; -+ -+ sfb = pci_get_drvdata(pdev); -+ smtc_unmap_smem(sfb); -+ smtc_unmap_mmio(sfb); -+ unregister_framebuffer(&sfb->fb); -+ smtc_free_fb_info(sfb); -+} -+ -+#ifdef CONFIG_PM -+static int smtcfb_pci_suspend(struct device *device) -+{ -+ struct pci_dev *pdev = to_pci_dev(device); -+ struct smtcfb_info *sfb; -+ -+ sfb = pci_get_drvdata(pdev); -+ -+ /* set the hw in sleep mode use external 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)); -+ -+ console_lock(); -+ fb_set_suspend(&sfb->fb, 1); -+ console_unlock(); -+ -+ /* additionally turn off all function blocks including internal PLLs */ -+ smtc_seqw(0x21, 0xff); -+ -+ return 0; -+} -+ -+static int smtcfb_pci_resume(struct device *device) -+{ -+ struct pci_dev *pdev = to_pci_dev(device); -+ struct smtcfb_info *sfb; -+ -+ sfb = pci_get_drvdata(pdev); -+ -+ /* reinit hardware */ -+ sm7xx_init_hw(); -+ switch (sfb->chip_id) { -+ 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); -+ -+ console_lock(); -+ fb_set_suspend(&sfb->fb, 0); -+ console_unlock(); -+ -+ return 0; -+} -+ -+static SIMPLE_DEV_PM_OPS(sm7xx_pm_ops, smtcfb_pci_suspend, smtcfb_pci_resume); -+#define SM7XX_PM_OPS (&sm7xx_pm_ops) -+ -+#else /* !CONFIG_PM */ -+ -+#define SM7XX_PM_OPS NULL -+ -+#endif /* !CONFIG_PM */ -+ -+static struct pci_driver smtcfb_driver = { -+ .name = "smtcfb", -+ .id_table = smtcfb_pci_table, -+ .probe = smtcfb_pci_probe, -+ .remove = smtcfb_pci_remove, -+ .driver.pm = SM7XX_PM_OPS, -+}; -+ -+module_pci_driver(smtcfb_driver); -+ -+MODULE_AUTHOR("Siliconmotion "); -+MODULE_DESCRIPTION("Framebuffer driver for SMI Graphic Cards"); -+MODULE_LICENSE("GPL"); diff --git a/debian/patches/debian/version.patch b/debian/patches/debian/version.patch index f8bb63774..c07b9aaeb 100644 --- a/debian/patches/debian/version.patch +++ b/debian/patches/debian/version.patch @@ -9,7 +9,7 @@ are set. --- a/Makefile +++ b/Makefile -@@ -826,7 +826,7 @@ endif +@@ -963,7 +963,7 @@ endif prepare2: prepare3 outputmakefile asm-generic prepare1: prepare2 $(version_h) include/generated/utsrelease.h \ @@ -18,7 +18,7 @@ are set. $(cmd_crmodverdir) archprepare: archheaders archscripts prepare1 scripts_basic -@@ -858,12 +858,25 @@ define filechk_version.h +@@ -995,12 +995,25 @@ define filechk_version.h echo '#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))';) endef @@ -54,7 +54,7 @@ are set. #include #include #include -@@ -16,8 +17,9 @@ void __show_regs(struct pt_regs *regs) +@@ -16,8 +17,9 @@ void show_regs(struct pt_regs *regs) { printk("\n"); print_modules(); @@ -90,7 +90,7 @@ are set. regs->ar_unat, regs->ar_pfs, regs->ar_rsc); --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c -@@ -38,6 +38,7 @@ +@@ -37,6 +37,7 @@ #include #include #include @@ -98,7 +98,7 @@ are set. #include #include -@@ -843,8 +844,9 @@ void show_regs(struct pt_regs * regs) +@@ -1004,8 +1005,9 @@ void show_regs(struct pt_regs * regs) printk("NIP: "REG" LR: "REG" CTR: "REG"\n", regs->nip, regs->link, regs->ctr); @@ -112,15 +112,15 @@ are set. printk(" CR: %08lx XER: %08lx\n", regs->ccr, regs->xer); --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c -@@ -45,6 +45,7 @@ - #include +@@ -46,6 +46,7 @@ #include #include + #include +#include #include -@@ -2871,11 +2872,12 @@ void __init dump_stack_set_arch_desc(con +@@ -3034,11 +3035,12 @@ void __init dump_stack_set_arch_desc(con */ void dump_stack_print_info(const char *log_lvl) { diff --git a/debian/patches/features/all/cgroups-Allow-memory-cgroup-support-to-be-included-b.patch b/debian/patches/features/all/cgroups-Allow-memory-cgroup-support-to-be-included-b.patch index 6b1ceb2fc..127598513 100644 --- a/debian/patches/features/all/cgroups-Allow-memory-cgroup-support-to-be-included-b.patch +++ b/debian/patches/features/all/cgroups-Allow-memory-cgroup-support-to-be-included-b.patch @@ -19,7 +19,7 @@ Signed-off-by: Ben Hutchings --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt -@@ -569,8 +569,8 @@ bytes respectively. Such letter suffixes +@@ -580,8 +580,8 @@ bytes respectively. Such letter suffixes ccw_timeout_log [S390] See Documentation/s390/CommonIO for details. @@ -32,7 +32,7 @@ Signed-off-by: Ben Hutchings a single hierarchy --- a/init/Kconfig +++ b/init/Kconfig -@@ -960,6 +960,14 @@ config MEMCG +@@ -1003,6 +1003,14 @@ config MEMCG disable memory resource controller and you can avoid overheads. (and lose benefits of memory resource controller) @@ -49,7 +49,7 @@ Signed-off-by: Ben Hutchings depends on MEMCG && SWAP --- a/kernel/cgroup.c +++ b/kernel/cgroup.c -@@ -5182,7 +5182,7 @@ static void cgroup_release_agent(struct +@@ -5359,7 +5359,7 @@ static void cgroup_release_agent(struct mutex_unlock(&cgroup_mutex); } @@ -58,7 +58,7 @@ Signed-off-by: Ben Hutchings { struct cgroup_subsys *ss; char *token; -@@ -5194,17 +5194,29 @@ static int __init cgroup_disable(char *s +@@ -5371,17 +5371,29 @@ static int __init cgroup_disable(char *s for_each_subsys(ss, i) { if (!strcmp(token, ss->name)) { @@ -88,12 +88,12 @@ Signed-off-by: Ben Hutchings +} +__setup("cgroup_enable=", cgroup_enable); + - /** - * css_tryget_online_from_dir - get corresponding css from a cgroup dentry - * @dentry: directory dentry of interest + static int __init cgroup_set_legacy_files_on_dfl(char *str) + { + printk("cgroup: using legacy files on the default hierarchy\n"); --- a/mm/memcontrol.c +++ b/mm/memcontrol.c -@@ -7015,6 +7015,9 @@ static void mem_cgroup_bind(struct cgrou +@@ -6297,6 +6297,9 @@ static void mem_cgroup_bind(struct cgrou } struct cgroup_subsys memory_cgrp_subsys = { diff --git a/debian/patches/features/all/efi-autoload-efivars.patch b/debian/patches/features/all/efi-autoload-efivars.patch index 758605e78..84b1a2dae 100644 --- a/debian/patches/features/all/efi-autoload-efivars.patch +++ b/debian/patches/features/all/efi-autoload-efivars.patch @@ -14,48 +14,8 @@ Instead, give them module aliases as if they are platform drivers, and register a corresponding platform device whenever EFI runtime services are available. This should trigger udev to load them. +[bwh: Most of this went upstream in 3.17-rc4, just not the efi-pstore bit.] --- ---- a/arch/x86/platform/efi/efi.c -+++ b/arch/x86/platform/efi/efi.c -@@ -42,6 +42,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -783,6 +784,20 @@ void __init efi_late_init(void) - efi_bgrt_init(); - } - -+#ifdef CONFIG_EFI_VARS_MODULE -+static int __init efi_load_efivars(void) -+{ -+ struct platform_device *pdev; -+ -+ if (!efi_enabled(EFI_RUNTIME_SERVICES)) -+ return 0; -+ -+ pdev = platform_device_register_simple("efivars", 0, NULL, 0); -+ return IS_ERR(pdev) ? PTR_ERR(pdev) : 0; -+} -+device_initcall(efi_load_efivars); -+#endif -+ - void __init efi_set_executable(efi_memory_desc_t *md, bool executable) - { - u64 addr, npages; ---- a/drivers/firmware/efi/efivars.c -+++ b/drivers/firmware/efi/efivars.c -@@ -77,6 +77,7 @@ MODULE_AUTHOR("Matt Domsch -Date: Sun, 6 Jul 2014 16:39:27 +0200 -Subject: virtio-scsi: Implement change_queue_depth for virtscsi targets -Origin: https://git.kernel.org/linus/761f1193f299873236dbc21277864d70cb7ba8a3 - -change_queue_depth allows changing per-target queue depth via sysfs. - -It also allows the SCSI midlayer to ramp down the number of concurrent -inflight requests in response to a SCSI BUSY status response and allows -the midlayer to ramp the count back up to the device maximum when the -BUSY condition has resolved. - -Signed-off-by: Venkatesh Srinivas -Signed-off-by: Paolo Bonzini -Signed-off-by: Christoph Hellwig -[bwh: Backported to 3.16: adjust context] ---- - drivers/scsi/virtio_scsi.c | 33 +++++++++++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - ---- a/drivers/scsi/virtio_scsi.c -+++ b/drivers/scsi/virtio_scsi.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #define VIRTIO_SCSI_MEMPOOL_SZ 64 - #define VIRTIO_SCSI_EVENT_LEN 8 -@@ -641,6 +642,36 @@ static int virtscsi_device_reset(struct - return virtscsi_tmf(vscsi, cmd); - } - -+/** -+ * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth -+ * @sdev: Virtscsi target whose queue depth to change -+ * @qdepth: New queue depth -+ * @reason: Reason for the queue depth change. -+ */ -+static int virtscsi_change_queue_depth(struct scsi_device *sdev, -+ int qdepth, -+ int reason) -+{ -+ struct Scsi_Host *shost = sdev->host; -+ int max_depth = shost->cmd_per_lun; -+ -+ switch (reason) { -+ case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */ -+ scsi_track_queue_full(sdev, qdepth); -+ break; -+ case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */ -+ case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */ -+ scsi_adjust_queue_depth(sdev, -+ scsi_get_tag_type(sdev), -+ min(max_depth, qdepth)); -+ break; -+ default: -+ return -EOPNOTSUPP; -+ } -+ -+ return sdev->queue_depth; -+} -+ - static int virtscsi_abort(struct scsi_cmnd *sc) - { - struct virtio_scsi *vscsi = shost_priv(sc->device->host); -@@ -693,6 +724,7 @@ static struct scsi_host_template virtscs - .this_id = -1, - .cmd_size = sizeof(struct virtio_scsi_cmd), - .queuecommand = virtscsi_queuecommand_single, -+ .change_queue_depth = virtscsi_change_queue_depth, - .eh_abort_handler = virtscsi_abort, - .eh_device_reset_handler = virtscsi_device_reset, - -@@ -710,6 +742,7 @@ static struct scsi_host_template virtscs - .this_id = -1, - .cmd_size = sizeof(struct virtio_scsi_cmd), - .queuecommand = virtscsi_queuecommand_multi, -+ .change_queue_depth = virtscsi_change_queue_depth, - .eh_abort_handler = virtscsi_abort, - .eh_device_reset_handler = virtscsi_device_reset, - diff --git a/debian/patches/features/arm64/drivers-net-Add-APM-X-Gene-SoC-ethernet-driver-suppo.patch b/debian/patches/features/arm64/drivers-net-Add-APM-X-Gene-SoC-ethernet-driver-suppo.patch deleted file mode 100644 index 4f4cf211e..000000000 --- a/debian/patches/features/arm64/drivers-net-Add-APM-X-Gene-SoC-ethernet-driver-suppo.patch +++ /dev/null @@ -1,2415 +0,0 @@ -From 6444ac4cf1506db36fb0ffb8d5c8b57cdb12adf7 Mon Sep 17 00:00:00 2001 -From: Iyappan Subramanian -Date: Thu, 7 Aug 2014 15:14:28 -0700 -Subject: [PATCH 1/4] drivers: net: Add APM X-Gene SoC ethernet driver - support. - -This patch adds network driver for APM X-Gene SoC ethernet. - -Signed-off-by: Iyappan Subramanian -Signed-off-by: Ravi Patel -Signed-off-by: Keyur Chudgar -Signed-off-by: Dean Nelson -Reviewed-by: Tobias Klauser -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/Kconfig | 1 + - drivers/net/ethernet/Makefile | 1 + - drivers/net/ethernet/apm/Kconfig | 1 + - drivers/net/ethernet/apm/Makefile | 5 + - drivers/net/ethernet/apm/xgene/Kconfig | 9 + - drivers/net/ethernet/apm/xgene/Makefile | 6 + - .../net/ethernet/apm/xgene/xgene_enet_ethtool.c | 125 +++ - drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 728 +++++++++++++++ - drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 337 +++++++ - drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 951 ++++++++++++++++++++ - drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 135 +++ - 11 files changed, 2299 insertions(+) - create mode 100644 drivers/net/ethernet/apm/Kconfig - create mode 100644 drivers/net/ethernet/apm/Makefile - create mode 100644 drivers/net/ethernet/apm/xgene/Kconfig - create mode 100644 drivers/net/ethernet/apm/xgene/Makefile - create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c - create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_hw.c - create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_hw.h - create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_main.c - create mode 100644 drivers/net/ethernet/apm/xgene/xgene_enet_main.h - -diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig -index edb7186..dc7406c 100644 ---- a/drivers/net/ethernet/Kconfig -+++ b/drivers/net/ethernet/Kconfig -@@ -24,6 +24,7 @@ source "drivers/net/ethernet/allwinner/Kconfig" - source "drivers/net/ethernet/alteon/Kconfig" - source "drivers/net/ethernet/altera/Kconfig" - source "drivers/net/ethernet/amd/Kconfig" -+source "drivers/net/ethernet/apm/Kconfig" - source "drivers/net/ethernet/apple/Kconfig" - source "drivers/net/ethernet/arc/Kconfig" - source "drivers/net/ethernet/atheros/Kconfig" -diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile -index 58de333..224a018 100644 ---- a/drivers/net/ethernet/Makefile -+++ b/drivers/net/ethernet/Makefile -@@ -10,6 +10,7 @@ obj-$(CONFIG_NET_VENDOR_ALLWINNER) += allwinner/ - obj-$(CONFIG_NET_VENDOR_ALTEON) += alteon/ - obj-$(CONFIG_ALTERA_TSE) += altera/ - obj-$(CONFIG_NET_VENDOR_AMD) += amd/ -+obj-$(CONFIG_NET_XGENE) += apm/ - obj-$(CONFIG_NET_VENDOR_APPLE) += apple/ - obj-$(CONFIG_NET_VENDOR_ARC) += arc/ - obj-$(CONFIG_NET_VENDOR_ATHEROS) += atheros/ -diff --git a/drivers/net/ethernet/apm/Kconfig b/drivers/net/ethernet/apm/Kconfig -new file mode 100644 -index 0000000..ec63d70 ---- /dev/null -+++ b/drivers/net/ethernet/apm/Kconfig -@@ -0,0 +1 @@ -+source "drivers/net/ethernet/apm/xgene/Kconfig" -diff --git a/drivers/net/ethernet/apm/Makefile b/drivers/net/ethernet/apm/Makefile -new file mode 100644 -index 0000000..65ce32a ---- /dev/null -+++ b/drivers/net/ethernet/apm/Makefile -@@ -0,0 +1,5 @@ -+# -+# Makefile for APM X-GENE Ethernet driver. -+# -+ -+obj-$(CONFIG_NET_XGENE) += xgene/ -diff --git a/drivers/net/ethernet/apm/xgene/Kconfig b/drivers/net/ethernet/apm/xgene/Kconfig -new file mode 100644 -index 0000000..616dff6 ---- /dev/null -+++ b/drivers/net/ethernet/apm/xgene/Kconfig -@@ -0,0 +1,9 @@ -+config NET_XGENE -+ tristate "APM X-Gene SoC Ethernet Driver" -+ select PHYLIB -+ help -+ This is the Ethernet driver for the on-chip ethernet interface on the -+ APM X-Gene SoC. -+ -+ To compile this driver as a module, choose M here. This module will -+ be called xgene_enet. -diff --git a/drivers/net/ethernet/apm/xgene/Makefile b/drivers/net/ethernet/apm/xgene/Makefile -new file mode 100644 -index 0000000..c643e8a ---- /dev/null -+++ b/drivers/net/ethernet/apm/xgene/Makefile -@@ -0,0 +1,6 @@ -+# -+# Makefile for APM X-Gene Ethernet Driver. -+# -+ -+xgene-enet-objs := xgene_enet_hw.o xgene_enet_main.o xgene_enet_ethtool.o -+obj-$(CONFIG_NET_XGENE) += xgene-enet.o -diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c -new file mode 100644 -index 0000000..63f2aa5 ---- /dev/null -+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c -@@ -0,0 +1,125 @@ -+/* Applied Micro X-Gene SoC Ethernet Driver -+ * -+ * Copyright (c) 2014, Applied Micro Circuits Corporation -+ * Authors: Iyappan Subramanian -+ * -+ * 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, see . -+ */ -+ -+#include -+#include "xgene_enet_main.h" -+ -+struct xgene_gstrings_stats { -+ char name[ETH_GSTRING_LEN]; -+ int offset; -+}; -+ -+#define XGENE_STAT(m) { #m, offsetof(struct xgene_enet_pdata, stats.m) } -+ -+static const struct xgene_gstrings_stats gstrings_stats[] = { -+ XGENE_STAT(rx_packets), -+ XGENE_STAT(tx_packets), -+ XGENE_STAT(rx_bytes), -+ XGENE_STAT(tx_bytes), -+ XGENE_STAT(rx_errors), -+ XGENE_STAT(tx_errors), -+ XGENE_STAT(rx_length_errors), -+ XGENE_STAT(rx_crc_errors), -+ XGENE_STAT(rx_frame_errors), -+ XGENE_STAT(rx_fifo_errors) -+}; -+ -+#define XGENE_STATS_LEN ARRAY_SIZE(gstrings_stats) -+ -+static void xgene_get_drvinfo(struct net_device *ndev, -+ struct ethtool_drvinfo *info) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct platform_device *pdev = pdata->pdev; -+ -+ strcpy(info->driver, "xgene_enet"); -+ strcpy(info->version, XGENE_DRV_VERSION); -+ snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A"); -+ sprintf(info->bus_info, "%s", pdev->name); -+} -+ -+static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct phy_device *phydev = pdata->phy_dev; -+ -+ if (phydev == NULL) -+ return -ENODEV; -+ -+ return phy_ethtool_gset(phydev, cmd); -+} -+ -+static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct phy_device *phydev = pdata->phy_dev; -+ -+ if (phydev == NULL) -+ return -ENODEV; -+ -+ return phy_ethtool_sset(phydev, cmd); -+} -+ -+static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data) -+{ -+ int i; -+ u8 *p = data; -+ -+ if (stringset != ETH_SS_STATS) -+ return; -+ -+ for (i = 0; i < XGENE_STATS_LEN; i++) { -+ memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN); -+ p += ETH_GSTRING_LEN; -+ } -+} -+ -+static int xgene_get_sset_count(struct net_device *ndev, int sset) -+{ -+ if (sset != ETH_SS_STATS) -+ return -EINVAL; -+ -+ return XGENE_STATS_LEN; -+} -+ -+static void xgene_get_ethtool_stats(struct net_device *ndev, -+ struct ethtool_stats *dummy, -+ u64 *data) -+{ -+ void *pdata = netdev_priv(ndev); -+ int i; -+ -+ for (i = 0; i < XGENE_STATS_LEN; i++) -+ *data++ = *(u64 *)(pdata + gstrings_stats[i].offset); -+} -+ -+static const struct ethtool_ops xgene_ethtool_ops = { -+ .get_drvinfo = xgene_get_drvinfo, -+ .get_settings = xgene_get_settings, -+ .set_settings = xgene_set_settings, -+ .get_link = ethtool_op_get_link, -+ .get_strings = xgene_get_strings, -+ .get_sset_count = xgene_get_sset_count, -+ .get_ethtool_stats = xgene_get_ethtool_stats -+}; -+ -+void xgene_enet_set_ethtool_ops(struct net_device *ndev) -+{ -+ ndev->ethtool_ops = &xgene_ethtool_ops; -+} -diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c -new file mode 100644 -index 0000000..812d8d6 ---- /dev/null -+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c -@@ -0,0 +1,728 @@ -+/* Applied Micro X-Gene SoC Ethernet Driver -+ * -+ * Copyright (c) 2014, Applied Micro Circuits Corporation -+ * Authors: Iyappan Subramanian -+ * Ravi Patel -+ * Keyur Chudgar -+ * -+ * 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, see . -+ */ -+ -+#include "xgene_enet_main.h" -+#include "xgene_enet_hw.h" -+ -+static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring) -+{ -+ u32 *ring_cfg = ring->state; -+ u64 addr = ring->dma; -+ enum xgene_enet_ring_cfgsize cfgsize = ring->cfgsize; -+ -+ ring_cfg[4] |= (1 << SELTHRSH_POS) & -+ CREATE_MASK(SELTHRSH_POS, SELTHRSH_LEN); -+ ring_cfg[3] |= ACCEPTLERR; -+ ring_cfg[2] |= QCOHERENT; -+ -+ addr >>= 8; -+ ring_cfg[2] |= (addr << RINGADDRL_POS) & -+ CREATE_MASK_ULL(RINGADDRL_POS, RINGADDRL_LEN); -+ addr >>= RINGADDRL_LEN; -+ ring_cfg[3] |= addr & CREATE_MASK_ULL(RINGADDRH_POS, RINGADDRH_LEN); -+ ring_cfg[3] |= ((u32)cfgsize << RINGSIZE_POS) & -+ CREATE_MASK(RINGSIZE_POS, RINGSIZE_LEN); -+} -+ -+static void xgene_enet_ring_set_type(struct xgene_enet_desc_ring *ring) -+{ -+ u32 *ring_cfg = ring->state; -+ bool is_bufpool; -+ u32 val; -+ -+ is_bufpool = xgene_enet_is_bufpool(ring->id); -+ val = (is_bufpool) ? RING_BUFPOOL : RING_REGULAR; -+ ring_cfg[4] |= (val << RINGTYPE_POS) & -+ CREATE_MASK(RINGTYPE_POS, RINGTYPE_LEN); -+ -+ if (is_bufpool) { -+ ring_cfg[3] |= (BUFPOOL_MODE << RINGMODE_POS) & -+ CREATE_MASK(RINGMODE_POS, RINGMODE_LEN); -+ } -+} -+ -+static void xgene_enet_ring_set_recombbuf(struct xgene_enet_desc_ring *ring) -+{ -+ u32 *ring_cfg = ring->state; -+ -+ ring_cfg[3] |= RECOMBBUF; -+ ring_cfg[3] |= (0xf << RECOMTIMEOUTL_POS) & -+ CREATE_MASK(RECOMTIMEOUTL_POS, RECOMTIMEOUTL_LEN); -+ ring_cfg[4] |= 0x7 & CREATE_MASK(RECOMTIMEOUTH_POS, RECOMTIMEOUTH_LEN); -+} -+ -+static void xgene_enet_ring_wr32(struct xgene_enet_desc_ring *ring, -+ u32 offset, u32 data) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); -+ -+ iowrite32(data, pdata->ring_csr_addr + offset); -+} -+ -+static void xgene_enet_ring_rd32(struct xgene_enet_desc_ring *ring, -+ u32 offset, u32 *data) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); -+ -+ *data = ioread32(pdata->ring_csr_addr + offset); -+} -+ -+static void xgene_enet_write_ring_state(struct xgene_enet_desc_ring *ring) -+{ -+ int i; -+ -+ xgene_enet_ring_wr32(ring, CSR_RING_CONFIG, ring->num); -+ for (i = 0; i < NUM_RING_CONFIG; i++) { -+ xgene_enet_ring_wr32(ring, CSR_RING_WR_BASE + (i * 4), -+ ring->state[i]); -+ } -+} -+ -+static void xgene_enet_clr_ring_state(struct xgene_enet_desc_ring *ring) -+{ -+ memset(ring->state, 0, sizeof(u32) * NUM_RING_CONFIG); -+ xgene_enet_write_ring_state(ring); -+} -+ -+static void xgene_enet_set_ring_state(struct xgene_enet_desc_ring *ring) -+{ -+ xgene_enet_ring_set_type(ring); -+ -+ if (xgene_enet_ring_owner(ring->id) == RING_OWNER_ETH0) -+ xgene_enet_ring_set_recombbuf(ring); -+ -+ xgene_enet_ring_init(ring); -+ xgene_enet_write_ring_state(ring); -+} -+ -+static void xgene_enet_set_ring_id(struct xgene_enet_desc_ring *ring) -+{ -+ u32 ring_id_val, ring_id_buf; -+ bool is_bufpool; -+ -+ is_bufpool = xgene_enet_is_bufpool(ring->id); -+ -+ ring_id_val = ring->id & GENMASK(9, 0); -+ ring_id_val |= OVERWRITE; -+ -+ ring_id_buf = (ring->num << 9) & GENMASK(18, 9); -+ ring_id_buf |= PREFETCH_BUF_EN; -+ if (is_bufpool) -+ ring_id_buf |= IS_BUFFER_POOL; -+ -+ xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id_val); -+ xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, ring_id_buf); -+} -+ -+static void xgene_enet_clr_desc_ring_id(struct xgene_enet_desc_ring *ring) -+{ -+ u32 ring_id; -+ -+ ring_id = ring->id | OVERWRITE; -+ xgene_enet_ring_wr32(ring, CSR_RING_ID, ring_id); -+ xgene_enet_ring_wr32(ring, CSR_RING_ID_BUF, 0); -+} -+ -+struct xgene_enet_desc_ring *xgene_enet_setup_ring( -+ struct xgene_enet_desc_ring *ring) -+{ -+ u32 size = ring->size; -+ u32 i, data; -+ bool is_bufpool; -+ -+ xgene_enet_clr_ring_state(ring); -+ xgene_enet_set_ring_state(ring); -+ xgene_enet_set_ring_id(ring); -+ -+ ring->slots = xgene_enet_get_numslots(ring->id, size); -+ -+ is_bufpool = xgene_enet_is_bufpool(ring->id); -+ if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU) -+ return ring; -+ -+ for (i = 0; i < ring->slots; i++) -+ xgene_enet_mark_desc_slot_empty(&ring->raw_desc[i]); -+ -+ xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data); -+ data |= BIT(31 - xgene_enet_ring_bufnum(ring->id)); -+ xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data); -+ -+ return ring; -+} -+ -+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring) -+{ -+ u32 data; -+ bool is_bufpool; -+ -+ is_bufpool = xgene_enet_is_bufpool(ring->id); -+ if (is_bufpool || xgene_enet_ring_owner(ring->id) != RING_OWNER_CPU) -+ goto out; -+ -+ xgene_enet_ring_rd32(ring, CSR_RING_NE_INT_MODE, &data); -+ data &= ~BIT(31 - xgene_enet_ring_bufnum(ring->id)); -+ xgene_enet_ring_wr32(ring, CSR_RING_NE_INT_MODE, data); -+ -+out: -+ xgene_enet_clr_desc_ring_id(ring); -+ xgene_enet_clr_ring_state(ring); -+} -+ -+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, -+ struct xgene_enet_pdata *pdata, -+ enum xgene_enet_err_code status) -+{ -+ struct rtnl_link_stats64 *stats = &pdata->stats; -+ -+ switch (status) { -+ case INGRESS_CRC: -+ stats->rx_crc_errors++; -+ break; -+ case INGRESS_CHECKSUM: -+ case INGRESS_CHECKSUM_COMPUTE: -+ stats->rx_errors++; -+ break; -+ case INGRESS_TRUNC_FRAME: -+ stats->rx_frame_errors++; -+ break; -+ case INGRESS_PKT_LEN: -+ stats->rx_length_errors++; -+ break; -+ case INGRESS_PKT_UNDER: -+ stats->rx_frame_errors++; -+ break; -+ case INGRESS_FIFO_OVERRUN: -+ stats->rx_fifo_errors++; -+ break; -+ default: -+ break; -+ } -+} -+ -+static void xgene_enet_wr_csr(struct xgene_enet_pdata *pdata, -+ u32 offset, u32 val) -+{ -+ void __iomem *addr = pdata->eth_csr_addr + offset; -+ -+ iowrite32(val, addr); -+} -+ -+static void xgene_enet_wr_ring_if(struct xgene_enet_pdata *pdata, -+ u32 offset, u32 val) -+{ -+ void __iomem *addr = pdata->eth_ring_if_addr + offset; -+ -+ iowrite32(val, addr); -+} -+ -+static void xgene_enet_wr_diag_csr(struct xgene_enet_pdata *pdata, -+ u32 offset, u32 val) -+{ -+ void __iomem *addr = pdata->eth_diag_csr_addr + offset; -+ -+ iowrite32(val, addr); -+} -+ -+static void xgene_enet_wr_mcx_csr(struct xgene_enet_pdata *pdata, -+ u32 offset, u32 val) -+{ -+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset; -+ -+ iowrite32(val, addr); -+} -+ -+static bool xgene_enet_wr_indirect(void __iomem *addr, void __iomem *wr, -+ void __iomem *cmd, void __iomem *cmd_done, -+ u32 wr_addr, u32 wr_data) -+{ -+ u32 done; -+ u8 wait = 10; -+ -+ iowrite32(wr_addr, addr); -+ iowrite32(wr_data, wr); -+ iowrite32(XGENE_ENET_WR_CMD, cmd); -+ -+ /* wait for write command to complete */ -+ while (!(done = ioread32(cmd_done)) && wait--) -+ udelay(1); -+ -+ if (!done) -+ return false; -+ -+ iowrite32(0, cmd); -+ -+ return true; -+} -+ -+static void xgene_enet_wr_mcx_mac(struct xgene_enet_pdata *pdata, -+ u32 wr_addr, u32 wr_data) -+{ -+ void __iomem *addr, *wr, *cmd, *cmd_done; -+ -+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; -+ wr = pdata->mcx_mac_addr + MAC_WRITE_REG_OFFSET; -+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; -+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; -+ -+ if (!xgene_enet_wr_indirect(addr, wr, cmd, cmd_done, wr_addr, wr_data)) -+ netdev_err(pdata->ndev, "MCX mac write failed, addr: %04x\n", -+ wr_addr); -+} -+ -+static void xgene_enet_rd_csr(struct xgene_enet_pdata *pdata, -+ u32 offset, u32 *val) -+{ -+ void __iomem *addr = pdata->eth_csr_addr + offset; -+ -+ *val = ioread32(addr); -+} -+ -+static void xgene_enet_rd_diag_csr(struct xgene_enet_pdata *pdata, -+ u32 offset, u32 *val) -+{ -+ void __iomem *addr = pdata->eth_diag_csr_addr + offset; -+ -+ *val = ioread32(addr); -+} -+ -+static void xgene_enet_rd_mcx_csr(struct xgene_enet_pdata *pdata, -+ u32 offset, u32 *val) -+{ -+ void __iomem *addr = pdata->mcx_mac_csr_addr + offset; -+ -+ *val = ioread32(addr); -+} -+ -+static bool xgene_enet_rd_indirect(void __iomem *addr, void __iomem *rd, -+ void __iomem *cmd, void __iomem *cmd_done, -+ u32 rd_addr, u32 *rd_data) -+{ -+ u32 done; -+ u8 wait = 10; -+ -+ iowrite32(rd_addr, addr); -+ iowrite32(XGENE_ENET_RD_CMD, cmd); -+ -+ /* wait for read command to complete */ -+ while (!(done = ioread32(cmd_done)) && wait--) -+ udelay(1); -+ -+ if (!done) -+ return false; -+ -+ *rd_data = ioread32(rd); -+ iowrite32(0, cmd); -+ -+ return true; -+} -+ -+static void xgene_enet_rd_mcx_mac(struct xgene_enet_pdata *pdata, -+ u32 rd_addr, u32 *rd_data) -+{ -+ void __iomem *addr, *rd, *cmd, *cmd_done; -+ -+ addr = pdata->mcx_mac_addr + MAC_ADDR_REG_OFFSET; -+ rd = pdata->mcx_mac_addr + MAC_READ_REG_OFFSET; -+ cmd = pdata->mcx_mac_addr + MAC_COMMAND_REG_OFFSET; -+ cmd_done = pdata->mcx_mac_addr + MAC_COMMAND_DONE_REG_OFFSET; -+ -+ if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data)) -+ netdev_err(pdata->ndev, "MCX mac read failed, addr: %04x\n", -+ rd_addr); -+} -+ -+static int xgene_mii_phy_write(struct xgene_enet_pdata *pdata, int phy_id, -+ u32 reg, u16 data) -+{ -+ u32 addr = 0, wr_data = 0; -+ u32 done; -+ u8 wait = 10; -+ -+ PHY_ADDR_SET(&addr, phy_id); -+ REG_ADDR_SET(&addr, reg); -+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr); -+ -+ PHY_CONTROL_SET(&wr_data, data); -+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONTROL_ADDR, wr_data); -+ do { -+ usleep_range(5, 10); -+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done); -+ } while ((done & BUSY_MASK) && wait--); -+ -+ if (done & BUSY_MASK) { -+ netdev_err(pdata->ndev, "MII_MGMT write failed\n"); -+ return -EBUSY; -+ } -+ -+ return 0; -+} -+ -+static int xgene_mii_phy_read(struct xgene_enet_pdata *pdata, -+ u8 phy_id, u32 reg) -+{ -+ u32 addr = 0; -+ u32 data, done; -+ u8 wait = 10; -+ -+ PHY_ADDR_SET(&addr, phy_id); -+ REG_ADDR_SET(&addr, reg); -+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_ADDRESS_ADDR, addr); -+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, READ_CYCLE_MASK); -+ do { -+ usleep_range(5, 10); -+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_INDICATORS_ADDR, &done); -+ } while ((done & BUSY_MASK) && wait--); -+ -+ if (done & BUSY_MASK) { -+ netdev_err(pdata->ndev, "MII_MGMT read failed\n"); -+ return -EBUSY; -+ } -+ -+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_STATUS_ADDR, &data); -+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_COMMAND_ADDR, 0); -+ -+ return data; -+} -+ -+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata) -+{ -+ u32 addr0, addr1; -+ u8 *dev_addr = pdata->ndev->dev_addr; -+ -+ addr0 = (dev_addr[3] << 24) | (dev_addr[2] << 16) | -+ (dev_addr[1] << 8) | dev_addr[0]; -+ addr1 = (dev_addr[5] << 24) | (dev_addr[4] << 16); -+ addr1 |= pdata->phy_addr & 0xFFFF; -+ -+ xgene_enet_wr_mcx_mac(pdata, STATION_ADDR0_ADDR, addr0); -+ xgene_enet_wr_mcx_mac(pdata, STATION_ADDR1_ADDR, addr1); -+} -+ -+static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata) -+{ -+ struct net_device *ndev = pdata->ndev; -+ u32 data; -+ u8 wait = 10; -+ -+ xgene_enet_wr_diag_csr(pdata, ENET_CFG_MEM_RAM_SHUTDOWN_ADDR, 0x0); -+ do { -+ usleep_range(100, 110); -+ xgene_enet_rd_diag_csr(pdata, ENET_BLOCK_MEM_RDY_ADDR, &data); -+ } while ((data != 0xffffffff) && wait--); -+ -+ if (data != 0xffffffff) { -+ netdev_err(ndev, "Failed to release memory from shutdown\n"); -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+ -+void xgene_gmac_reset(struct xgene_enet_pdata *pdata) -+{ -+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, SOFT_RESET1); -+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, 0); -+} -+ -+void xgene_gmac_init(struct xgene_enet_pdata *pdata, int speed) -+{ -+ u32 value, mc2; -+ u32 intf_ctl, rgmii; -+ u32 icm0, icm2; -+ -+ xgene_gmac_reset(pdata); -+ -+ xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, &icm0); -+ xgene_enet_rd_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, &icm2); -+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_2_ADDR, &mc2); -+ xgene_enet_rd_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, &intf_ctl); -+ xgene_enet_rd_csr(pdata, RGMII_REG_0_ADDR, &rgmii); -+ -+ switch (speed) { -+ case SPEED_10: -+ ENET_INTERFACE_MODE2_SET(&mc2, 1); -+ CFG_MACMODE_SET(&icm0, 0); -+ CFG_WAITASYNCRD_SET(&icm2, 500); -+ rgmii &= ~CFG_SPEED_1250; -+ break; -+ case SPEED_100: -+ ENET_INTERFACE_MODE2_SET(&mc2, 1); -+ intf_ctl |= ENET_LHD_MODE; -+ CFG_MACMODE_SET(&icm0, 1); -+ CFG_WAITASYNCRD_SET(&icm2, 80); -+ rgmii &= ~CFG_SPEED_1250; -+ break; -+ default: -+ ENET_INTERFACE_MODE2_SET(&mc2, 2); -+ intf_ctl |= ENET_GHD_MODE; -+ CFG_TXCLK_MUXSEL0_SET(&rgmii, 4); -+ xgene_enet_rd_csr(pdata, DEBUG_REG_ADDR, &value); -+ value |= CFG_BYPASS_UNISEC_TX | CFG_BYPASS_UNISEC_RX; -+ xgene_enet_wr_csr(pdata, DEBUG_REG_ADDR, value); -+ break; -+ } -+ -+ mc2 |= FULL_DUPLEX2; -+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_2_ADDR, mc2); -+ xgene_enet_wr_mcx_mac(pdata, INTERFACE_CONTROL_ADDR, intf_ctl); -+ -+ xgene_gmac_set_mac_addr(pdata); -+ -+ /* Adjust MDC clock frequency */ -+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &value); -+ MGMT_CLOCK_SEL_SET(&value, 7); -+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, value); -+ -+ /* Enable drop if bufpool not available */ -+ xgene_enet_rd_csr(pdata, RSIF_CONFIG_REG_ADDR, &value); -+ value |= CFG_RSIF_FPBUFF_TIMEOUT_EN; -+ xgene_enet_wr_csr(pdata, RSIF_CONFIG_REG_ADDR, value); -+ -+ /* Rtype should be copied from FP */ -+ xgene_enet_wr_csr(pdata, RSIF_RAM_DBG_REG0_ADDR, 0); -+ xgene_enet_wr_csr(pdata, RGMII_REG_0_ADDR, rgmii); -+ -+ /* Rx-Tx traffic resume */ -+ xgene_enet_wr_csr(pdata, CFG_LINK_AGGR_RESUME_0_ADDR, TX_PORT0); -+ -+ xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG0_REG_0_ADDR, icm0); -+ xgene_enet_wr_mcx_csr(pdata, ICM_CONFIG2_REG_0_ADDR, icm2); -+ -+ xgene_enet_rd_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, &value); -+ value &= ~TX_DV_GATE_EN0; -+ value &= ~RX_DV_GATE_EN0; -+ value |= RESUME_RX0; -+ xgene_enet_wr_mcx_csr(pdata, RX_DV_GATE_REG_0_ADDR, value); -+ -+ xgene_enet_wr_csr(pdata, CFG_BYPASS_ADDR, RESUME_TX); -+} -+ -+static void xgene_enet_config_ring_if_assoc(struct xgene_enet_pdata *pdata) -+{ -+ u32 val = 0xffffffff; -+ -+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQASSOC_ADDR, val); -+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIFPQASSOC_ADDR, val); -+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEWQASSOC_ADDR, val); -+ xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIQMLITEFPQASSOC_ADDR, val); -+} -+ -+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata, -+ u32 dst_ring_num, u16 bufpool_id) -+{ -+ u32 cb; -+ u32 fpsel; -+ -+ fpsel = xgene_enet_ring_bufnum(bufpool_id) - 0x20; -+ -+ xgene_enet_rd_csr(pdata, CLE_BYPASS_REG0_0_ADDR, &cb); -+ cb |= CFG_CLE_BYPASS_EN0; -+ CFG_CLE_IP_PROTOCOL0_SET(&cb, 3); -+ xgene_enet_wr_csr(pdata, CLE_BYPASS_REG0_0_ADDR, cb); -+ -+ xgene_enet_rd_csr(pdata, CLE_BYPASS_REG1_0_ADDR, &cb); -+ CFG_CLE_DSTQID0_SET(&cb, dst_ring_num); -+ CFG_CLE_FPSEL0_SET(&cb, fpsel); -+ xgene_enet_wr_csr(pdata, CLE_BYPASS_REG1_0_ADDR, cb); -+} -+ -+void xgene_gmac_rx_enable(struct xgene_enet_pdata *pdata) -+{ -+ u32 data; -+ -+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); -+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | RX_EN); -+} -+ -+void xgene_gmac_tx_enable(struct xgene_enet_pdata *pdata) -+{ -+ u32 data; -+ -+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); -+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data | TX_EN); -+} -+ -+void xgene_gmac_rx_disable(struct xgene_enet_pdata *pdata) -+{ -+ u32 data; -+ -+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); -+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~RX_EN); -+} -+ -+void xgene_gmac_tx_disable(struct xgene_enet_pdata *pdata) -+{ -+ u32 data; -+ -+ xgene_enet_rd_mcx_mac(pdata, MAC_CONFIG_1_ADDR, &data); -+ xgene_enet_wr_mcx_mac(pdata, MAC_CONFIG_1_ADDR, data & ~TX_EN); -+} -+ -+void xgene_enet_reset(struct xgene_enet_pdata *pdata) -+{ -+ u32 val; -+ -+ clk_prepare_enable(pdata->clk); -+ clk_disable_unprepare(pdata->clk); -+ clk_prepare_enable(pdata->clk); -+ xgene_enet_ecc_init(pdata); -+ xgene_enet_config_ring_if_assoc(pdata); -+ -+ /* Enable auto-incr for scanning */ -+ xgene_enet_rd_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, &val); -+ val |= SCAN_AUTO_INCR; -+ MGMT_CLOCK_SEL_SET(&val, 1); -+ xgene_enet_wr_mcx_mac(pdata, MII_MGMT_CONFIG_ADDR, val); -+} -+ -+void xgene_gport_shutdown(struct xgene_enet_pdata *pdata) -+{ -+ clk_disable_unprepare(pdata->clk); -+} -+ -+static int xgene_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) -+{ -+ struct xgene_enet_pdata *pdata = bus->priv; -+ u32 val; -+ -+ val = xgene_mii_phy_read(pdata, mii_id, regnum); -+ netdev_dbg(pdata->ndev, "mdio_rd: bus=%d reg=%d val=%x\n", -+ mii_id, regnum, val); -+ -+ return val; -+} -+ -+static int xgene_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, -+ u16 val) -+{ -+ struct xgene_enet_pdata *pdata = bus->priv; -+ -+ netdev_dbg(pdata->ndev, "mdio_wr: bus=%d reg=%d val=%x\n", -+ mii_id, regnum, val); -+ return xgene_mii_phy_write(pdata, mii_id, regnum, val); -+} -+ -+static void xgene_enet_adjust_link(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct phy_device *phydev = pdata->phy_dev; -+ -+ if (phydev->link) { -+ if (pdata->phy_speed != phydev->speed) { -+ xgene_gmac_init(pdata, phydev->speed); -+ xgene_gmac_rx_enable(pdata); -+ xgene_gmac_tx_enable(pdata); -+ pdata->phy_speed = phydev->speed; -+ phy_print_status(phydev); -+ } -+ } else { -+ xgene_gmac_rx_disable(pdata); -+ xgene_gmac_tx_disable(pdata); -+ pdata->phy_speed = SPEED_UNKNOWN; -+ phy_print_status(phydev); -+ } -+} -+ -+static int xgene_enet_phy_connect(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct device_node *phy_np; -+ struct phy_device *phy_dev; -+ struct device *dev = &pdata->pdev->dev; -+ -+ phy_np = of_parse_phandle(dev->of_node, "phy-handle", 0); -+ if (!phy_np) { -+ netdev_dbg(ndev, "No phy-handle found\n"); -+ return -ENODEV; -+ } -+ -+ phy_dev = of_phy_connect(ndev, phy_np, &xgene_enet_adjust_link, -+ 0, pdata->phy_mode); -+ if (!phy_dev) { -+ netdev_err(ndev, "Could not connect to PHY\n"); -+ return -ENODEV; -+ } -+ -+ pdata->phy_speed = SPEED_UNKNOWN; -+ phy_dev->supported &= ~SUPPORTED_10baseT_Half & -+ ~SUPPORTED_100baseT_Half & -+ ~SUPPORTED_1000baseT_Half; -+ phy_dev->advertising = phy_dev->supported; -+ pdata->phy_dev = phy_dev; -+ -+ return 0; -+} -+ -+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata) -+{ -+ struct net_device *ndev = pdata->ndev; -+ struct device *dev = &pdata->pdev->dev; -+ struct device_node *child_np; -+ struct device_node *mdio_np = NULL; -+ struct mii_bus *mdio_bus; -+ int ret; -+ -+ for_each_child_of_node(dev->of_node, child_np) { -+ if (of_device_is_compatible(child_np, "apm,xgene-mdio")) { -+ mdio_np = child_np; -+ break; -+ } -+ } -+ -+ if (!mdio_np) { -+ netdev_dbg(ndev, "No mdio node in the dts\n"); -+ return -ENXIO; -+ } -+ -+ mdio_bus = mdiobus_alloc(); -+ if (!mdio_bus) -+ return -ENOMEM; -+ -+ mdio_bus->name = "APM X-Gene MDIO bus"; -+ mdio_bus->read = xgene_enet_mdio_read; -+ mdio_bus->write = xgene_enet_mdio_write; -+ snprintf(mdio_bus->id, MII_BUS_ID_SIZE, "%s-%s", "xgene-mii", -+ ndev->name); -+ -+ mdio_bus->priv = pdata; -+ mdio_bus->parent = &ndev->dev; -+ -+ ret = of_mdiobus_register(mdio_bus, mdio_np); -+ if (ret) { -+ netdev_err(ndev, "Failed to register MDIO bus\n"); -+ mdiobus_free(mdio_bus); -+ return ret; -+ } -+ pdata->mdio_bus = mdio_bus; -+ -+ ret = xgene_enet_phy_connect(ndev); -+ if (ret) -+ xgene_enet_mdio_remove(pdata); -+ -+ return ret; -+} -+ -+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata) -+{ -+ mdiobus_unregister(pdata->mdio_bus); -+ mdiobus_free(pdata->mdio_bus); -+ pdata->mdio_bus = NULL; -+} -diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h -new file mode 100644 -index 0000000..371e7a5 ---- /dev/null -+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h -@@ -0,0 +1,337 @@ -+/* Applied Micro X-Gene SoC Ethernet Driver -+ * -+ * Copyright (c) 2014, Applied Micro Circuits Corporation -+ * Authors: Iyappan Subramanian -+ * Ravi Patel -+ * Keyur Chudgar -+ * -+ * 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, see . -+ */ -+ -+#ifndef __XGENE_ENET_HW_H__ -+#define __XGENE_ENET_HW_H__ -+ -+#include "xgene_enet_main.h" -+ -+struct xgene_enet_pdata; -+struct xgene_enet_stats; -+ -+/* clears and then set bits */ -+static inline void xgene_set_bits(u32 *dst, u32 val, u32 start, u32 len) -+{ -+ u32 end = start + len - 1; -+ u32 mask = GENMASK(end, start); -+ -+ *dst &= ~mask; -+ *dst |= (val << start) & mask; -+} -+ -+static inline u32 xgene_get_bits(u32 val, u32 start, u32 end) -+{ -+ return (val & GENMASK(end, start)) >> start; -+} -+ -+#define CSR_RING_ID 0x0008 -+#define OVERWRITE BIT(31) -+#define IS_BUFFER_POOL BIT(20) -+#define PREFETCH_BUF_EN BIT(21) -+#define CSR_RING_ID_BUF 0x000c -+#define CSR_RING_NE_INT_MODE 0x017c -+#define CSR_RING_CONFIG 0x006c -+#define CSR_RING_WR_BASE 0x0070 -+#define NUM_RING_CONFIG 5 -+#define BUFPOOL_MODE 3 -+#define RM3 3 -+#define INC_DEC_CMD_ADDR 0x002c -+#define UDP_HDR_SIZE 2 -+#define BUF_LEN_CODE_2K 0x5000 -+ -+#define CREATE_MASK(pos, len) GENMASK((pos)+(len)-1, (pos)) -+#define CREATE_MASK_ULL(pos, len) GENMASK_ULL((pos)+(len)-1, (pos)) -+ -+/* Empty slot soft signature */ -+#define EMPTY_SLOT_INDEX 1 -+#define EMPTY_SLOT ~0ULL -+ -+#define WORK_DESC_SIZE 32 -+#define BUFPOOL_DESC_SIZE 16 -+ -+#define RING_OWNER_MASK GENMASK(9, 6) -+#define RING_BUFNUM_MASK GENMASK(5, 0) -+ -+#define SELTHRSH_POS 3 -+#define SELTHRSH_LEN 3 -+#define RINGADDRL_POS 5 -+#define RINGADDRL_LEN 27 -+#define RINGADDRH_POS 0 -+#define RINGADDRH_LEN 6 -+#define RINGSIZE_POS 23 -+#define RINGSIZE_LEN 3 -+#define RINGTYPE_POS 19 -+#define RINGTYPE_LEN 2 -+#define RINGMODE_POS 20 -+#define RINGMODE_LEN 3 -+#define RECOMTIMEOUTL_POS 28 -+#define RECOMTIMEOUTL_LEN 3 -+#define RECOMTIMEOUTH_POS 0 -+#define RECOMTIMEOUTH_LEN 2 -+#define NUMMSGSINQ_POS 1 -+#define NUMMSGSINQ_LEN 16 -+#define ACCEPTLERR BIT(19) -+#define QCOHERENT BIT(4) -+#define RECOMBBUF BIT(27) -+ -+#define BLOCK_ETH_CSR_OFFSET 0x2000 -+#define BLOCK_ETH_RING_IF_OFFSET 0x9000 -+#define BLOCK_ETH_CLKRST_CSR_OFFSET 0xC000 -+#define BLOCK_ETH_DIAG_CSR_OFFSET 0xD000 -+ -+#define BLOCK_ETH_MAC_OFFSET 0x0000 -+#define BLOCK_ETH_STATS_OFFSET 0x0014 -+#define BLOCK_ETH_MAC_CSR_OFFSET 0x2800 -+ -+#define MAC_ADDR_REG_OFFSET 0x00 -+#define MAC_COMMAND_REG_OFFSET 0x04 -+#define MAC_WRITE_REG_OFFSET 0x08 -+#define MAC_READ_REG_OFFSET 0x0c -+#define MAC_COMMAND_DONE_REG_OFFSET 0x10 -+ -+#define STAT_ADDR_REG_OFFSET 0x00 -+#define STAT_COMMAND_REG_OFFSET 0x04 -+#define STAT_WRITE_REG_OFFSET 0x08 -+#define STAT_READ_REG_OFFSET 0x0c -+#define STAT_COMMAND_DONE_REG_OFFSET 0x10 -+ -+#define MII_MGMT_CONFIG_ADDR 0x20 -+#define MII_MGMT_COMMAND_ADDR 0x24 -+#define MII_MGMT_ADDRESS_ADDR 0x28 -+#define MII_MGMT_CONTROL_ADDR 0x2c -+#define MII_MGMT_STATUS_ADDR 0x30 -+#define MII_MGMT_INDICATORS_ADDR 0x34 -+ -+#define BUSY_MASK BIT(0) -+#define READ_CYCLE_MASK BIT(0) -+#define PHY_CONTROL_SET(dst, val) xgene_set_bits(dst, val, 0, 16) -+ -+#define ENET_SPARE_CFG_REG_ADDR 0x0750 -+#define RSIF_CONFIG_REG_ADDR 0x0010 -+#define RSIF_RAM_DBG_REG0_ADDR 0x0048 -+#define RGMII_REG_0_ADDR 0x07e0 -+#define CFG_LINK_AGGR_RESUME_0_ADDR 0x07c8 -+#define DEBUG_REG_ADDR 0x0700 -+#define CFG_BYPASS_ADDR 0x0294 -+#define CLE_BYPASS_REG0_0_ADDR 0x0490 -+#define CLE_BYPASS_REG1_0_ADDR 0x0494 -+#define CFG_RSIF_FPBUFF_TIMEOUT_EN BIT(31) -+#define RESUME_TX BIT(0) -+#define CFG_SPEED_1250 BIT(24) -+#define TX_PORT0 BIT(0) -+#define CFG_BYPASS_UNISEC_TX BIT(2) -+#define CFG_BYPASS_UNISEC_RX BIT(1) -+#define CFG_CLE_BYPASS_EN0 BIT(31) -+#define CFG_TXCLK_MUXSEL0_SET(dst, val) xgene_set_bits(dst, val, 29, 3) -+ -+#define CFG_CLE_IP_PROTOCOL0_SET(dst, val) xgene_set_bits(dst, val, 16, 2) -+#define CFG_CLE_DSTQID0_SET(dst, val) xgene_set_bits(dst, val, 0, 12) -+#define CFG_CLE_FPSEL0_SET(dst, val) xgene_set_bits(dst, val, 16, 4) -+#define CFG_MACMODE_SET(dst, val) xgene_set_bits(dst, val, 18, 2) -+#define CFG_WAITASYNCRD_SET(dst, val) xgene_set_bits(dst, val, 0, 16) -+#define ICM_CONFIG0_REG_0_ADDR 0x0400 -+#define ICM_CONFIG2_REG_0_ADDR 0x0410 -+#define RX_DV_GATE_REG_0_ADDR 0x05fc -+#define TX_DV_GATE_EN0 BIT(2) -+#define RX_DV_GATE_EN0 BIT(1) -+#define RESUME_RX0 BIT(0) -+#define ENET_CFGSSQMIWQASSOC_ADDR 0xe0 -+#define ENET_CFGSSQMIFPQASSOC_ADDR 0xdc -+#define ENET_CFGSSQMIQMLITEFPQASSOC_ADDR 0xf0 -+#define ENET_CFGSSQMIQMLITEWQASSOC_ADDR 0xf4 -+#define ENET_CFG_MEM_RAM_SHUTDOWN_ADDR 0x70 -+#define ENET_BLOCK_MEM_RDY_ADDR 0x74 -+#define MAC_CONFIG_1_ADDR 0x00 -+#define MAC_CONFIG_2_ADDR 0x04 -+#define MAX_FRAME_LEN_ADDR 0x10 -+#define INTERFACE_CONTROL_ADDR 0x38 -+#define STATION_ADDR0_ADDR 0x40 -+#define STATION_ADDR1_ADDR 0x44 -+#define PHY_ADDR_SET(dst, val) xgene_set_bits(dst, val, 8, 5) -+#define REG_ADDR_SET(dst, val) xgene_set_bits(dst, val, 0, 5) -+#define ENET_INTERFACE_MODE2_SET(dst, val) xgene_set_bits(dst, val, 8, 2) -+#define MGMT_CLOCK_SEL_SET(dst, val) xgene_set_bits(dst, val, 0, 3) -+#define SOFT_RESET1 BIT(31) -+#define TX_EN BIT(0) -+#define RX_EN BIT(2) -+#define ENET_LHD_MODE BIT(25) -+#define ENET_GHD_MODE BIT(26) -+#define FULL_DUPLEX2 BIT(0) -+#define SCAN_AUTO_INCR BIT(5) -+#define TBYT_ADDR 0x38 -+#define TPKT_ADDR 0x39 -+#define TDRP_ADDR 0x45 -+#define TFCS_ADDR 0x47 -+#define TUND_ADDR 0x4a -+ -+#define TSO_IPPROTO_TCP 1 -+#define FULL_DUPLEX 2 -+ -+#define USERINFO_POS 0 -+#define USERINFO_LEN 32 -+#define FPQNUM_POS 32 -+#define FPQNUM_LEN 12 -+#define LERR_POS 60 -+#define LERR_LEN 3 -+#define STASH_POS 52 -+#define STASH_LEN 2 -+#define BUFDATALEN_POS 48 -+#define BUFDATALEN_LEN 12 -+#define DATAADDR_POS 0 -+#define DATAADDR_LEN 42 -+#define COHERENT_POS 63 -+#define HENQNUM_POS 48 -+#define HENQNUM_LEN 12 -+#define TYPESEL_POS 44 -+#define TYPESEL_LEN 4 -+#define ETHHDR_POS 12 -+#define ETHHDR_LEN 8 -+#define IC_POS 35 /* Insert CRC */ -+#define TCPHDR_POS 0 -+#define TCPHDR_LEN 6 -+#define IPHDR_POS 6 -+#define IPHDR_LEN 6 -+#define EC_POS 22 /* Enable checksum */ -+#define EC_LEN 1 -+#define IS_POS 24 /* IP protocol select */ -+#define IS_LEN 1 -+#define TYPE_ETH_WORK_MESSAGE_POS 44 -+ -+struct xgene_enet_raw_desc { -+ __le64 m0; -+ __le64 m1; -+ __le64 m2; -+ __le64 m3; -+}; -+ -+struct xgene_enet_raw_desc16 { -+ __le64 m0; -+ __le64 m1; -+}; -+ -+static inline void xgene_enet_mark_desc_slot_empty(void *desc_slot_ptr) -+{ -+ __le64 *desc_slot = desc_slot_ptr; -+ -+ desc_slot[EMPTY_SLOT_INDEX] = cpu_to_le64(EMPTY_SLOT); -+} -+ -+static inline bool xgene_enet_is_desc_slot_empty(void *desc_slot_ptr) -+{ -+ __le64 *desc_slot = desc_slot_ptr; -+ -+ return (desc_slot[EMPTY_SLOT_INDEX] == cpu_to_le64(EMPTY_SLOT)); -+} -+ -+enum xgene_enet_ring_cfgsize { -+ RING_CFGSIZE_512B, -+ RING_CFGSIZE_2KB, -+ RING_CFGSIZE_16KB, -+ RING_CFGSIZE_64KB, -+ RING_CFGSIZE_512KB, -+ RING_CFGSIZE_INVALID -+}; -+ -+enum xgene_enet_ring_type { -+ RING_DISABLED, -+ RING_REGULAR, -+ RING_BUFPOOL -+}; -+ -+enum xgene_ring_owner { -+ RING_OWNER_ETH0, -+ RING_OWNER_CPU = 15, -+ RING_OWNER_INVALID -+}; -+ -+enum xgene_enet_ring_bufnum { -+ RING_BUFNUM_REGULAR = 0x0, -+ RING_BUFNUM_BUFPOOL = 0x20, -+ RING_BUFNUM_INVALID -+}; -+ -+enum xgene_enet_cmd { -+ XGENE_ENET_WR_CMD = BIT(31), -+ XGENE_ENET_RD_CMD = BIT(30) -+}; -+ -+enum xgene_enet_err_code { -+ HBF_READ_DATA = 3, -+ HBF_LL_READ = 4, -+ BAD_WORK_MSG = 6, -+ BUFPOOL_TIMEOUT = 15, -+ INGRESS_CRC = 16, -+ INGRESS_CHECKSUM = 17, -+ INGRESS_TRUNC_FRAME = 18, -+ INGRESS_PKT_LEN = 19, -+ INGRESS_PKT_UNDER = 20, -+ INGRESS_FIFO_OVERRUN = 21, -+ INGRESS_CHECKSUM_COMPUTE = 26, -+ ERR_CODE_INVALID -+}; -+ -+static inline enum xgene_ring_owner xgene_enet_ring_owner(u16 id) -+{ -+ return (id & RING_OWNER_MASK) >> 6; -+} -+ -+static inline u8 xgene_enet_ring_bufnum(u16 id) -+{ -+ return id & RING_BUFNUM_MASK; -+} -+ -+static inline bool xgene_enet_is_bufpool(u16 id) -+{ -+ return ((id & RING_BUFNUM_MASK) >= 0x20) ? true : false; -+} -+ -+static inline u16 xgene_enet_get_numslots(u16 id, u32 size) -+{ -+ bool is_bufpool = xgene_enet_is_bufpool(id); -+ -+ return (is_bufpool) ? size / BUFPOOL_DESC_SIZE : -+ size / WORK_DESC_SIZE; -+} -+ -+struct xgene_enet_desc_ring *xgene_enet_setup_ring( -+ struct xgene_enet_desc_ring *ring); -+void xgene_enet_clear_ring(struct xgene_enet_desc_ring *ring); -+void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring, -+ struct xgene_enet_pdata *pdata, -+ enum xgene_enet_err_code status); -+ -+void xgene_enet_reset(struct xgene_enet_pdata *priv); -+void xgene_gmac_reset(struct xgene_enet_pdata *priv); -+void xgene_gmac_init(struct xgene_enet_pdata *priv, int speed); -+void xgene_gmac_tx_enable(struct xgene_enet_pdata *priv); -+void xgene_gmac_rx_enable(struct xgene_enet_pdata *priv); -+void xgene_gmac_tx_disable(struct xgene_enet_pdata *priv); -+void xgene_gmac_rx_disable(struct xgene_enet_pdata *priv); -+void xgene_gmac_set_mac_addr(struct xgene_enet_pdata *pdata); -+void xgene_enet_cle_bypass(struct xgene_enet_pdata *pdata, -+ u32 dst_ring_num, u16 bufpool_id); -+void xgene_gport_shutdown(struct xgene_enet_pdata *priv); -+void xgene_gmac_get_tx_stats(struct xgene_enet_pdata *pdata); -+ -+int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata); -+void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata); -+ -+#endif /* __XGENE_ENET_HW_H__ */ -diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -new file mode 100644 -index 0000000..af7c40a ---- /dev/null -+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -@@ -0,0 +1,951 @@ -+/* Applied Micro X-Gene SoC Ethernet Driver -+ * -+ * Copyright (c) 2014, Applied Micro Circuits Corporation -+ * Authors: Iyappan Subramanian -+ * Ravi Patel -+ * Keyur Chudgar -+ * -+ * 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, see . -+ */ -+ -+#include "xgene_enet_main.h" -+#include "xgene_enet_hw.h" -+ -+static void xgene_enet_init_bufpool(struct xgene_enet_desc_ring *buf_pool) -+{ -+ struct xgene_enet_raw_desc16 *raw_desc; -+ int i; -+ -+ for (i = 0; i < buf_pool->slots; i++) { -+ raw_desc = &buf_pool->raw_desc16[i]; -+ -+ /* Hardware expects descriptor in little endian format */ -+ raw_desc->m0 = cpu_to_le64(i | -+ SET_VAL(FPQNUM, buf_pool->dst_ring_num) | -+ SET_VAL(STASH, 3)); -+ } -+} -+ -+static int xgene_enet_refill_bufpool(struct xgene_enet_desc_ring *buf_pool, -+ u32 nbuf) -+{ -+ struct sk_buff *skb; -+ struct xgene_enet_raw_desc16 *raw_desc; -+ struct net_device *ndev; -+ struct device *dev; -+ dma_addr_t dma_addr; -+ u32 tail = buf_pool->tail; -+ u32 slots = buf_pool->slots - 1; -+ u16 bufdatalen, len; -+ int i; -+ -+ ndev = buf_pool->ndev; -+ dev = ndev_to_dev(buf_pool->ndev); -+ bufdatalen = BUF_LEN_CODE_2K | (SKB_BUFFER_SIZE & GENMASK(11, 0)); -+ len = XGENE_ENET_MAX_MTU; -+ -+ for (i = 0; i < nbuf; i++) { -+ raw_desc = &buf_pool->raw_desc16[tail]; -+ -+ skb = netdev_alloc_skb_ip_align(ndev, len); -+ if (unlikely(!skb)) -+ return -ENOMEM; -+ buf_pool->rx_skb[tail] = skb; -+ -+ dma_addr = dma_map_single(dev, skb->data, len, DMA_FROM_DEVICE); -+ if (dma_mapping_error(dev, dma_addr)) { -+ netdev_err(ndev, "DMA mapping error\n"); -+ dev_kfree_skb_any(skb); -+ return -EINVAL; -+ } -+ -+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) | -+ SET_VAL(BUFDATALEN, bufdatalen) | -+ SET_BIT(COHERENT)); -+ tail = (tail + 1) & slots; -+ } -+ -+ iowrite32(nbuf, buf_pool->cmd); -+ buf_pool->tail = tail; -+ -+ return 0; -+} -+ -+static u16 xgene_enet_dst_ring_num(struct xgene_enet_desc_ring *ring) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); -+ -+ return ((u16)pdata->rm << 10) | ring->num; -+} -+ -+static u8 xgene_enet_hdr_len(const void *data) -+{ -+ const struct ethhdr *eth = data; -+ -+ return (eth->h_proto == htons(ETH_P_8021Q)) ? VLAN_ETH_HLEN : ETH_HLEN; -+} -+ -+static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring) -+{ -+ u32 __iomem *cmd_base = ring->cmd_base; -+ u32 ring_state, num_msgs; -+ -+ ring_state = ioread32(&cmd_base[1]); -+ num_msgs = ring_state & CREATE_MASK(NUMMSGSINQ_POS, NUMMSGSINQ_LEN); -+ -+ return num_msgs >> NUMMSGSINQ_POS; -+} -+ -+static void xgene_enet_delete_bufpool(struct xgene_enet_desc_ring *buf_pool) -+{ -+ struct xgene_enet_raw_desc16 *raw_desc; -+ u32 slots = buf_pool->slots - 1; -+ u32 tail = buf_pool->tail; -+ u32 userinfo; -+ int i, len; -+ -+ len = xgene_enet_ring_len(buf_pool); -+ for (i = 0; i < len; i++) { -+ tail = (tail - 1) & slots; -+ raw_desc = &buf_pool->raw_desc16[tail]; -+ -+ /* Hardware stores descriptor in little endian format */ -+ userinfo = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0)); -+ dev_kfree_skb_any(buf_pool->rx_skb[userinfo]); -+ } -+ -+ iowrite32(-len, buf_pool->cmd); -+ buf_pool->tail = tail; -+} -+ -+static irqreturn_t xgene_enet_rx_irq(const int irq, void *data) -+{ -+ struct xgene_enet_desc_ring *rx_ring = data; -+ -+ if (napi_schedule_prep(&rx_ring->napi)) { -+ disable_irq_nosync(irq); -+ __napi_schedule(&rx_ring->napi); -+ } -+ -+ return IRQ_HANDLED; -+} -+ -+static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring, -+ struct xgene_enet_raw_desc *raw_desc) -+{ -+ struct sk_buff *skb; -+ struct device *dev; -+ u16 skb_index; -+ u8 status; -+ int ret = 0; -+ -+ skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0)); -+ skb = cp_ring->cp_skb[skb_index]; -+ -+ dev = ndev_to_dev(cp_ring->ndev); -+ dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)), -+ GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1)), -+ DMA_TO_DEVICE); -+ -+ /* Checking for error */ -+ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); -+ if (unlikely(status > 2)) { -+ xgene_enet_parse_error(cp_ring, netdev_priv(cp_ring->ndev), -+ status); -+ ret = -EIO; -+ } -+ -+ if (likely(skb)) { -+ dev_kfree_skb_any(skb); -+ } else { -+ netdev_err(cp_ring->ndev, "completion skb is NULL\n"); -+ ret = -EIO; -+ } -+ -+ return ret; -+} -+ -+static u64 xgene_enet_work_msg(struct sk_buff *skb) -+{ -+ struct iphdr *iph; -+ u8 l3hlen, l4hlen = 0; -+ u8 csum_enable = 0; -+ u8 proto = 0; -+ u8 ethhdr; -+ u64 hopinfo; -+ -+ if (unlikely(skb->protocol != htons(ETH_P_IP)) && -+ unlikely(skb->protocol != htons(ETH_P_8021Q))) -+ goto out; -+ -+ if (unlikely(!(skb->dev->features & NETIF_F_IP_CSUM))) -+ goto out; -+ -+ iph = ip_hdr(skb); -+ if (unlikely(ip_is_fragment(iph))) -+ goto out; -+ -+ if (likely(iph->protocol == IPPROTO_TCP)) { -+ l4hlen = tcp_hdrlen(skb) >> 2; -+ csum_enable = 1; -+ proto = TSO_IPPROTO_TCP; -+ } else if (iph->protocol == IPPROTO_UDP) { -+ l4hlen = UDP_HDR_SIZE; -+ csum_enable = 1; -+ } -+out: -+ l3hlen = ip_hdrlen(skb) >> 2; -+ ethhdr = xgene_enet_hdr_len(skb->data); -+ hopinfo = SET_VAL(TCPHDR, l4hlen) | -+ SET_VAL(IPHDR, l3hlen) | -+ SET_VAL(ETHHDR, ethhdr) | -+ SET_VAL(EC, csum_enable) | -+ SET_VAL(IS, proto) | -+ SET_BIT(IC) | -+ SET_BIT(TYPE_ETH_WORK_MESSAGE); -+ -+ return hopinfo; -+} -+ -+static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring, -+ struct sk_buff *skb) -+{ -+ struct device *dev = ndev_to_dev(tx_ring->ndev); -+ struct xgene_enet_raw_desc *raw_desc; -+ dma_addr_t dma_addr; -+ u16 tail = tx_ring->tail; -+ u64 hopinfo; -+ -+ raw_desc = &tx_ring->raw_desc[tail]; -+ memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc)); -+ -+ dma_addr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, dma_addr)) { -+ netdev_err(tx_ring->ndev, "DMA mapping error\n"); -+ return -EINVAL; -+ } -+ -+ /* Hardware expects descriptor in little endian format */ -+ raw_desc->m0 = cpu_to_le64(tail); -+ raw_desc->m1 = cpu_to_le64(SET_VAL(DATAADDR, dma_addr) | -+ SET_VAL(BUFDATALEN, skb->len) | -+ SET_BIT(COHERENT)); -+ hopinfo = xgene_enet_work_msg(skb); -+ raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) | -+ hopinfo); -+ tx_ring->cp_ring->cp_skb[tail] = skb; -+ -+ return 0; -+} -+ -+static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb, -+ struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct xgene_enet_desc_ring *tx_ring = pdata->tx_ring; -+ struct xgene_enet_desc_ring *cp_ring = tx_ring->cp_ring; -+ u32 tx_level, cq_level; -+ -+ tx_level = xgene_enet_ring_len(tx_ring); -+ cq_level = xgene_enet_ring_len(cp_ring); -+ if (unlikely(tx_level > pdata->tx_qcnt_hi || -+ cq_level > pdata->cp_qcnt_hi)) { -+ netif_stop_queue(ndev); -+ return NETDEV_TX_BUSY; -+ } -+ -+ if (xgene_enet_setup_tx_desc(tx_ring, skb)) { -+ dev_kfree_skb_any(skb); -+ return NETDEV_TX_OK; -+ } -+ -+ iowrite32(1, tx_ring->cmd); -+ skb_tx_timestamp(skb); -+ tx_ring->tail = (tx_ring->tail + 1) & (tx_ring->slots - 1); -+ -+ pdata->stats.tx_packets++; -+ pdata->stats.tx_bytes += skb->len; -+ -+ return NETDEV_TX_OK; -+} -+ -+static void xgene_enet_skip_csum(struct sk_buff *skb) -+{ -+ struct iphdr *iph = ip_hdr(skb); -+ -+ if (!ip_is_fragment(iph) || -+ (iph->protocol != IPPROTO_TCP && iph->protocol != IPPROTO_UDP)) { -+ skb->ip_summed = CHECKSUM_UNNECESSARY; -+ } -+} -+ -+static int xgene_enet_rx_frame(struct xgene_enet_desc_ring *rx_ring, -+ struct xgene_enet_raw_desc *raw_desc) -+{ -+ struct net_device *ndev; -+ struct xgene_enet_pdata *pdata; -+ struct device *dev; -+ struct xgene_enet_desc_ring *buf_pool; -+ u32 datalen, skb_index; -+ struct sk_buff *skb; -+ u8 status; -+ int ret = 0; -+ -+ ndev = rx_ring->ndev; -+ pdata = netdev_priv(ndev); -+ dev = ndev_to_dev(rx_ring->ndev); -+ buf_pool = rx_ring->buf_pool; -+ -+ dma_unmap_single(dev, GET_VAL(DATAADDR, le64_to_cpu(raw_desc->m1)), -+ XGENE_ENET_MAX_MTU, DMA_FROM_DEVICE); -+ skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0)); -+ skb = buf_pool->rx_skb[skb_index]; -+ -+ /* checking for error */ -+ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0)); -+ if (unlikely(status > 2)) { -+ dev_kfree_skb_any(skb); -+ xgene_enet_parse_error(rx_ring, netdev_priv(rx_ring->ndev), -+ status); -+ pdata->stats.rx_dropped++; -+ ret = -EIO; -+ goto out; -+ } -+ -+ /* strip off CRC as HW isn't doing this */ -+ datalen = GET_VAL(BUFDATALEN, le64_to_cpu(raw_desc->m1)); -+ datalen -= 4; -+ prefetch(skb->data - NET_IP_ALIGN); -+ skb_put(skb, datalen); -+ -+ skb_checksum_none_assert(skb); -+ skb->protocol = eth_type_trans(skb, ndev); -+ if (likely((ndev->features & NETIF_F_IP_CSUM) && -+ skb->protocol == htons(ETH_P_IP))) { -+ xgene_enet_skip_csum(skb); -+ } -+ -+ pdata->stats.rx_packets++; -+ pdata->stats.rx_bytes += datalen; -+ napi_gro_receive(&rx_ring->napi, skb); -+out: -+ if (--rx_ring->nbufpool == 0) { -+ ret = xgene_enet_refill_bufpool(buf_pool, NUM_BUFPOOL); -+ rx_ring->nbufpool = NUM_BUFPOOL; -+ } -+ -+ return ret; -+} -+ -+static bool is_rx_desc(struct xgene_enet_raw_desc *raw_desc) -+{ -+ return GET_VAL(FPQNUM, le64_to_cpu(raw_desc->m0)) ? true : false; -+} -+ -+static int xgene_enet_process_ring(struct xgene_enet_desc_ring *ring, -+ int budget) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ring->ndev); -+ struct xgene_enet_raw_desc *raw_desc; -+ u16 head = ring->head; -+ u16 slots = ring->slots - 1; -+ int ret, count = 0; -+ -+ do { -+ raw_desc = &ring->raw_desc[head]; -+ if (unlikely(xgene_enet_is_desc_slot_empty(raw_desc))) -+ break; -+ -+ if (is_rx_desc(raw_desc)) -+ ret = xgene_enet_rx_frame(ring, raw_desc); -+ else -+ ret = xgene_enet_tx_completion(ring, raw_desc); -+ xgene_enet_mark_desc_slot_empty(raw_desc); -+ -+ head = (head + 1) & slots; -+ count++; -+ -+ if (ret) -+ break; -+ } while (--budget); -+ -+ if (likely(count)) { -+ iowrite32(-count, ring->cmd); -+ ring->head = head; -+ -+ if (netif_queue_stopped(ring->ndev)) { -+ if (xgene_enet_ring_len(ring) < pdata->cp_qcnt_low) -+ netif_wake_queue(ring->ndev); -+ } -+ } -+ -+ return budget; -+} -+ -+static int xgene_enet_napi(struct napi_struct *napi, const int budget) -+{ -+ struct xgene_enet_desc_ring *ring; -+ int processed; -+ -+ ring = container_of(napi, struct xgene_enet_desc_ring, napi); -+ processed = xgene_enet_process_ring(ring, budget); -+ -+ if (processed != budget) { -+ napi_complete(napi); -+ enable_irq(ring->irq); -+ } -+ -+ return processed; -+} -+ -+static void xgene_enet_timeout(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ -+ xgene_gmac_reset(pdata); -+} -+ -+static int xgene_enet_register_irq(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct device *dev = ndev_to_dev(ndev); -+ int ret; -+ -+ ret = devm_request_irq(dev, pdata->rx_ring->irq, xgene_enet_rx_irq, -+ IRQF_SHARED, ndev->name, pdata->rx_ring); -+ if (ret) { -+ netdev_err(ndev, "rx%d interrupt request failed\n", -+ pdata->rx_ring->irq); -+ } -+ -+ return ret; -+} -+ -+static void xgene_enet_free_irq(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata; -+ struct device *dev; -+ -+ pdata = netdev_priv(ndev); -+ dev = ndev_to_dev(ndev); -+ devm_free_irq(dev, pdata->rx_ring->irq, pdata->rx_ring); -+} -+ -+static int xgene_enet_open(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ int ret; -+ -+ xgene_gmac_tx_enable(pdata); -+ xgene_gmac_rx_enable(pdata); -+ -+ ret = xgene_enet_register_irq(ndev); -+ if (ret) -+ return ret; -+ napi_enable(&pdata->rx_ring->napi); -+ -+ if (pdata->phy_dev) -+ phy_start(pdata->phy_dev); -+ -+ netif_start_queue(ndev); -+ -+ return ret; -+} -+ -+static int xgene_enet_close(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ -+ netif_stop_queue(ndev); -+ -+ if (pdata->phy_dev) -+ phy_stop(pdata->phy_dev); -+ -+ napi_disable(&pdata->rx_ring->napi); -+ xgene_enet_free_irq(ndev); -+ xgene_enet_process_ring(pdata->rx_ring, -1); -+ -+ xgene_gmac_tx_disable(pdata); -+ xgene_gmac_rx_disable(pdata); -+ -+ return 0; -+} -+ -+static void xgene_enet_delete_ring(struct xgene_enet_desc_ring *ring) -+{ -+ struct xgene_enet_pdata *pdata; -+ struct device *dev; -+ -+ pdata = netdev_priv(ring->ndev); -+ dev = ndev_to_dev(ring->ndev); -+ -+ xgene_enet_clear_ring(ring); -+ dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma); -+} -+ -+static void xgene_enet_delete_desc_rings(struct xgene_enet_pdata *pdata) -+{ -+ struct xgene_enet_desc_ring *buf_pool; -+ -+ if (pdata->tx_ring) { -+ xgene_enet_delete_ring(pdata->tx_ring); -+ pdata->tx_ring = NULL; -+ } -+ -+ if (pdata->rx_ring) { -+ buf_pool = pdata->rx_ring->buf_pool; -+ xgene_enet_delete_bufpool(buf_pool); -+ xgene_enet_delete_ring(buf_pool); -+ xgene_enet_delete_ring(pdata->rx_ring); -+ pdata->rx_ring = NULL; -+ } -+} -+ -+static int xgene_enet_get_ring_size(struct device *dev, -+ enum xgene_enet_ring_cfgsize cfgsize) -+{ -+ int size = -EINVAL; -+ -+ switch (cfgsize) { -+ case RING_CFGSIZE_512B: -+ size = 0x200; -+ break; -+ case RING_CFGSIZE_2KB: -+ size = 0x800; -+ break; -+ case RING_CFGSIZE_16KB: -+ size = 0x4000; -+ break; -+ case RING_CFGSIZE_64KB: -+ size = 0x10000; -+ break; -+ case RING_CFGSIZE_512KB: -+ size = 0x80000; -+ break; -+ default: -+ dev_err(dev, "Unsupported cfg ring size %d\n", cfgsize); -+ break; -+ } -+ -+ return size; -+} -+ -+static void xgene_enet_free_desc_ring(struct xgene_enet_desc_ring *ring) -+{ -+ struct device *dev; -+ -+ if (!ring) -+ return; -+ -+ dev = ndev_to_dev(ring->ndev); -+ -+ if (ring->desc_addr) { -+ xgene_enet_clear_ring(ring); -+ dma_free_coherent(dev, ring->size, ring->desc_addr, ring->dma); -+ } -+ devm_kfree(dev, ring); -+} -+ -+static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata) -+{ -+ struct device *dev = &pdata->pdev->dev; -+ struct xgene_enet_desc_ring *ring; -+ -+ ring = pdata->tx_ring; -+ if (ring && ring->cp_ring && ring->cp_ring->cp_skb) -+ devm_kfree(dev, ring->cp_ring->cp_skb); -+ xgene_enet_free_desc_ring(ring); -+ -+ ring = pdata->rx_ring; -+ if (ring && ring->buf_pool && ring->buf_pool->rx_skb) -+ devm_kfree(dev, ring->buf_pool->rx_skb); -+ xgene_enet_free_desc_ring(ring->buf_pool); -+ xgene_enet_free_desc_ring(ring); -+} -+ -+static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( -+ struct net_device *ndev, u32 ring_num, -+ enum xgene_enet_ring_cfgsize cfgsize, u32 ring_id) -+{ -+ struct xgene_enet_desc_ring *ring; -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct device *dev = ndev_to_dev(ndev); -+ u32 size; -+ -+ ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring), -+ GFP_KERNEL); -+ if (!ring) -+ return NULL; -+ -+ ring->ndev = ndev; -+ ring->num = ring_num; -+ ring->cfgsize = cfgsize; -+ ring->id = ring_id; -+ -+ size = xgene_enet_get_ring_size(dev, cfgsize); -+ ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma, -+ GFP_KERNEL); -+ if (!ring->desc_addr) { -+ devm_kfree(dev, ring); -+ return NULL; -+ } -+ ring->size = size; -+ -+ ring->cmd_base = pdata->ring_cmd_addr + (ring->num << 6); -+ ring->cmd = ring->cmd_base + INC_DEC_CMD_ADDR; -+ pdata->rm = RM3; -+ ring = xgene_enet_setup_ring(ring); -+ netdev_dbg(ndev, "ring info: num=%d size=%d id=%d slots=%d\n", -+ ring->num, ring->size, ring->id, ring->slots); -+ -+ return ring; -+} -+ -+static u16 xgene_enet_get_ring_id(enum xgene_ring_owner owner, u8 bufnum) -+{ -+ return (owner << 6) | (bufnum & GENMASK(5, 0)); -+} -+ -+static int xgene_enet_create_desc_rings(struct net_device *ndev) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct device *dev = ndev_to_dev(ndev); -+ struct xgene_enet_desc_ring *rx_ring, *tx_ring, *cp_ring; -+ struct xgene_enet_desc_ring *buf_pool = NULL; -+ u8 cpu_bufnum = 0, eth_bufnum = 0; -+ u8 bp_bufnum = 0x20; -+ u16 ring_id, ring_num = 0; -+ int ret; -+ -+ /* allocate rx descriptor ring */ -+ ring_id = xgene_enet_get_ring_id(RING_OWNER_CPU, cpu_bufnum++); -+ rx_ring = xgene_enet_create_desc_ring(ndev, ring_num++, -+ RING_CFGSIZE_16KB, ring_id); -+ if (!rx_ring) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ /* allocate buffer pool for receiving packets */ -+ ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, bp_bufnum++); -+ buf_pool = xgene_enet_create_desc_ring(ndev, ring_num++, -+ RING_CFGSIZE_2KB, ring_id); -+ if (!buf_pool) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ rx_ring->nbufpool = NUM_BUFPOOL; -+ rx_ring->buf_pool = buf_pool; -+ rx_ring->irq = pdata->rx_irq; -+ buf_pool->rx_skb = devm_kcalloc(dev, buf_pool->slots, -+ sizeof(struct sk_buff *), GFP_KERNEL); -+ if (!buf_pool->rx_skb) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ -+ buf_pool->dst_ring_num = xgene_enet_dst_ring_num(buf_pool); -+ rx_ring->buf_pool = buf_pool; -+ pdata->rx_ring = rx_ring; -+ -+ /* allocate tx descriptor ring */ -+ ring_id = xgene_enet_get_ring_id(RING_OWNER_ETH0, eth_bufnum++); -+ tx_ring = xgene_enet_create_desc_ring(ndev, ring_num++, -+ RING_CFGSIZE_16KB, ring_id); -+ if (!tx_ring) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ pdata->tx_ring = tx_ring; -+ -+ cp_ring = pdata->rx_ring; -+ cp_ring->cp_skb = devm_kcalloc(dev, tx_ring->slots, -+ sizeof(struct sk_buff *), GFP_KERNEL); -+ if (!cp_ring->cp_skb) { -+ ret = -ENOMEM; -+ goto err; -+ } -+ pdata->tx_ring->cp_ring = cp_ring; -+ pdata->tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring); -+ -+ pdata->tx_qcnt_hi = pdata->tx_ring->slots / 2; -+ pdata->cp_qcnt_hi = pdata->rx_ring->slots / 2; -+ pdata->cp_qcnt_low = pdata->cp_qcnt_hi / 2; -+ -+ return 0; -+ -+err: -+ xgene_enet_free_desc_rings(pdata); -+ return ret; -+} -+ -+static struct rtnl_link_stats64 *xgene_enet_get_stats64( -+ struct net_device *ndev, -+ struct rtnl_link_stats64 *storage) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ struct rtnl_link_stats64 *stats = &pdata->stats; -+ -+ stats->rx_errors += stats->rx_length_errors + -+ stats->rx_crc_errors + -+ stats->rx_frame_errors + -+ stats->rx_fifo_errors; -+ memcpy(storage, &pdata->stats, sizeof(struct rtnl_link_stats64)); -+ -+ return storage; -+} -+ -+static int xgene_enet_set_mac_address(struct net_device *ndev, void *addr) -+{ -+ struct xgene_enet_pdata *pdata = netdev_priv(ndev); -+ int ret; -+ -+ ret = eth_mac_addr(ndev, addr); -+ if (ret) -+ return ret; -+ xgene_gmac_set_mac_addr(pdata); -+ -+ return ret; -+} -+ -+static const struct net_device_ops xgene_ndev_ops = { -+ .ndo_open = xgene_enet_open, -+ .ndo_stop = xgene_enet_close, -+ .ndo_start_xmit = xgene_enet_start_xmit, -+ .ndo_tx_timeout = xgene_enet_timeout, -+ .ndo_get_stats64 = xgene_enet_get_stats64, -+ .ndo_change_mtu = eth_change_mtu, -+ .ndo_set_mac_address = xgene_enet_set_mac_address, -+}; -+ -+static int xgene_enet_get_resources(struct xgene_enet_pdata *pdata) -+{ -+ struct platform_device *pdev; -+ struct net_device *ndev; -+ struct device *dev; -+ struct resource *res; -+ void __iomem *base_addr; -+ const char *mac; -+ int ret; -+ -+ pdev = pdata->pdev; -+ dev = &pdev->dev; -+ ndev = pdata->ndev; -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "enet_csr"); -+ if (!res) { -+ dev_err(dev, "Resource enet_csr not defined\n"); -+ return -ENODEV; -+ } -+ pdata->base_addr = devm_ioremap_resource(dev, res); -+ if (IS_ERR(pdata->base_addr)) { -+ dev_err(dev, "Unable to retrieve ENET Port CSR region\n"); -+ return PTR_ERR(pdata->base_addr); -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_csr"); -+ if (!res) { -+ dev_err(dev, "Resource ring_csr not defined\n"); -+ return -ENODEV; -+ } -+ pdata->ring_csr_addr = devm_ioremap_resource(dev, res); -+ if (IS_ERR(pdata->ring_csr_addr)) { -+ dev_err(dev, "Unable to retrieve ENET Ring CSR region\n"); -+ return PTR_ERR(pdata->ring_csr_addr); -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ring_cmd"); -+ if (!res) { -+ dev_err(dev, "Resource ring_cmd not defined\n"); -+ return -ENODEV; -+ } -+ pdata->ring_cmd_addr = devm_ioremap_resource(dev, res); -+ if (IS_ERR(pdata->ring_cmd_addr)) { -+ dev_err(dev, "Unable to retrieve ENET Ring command region\n"); -+ return PTR_ERR(pdata->ring_cmd_addr); -+ } -+ -+ ret = platform_get_irq(pdev, 0); -+ if (ret <= 0) { -+ dev_err(dev, "Unable to get ENET Rx IRQ\n"); -+ ret = ret ? : -ENXIO; -+ return ret; -+ } -+ pdata->rx_irq = ret; -+ -+ mac = of_get_mac_address(dev->of_node); -+ if (mac) -+ memcpy(ndev->dev_addr, mac, ndev->addr_len); -+ else -+ eth_hw_addr_random(ndev); -+ memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); -+ -+ pdata->phy_mode = of_get_phy_mode(pdev->dev.of_node); -+ if (pdata->phy_mode < 0) { -+ dev_err(dev, "Incorrect phy-connection-type in DTS\n"); -+ return -EINVAL; -+ } -+ -+ pdata->clk = devm_clk_get(&pdev->dev, NULL); -+ ret = IS_ERR(pdata->clk); -+ if (IS_ERR(pdata->clk)) { -+ dev_err(&pdev->dev, "can't get clock\n"); -+ ret = PTR_ERR(pdata->clk); -+ return ret; -+ } -+ -+ base_addr = pdata->base_addr; -+ pdata->eth_csr_addr = base_addr + BLOCK_ETH_CSR_OFFSET; -+ pdata->eth_ring_if_addr = base_addr + BLOCK_ETH_RING_IF_OFFSET; -+ pdata->eth_diag_csr_addr = base_addr + BLOCK_ETH_DIAG_CSR_OFFSET; -+ pdata->mcx_mac_addr = base_addr + BLOCK_ETH_MAC_OFFSET; -+ pdata->mcx_stats_addr = base_addr + BLOCK_ETH_STATS_OFFSET; -+ pdata->mcx_mac_csr_addr = base_addr + BLOCK_ETH_MAC_CSR_OFFSET; -+ pdata->rx_buff_cnt = NUM_PKT_BUF; -+ -+ return ret; -+} -+ -+static int xgene_enet_init_hw(struct xgene_enet_pdata *pdata) -+{ -+ struct net_device *ndev = pdata->ndev; -+ struct xgene_enet_desc_ring *buf_pool; -+ u16 dst_ring_num; -+ int ret; -+ -+ xgene_gmac_tx_disable(pdata); -+ xgene_gmac_rx_disable(pdata); -+ -+ ret = xgene_enet_create_desc_rings(ndev); -+ if (ret) { -+ netdev_err(ndev, "Error in ring configuration\n"); -+ return ret; -+ } -+ -+ /* setup buffer pool */ -+ buf_pool = pdata->rx_ring->buf_pool; -+ xgene_enet_init_bufpool(buf_pool); -+ ret = xgene_enet_refill_bufpool(buf_pool, pdata->rx_buff_cnt); -+ if (ret) { -+ xgene_enet_delete_desc_rings(pdata); -+ return ret; -+ } -+ -+ dst_ring_num = xgene_enet_dst_ring_num(pdata->rx_ring); -+ xgene_enet_cle_bypass(pdata, dst_ring_num, buf_pool->id); -+ -+ return ret; -+} -+ -+static int xgene_enet_probe(struct platform_device *pdev) -+{ -+ struct net_device *ndev; -+ struct xgene_enet_pdata *pdata; -+ struct device *dev = &pdev->dev; -+ struct napi_struct *napi; -+ int ret; -+ -+ ndev = alloc_etherdev(sizeof(struct xgene_enet_pdata)); -+ if (!ndev) -+ return -ENOMEM; -+ -+ pdata = netdev_priv(ndev); -+ -+ pdata->pdev = pdev; -+ pdata->ndev = ndev; -+ SET_NETDEV_DEV(ndev, dev); -+ platform_set_drvdata(pdev, pdata); -+ ndev->netdev_ops = &xgene_ndev_ops; -+ xgene_enet_set_ethtool_ops(ndev); -+ ndev->features |= NETIF_F_IP_CSUM | -+ NETIF_F_GSO | -+ NETIF_F_GRO; -+ -+ ret = xgene_enet_get_resources(pdata); -+ if (ret) -+ goto err; -+ -+ xgene_enet_reset(pdata); -+ xgene_gmac_init(pdata, SPEED_1000); -+ -+ ret = register_netdev(ndev); -+ if (ret) { -+ netdev_err(ndev, "Failed to register netdev\n"); -+ goto err; -+ } -+ -+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); -+ if (ret) { -+ netdev_err(ndev, "No usable DMA configuration\n"); -+ goto err; -+ } -+ -+ ret = xgene_enet_init_hw(pdata); -+ if (ret) -+ goto err; -+ -+ napi = &pdata->rx_ring->napi; -+ netif_napi_add(ndev, napi, xgene_enet_napi, NAPI_POLL_WEIGHT); -+ ret = xgene_enet_mdio_config(pdata); -+ -+ return ret; -+err: -+ free_netdev(ndev); -+ return ret; -+} -+ -+static int xgene_enet_remove(struct platform_device *pdev) -+{ -+ struct xgene_enet_pdata *pdata; -+ struct net_device *ndev; -+ -+ pdata = platform_get_drvdata(pdev); -+ ndev = pdata->ndev; -+ -+ xgene_gmac_rx_disable(pdata); -+ xgene_gmac_tx_disable(pdata); -+ -+ netif_napi_del(&pdata->rx_ring->napi); -+ xgene_enet_mdio_remove(pdata); -+ xgene_enet_delete_desc_rings(pdata); -+ unregister_netdev(ndev); -+ xgene_gport_shutdown(pdata); -+ free_netdev(ndev); -+ -+ return 0; -+} -+ -+static struct of_device_id xgene_enet_match[] = { -+ {.compatible = "apm,xgene-enet",}, -+ {}, -+}; -+ -+MODULE_DEVICE_TABLE(of, xgene_enet_match); -+ -+static struct platform_driver xgene_enet_driver = { -+ .driver = { -+ .name = "xgene-enet", -+ .of_match_table = xgene_enet_match, -+ }, -+ .probe = xgene_enet_probe, -+ .remove = xgene_enet_remove, -+}; -+ -+module_platform_driver(xgene_enet_driver); -+ -+MODULE_DESCRIPTION("APM X-Gene SoC Ethernet driver"); -+MODULE_VERSION(XGENE_DRV_VERSION); -+MODULE_AUTHOR("Keyur Chudgar "); -+MODULE_LICENSE("GPL"); -diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h -new file mode 100644 -index 0000000..0815866 ---- /dev/null -+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h -@@ -0,0 +1,135 @@ -+/* Applied Micro X-Gene SoC Ethernet Driver -+ * -+ * Copyright (c) 2014, Applied Micro Circuits Corporation -+ * Authors: Iyappan Subramanian -+ * Ravi Patel -+ * Keyur Chudgar -+ * -+ * 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, see . -+ */ -+ -+#ifndef __XGENE_ENET_MAIN_H__ -+#define __XGENE_ENET_MAIN_H__ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "xgene_enet_hw.h" -+ -+#define XGENE_DRV_VERSION "v1.0" -+#define XGENE_ENET_MAX_MTU 1536 -+#define SKB_BUFFER_SIZE (XGENE_ENET_MAX_MTU - NET_IP_ALIGN) -+#define NUM_PKT_BUF 64 -+#define NUM_BUFPOOL 32 -+ -+/* software context of a descriptor ring */ -+struct xgene_enet_desc_ring { -+ struct net_device *ndev; -+ u16 id; -+ u16 num; -+ u16 head; -+ u16 tail; -+ u16 slots; -+ u16 irq; -+ u32 size; -+ u32 state[NUM_RING_CONFIG]; -+ void __iomem *cmd_base; -+ void __iomem *cmd; -+ dma_addr_t dma; -+ u16 dst_ring_num; -+ u8 nbufpool; -+ struct sk_buff *(*rx_skb); -+ struct sk_buff *(*cp_skb); -+ enum xgene_enet_ring_cfgsize cfgsize; -+ struct xgene_enet_desc_ring *cp_ring; -+ struct xgene_enet_desc_ring *buf_pool; -+ struct napi_struct napi; -+ union { -+ void *desc_addr; -+ struct xgene_enet_raw_desc *raw_desc; -+ struct xgene_enet_raw_desc16 *raw_desc16; -+ }; -+}; -+ -+/* ethernet private data */ -+struct xgene_enet_pdata { -+ struct net_device *ndev; -+ struct mii_bus *mdio_bus; -+ struct phy_device *phy_dev; -+ int phy_speed; -+ struct clk *clk; -+ struct platform_device *pdev; -+ struct xgene_enet_desc_ring *tx_ring; -+ struct xgene_enet_desc_ring *rx_ring; -+ char *dev_name; -+ u32 rx_buff_cnt; -+ u32 tx_qcnt_hi; -+ u32 cp_qcnt_hi; -+ u32 cp_qcnt_low; -+ u32 rx_irq; -+ void __iomem *eth_csr_addr; -+ void __iomem *eth_ring_if_addr; -+ void __iomem *eth_diag_csr_addr; -+ void __iomem *mcx_mac_addr; -+ void __iomem *mcx_stats_addr; -+ void __iomem *mcx_mac_csr_addr; -+ void __iomem *base_addr; -+ void __iomem *ring_csr_addr; -+ void __iomem *ring_cmd_addr; -+ u32 phy_addr; -+ int phy_mode; -+ u32 speed; -+ u16 rm; -+ struct rtnl_link_stats64 stats; -+}; -+ -+/* Set the specified value into a bit-field defined by its starting position -+ * and length within a single u64. -+ */ -+static inline u64 xgene_enet_set_field_value(int pos, int len, u64 val) -+{ -+ return (val & ((1ULL << len) - 1)) << pos; -+} -+ -+#define SET_VAL(field, val) \ -+ xgene_enet_set_field_value(field ## _POS, field ## _LEN, val) -+ -+#define SET_BIT(field) \ -+ xgene_enet_set_field_value(field ## _POS, 1, 1) -+ -+/* Get the value from a bit-field defined by its starting position -+ * and length within the specified u64. -+ */ -+static inline u64 xgene_enet_get_field_value(int pos, int len, u64 src) -+{ -+ return (src >> pos) & ((1ULL << len) - 1); -+} -+ -+#define GET_VAL(field, src) \ -+ xgene_enet_get_field_value(field ## _POS, field ## _LEN, src) -+ -+static inline struct device *ndev_to_dev(struct net_device *ndev) -+{ -+ return ndev->dev.parent; -+} -+ -+void xgene_enet_set_ethtool_ops(struct net_device *netdev); -+ -+#endif /* __XGENE_ENET_MAIN_H__ */ --- -1.7.10.4 - diff --git a/debian/patches/features/arm64/dts-Add-bindings-for-APM-X-Gene-SoC-ethernet-driver.patch b/debian/patches/features/arm64/dts-Add-bindings-for-APM-X-Gene-SoC-ethernet-driver.patch deleted file mode 100644 index 69d884725..000000000 --- a/debian/patches/features/arm64/dts-Add-bindings-for-APM-X-Gene-SoC-ethernet-driver.patch +++ /dev/null @@ -1,83 +0,0 @@ -From ad56b94346519e510355624dc2f88a11ee0fe07a Mon Sep 17 00:00:00 2001 -From: Iyappan Subramanian -Date: Thu, 7 Aug 2014 15:14:27 -0700 -Subject: [PATCH] dts: Add bindings for APM X-Gene SoC ethernet driver - -This patch adds bindings for APM X-Gene SoC ethernet driver. - -Signed-off-by: Iyappan Subramanian -Signed-off-by: Ravi Patel -Signed-off-by: Keyur Chudgar -Signed-off-by: David S. Miller ---- - arch/arm64/boot/dts/apm-mustang.dts | 4 ++++ - arch/arm64/boot/dts/apm-storm.dtsi | 30 +++++++++++++++++++++++++++--- - 2 files changed, 31 insertions(+), 3 deletions(-) - -diff --git a/arch/arm64/boot/dts/apm-mustang.dts b/arch/arm64/boot/dts/apm-mustang.dts -index 6541962..b2f5622 100644 ---- a/arch/arm64/boot/dts/apm-mustang.dts -+++ b/arch/arm64/boot/dts/apm-mustang.dts -@@ -28,3 +28,7 @@ - &serial0 { - status = "ok"; - }; -+ -+&menet { -+ status = "ok"; -+}; -diff --git a/arch/arm64/boot/dts/apm-storm.dtsi b/arch/arm64/boot/dts/apm-storm.dtsi -index 40aa96c..c0aceef 100644 ---- a/arch/arm64/boot/dts/apm-storm.dtsi -+++ b/arch/arm64/boot/dts/apm-storm.dtsi -@@ -167,14 +167,13 @@ - clock-output-names = "ethclk"; - }; - -- eth8clk: eth8clk { -+ menetclk: menetclk { - compatible = "apm,xgene-device-clock"; - #clock-cells = <1>; - clocks = <ðclk 0>; -- clock-names = "eth8clk"; - reg = <0x0 0x1702C000 0x0 0x1000>; - reg-names = "csr-reg"; -- clock-output-names = "eth8clk"; -+ clock-output-names = "menetclk"; - }; - - sataphy1clk: sataphy1clk@1f21c000 { -@@ -397,5 +396,30 @@ - #clock-cells = <1>; - clocks = <&rtcclk 0>; - }; -+ -+ menet: ethernet@17020000 { -+ compatible = "apm,xgene-enet"; -+ status = "disabled"; -+ reg = <0x0 0x17020000 0x0 0xd100>, -+ <0x0 0X17030000 0x0 0X400>, -+ <0x0 0X10000000 0x0 0X200>; -+ reg-names = "enet_csr", "ring_csr", "ring_cmd"; -+ interrupts = <0x0 0x3c 0x4>; -+ dma-coherent; -+ clocks = <&menetclk 0>; -+ local-mac-address = [00 01 73 00 00 01]; -+ phy-connection-type = "rgmii"; -+ phy-handle = <&menetphy>; -+ mdio { -+ compatible = "apm,xgene-mdio"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ menetphy: menetphy@3 { -+ compatible = "ethernet-phy-id001c.c915"; -+ reg = <0x3>; -+ }; -+ -+ }; -+ }; - }; - }; --- -1.7.10.4 - diff --git a/debian/patches/features/arm64/net-xgene-Check-negative-return-value-of-xgene_enet_.patch b/debian/patches/features/arm64/net-xgene-Check-negative-return-value-of-xgene_enet_.patch deleted file mode 100644 index 2d27c9ad6..000000000 --- a/debian/patches/features/arm64/net-xgene-Check-negative-return-value-of-xgene_enet_.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 42113901e335c5431e11e33711f5cdcc8e033955 Mon Sep 17 00:00:00 2001 -From: Tobias Klauser -Date: Thu, 14 Aug 2014 13:59:42 +0200 -Subject: [PATCH 2/4] net: xgene: Check negative return value of - xgene_enet_get_ring_size() - -xgene_enet_get_ring_size() returns a negative value in case of an error, -but its only caller in xgene_enet_create_desc_ring() currently uses the -return value directly as u32. Instead, check for a negative value first and -error out in case. Also move the call to xgene_enet_get_ring_size() before -devm_kzalloc() so we don't need to free anything in the error path. - -This fixes the following issue reported by the Coverity Scanner: - -** CID 1231336: Improper use of negative value (NEGATIVE_RETURNS) -/drivers/net/ethernet/apm/xgene/xgene_enet_main.c: 596 in xgene_enet_create_desc_ring() - -Signed-off-by: Tobias Klauser -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -index af7c40a..e1a8f4e 100644 ---- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -@@ -581,7 +581,11 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( - struct xgene_enet_desc_ring *ring; - struct xgene_enet_pdata *pdata = netdev_priv(ndev); - struct device *dev = ndev_to_dev(ndev); -- u32 size; -+ int size; -+ -+ size = xgene_enet_get_ring_size(dev, cfgsize); -+ if (size < 0) -+ return NULL; - - ring = devm_kzalloc(dev, sizeof(struct xgene_enet_desc_ring), - GFP_KERNEL); -@@ -593,7 +597,6 @@ static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( - ring->cfgsize = cfgsize; - ring->id = ring_id; - -- size = xgene_enet_get_ring_size(dev, cfgsize); - ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma, - GFP_KERNEL); - if (!ring->desc_addr) { --- -1.7.10.4 - diff --git a/debian/patches/features/arm64/net-xgene-fix-possible-NULL-dereference-in-xgene_ene.patch b/debian/patches/features/arm64/net-xgene-fix-possible-NULL-dereference-in-xgene_ene.patch deleted file mode 100644 index 314b7defc..000000000 --- a/debian/patches/features/arm64/net-xgene-fix-possible-NULL-dereference-in-xgene_ene.patch +++ /dev/null @@ -1,56 +0,0 @@ -From c04bbc2b1df7034f463ef512c34010b71c12c257 Mon Sep 17 00:00:00 2001 -From: Iyappan Subramanian -Date: Thu, 21 Aug 2014 13:44:48 -0700 -Subject: [PATCH 3/4] net: xgene: fix possible NULL dereference in - xgene_enet_free_desc_rings() - -A NULL pointer dereference is possible for the argument ring->buf_pool -which is passed to xgene_enet_free_desc_ring(), as ring could be NULL. - -And now since NULL pointers are being checked for before the calls to -xgene_enet_free_desc_ring(), might as well take advantage of them and -not call the function if the argument would be NULL. - -Reported-by: Dan Carpenter -Signed-off-by: Iyappan Subramanian -Signed-off-by: David S. Miller ---- - drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 20 +++++++++++++------- - 1 file changed, 13 insertions(+), 7 deletions(-) - -diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -index e1a8f4e..e4222af 100644 ---- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c -@@ -563,15 +563,21 @@ static void xgene_enet_free_desc_rings(struct xgene_enet_pdata *pdata) - struct xgene_enet_desc_ring *ring; - - ring = pdata->tx_ring; -- if (ring && ring->cp_ring && ring->cp_ring->cp_skb) -- devm_kfree(dev, ring->cp_ring->cp_skb); -- xgene_enet_free_desc_ring(ring); -+ if (ring) { -+ if (ring->cp_ring && ring->cp_ring->cp_skb) -+ devm_kfree(dev, ring->cp_ring->cp_skb); -+ xgene_enet_free_desc_ring(ring); -+ } - - ring = pdata->rx_ring; -- if (ring && ring->buf_pool && ring->buf_pool->rx_skb) -- devm_kfree(dev, ring->buf_pool->rx_skb); -- xgene_enet_free_desc_ring(ring->buf_pool); -- xgene_enet_free_desc_ring(ring); -+ if (ring) { -+ if (ring->buf_pool) { -+ if (ring->buf_pool->rx_skb) -+ devm_kfree(dev, ring->buf_pool->rx_skb); -+ xgene_enet_free_desc_ring(ring->buf_pool); -+ } -+ xgene_enet_free_desc_ring(ring); -+ } - } - - static struct xgene_enet_desc_ring *xgene_enet_create_desc_ring( --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Add-Loongson-3B-support.patch b/debian/patches/features/mips/MIPS-Add-Loongson-3B-support.patch deleted file mode 100644 index 2cad36ac3..000000000 --- a/debian/patches/features/mips/MIPS-Add-Loongson-3B-support.patch +++ /dev/null @@ -1,725 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:30 +0800 -Subject: [6/8] MIPS: Add Loongson-3B support -Origin: https://git.kernel.org/linus/e7841be50fe2b8751a51a068b8cdcdcb6611e354 - -Loongson-3B is a 8-cores processor. In general it looks like there are -two Loongson-3A integrated in one chip: 8 cores are separated into two -groups (two NUMA node), each node has its own local memory. - -Of course there are some differences between one Loongson-3B and two -Loongson-3A. E.g., the base addresses of IPI registers of each node are -not the same; Loongson-3A use ChipConfig register to enable/disable -clock, but Loongson-3B use FreqControl register instead. - -There are two revision of Loongson-3B, the first revision is called as -Loongson-3B1000, whose frequency is 1GHz and has a PRid 0x6306, the -second revision is called as Loongson-3B1500, whose frequency is 1.5GHz -and has a PRid 0x6307. Both revisions has a bug that clock cannot be -disabled at runtime, but this will be fixed in future. - -Signed-off-by: Huacai Chen -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7188/ -Signed-off-by: Ralf Baechle ---- - arch/mips/include/asm/cpu.h | 2 + - arch/mips/include/asm/mach-loongson/boot_param.h | 1 + - arch/mips/include/asm/mach-loongson/loongson.h | 4 + - arch/mips/kernel/cpu-probe.c | 6 + - arch/mips/loongson/common/env.c | 31 +- - arch/mips/loongson/loongson-3/irq.c | 26 +- - arch/mips/loongson/loongson-3/smp.c | 387 ++++++++++++++++------ - arch/mips/loongson/loongson-3/smp.h | 37 ++- - 8 files changed, 372 insertions(+), 122 deletions(-) - -diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h -index 129d087..abf7e00 100644 ---- a/arch/mips/include/asm/cpu.h -+++ b/arch/mips/include/asm/cpu.h -@@ -233,6 +233,8 @@ - #define PRID_REV_LOONGSON2E 0x0002 - #define PRID_REV_LOONGSON2F 0x0003 - #define PRID_REV_LOONGSON3A 0x0005 -+#define PRID_REV_LOONGSON3B_R1 0x0006 -+#define PRID_REV_LOONGSON3B_R2 0x0007 - - /* - * Older processors used to encode processor version and revision in two -diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h -index 8b06c96..3388fc5 100644 ---- a/arch/mips/include/asm/mach-loongson/boot_param.h -+++ b/arch/mips/include/asm/mach-loongson/boot_param.h -@@ -163,4 +163,5 @@ struct loongson_system_configuration { - - extern struct efi_memory_map_loongson *loongson_memmap; - extern struct loongson_system_configuration loongson_sysconf; -+extern int cpuhotplug_workaround; - #endif -diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h -index a1c76ca..92bf76c 100644 ---- a/arch/mips/include/asm/mach-loongson/loongson.h -+++ b/arch/mips/include/asm/mach-loongson/loongson.h -@@ -255,6 +255,10 @@ static inline void do_perfcnt_IRQ(void) - extern u64 loongson_chipcfg[MAX_PACKAGES]; - #define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id])) - -+/* Freq Control register of each physical cpu package, PRid >= Loongson-3B */ -+extern u64 loongson_freqctrl[MAX_PACKAGES]; -+#define LOONGSON_FREQCTRL(id) (*(volatile u32 *)(loongson_freqctrl[id])) -+ - /* pcimap */ - - #define LOONGSON_PCIMAP_PCIMAP_LO0 0x0000003f -diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c -index d74f957..2d2e287 100644 ---- a/arch/mips/kernel/cpu-probe.c -+++ b/arch/mips/kernel/cpu-probe.c -@@ -740,6 +740,12 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) - __cpu_name[cpu] = "ICT Loongson-3"; - set_elf_platform(cpu, "loongson3a"); - break; -+ case PRID_REV_LOONGSON3B_R1: -+ case PRID_REV_LOONGSON3B_R2: -+ c->cputype = CPU_LOONGSON3; -+ __cpu_name[cpu] = "ICT Loongson-3"; -+ set_elf_platform(cpu, "loongson3b"); -+ break; - } - - set_isa(c, MIPS_CPU_ISA_III); -diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c -index 33a13b9..f152285 100644 ---- a/arch/mips/loongson/common/env.c -+++ b/arch/mips/loongson/common/env.c -@@ -28,6 +28,10 @@ struct efi_memory_map_loongson *loongson_memmap; - struct loongson_system_configuration loongson_sysconf; - - u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180}; -+u64 loongson_freqctrl[MAX_PACKAGES]; -+ -+unsigned long long smp_group[4]; -+int cpuhotplug_workaround = 0; - - #define parse_even_earlier(res, option, p) \ - do { \ -@@ -82,10 +86,32 @@ void __init prom_init_env(void) - if (ecpu->cputype == Loongson_3A) { - loongson_sysconf.cores_per_node = 4; - loongson_sysconf.cores_per_package = 4; -+ smp_group[0] = 0x900000003ff01000; -+ smp_group[1] = 0x900010003ff01000; -+ smp_group[2] = 0x900020003ff01000; -+ smp_group[3] = 0x900030003ff01000; - loongson_chipcfg[0] = 0x900000001fe00180; - loongson_chipcfg[1] = 0x900010001fe00180; - loongson_chipcfg[2] = 0x900020001fe00180; - loongson_chipcfg[3] = 0x900030001fe00180; -+ loongson_sysconf.ht_control_base = 0x90000EFDFB000000; -+ } else if (ecpu->cputype == Loongson_3B) { -+ loongson_sysconf.cores_per_node = 4; /* One chip has 2 nodes */ -+ loongson_sysconf.cores_per_package = 8; -+ smp_group[0] = 0x900000003ff01000; -+ smp_group[1] = 0x900010003ff05000; -+ smp_group[2] = 0x900020003ff09000; -+ smp_group[3] = 0x900030003ff0d000; -+ loongson_chipcfg[0] = 0x900000001fe00180; -+ loongson_chipcfg[1] = 0x900020001fe00180; -+ loongson_chipcfg[2] = 0x900040001fe00180; -+ loongson_chipcfg[3] = 0x900060001fe00180; -+ loongson_freqctrl[0] = 0x900000001fe001d0; -+ loongson_freqctrl[1] = 0x900020001fe001d0; -+ loongson_freqctrl[2] = 0x900040001fe001d0; -+ loongson_freqctrl[3] = 0x900060001fe001d0; -+ loongson_sysconf.ht_control_base = 0x90001EFDFB000000; -+ cpuhotplug_workaround = 1; - } else { - loongson_sysconf.cores_per_node = 1; - loongson_sysconf.cores_per_package = 1; -@@ -111,7 +137,6 @@ void __init prom_init_env(void) - loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown; - loongson_sysconf.suspend_addr = boot_p->reset_system.DoSuspend; - -- loongson_sysconf.ht_control_base = 0x90000EFDFB000000; - loongson_sysconf.vgabios_addr = boot_p->efi.smbios.vga_bios; - pr_debug("Shutdown Addr: %llx, Restart Addr: %llx, VBIOS Addr: %llx\n", - loongson_sysconf.poweroff_addr, loongson_sysconf.restart_addr, -@@ -129,6 +154,10 @@ void __init prom_init_env(void) - case PRID_REV_LOONGSON3A: - cpu_clock_freq = 900000000; - break; -+ case PRID_REV_LOONGSON3B_R1: -+ case PRID_REV_LOONGSON3B_R2: -+ cpu_clock_freq = 1000000000; -+ break; - default: - cpu_clock_freq = 100000000; - break; -diff --git a/arch/mips/loongson/loongson-3/irq.c b/arch/mips/loongson/loongson-3/irq.c -index f240828..ca1c62a 100644 ---- a/arch/mips/loongson/loongson-3/irq.c -+++ b/arch/mips/loongson/loongson-3/irq.c -@@ -7,6 +7,8 @@ - #include - #include - -+#include "smp.h" -+ - unsigned int ht_irq[] = {1, 3, 4, 5, 6, 7, 8, 12, 14, 15}; - - static void ht_irqdispatch(void) -@@ -53,9 +55,15 @@ static inline void mask_loongson_irq(struct irq_data *d) - /* Workaround: UART IRQ may deliver to any core */ - if (d->irq == LOONGSON_UART_IRQ) { - int cpu = smp_processor_id(); -- -- LOONGSON_INT_ROUTER_INTENCLR = 1 << 10; -- LOONGSON_INT_ROUTER_LPC = 0x10 + (1<irq == LOONGSON_UART_IRQ) { - int cpu = smp_processor_id(); -- -- LOONGSON_INT_ROUTER_INTENSET = 1 << 10; -- LOONGSON_INT_ROUTER_LPC = 0x10 + (1<irq - MIPS_CPU_IRQ_BASE)); -diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c -index ed0e2d0..74e827b 100644 ---- a/arch/mips/loongson/loongson-3/smp.c -+++ b/arch/mips/loongson/loongson-3/smp.c -@@ -31,6 +31,12 @@ - DEFINE_PER_CPU(int, cpu_state); - DEFINE_PER_CPU(uint32_t, core0_c0count); - -+static void *ipi_set0_regs[16]; -+static void *ipi_clear0_regs[16]; -+static void *ipi_status0_regs[16]; -+static void *ipi_en0_regs[16]; -+static void *ipi_mailbox_buf[16]; -+ - /* read a 32bit value from ipi register */ - #define loongson3_ipi_read32(addr) readl(addr) - /* read a 64bit value from ipi register */ -@@ -48,100 +54,185 @@ DEFINE_PER_CPU(uint32_t, core0_c0count); - __wbflush(); \ - } while (0) - --static void *ipi_set0_regs[] = { -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0), --}; -+static void ipi_set0_regs_init(void) -+{ -+ ipi_set0_regs[0] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + SET0); -+ ipi_set0_regs[1] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + SET0); -+ ipi_set0_regs[2] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + SET0); -+ ipi_set0_regs[3] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + SET0); -+ ipi_set0_regs[4] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + SET0); -+ ipi_set0_regs[5] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + SET0); -+ ipi_set0_regs[6] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + SET0); -+ ipi_set0_regs[7] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + SET0); -+ ipi_set0_regs[8] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + SET0); -+ ipi_set0_regs[9] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + SET0); -+ ipi_set0_regs[10] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + SET0); -+ ipi_set0_regs[11] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + SET0); -+ ipi_set0_regs[12] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + SET0); -+ ipi_set0_regs[13] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + SET0); -+ ipi_set0_regs[14] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + SET0); -+ ipi_set0_regs[15] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + SET0); -+} - --static void *ipi_clear0_regs[] = { -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0), --}; -+static void ipi_clear0_regs_init(void) -+{ -+ ipi_clear0_regs[0] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + CLEAR0); -+ ipi_clear0_regs[1] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + CLEAR0); -+ ipi_clear0_regs[2] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + CLEAR0); -+ ipi_clear0_regs[3] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + CLEAR0); -+ ipi_clear0_regs[4] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + CLEAR0); -+ ipi_clear0_regs[5] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + CLEAR0); -+ ipi_clear0_regs[6] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + CLEAR0); -+ ipi_clear0_regs[7] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + CLEAR0); -+ ipi_clear0_regs[8] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + CLEAR0); -+ ipi_clear0_regs[9] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + CLEAR0); -+ ipi_clear0_regs[10] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + CLEAR0); -+ ipi_clear0_regs[11] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + CLEAR0); -+ ipi_clear0_regs[12] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + CLEAR0); -+ ipi_clear0_regs[13] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + CLEAR0); -+ ipi_clear0_regs[14] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + CLEAR0); -+ ipi_clear0_regs[15] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + CLEAR0); -+} - --static void *ipi_status0_regs[] = { -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0), --}; -+static void ipi_status0_regs_init(void) -+{ -+ ipi_status0_regs[0] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + STATUS0); -+ ipi_status0_regs[1] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + STATUS0); -+ ipi_status0_regs[2] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + STATUS0); -+ ipi_status0_regs[3] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + STATUS0); -+ ipi_status0_regs[4] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + STATUS0); -+ ipi_status0_regs[5] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + STATUS0); -+ ipi_status0_regs[6] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + STATUS0); -+ ipi_status0_regs[7] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + STATUS0); -+ ipi_status0_regs[8] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + STATUS0); -+ ipi_status0_regs[9] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + STATUS0); -+ ipi_status0_regs[10] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + STATUS0); -+ ipi_status0_regs[11] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + STATUS0); -+ ipi_status0_regs[12] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + STATUS0); -+ ipi_status0_regs[13] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + STATUS0); -+ ipi_status0_regs[14] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + STATUS0); -+ ipi_status0_regs[15] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + STATUS0); -+} - --static void *ipi_en0_regs[] = { -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0), --}; -+static void ipi_en0_regs_init(void) -+{ -+ ipi_en0_regs[0] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + EN0); -+ ipi_en0_regs[1] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + EN0); -+ ipi_en0_regs[2] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + EN0); -+ ipi_en0_regs[3] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + EN0); -+ ipi_en0_regs[4] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + EN0); -+ ipi_en0_regs[5] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + EN0); -+ ipi_en0_regs[6] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + EN0); -+ ipi_en0_regs[7] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + EN0); -+ ipi_en0_regs[8] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + EN0); -+ ipi_en0_regs[9] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + EN0); -+ ipi_en0_regs[10] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + EN0); -+ ipi_en0_regs[11] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + EN0); -+ ipi_en0_regs[12] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + EN0); -+ ipi_en0_regs[13] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + EN0); -+ ipi_en0_regs[14] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + EN0); -+ ipi_en0_regs[15] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + EN0); -+} - --static void *ipi_mailbox_buf[] = { -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF), -- (void *)(SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF), --}; -+static void ipi_mailbox_buf_init(void) -+{ -+ ipi_mailbox_buf[0] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE0_OFFSET + BUF); -+ ipi_mailbox_buf[1] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE1_OFFSET + BUF); -+ ipi_mailbox_buf[2] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE2_OFFSET + BUF); -+ ipi_mailbox_buf[3] = (void *) -+ (SMP_CORE_GROUP0_BASE + SMP_CORE3_OFFSET + BUF); -+ ipi_mailbox_buf[4] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE0_OFFSET + BUF); -+ ipi_mailbox_buf[5] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE1_OFFSET + BUF); -+ ipi_mailbox_buf[6] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE2_OFFSET + BUF); -+ ipi_mailbox_buf[7] = (void *) -+ (SMP_CORE_GROUP1_BASE + SMP_CORE3_OFFSET + BUF); -+ ipi_mailbox_buf[8] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE0_OFFSET + BUF); -+ ipi_mailbox_buf[9] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE1_OFFSET + BUF); -+ ipi_mailbox_buf[10] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE2_OFFSET + BUF); -+ ipi_mailbox_buf[11] = (void *) -+ (SMP_CORE_GROUP2_BASE + SMP_CORE3_OFFSET + BUF); -+ ipi_mailbox_buf[12] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE0_OFFSET + BUF); -+ ipi_mailbox_buf[13] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE1_OFFSET + BUF); -+ ipi_mailbox_buf[14] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE2_OFFSET + BUF); -+ ipi_mailbox_buf[15] = (void *) -+ (SMP_CORE_GROUP3_BASE + SMP_CORE3_OFFSET + BUF); -+} - - /* - * Simple enough, just poke the appropriate ipi register -@@ -248,6 +339,11 @@ static void __init loongson3_smp_setup(void) - __cpu_number_map[i] = ++num; - __cpu_logical_map[num] = i; - } -+ ipi_set0_regs_init(); -+ ipi_clear0_regs_init(); -+ ipi_status0_regs_init(); -+ ipi_en0_regs_init(); -+ ipi_mailbox_buf_init(); - pr_info("Detected %i available secondary CPU(s)\n", num); - } - -@@ -315,7 +411,7 @@ static void loongson3_cpu_die(unsigned int cpu) - * flush all L1 entries at first. Then, another core (usually Core 0) can - * safely disable the clock of the target core. loongson3_play_dead() is - * called via CKSEG1 (uncached and unmmaped) */ --static void loongson3_play_dead(int *state_addr) -+static void loongson3a_play_dead(int *state_addr) - { - register int val; - register long cpuid, core, node, count; -@@ -377,6 +473,70 @@ static void loongson3_play_dead(int *state_addr) - : "a1"); - } - -+static void loongson3b_play_dead(int *state_addr) -+{ -+ register int val; -+ register long cpuid, core, node, count; -+ register void *addr, *base, *initfunc; -+ -+ __asm__ __volatile__( -+ " .set push \n" -+ " .set noreorder \n" -+ " li %[addr], 0x80000000 \n" /* KSEG0 */ -+ "1: cache 0, 0(%[addr]) \n" /* flush L1 ICache */ -+ " cache 0, 1(%[addr]) \n" -+ " cache 0, 2(%[addr]) \n" -+ " cache 0, 3(%[addr]) \n" -+ " cache 1, 0(%[addr]) \n" /* flush L1 DCache */ -+ " cache 1, 1(%[addr]) \n" -+ " cache 1, 2(%[addr]) \n" -+ " cache 1, 3(%[addr]) \n" -+ " addiu %[sets], %[sets], -1 \n" -+ " bnez %[sets], 1b \n" -+ " addiu %[addr], %[addr], 0x20 \n" -+ " li %[val], 0x7 \n" /* *state_addr = CPU_DEAD; */ -+ " sw %[val], (%[state_addr]) \n" -+ " sync \n" -+ " cache 21, (%[state_addr]) \n" /* flush entry of *state_addr */ -+ " .set pop \n" -+ : [addr] "=&r" (addr), [val] "=&r" (val) -+ : [state_addr] "r" (state_addr), -+ [sets] "r" (cpu_data[smp_processor_id()].dcache.sets)); -+ -+ __asm__ __volatile__( -+ " .set push \n" -+ " .set noreorder \n" -+ " .set mips64 \n" -+ " mfc0 %[cpuid], $15, 1 \n" -+ " andi %[cpuid], 0x3ff \n" -+ " dli %[base], 0x900000003ff01000 \n" -+ " andi %[core], %[cpuid], 0x3 \n" -+ " sll %[core], 8 \n" /* get core id */ -+ " or %[base], %[base], %[core] \n" -+ " andi %[node], %[cpuid], 0xc \n" -+ " dsll %[node], 42 \n" /* get node id */ -+ " or %[base], %[base], %[node] \n" -+ " dsrl %[node], 30 \n" /* 15:14 */ -+ " or %[base], %[base], %[node] \n" -+ "1: li %[count], 0x100 \n" /* wait for init loop */ -+ "2: bnez %[count], 2b \n" /* limit mailbox access */ -+ " addiu %[count], -1 \n" -+ " ld %[initfunc], 0x20(%[base]) \n" /* get PC via mailbox */ -+ " beqz %[initfunc], 1b \n" -+ " nop \n" -+ " ld $sp, 0x28(%[base]) \n" /* get SP via mailbox */ -+ " ld $gp, 0x30(%[base]) \n" /* get GP via mailbox */ -+ " ld $a1, 0x38(%[base]) \n" -+ " jr %[initfunc] \n" /* jump to initial PC */ -+ " nop \n" -+ " .set pop \n" -+ : [core] "=&r" (core), [node] "=&r" (node), -+ [base] "=&r" (base), [cpuid] "=&r" (cpuid), -+ [count] "=&r" (count), [initfunc] "=&r" (initfunc) -+ : /* No Input */ -+ : "a1"); -+} -+ - void play_dead(void) - { - int *state_addr; -@@ -384,31 +544,64 @@ void play_dead(void) - void (*play_dead_at_ckseg1)(int *); - - idle_task_exit(); -- play_dead_at_ckseg1 = -- (void *)CKSEG1ADDR((unsigned long)loongson3_play_dead); -+ switch (loongson_sysconf.cputype) { -+ case Loongson_3A: -+ default: -+ play_dead_at_ckseg1 = -+ (void *)CKSEG1ADDR((unsigned long)loongson3a_play_dead); -+ break; -+ case Loongson_3B: -+ play_dead_at_ckseg1 = -+ (void *)CKSEG1ADDR((unsigned long)loongson3b_play_dead); -+ break; -+ } - state_addr = &per_cpu(cpu_state, cpu); - mb(); - play_dead_at_ckseg1(state_addr); - } - -+void loongson3_disable_clock(int cpu) -+{ -+ uint64_t core_id = cpu_data[cpu].core; -+ uint64_t package_id = cpu_data[cpu].package; -+ -+ if (loongson_sysconf.cputype == Loongson_3A) { -+ LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); -+ } else if (loongson_sysconf.cputype == Loongson_3B) { -+ if (!cpuhotplug_workaround) -+ LOONGSON_FREQCTRL(package_id) &= ~(1 << (core_id * 4 + 3)); -+ } -+} -+ -+void loongson3_enable_clock(int cpu) -+{ -+ uint64_t core_id = cpu_data[cpu].core; -+ uint64_t package_id = cpu_data[cpu].package; -+ -+ if (loongson_sysconf.cputype == Loongson_3A) { -+ LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); -+ } else if (loongson_sysconf.cputype == Loongson_3B) { -+ if (!cpuhotplug_workaround) -+ LOONGSON_FREQCTRL(package_id) |= 1 << (core_id * 4 + 3); -+ } -+} -+ - #define CPU_POST_DEAD_FROZEN (CPU_POST_DEAD | CPU_TASKS_FROZEN) - static int loongson3_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) - { - unsigned int cpu = (unsigned long)hcpu; -- uint64_t core_id = cpu_data[cpu].core; -- uint64_t package_id = cpu_data[cpu].package; - - switch (action) { - case CPU_POST_DEAD: - case CPU_POST_DEAD_FROZEN: - pr_info("Disable clock for CPU#%d\n", cpu); -- LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); -+ loongson3_disable_clock(cpu); - break; - case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: - pr_info("Enable clock for CPU#%d\n", cpu); -- LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); -+ loongson3_enable_clock(cpu); - break; - } - -diff --git a/arch/mips/loongson/loongson-3/smp.h b/arch/mips/loongson/loongson-3/smp.h -index 3453e8c..d98ff65 100644 ---- a/arch/mips/loongson/loongson-3/smp.h -+++ b/arch/mips/loongson/loongson-3/smp.h -@@ -1,29 +1,30 @@ - #ifndef __LOONGSON_SMP_H_ - #define __LOONGSON_SMP_H_ - --/* for Loongson-3A smp support */ -+/* for Loongson-3 smp support */ -+extern unsigned long long smp_group[4]; - - /* 4 groups(nodes) in maximum in numa case */ --#define SMP_CORE_GROUP0_BASE 0x900000003ff01000 --#define SMP_CORE_GROUP1_BASE 0x900010003ff01000 --#define SMP_CORE_GROUP2_BASE 0x900020003ff01000 --#define SMP_CORE_GROUP3_BASE 0x900030003ff01000 -+#define SMP_CORE_GROUP0_BASE (smp_group[0]) -+#define SMP_CORE_GROUP1_BASE (smp_group[1]) -+#define SMP_CORE_GROUP2_BASE (smp_group[2]) -+#define SMP_CORE_GROUP3_BASE (smp_group[3]) - - /* 4 cores in each group(node) */ --#define SMP_CORE0_OFFSET 0x000 --#define SMP_CORE1_OFFSET 0x100 --#define SMP_CORE2_OFFSET 0x200 --#define SMP_CORE3_OFFSET 0x300 -+#define SMP_CORE0_OFFSET 0x000 -+#define SMP_CORE1_OFFSET 0x100 -+#define SMP_CORE2_OFFSET 0x200 -+#define SMP_CORE3_OFFSET 0x300 - - /* ipi registers offsets */ --#define STATUS0 0x00 --#define EN0 0x04 --#define SET0 0x08 --#define CLEAR0 0x0c --#define STATUS1 0x10 --#define MASK1 0x14 --#define SET1 0x18 --#define CLEAR1 0x1c --#define BUF 0x20 -+#define STATUS0 0x00 -+#define EN0 0x04 -+#define SET0 0x08 -+#define CLEAR0 0x0c -+#define STATUS1 0x10 -+#define MASK1 0x14 -+#define SET1 0x18 -+#define CLEAR1 0x1c -+#define BUF 0x20 - - #endif --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Add-NUMA-support-for-Loongson-3.patch b/debian/patches/features/mips/MIPS-Add-NUMA-support-for-Loongson-3.patch deleted file mode 100644 index dbaf4ace6..000000000 --- a/debian/patches/features/mips/MIPS-Add-NUMA-support-for-Loongson-3.patch +++ /dev/null @@ -1,651 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:28 +0800 -Subject: [4/8] MIPS: Add NUMA support for Loongson-3 -Origin: https://git.kernel.org/linus/c46173183657bbdbe0d54a981c28807581648422 - -Multiple Loongson-3A chips can be interconnected with HT0-bus. This is -a CC-NUMA system that every chip (node) has its own local memory and -cache coherency is maintained by hardware. The 64-bit physical memory -address format is as follows: - -0x-0000-YZZZ-ZZZZ-ZZZZ - -The high 16 bits should be 0, which means the real physical address -supported by Loongson-3 is 48-bit. The "Y" bits is the base address of -each node, which can be also considered as the node-id. The "Z" bits is -the address offset within a node, which means every node has a 44 bits -address space. - -Macros XPHYSADDR and MAX_PHYSMEM_BITS are modified unconditionally, -because many other MIPS CPUs have also extended their address spaces. - -Signed-off-by: Huacai Chen -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7187/ -Signed-off-by: Ralf Baechle ---- - arch/mips/include/asm/addrspace.h | 2 +- - arch/mips/include/asm/mach-loongson/boot_param.h | 3 + - .../include/asm/mach-loongson/kernel-entry-init.h | 52 ++++ - arch/mips/include/asm/mach-loongson/mmzone.h | 53 ++++ - arch/mips/include/asm/mach-loongson/topology.h | 23 ++ - arch/mips/include/asm/sparsemem.h | 2 +- - arch/mips/kernel/setup.c | 2 +- - arch/mips/loongson/Kconfig | 1 + - arch/mips/loongson/common/env.c | 7 + - arch/mips/loongson/common/init.c | 4 + - arch/mips/loongson/loongson-3/Makefile | 2 + - arch/mips/loongson/loongson-3/numa.c | 291 ++++++++++++++++++++ - arch/mips/loongson/loongson-3/smp.c | 8 +- - 13 files changed, 445 insertions(+), 5 deletions(-) - create mode 100644 arch/mips/include/asm/mach-loongson/kernel-entry-init.h - create mode 100644 arch/mips/include/asm/mach-loongson/mmzone.h - create mode 100644 arch/mips/include/asm/mach-loongson/topology.h - create mode 100644 arch/mips/loongson/loongson-3/numa.c - -diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h -index 3f74545..3b0e51d 100644 ---- a/arch/mips/include/asm/addrspace.h -+++ b/arch/mips/include/asm/addrspace.h -@@ -52,7 +52,7 @@ - */ - #define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) - #define XPHYSADDR(a) ((_ACAST64_(a)) & \ -- _CONST64_(0x000000ffffffffff)) -+ _CONST64_(0x0000ffffffffffff)) - - #ifdef CONFIG_64BIT - -diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h -index 829a7ec..8b06c96 100644 ---- a/arch/mips/include/asm/mach-loongson/boot_param.h -+++ b/arch/mips/include/asm/mach-loongson/boot_param.h -@@ -146,6 +146,9 @@ struct boot_params { - - struct loongson_system_configuration { - u32 nr_cpus; -+ u32 nr_nodes; -+ int cores_per_node; -+ int cores_per_package; - enum loongson_cpu_type cputype; - u64 ht_control_base; - u64 pci_mem_start_addr; -diff --git a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h -new file mode 100644 -index 0000000..df5fca8 ---- /dev/null -+++ b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h -@@ -0,0 +1,52 @@ -+/* -+ * 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. -+ * -+ * Copyright (C) 2005 Embedded Alley Solutions, Inc -+ * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org) -+ * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn) -+ * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com) -+ */ -+#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H -+#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H -+ -+/* -+ * Override macros used in arch/mips/kernel/head.S. -+ */ -+ .macro kernel_entry_setup -+#ifdef CONFIG_CPU_LOONGSON3 -+ .set push -+ .set mips64 -+ /* Set LPA on LOONGSON3 config3 */ -+ mfc0 t0, $16, 3 -+ or t0, (0x1 << 7) -+ mtc0 t0, $16, 3 -+ /* Set ELPA on LOONGSON3 pagegrain */ -+ li t0, (0x1 << 29) -+ mtc0 t0, $5, 1 -+ _ehb -+ .set pop -+#endif -+ .endm -+ -+/* -+ * Do SMP slave processor setup. -+ */ -+ .macro smp_slave_setup -+#ifdef CONFIG_CPU_LOONGSON3 -+ .set push -+ .set mips64 -+ /* Set LPA on LOONGSON3 config3 */ -+ mfc0 t0, $16, 3 -+ or t0, (0x1 << 7) -+ mtc0 t0, $16, 3 -+ /* Set ELPA on LOONGSON3 pagegrain */ -+ li t0, (0x1 << 29) -+ mtc0 t0, $5, 1 -+ _ehb -+ .set pop -+#endif -+ .endm -+ -+#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */ -diff --git a/arch/mips/include/asm/mach-loongson/mmzone.h b/arch/mips/include/asm/mach-loongson/mmzone.h -new file mode 100644 -index 0000000..37c08a2 ---- /dev/null -+++ b/arch/mips/include/asm/mach-loongson/mmzone.h -@@ -0,0 +1,53 @@ -+/* -+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & -+ * Insititute of Computing Technology -+ * Author: Xiang Gao, gaoxiang@ict.ac.cn -+ * Huacai Chen, chenhc@lemote.com -+ * Xiaofu Meng, Shuangshuang Zhang -+ * -+ * 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. -+ */ -+#ifndef _ASM_MACH_MMZONE_H -+#define _ASM_MACH_MMZONE_H -+ -+#include -+#define NODE_ADDRSPACE_SHIFT 44 -+#define NODE0_ADDRSPACE_OFFSET 0x000000000000UL -+#define NODE1_ADDRSPACE_OFFSET 0x100000000000UL -+#define NODE2_ADDRSPACE_OFFSET 0x200000000000UL -+#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL -+ -+#define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT) -+ -+#define LEVELS_PER_SLICE 128 -+ -+struct slice_data { -+ unsigned long irq_enable_mask[2]; -+ int level_to_irq[LEVELS_PER_SLICE]; -+}; -+ -+struct hub_data { -+ cpumask_t h_cpus; -+ unsigned long slice_map; -+ unsigned long irq_alloc_mask[2]; -+ struct slice_data slice[2]; -+}; -+ -+struct node_data { -+ struct pglist_data pglist; -+ struct hub_data hub; -+ cpumask_t cpumask; -+}; -+ -+extern struct node_data *__node_data[]; -+ -+#define NODE_DATA(n) (&__node_data[(n)]->pglist) -+#define hub_data(n) (&__node_data[(n)]->hub) -+ -+extern void setup_zero_pages(void); -+extern void __init prom_init_numa_memory(void); -+ -+#endif /* _ASM_MACH_MMZONE_H */ -diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h -new file mode 100644 -index 0000000..5598ba7 ---- /dev/null -+++ b/arch/mips/include/asm/mach-loongson/topology.h -@@ -0,0 +1,23 @@ -+#ifndef _ASM_MACH_TOPOLOGY_H -+#define _ASM_MACH_TOPOLOGY_H -+ -+#ifdef CONFIG_NUMA -+ -+#define cpu_to_node(cpu) ((cpu) >> 2) -+#define parent_node(node) (node) -+#define cpumask_of_node(node) (&__node_data[(node)]->cpumask) -+ -+struct pci_bus; -+extern int pcibus_to_node(struct pci_bus *); -+ -+#define cpumask_of_pcibus(bus) (cpu_online_mask) -+ -+extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES]; -+ -+#define node_distance(from, to) (__node_distances[(from)][(to)]) -+ -+#endif -+ -+#include -+ -+#endif /* _ASM_MACH_TOPOLOGY_H */ -diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h -index d2da53c..b1071c1 100644 ---- a/arch/mips/include/asm/sparsemem.h -+++ b/arch/mips/include/asm/sparsemem.h -@@ -11,7 +11,7 @@ - #else - # define SECTION_SIZE_BITS 28 - #endif --#define MAX_PHYSMEM_BITS 35 -+#define MAX_PHYSMEM_BITS 48 - - #endif /* CONFIG_SPARSEMEM */ - #endif /* _MIPS_SPARSEMEM_H */ -diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c -index 2f01201..7c1fe2b 100644 ---- a/arch/mips/kernel/setup.c -+++ b/arch/mips/kernel/setup.c -@@ -282,7 +282,7 @@ static unsigned long __init init_initrd(void) - * Initialize the bootmem allocator. It also setup initrd related data - * if needed. - */ --#ifdef CONFIG_SGI_IP27 -+#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA)) - - static void __init bootmem_init(void) - { -diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig -index e6a86cc..a14a50d 100644 ---- a/arch/mips/loongson/Kconfig -+++ b/arch/mips/loongson/Kconfig -@@ -79,6 +79,7 @@ config LEMOTE_MACH3A - select SYS_HAS_EARLY_PRINTK - select SYS_SUPPORTS_SMP - select SYS_SUPPORTS_HOTPLUG_CPU -+ select SYS_SUPPORTS_NUMA - select SYS_SUPPORTS_64BIT_KERNEL - select SYS_SUPPORTS_HIGHMEM - select SYS_SUPPORTS_LITTLE_ENDIAN -diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c -index dc59241..33a13b9 100644 ---- a/arch/mips/loongson/common/env.c -+++ b/arch/mips/loongson/common/env.c -@@ -80,17 +80,24 @@ void __init prom_init_env(void) - cpu_clock_freq = ecpu->cpu_clock_freq; - loongson_sysconf.cputype = ecpu->cputype; - if (ecpu->cputype == Loongson_3A) { -+ loongson_sysconf.cores_per_node = 4; -+ loongson_sysconf.cores_per_package = 4; - loongson_chipcfg[0] = 0x900000001fe00180; - loongson_chipcfg[1] = 0x900010001fe00180; - loongson_chipcfg[2] = 0x900020001fe00180; - loongson_chipcfg[3] = 0x900030001fe00180; - } else { -+ loongson_sysconf.cores_per_node = 1; -+ loongson_sysconf.cores_per_package = 1; - loongson_chipcfg[0] = 0x900000001fe00180; - } - - loongson_sysconf.nr_cpus = ecpu->nr_cpus; - if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0) - loongson_sysconf.nr_cpus = NR_CPUS; -+ loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus + -+ loongson_sysconf.cores_per_node - 1) / -+ loongson_sysconf.cores_per_node; - - loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr; - loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr; -diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c -index f37fe54..f6af3ab 100644 ---- a/arch/mips/loongson/common/init.c -+++ b/arch/mips/loongson/common/init.c -@@ -30,7 +30,11 @@ void __init prom_init(void) - set_io_port_base((unsigned long) - ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE)); - -+#ifdef CONFIG_NUMA -+ prom_init_numa_memory(); -+#else - prom_init_memory(); -+#endif - - /*init the uart base address */ - prom_init_uart_base(); -diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile -index 70152b2..471b0f2a 100644 ---- a/arch/mips/loongson/loongson-3/Makefile -+++ b/arch/mips/loongson/loongson-3/Makefile -@@ -4,3 +4,5 @@ - obj-y += irq.o - - obj-$(CONFIG_SMP) += smp.o -+ -+obj-$(CONFIG_NUMA) += numa.o -diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c -new file mode 100644 -index 0000000..ca025a6 ---- /dev/null -+++ b/arch/mips/loongson/loongson-3/numa.c -@@ -0,0 +1,291 @@ -+/* -+ * Copyright (C) 2010 Loongson Inc. & Lemote Inc. & -+ * Insititute of Computing Technology -+ * Author: Xiang Gao, gaoxiang@ict.ac.cn -+ * Huacai Chen, chenhc@lemote.com -+ * Xiaofu Meng, Shuangshuang Zhang -+ * -+ * 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. -+ */ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+static struct node_data prealloc__node_data[MAX_NUMNODES]; -+unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES]; -+struct node_data *__node_data[MAX_NUMNODES]; -+EXPORT_SYMBOL(__node_data); -+ -+static void enable_lpa(void) -+{ -+ unsigned long value; -+ -+ value = __read_32bit_c0_register($16, 3); -+ value |= 0x00000080; -+ __write_32bit_c0_register($16, 3, value); -+ value = __read_32bit_c0_register($16, 3); -+ pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value); -+ -+ value = __read_32bit_c0_register($5, 1); -+ value |= 0x20000000; -+ __write_32bit_c0_register($5, 1, value); -+ value = __read_32bit_c0_register($5, 1); -+ pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value); -+} -+ -+static void cpu_node_probe(void) -+{ -+ int i; -+ -+ nodes_clear(node_possible_map); -+ nodes_clear(node_online_map); -+ for (i = 0; i < loongson_sysconf.nr_nodes; i++) { -+ node_set_state(num_online_nodes(), N_POSSIBLE); -+ node_set_online(num_online_nodes()); -+ } -+ -+ pr_info("NUMA: Discovered %d cpus on %d nodes\n", -+ loongson_sysconf.nr_cpus, num_online_nodes()); -+} -+ -+static int __init compute_node_distance(int row, int col) -+{ -+ int package_row = row * loongson_sysconf.cores_per_node / -+ loongson_sysconf.cores_per_package; -+ int package_col = col * loongson_sysconf.cores_per_node / -+ loongson_sysconf.cores_per_package; -+ -+ if (col == row) -+ return 0; -+ else if (package_row == package_col) -+ return 40; -+ else -+ return 100; -+} -+ -+static void __init init_topology_matrix(void) -+{ -+ int row, col; -+ -+ for (row = 0; row < MAX_NUMNODES; row++) -+ for (col = 0; col < MAX_NUMNODES; col++) -+ __node_distances[row][col] = -1; -+ -+ for_each_online_node(row) { -+ for_each_online_node(col) { -+ __node_distances[row][col] = -+ compute_node_distance(row, col); -+ } -+ } -+} -+ -+static unsigned long nid_to_addroffset(unsigned int nid) -+{ -+ unsigned long result; -+ switch (nid) { -+ case 0: -+ default: -+ result = NODE0_ADDRSPACE_OFFSET; -+ break; -+ case 1: -+ result = NODE1_ADDRSPACE_OFFSET; -+ break; -+ case 2: -+ result = NODE2_ADDRSPACE_OFFSET; -+ break; -+ case 3: -+ result = NODE3_ADDRSPACE_OFFSET; -+ break; -+ } -+ return result; -+} -+ -+static void __init szmem(unsigned int node) -+{ -+ u32 i, mem_type; -+ static unsigned long num_physpages = 0; -+ u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size; -+ -+ /* Parse memory information and activate */ -+ for (i = 0; i < loongson_memmap->nr_map; i++) { -+ node_id = loongson_memmap->map[i].node_id; -+ if (node_id != node) -+ continue; -+ -+ mem_type = loongson_memmap->map[i].mem_type; -+ mem_size = loongson_memmap->map[i].mem_size; -+ mem_start = loongson_memmap->map[i].mem_start; -+ -+ switch (mem_type) { -+ case SYSTEM_RAM_LOW: -+ start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT; -+ node_psize = (mem_size << 20) >> PAGE_SHIFT; -+ end_pfn = start_pfn + node_psize; -+ num_physpages += node_psize; -+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", -+ (u32)node_id, mem_type, mem_start, mem_size); -+ pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", -+ start_pfn, end_pfn, num_physpages); -+ add_memory_region((node_id << 44) + mem_start, -+ (u64)mem_size << 20, BOOT_MEM_RAM); -+ memblock_add_node(PFN_PHYS(start_pfn), -+ PFN_PHYS(end_pfn - start_pfn), node); -+ break; -+ case SYSTEM_RAM_HIGH: -+ start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT; -+ node_psize = (mem_size << 20) >> PAGE_SHIFT; -+ end_pfn = start_pfn + node_psize; -+ num_physpages += node_psize; -+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", -+ (u32)node_id, mem_type, mem_start, mem_size); -+ pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", -+ start_pfn, end_pfn, num_physpages); -+ add_memory_region((node_id << 44) + mem_start, -+ (u64)mem_size << 20, BOOT_MEM_RAM); -+ memblock_add_node(PFN_PHYS(start_pfn), -+ PFN_PHYS(end_pfn - start_pfn), node); -+ break; -+ case MEM_RESERVED: -+ pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", -+ (u32)node_id, mem_type, mem_start, mem_size); -+ add_memory_region((node_id << 44) + mem_start, -+ (u64)mem_size << 20, BOOT_MEM_RESERVED); -+ memblock_reserve(((node_id << 44) + mem_start), -+ mem_size << 20); -+ break; -+ } -+ } -+} -+ -+static void __init node_mem_init(unsigned int node) -+{ -+ unsigned long bootmap_size; -+ unsigned long node_addrspace_offset; -+ unsigned long start_pfn, end_pfn, freepfn; -+ -+ node_addrspace_offset = nid_to_addroffset(node); -+ pr_info("Node%d's addrspace_offset is 0x%lx\n", -+ node, node_addrspace_offset); -+ -+ get_pfn_range_for_nid(node, &start_pfn, &end_pfn); -+ freepfn = start_pfn; -+ if (node == 0) -+ freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */ -+ pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n", -+ node, start_pfn, end_pfn, freepfn); -+ -+ __node_data[node] = prealloc__node_data + node; -+ -+ NODE_DATA(node)->bdata = &bootmem_node_data[node]; -+ NODE_DATA(node)->node_start_pfn = start_pfn; -+ NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; -+ -+ bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn, -+ start_pfn, end_pfn); -+ free_bootmem_with_active_regions(node, end_pfn); -+ if (node == 0) /* used by finalize_initrd() */ -+ max_low_pfn = end_pfn; -+ -+ /* This is reserved for the kernel and bdata->node_bootmem_map */ -+ reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT, -+ ((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size, -+ BOOTMEM_DEFAULT); -+ -+ if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) { -+ /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */ -+ reserve_bootmem_node(NODE_DATA(node), -+ (node_addrspace_offset | 0xff800000), -+ 8 << 20, BOOTMEM_DEFAULT); -+ } -+ -+ sparse_memory_present_with_active_regions(node); -+} -+ -+static __init void prom_meminit(void) -+{ -+ unsigned int node, cpu; -+ -+ cpu_node_probe(); -+ init_topology_matrix(); -+ -+ for (node = 0; node < loongson_sysconf.nr_nodes; node++) { -+ if (node_online(node)) { -+ szmem(node); -+ node_mem_init(node); -+ cpus_clear(__node_data[(node)]->cpumask); -+ } -+ } -+ for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) { -+ node = cpu / loongson_sysconf.cores_per_node; -+ if (node >= num_online_nodes()) -+ node = 0; -+ pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node); -+ cpu_set(cpu, __node_data[(node)]->cpumask); -+ } -+} -+ -+void __init paging_init(void) -+{ -+ unsigned node; -+ unsigned long zones_size[MAX_NR_ZONES] = {0, }; -+ -+ pagetable_init(); -+ -+ for_each_online_node(node) { -+ unsigned long start_pfn, end_pfn; -+ -+ get_pfn_range_for_nid(node, &start_pfn, &end_pfn); -+ -+ if (end_pfn > max_low_pfn) -+ max_low_pfn = end_pfn; -+ } -+#ifdef CONFIG_ZONE_DMA32 -+ zones_size[ZONE_DMA32] = MAX_DMA32_PFN; -+#endif -+ zones_size[ZONE_NORMAL] = max_low_pfn; -+ free_area_init_nodes(zones_size); -+} -+ -+void __init mem_init(void) -+{ -+ high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT); -+ free_all_bootmem(); -+ setup_zero_pages(); /* This comes from node 0 */ -+ mem_init_print_info(NULL); -+} -+ -+/* All PCI device belongs to logical Node-0 */ -+int pcibus_to_node(struct pci_bus *bus) -+{ -+ return 0; -+} -+EXPORT_SYMBOL(pcibus_to_node); -+ -+void __init prom_init_numa_memory(void) -+{ -+ enable_lpa(); -+ prom_meminit(); -+} -+EXPORT_SYMBOL(prom_init_numa_memory); -diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c -index 3c320e7..ed0e2d0 100644 ---- a/arch/mips/loongson/loongson-3/smp.c -+++ b/arch/mips/loongson/loongson-3/smp.c -@@ -203,6 +203,8 @@ static void loongson3_init_secondary(void) - for (i = 0; i < loongson_sysconf.nr_cpus; i++) - loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]); - -+ cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package; -+ cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package; - per_cpu(cpu_state, cpu) = CPU_ONLINE; - - i = 0; -@@ -394,17 +396,19 @@ static int loongson3_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) - { - unsigned int cpu = (unsigned long)hcpu; -+ uint64_t core_id = cpu_data[cpu].core; -+ uint64_t package_id = cpu_data[cpu].package; - - switch (action) { - case CPU_POST_DEAD: - case CPU_POST_DEAD_FROZEN: - pr_info("Disable clock for CPU#%d\n", cpu); -- LOONGSON_CHIPCFG(0) &= ~(1 << (12 + cpu)); -+ LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id)); - break; - case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: - pr_info("Enable clock for CPU#%d\n", cpu); -- LOONGSON_CHIPCFG(0) |= 1 << (12 + cpu); -+ LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id); - break; - } - --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Add-numa-api-support.patch b/debian/patches/features/mips/MIPS-Add-numa-api-support.patch deleted file mode 100644 index 9a98b2fed..000000000 --- a/debian/patches/features/mips/MIPS-Add-numa-api-support.patch +++ /dev/null @@ -1,119 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:29 +0800 -Subject: [5/8] MIPS: Add numa api support -Origin: https://git.kernel.org/linus/1ff1ad6bc2c63f219cbc00dcdd35dcf36a7d6fe4 - -Enable sys_mbind()/sys_get_mempolicy()/sys_set_mempolicy() for O32, N32, -and N64 ABIs. By the way, O32/N32 should use the compat version of -sys_migrate_pages()/sys_move_pages(), so fix that. - -Signed-off-by: Huacai Chen -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7186/ -Signed-off-by: Ralf Baechle ---- - arch/mips/kernel/scall32-o32.S | 4 ++-- - arch/mips/kernel/scall64-64.S | 4 ++-- - arch/mips/kernel/scall64-n32.S | 10 +++++----- - arch/mips/kernel/scall64-o32.S | 8 ++++---- - 4 files changed, 13 insertions(+), 13 deletions(-) - -diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S -index 3245474..6bfdc82 100644 ---- a/arch/mips/kernel/scall32-o32.S -+++ b/arch/mips/kernel/scall32-o32.S -@@ -495,8 +495,8 @@ EXPORT(sys_call_table) - PTR sys_tgkill - PTR sys_utimes - PTR sys_mbind -- PTR sys_ni_syscall /* sys_get_mempolicy */ -- PTR sys_ni_syscall /* 4270 sys_set_mempolicy */ -+ PTR sys_get_mempolicy -+ PTR sys_set_mempolicy /* 4270 */ - PTR sys_mq_open - PTR sys_mq_unlink - PTR sys_mq_timedsend -diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S -index be2fedd..0952139 100644 ---- a/arch/mips/kernel/scall64-64.S -+++ b/arch/mips/kernel/scall64-64.S -@@ -347,8 +347,8 @@ EXPORT(sys_call_table) - PTR sys_tgkill /* 5225 */ - PTR sys_utimes - PTR sys_mbind -- PTR sys_ni_syscall /* sys_get_mempolicy */ -- PTR sys_ni_syscall /* sys_set_mempolicy */ -+ PTR sys_get_mempolicy -+ PTR sys_set_mempolicy - PTR sys_mq_open /* 5230 */ - PTR sys_mq_unlink - PTR sys_mq_timedsend -diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S -index c1dbcda..7641c87 100644 ---- a/arch/mips/kernel/scall64-n32.S -+++ b/arch/mips/kernel/scall64-n32.S -@@ -339,9 +339,9 @@ EXPORT(sysn32_call_table) - PTR compat_sys_clock_nanosleep - PTR sys_tgkill - PTR compat_sys_utimes /* 6230 */ -- PTR sys_ni_syscall /* sys_mbind */ -- PTR sys_ni_syscall /* sys_get_mempolicy */ -- PTR sys_ni_syscall /* sys_set_mempolicy */ -+ PTR compat_sys_mbind -+ PTR compat_sys_get_mempolicy -+ PTR compat_sys_set_mempolicy - PTR compat_sys_mq_open - PTR sys_mq_unlink /* 6235 */ - PTR compat_sys_mq_timedsend -@@ -358,7 +358,7 @@ EXPORT(sysn32_call_table) - PTR sys_inotify_init - PTR sys_inotify_add_watch - PTR sys_inotify_rm_watch -- PTR sys_migrate_pages /* 6250 */ -+ PTR compat_sys_migrate_pages /* 6250 */ - PTR sys_openat - PTR sys_mkdirat - PTR sys_mknodat -@@ -379,7 +379,7 @@ EXPORT(sysn32_call_table) - PTR sys_sync_file_range - PTR sys_tee - PTR compat_sys_vmsplice /* 6270 */ -- PTR sys_move_pages -+ PTR compat_sys_move_pages - PTR compat_sys_set_robust_list - PTR compat_sys_get_robust_list - PTR compat_sys_kexec_load -diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S -index f1343cc..18cfa11 100644 ---- a/arch/mips/kernel/scall64-o32.S -+++ b/arch/mips/kernel/scall64-o32.S -@@ -473,9 +473,9 @@ EXPORT(sys32_call_table) - PTR compat_sys_clock_nanosleep /* 4265 */ - PTR sys_tgkill - PTR compat_sys_utimes -- PTR sys_ni_syscall /* sys_mbind */ -- PTR sys_ni_syscall /* sys_get_mempolicy */ -- PTR sys_ni_syscall /* 4270 sys_set_mempolicy */ -+ PTR compat_sys_mbind -+ PTR compat_sys_get_mempolicy -+ PTR compat_sys_set_mempolicy /* 4270 */ - PTR compat_sys_mq_open - PTR sys_mq_unlink - PTR compat_sys_mq_timedsend -@@ -492,7 +492,7 @@ EXPORT(sys32_call_table) - PTR sys_inotify_init - PTR sys_inotify_add_watch /* 4285 */ - PTR sys_inotify_rm_watch -- PTR sys_migrate_pages -+ PTR compat_sys_migrate_pages - PTR compat_sys_openat - PTR sys_mkdirat - PTR sys_mknodat /* 4290 */ --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Loongson-3-Enable-the-COP2-usage.patch b/debian/patches/features/mips/MIPS-Loongson-3-Enable-the-COP2-usage.patch deleted file mode 100644 index 4da826ac3..000000000 --- a/debian/patches/features/mips/MIPS-Loongson-3-Enable-the-COP2-usage.patch +++ /dev/null @@ -1,132 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:31 +0800 -Subject: [7/8] MIPS: Loongson-3: Enable the COP2 usage -Origin: https://git.kernel.org/linus/ef2f826c8f2ff1e4215968042139604633581a13 - -Loongson-3 has some specific instructions (MMI/SIMD) in coprocessor 2. -COP2 isn't independent because it share COP1 (FPU)'s registers. This -patch enable the COP2 usage so user-space programs can use the MMI/SIMD -instructions. When COP2 exception happens, we enable both COP1 (FPU) -and COP2, only in this way the fp context can be saved and restored -correctly. - -Signed-off-by: Huacai Chen -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7189/ -Signed-off-by: Ralf Baechle ---- - arch/mips/include/asm/cop2.h | 8 ++++ - arch/mips/loongson/loongson-3/Makefile | 2 +- - arch/mips/loongson/loongson-3/cop2-ex.c | 63 +++++++++++++++++++++++++++++++ - 3 files changed, 72 insertions(+), 1 deletion(-) - create mode 100644 arch/mips/loongson/loongson-3/cop2-ex.c - -diff --git a/arch/mips/include/asm/cop2.h b/arch/mips/include/asm/cop2.h -index c1516cc..d035298 100644 ---- a/arch/mips/include/asm/cop2.h -+++ b/arch/mips/include/asm/cop2.h -@@ -32,6 +32,14 @@ extern void nlm_cop2_restore(struct nlm_cop2_state *); - #define cop2_present 1 - #define cop2_lazy_restore 0 - -+#elif defined(CONFIG_CPU_LOONGSON3) -+ -+#define cop2_save(r) -+#define cop2_restore(r) -+ -+#define cop2_present 1 -+#define cop2_lazy_restore 1 -+ - #else - - #define cop2_present 0 -diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile -index 471b0f2a..b4df775 100644 ---- a/arch/mips/loongson/loongson-3/Makefile -+++ b/arch/mips/loongson/loongson-3/Makefile -@@ -1,7 +1,7 @@ - # - # Makefile for Loongson-3 family machines - # --obj-y += irq.o -+obj-y += irq.o cop2-ex.o - - obj-$(CONFIG_SMP) += smp.o - -diff --git a/arch/mips/loongson/loongson-3/cop2-ex.c b/arch/mips/loongson/loongson-3/cop2-ex.c -new file mode 100644 -index 0000000..9182e8d ---- /dev/null -+++ b/arch/mips/loongson/loongson-3/cop2-ex.c -@@ -0,0 +1,63 @@ -+/* -+ * 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. -+ * -+ * Copyright (C) 2014 Lemote Corporation. -+ * written by Huacai Chen -+ * -+ * based on arch/mips/cavium-octeon/cpu.c -+ * Copyright (C) 2009 Wind River Systems, -+ * written by Ralf Baechle -+ */ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+static int loongson_cu2_call(struct notifier_block *nfb, unsigned long action, -+ void *data) -+{ -+ int fpu_enabled; -+ int fr = !test_thread_flag(TIF_32BIT_FPREGS); -+ -+ switch (action) { -+ case CU2_EXCEPTION: -+ preempt_disable(); -+ fpu_enabled = read_c0_status() & ST0_CU1; -+ if (!fr) -+ set_c0_status(ST0_CU1 | ST0_CU2); -+ else -+ set_c0_status(ST0_CU1 | ST0_CU2 | ST0_FR); -+ enable_fpu_hazard(); -+ KSTK_STATUS(current) |= (ST0_CU1 | ST0_CU2); -+ if (fr) -+ KSTK_STATUS(current) |= ST0_FR; -+ else -+ KSTK_STATUS(current) &= ~ST0_FR; -+ /* If FPU is enabled, we needn't init or restore fp */ -+ if(!fpu_enabled) { -+ set_thread_flag(TIF_USEDFPU); -+ if (!used_math()) { -+ _init_fpu(); -+ set_used_math(); -+ } else -+ _restore_fp(current); -+ } -+ preempt_enable(); -+ -+ return NOTIFY_STOP; /* Don't call default notifier */ -+ } -+ -+ return NOTIFY_OK; /* Let default notifier send signals */ -+} -+ -+static int __init loongson_cu2_setup(void) -+{ -+ return cu2_notifier(loongson_cu2_call, 0); -+} -+early_initcall(loongson_cu2_setup); --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Loongson-Modify-ChipConfig-register-definition.patch b/debian/patches/features/mips/MIPS-Loongson-Modify-ChipConfig-register-definition.patch deleted file mode 100644 index f8331b4bf..000000000 --- a/debian/patches/features/mips/MIPS-Loongson-Modify-ChipConfig-register-definition.patch +++ /dev/null @@ -1,174 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:27 +0800 -Subject: [3/8] MIPS: Loongson: Modify ChipConfig register definition -Origin: https://git.kernel.org/linus/140e39c1e3d29f50e161f55cca60f60b80408c2a - -This patch is prepared for Multi-chip interconnection. Since each chip -has a ChipConfig register, LOONGSON_CHIPCFG should be an array. - -Signed-off-by: Huacai Chen -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7185/ -Signed-off-by: Ralf Baechle ---- - arch/mips/include/asm/mach-loongson/loongson.h | 7 +++++-- - arch/mips/loongson/common/env.c | 11 +++++++++++ - arch/mips/loongson/common/pm.c | 8 ++++---- - arch/mips/loongson/lemote-2f/clock.c | 4 ++-- - arch/mips/loongson/lemote-2f/reset.c | 2 +- - arch/mips/loongson/loongson-3/smp.c | 4 ++-- - drivers/cpufreq/loongson2_cpufreq.c | 6 +++--- - 7 files changed, 28 insertions(+), 14 deletions(-) - -diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h -index f3fd1eb..a1c76ca 100644 ---- a/arch/mips/include/asm/mach-loongson/loongson.h -+++ b/arch/mips/include/asm/mach-loongson/loongson.h -@@ -249,8 +249,11 @@ static inline void do_perfcnt_IRQ(void) - #define LOONGSON_PXARB_CFG LOONGSON_REG(LOONGSON_REGBASE + 0x68) - #define LOONGSON_PXARB_STATUS LOONGSON_REG(LOONGSON_REGBASE + 0x6c) - --/* Chip Config */ --#define LOONGSON_CHIPCFG0 LOONGSON_REG(LOONGSON_REGBASE + 0x80) -+#define MAX_PACKAGES 4 -+ -+/* Chip Config registor of each physical cpu package, PRid >= Loongson-2F */ -+extern u64 loongson_chipcfg[MAX_PACKAGES]; -+#define LOONGSON_CHIPCFG(id) (*(volatile u32 *)(loongson_chipcfg[id])) - - /* pcimap */ - -diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c -index 0c543ea..dc59241 100644 ---- a/arch/mips/loongson/common/env.c -+++ b/arch/mips/loongson/common/env.c -@@ -27,6 +27,8 @@ EXPORT_SYMBOL(cpu_clock_freq); - struct efi_memory_map_loongson *loongson_memmap; - struct loongson_system_configuration loongson_sysconf; - -+u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180}; -+ - #define parse_even_earlier(res, option, p) \ - do { \ - unsigned int tmp __maybe_unused; \ -@@ -77,6 +79,15 @@ void __init prom_init_env(void) - - cpu_clock_freq = ecpu->cpu_clock_freq; - loongson_sysconf.cputype = ecpu->cputype; -+ if (ecpu->cputype == Loongson_3A) { -+ loongson_chipcfg[0] = 0x900000001fe00180; -+ loongson_chipcfg[1] = 0x900010001fe00180; -+ loongson_chipcfg[2] = 0x900020001fe00180; -+ loongson_chipcfg[3] = 0x900030001fe00180; -+ } else { -+ loongson_chipcfg[0] = 0x900000001fe00180; -+ } -+ - loongson_sysconf.nr_cpus = ecpu->nr_cpus; - if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0) - loongson_sysconf.nr_cpus = NR_CPUS; -diff --git a/arch/mips/loongson/common/pm.c b/arch/mips/loongson/common/pm.c -index f55e07a..a6b67cc 100644 ---- a/arch/mips/loongson/common/pm.c -+++ b/arch/mips/loongson/common/pm.c -@@ -79,7 +79,7 @@ int __weak wakeup_loongson(void) - static void wait_for_wakeup_events(void) - { - while (!wakeup_loongson()) -- LOONGSON_CHIPCFG0 &= ~0x7; -+ LOONGSON_CHIPCFG(0) &= ~0x7; - } - - /* -@@ -102,15 +102,15 @@ static void loongson_suspend_enter(void) - - stop_perf_counters(); - -- cached_cpu_freq = LOONGSON_CHIPCFG0; -+ cached_cpu_freq = LOONGSON_CHIPCFG(0); - - /* Put CPU into wait mode */ -- LOONGSON_CHIPCFG0 &= ~0x7; -+ LOONGSON_CHIPCFG(0) &= ~0x7; - - /* wait for the given events to wakeup cpu from wait mode */ - wait_for_wakeup_events(); - -- LOONGSON_CHIPCFG0 = cached_cpu_freq; -+ LOONGSON_CHIPCFG(0) = cached_cpu_freq; - mmiowb(); - } - -diff --git a/arch/mips/loongson/lemote-2f/clock.c b/arch/mips/loongson/lemote-2f/clock.c -index 1eed38e..a217061 100644 ---- a/arch/mips/loongson/lemote-2f/clock.c -+++ b/arch/mips/loongson/lemote-2f/clock.c -@@ -114,9 +114,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate) - - clk->rate = rate; - -- regval = LOONGSON_CHIPCFG0; -+ regval = LOONGSON_CHIPCFG(0); - regval = (regval & ~0x7) | (pos->driver_data - 1); -- LOONGSON_CHIPCFG0 = regval; -+ LOONGSON_CHIPCFG(0) = regval; - - return ret; - } -diff --git a/arch/mips/loongson/lemote-2f/reset.c b/arch/mips/loongson/lemote-2f/reset.c -index 90962a3..79ac694 100644 ---- a/arch/mips/loongson/lemote-2f/reset.c -+++ b/arch/mips/loongson/lemote-2f/reset.c -@@ -28,7 +28,7 @@ static void reset_cpu(void) - * reset cpu to full speed, this is needed when enabling cpu frequency - * scalling - */ -- LOONGSON_CHIPCFG0 |= 0x7; -+ LOONGSON_CHIPCFG(0) |= 0x7; - } - - /* reset support for fuloong2f */ -diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c -index 1e88940..3c320e7 100644 ---- a/arch/mips/loongson/loongson-3/smp.c -+++ b/arch/mips/loongson/loongson-3/smp.c -@@ -399,12 +399,12 @@ static int loongson3_cpu_callback(struct notifier_block *nfb, - case CPU_POST_DEAD: - case CPU_POST_DEAD_FROZEN: - pr_info("Disable clock for CPU#%d\n", cpu); -- LOONGSON_CHIPCFG0 &= ~(1 << (12 + cpu)); -+ LOONGSON_CHIPCFG(0) &= ~(1 << (12 + cpu)); - break; - case CPU_UP_PREPARE: - case CPU_UP_PREPARE_FROZEN: - pr_info("Enable clock for CPU#%d\n", cpu); -- LOONGSON_CHIPCFG0 |= 1 << (12 + cpu); -+ LOONGSON_CHIPCFG(0) |= 1 << (12 + cpu); - break; - } - -diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c -index d4add86..9fa1772 100644 ---- a/drivers/cpufreq/loongson2_cpufreq.c -+++ b/drivers/cpufreq/loongson2_cpufreq.c -@@ -148,9 +148,9 @@ static void loongson2_cpu_wait(void) - u32 cpu_freq; - - spin_lock_irqsave(&loongson2_wait_lock, flags); -- cpu_freq = LOONGSON_CHIPCFG0; -- LOONGSON_CHIPCFG0 &= ~0x7; /* Put CPU into wait mode */ -- LOONGSON_CHIPCFG0 = cpu_freq; /* Restore CPU state */ -+ cpu_freq = LOONGSON_CHIPCFG(0); -+ LOONGSON_CHIPCFG(0) &= ~0x7; /* Put CPU into wait mode */ -+ LOONGSON_CHIPCFG(0) = cpu_freq; /* Restore CPU state */ - spin_unlock_irqrestore(&loongson2_wait_lock, flags); - local_irq_enable(); - } --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Loongson-Rename-CONFIG_LEMOTE_MACH3A-to-CONFIG_.patch b/debian/patches/features/mips/MIPS-Loongson-Rename-CONFIG_LEMOTE_MACH3A-to-CONFIG_.patch deleted file mode 100644 index e3687b8e7..000000000 --- a/debian/patches/features/mips/MIPS-Loongson-Rename-CONFIG_LEMOTE_MACH3A-to-CONFIG_.patch +++ /dev/null @@ -1,108 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:32 +0800 -Subject: [8/8] MIPS: Loongson: Rename CONFIG_LEMOTE_MACH3A to - CONFIG_LOONGSON_MACH3X -Origin: https://git.kernel.org/linus/5a21e0ba3e8996353e6892ccc54b0aab541d9722 - -Since this CONFIG option will be used for both Loongson-3A/3B machines, -and not all Loongson-3 machines are produced by Lemote, we rename -CONFIG_LEMOTE_MACH3A to CONFIG_LOONGSON_MACH3X. - -Signed-off-by: Huacai Chen -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7190/ -Signed-off-by: Ralf Baechle ---- - arch/mips/configs/loongson3_defconfig | 2 +- - arch/mips/include/asm/mach-loongson/machine.h | 4 ++-- - arch/mips/loongson/Kconfig | 8 ++++---- - arch/mips/loongson/Platform | 2 +- - arch/mips/pci/Makefile | 2 +- - 5 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/arch/mips/configs/loongson3_defconfig b/arch/mips/configs/loongson3_defconfig -index ea1761f..130e31b 100644 ---- a/arch/mips/configs/loongson3_defconfig -+++ b/arch/mips/configs/loongson3_defconfig -@@ -1,6 +1,6 @@ - CONFIG_MACH_LOONGSON=y - CONFIG_SWIOTLB=y --CONFIG_LEMOTE_MACH3A=y -+CONFIG_LOONGSON_MACH3X=y - CONFIG_CPU_LOONGSON3=y - CONFIG_64BIT=y - CONFIG_PAGE_SIZE_16KB=y -diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h -index 1b1f592..228e3784 100644 ---- a/arch/mips/include/asm/mach-loongson/machine.h -+++ b/arch/mips/include/asm/mach-loongson/machine.h -@@ -24,10 +24,10 @@ - - #endif - --#ifdef CONFIG_LEMOTE_MACH3A -+#ifdef CONFIG_LOONGSON_MACH3X - - #define LOONGSON_MACHTYPE MACH_LEMOTE_A1101 - --#endif /* CONFIG_LEMOTE_MACH3A */ -+#endif /* CONFIG_LOONGSON_MACH3X */ - - #endif /* __ASM_MACH_LOONGSON_MACHINE_H */ -diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig -index a14a50d..1b91fc6 100644 ---- a/arch/mips/loongson/Kconfig -+++ b/arch/mips/loongson/Kconfig -@@ -60,8 +60,8 @@ config LEMOTE_MACH2F - These family machines include fuloong2f mini PC, yeeloong2f notebook, - LingLoong allinone PC and so forth. - --config LEMOTE_MACH3A -- bool "Lemote Loongson 3A family machines" -+config LOONGSON_MACH3X -+ bool "Generic Loongson 3 family machines" - select ARCH_SPARSEMEM_ENABLE - select GENERIC_ISA_DMA_SUPPORT_BROKEN - select BOOT_ELF32 -@@ -87,8 +87,8 @@ config LEMOTE_MACH3A - select ZONE_DMA32 - select LEFI_FIRMWARE_INTERFACE - help -- Lemote Loongson 3A family machines utilize the 3A revision of -- Loongson processor and RS780/SBX00 chipset. -+ Generic Loongson 3 family machines utilize the 3A/3B revision -+ of Loongson processor and RS780/SBX00 chipset. - endchoice - - config CS5536 -diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform -index 6205372..0ac20eb 100644 ---- a/arch/mips/loongson/Platform -+++ b/arch/mips/loongson/Platform -@@ -30,4 +30,4 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/ - cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely - load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000 - load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000 --load-$(CONFIG_CPU_LOONGSON3) += 0xffffffff80200000 -+load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000 -diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile -index ff8a553..6523d55 100644 ---- a/arch/mips/pci/Makefile -+++ b/arch/mips/pci/Makefile -@@ -29,7 +29,7 @@ obj-$(CONFIG_LASAT) += pci-lasat.o - obj-$(CONFIG_MIPS_COBALT) += fixup-cobalt.o - obj-$(CONFIG_LEMOTE_FULOONG2E) += fixup-fuloong2e.o ops-loongson2.o - obj-$(CONFIG_LEMOTE_MACH2F) += fixup-lemote2f.o ops-loongson2.o --obj-$(CONFIG_LEMOTE_MACH3A) += fixup-loongson3.o ops-loongson3.o -+obj-$(CONFIG_LOONGSON_MACH3X) += fixup-loongson3.o ops-loongson3.o - obj-$(CONFIG_MIPS_MALTA) += fixup-malta.o pci-malta.o - obj-$(CONFIG_PMC_MSP7120_GW) += fixup-pmcmsp.o ops-pmcmsp.o - obj-$(CONFIG_PMC_MSP7120_EVAL) += fixup-pmcmsp.o ops-pmcmsp.o --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Support-CPU-topology-files-in-sysfs.patch b/debian/patches/features/mips/MIPS-Support-CPU-topology-files-in-sysfs.patch deleted file mode 100644 index 22eb56db6..000000000 --- a/debian/patches/features/mips/MIPS-Support-CPU-topology-files-in-sysfs.patch +++ /dev/null @@ -1,145 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:26 +0800 -Subject: [2/8] MIPS: Support CPU topology files in sysfs -Origin: https://git.kernel.org/linus/bda4584cd943d7bb6cf677a8d694700c1984cf3e - -This patch is prepared for Loongson's NUMA support, it offer meaningful -sysfs files such as physical_package_id, core_id, core_siblings and -thread_siblings in /sys/devices/system/cpu/cpu?/topology. - -Signed-off-by: Huacai Chen -Reviewed-by: Andreas Herrmann -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7184/ -Signed-off-by: Ralf Baechle ---- - arch/mips/include/asm/cpu-info.h | 1 + - arch/mips/include/asm/smp.h | 6 ++++++ - arch/mips/kernel/proc.c | 1 + - arch/mips/kernel/smp.c | 26 +++++++++++++++++++++++++- - 4 files changed, 33 insertions(+), 1 deletion(-) - -diff --git a/arch/mips/include/asm/cpu-info.h b/arch/mips/include/asm/cpu-info.h -index a28e3de..6690d7a 100644 ---- a/arch/mips/include/asm/cpu-info.h -+++ b/arch/mips/include/asm/cpu-info.h -@@ -61,6 +61,7 @@ struct cpuinfo_mips { - struct cache_desc scache; /* Secondary cache */ - struct cache_desc tcache; /* Tertiary/split secondary cache */ - int srsets; /* Shadow register sets */ -+ int package;/* physical package number */ - int core; /* physical core number */ - #ifdef CONFIG_64BIT - int vmbits; /* Virtual memory size in bits */ -diff --git a/arch/mips/include/asm/smp.h b/arch/mips/include/asm/smp.h -index b037334..1e0f20a 100644 ---- a/arch/mips/include/asm/smp.h -+++ b/arch/mips/include/asm/smp.h -@@ -22,6 +22,7 @@ - - extern int smp_num_siblings; - extern cpumask_t cpu_sibling_map[]; -+extern cpumask_t cpu_core_map[]; - - #define raw_smp_processor_id() (current_thread_info()->cpu) - -@@ -36,6 +37,11 @@ extern int __cpu_logical_map[NR_CPUS]; - - #define NO_PROC_ID (-1) - -+#define topology_physical_package_id(cpu) (cpu_data[cpu].package) -+#define topology_core_id(cpu) (cpu_data[cpu].core) -+#define topology_core_cpumask(cpu) (&cpu_core_map[cpu]) -+#define topology_thread_cpumask(cpu) (&cpu_sibling_map[cpu]) -+ - #define SMP_RESCHEDULE_YOURSELF 0x1 /* XXX braindead */ - #define SMP_CALL_FUNCTION 0x2 - /* Octeon - Tell another core to flush its icache */ -diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c -index 037a44d..62c4439 100644 ---- a/arch/mips/kernel/proc.c -+++ b/arch/mips/kernel/proc.c -@@ -123,6 +123,7 @@ static int show_cpuinfo(struct seq_file *m, void *v) - cpu_data[n].srsets); - seq_printf(m, "kscratch registers\t: %d\n", - hweight8(cpu_data[n].kscratch_mask)); -+ seq_printf(m, "package\t\t\t: %d\n", cpu_data[n].package); - seq_printf(m, "core\t\t\t: %d\n", cpu_data[n].core); - - sprintf(fmt, "VCE%%c exceptions\t\t: %s\n", -diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c -index 9bad52e..c94c4e9 100644 ---- a/arch/mips/kernel/smp.c -+++ b/arch/mips/kernel/smp.c -@@ -59,9 +59,16 @@ EXPORT_SYMBOL(smp_num_siblings); - cpumask_t cpu_sibling_map[NR_CPUS] __read_mostly; - EXPORT_SYMBOL(cpu_sibling_map); - -+/* representing the core map of multi-core chips of each logical CPU */ -+cpumask_t cpu_core_map[NR_CPUS] __read_mostly; -+EXPORT_SYMBOL(cpu_core_map); -+ - /* representing cpus for which sibling maps can be computed */ - static cpumask_t cpu_sibling_setup_map; - -+/* representing cpus for which core maps can be computed */ -+static cpumask_t cpu_core_setup_map; -+ - cpumask_t cpu_coherent_mask; - - static inline void set_cpu_sibling_map(int cpu) -@@ -72,7 +79,8 @@ static inline void set_cpu_sibling_map(int cpu) - - if (smp_num_siblings > 1) { - for_each_cpu_mask(i, cpu_sibling_setup_map) { -- if (cpu_data[cpu].core == cpu_data[i].core) { -+ if (cpu_data[cpu].package == cpu_data[i].package && -+ cpu_data[cpu].core == cpu_data[i].core) { - cpu_set(i, cpu_sibling_map[cpu]); - cpu_set(cpu, cpu_sibling_map[i]); - } -@@ -81,6 +89,20 @@ static inline void set_cpu_sibling_map(int cpu) - cpu_set(cpu, cpu_sibling_map[cpu]); - } - -+static inline void set_cpu_core_map(int cpu) -+{ -+ int i; -+ -+ cpu_set(cpu, cpu_core_setup_map); -+ -+ for_each_cpu_mask(i, cpu_core_setup_map) { -+ if (cpu_data[cpu].package == cpu_data[i].package) { -+ cpu_set(i, cpu_core_map[cpu]); -+ cpu_set(cpu, cpu_core_map[i]); -+ } -+ } -+} -+ - struct plat_smp_ops *mp_ops; - EXPORT_SYMBOL(mp_ops); - -@@ -122,6 +144,7 @@ asmlinkage void start_secondary(void) - set_cpu_online(cpu, true); - - set_cpu_sibling_map(cpu); -+ set_cpu_core_map(cpu); - - cpu_set(cpu, cpu_callin_map); - -@@ -175,6 +198,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) - current_thread_info()->cpu = 0; - mp_ops->prepare_cpus(max_cpus); - set_cpu_sibling_map(0); -+ set_cpu_core_map(0); - #ifndef CONFIG_HOTPLUG_CPU - init_cpu_present(cpu_possible_mask); - #endif --- -1.7.10.4 - diff --git a/debian/patches/features/mips/MIPS-Support-hard-limit-of-cpu-count-nr_cpu_ids.patch b/debian/patches/features/mips/MIPS-Support-hard-limit-of-cpu-count-nr_cpu_ids.patch deleted file mode 100644 index 07b05e50c..000000000 --- a/debian/patches/features/mips/MIPS-Support-hard-limit-of-cpu-count-nr_cpu_ids.patch +++ /dev/null @@ -1,65 +0,0 @@ -From: Huacai Chen -Date: Thu, 26 Jun 2014 11:41:25 +0800 -Subject: [1/8] MIPS: Support hard limit of cpu count (nr_cpu_ids) -Origin: https://git.kernel.org/linus/0f3f506b275517250ee0169ec075d5382967f5f6 - -On MIPS currently, only the soft limit of cpu count (maxcpus) has its -effect, this patch enable the hard limit (nr_cpus) as well. Processor -cores which greater than maxcpus and less than nr_cpus can be taken up -via cpu hotplug. The code is borrowed from X86. - -Signed-off-by: Huacai Chen -Reviewed-by: Andreas Herrmann -Cc: John Crispin -Cc: Steven J. Hill -Cc: Aurelien Jarno -Cc: linux-mips@linux-mips.org -Cc: Fuxin Zhang -Cc: Zhangjin Wu -Patchwork: https://patchwork.linux-mips.org/patch/7183/ -Signed-off-by: Ralf Baechle ---- - arch/mips/kernel/setup.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c -index a842154..2f01201 100644 ---- a/arch/mips/kernel/setup.c -+++ b/arch/mips/kernel/setup.c -@@ -729,6 +729,25 @@ static void __init resource_init(void) - } - } - -+#ifdef CONFIG_SMP -+static void __init prefill_possible_map(void) -+{ -+ int i, possible = num_possible_cpus(); -+ -+ if (possible > nr_cpu_ids) -+ possible = nr_cpu_ids; -+ -+ for (i = 0; i < possible; i++) -+ set_cpu_possible(i, true); -+ for (; i < NR_CPUS; i++) -+ set_cpu_possible(i, false); -+ -+ nr_cpu_ids = possible; -+} -+#else -+static inline void prefill_possible_map(void) {} -+#endif -+ - void __init setup_arch(char **cmdline_p) - { - cpu_probe(); -@@ -752,6 +771,7 @@ void __init setup_arch(char **cmdline_p) - - resource_init(); - plat_smp_setup(); -+ prefill_possible_map(); - - cpu_cache_init(); - } --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-Allow-KVM_CHECK_EXTENSION-on-the-vm-fd.patch b/debian/patches/features/powerpc/KVM-Allow-KVM_CHECK_EXTENSION-on-the-vm-fd.patch deleted file mode 100644 index d3a233789..000000000 --- a/debian/patches/features/powerpc/KVM-Allow-KVM_CHECK_EXTENSION-on-the-vm-fd.patch +++ /dev/null @@ -1,144 +0,0 @@ -From: Alexander Graf -Date: Mon, 14 Jul 2014 18:33:08 +0200 -Subject: KVM: Allow KVM_CHECK_EXTENSION on the vm fd -Origin: https://git.kernel.org/linus/92b591a4c46b103ebd3fc0d03a084e1efd331253 - -The KVM_CHECK_EXTENSION is only available on the kvm fd today. Unfortunately -on PPC some of the capabilities change depending on the way a VM was created. - -So instead we need a way to expose capabilities as VM ioctl, so that we can -see which VM type we're using (HV or PR). To enable this, add the -KVM_CHECK_EXTENSION ioctl to our vm ioctl portfolio. - -Signed-off-by: Alexander Graf -Acked-by: Paolo Bonzini ---- - Documentation/virtual/kvm/api.txt | 7 +++-- - include/uapi/linux/kvm.h | 1 + - virt/kvm/kvm_main.c | 58 ++++++++++++++++++++----------------- - 3 files changed, 37 insertions(+), 29 deletions(-) - -diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt -index 884f819..8898caf 100644 ---- a/Documentation/virtual/kvm/api.txt -+++ b/Documentation/virtual/kvm/api.txt -@@ -148,9 +148,9 @@ of banks, as set via the KVM_X86_SETUP_MCE ioctl. - - 4.4 KVM_CHECK_EXTENSION - --Capability: basic -+Capability: basic, KVM_CAP_CHECK_EXTENSION_VM for vm ioctl - Architectures: all --Type: system ioctl -+Type: system ioctl, vm ioctl - Parameters: extension identifier (KVM_CAP_*) - Returns: 0 if unsupported; 1 (or some other positive integer) if supported - -@@ -160,6 +160,9 @@ receives an integer that describes the extension availability. - Generally 0 means no and 1 means yes, but some extensions may report - additional information in the integer return value. - -+Based on their initialization different VMs may have different capabilities. -+It is thus encouraged to use the vm ioctl to query for capabilities (available -+with KVM_CAP_CHECK_EXTENSION_VM on the vm fd) - - 4.5 KVM_GET_VCPU_MMAP_SIZE - -diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h -index 0418b74..51776ca 100644 ---- a/include/uapi/linux/kvm.h -+++ b/include/uapi/linux/kvm.h -@@ -759,6 +759,7 @@ struct kvm_ppc_smmu_info { - #define KVM_CAP_ARM_PSCI_0_2 102 - #define KVM_CAP_PPC_FIXUP_HCALL 103 - #define KVM_CAP_PPC_ENABLE_HCALL 104 -+#define KVM_CAP_CHECK_EXTENSION_VM 105 - - #ifdef KVM_CAP_IRQ_ROUTING - -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index e28f3ca..1b95cc9 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -2324,6 +2324,34 @@ static int kvm_ioctl_create_device(struct kvm *kvm, - return 0; - } - -+static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) -+{ -+ switch (arg) { -+ case KVM_CAP_USER_MEMORY: -+ case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: -+ case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS: -+#ifdef CONFIG_KVM_APIC_ARCHITECTURE -+ case KVM_CAP_SET_BOOT_CPU_ID: -+#endif -+ case KVM_CAP_INTERNAL_ERROR_DATA: -+#ifdef CONFIG_HAVE_KVM_MSI -+ case KVM_CAP_SIGNAL_MSI: -+#endif -+#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -+ case KVM_CAP_IRQFD_RESAMPLE: -+#endif -+ case KVM_CAP_CHECK_EXTENSION_VM: -+ return 1; -+#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -+ case KVM_CAP_IRQ_ROUTING: -+ return KVM_MAX_IRQ_ROUTES; -+#endif -+ default: -+ break; -+ } -+ return kvm_vm_ioctl_check_extension(kvm, arg); -+} -+ - static long kvm_vm_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) - { -@@ -2487,6 +2515,9 @@ static long kvm_vm_ioctl(struct file *filp, - r = 0; - break; - } -+ case KVM_CHECK_EXTENSION: -+ r = kvm_vm_ioctl_check_extension_generic(kvm, arg); -+ break; - default: - r = kvm_arch_vm_ioctl(filp, ioctl, arg); - if (r == -ENOTTY) -@@ -2571,33 +2602,6 @@ static int kvm_dev_ioctl_create_vm(unsigned long type) - return r; - } - --static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) --{ -- switch (arg) { -- case KVM_CAP_USER_MEMORY: -- case KVM_CAP_DESTROY_MEMORY_REGION_WORKS: -- case KVM_CAP_JOIN_MEMORY_REGIONS_WORKS: --#ifdef CONFIG_KVM_APIC_ARCHITECTURE -- case KVM_CAP_SET_BOOT_CPU_ID: --#endif -- case KVM_CAP_INTERNAL_ERROR_DATA: --#ifdef CONFIG_HAVE_KVM_MSI -- case KVM_CAP_SIGNAL_MSI: --#endif --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -- case KVM_CAP_IRQFD_RESAMPLE: --#endif -- return 1; --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -- case KVM_CAP_IRQ_ROUTING: -- return KVM_MAX_IRQ_ROUTES; --#endif -- default: -- break; -- } -- return kvm_vm_ioctl_check_extension(kvm, arg); --} -- - static long kvm_dev_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) - { --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-Don-t-keep-reference-to-irq-routing-table-in-irq.patch b/debian/patches/features/powerpc/KVM-Don-t-keep-reference-to-irq-routing-table-in-irq.patch deleted file mode 100644 index 48b34730d..000000000 --- a/debian/patches/features/powerpc/KVM-Don-t-keep-reference-to-irq-routing-table-in-irq.patch +++ /dev/null @@ -1,134 +0,0 @@ -From: Paul Mackerras -Date: Mon, 30 Jun 2014 20:51:09 +1000 -Subject: KVM: Don't keep reference to irq routing table in - irqfd struct -Origin: https://git.kernel.org/linus/56f89f3629ffd1a21d38c3d0bea23deac0e284ce - -This makes the irqfd code keep a copy of the irq routing table entry -for each irqfd, rather than a reference to the copy in the actual -irq routing table maintained in kvm/virt/irqchip.c. This will enable -us to change the routing table structure in future, or even not have a -routing table at all on some platforms. - -The synchronization that was previously achieved using srcu_dereference -on the read side is now achieved using a seqcount_t structure. That -ensures that we don't get a halfway-updated copy of the structure if -we read it while another thread is updating it. - -We still use srcu_read_lock/unlock around the read side so that when -changing the routing table we can be sure that after calling -synchronize_srcu, nothing will be using the old routing. - -Signed-off-by: Paul Mackerras -Tested-by: Eric Auger -Tested-by: Cornelia Huck -Signed-off-by: Paolo Bonzini ---- - virt/kvm/eventfd.c | 41 +++++++++++++++++++++++++---------------- - 1 file changed, 25 insertions(+), 16 deletions(-) - -diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c -index 20c3af7..bae593a 100644 ---- a/virt/kvm/eventfd.c -+++ b/virt/kvm/eventfd.c -@@ -33,6 +33,7 @@ - #include - #include - #include -+#include - - #include "iodev.h" - -@@ -75,7 +76,8 @@ struct _irqfd { - struct kvm *kvm; - wait_queue_t wait; - /* Update side is protected by irqfds.lock */ -- struct kvm_kernel_irq_routing_entry __rcu *irq_entry; -+ struct kvm_kernel_irq_routing_entry irq_entry; -+ seqcount_t irq_entry_sc; - /* Used for level IRQ fast-path */ - int gsi; - struct work_struct inject; -@@ -223,16 +225,20 @@ irqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key) - { - struct _irqfd *irqfd = container_of(wait, struct _irqfd, wait); - unsigned long flags = (unsigned long)key; -- struct kvm_kernel_irq_routing_entry *irq; -+ struct kvm_kernel_irq_routing_entry irq; - struct kvm *kvm = irqfd->kvm; -+ unsigned seq; - int idx; - - if (flags & POLLIN) { - idx = srcu_read_lock(&kvm->irq_srcu); -- irq = srcu_dereference(irqfd->irq_entry, &kvm->irq_srcu); -+ do { -+ seq = read_seqcount_begin(&irqfd->irq_entry_sc); -+ irq = irqfd->irq_entry; -+ } while (read_seqcount_retry(&irqfd->irq_entry_sc, seq)); - /* An event has been signaled, inject an interrupt */ -- if (irq) -- kvm_set_msi(irq, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, -+ if (irq.type == KVM_IRQ_ROUTING_MSI) -+ kvm_set_msi(&irq, kvm, KVM_USERSPACE_IRQ_SOURCE_ID, 1, - false); - else - schedule_work(&irqfd->inject); -@@ -277,18 +283,20 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, - { - struct kvm_kernel_irq_routing_entry *e; - -- if (irqfd->gsi >= irq_rt->nr_rt_entries) { -- rcu_assign_pointer(irqfd->irq_entry, NULL); -- return; -- } -+ write_seqcount_begin(&irqfd->irq_entry_sc); -+ -+ irqfd->irq_entry.type = 0; -+ if (irqfd->gsi >= irq_rt->nr_rt_entries) -+ goto out; - - hlist_for_each_entry(e, &irq_rt->map[irqfd->gsi], link) { - /* Only fast-path MSI. */ - if (e->type == KVM_IRQ_ROUTING_MSI) -- rcu_assign_pointer(irqfd->irq_entry, e); -- else -- rcu_assign_pointer(irqfd->irq_entry, NULL); -+ irqfd->irq_entry = *e; - } -+ -+ out: -+ write_seqcount_end(&irqfd->irq_entry_sc); - } - - static int -@@ -310,6 +318,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) - INIT_LIST_HEAD(&irqfd->list); - INIT_WORK(&irqfd->inject, irqfd_inject); - INIT_WORK(&irqfd->shutdown, irqfd_shutdown); -+ seqcount_init(&irqfd->irq_entry_sc); - - f = fdget(args->fd); - if (!f.file) { -@@ -466,14 +475,14 @@ kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args) - list_for_each_entry_safe(irqfd, tmp, &kvm->irqfds.items, list) { - if (irqfd->eventfd == eventfd && irqfd->gsi == args->gsi) { - /* -- * This rcu_assign_pointer is needed for when -+ * This clearing of irq_entry.type is needed for when - * another thread calls kvm_irq_routing_update before - * we flush workqueue below (we synchronize with - * kvm_irq_routing_update using irqfds.lock). -- * It is paired with synchronize_srcu done by caller -- * of that function. - */ -- rcu_assign_pointer(irqfd->irq_entry, NULL); -+ write_seqcount_begin(&irqfd->irq_entry_sc); -+ irqfd->irq_entry.type = 0; -+ write_seqcount_end(&irqfd->irq_entry_sc); - irqfd_deactivate(irqfd); - } - } --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-Give-IRQFD-its-own-separate-enabling-Kconfig-opt.patch b/debian/patches/features/powerpc/KVM-Give-IRQFD-its-own-separate-enabling-Kconfig-opt.patch deleted file mode 100644 index e416c92ce..000000000 --- a/debian/patches/features/powerpc/KVM-Give-IRQFD-its-own-separate-enabling-Kconfig-opt.patch +++ /dev/null @@ -1,174 +0,0 @@ -From: Paul Mackerras -Date: Mon, 30 Jun 2014 20:51:13 +1000 -Subject: KVM: Give IRQFD its own separate enabling Kconfig - option -Origin: https://git.kernel.org/linus/297e21053a52f060944e9f0de4c64fad9bcd72fc - -Currently, the IRQFD code is conditional on CONFIG_HAVE_KVM_IRQ_ROUTING. -So that we can have the IRQFD code compiled in without having the -IRQ routing code, this creates a new CONFIG_HAVE_KVM_IRQFD, makes -the IRQFD code conditional on it instead of CONFIG_HAVE_KVM_IRQ_ROUTING, -and makes all the platforms that currently select HAVE_KVM_IRQ_ROUTING -also select HAVE_KVM_IRQFD. - -Signed-off-by: Paul Mackerras -Tested-by: Eric Auger -Tested-by: Cornelia Huck -Signed-off-by: Paolo Bonzini ---- - arch/ia64/kvm/Kconfig | 1 + - arch/powerpc/kvm/Kconfig | 1 + - arch/s390/kvm/Kconfig | 1 + - arch/x86/kvm/Kconfig | 1 + - include/linux/kvm_host.h | 8 ++++---- - virt/kvm/Kconfig | 3 +++ - virt/kvm/eventfd.c | 6 +++--- - virt/kvm/kvm_main.c | 2 +- - 8 files changed, 15 insertions(+), 8 deletions(-) - -diff --git a/arch/ia64/kvm/Kconfig b/arch/ia64/kvm/Kconfig -index 990b864..3d50ea9 100644 ---- a/arch/ia64/kvm/Kconfig -+++ b/arch/ia64/kvm/Kconfig -@@ -25,6 +25,7 @@ config KVM - select PREEMPT_NOTIFIERS - select ANON_INODES - select HAVE_KVM_IRQCHIP -+ select HAVE_KVM_IRQFD - select HAVE_KVM_IRQ_ROUTING - select KVM_APIC_ARCHITECTURE - select KVM_MMIO -diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig -index 8f104a6..d4741db 100644 ---- a/arch/powerpc/kvm/Kconfig -+++ b/arch/powerpc/kvm/Kconfig -@@ -158,6 +158,7 @@ config KVM_MPIC - bool "KVM in-kernel MPIC emulation" - depends on KVM && E500 - select HAVE_KVM_IRQCHIP -+ select HAVE_KVM_IRQFD - select HAVE_KVM_IRQ_ROUTING - select HAVE_KVM_MSI - help -diff --git a/arch/s390/kvm/Kconfig b/arch/s390/kvm/Kconfig -index 10d529a..646db9c 100644 ---- a/arch/s390/kvm/Kconfig -+++ b/arch/s390/kvm/Kconfig -@@ -26,6 +26,7 @@ config KVM - select KVM_ASYNC_PF - select KVM_ASYNC_PF_SYNC - select HAVE_KVM_IRQCHIP -+ select HAVE_KVM_IRQFD - select HAVE_KVM_IRQ_ROUTING - ---help--- - Support hosting paravirtualized guest machines using the SIE -diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig -index 287e4c8..f9d16ff 100644 ---- a/arch/x86/kvm/Kconfig -+++ b/arch/x86/kvm/Kconfig -@@ -27,6 +27,7 @@ config KVM - select MMU_NOTIFIER - select ANON_INODES - select HAVE_KVM_IRQCHIP -+ select HAVE_KVM_IRQFD - select HAVE_KVM_IRQ_ROUTING - select HAVE_KVM_EVENTFD - select KVM_APIC_ARCHITECTURE -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index ddd33e1..8593d2e 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -437,7 +437,7 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vcpu); - int __must_check vcpu_load(struct kvm_vcpu *vcpu); - void vcpu_put(struct kvm_vcpu *vcpu); - --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -+#ifdef CONFIG_HAVE_KVM_IRQFD - int kvm_irqfd_init(void); - void kvm_irqfd_exit(void); - #else -@@ -932,20 +932,20 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, - const struct kvm_irq_routing_entry *ue); - void kvm_free_irq_routing(struct kvm *kvm); - --int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi); -- - #else - - static inline void kvm_free_irq_routing(struct kvm *kvm) {} - - #endif - -+int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi); -+ - #ifdef CONFIG_HAVE_KVM_EVENTFD - - void kvm_eventfd_init(struct kvm *kvm); - int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args); - --#ifdef CONFIG_HAVE_KVM_IRQCHIP -+#ifdef CONFIG_HAVE_KVM_IRQFD - int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args); - void kvm_irqfd_release(struct kvm *kvm); - void kvm_irq_routing_update(struct kvm *); -diff --git a/virt/kvm/Kconfig b/virt/kvm/Kconfig -index 13f2d19..fc0c5e6 100644 ---- a/virt/kvm/Kconfig -+++ b/virt/kvm/Kconfig -@@ -6,6 +6,9 @@ config HAVE_KVM - config HAVE_KVM_IRQCHIP - bool - -+config HAVE_KVM_IRQFD -+ bool -+ - config HAVE_KVM_IRQ_ROUTING - bool - -diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c -index 99957df..f5f6154 100644 ---- a/virt/kvm/eventfd.c -+++ b/virt/kvm/eventfd.c -@@ -39,7 +39,7 @@ - #include "irq.h" - #include "iodev.h" - --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -+#ifdef CONFIG_HAVE_KVM_IRQFD - /* - * -------------------------------------------------------------------- - * irqfd: Allows an fd to be used to inject an interrupt to the guest -@@ -450,7 +450,7 @@ out: - void - kvm_eventfd_init(struct kvm *kvm) - { --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -+#ifdef CONFIG_HAVE_KVM_IRQFD - spin_lock_init(&kvm->irqfds.lock); - INIT_LIST_HEAD(&kvm->irqfds.items); - INIT_LIST_HEAD(&kvm->irqfds.resampler_list); -@@ -459,7 +459,7 @@ kvm_eventfd_init(struct kvm *kvm) - INIT_LIST_HEAD(&kvm->ioeventfds); - } - --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -+#ifdef CONFIG_HAVE_KVM_IRQFD - /* - * shutdown any irqfd's that match fd+gsi - */ -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index 1b95cc9..a69a623 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -2337,7 +2337,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) - #ifdef CONFIG_HAVE_KVM_MSI - case KVM_CAP_SIGNAL_MSI: - #endif --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -+#ifdef CONFIG_HAVE_KVM_IRQFD - case KVM_CAP_IRQFD_RESAMPLE: - #endif - case KVM_CAP_CHECK_EXTENSION_VM: --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-Move-all-accesses-to-kvm-irq_routing-into-irqchi.patch b/debian/patches/features/powerpc/KVM-Move-all-accesses-to-kvm-irq_routing-into-irqchi.patch deleted file mode 100644 index 84df9b0e2..000000000 --- a/debian/patches/features/powerpc/KVM-Move-all-accesses-to-kvm-irq_routing-into-irqchi.patch +++ /dev/null @@ -1,317 +0,0 @@ -From: Paul Mackerras -Date: Mon, 30 Jun 2014 20:51:11 +1000 -Subject: KVM: Move all accesses to kvm::irq_routing into - irqchip.c -Origin: https://git.kernel.org/linus/9957c86d659a4d5a2bed25ccbd3bfc9c3f25e658 - -Now that struct _irqfd does not keep a reference to storage pointed -to by the irq_routing field of struct kvm, we can move the statement -that updates it out from under the irqfds.lock and put it in -kvm_set_irq_routing() instead. That means we then have to take a -srcu_read_lock on kvm->irq_srcu around the irqfd_update call in -kvm_irqfd_assign(), since holding the kvm->irqfds.lock no longer -ensures that that the routing can't change. - -Combined with changing kvm_irq_map_gsi() and kvm_irq_map_chip_pin() -to take a struct kvm * argument instead of the pointer to the routing -table, this allows us to to move all references to kvm->irq_routing -into irqchip.c. That in turn allows us to move the definition of the -kvm_irq_routing_table struct into irqchip.c as well. - -Signed-off-by: Paul Mackerras -Tested-by: Eric Auger -Tested-by: Cornelia Huck -Signed-off-by: Paolo Bonzini ---- - include/linux/kvm_host.h | 35 +++++++---------------------------- - virt/kvm/eventfd.c | 22 +++++++++------------- - virt/kvm/irq_comm.c | 6 ++---- - virt/kvm/irqchip.c | 39 +++++++++++++++++++++++++-------------- - 4 files changed, 43 insertions(+), 59 deletions(-) - -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index 4956149..ddd33e1 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -325,24 +325,7 @@ struct kvm_kernel_irq_routing_entry { - struct hlist_node link; - }; - --#ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -- --struct kvm_irq_routing_table { -- int chip[KVM_NR_IRQCHIPS][KVM_IRQCHIP_NUM_PINS]; -- struct kvm_kernel_irq_routing_entry *rt_entries; -- u32 nr_rt_entries; -- /* -- * Array indexed by gsi. Each entry contains list of irq chips -- * the gsi is connected to. -- */ -- struct hlist_head map[0]; --}; -- --#else -- --struct kvm_irq_routing_table {}; -- --#endif -+struct kvm_irq_routing_table; - - #ifndef KVM_PRIVATE_MEM_SLOTS - #define KVM_PRIVATE_MEM_SLOTS 0 -@@ -401,8 +384,7 @@ struct kvm { - struct mutex irq_lock; - #ifdef CONFIG_HAVE_KVM_IRQCHIP - /* -- * Update side is protected by irq_lock and, -- * if configured, irqfds.lock. -+ * Update side is protected by irq_lock. - */ - struct kvm_irq_routing_table __rcu *irq_routing; - struct hlist_head mask_notifier_list; -@@ -752,10 +734,9 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, - void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, - bool mask); - --int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries, -- struct kvm_irq_routing_table *irq_rt, int gsi); --int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt, -- unsigned irqchip, unsigned pin); -+int kvm_irq_map_gsi(struct kvm *kvm, -+ struct kvm_kernel_irq_routing_entry *entries, int gsi); -+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin); - - int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - bool line_status); -@@ -967,7 +948,7 @@ int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args); - #ifdef CONFIG_HAVE_KVM_IRQCHIP - int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args); - void kvm_irqfd_release(struct kvm *kvm); --void kvm_irq_routing_update(struct kvm *, struct kvm_irq_routing_table *); -+void kvm_irq_routing_update(struct kvm *); - #else - static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) - { -@@ -989,10 +970,8 @@ static inline int kvm_irqfd(struct kvm *kvm, struct kvm_irqfd *args) - static inline void kvm_irqfd_release(struct kvm *kvm) {} - - #ifdef CONFIG_HAVE_KVM_IRQCHIP --static inline void kvm_irq_routing_update(struct kvm *kvm, -- struct kvm_irq_routing_table *irq_rt) -+static inline void kvm_irq_routing_update(struct kvm *kvm) - { -- rcu_assign_pointer(kvm->irq_routing, irq_rt); - } - #endif - -diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c -index 15fa948..f0075ff 100644 ---- a/virt/kvm/eventfd.c -+++ b/virt/kvm/eventfd.c -@@ -278,14 +278,13 @@ irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh, - } - - /* Must be called under irqfds.lock */ --static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, -- struct kvm_irq_routing_table *irq_rt) -+static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd) - { - struct kvm_kernel_irq_routing_entry *e; - struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; - int i, n_entries; - -- n_entries = kvm_irq_map_gsi(entries, irq_rt, irqfd->gsi); -+ n_entries = kvm_irq_map_gsi(kvm, entries, irqfd->gsi); - - write_seqcount_begin(&irqfd->irq_entry_sc); - -@@ -304,12 +303,12 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, - static int - kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) - { -- struct kvm_irq_routing_table *irq_rt; - struct _irqfd *irqfd, *tmp; - struct fd f; - struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL; - int ret; - unsigned int events; -+ int idx; - - irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL); - if (!irqfd) -@@ -403,9 +402,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args) - goto fail; - } - -- irq_rt = rcu_dereference_protected(kvm->irq_routing, -- lockdep_is_held(&kvm->irqfds.lock)); -- irqfd_update(kvm, irqfd, irq_rt); -+ idx = srcu_read_lock(&kvm->irq_srcu); -+ irqfd_update(kvm, irqfd); -+ srcu_read_unlock(&kvm->irq_srcu, idx); - - list_add_tail(&irqfd->list, &kvm->irqfds.items); - -@@ -539,20 +538,17 @@ kvm_irqfd_release(struct kvm *kvm) - } - - /* -- * Change irq_routing and irqfd. -+ * Take note of a change in irq routing. - * Caller must invoke synchronize_srcu(&kvm->irq_srcu) afterwards. - */ --void kvm_irq_routing_update(struct kvm *kvm, -- struct kvm_irq_routing_table *irq_rt) -+void kvm_irq_routing_update(struct kvm *kvm) - { - struct _irqfd *irqfd; - - spin_lock_irq(&kvm->irqfds.lock); - -- rcu_assign_pointer(kvm->irq_routing, irq_rt); -- - list_for_each_entry(irqfd, &kvm->irqfds.items, list) -- irqfd_update(kvm, irqfd, irq_rt); -+ irqfd_update(kvm, irqfd); - - spin_unlock_irq(&kvm->irqfds.lock); - } -diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c -index 1758445..963b899 100644 ---- a/virt/kvm/irq_comm.c -+++ b/virt/kvm/irq_comm.c -@@ -163,7 +163,6 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level) - struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; - struct kvm_kernel_irq_routing_entry *e; - int ret = -EINVAL; -- struct kvm_irq_routing_table *irq_rt; - int idx; - - trace_kvm_set_irq(irq, level, irq_source_id); -@@ -177,8 +176,7 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level) - * which is limited to 1:1 GSI mapping. - */ - idx = srcu_read_lock(&kvm->irq_srcu); -- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -- if (kvm_irq_map_gsi(entries, irq_rt, irq) > 0) { -+ if (kvm_irq_map_gsi(kvm, entries, irq) > 0) { - e = &entries[0]; - if (likely(e->type == KVM_IRQ_ROUTING_MSI)) - ret = kvm_set_msi_inatomic(e, kvm); -@@ -264,7 +262,7 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, - int idx, gsi; - - idx = srcu_read_lock(&kvm->irq_srcu); -- gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin]; -+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); - if (gsi != -1) - hlist_for_each_entry_rcu(kimn, &kvm->mask_notifier_list, link) - if (kimn->irq == gsi) -diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c -index f4648dd..04faac5 100644 ---- a/virt/kvm/irqchip.c -+++ b/virt/kvm/irqchip.c -@@ -31,12 +31,26 @@ - #include - #include "irq.h" - --int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries, -- struct kvm_irq_routing_table *irq_rt, int gsi) -+struct kvm_irq_routing_table { -+ int chip[KVM_NR_IRQCHIPS][KVM_IRQCHIP_NUM_PINS]; -+ struct kvm_kernel_irq_routing_entry *rt_entries; -+ u32 nr_rt_entries; -+ /* -+ * Array indexed by gsi. Each entry contains list of irq chips -+ * the gsi is connected to. -+ */ -+ struct hlist_head map[0]; -+}; -+ -+int kvm_irq_map_gsi(struct kvm *kvm, -+ struct kvm_kernel_irq_routing_entry *entries, int gsi) - { -+ struct kvm_irq_routing_table *irq_rt; - struct kvm_kernel_irq_routing_entry *e; - int n = 0; - -+ irq_rt = srcu_dereference_check(kvm->irq_routing, &kvm->irq_srcu, -+ lockdep_is_held(&kvm->irq_lock)); - if (gsi < irq_rt->nr_rt_entries) { - hlist_for_each_entry(e, &irq_rt->map[gsi], link) { - entries[n] = *e; -@@ -47,21 +61,21 @@ int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries, - return n; - } - --int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt, -- unsigned irqchip, unsigned pin) -+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) - { -+ struct kvm_irq_routing_table *irq_rt; -+ -+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); - return irq_rt->chip[irqchip][pin]; - } - - bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) - { -- struct kvm_irq_routing_table *irq_rt; - struct kvm_irq_ack_notifier *kian; - int gsi, idx; - - idx = srcu_read_lock(&kvm->irq_srcu); -- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -- gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin); -+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); - if (gsi != -1) - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, - link) -@@ -78,15 +92,13 @@ EXPORT_SYMBOL_GPL(kvm_irq_has_notifier); - - void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) - { -- struct kvm_irq_routing_table *irq_rt; - struct kvm_irq_ack_notifier *kian; - int gsi, idx; - - trace_kvm_ack_irq(irqchip, pin); - - idx = srcu_read_lock(&kvm->irq_srcu); -- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -- gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin); -+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); - if (gsi != -1) - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, - link) -@@ -143,7 +155,6 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - { - struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS]; - int ret = -1, i, idx; -- struct kvm_irq_routing_table *irq_rt; - - trace_kvm_set_irq(irq, level, irq_source_id); - -@@ -152,8 +163,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - * writes to the unused one. - */ - idx = srcu_read_lock(&kvm->irq_srcu); -- irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -- i = kvm_irq_map_gsi(irq_set, irq_rt, irq); -+ i = kvm_irq_map_gsi(kvm, irq_set, irq); - srcu_read_unlock(&kvm->irq_srcu, idx); - - while(i--) { -@@ -250,7 +260,8 @@ int kvm_set_irq_routing(struct kvm *kvm, - - mutex_lock(&kvm->irq_lock); - old = kvm->irq_routing; -- kvm_irq_routing_update(kvm, new); -+ rcu_assign_pointer(kvm->irq_routing, new); -+ kvm_irq_routing_update(kvm); - mutex_unlock(&kvm->irq_lock); - - synchronize_srcu_expedited(&kvm->irq_srcu); --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-Move-irq-notifier-implementation-into-eventfd.c.patch b/debian/patches/features/powerpc/KVM-Move-irq-notifier-implementation-into-eventfd.c.patch deleted file mode 100644 index d1a8b5423..000000000 --- a/debian/patches/features/powerpc/KVM-Move-irq-notifier-implementation-into-eventfd.c.patch +++ /dev/null @@ -1,177 +0,0 @@ -From: Paul Mackerras -Date: Mon, 30 Jun 2014 20:51:12 +1000 -Subject: KVM: Move irq notifier implementation into eventfd.c -Origin: https://git.kernel.org/linus/e4d57e1ee1ab59f0cef0272800ac6c52e0ec814a - -This moves the functions kvm_irq_has_notifier(), kvm_notify_acked_irq(), -kvm_register_irq_ack_notifier() and kvm_unregister_irq_ack_notifier() -from irqchip.c to eventfd.c. The reason for doing this is that those -functions are used in connection with IRQFDs, which are implemented in -eventfd.c. In future we will want to use IRQFDs on platforms that -don't implement the GSI routing implemented in irqchip.c, so we won't -be compiling in irqchip.c, but we still need the irq notifiers. The -implementation is unchanged. - -Signed-off-by: Paul Mackerras -Tested-by: Eric Auger -Tested-by: Cornelia Huck -Signed-off-by: Paolo Bonzini ---- - virt/kvm/eventfd.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - virt/kvm/irqchip.c | 61 -------------------------------------------------- - 2 files changed, 63 insertions(+), 61 deletions(-) - -diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c -index f0075ff..99957df 100644 ---- a/virt/kvm/eventfd.c -+++ b/virt/kvm/eventfd.c -@@ -34,7 +34,9 @@ - #include - #include - #include -+#include - -+#include "irq.h" - #include "iodev.h" - - #ifdef CONFIG_HAVE_KVM_IRQ_ROUTING -@@ -865,3 +867,64 @@ kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) - - return kvm_assign_ioeventfd(kvm, args); - } -+ -+bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) -+{ -+ struct kvm_irq_ack_notifier *kian; -+ int gsi, idx; -+ -+ idx = srcu_read_lock(&kvm->irq_srcu); -+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); -+ if (gsi != -1) -+ hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, -+ link) -+ if (kian->gsi == gsi) { -+ srcu_read_unlock(&kvm->irq_srcu, idx); -+ return true; -+ } -+ -+ srcu_read_unlock(&kvm->irq_srcu, idx); -+ -+ return false; -+} -+EXPORT_SYMBOL_GPL(kvm_irq_has_notifier); -+ -+void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) -+{ -+ struct kvm_irq_ack_notifier *kian; -+ int gsi, idx; -+ -+ trace_kvm_ack_irq(irqchip, pin); -+ -+ idx = srcu_read_lock(&kvm->irq_srcu); -+ gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); -+ if (gsi != -1) -+ hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, -+ link) -+ if (kian->gsi == gsi) -+ kian->irq_acked(kian); -+ srcu_read_unlock(&kvm->irq_srcu, idx); -+} -+ -+void kvm_register_irq_ack_notifier(struct kvm *kvm, -+ struct kvm_irq_ack_notifier *kian) -+{ -+ mutex_lock(&kvm->irq_lock); -+ hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list); -+ mutex_unlock(&kvm->irq_lock); -+#ifdef __KVM_HAVE_IOAPIC -+ kvm_vcpu_request_scan_ioapic(kvm); -+#endif -+} -+ -+void kvm_unregister_irq_ack_notifier(struct kvm *kvm, -+ struct kvm_irq_ack_notifier *kian) -+{ -+ mutex_lock(&kvm->irq_lock); -+ hlist_del_init_rcu(&kian->link); -+ mutex_unlock(&kvm->irq_lock); -+ synchronize_srcu(&kvm->irq_srcu); -+#ifdef __KVM_HAVE_IOAPIC -+ kvm_vcpu_request_scan_ioapic(kvm); -+#endif -+} -diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c -index 04faac5..7f256f3 100644 ---- a/virt/kvm/irqchip.c -+++ b/virt/kvm/irqchip.c -@@ -69,67 +69,6 @@ int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) - return irq_rt->chip[irqchip][pin]; - } - --bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) --{ -- struct kvm_irq_ack_notifier *kian; -- int gsi, idx; -- -- idx = srcu_read_lock(&kvm->irq_srcu); -- gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); -- if (gsi != -1) -- hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, -- link) -- if (kian->gsi == gsi) { -- srcu_read_unlock(&kvm->irq_srcu, idx); -- return true; -- } -- -- srcu_read_unlock(&kvm->irq_srcu, idx); -- -- return false; --} --EXPORT_SYMBOL_GPL(kvm_irq_has_notifier); -- --void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) --{ -- struct kvm_irq_ack_notifier *kian; -- int gsi, idx; -- -- trace_kvm_ack_irq(irqchip, pin); -- -- idx = srcu_read_lock(&kvm->irq_srcu); -- gsi = kvm_irq_map_chip_pin(kvm, irqchip, pin); -- if (gsi != -1) -- hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, -- link) -- if (kian->gsi == gsi) -- kian->irq_acked(kian); -- srcu_read_unlock(&kvm->irq_srcu, idx); --} -- --void kvm_register_irq_ack_notifier(struct kvm *kvm, -- struct kvm_irq_ack_notifier *kian) --{ -- mutex_lock(&kvm->irq_lock); -- hlist_add_head_rcu(&kian->link, &kvm->irq_ack_notifier_list); -- mutex_unlock(&kvm->irq_lock); --#ifdef __KVM_HAVE_IOAPIC -- kvm_vcpu_request_scan_ioapic(kvm); --#endif --} -- --void kvm_unregister_irq_ack_notifier(struct kvm *kvm, -- struct kvm_irq_ack_notifier *kian) --{ -- mutex_lock(&kvm->irq_lock); -- hlist_del_init_rcu(&kian->link); -- mutex_unlock(&kvm->irq_lock); -- synchronize_srcu(&kvm->irq_srcu); --#ifdef __KVM_HAVE_IOAPIC -- kvm_vcpu_request_scan_ioapic(kvm); --#endif --} -- - int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi) - { - struct kvm_kernel_irq_routing_entry route; --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-Controls-for-in-kernel-sPAPR-hypercal.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-Controls-for-in-kernel-sPAPR-hypercal.patch deleted file mode 100644 index 9d55b11e7..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-Controls-for-in-kernel-sPAPR-hypercal.patch +++ /dev/null @@ -1,422 +0,0 @@ -From: Paul Mackerras -Date: Mon, 2 Jun 2014 11:02:59 +1000 -Subject: KVM: PPC: Book3S: Controls for in-kernel sPAPR - hypercall handling -Origin: https://git.kernel.org/linus/699a0ea0823d32030b0666b28ff8633960f7ffa7 - -This provides a way for userspace controls which sPAPR hcalls get -handled in the kernel. Each hcall can be individually enabled or -disabled for in-kernel handling, except for H_RTAS. The exception -for H_RTAS is because userspace can already control whether -individual RTAS functions are handled in-kernel or not via the -KVM_PPC_RTAS_DEFINE_TOKEN ioctl, and because the numeric value for -H_RTAS is out of the normal sequence of hcall numbers. - -Hcalls are enabled or disabled using the KVM_ENABLE_CAP ioctl for the -KVM_CAP_PPC_ENABLE_HCALL capability on the file descriptor for the VM. -The args field of the struct kvm_enable_cap specifies the hcall number -in args[0] and the enable/disable flag in args[1]; 0 means disable -in-kernel handling (so that the hcall will always cause an exit to -userspace) and 1 means enable. Enabling or disabling in-kernel -handling of an hcall is effective across the whole VM. - -The ability for KVM_ENABLE_CAP to be used on a VM file descriptor -on PowerPC is new, added by this commit. The KVM_CAP_ENABLE_CAP_VM -capability advertises that this ability exists. - -When a VM is created, an initial set of hcalls are enabled for -in-kernel handling. The set that is enabled is the set that have -an in-kernel implementation at this point. Any new hcall -implementations from this point onwards should not be added to the -default set without a good reason. - -No distinction is made between real-mode and virtual-mode hcall -implementations; the one setting controls them both. - -Signed-off-by: Paul Mackerras -Signed-off-by: Alexander Graf ---- - Documentation/virtual/kvm/api.txt | 41 +++++++++++++++++++++++-- - arch/powerpc/include/asm/kvm_book3s.h | 1 + - arch/powerpc/include/asm/kvm_host.h | 2 ++ - arch/powerpc/kernel/asm-offsets.c | 1 + - arch/powerpc/kvm/book3s_hv.c | 51 +++++++++++++++++++++++++++++++ - arch/powerpc/kvm/book3s_hv_rmhandlers.S | 11 +++++++ - arch/powerpc/kvm/book3s_pr.c | 5 +++ - arch/powerpc/kvm/book3s_pr_papr.c | 37 ++++++++++++++++++++++ - arch/powerpc/kvm/powerpc.c | 45 +++++++++++++++++++++++++++ - include/uapi/linux/kvm.h | 1 + - 10 files changed, 193 insertions(+), 2 deletions(-) - -diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt -index 0fe3649..5c54d19 100644 ---- a/Documentation/virtual/kvm/api.txt -+++ b/Documentation/virtual/kvm/api.txt -@@ -2863,8 +2863,8 @@ The fields in each entry are defined as follows: - this function/index combination - - --6. Capabilities that can be enabled ------------------------------------- -+6. Capabilities that can be enabled on vCPUs -+-------------------------------------------- - - There are certain capabilities that change the behavior of the virtual CPU when - enabled. To enable them, please see section 4.37. Below you can find a list of -@@ -3002,3 +3002,40 @@ Parameters: args[0] is the XICS device fd - args[1] is the XICS CPU number (server ID) for this vcpu - - This capability connects the vcpu to an in-kernel XICS device. -+ -+ -+7. Capabilities that can be enabled on VMs -+------------------------------------------ -+ -+There are certain capabilities that change the behavior of the virtual -+machine when enabled. To enable them, please see section 4.37. Below -+you can find a list of capabilities and what their effect on the VM -+is when enabling them. -+ -+The following information is provided along with the description: -+ -+ Architectures: which instruction set architectures provide this ioctl. -+ x86 includes both i386 and x86_64. -+ -+ Parameters: what parameters are accepted by the capability. -+ -+ Returns: the return value. General error numbers (EBADF, ENOMEM, EINVAL) -+ are not detailed, but errors with specific meanings are. -+ -+ -+7.1 KVM_CAP_PPC_ENABLE_HCALL -+ -+Architectures: ppc -+Parameters: args[0] is the sPAPR hcall number -+ args[1] is 0 to disable, 1 to enable in-kernel handling -+ -+This capability controls whether individual sPAPR hypercalls (hcalls) -+get handled by the kernel or not. Enabling or disabling in-kernel -+handling of an hcall is effective across the VM. On creation, an -+initial set of hcalls are enabled for in-kernel handling, which -+consists of those hcalls for which in-kernel handlers were implemented -+before this capability was implemented. If disabled, the kernel will -+not to attempt to handle the hcall, but will always exit to userspace -+to handle it. Note that it may not make sense to enable some and -+disable others of a group of related hcalls, but KVM does not prevent -+userspace from doing that. -diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h -index a20cc0b..052ab2a 100644 ---- a/arch/powerpc/include/asm/kvm_book3s.h -+++ b/arch/powerpc/include/asm/kvm_book3s.h -@@ -187,6 +187,7 @@ extern void kvmppc_hv_entry_trampoline(void); - extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); - extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst); - extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd); -+extern void kvmppc_pr_init_default_hcalls(struct kvm *kvm); - extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, - struct kvm_vcpu *vcpu); - extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, -diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h -index f9ae696..62b2cee 100644 ---- a/arch/powerpc/include/asm/kvm_host.h -+++ b/arch/powerpc/include/asm/kvm_host.h -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - - #define KVM_MAX_VCPUS NR_CPUS - #define KVM_MAX_VCORES NR_CPUS -@@ -263,6 +264,7 @@ struct kvm_arch { - #ifdef CONFIG_PPC_BOOK3S_64 - struct list_head spapr_tce_tables; - struct list_head rtas_tokens; -+ DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); - #endif - #ifdef CONFIG_KVM_MPIC - struct openpic *mpic; -diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c -index f5995a9..17ffcb4 100644 ---- a/arch/powerpc/kernel/asm-offsets.c -+++ b/arch/powerpc/kernel/asm-offsets.c -@@ -493,6 +493,7 @@ int main(void) - DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1)); - DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock)); - DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits)); -+ DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls)); - DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr)); - DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor)); - DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v)); -diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c -index 1562acf..cf445d2 100644 ---- a/arch/powerpc/kvm/book3s_hv.c -+++ b/arch/powerpc/kvm/book3s_hv.c -@@ -67,6 +67,8 @@ - /* Used as a "null" value for timebase values */ - #define TB_NIL (~(u64)0) - -+static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); -+ - static void kvmppc_end_cede(struct kvm_vcpu *vcpu); - static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); - -@@ -562,6 +564,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) - struct kvm_vcpu *tvcpu; - int idx, rc; - -+ if (req <= MAX_HCALL_OPCODE && -+ !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls)) -+ return RESUME_HOST; -+ - switch (req) { - case H_ENTER: - idx = srcu_read_lock(&vcpu->kvm->srcu); -@@ -2269,6 +2275,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) - */ - cpumask_setall(&kvm->arch.need_tlb_flush); - -+ /* Start out with the default set of hcalls enabled */ -+ memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls, -+ sizeof(kvm->arch.enabled_hcalls)); -+ - kvm->arch.rma = NULL; - - kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); -@@ -2407,6 +2417,45 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp, - return r; - } - -+/* -+ * List of hcall numbers to enable by default. -+ * For compatibility with old userspace, we enable by default -+ * all hcalls that were implemented before the hcall-enabling -+ * facility was added. Note this list should not include H_RTAS. -+ */ -+static unsigned int default_hcall_list[] = { -+ H_REMOVE, -+ H_ENTER, -+ H_READ, -+ H_PROTECT, -+ H_BULK_REMOVE, -+ H_GET_TCE, -+ H_PUT_TCE, -+ H_SET_DABR, -+ H_SET_XDABR, -+ H_CEDE, -+ H_PROD, -+ H_CONFER, -+ H_REGISTER_VPA, -+#ifdef CONFIG_KVM_XICS -+ H_EOI, -+ H_CPPR, -+ H_IPI, -+ H_IPOLL, -+ H_XIRR, -+ H_XIRR_X, -+#endif -+ 0 -+}; -+ -+static void init_default_hcalls(void) -+{ -+ int i; -+ -+ for (i = 0; default_hcall_list[i]; ++i) -+ __set_bit(default_hcall_list[i] / 4, default_enabled_hcalls); -+} -+ - static struct kvmppc_ops kvm_ops_hv = { - .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, - .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, -@@ -2454,6 +2503,8 @@ static int kvmppc_book3s_init_hv(void) - kvm_ops_hv.owner = THIS_MODULE; - kvmppc_hv_ops = &kvm_ops_hv; - -+ init_default_hcalls(); -+ - r = kvmppc_mmu_hv_init(); - return r; - } -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index 64ac56f..33aaade 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -1909,6 +1909,17 @@ hcall_try_real_mode: - clrrdi r3,r3,2 - cmpldi r3,hcall_real_table_end - hcall_real_table - bge guest_exit_cont -+ /* See if this hcall is enabled for in-kernel handling */ -+ ld r4, VCPU_KVM(r9) -+ srdi r0, r3, 8 /* r0 = (r3 / 4) >> 6 */ -+ sldi r0, r0, 3 /* index into kvm->arch.enabled_hcalls[] */ -+ add r4, r4, r0 -+ ld r0, KVM_ENABLED_HCALLS(r4) -+ rlwinm r4, r3, 32-2, 0x3f /* r4 = (r3 / 4) & 0x3f */ -+ srd r0, r0, r4 -+ andi. r0, r0, 1 -+ beq guest_exit_cont -+ /* Get pointer to handler, if any, and call it */ - LOAD_REG_ADDR(r4, hcall_real_table) - lwax r3,r3,r4 - cmpwi r3,0 -diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c -index 3b82e86..123ac7d 100644 ---- a/arch/powerpc/kvm/book3s_pr.c -+++ b/arch/powerpc/kvm/book3s_pr.c -@@ -1597,6 +1597,11 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm) - { - mutex_init(&kvm->arch.hpt_mutex); - -+#ifdef CONFIG_PPC_BOOK3S_64 -+ /* Start out with the default set of hcalls enabled */ -+ kvmppc_pr_init_default_hcalls(kvm); -+#endif -+ - if (firmware_has_feature(FW_FEATURE_SET_MODE)) { - spin_lock(&kvm_global_user_count_lock); - if (++kvm_global_user_count == 1) -diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c -index f7c25c6..eacaa6e 100644 ---- a/arch/powerpc/kvm/book3s_pr_papr.c -+++ b/arch/powerpc/kvm/book3s_pr_papr.c -@@ -267,6 +267,10 @@ static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd) - - int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) - { -+ if (cmd <= MAX_HCALL_OPCODE && -+ !test_bit(cmd/4, vcpu->kvm->arch.enabled_hcalls)) -+ return EMULATE_FAIL; -+ - switch (cmd) { - case H_ENTER: - return kvmppc_h_pr_enter(vcpu); -@@ -304,3 +308,36 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) - - return EMULATE_FAIL; - } -+ -+ -+/* -+ * List of hcall numbers to enable by default. -+ * For compatibility with old userspace, we enable by default -+ * all hcalls that were implemented before the hcall-enabling -+ * facility was added. Note this list should not include H_RTAS. -+ */ -+static unsigned int default_hcall_list[] = { -+ H_ENTER, -+ H_REMOVE, -+ H_PROTECT, -+ H_BULK_REMOVE, -+ H_PUT_TCE, -+ H_CEDE, -+#ifdef CONFIG_KVM_XICS -+ H_XIRR, -+ H_CPPR, -+ H_EOI, -+ H_IPI, -+ H_IPOLL, -+ H_XIRR_X, -+#endif -+ 0 -+}; -+ -+void kvmppc_pr_init_default_hcalls(struct kvm *kvm) -+{ -+ int i; -+ -+ for (i = 0; default_hcall_list[i]; ++i) -+ __set_bit(default_hcall_list[i] / 4, kvm->arch.enabled_hcalls); -+} -diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c -index 61c738a..3222a4d 100644 ---- a/arch/powerpc/kvm/powerpc.c -+++ b/arch/powerpc/kvm/powerpc.c -@@ -387,6 +387,7 @@ int kvm_dev_ioctl_check_extension(long ext) - case KVM_CAP_PPC_UNSET_IRQ: - case KVM_CAP_PPC_IRQ_LEVEL: - case KVM_CAP_ENABLE_CAP: -+ case KVM_CAP_ENABLE_CAP_VM: - case KVM_CAP_ONE_REG: - case KVM_CAP_IOEVENTFD: - case KVM_CAP_DEVICE_CTRL: -@@ -417,6 +418,7 @@ int kvm_dev_ioctl_check_extension(long ext) - case KVM_CAP_PPC_ALLOC_HTAB: - case KVM_CAP_PPC_RTAS: - case KVM_CAP_PPC_FIXUP_HCALL: -+ case KVM_CAP_PPC_ENABLE_HCALL: - #ifdef CONFIG_KVM_XICS - case KVM_CAP_IRQ_XICS: - #endif -@@ -1099,6 +1101,40 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, - return 0; - } - -+ -+static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, -+ struct kvm_enable_cap *cap) -+{ -+ int r; -+ -+ if (cap->flags) -+ return -EINVAL; -+ -+ switch (cap->cap) { -+#ifdef CONFIG_KVM_BOOK3S_64_HANDLER -+ case KVM_CAP_PPC_ENABLE_HCALL: { -+ unsigned long hcall = cap->args[0]; -+ -+ r = -EINVAL; -+ if (hcall > MAX_HCALL_OPCODE || (hcall & 3) || -+ cap->args[1] > 1) -+ break; -+ if (cap->args[1]) -+ set_bit(hcall / 4, kvm->arch.enabled_hcalls); -+ else -+ clear_bit(hcall / 4, kvm->arch.enabled_hcalls); -+ r = 0; -+ break; -+ } -+#endif -+ default: -+ r = -EINVAL; -+ break; -+ } -+ -+ return r; -+} -+ - long kvm_arch_vm_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg) - { -@@ -1118,6 +1154,15 @@ long kvm_arch_vm_ioctl(struct file *filp, - - break; - } -+ case KVM_ENABLE_CAP: -+ { -+ struct kvm_enable_cap cap; -+ r = -EFAULT; -+ if (copy_from_user(&cap, argp, sizeof(cap))) -+ goto out; -+ r = kvm_vm_ioctl_enable_cap(kvm, &cap); -+ break; -+ } - #ifdef CONFIG_PPC_BOOK3S_64 - case KVM_CREATE_SPAPR_TCE: { - struct kvm_create_spapr_tce create_tce; -diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h -index e11d8f1..0418b74 100644 ---- a/include/uapi/linux/kvm.h -+++ b/include/uapi/linux/kvm.h -@@ -758,6 +758,7 @@ struct kvm_ppc_smmu_info { - #define KVM_CAP_VM_ATTRIBUTES 101 - #define KVM_CAP_ARM_PSCI_0_2 102 - #define KVM_CAP_PPC_FIXUP_HCALL 103 -+#define KVM_CAP_PPC_ENABLE_HCALL 104 - - #ifdef KVM_CAP_IRQ_ROUTING - --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-XICS-in-BE.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-XICS-in-BE.patch deleted file mode 100644 index 2ad635246..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-XICS-in-BE.patch +++ /dev/null @@ -1,59 +0,0 @@ -From: Alexander Graf -Date: Wed, 11 Jun 2014 10:37:52 +0200 -Subject: KVM: PPC: Book3S HV: Access XICS in BE -Origin: https://git.kernel.org/linus/76d072fb05f646eb180f161bbe06ab185af52f38 - -On the exit path from the guest we check what type of interrupt we received -if we received one. This means we're doing hardware access to the XICS interrupt -controller. - -However, when running on a little endian system, this access is byte reversed. - -So let's make sure to swizzle the bytes back again and virtually make XICS -accesses big endian. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/book3s_hv_rmhandlers.S | 18 ++++++++++++++---- - 1 file changed, 14 insertions(+), 4 deletions(-) - -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index bf5270e..364ca0c 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -2350,7 +2350,18 @@ kvmppc_read_intr: - cmpdi r6, 0 - beq- 1f - lwzcix r0, r6, r7 -- rlwinm. r3, r0, 0, 0xffffff -+ /* -+ * Save XIRR for later. Since we get in in reverse endian on LE -+ * systems, save it byte reversed and fetch it back in host endian. -+ */ -+ li r3, HSTATE_SAVED_XIRR -+ STWX_BE r0, r3, r13 -+#ifdef __LITTLE_ENDIAN__ -+ lwz r3, HSTATE_SAVED_XIRR(r13) -+#else -+ mr r3, r0 -+#endif -+ rlwinm. r3, r3, 0, 0xffffff - sync - beq 1f /* if nothing pending in the ICP */ - -@@ -2382,10 +2393,9 @@ kvmppc_read_intr: - li r3, -1 - 1: blr - --42: /* It's not an IPI and it's for the host, stash it in the PACA -- * before exit, it will be picked up by the host ICP driver -+42: /* It's not an IPI and it's for the host. We saved a copy of XIRR in -+ * the PACA earlier, it will be picked up by the host ICP driver - */ -- stw r0, HSTATE_SAVED_XIRR(r13) - li r3, 1 - b 1b - --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-guest-VPA-in-BE.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-guest-VPA-in-BE.patch deleted file mode 100644 index 27eed43b3..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-guest-VPA-in-BE.patch +++ /dev/null @@ -1,103 +0,0 @@ -From: Alexander Graf -Date: Wed, 11 Jun 2014 10:34:19 +0200 -Subject: KVM: PPC: Book3S HV: Access guest VPA in BE -Origin: https://git.kernel.org/linus/02407552256111479fbfd23a3e01218b399aaa35 - -There are a few shared data structures between the host and the guest. Most -of them get registered through the VPA interface. - -These data structures are defined to always be in big endian byte order, so -let's make sure we always access them in big endian. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/book3s_hv.c | 22 +++++++++++----------- - arch/powerpc/kvm/book3s_hv_ras.c | 6 +++--- - 2 files changed, 14 insertions(+), 14 deletions(-) - -diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c -index 7db9df2..f1281c4 100644 ---- a/arch/powerpc/kvm/book3s_hv.c -+++ b/arch/powerpc/kvm/book3s_hv.c -@@ -272,7 +272,7 @@ struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id) - static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa) - { - vpa->__old_status |= LPPACA_OLD_SHARED_PROC; -- vpa->yield_count = 1; -+ vpa->yield_count = cpu_to_be32(1); - } - - static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v, -@@ -295,8 +295,8 @@ static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v, - struct reg_vpa { - u32 dummy; - union { -- u16 hword; -- u32 word; -+ __be16 hword; -+ __be32 word; - } length; - }; - -@@ -335,9 +335,9 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu, - if (va == NULL) - return H_PARAMETER; - if (subfunc == H_VPA_REG_VPA) -- len = ((struct reg_vpa *)va)->length.hword; -+ len = be16_to_cpu(((struct reg_vpa *)va)->length.hword); - else -- len = ((struct reg_vpa *)va)->length.word; -+ len = be32_to_cpu(((struct reg_vpa *)va)->length.word); - kvmppc_unpin_guest_page(kvm, va, vpa, false); - - /* Check length */ -@@ -542,18 +542,18 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, - return; - memset(dt, 0, sizeof(struct dtl_entry)); - dt->dispatch_reason = 7; -- dt->processor_id = vc->pcpu + vcpu->arch.ptid; -- dt->timebase = now + vc->tb_offset; -- dt->enqueue_to_dispatch_time = stolen; -- dt->srr0 = kvmppc_get_pc(vcpu); -- dt->srr1 = vcpu->arch.shregs.msr; -+ dt->processor_id = cpu_to_be16(vc->pcpu + vcpu->arch.ptid); -+ dt->timebase = cpu_to_be64(now + vc->tb_offset); -+ dt->enqueue_to_dispatch_time = cpu_to_be32(stolen); -+ dt->srr0 = cpu_to_be64(kvmppc_get_pc(vcpu)); -+ dt->srr1 = cpu_to_be64(vcpu->arch.shregs.msr); - ++dt; - if (dt == vcpu->arch.dtl.pinned_end) - dt = vcpu->arch.dtl.pinned_addr; - vcpu->arch.dtl_ptr = dt; - /* order writing *dt vs. writing vpa->dtl_idx */ - smp_wmb(); -- vpa->dtl_idx = ++vcpu->arch.dtl_index; -+ vpa->dtl_idx = cpu_to_be64(++vcpu->arch.dtl_index); - vcpu->arch.dtl.dirty = true; - } - -diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c -index 3a5c568..d562c8e 100644 ---- a/arch/powerpc/kvm/book3s_hv_ras.c -+++ b/arch/powerpc/kvm/book3s_hv_ras.c -@@ -45,14 +45,14 @@ static void reload_slb(struct kvm_vcpu *vcpu) - return; - - /* Sanity check */ -- n = min_t(u32, slb->persistent, SLB_MIN_SIZE); -+ n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE); - if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end) - return; - - /* Load up the SLB from that */ - for (i = 0; i < n; ++i) { -- unsigned long rb = slb->save_area[i].esid; -- unsigned long rs = slb->save_area[i].vsid; -+ unsigned long rb = be64_to_cpu(slb->save_area[i].esid); -+ unsigned long rs = be64_to_cpu(slb->save_area[i].vsid); - - rb = (rb & ~0xFFFul) | i; /* insert entry number */ - asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb)); --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-host-lppaca-and-shadow-slb-.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-host-lppaca-and-shadow-slb-.patch deleted file mode 100644 index cbd8260cf..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Access-host-lppaca-and-shadow-slb-.patch +++ /dev/null @@ -1,74 +0,0 @@ -From: Alexander Graf -Date: Wed, 11 Jun 2014 10:36:17 +0200 -Subject: KVM: PPC: Book3S HV: Access host lppaca and shadow slb - in BE -Origin: https://git.kernel.org/linus/0865a583a4881975cc4b621f4886c02f01600302 - -Some data structures are always stored in big endian. Among those are the LPPACA -fields as well as the shadow slb. These structures might be shared with a -hypervisor. - -So whenever we access those fields, make sure we do so in big endian byte order. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/book3s_hv_rmhandlers.S | 20 ++++++++++---------- - 1 file changed, 10 insertions(+), 10 deletions(-) - -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index e66c1e38..bf5270e 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -32,10 +32,6 @@ - - #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM) - --#ifdef __LITTLE_ENDIAN__ --#error Need to fix lppaca and SLB shadow accesses in little endian mode --#endif -- - /* Values in HSTATE_NAPPING(r13) */ - #define NAPPING_CEDE 1 - #define NAPPING_NOVCPU 2 -@@ -595,9 +591,10 @@ kvmppc_got_guest: - ld r3, VCPU_VPA(r4) - cmpdi r3, 0 - beq 25f -- lwz r5, LPPACA_YIELDCOUNT(r3) -+ li r6, LPPACA_YIELDCOUNT -+ LWZX_BE r5, r3, r6 - addi r5, r5, 1 -- stw r5, LPPACA_YIELDCOUNT(r3) -+ STWX_BE r5, r3, r6 - li r6, 1 - stb r6, VCPU_VPA_DIRTY(r4) - 25: -@@ -1442,9 +1439,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM) - ld r8, VCPU_VPA(r9) /* do they have a VPA? */ - cmpdi r8, 0 - beq 25f -- lwz r3, LPPACA_YIELDCOUNT(r8) -+ li r4, LPPACA_YIELDCOUNT -+ LWZX_BE r3, r8, r4 - addi r3, r3, 1 -- stw r3, LPPACA_YIELDCOUNT(r8) -+ STWX_BE r3, r8, r4 - li r3, 1 - stb r3, VCPU_VPA_DIRTY(r9) - 25: -@@ -1757,8 +1755,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) - 33: ld r8,PACA_SLBSHADOWPTR(r13) - - .rept SLB_NUM_BOLTED -- ld r5,SLBSHADOW_SAVEAREA(r8) -- ld r6,SLBSHADOW_SAVEAREA+8(r8) -+ li r3, SLBSHADOW_SAVEAREA -+ LDX_BE r5, r8, r3 -+ addi r3, r3, 8 -+ LDX_BE r6, r8, r3 - andis. r7,r5,SLB_ESID_V@h - beq 1f - slbmte r6,r5 --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Enable-for-little-endian-hosts.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Enable-for-little-endian-hosts.patch deleted file mode 100644 index 640f454fb..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Enable-for-little-endian-hosts.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: Alexander Graf -Date: Wed, 11 Jun 2014 10:39:38 +0200 -Subject: KVM: PPC: Book3S HV: Enable for little endian hosts -Origin: https://git.kernel.org/linus/6947f948f06128409b94306afaca5ece873ee5a2 - -Now that we've fixed all the issues that HV KVM code had on little endian -hosts, we can enable it in the kernel configuration for users to play with. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/Kconfig | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig -index d6a53b9..8aeeda1 100644 ---- a/arch/powerpc/kvm/Kconfig -+++ b/arch/powerpc/kvm/Kconfig -@@ -75,7 +75,6 @@ config KVM_BOOK3S_64 - config KVM_BOOK3S_64_HV - tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host" - depends on KVM_BOOK3S_64 -- depends on !CPU_LITTLE_ENDIAN - select KVM_BOOK3S_HV_POSSIBLE - select MMU_NOTIFIER - select CMA --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-indirect-branch-issue.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-indirect-branch-issue.patch deleted file mode 100644 index 44ec58b93..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-indirect-branch-issue.patch +++ /dev/null @@ -1,32 +0,0 @@ -From: Anton Blanchard -Date: Thu, 12 Jun 2014 18:16:10 +1000 -Subject: KVM: PPC: Book3S HV: Fix ABIv2 indirect branch issue -Origin: https://git.kernel.org/linus/05a308c722822b0fbcc706b54be70f9bb9d52539 - -To establish addressability quickly, ABIv2 requires the target -address of the function being called to be in r12. - -Signed-off-by: Anton Blanchard -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/book3s_hv_rmhandlers.S | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index 868347e..da1cac5 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -1913,8 +1913,8 @@ hcall_try_real_mode: - lwax r3,r3,r4 - cmpwi r3,0 - beq guest_exit_cont -- add r3,r3,r4 -- mtctr r3 -+ add r12,r3,r4 -+ mtctr r12 - mr r3,r9 /* get vcpu pointer */ - ld r4,VCPU_GPR(R4)(r9) - bctrl --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-on-LE.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-on-LE.patch deleted file mode 100644 index 434820d79..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-on-LE.patch +++ /dev/null @@ -1,74 +0,0 @@ -From: Alexander Graf -Date: Mon, 16 Jun 2014 14:41:15 +0200 -Subject: KVM: PPC: Book3S HV: Fix ABIv2 on LE -Origin: https://git.kernel.org/linus/9bf163f86d0dc2f9070d9b1b8c27cedcf8eec816 - -For code that doesn't live in modules we can just branch to the real function -names, giving us compatibility with ABIv1 and ABIv2. - -Do this for the compiled-in code of HV KVM. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/book3s_hv_rmhandlers.S | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -index 364ca0c..855521e 100644 ---- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S -+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S -@@ -668,9 +668,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM) - - mr r31, r4 - addi r3, r31, VCPU_FPRS_TM -- bl .load_fp_state -+ bl load_fp_state - addi r3, r31, VCPU_VRS_TM -- bl .load_vr_state -+ bl load_vr_state - mr r4, r31 - lwz r7, VCPU_VRSAVE_TM(r4) - mtspr SPRN_VRSAVE, r7 -@@ -1414,9 +1414,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM) - - /* Save FP/VSX. */ - addi r3, r9, VCPU_FPRS_TM -- bl .store_fp_state -+ bl store_fp_state - addi r3, r9, VCPU_VRS_TM -- bl .store_vr_state -+ bl store_vr_state - mfspr r6, SPRN_VRSAVE - stw r6, VCPU_VRSAVE_TM(r9) - 1: -@@ -2430,11 +2430,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) - mtmsrd r8 - isync - addi r3,r3,VCPU_FPRS -- bl .store_fp_state -+ bl store_fp_state - #ifdef CONFIG_ALTIVEC - BEGIN_FTR_SECTION - addi r3,r31,VCPU_VRS -- bl .store_vr_state -+ bl store_vr_state - END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) - #endif - mfspr r6,SPRN_VRSAVE -@@ -2466,11 +2466,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) - mtmsrd r8 - isync - addi r3,r4,VCPU_FPRS -- bl .load_fp_state -+ bl load_fp_state - #ifdef CONFIG_ALTIVEC - BEGIN_FTR_SECTION - addi r3,r31,VCPU_VRS -- bl .load_vr_state -+ bl load_vr_state - END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) - #endif - lwz r7,VCPU_VRSAVE(r31) --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Make-HTAB-code-LE-host-aware.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Make-HTAB-code-LE-host-aware.patch deleted file mode 100644 index bc85eaa0d..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-HV-Make-HTAB-code-LE-host-aware.patch +++ /dev/null @@ -1,881 +0,0 @@ -From: Alexander Graf -Date: Wed, 11 Jun 2014 10:16:06 +0200 -Subject: KVM: PPC: Book3S HV: Make HTAB code LE host aware -Origin: https://git.kernel.org/linus/6f22bd3265fb542acb2697026b953ec07298242d - -When running on an LE host all data structures are kept in little endian -byte order. However, the HTAB still needs to be maintained in big endian. - -So every time we access any HTAB we need to make sure we do so in the right -byte order. Fix up all accesses to manually byte swap. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/include/asm/kvm_book3s.h | 4 - arch/powerpc/include/asm/kvm_book3s_64.h | 15 ++- - arch/powerpc/kvm/book3s_64_mmu_hv.c | 128 ++++++++++++++------------- - arch/powerpc/kvm/book3s_hv_rm_mmu.c | 146 +++++++++++++++++-------------- - 4 files changed, 164 insertions(+), 129 deletions(-) - ---- a/arch/powerpc/include/asm/kvm_book3s.h -+++ b/arch/powerpc/include/asm/kvm_book3s.h -@@ -163,9 +163,9 @@ - bool *writable); - extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, - unsigned long *rmap, long pte_index, int realmode); --extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep, -+extern void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep, - unsigned long pte_index); --void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep, -+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep, - unsigned long pte_index); - extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr, - unsigned long *nb_ret); ---- a/arch/powerpc/include/asm/kvm_book3s_64.h -+++ b/arch/powerpc/include/asm/kvm_book3s_64.h -@@ -59,20 +59,29 @@ - /* These bits are reserved in the guest view of the HPTE */ - #define HPTE_GR_RESERVED HPTE_GR_MODIFIED - --static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits) -+static inline long try_lock_hpte(__be64 *hpte, unsigned long bits) - { - unsigned long tmp, old; -+ __be64 be_lockbit, be_bits; -+ -+ /* -+ * We load/store in native endian, but the HTAB is in big endian. If -+ * we byte swap all data we apply on the PTE we're implicitly correct -+ * again. -+ */ -+ be_lockbit = cpu_to_be64(HPTE_V_HVLOCK); -+ be_bits = cpu_to_be64(bits); - - asm volatile(" ldarx %0,0,%2\n" - " and. %1,%0,%3\n" - " bne 2f\n" -- " ori %0,%0,%4\n" -+ " or %0,%0,%4\n" - " stdcx. %0,0,%2\n" - " beq+ 2f\n" - " mr %1,%3\n" - "2: isync" - : "=&r" (tmp), "=&r" (old) -- : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK) -+ : "r" (hpte), "r" (be_bits), "r" (be_lockbit) - : "cc", "memory"); - return old == 0; - } ---- a/arch/powerpc/kvm/book3s_64_mmu_hv.c -+++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c -@@ -450,7 +450,7 @@ - unsigned long slb_v; - unsigned long pp, key; - unsigned long v, gr; -- unsigned long *hptep; -+ __be64 *hptep; - int index; - int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR); - -@@ -473,13 +473,13 @@ - preempt_enable(); - return -ENOENT; - } -- hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4)); -- v = hptep[0] & ~HPTE_V_HVLOCK; -+ hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4)); -+ v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; - gr = kvm->arch.revmap[index].guest_rpte; - - /* Unlock the HPTE */ - asm volatile("lwsync" : : : "memory"); -- hptep[0] = v; -+ hptep[0] = cpu_to_be64(v); - preempt_enable(); - - gpte->eaddr = eaddr; -@@ -583,7 +583,8 @@ - unsigned long ea, unsigned long dsisr) - { - struct kvm *kvm = vcpu->kvm; -- unsigned long *hptep, hpte[3], r; -+ unsigned long hpte[3], r; -+ __be64 *hptep; - unsigned long mmu_seq, psize, pte_size; - unsigned long gpa_base, gfn_base; - unsigned long gpa, gfn, hva, pfn; -@@ -606,16 +607,16 @@ - if (ea != vcpu->arch.pgfault_addr) - return RESUME_GUEST; - index = vcpu->arch.pgfault_index; -- hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4)); -+ hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4)); - rev = &kvm->arch.revmap[index]; - preempt_disable(); - while (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) - cpu_relax(); -- hpte[0] = hptep[0] & ~HPTE_V_HVLOCK; -- hpte[1] = hptep[1]; -+ hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; -+ hpte[1] = be64_to_cpu(hptep[1]); - hpte[2] = r = rev->guest_rpte; - asm volatile("lwsync" : : : "memory"); -- hptep[0] = hpte[0]; -+ hptep[0] = cpu_to_be64(hpte[0]); - preempt_enable(); - - if (hpte[0] != vcpu->arch.pgfault_hpte[0] || -@@ -731,8 +732,9 @@ - preempt_disable(); - while (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) - cpu_relax(); -- if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] || -- rev->guest_rpte != hpte[2]) -+ if ((be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK) != hpte[0] || -+ be64_to_cpu(hptep[1]) != hpte[1] || -+ rev->guest_rpte != hpte[2]) - /* HPTE has been changed under us; let the guest retry */ - goto out_unlock; - hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID; -@@ -752,20 +754,20 @@ - rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT; - r &= rcbits | ~(HPTE_R_R | HPTE_R_C); - -- if (hptep[0] & HPTE_V_VALID) { -+ if (be64_to_cpu(hptep[0]) & HPTE_V_VALID) { - /* HPTE was previously valid, so we need to invalidate it */ - unlock_rmap(rmap); -- hptep[0] |= HPTE_V_ABSENT; -+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT); - kvmppc_invalidate_hpte(kvm, hptep, index); - /* don't lose previous R and C bits */ -- r |= hptep[1] & (HPTE_R_R | HPTE_R_C); -+ r |= be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C); - } else { - kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0); - } - -- hptep[1] = r; -+ hptep[1] = cpu_to_be64(r); - eieio(); -- hptep[0] = hpte[0]; -+ hptep[0] = cpu_to_be64(hpte[0]); - asm volatile("ptesync" : : : "memory"); - preempt_enable(); - if (page && hpte_is_writable(r)) -@@ -784,7 +786,7 @@ - return ret; - - out_unlock: -- hptep[0] &= ~HPTE_V_HVLOCK; -+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); - preempt_enable(); - goto out_put; - } -@@ -860,7 +862,7 @@ - { - struct revmap_entry *rev = kvm->arch.revmap; - unsigned long h, i, j; -- unsigned long *hptep; -+ __be64 *hptep; - unsigned long ptel, psize, rcbits; - - for (;;) { -@@ -876,11 +878,11 @@ - * rmap chain lock. - */ - i = *rmapp & KVMPPC_RMAP_INDEX; -- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4)); -+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4)); - if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { - /* unlock rmap before spinning on the HPTE lock */ - unlock_rmap(rmapp); -- while (hptep[0] & HPTE_V_HVLOCK) -+ while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK) - cpu_relax(); - continue; - } -@@ -899,14 +901,14 @@ - - /* Now check and modify the HPTE */ - ptel = rev[i].guest_rpte; -- psize = hpte_page_size(hptep[0], ptel); -- if ((hptep[0] & HPTE_V_VALID) && -+ psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel); -+ if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) && - hpte_rpn(ptel, psize) == gfn) { - if (kvm->arch.using_mmu_notifiers) -- hptep[0] |= HPTE_V_ABSENT; -+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT); - kvmppc_invalidate_hpte(kvm, hptep, i); - /* Harvest R and C */ -- rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C); -+ rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C); - *rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT; - if (rcbits & ~rev[i].guest_rpte) { - rev[i].guest_rpte = ptel | rcbits; -@@ -914,7 +916,7 @@ - } - } - unlock_rmap(rmapp); -- hptep[0] &= ~HPTE_V_HVLOCK; -+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); - } - return 0; - } -@@ -961,7 +963,7 @@ - { - struct revmap_entry *rev = kvm->arch.revmap; - unsigned long head, i, j; -- unsigned long *hptep; -+ __be64 *hptep; - int ret = 0; - - retry: -@@ -977,23 +979,24 @@ - - i = head = *rmapp & KVMPPC_RMAP_INDEX; - do { -- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4)); -+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4)); - j = rev[i].forw; - - /* If this HPTE isn't referenced, ignore it */ -- if (!(hptep[1] & HPTE_R_R)) -+ if (!(be64_to_cpu(hptep[1]) & HPTE_R_R)) - continue; - - if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { - /* unlock rmap before spinning on the HPTE lock */ - unlock_rmap(rmapp); -- while (hptep[0] & HPTE_V_HVLOCK) -+ while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK) - cpu_relax(); - goto retry; - } - - /* Now check and modify the HPTE */ -- if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) { -+ if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) && -+ (be64_to_cpu(hptep[1]) & HPTE_R_R)) { - kvmppc_clear_ref_hpte(kvm, hptep, i); - if (!(rev[i].guest_rpte & HPTE_R_R)) { - rev[i].guest_rpte |= HPTE_R_R; -@@ -1001,7 +1004,7 @@ - } - ret = 1; - } -- hptep[0] &= ~HPTE_V_HVLOCK; -+ hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); - } while ((i = j) != head); - - unlock_rmap(rmapp); -@@ -1035,7 +1038,7 @@ - do { - hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4)); - j = rev[i].forw; -- if (hp[1] & HPTE_R_R) -+ if (be64_to_cpu(hp[1]) & HPTE_R_R) - goto out; - } while ((i = j) != head); - } -@@ -1075,7 +1078,7 @@ - unsigned long head, i, j; - unsigned long n; - unsigned long v, r; -- unsigned long *hptep; -+ __be64 *hptep; - int npages_dirty = 0; - - retry: -@@ -1091,7 +1094,8 @@ - - i = head = *rmapp & KVMPPC_RMAP_INDEX; - do { -- hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4)); -+ unsigned long hptep1; -+ hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4)); - j = rev[i].forw; - - /* -@@ -1108,29 +1112,30 @@ - * Otherwise we need to do the tlbie even if C==0 in - * order to pick up any delayed writeback of C. - */ -- if (!(hptep[1] & HPTE_R_C) && -- (!hpte_is_writable(hptep[1]) || vcpus_running(kvm))) -+ hptep1 = be64_to_cpu(hptep[1]); -+ if (!(hptep1 & HPTE_R_C) && -+ (!hpte_is_writable(hptep1) || vcpus_running(kvm))) - continue; - - if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { - /* unlock rmap before spinning on the HPTE lock */ - unlock_rmap(rmapp); -- while (hptep[0] & HPTE_V_HVLOCK) -+ while (hptep[0] & cpu_to_be64(HPTE_V_HVLOCK)) - cpu_relax(); - goto retry; - } - - /* Now check and modify the HPTE */ -- if (!(hptep[0] & HPTE_V_VALID)) -+ if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID))) - continue; - - /* need to make it temporarily absent so C is stable */ -- hptep[0] |= HPTE_V_ABSENT; -+ hptep[0] |= cpu_to_be64(HPTE_V_ABSENT); - kvmppc_invalidate_hpte(kvm, hptep, i); -- v = hptep[0]; -- r = hptep[1]; -+ v = be64_to_cpu(hptep[0]); -+ r = be64_to_cpu(hptep[1]); - if (r & HPTE_R_C) { -- hptep[1] = r & ~HPTE_R_C; -+ hptep[1] = cpu_to_be64(r & ~HPTE_R_C); - if (!(rev[i].guest_rpte & HPTE_R_C)) { - rev[i].guest_rpte |= HPTE_R_C; - note_hpte_modification(kvm, &rev[i]); -@@ -1143,7 +1148,7 @@ - } - v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK); - v |= HPTE_V_VALID; -- hptep[0] = v; -+ hptep[0] = cpu_to_be64(v); - } while ((i = j) != head); - - unlock_rmap(rmapp); -@@ -1307,7 +1312,7 @@ - * Returns 1 if this HPT entry has been modified or has pending - * R/C bit changes. - */ --static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp) -+static int hpte_dirty(struct revmap_entry *revp, __be64 *hptp) - { - unsigned long rcbits_unset; - -@@ -1316,13 +1321,14 @@ - - /* Also need to consider changes in reference and changed bits */ - rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C); -- if ((hptp[0] & HPTE_V_VALID) && (hptp[1] & rcbits_unset)) -+ if ((be64_to_cpu(hptp[0]) & HPTE_V_VALID) && -+ (be64_to_cpu(hptp[1]) & rcbits_unset)) - return 1; - - return 0; - } - --static long record_hpte(unsigned long flags, unsigned long *hptp, -+static long record_hpte(unsigned long flags, __be64 *hptp, - unsigned long *hpte, struct revmap_entry *revp, - int want_valid, int first_pass) - { -@@ -1337,10 +1343,10 @@ - return 0; - - valid = 0; -- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) { -+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) { - valid = 1; - if ((flags & KVM_GET_HTAB_BOLTED_ONLY) && -- !(hptp[0] & HPTE_V_BOLTED)) -+ !(be64_to_cpu(hptp[0]) & HPTE_V_BOLTED)) - valid = 0; - } - if (valid != want_valid) -@@ -1352,7 +1358,7 @@ - preempt_disable(); - while (!try_lock_hpte(hptp, HPTE_V_HVLOCK)) - cpu_relax(); -- v = hptp[0]; -+ v = be64_to_cpu(hptp[0]); - - /* re-evaluate valid and dirty from synchronized HPTE value */ - valid = !!(v & HPTE_V_VALID); -@@ -1360,9 +1366,9 @@ - - /* Harvest R and C into guest view if necessary */ - rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C); -- if (valid && (rcbits_unset & hptp[1])) { -- revp->guest_rpte |= (hptp[1] & (HPTE_R_R | HPTE_R_C)) | -- HPTE_GR_MODIFIED; -+ if (valid && (rcbits_unset & be64_to_cpu(hptp[1]))) { -+ revp->guest_rpte |= (be64_to_cpu(hptp[1]) & -+ (HPTE_R_R | HPTE_R_C)) | HPTE_GR_MODIFIED; - dirty = 1; - } - -@@ -1381,13 +1387,13 @@ - revp->guest_rpte = r; - } - asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); -- hptp[0] &= ~HPTE_V_HVLOCK; -+ hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); - preempt_enable(); - if (!(valid == want_valid && (first_pass || dirty))) - ok = 0; - } -- hpte[0] = v; -- hpte[1] = r; -+ hpte[0] = cpu_to_be64(v); -+ hpte[1] = cpu_to_be64(r); - return ok; - } - -@@ -1397,7 +1403,7 @@ - struct kvm_htab_ctx *ctx = file->private_data; - struct kvm *kvm = ctx->kvm; - struct kvm_get_htab_header hdr; -- unsigned long *hptp; -+ __be64 *hptp; - struct revmap_entry *revp; - unsigned long i, nb, nw; - unsigned long __user *lbuf; -@@ -1413,7 +1419,7 @@ - flags = ctx->flags; - - i = ctx->index; -- hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); -+ hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); - revp = kvm->arch.revmap + i; - lbuf = (unsigned long __user *)buf; - -@@ -1497,7 +1503,7 @@ - unsigned long i, j; - unsigned long v, r; - unsigned long __user *lbuf; -- unsigned long *hptp; -+ __be64 *hptp; - unsigned long tmp[2]; - ssize_t nb; - long int err, ret; -@@ -1539,7 +1545,7 @@ - i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte) - break; - -- hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); -+ hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); - lbuf = (unsigned long __user *)buf; - for (j = 0; j < hdr.n_valid; ++j) { - err = -EFAULT; -@@ -1551,7 +1557,7 @@ - lbuf += 2; - nb += HPTE_SIZE; - -- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) -+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) - kvmppc_do_h_remove(kvm, 0, i, 0, tmp); - err = -EIO; - ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r, -@@ -1577,7 +1583,7 @@ - } - - for (j = 0; j < hdr.n_invalid; ++j) { -- if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) -+ if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) - kvmppc_do_h_remove(kvm, 0, i, 0, tmp); - ++i; - hptp += 2; ---- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c -+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c -@@ -154,10 +154,10 @@ - return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift); - } - --static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v) -+static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v) - { - asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); -- hpte[0] = hpte_v; -+ hpte[0] = cpu_to_be64(hpte_v); - } - - long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, -@@ -166,7 +166,7 @@ - { - unsigned long i, pa, gpa, gfn, psize; - unsigned long slot_fn, hva; -- unsigned long *hpte; -+ __be64 *hpte; - struct revmap_entry *rev; - unsigned long g_ptel; - struct kvm_memory_slot *memslot; -@@ -275,9 +275,9 @@ - return H_PARAMETER; - if (likely((flags & H_EXACT) == 0)) { - pte_index &= ~7UL; -- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); -+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); - for (i = 0; i < 8; ++i) { -- if ((*hpte & HPTE_V_VALID) == 0 && -+ if ((be64_to_cpu(*hpte) & HPTE_V_VALID) == 0 && - try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID | - HPTE_V_ABSENT)) - break; -@@ -292,11 +292,13 @@ - */ - hpte -= 16; - for (i = 0; i < 8; ++i) { -+ u64 pte; - while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) - cpu_relax(); -- if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT))) -+ pte = be64_to_cpu(*hpte); -+ if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT))) - break; -- *hpte &= ~HPTE_V_HVLOCK; -+ *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK); - hpte += 2; - } - if (i == 8) -@@ -304,14 +306,17 @@ - } - pte_index += i; - } else { -- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); -+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); - if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID | - HPTE_V_ABSENT)) { - /* Lock the slot and check again */ -+ u64 pte; -+ - while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) - cpu_relax(); -- if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) { -- *hpte &= ~HPTE_V_HVLOCK; -+ pte = be64_to_cpu(*hpte); -+ if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) { -+ *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK); - return H_PTEG_FULL; - } - } -@@ -347,11 +352,11 @@ - } - } - -- hpte[1] = ptel; -+ hpte[1] = cpu_to_be64(ptel); - - /* Write the first HPTE dword, unlocking the HPTE and making it valid */ - eieio(); -- hpte[0] = pteh; -+ hpte[0] = cpu_to_be64(pteh); - asm volatile("ptesync" : : : "memory"); - - *pte_idx_ret = pte_index; -@@ -468,30 +473,35 @@ - unsigned long pte_index, unsigned long avpn, - unsigned long *hpret) - { -- unsigned long *hpte; -+ __be64 *hpte; - unsigned long v, r, rb; - struct revmap_entry *rev; -+ u64 pte; - - if (pte_index >= kvm->arch.hpt_npte) - return H_PARAMETER; -- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); -+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); - while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) - cpu_relax(); -- if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || -- ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) || -- ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) { -- hpte[0] &= ~HPTE_V_HVLOCK; -+ pte = be64_to_cpu(hpte[0]); -+ if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || -+ ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) || -+ ((flags & H_ANDCOND) && (pte & avpn) != 0)) { -+ hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); - return H_NOT_FOUND; - } - - rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); -- v = hpte[0] & ~HPTE_V_HVLOCK; -+ v = pte & ~HPTE_V_HVLOCK; - if (v & HPTE_V_VALID) { -- hpte[0] &= ~HPTE_V_VALID; -- rb = compute_tlbie_rb(v, hpte[1], pte_index); -+ u64 pte1; -+ -+ pte1 = be64_to_cpu(hpte[1]); -+ hpte[0] &= ~cpu_to_be64(HPTE_V_VALID); -+ rb = compute_tlbie_rb(v, pte1, pte_index); - do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true); - /* Read PTE low word after tlbie to get final R/C values */ -- remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]); -+ remove_revmap_chain(kvm, pte_index, rev, v, pte1); - } - r = rev->guest_rpte & ~HPTE_GR_RESERVED; - note_hpte_modification(kvm, rev); -@@ -514,12 +524,14 @@ - { - struct kvm *kvm = vcpu->kvm; - unsigned long *args = &vcpu->arch.gpr[4]; -- unsigned long *hp, *hptes[4], tlbrb[4]; -+ __be64 *hp, *hptes[4]; -+ unsigned long tlbrb[4]; - long int i, j, k, n, found, indexes[4]; - unsigned long flags, req, pte_index, rcbits; - int global; - long int ret = H_SUCCESS; - struct revmap_entry *rev, *revs[4]; -+ u64 hp0; - - global = global_invalidates(kvm, 0); - for (i = 0; i < 4 && ret == H_SUCCESS; ) { -@@ -542,8 +554,7 @@ - ret = H_PARAMETER; - break; - } -- hp = (unsigned long *) -- (kvm->arch.hpt_virt + (pte_index << 4)); -+ hp = (__be64 *) (kvm->arch.hpt_virt + (pte_index << 4)); - /* to avoid deadlock, don't spin except for first */ - if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) { - if (n) -@@ -552,23 +563,24 @@ - cpu_relax(); - } - found = 0; -- if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) { -+ hp0 = be64_to_cpu(hp[0]); -+ if (hp0 & (HPTE_V_ABSENT | HPTE_V_VALID)) { - switch (flags & 3) { - case 0: /* absolute */ - found = 1; - break; - case 1: /* andcond */ -- if (!(hp[0] & args[j + 1])) -+ if (!(hp0 & args[j + 1])) - found = 1; - break; - case 2: /* AVPN */ -- if ((hp[0] & ~0x7fUL) == args[j + 1]) -+ if ((hp0 & ~0x7fUL) == args[j + 1]) - found = 1; - break; - } - } - if (!found) { -- hp[0] &= ~HPTE_V_HVLOCK; -+ hp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); - args[j] = ((0x90 | flags) << 56) + pte_index; - continue; - } -@@ -577,7 +589,7 @@ - rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); - note_hpte_modification(kvm, rev); - -- if (!(hp[0] & HPTE_V_VALID)) { -+ if (!(hp0 & HPTE_V_VALID)) { - /* insert R and C bits from PTE */ - rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); - args[j] |= rcbits << (56 - 5); -@@ -585,8 +597,10 @@ - continue; - } - -- hp[0] &= ~HPTE_V_VALID; /* leave it locked */ -- tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index); -+ /* leave it locked */ -+ hp[0] &= ~cpu_to_be64(HPTE_V_VALID); -+ tlbrb[n] = compute_tlbie_rb(be64_to_cpu(hp[0]), -+ be64_to_cpu(hp[1]), pte_index); - indexes[n] = j; - hptes[n] = hp; - revs[n] = rev; -@@ -605,7 +619,8 @@ - pte_index = args[j] & ((1ul << 56) - 1); - hp = hptes[k]; - rev = revs[k]; -- remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]); -+ remove_revmap_chain(kvm, pte_index, rev, -+ be64_to_cpu(hp[0]), be64_to_cpu(hp[1])); - rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); - args[j] |= rcbits << (56 - 5); - hp[0] = 0; -@@ -620,23 +635,25 @@ - unsigned long va) - { - struct kvm *kvm = vcpu->kvm; -- unsigned long *hpte; -+ __be64 *hpte; - struct revmap_entry *rev; - unsigned long v, r, rb, mask, bits; -+ u64 pte; - - if (pte_index >= kvm->arch.hpt_npte) - return H_PARAMETER; - -- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); -+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); - while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) - cpu_relax(); -- if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || -- ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) { -- hpte[0] &= ~HPTE_V_HVLOCK; -+ pte = be64_to_cpu(hpte[0]); -+ if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || -+ ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) { -+ hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); - return H_NOT_FOUND; - } - -- v = hpte[0]; -+ v = pte; - bits = (flags << 55) & HPTE_R_PP0; - bits |= (flags << 48) & HPTE_R_KEY_HI; - bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO); -@@ -650,12 +667,12 @@ - rev->guest_rpte = r; - note_hpte_modification(kvm, rev); - } -- r = (hpte[1] & ~mask) | bits; -+ r = (be64_to_cpu(hpte[1]) & ~mask) | bits; - - /* Update HPTE */ - if (v & HPTE_V_VALID) { - rb = compute_tlbie_rb(v, r, pte_index); -- hpte[0] = v & ~HPTE_V_VALID; -+ hpte[0] = cpu_to_be64(v & ~HPTE_V_VALID); - do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true); - /* - * If the host has this page as readonly but the guest -@@ -681,9 +698,9 @@ - } - } - } -- hpte[1] = r; -+ hpte[1] = cpu_to_be64(r); - eieio(); -- hpte[0] = v & ~HPTE_V_HVLOCK; -+ hpte[0] = cpu_to_be64(v & ~HPTE_V_HVLOCK); - asm volatile("ptesync" : : : "memory"); - return H_SUCCESS; - } -@@ -692,7 +709,8 @@ - unsigned long pte_index) - { - struct kvm *kvm = vcpu->kvm; -- unsigned long *hpte, v, r; -+ __be64 *hpte; -+ unsigned long v, r; - int i, n = 1; - struct revmap_entry *rev = NULL; - -@@ -704,9 +722,9 @@ - } - rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); - for (i = 0; i < n; ++i, ++pte_index) { -- hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); -- v = hpte[0] & ~HPTE_V_HVLOCK; -- r = hpte[1]; -+ hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); -+ v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK; -+ r = be64_to_cpu(hpte[1]); - if (v & HPTE_V_ABSENT) { - v &= ~HPTE_V_ABSENT; - v |= HPTE_V_VALID; -@@ -721,25 +739,27 @@ - return H_SUCCESS; - } - --void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep, -+void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep, - unsigned long pte_index) - { - unsigned long rb; - -- hptep[0] &= ~HPTE_V_VALID; -- rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index); -+ hptep[0] &= ~cpu_to_be64(HPTE_V_VALID); -+ rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]), -+ pte_index); - do_tlbies(kvm, &rb, 1, 1, true); - } - EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte); - --void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep, -+void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep, - unsigned long pte_index) - { - unsigned long rb; - unsigned char rbyte; - -- rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index); -- rbyte = (hptep[1] & ~HPTE_R_R) >> 8; -+ rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]), -+ pte_index); -+ rbyte = (be64_to_cpu(hptep[1]) & ~HPTE_R_R) >> 8; - /* modify only the second-last byte, which contains the ref bit */ - *((char *)hptep + 14) = rbyte; - do_tlbies(kvm, &rb, 1, 1, false); -@@ -765,7 +785,7 @@ - unsigned long somask; - unsigned long vsid, hash; - unsigned long avpn; -- unsigned long *hpte; -+ __be64 *hpte; - unsigned long mask, val; - unsigned long v, r; - -@@ -797,11 +817,11 @@ - val |= avpn; - - for (;;) { -- hpte = (unsigned long *)(kvm->arch.hpt_virt + (hash << 7)); -+ hpte = (__be64 *)(kvm->arch.hpt_virt + (hash << 7)); - - for (i = 0; i < 16; i += 2) { - /* Read the PTE racily */ -- v = hpte[i] & ~HPTE_V_HVLOCK; -+ v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK; - - /* Check valid/absent, hash, segment size and AVPN */ - if (!(v & valid) || (v & mask) != val) -@@ -810,8 +830,8 @@ - /* Lock the PTE and read it under the lock */ - while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK)) - cpu_relax(); -- v = hpte[i] & ~HPTE_V_HVLOCK; -- r = hpte[i+1]; -+ v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK; -+ r = be64_to_cpu(hpte[i+1]); - - /* - * Check the HPTE again, including base page size -@@ -822,7 +842,7 @@ - return (hash << 3) + (i >> 1); - - /* Unlock and move on */ -- hpte[i] = v; -+ hpte[i] = cpu_to_be64(v); - } - - if (val & HPTE_V_SECONDARY) -@@ -851,7 +871,7 @@ - struct kvm *kvm = vcpu->kvm; - long int index; - unsigned long v, r, gr; -- unsigned long *hpte; -+ __be64 *hpte; - unsigned long valid; - struct revmap_entry *rev; - unsigned long pp, key; -@@ -867,9 +887,9 @@ - return status; /* there really was no HPTE */ - return 0; /* for prot fault, HPTE disappeared */ - } -- hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4)); -- v = hpte[0] & ~HPTE_V_HVLOCK; -- r = hpte[1]; -+ hpte = (__be64 *)(kvm->arch.hpt_virt + (index << 4)); -+ v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK; -+ r = be64_to_cpu(hpte[1]); - rev = real_vmalloc_addr(&kvm->arch.revmap[index]); - gr = rev->guest_rpte; - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-PR-Fix-sparse-endian-checks.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-PR-Fix-sparse-endian-checks.patch deleted file mode 100644 index 6a1ff31ea..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-PR-Fix-sparse-endian-checks.patch +++ /dev/null @@ -1,76 +0,0 @@ -From: Alexander Graf -Date: Mon, 16 Jun 2014 13:58:11 +0200 -Subject: KVM: PPC: Book3S PR: Fix sparse endian checks -Origin: https://git.kernel.org/linus/f396df35188c59a5ecb83932190505ef297754e6 - -While sending sparse with endian checks over the code base, it triggered at -some places that were missing casts or had wrong types. Fix them up. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/book3s_pr_papr.c | 21 +++++++++++---------- - 1 file changed, 11 insertions(+), 10 deletions(-) - -diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c -index 52a63bf..f7c25c6 100644 ---- a/arch/powerpc/kvm/book3s_pr_papr.c -+++ b/arch/powerpc/kvm/book3s_pr_papr.c -@@ -40,8 +40,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu) - { - long flags = kvmppc_get_gpr(vcpu, 4); - long pte_index = kvmppc_get_gpr(vcpu, 5); -- unsigned long pteg[2 * 8]; -- unsigned long pteg_addr, i, *hpte; -+ __be64 pteg[2 * 8]; -+ __be64 *hpte; -+ unsigned long pteg_addr, i; - long int ret; - - i = pte_index & 7; -@@ -93,8 +94,8 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu) - pteg = get_pteg_addr(vcpu, pte_index); - mutex_lock(&vcpu->kvm->arch.hpt_mutex); - copy_from_user(pte, (void __user *)pteg, sizeof(pte)); -- pte[0] = be64_to_cpu(pte[0]); -- pte[1] = be64_to_cpu(pte[1]); -+ pte[0] = be64_to_cpu((__force __be64)pte[0]); -+ pte[1] = be64_to_cpu((__force __be64)pte[1]); - - ret = H_NOT_FOUND; - if ((pte[0] & HPTE_V_VALID) == 0 || -@@ -171,8 +172,8 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu) - - pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX); - copy_from_user(pte, (void __user *)pteg, sizeof(pte)); -- pte[0] = be64_to_cpu(pte[0]); -- pte[1] = be64_to_cpu(pte[1]); -+ pte[0] = be64_to_cpu((__force __be64)pte[0]); -+ pte[1] = be64_to_cpu((__force __be64)pte[1]); - - /* tsl = AVPN */ - flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26; -@@ -211,8 +212,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) - pteg = get_pteg_addr(vcpu, pte_index); - mutex_lock(&vcpu->kvm->arch.hpt_mutex); - copy_from_user(pte, (void __user *)pteg, sizeof(pte)); -- pte[0] = be64_to_cpu(pte[0]); -- pte[1] = be64_to_cpu(pte[1]); -+ pte[0] = be64_to_cpu((__force __be64)pte[0]); -+ pte[1] = be64_to_cpu((__force __be64)pte[1]); - - ret = H_NOT_FOUND; - if ((pte[0] & HPTE_V_VALID) == 0 || -@@ -231,8 +232,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) - - rb = compute_tlbie_rb(v, r, pte_index); - vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); -- pte[0] = cpu_to_be64(pte[0]); -- pte[1] = cpu_to_be64(pte[1]); -+ pte[0] = (__force u64)cpu_to_be64(pte[0]); -+ pte[1] = (__force u64)cpu_to_be64(pte[1]); - copy_to_user((void __user *)pteg, pte, sizeof(pte)); - ret = H_SUCCESS; - --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3S-PR-Handle-hyp-doorbell-exits.patch b/debian/patches/features/powerpc/KVM-PPC-Book3S-PR-Handle-hyp-doorbell-exits.patch deleted file mode 100644 index f645e9683..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3S-PR-Handle-hyp-doorbell-exits.patch +++ /dev/null @@ -1,28 +0,0 @@ -From: Alexander Graf -Date: Mon, 16 Jun 2014 16:37:38 +0200 -Subject: KVM: PPC: Book3S PR: Handle hyp doorbell exits -Origin: https://git.kernel.org/linus/568fccc43f901889b94b228cd0238916cb40e0bd - -If we're running PR KVM in HV mode, we may get hypervisor doorbell interrupts. -Handle those the same way we treat normal doorbells. - -Signed-off-by: Alexander Graf ---- - arch/powerpc/kvm/book3s_pr.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c -index 8ea7da4..3b82e86 100644 ---- a/arch/powerpc/kvm/book3s_pr.c -+++ b/arch/powerpc/kvm/book3s_pr.c -@@ -988,6 +988,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, - case BOOK3S_INTERRUPT_DECREMENTER: - case BOOK3S_INTERRUPT_HV_DECREMENTER: - case BOOK3S_INTERRUPT_DOORBELL: -+ case BOOK3S_INTERRUPT_H_DOORBELL: - vcpu->stat.dec_exits++; - r = RESUME_GUEST; - break; --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3s-HV-Fix-tlbie-compile-error.patch b/debian/patches/features/powerpc/KVM-PPC-Book3s-HV-Fix-tlbie-compile-error.patch deleted file mode 100644 index 72f9c25d6..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3s-HV-Fix-tlbie-compile-error.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Alexander Graf -Date: Wed, 11 Jun 2014 17:13:55 +0200 -Subject: KVM: PPC: Book3s HV: Fix tlbie compile error -Origin: https://git.kernel.org/linus/f6bf3a66227447f89f25b9db0ae39357decf2509 - -Some compilers complain about uninitialized variables in the compute_tlbie_rb -function. When you follow the code path you'll realize that we'll never get -to that point, but the compiler isn't all that smart. - -So just default to 4k page sizes for everything, making the compiler happy -and the code slightly easier to read. - -Signed-off-by: Alexander Graf -Acked-by: Paul Mackerras ---- - arch/powerpc/include/asm/kvm_book3s_64.h | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h -index fddb72b..c7871f3 100644 ---- a/arch/powerpc/include/asm/kvm_book3s_64.h -+++ b/arch/powerpc/include/asm/kvm_book3s_64.h -@@ -110,16 +110,12 @@ static inline int __hpte_actual_psize(unsigned int lp, int psize) - static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, - unsigned long pte_index) - { -- int b_psize, a_psize; -+ int b_psize = MMU_PAGE_4K, a_psize = MMU_PAGE_4K; - unsigned int penc; - unsigned long rb = 0, va_low, sllp; - unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1); - -- if (!(v & HPTE_V_LARGE)) { -- /* both base and actual psize is 4k */ -- b_psize = MMU_PAGE_4K; -- a_psize = MMU_PAGE_4K; -- } else { -+ if (v & HPTE_V_LARGE) { - for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) { - - /* valid entries have a shift value */ --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Book3s-PR-Disable-AIL-mode-with-OPAL.patch b/debian/patches/features/powerpc/KVM-PPC-Book3s-PR-Disable-AIL-mode-with-OPAL.patch deleted file mode 100644 index e6104d7bc..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Book3s-PR-Disable-AIL-mode-with-OPAL.patch +++ /dev/null @@ -1,63 +0,0 @@ -From: Alexander Graf -Date: Mon, 9 Jun 2014 01:16:32 +0200 -Subject: KVM: PPC: Book3s PR: Disable AIL mode with OPAL -Origin: https://git.kernel.org/linus/fb4188bad02f4871b26cf19b98e8d92499ca5d31 - -When we're using PR KVM we must not allow the CPU to take interrupts -in virtual mode, as the SLB does not contain host kernel mappings -when running inside the guest context. - -To make sure we get good performance for non-KVM tasks but still -properly functioning PR KVM, let's just disable AIL whenever a vcpu -is scheduled in. - -This is fundamentally different from how we deal with AIL on pSeries -type machines where we disable AIL for the whole machine as soon as -a single KVM VM is up. - -The reason for that is easy - on pSeries we do not have control over -per-cpu configuration of AIL. We also don't want to mess with CPU hotplug -races and AIL configuration, so setting it per CPU is easier and more -flexible. - -This patch fixes running PR KVM on POWER8 bare metal for me. - -Signed-off-by: Alexander Graf -Acked-by: Paul Mackerras ---- - arch/powerpc/kvm/book3s_pr.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c -index 3da412e..8ea7da4 100644 ---- a/arch/powerpc/kvm/book3s_pr.c -+++ b/arch/powerpc/kvm/book3s_pr.c -@@ -71,6 +71,12 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu) - svcpu->in_use = 0; - svcpu_put(svcpu); - #endif -+ -+ /* Disable AIL if supported */ -+ if (cpu_has_feature(CPU_FTR_HVMODE) && -+ cpu_has_feature(CPU_FTR_ARCH_207S)) -+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL); -+ - vcpu->cpu = smp_processor_id(); - #ifdef CONFIG_PPC_BOOK3S_32 - current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu; -@@ -91,6 +97,12 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu) - - kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX); - kvmppc_giveup_fac(vcpu, FSCR_TAR_LG); -+ -+ /* Enable AIL if supported */ -+ if (cpu_has_feature(CPU_FTR_HVMODE) && -+ cpu_has_feature(CPU_FTR_ARCH_207S)) -+ mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3); -+ - vcpu->cpu = -1; - } - --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-PPC-Enable-IRQFD-support-for-the-XICS-interrupt-.patch b/debian/patches/features/powerpc/KVM-PPC-Enable-IRQFD-support-for-the-XICS-interrupt-.patch deleted file mode 100644 index cd26cf873..000000000 --- a/debian/patches/features/powerpc/KVM-PPC-Enable-IRQFD-support-for-the-XICS-interrupt-.patch +++ /dev/null @@ -1,193 +0,0 @@ -From: Paul Mackerras -Date: Mon, 30 Jun 2014 20:51:14 +1000 -Subject: KVM: PPC: Enable IRQFD support for the XICS interrupt - controller -Origin: https://git.kernel.org/linus/25a2150bee00b4d996487552948b9b3ba21d0257 - -This makes it possible to use IRQFDs on platforms that use the XICS -interrupt controller. To do this we implement kvm_irq_map_gsi() and -kvm_irq_map_chip_pin() in book3s_xics.c, so as to provide a 1-1 mapping -between global interrupt numbers and XICS interrupt source numbers. -For now, all interrupts are mapped as "IRQCHIP" interrupts, and no -MSI support is provided. - -This means that kvm_set_irq can now get called with level == 0 or 1 -as well as the powerpc-specific values KVM_INTERRUPT_SET, -KVM_INTERRUPT_UNSET and KVM_INTERRUPT_SET_LEVEL. We change -ics_deliver_irq() to accept all those values, and remove its -report_status argument, as it is always false, given that we don't -support KVM_IRQ_LINE_STATUS. - -This also adds support for interrupt ack notifiers to the XICS code -so that the IRQFD resampler functionality can be supported. - -Signed-off-by: Paul Mackerras -Tested-by: Eric Auger -Tested-by: Cornelia Huck -Signed-off-by: Paolo Bonzini ---- - arch/powerpc/kvm/Kconfig | 2 ++ - arch/powerpc/kvm/book3s_hv_rm_xics.c | 5 ++++ - arch/powerpc/kvm/book3s_xics.c | 55 ++++++++++++++++++++++++++++------ - arch/powerpc/kvm/book3s_xics.h | 2 ++ - 4 files changed, 55 insertions(+), 9 deletions(-) - -diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig -index d4741db..602eb51 100644 ---- a/arch/powerpc/kvm/Kconfig -+++ b/arch/powerpc/kvm/Kconfig -@@ -170,6 +170,8 @@ config KVM_MPIC - config KVM_XICS - bool "KVM in-kernel XICS emulation" - depends on KVM_BOOK3S_64 && !KVM_MPIC -+ select HAVE_KVM_IRQCHIP -+ select HAVE_KVM_IRQFD - ---help--- - Include support for the XICS (eXternal Interrupt Controller - Specification) interrupt controller architecture used on -diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c -index b4b0082..3ee38e6 100644 ---- a/arch/powerpc/kvm/book3s_hv_rm_xics.c -+++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c -@@ -401,6 +401,11 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) - icp->rm_action |= XICS_RM_REJECT; - icp->rm_reject = irq; - } -+ -+ if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) { -+ icp->rm_action |= XICS_RM_NOTIFY_EOI; -+ icp->rm_eoied_irq = irq; -+ } - bail: - return check_too_hard(xics, icp); - } -diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c -index d1acd32..eaeb780 100644 ---- a/arch/powerpc/kvm/book3s_xics.c -+++ b/arch/powerpc/kvm/book3s_xics.c -@@ -64,8 +64,12 @@ - static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, - u32 new_irq); - --static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, -- bool report_status) -+/* -+ * Return value ideally indicates how the interrupt was handled, but no -+ * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS), -+ * so just return 0. -+ */ -+static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level) - { - struct ics_irq_state *state; - struct kvmppc_ics *ics; -@@ -82,17 +86,14 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, - if (!state->exists) - return -EINVAL; - -- if (report_status) -- return state->asserted; -- - /* - * We set state->asserted locklessly. This should be fine as - * we are the only setter, thus concurrent access is undefined - * to begin with. - */ -- if (level == KVM_INTERRUPT_SET_LEVEL) -+ if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL) - state->asserted = 1; -- else if (level == KVM_INTERRUPT_UNSET) { -+ else if (level == 0 || level == KVM_INTERRUPT_UNSET) { - state->asserted = 0; - return 0; - } -@@ -100,7 +101,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, - /* Attempt delivery */ - icp_deliver_irq(xics, NULL, irq); - -- return state->asserted; -+ return 0; - } - - static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics, -@@ -772,6 +773,8 @@ static noinline int kvmppc_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) - if (state->asserted) - icp_deliver_irq(xics, icp, irq); - -+ kvm_notify_acked_irq(vcpu->kvm, 0, irq); -+ - return H_SUCCESS; - } - -@@ -789,6 +792,8 @@ static noinline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall) - icp_check_resend(xics, icp); - if (icp->rm_action & XICS_RM_REJECT) - icp_deliver_irq(xics, icp, icp->rm_reject); -+ if (icp->rm_action & XICS_RM_NOTIFY_EOI) -+ kvm_notify_acked_irq(vcpu->kvm, 0, icp->rm_eoied_irq); - - icp->rm_action = 0; - -@@ -1170,7 +1175,16 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - { - struct kvmppc_xics *xics = kvm->arch.xics; - -- return ics_deliver_irq(xics, irq, level, line_status); -+ return ics_deliver_irq(xics, irq, level); -+} -+ -+int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm, -+ int irq_source_id, int level, bool line_status) -+{ -+ if (!level) -+ return -1; -+ return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi, -+ level, line_status); - } - - static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) -@@ -1301,3 +1315,26 @@ void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) - vcpu->arch.icp = NULL; - vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT; - } -+ -+static int xics_set_irq(struct kvm_kernel_irq_routing_entry *e, -+ struct kvm *kvm, int irq_source_id, int level, -+ bool line_status) -+{ -+ return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status); -+} -+ -+int kvm_irq_map_gsi(struct kvm *kvm, -+ struct kvm_kernel_irq_routing_entry *entries, int gsi) -+{ -+ entries->gsi = gsi; -+ entries->type = KVM_IRQ_ROUTING_IRQCHIP; -+ entries->set = xics_set_irq; -+ entries->irqchip.irqchip = 0; -+ entries->irqchip.pin = gsi; -+ return 1; -+} -+ -+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) -+{ -+ return pin; -+} -diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h -index dd9326c..e8aaa7a 100644 ---- a/arch/powerpc/kvm/book3s_xics.h -+++ b/arch/powerpc/kvm/book3s_xics.h -@@ -71,9 +71,11 @@ struct kvmppc_icp { - #define XICS_RM_KICK_VCPU 0x1 - #define XICS_RM_CHECK_RESEND 0x2 - #define XICS_RM_REJECT 0x4 -+#define XICS_RM_NOTIFY_EOI 0x8 - u32 rm_action; - struct kvm_vcpu *rm_kick_target; - u32 rm_reject; -+ u32 rm_eoied_irq; - - /* Debug stuff for real mode */ - union kvmppc_icp_state rm_dbgstate; --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-Rename-and-add-argument-to-check_extension.patch b/debian/patches/features/powerpc/KVM-Rename-and-add-argument-to-check_extension.patch deleted file mode 100644 index 24849582f..000000000 --- a/debian/patches/features/powerpc/KVM-Rename-and-add-argument-to-check_extension.patch +++ /dev/null @@ -1,148 +0,0 @@ -From: Alexander Graf -Date: Mon, 14 Jul 2014 18:27:35 +0200 -Subject: KVM: Rename and add argument to check_extension -Origin: https://git.kernel.org/linus/784aa3d7fb6f729c06d5836c9d9569f58e4d05ae - -In preparation to make the check_extension function available to VM scope -we add a struct kvm * argument to the function header and rename the function -accordingly. It will still be called from the /dev/kvm fd, but with a NULL -argument for struct kvm *. - -Signed-off-by: Alexander Graf -Acked-by: Paolo Bonzini ---- - arch/arm/kvm/arm.c | 2 +- - arch/ia64/kvm/kvm-ia64.c | 2 +- - arch/mips/kvm/kvm_mips.c | 2 +- - arch/powerpc/kvm/powerpc.c | 2 +- - arch/s390/kvm/kvm-s390.c | 2 +- - arch/x86/kvm/x86.c | 2 +- - include/linux/kvm_host.h | 2 +- - virt/kvm/kvm_main.c | 6 +++--- - 8 files changed, 10 insertions(+), 10 deletions(-) - -diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c -index 3c82b37..cb77f999 100644 ---- a/arch/arm/kvm/arm.c -+++ b/arch/arm/kvm/arm.c -@@ -184,7 +184,7 @@ void kvm_arch_destroy_vm(struct kvm *kvm) - } - } - --int kvm_dev_ioctl_check_extension(long ext) -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) - { - int r; - switch (ext) { -diff --git a/arch/ia64/kvm/kvm-ia64.c b/arch/ia64/kvm/kvm-ia64.c -index 6a4309b..0729ba6 100644 ---- a/arch/ia64/kvm/kvm-ia64.c -+++ b/arch/ia64/kvm/kvm-ia64.c -@@ -190,7 +190,7 @@ void kvm_arch_check_processor_compat(void *rtn) - *(int *)rtn = 0; - } - --int kvm_dev_ioctl_check_extension(long ext) -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) - { - - int r; -diff --git a/arch/mips/kvm/kvm_mips.c b/arch/mips/kvm/kvm_mips.c -index d687c6e..3ca79aa 100644 ---- a/arch/mips/kvm/kvm_mips.c -+++ b/arch/mips/kvm/kvm_mips.c -@@ -885,7 +885,7 @@ int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) - return VM_FAULT_SIGBUS; - } - --int kvm_dev_ioctl_check_extension(long ext) -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) - { - int r; - -diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c -index 8e03568..d870bac 100644 ---- a/arch/powerpc/kvm/powerpc.c -+++ b/arch/powerpc/kvm/powerpc.c -@@ -391,7 +391,7 @@ void kvm_arch_sync_events(struct kvm *kvm) - { - } - --int kvm_dev_ioctl_check_extension(long ext) -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) - { - int r; - /* FIXME!! -diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c -index 2f3e14f..00268ca 100644 ---- a/arch/s390/kvm/kvm-s390.c -+++ b/arch/s390/kvm/kvm-s390.c -@@ -146,7 +146,7 @@ long kvm_arch_dev_ioctl(struct file *filp, - return -EINVAL; - } - --int kvm_dev_ioctl_check_extension(long ext) -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) - { - int r; - -diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c -index 5a8691b..5a62d91 100644 ---- a/arch/x86/kvm/x86.c -+++ b/arch/x86/kvm/x86.c -@@ -2616,7 +2616,7 @@ out: - return r; - } - --int kvm_dev_ioctl_check_extension(long ext) -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) - { - int r; - -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index ec4e3bd..5065b95 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -602,7 +602,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg); - int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf); - --int kvm_dev_ioctl_check_extension(long ext); -+int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext); - - int kvm_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log, int *is_dirty); -diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c -index 4b6c01b..e28f3ca 100644 ---- a/virt/kvm/kvm_main.c -+++ b/virt/kvm/kvm_main.c -@@ -2571,7 +2571,7 @@ static int kvm_dev_ioctl_create_vm(unsigned long type) - return r; - } - --static long kvm_dev_ioctl_check_extension_generic(long arg) -+static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) - { - switch (arg) { - case KVM_CAP_USER_MEMORY: -@@ -2595,7 +2595,7 @@ static long kvm_dev_ioctl_check_extension_generic(long arg) - default: - break; - } -- return kvm_dev_ioctl_check_extension(arg); -+ return kvm_vm_ioctl_check_extension(kvm, arg); - } - - static long kvm_dev_ioctl(struct file *filp, -@@ -2614,7 +2614,7 @@ static long kvm_dev_ioctl(struct file *filp, - r = kvm_dev_ioctl_create_vm(arg); - break; - case KVM_CHECK_EXTENSION: -- r = kvm_dev_ioctl_check_extension_generic(arg); -+ r = kvm_vm_ioctl_check_extension_generic(NULL, arg); - break; - case KVM_GET_VCPU_MMAP_SIZE: - r = -EINVAL; --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-irqchip-Provide-and-use-accessors-for-irq-routin.patch b/debian/patches/features/powerpc/KVM-irqchip-Provide-and-use-accessors-for-irq-routin.patch deleted file mode 100644 index a4b29676c..000000000 --- a/debian/patches/features/powerpc/KVM-irqchip-Provide-and-use-accessors-for-irq-routin.patch +++ /dev/null @@ -1,278 +0,0 @@ -From: Paul Mackerras -Date: Mon, 30 Jun 2014 20:51:10 +1000 -Subject: KVM: irqchip: Provide and use accessors for irq - routing table -Origin: https://git.kernel.org/linus/8ba918d488caded2c4368b0b922eb905fe3bb101 - -This provides accessor functions for the KVM interrupt mappings, in -order to reduce the amount of code that accesses the fields of the -kvm_irq_routing_table struct, and restrict that code to one file, -virt/kvm/irqchip.c. The new functions are kvm_irq_map_gsi(), which -maps from a global interrupt number to a set of IRQ routing entries, -and kvm_irq_map_chip_pin, which maps from IRQ chip and pin numbers to -a global interrupt number. - -This also moves the update of kvm_irq_routing_table::chip[][] -into irqchip.c, out of the various kvm_set_routing_entry -implementations. That means that none of the kvm_set_routing_entry -implementations need the kvm_irq_routing_table argument anymore, -so this removes it. - -This does not change any locking or data lifetime rules. - -Signed-off-by: Paul Mackerras -Tested-by: Eric Auger -Tested-by: Cornelia Huck -Signed-off-by: Paolo Bonzini ---- - arch/powerpc/kvm/mpic.c | 4 +--- - arch/s390/kvm/interrupt.c | 3 +-- - include/linux/kvm_host.h | 8 ++++++-- - virt/kvm/eventfd.c | 10 ++++++---- - virt/kvm/irq_comm.c | 20 +++++++++----------- - virt/kvm/irqchip.c | 42 ++++++++++++++++++++++++++++++++++-------- - 6 files changed, 57 insertions(+), 30 deletions(-) - -diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c -index b68d0dc..39b3a8f 100644 ---- a/arch/powerpc/kvm/mpic.c -+++ b/arch/powerpc/kvm/mpic.c -@@ -1826,8 +1826,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, - return 0; - } - --int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, -- struct kvm_kernel_irq_routing_entry *e, -+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, - const struct kvm_irq_routing_entry *ue) - { - int r = -EINVAL; -@@ -1839,7 +1838,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, - e->irqchip.pin = ue->u.irqchip.pin; - if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) - goto out; -- rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi; - break; - case KVM_IRQ_ROUTING_MSI: - e->set = kvm_set_msi; -diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c -index 92528a0..f4c819b 100644 ---- a/arch/s390/kvm/interrupt.c -+++ b/arch/s390/kvm/interrupt.c -@@ -1556,8 +1556,7 @@ static int set_adapter_int(struct kvm_kernel_irq_routing_entry *e, - return ret; - } - --int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, -- struct kvm_kernel_irq_routing_entry *e, -+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, - const struct kvm_irq_routing_entry *ue) - { - int ret; -diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h -index 5065b95..4956149 100644 ---- a/include/linux/kvm_host.h -+++ b/include/linux/kvm_host.h -@@ -752,6 +752,11 @@ void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, - void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, - bool mask); - -+int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries, -+ struct kvm_irq_routing_table *irq_rt, int gsi); -+int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt, -+ unsigned irqchip, unsigned pin); -+ - int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - bool line_status); - int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level); -@@ -942,8 +947,7 @@ int kvm_set_irq_routing(struct kvm *kvm, - const struct kvm_irq_routing_entry *entries, - unsigned nr, - unsigned flags); --int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, -- struct kvm_kernel_irq_routing_entry *e, -+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, - const struct kvm_irq_routing_entry *ue); - void kvm_free_irq_routing(struct kvm *kvm); - -diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c -index bae593a..15fa948 100644 ---- a/virt/kvm/eventfd.c -+++ b/virt/kvm/eventfd.c -@@ -282,20 +282,22 @@ static void irqfd_update(struct kvm *kvm, struct _irqfd *irqfd, - struct kvm_irq_routing_table *irq_rt) - { - struct kvm_kernel_irq_routing_entry *e; -+ struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; -+ int i, n_entries; -+ -+ n_entries = kvm_irq_map_gsi(entries, irq_rt, irqfd->gsi); - - write_seqcount_begin(&irqfd->irq_entry_sc); - - irqfd->irq_entry.type = 0; -- if (irqfd->gsi >= irq_rt->nr_rt_entries) -- goto out; - -- hlist_for_each_entry(e, &irq_rt->map[irqfd->gsi], link) { -+ e = entries; -+ for (i = 0; i < n_entries; ++i, ++e) { - /* Only fast-path MSI. */ - if (e->type == KVM_IRQ_ROUTING_MSI) - irqfd->irq_entry = *e; - } - -- out: - write_seqcount_end(&irqfd->irq_entry_sc); - } - -diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c -index a228ee8..1758445 100644 ---- a/virt/kvm/irq_comm.c -+++ b/virt/kvm/irq_comm.c -@@ -160,6 +160,7 @@ static int kvm_set_msi_inatomic(struct kvm_kernel_irq_routing_entry *e, - */ - int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level) - { -+ struct kvm_kernel_irq_routing_entry entries[KVM_NR_IRQCHIPS]; - struct kvm_kernel_irq_routing_entry *e; - int ret = -EINVAL; - struct kvm_irq_routing_table *irq_rt; -@@ -177,14 +178,13 @@ int kvm_set_irq_inatomic(struct kvm *kvm, int irq_source_id, u32 irq, int level) - */ - idx = srcu_read_lock(&kvm->irq_srcu); - irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -- if (irq < irq_rt->nr_rt_entries) -- hlist_for_each_entry(e, &irq_rt->map[irq], link) { -- if (likely(e->type == KVM_IRQ_ROUTING_MSI)) -- ret = kvm_set_msi_inatomic(e, kvm); -- else -- ret = -EWOULDBLOCK; -- break; -- } -+ if (kvm_irq_map_gsi(entries, irq_rt, irq) > 0) { -+ e = &entries[0]; -+ if (likely(e->type == KVM_IRQ_ROUTING_MSI)) -+ ret = kvm_set_msi_inatomic(e, kvm); -+ else -+ ret = -EWOULDBLOCK; -+ } - srcu_read_unlock(&kvm->irq_srcu, idx); - return ret; - } -@@ -272,8 +272,7 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, - srcu_read_unlock(&kvm->irq_srcu, idx); - } - --int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, -- struct kvm_kernel_irq_routing_entry *e, -+int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, - const struct kvm_irq_routing_entry *ue) - { - int r = -EINVAL; -@@ -304,7 +303,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, - e->irqchip.pin = ue->u.irqchip.pin + delta; - if (e->irqchip.pin >= max_pin) - goto out; -- rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi; - break; - case KVM_IRQ_ROUTING_MSI: - e->set = kvm_set_msi; -diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c -index b43c275..f4648dd 100644 ---- a/virt/kvm/irqchip.c -+++ b/virt/kvm/irqchip.c -@@ -31,13 +31,37 @@ - #include - #include "irq.h" - -+int kvm_irq_map_gsi(struct kvm_kernel_irq_routing_entry *entries, -+ struct kvm_irq_routing_table *irq_rt, int gsi) -+{ -+ struct kvm_kernel_irq_routing_entry *e; -+ int n = 0; -+ -+ if (gsi < irq_rt->nr_rt_entries) { -+ hlist_for_each_entry(e, &irq_rt->map[gsi], link) { -+ entries[n] = *e; -+ ++n; -+ } -+ } -+ -+ return n; -+} -+ -+int kvm_irq_map_chip_pin(struct kvm_irq_routing_table *irq_rt, -+ unsigned irqchip, unsigned pin) -+{ -+ return irq_rt->chip[irqchip][pin]; -+} -+ - bool kvm_irq_has_notifier(struct kvm *kvm, unsigned irqchip, unsigned pin) - { -+ struct kvm_irq_routing_table *irq_rt; - struct kvm_irq_ack_notifier *kian; - int gsi, idx; - - idx = srcu_read_lock(&kvm->irq_srcu); -- gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin]; -+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -+ gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin); - if (gsi != -1) - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, - link) -@@ -54,13 +78,15 @@ EXPORT_SYMBOL_GPL(kvm_irq_has_notifier); - - void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin) - { -+ struct kvm_irq_routing_table *irq_rt; - struct kvm_irq_ack_notifier *kian; - int gsi, idx; - - trace_kvm_ack_irq(irqchip, pin); - - idx = srcu_read_lock(&kvm->irq_srcu); -- gsi = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu)->chip[irqchip][pin]; -+ irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -+ gsi = kvm_irq_map_chip_pin(irq_rt, irqchip, pin); - if (gsi != -1) - hlist_for_each_entry_rcu(kian, &kvm->irq_ack_notifier_list, - link) -@@ -115,8 +141,8 @@ int kvm_send_userspace_msi(struct kvm *kvm, struct kvm_msi *msi) - int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - bool line_status) - { -- struct kvm_kernel_irq_routing_entry *e, irq_set[KVM_NR_IRQCHIPS]; -- int ret = -1, i = 0, idx; -+ struct kvm_kernel_irq_routing_entry irq_set[KVM_NR_IRQCHIPS]; -+ int ret = -1, i, idx; - struct kvm_irq_routing_table *irq_rt; - - trace_kvm_set_irq(irq, level, irq_source_id); -@@ -127,9 +153,7 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, - */ - idx = srcu_read_lock(&kvm->irq_srcu); - irq_rt = srcu_dereference(kvm->irq_routing, &kvm->irq_srcu); -- if (irq < irq_rt->nr_rt_entries) -- hlist_for_each_entry(e, &irq_rt->map[irq], link) -- irq_set[i++] = *e; -+ i = kvm_irq_map_gsi(irq_set, irq_rt, irq); - srcu_read_unlock(&kvm->irq_srcu, idx); - - while(i--) { -@@ -171,9 +195,11 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt, - - e->gsi = ue->gsi; - e->type = ue->type; -- r = kvm_set_routing_entry(rt, e, ue); -+ r = kvm_set_routing_entry(e, ue); - if (r) - goto out; -+ if (e->type == KVM_IRQ_ROUTING_IRQCHIP) -+ rt->chip[e->irqchip.irqchip][e->irqchip.pin] = e->gsi; - - hlist_add_head(&e->link, &rt->map[e->gsi]); - r = 0; --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/KVM-prepare-for-KVM_-S-G-ET_MP_STATE-on-other-archit.patch b/debian/patches/features/powerpc/KVM-prepare-for-KVM_-S-G-ET_MP_STATE-on-other-archit.patch deleted file mode 100644 index 0d3b3a02a..000000000 --- a/debian/patches/features/powerpc/KVM-prepare-for-KVM_-S-G-ET_MP_STATE-on-other-archit.patch +++ /dev/null @@ -1,84 +0,0 @@ -From: David Hildenbrand -Date: Mon, 12 May 2014 16:05:13 +0200 -Subject: KVM: prepare for KVM_(S|G)ET_MP_STATE on other - architectures -Origin: https://git.kernel.org/linus/0b4820d6d8b6448bc9f7fac1bb1a801a53b425e1 - -Highlight the aspects of the ioctls that are actually specific to x86 -and ia64. As defined restrictions (irqchip) and mp states may not apply -to other architectures, these parts are flagged to belong to x86 and ia64. - -In preparation for the use of KVM_(S|G)ET_MP_STATE by s390. -Fix a spelling error (KVM_SET_MP_STATE vs. KVM_SET_MPSTATE) on the way. - -Signed-off-by: David Hildenbrand -Reviewed-by: Cornelia Huck -Acked-by: Christian Borntraeger -Signed-off-by: Christian Borntraeger ---- - Documentation/virtual/kvm/api.txt | 21 ++++++++++++--------- - include/uapi/linux/kvm.h | 3 ++- - 2 files changed, 14 insertions(+), 10 deletions(-) - -diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt -index 0fe3649..904c61c 100644 ---- a/Documentation/virtual/kvm/api.txt -+++ b/Documentation/virtual/kvm/api.txt -@@ -988,18 +988,20 @@ uniprocessor guests). - - Possible values are: - -- - KVM_MP_STATE_RUNNABLE: the vcpu is currently running -+ - KVM_MP_STATE_RUNNABLE: the vcpu is currently running [x86, ia64] - - KVM_MP_STATE_UNINITIALIZED: the vcpu is an application processor (AP) -- which has not yet received an INIT signal -+ which has not yet received an INIT signal [x86, -+ ia64] - - KVM_MP_STATE_INIT_RECEIVED: the vcpu has received an INIT signal, and is -- now ready for a SIPI -+ now ready for a SIPI [x86, ia64] - - KVM_MP_STATE_HALTED: the vcpu has executed a HLT instruction and -- is waiting for an interrupt -+ is waiting for an interrupt [x86, ia64] - - KVM_MP_STATE_SIPI_RECEIVED: the vcpu has just received a SIPI (vector -- accessible via KVM_GET_VCPU_EVENTS) -+ accessible via KVM_GET_VCPU_EVENTS) [x86, ia64] - --This ioctl is only useful after KVM_CREATE_IRQCHIP. Without an in-kernel --irqchip, the multiprocessing state must be maintained by userspace. -+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an -+in-kernel irqchip, the multiprocessing state must be maintained by userspace on -+these architectures. - - - 4.39 KVM_SET_MP_STATE -@@ -1013,8 +1015,9 @@ Returns: 0 on success; -1 on error - Sets the vcpu's current "multiprocessing state"; see KVM_GET_MP_STATE for - arguments. - --This ioctl is only useful after KVM_CREATE_IRQCHIP. Without an in-kernel --irqchip, the multiprocessing state must be maintained by userspace. -+On x86 and ia64, this ioctl is only useful after KVM_CREATE_IRQCHIP. Without an -+in-kernel irqchip, the multiprocessing state must be maintained by userspace on -+these architectures. - - - 4.40 KVM_SET_IDENTITY_MAP_ADDR -diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h -index e11d8f1..37d4ec6 100644 ---- a/include/uapi/linux/kvm.h -+++ b/include/uapi/linux/kvm.h -@@ -399,8 +399,9 @@ struct kvm_vapic_addr { - __u64 vapic_addr; - }; - --/* for KVM_SET_MPSTATE */ -+/* for KVM_SET_MP_STATE */ - -+/* not all states are valid on all architectures */ - #define KVM_MP_STATE_RUNNABLE 0 - #define KVM_MP_STATE_UNINITIALIZED 1 - #define KVM_MP_STATE_INIT_RECEIVED 2 --- -1.7.10.4 - diff --git a/debian/patches/features/powerpc/PPC-Add-asm-helpers-for-BE-32bit-load-store.patch b/debian/patches/features/powerpc/PPC-Add-asm-helpers-for-BE-32bit-load-store.patch deleted file mode 100644 index e2a33e9f8..000000000 --- a/debian/patches/features/powerpc/PPC-Add-asm-helpers-for-BE-32bit-load-store.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Alexander Graf -Date: Wed, 11 Jun 2014 10:07:40 +0200 -Subject: PPC: Add asm helpers for BE 32bit load/store -Origin: https://git.kernel.org/linus/8f6822c4b9fac6e47414d2f1e11dbabda9bc2163 - -From assembly code we might not only have to explicitly BE access 64bit values, -but sometimes also 32bit ones. Add helpers that allow for easy use of lwzx/stwx -in their respective byte-reverse or native form. - -Signed-off-by: Alexander Graf -CC: Benjamin Herrenschmidt ---- - arch/powerpc/include/asm/asm-compat.h | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h -index 4b237aa..21be8ae 100644 ---- a/arch/powerpc/include/asm/asm-compat.h -+++ b/arch/powerpc/include/asm/asm-compat.h -@@ -34,10 +34,14 @@ - #define PPC_MIN_STKFRM 112 - - #ifdef __BIG_ENDIAN__ -+#define LWZX_BE stringify_in_c(lwzx) - #define LDX_BE stringify_in_c(ldx) -+#define STWX_BE stringify_in_c(stwx) - #define STDX_BE stringify_in_c(stdx) - #else -+#define LWZX_BE stringify_in_c(lwbrx) - #define LDX_BE stringify_in_c(ldbrx) -+#define STWX_BE stringify_in_c(stwbrx) - #define STDX_BE stringify_in_c(stdbrx) - #endif - --- -1.7.10.4 - diff --git a/debian/patches/series b/debian/patches/series index 550c9a662..d5e3435f7 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -18,13 +18,13 @@ bugfix/all/radeon-firmware-is-required-for-drm-and-kms-on-r600-onward.patch # Patches and source files from aufs3 repository, imported with # debian/patches/features/all/aufs3/gen-patch. -features/all/aufs3/aufs3-kbuild.patch -features/all/aufs3/aufs3-base.patch -features/all/aufs3/aufs3-mmap.patch -features/all/aufs3/aufs3-standalone.patch -features/all/aufs3/aufs3-add.patch +#features/all/aufs3/aufs3-kbuild.patch +#features/all/aufs3/aufs3-base.patch +#features/all/aufs3/aufs3-mmap.patch +#features/all/aufs3/aufs3-standalone.patch +#features/all/aufs3/aufs3-add.patch # Debian-specific changes -debian/aufs3-mark-as-staging.patch +#debian/aufs3-mark-as-staging.patch # Change some defaults for security reasons debian/af_802154-Disable-auto-loading-as-mitigation-against.patch @@ -52,75 +52,23 @@ bugfix/mips/disable-advansys.patch bugfix/arm/ixp4xx_iobe.patch bugfix/m68k/ethernat-kconfig.patch bugfix/mips/MIPS-ZBOOT-add-missing-linux-string.h-include.patch -bugfix/mips/MIPS-OCTEON-make-get_system_type-thread-safe.patch -bugfix/mips/MIPS-O32-32-bit-Fix-bug-which-can-cause-incorrect-sy.patch -bugfix/mips/MIPS-tlbex-fix-a-missing-statement-for-HUGETLB.patch -bugfix/mips/MIPS-prevent-user-from-setting-FCSR-cause-bits.patch -bugfix/mips/MIPS-Remove-BUG_ON-is_fpu_owner-in-do_ade.patch bugfix/x86/x86-reject-x32-executables-if-x32-abi-not-supported.patch -bugfix/s390/s390-3215-fix-hanging-console-issue.patch # Arch features -features/mips/MIPS-Support-hard-limit-of-cpu-count-nr_cpu_ids.patch -features/mips/MIPS-Support-CPU-topology-files-in-sysfs.patch -features/mips/MIPS-Loongson-Modify-ChipConfig-register-definition.patch -features/mips/MIPS-Add-NUMA-support-for-Loongson-3.patch -features/mips/MIPS-Add-numa-api-support.patch -features/mips/MIPS-Add-Loongson-3B-support.patch -features/mips/MIPS-Loongson-3-Enable-the-COP2-usage.patch -features/mips/MIPS-Loongson-Rename-CONFIG_LEMOTE_MACH3A-to-CONFIG_.patch features/mips/MIPS-Loongson-3-Add-Loongson-LS3A-RS780E-1-way-machi.patch -features/powerpc/KVM-prepare-for-KVM_-S-G-ET_MP_STATE-on-other-archit.patch -features/powerpc/KVM-PPC-Book3s-PR-Disable-AIL-mode-with-OPAL.patch -features/powerpc/KVM-PPC-Book3s-HV-Fix-tlbie-compile-error.patch -features/powerpc/KVM-PPC-Book3S-PR-Handle-hyp-doorbell-exits.patch -features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-indirect-branch-issue.patch -features/powerpc/KVM-PPC-Book3S-PR-Fix-sparse-endian-checks.patch -features/powerpc/KVM-PPC-Book3S-Controls-for-in-kernel-sPAPR-hypercal.patch -features/powerpc/PPC-Add-asm-helpers-for-BE-32bit-load-store.patch -features/powerpc/KVM-PPC-Book3S-HV-Make-HTAB-code-LE-host-aware.patch -features/powerpc/KVM-PPC-Book3S-HV-Access-guest-VPA-in-BE.patch -features/powerpc/KVM-PPC-Book3S-HV-Access-host-lppaca-and-shadow-slb-.patch -features/powerpc/KVM-PPC-Book3S-HV-Access-XICS-in-BE.patch -features/powerpc/KVM-PPC-Book3S-HV-Fix-ABIv2-on-LE.patch -features/powerpc/KVM-PPC-Book3S-HV-Enable-for-little-endian-hosts.patch -features/powerpc/KVM-Rename-and-add-argument-to-check_extension.patch -features/powerpc/KVM-Allow-KVM_CHECK_EXTENSION-on-the-vm-fd.patch -features/powerpc/KVM-Don-t-keep-reference-to-irq-routing-table-in-irq.patch -features/powerpc/KVM-irqchip-Provide-and-use-accessors-for-irq-routin.patch -features/powerpc/KVM-Move-all-accesses-to-kvm-irq_routing-into-irqchi.patch -features/powerpc/KVM-Move-irq-notifier-implementation-into-eventfd.c.patch -features/powerpc/KVM-Give-IRQFD-its-own-separate-enabling-Kconfig-opt.patch -features/powerpc/KVM-PPC-Enable-IRQFD-support-for-the-XICS-interrupt-.patch features/powerpc/deb-pkg-add-support-for-powerpc-little-endian.patch features/x86/x86-memtest-WARN-if-bad-RAM-found.patch features/x86/x86-make-x32-syscall-support-conditional.patch features/arm/deb-pkg-add-automatic-support-for-armhf-architecture.patch -features/arm64/drivers-net-Add-APM-X-Gene-SoC-ethernet-driver-suppo.patch features/arm64/drivers-net-NET_XGENE-should-depend-on-HAS_DMA.patch -features/arm64/net-xgene-Check-negative-return-value-of-xgene_enet_.patch -features/arm64/net-xgene-fix-possible-NULL-dereference-in-xgene_ene.patch -features/arm64/dts-Add-bindings-for-APM-X-Gene-SoC-ethernet-driver.patch # Miscellaneous bug fixes bugfix/all/misc-bmp085-Enable-building-as-a-module.patch bugfix/all/kbuild-use-nostdinc-in-compile-tests.patch bugfix/all/disable-some-marvell-phys.patch -bugfix/all/aio-fix-reqs_available-handling.patch -bugfix/all/mnt-Only-change-user-settable-mount-flags-in-remount.patch -bugfix/all/mnt-Move-the-test-for-MNT_LOCK_READONLY-from-change_.patch -bugfix/all/mnt-Correct-permission-checks-in-do_remount.patch -bugfix/all/mnt-Change-the-default-remount-atime-from-relatime-t.patch -bugfix/all/mnt-Add-tests-for-unprivileged-remount-cases-that-ha.patch debian/i2o-disable-i2o_ext_adaptec-on-64bit.patch bugfix/all/aic94xx-remove-broken-fallback-for-missing-ctrl-a.patch bugfix/all/builddeb-put-the-dbg-files-into-the-correct-director.patch -bugfix/all/libceph-set-last_piece-in-ceph_msg_data_pages_cursor.patch -bugfix/all/libceph-gracefully-handle-large-reply-messages-from-.patch -bugfix/all/libceph-add-process_one_ticket-helper.patch -bugfix/all/libceph-do-not-hard-code-max-auth-ticket-len.patch # Miscellaneous features features/all/efi-autoload-efivars.patch -features/all/virtio-scsi-Implement-change_queue_depth-for-virtscs.patch -debian/revert-staging-sm7xxfb-remove-driver.patch diff --git a/debian/patches/series-orig b/debian/patches/series-orig index b98b60b8a..3294794fe 100644 --- a/debian/patches/series-orig +++ b/debian/patches/series-orig @@ -2,8 +2,6 @@ + debian/dfsg/drivers-media-dvb-dvb-usb-af9005-disable.patch + debian/dfsg/vs6624-disable.patch + debian/dfsg/drivers-net-appletalk-cops.patch -+ debian/dfsg/drivers-staging-wlags49_h2-disable.patch -+ debian/dfsg/drivers-staging-wlags49_h25-disable.patch + debian/dfsg/video-remove-nvidiafb-and-rivafb.patch + debian/dfsg/firmware-cleanup.patch X debian/dfsg/files-1