Block patches (includes build fix for non-Linux)
The following changes since commit 27cdad67a1bc23b38c765b677ed8064bfb8d3e44:
Revert "alpha-softmmu: Disable for the 0.15 release branch." (2011-09-21 00:50:32 +0200)
are available in the git repository at:
git://repo.or.cz/qemu/kevin.git for-anthony
Daniel Verkamp (1):
ahci: add port I/O index-data pair
Nick Thomas (2):
block/curl: Implement a flush function on the fd handlers block/curl: Don't finish AIOCBs too early
Paolo Bonzini (1):
nbd: fix non-Linux build failure
block/curl.c | 94 +++++++++++++++++++++++++++++++++++++++++++-------------- hw/ide/ahci.c | 42 +++++++++++++++++++++++++- hw/ide/ahci.h | 9 +++++- hw/ide/ich.c | 27 ++++++++++++++++- hw/pci_regs.h | 1 + nbd.c | 2 +- 6 files changed, 148 insertions(+), 27 deletions(-)
PATCH 1/4 nbd: fix non-Linux build failure
From: Paolo Bonzini <[email protected]>
--- nbd.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
nbd.c +1 -1
@@ -439,7 +439,7 @@ int nbd_client(int fd) return ret; }#else -int nbd_init (int fd,int csock,off_t size,size_t blocksize) +int nbd_init (int fd,int csock,uint32_t flags,off_t size,size_t blocksize) { errno =ENOTSUP ;return -1 ;
Signature · 1 line
1.7.6.2
PATCH 2/4 ahci: add port I/O index-data pair
In reply to Kevin WolfFrom: Daniel Verkamp <[email protected]>
Implement an I/O space index-data register pair as defined by the AHCI spec, including the corresponding SATA PCI capability and BAR.
This allows real-mode code to access the AHCI registers; real-mode code cannot address the memory-mapped register space because it is beyond the first megabyte.
--- hw/ide/ahci.c | 42 +++++++++++++++++++++++++++++++++++++++++- hw/ide/ahci.h | 9 ++++++++- hw/ide/ich.c | 27 ++++++++++++++++++++++++++- hw/pci_regs.h | 1 + 4 files changed, 76 insertions(+), 3 deletions(-)
hw/ide/ahci.c +41 -1
@@ -370,6 +370,43 @@ static MemoryRegionOps ahci_mem_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; +static uint64_t ahci_idp_read (void *opaque,target_phys_addr_t addr, +unsigned size) +{ +AHCIState *s = opaque; + +if (addr == s->idp_offset) { +/* index register */ +return s->idp_index; + }else if (addr == s->idp_offset +4 ) { +/* data register - do memory read at location selected by index */ +return ahci_mem_read (opaque, s->idp_index, size); + }else { +return 0 ; + } +} + +static void ahci_idp_write (void *opaque,target_phys_addr_t addr, +uint64_t val,unsigned size) +{ +AHCIState *s = opaque; + +if (addr == s->idp_offset) { +/* index register - mask off reserved bits */ + s->idp_index = (uint32_t )val & ((AHCI_MEM_BAR_SIZE -1 ) & ~3 ); + }else if (addr == s->idp_offset +4 ) { +/* data register - do memory write at location selected by index */ +ahci_mem_write (opaque, s->idp_index, val, size); + } +} + +static MemoryRegionOps ahci_idp_ops = { + .read = ahci_idp_read, + .write = ahci_idp_write, + .endianness =DEVICE_LITTLE_ENDIAN , +}; + +static void ahci_reg_init (AHCIState *s) {int i;
@@ -1130,7 +1167,9 @@ void ahci_init(AHCIState *s, DeviceState *qdev, int ports) s->dev =g_malloc0 (sizeof (AHCIDevice) * ports);ahci_reg_init (s);/* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */ -memory_region_init_io (&s->mem, &ahci_mem_ops, s,"ahci" ,0x1000 ); +memory_region_init_io (&s->mem, &ahci_mem_ops, s,"ahci" ,AHCI_MEM_BAR_SIZE ); +memory_region_init_io (&s->idp, &ahci_idp_ops, s,"ahci-idp" ,32 ); + irqs =qemu_allocate_irqs (ahci_irq_set, s, s->ports);for (i =0 ; i < s->ports; i++) {
@@ -1150,6 +1189,7 @@ void ahci_init(AHCIState *s, DeviceState *qdev, int ports)void ahci_uninit (AHCIState *s) {memory_region_destroy (&s->mem); +memory_region_destroy (&s->idp);g_free (s->dev); }
hw/ide/ahci.h +8 -1
@@ -24,7 +24,7 @@#ifndef HW_IDE_AHCI_H #define HW_IDE_AHCI_H -#define AHCI_PCI_BAR 5 +#define AHCI_MEM_BAR_SIZE 0x1000#define AHCI_MAX_PORTS 32#define AHCI_MAX_SG 168/* hardware max is 64K */ #define AHCI_DMA_BOUNDARY 0xffffffff
@@ -212,6 +212,10 @@#define RES_FIS_SDBFIS 0x58#define RES_FIS_UFIS 0x60 +#define SATA_CAP_SIZE 0x8 +#define SATA_CAP_REV 0x2 +#define SATA_CAP_BAR 0x4 + typedef struct AHCIControlRegs { uint32_t cap; uint32_t ghc;
@@ -290,6 +294,9 @@ typedef struct AHCIState {AHCIDevice *dev;AHCIControlRegs control_regs;MemoryRegion mem; +MemoryRegion idp;/* Index-Data Pair I/O port space */ +unsigned idp_offset;/* Offset of index in I/O port space */ +uint32_t idp_index;/* Current IDP index */ int ports;qemu_irq irq; } AHCIState;
hw/ide/ich.c +26 -1
@@ -71,6 +71,14 @@#include <hw/ide/pci.h> #include <hw/ide/ahci.h> +#define ICH9_SATA_CAP_OFFSET 0xA8 + +#define ICH9_IDP_BAR 4 +#define ICH9_MEM_BAR 5 + +#define ICH9_IDP_INDEX 0x10 +#define ICH9_IDP_INDEX_LOG2 0x04 +static const VMStateDescription vmstate_ahci = { .name ="ahci" , .unmigratable =1 ,
@@ -79,6 +87,8 @@ static const VMStateDescription vmstate_ahci = {static int pci_ich9_ahci_init (PCIDevice *dev) {struct AHCIPCIState *d; +int sata_cap_offset; +uint8_t *sata_cap; d = DO_UPCAST(struct AHCIPCIState, card, dev);ahci_init (&d->ahci, &dev->qdev,6 );
@@ -97,7 +107,22 @@ static int pci_ich9_ahci_init(PCIDevice *dev)msi_init (dev,0x50 ,1 , true, false); d->ahci.irq = d->card.irq[0 ]; -pci_register_bar (&d->card,5 ,0 , &d->ahci.mem); +pci_register_bar (&d->card,ICH9_IDP_BAR ,PCI_BASE_ADDRESS_SPACE_IO , + &d->ahci.idp); +pci_register_bar (&d->card,ICH9_MEM_BAR ,PCI_BASE_ADDRESS_SPACE_MEMORY , + &d->ahci.mem); + + sata_cap_offset =pci_add_capability (&d->card,PCI_CAP_ID_SATA , +ICH9_SATA_CAP_OFFSET ,SATA_CAP_SIZE ); +if (sata_cap_offset <0 ) { +return sata_cap_offset; + } + + sata_cap = d->card.config + sata_cap_offset; +pci_set_word (sata_cap +SATA_CAP_REV ,0x10 ); +pci_set_long (sata_cap +SATA_CAP_BAR , + (ICH9_IDP_BAR +0x4 ) | (ICH9_IDP_INDEX_LOG2 <<4 )); + d->ahci.idp_offset =ICH9_IDP_INDEX ;return 0 ; }
hw/pci_regs.h +1 -0
@@ -211,6 +211,7 @@#define PCI_CAP_ID_AGP3 0x0E/* AGP Target PCI-PCI bridge */ #define PCI_CAP_ID_EXP 0x10/* PCI Express */ #define PCI_CAP_ID_MSIX 0x11/* MSI-X */ +#define PCI_CAP_ID_SATA 0x12/* Serial ATA */ #define PCI_CAP_ID_AF 0x13/* PCI Advanced Features */ #define PCI_CAP_LIST_NEXT 1/* Next capability in the list */ #define PCI_CAP_FLAGS 2/* Capability defined flags (16 bits) */
Signature · 1 line
1.7.6.2
PATCH 3/4 block/curl: Implement a flush function on the fd handlers
In reply to Kevin WolfFrom: Nick Thomas <[email protected]>
--- block/curl.c | 26 ++++++++++++++++++++++---- 1 files changed, 22 insertions(+), 4 deletions(-)
block/curl.c +22 -4
@@ -76,6 +76,7 @@ typedef struct BDRVCURLState {static void curl_clean_state (CURLState *s);static void curl_multi_do (void *arg); +static int curl_aio_flush (void *opaque);static int curl_sock_cb (CURL *curl,curl_socket_t fd,int action,void *s,void *sp)
@@ -83,14 +84,16 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action,DPRINTF ("CURL (AIO): Sock action %d on fd %d\n" , action, fd);switch (action) {case CURL_POLL_IN : -qemu_aio_set_fd_handler (fd, curl_multi_do,NULL ,NULL ,NULL , s); +qemu_aio_set_fd_handler (fd, curl_multi_do,NULL , curl_aio_flush, +NULL , s);break ;case CURL_POLL_OUT : -qemu_aio_set_fd_handler (fd,NULL , curl_multi_do,NULL ,NULL , s); +qemu_aio_set_fd_handler (fd,NULL , curl_multi_do, curl_aio_flush, +NULL , s);break ;case CURL_POLL_INOUT : -qemu_aio_set_fd_handler (fd, curl_multi_do, - curl_multi_do,NULL ,NULL , s); +qemu_aio_set_fd_handler (fd, curl_multi_do, curl_multi_do, + curl_aio_flush,NULL , s);break ;case CURL_POLL_REMOVE :qemu_aio_set_fd_handler (fd,NULL ,NULL ,NULL ,NULL ,NULL );
@@ -412,6 +415,21 @@ out_noclean:return -EINVAL ; } +static int curl_aio_flush (void *opaque) +{ +BDRVCURLState *s = opaque; +int i, j; + +for (i=0 ; i <CURL_NUM_STATES ; i++) { +for (j=0 ; j <CURL_NUM_ACB ; j++) { +if (s->states[i].acb[j]) { +return 1 ; + } + } + } +return 0 ; +} +static void curl_aio_cancel (BlockDriverAIOCB *blockacb) {// Do we have to implement canceling? Seems to work without...
Signature · 1 line
1.7.6.2
PATCH 4/4 block/curl: Don't finish AIOCBs too early
In reply to Kevin WolfFrom: Nick Thomas <[email protected]>
The previous behaviour was to finish AIOCBs inside curl_aio_readv() if the data was cached. This caused the following failed assertion at hw/ide/pci.c:314: bmdma_cmd_writeb
"Assertion `bm->bus->dma->aiocb == ((void *)0)' failed."
By scheduling a QEMUBH and performing the completion inside the callback, we avoid this problem.
--- block/curl.c | 68 +++++++++++++++++++++++++++++++++++++++++---------------- 1 files changed, 49 insertions(+), 19 deletions(-)
block/curl.c +49 -19
@@ -47,7 +47,12 @@ struct BDRVCURLState;typedef struct CURLAIOCB {BlockDriverAIOCB common; +QEMUBH *bh;QEMUIOVector *qiov; + +int64_t sector_num; +int nb_sectors; +size_t start;size_t end; }CURLAIOCB ;
@@ -440,43 +445,42 @@ static AIOPool curl_aio_pool = { .cancel = curl_aio_cancel, }; -static BlockDriverAIOCB *curl_aio_readv (BlockDriverState *bs, -int64_t sector_num,QEMUIOVector *qiov,int nb_sectors, -BlockDriverCompletionFunc *cb,void *opaque) + +static void curl_readv_bh_cb (void *p) { -BDRVCURLState *s = bs->opaque; -CURLAIOCB *acb; -size_t start = sector_num *SECTOR_SIZE ; -size_t end;CURLState *state; - acb =qemu_aio_get (&curl_aio_pool, bs, cb, opaque); -if (!acb) -return NULL ; +CURLAIOCB *acb = p; +BDRVCURLState *s = acb->common.bs->opaque; - acb->qiov = qiov; +qemu_bh_delete (acb->bh); + acb->bh =NULL ; + +size_t start = acb->sector_num *SECTOR_SIZE ; +size_t end;// In case we have the requested data already (e.g. read-ahead), // we can just call the callback and be done. - -switch (curl_find_buf (s, start, nb_sectors *SECTOR_SIZE , acb)) { +switch (curl_find_buf (s, start, acb->nb_sectors *SECTOR_SIZE , acb)) {case FIND_RET_OK :qemu_aio_release (acb);// fall through case FIND_RET_WAIT : -return &acb->common; +return ;default :break ; }// No cache found, so let's start a new request - state =curl_init_state (s); -if (!state) -return NULL ; +if (!state) { + acb->common.cb (acb->common.opaque, -EIO ); +qemu_aio_release (acb); +return ; + } acb->start =0 ; - acb->end = (nb_sectors *SECTOR_SIZE ); + acb->end = (acb->nb_sectors *SECTOR_SIZE ); state->buf_off =0 ;if (state->orig_buf)
@@ -489,12 +493,38 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,snprintf (state->range,127 ,"%zd-%zd" , start, end);DPRINTF ("CURL (AIO): Reading %d at %zd (%s)\n" , - (nb_sectors *SECTOR_SIZE ), start, state->range); + (acb->nb_sectors *SECTOR_SIZE ), start, state->range);curl_easy_setopt (state->curl,CURLOPT_RANGE , state->range);curl_multi_add_handle (s->multi, state->curl);curl_multi_do (s); +} + +static BlockDriverAIOCB *curl_aio_readv (BlockDriverState *bs, +int64_t sector_num,QEMUIOVector *qiov,int nb_sectors, +BlockDriverCompletionFunc *cb,void *opaque) +{ +CURLAIOCB *acb; + + acb =qemu_aio_get (&curl_aio_pool, bs, cb, opaque); + +if (!acb) { +return NULL ; + } + + acb->qiov = qiov; + acb->sector_num = sector_num; + acb->nb_sectors = nb_sectors; + + acb->bh =qemu_bh_new (curl_readv_bh_cb, acb); + +if (!acb->bh) { +DPRINTF ("CURL: qemu_bh_new failed\n" ); +return NULL ; + } + +qemu_bh_schedule (acb->bh);return &acb->common; }
Signature · 1 line
1.7.6.2
Quoted 3 lines · Kevin Wolf
The following changes since commit
27cdad67a1bc23b38c765b677ed8064bfb8d3e44:Revert "alpha-softmmu: Disable for the 0.15 release branch." (2011-09-21 00:50:32 +0200)
Pulled. Thanks.
Regards,
Anthony Liguori
Quoted 23 lines
are available in the git repository at:
git://repo.or.cz/qemu/kevin.gitfor-anthonyDaniel Verkamp (1):
ahci: add port I/O index-data pairNick Thomas (2):
block/curl: Implement a flush function on the fd handlers block/curl: Don't finish AIOCBs too earlyPaolo Bonzini (1):
nbd: fix non-Linux build failureblock/curl.c | 94 +++++++++++++++++++++++++++++++++++++++++++-------------- hw/ide/ahci.c | 42 +++++++++++++++++++++++++- hw/ide/ahci.h | 9 +++++- hw/ide/ich.c | 27 ++++++++++++++++- hw/pci_regs.h | 1 + nbd.c | 2 +- 6 files changed, 148 insertions(+), 27 deletions(-)