Commit d8564e19 authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Vasily Gorbik

s390/qdio: allow for non-contiguous SBAL array in init_data

Upper-layer drivers allocate their SBALs by calling qdio_alloc_buffers()
for each individual queue. But when later passing the SBAL addresses to
qdio_establish(), they need to be in a single array of pointers.
So if the driver uses multiple Input or Output queues, it needs to
allocate a temporary array just to present all its SBAL pointers in this
layout.

This patch slightly changes the format of the QDIO initialization data,
so that drivers can pass a per-queue array where each element points to
a queue's SBAL array.
zfcp doesn't use multiple queues, so the impact there is trivial.
For qeth this brings a nice reduction in complexity, and removes
a page-sized allocation.
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Reviewed-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent ad96401c
...@@ -341,8 +341,8 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int, ...@@ -341,8 +341,8 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
* @irq_poll: Data IRQ polling handler (NULL when not supported) * @irq_poll: Data IRQ polling handler (NULL when not supported)
* @scan_threshold: # of in-use buffers that triggers scan on output queue * @scan_threshold: # of in-use buffers that triggers scan on output queue
* @int_parm: interruption parameter * @int_parm: interruption parameter
* @input_sbal_addr_array: address of no_input_qs * 128 pointers * @input_sbal_addr_array: per-queue array, each element points to 128 SBALs
* @output_sbal_addr_array: address of no_output_qs * 128 pointers * @output_sbal_addr_array: per-queue array, each element points to 128 SBALs
* @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL) * @output_sbal_state_array: no_output_qs * 128 state info (for CQ or NULL)
*/ */
struct qdio_initialize { struct qdio_initialize {
...@@ -362,8 +362,8 @@ struct qdio_initialize { ...@@ -362,8 +362,8 @@ struct qdio_initialize {
void (*irq_poll)(struct ccw_device *cdev, unsigned long data); void (*irq_poll)(struct ccw_device *cdev, unsigned long data);
unsigned int scan_threshold; unsigned int scan_threshold;
unsigned long int_parm; unsigned long int_parm;
struct qdio_buffer **input_sbal_addr_array; struct qdio_buffer ***input_sbal_addr_array;
struct qdio_buffer **output_sbal_addr_array; struct qdio_buffer ***output_sbal_addr_array;
struct qdio_outbuf_state *output_sbal_state_array; struct qdio_outbuf_state *output_sbal_state_array;
}; };
......
...@@ -213,8 +213,6 @@ static void setup_queues(struct qdio_irq *irq_ptr, ...@@ -213,8 +213,6 @@ static void setup_queues(struct qdio_irq *irq_ptr,
struct qdio_initialize *qdio_init) struct qdio_initialize *qdio_init)
{ {
struct qdio_q *q; struct qdio_q *q;
struct qdio_buffer **input_sbal_array = qdio_init->input_sbal_addr_array;
struct qdio_buffer **output_sbal_array = qdio_init->output_sbal_addr_array;
struct qdio_outbuf_state *output_sbal_state_array = struct qdio_outbuf_state *output_sbal_state_array =
qdio_init->output_sbal_state_array; qdio_init->output_sbal_state_array;
int i; int i;
...@@ -225,8 +223,8 @@ static void setup_queues(struct qdio_irq *irq_ptr, ...@@ -225,8 +223,8 @@ static void setup_queues(struct qdio_irq *irq_ptr,
q->is_input_q = 1; q->is_input_q = 1;
setup_storage_lists(q, irq_ptr, input_sbal_array, i); setup_storage_lists(q, irq_ptr,
input_sbal_array += QDIO_MAX_BUFFERS_PER_Q; qdio_init->input_sbal_addr_array[i], i);
if (is_thinint_irq(irq_ptr)) { if (is_thinint_irq(irq_ptr)) {
tasklet_init(&q->tasklet, tiqdio_inbound_processing, tasklet_init(&q->tasklet, tiqdio_inbound_processing,
...@@ -245,8 +243,8 @@ static void setup_queues(struct qdio_irq *irq_ptr, ...@@ -245,8 +243,8 @@ static void setup_queues(struct qdio_irq *irq_ptr,
output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q; output_sbal_state_array += QDIO_MAX_BUFFERS_PER_Q;
q->is_input_q = 0; q->is_input_q = 0;
setup_storage_lists(q, irq_ptr, output_sbal_array, i); setup_storage_lists(q, irq_ptr,
output_sbal_array += QDIO_MAX_BUFFERS_PER_Q; qdio_init->output_sbal_addr_array[i], i);
tasklet_init(&q->tasklet, qdio_outbound_processing, tasklet_init(&q->tasklet, qdio_outbound_processing,
(unsigned long) q); (unsigned long) q);
......
...@@ -181,11 +181,12 @@ struct qeth_vnicc_info { ...@@ -181,11 +181,12 @@ struct qeth_vnicc_info {
/*****************************************************************************/ /*****************************************************************************/
/* QDIO queue and buffer handling */ /* QDIO queue and buffer handling */
/*****************************************************************************/ /*****************************************************************************/
#define QETH_MAX_QUEUES 4 #define QETH_MAX_OUT_QUEUES 4
#define QETH_IQD_MIN_TXQ 2 /* One for ucast, one for mcast. */ #define QETH_IQD_MIN_TXQ 2 /* One for ucast, one for mcast. */
#define QETH_IQD_MCAST_TXQ 0 #define QETH_IQD_MCAST_TXQ 0
#define QETH_IQD_MIN_UCAST_TXQ 1 #define QETH_IQD_MIN_UCAST_TXQ 1
#define QETH_MAX_IN_QUEUES 2
#define QETH_RX_COPYBREAK (PAGE_SIZE >> 1) #define QETH_RX_COPYBREAK (PAGE_SIZE >> 1)
#define QETH_IN_BUF_SIZE_DEFAULT 65536 #define QETH_IN_BUF_SIZE_DEFAULT 65536
#define QETH_IN_BUF_COUNT_DEFAULT 64 #define QETH_IN_BUF_COUNT_DEFAULT 64
...@@ -539,7 +540,7 @@ struct qeth_qdio_info { ...@@ -539,7 +540,7 @@ struct qeth_qdio_info {
/* output */ /* output */
int no_out_queues; int no_out_queues;
struct qeth_qdio_out_q *out_qs[QETH_MAX_QUEUES]; struct qeth_qdio_out_q *out_qs[QETH_MAX_OUT_QUEUES];
struct qdio_outbuf_state *out_bufstates; struct qdio_outbuf_state *out_bufstates;
/* priority queueing */ /* priority queueing */
......
...@@ -4812,28 +4812,13 @@ static void qeth_determine_capabilities(struct qeth_card *card) ...@@ -4812,28 +4812,13 @@ static void qeth_determine_capabilities(struct qeth_card *card)
return; return;
} }
static void qeth_qdio_establish_cq(struct qeth_card *card,
struct qdio_buffer **in_sbal_ptrs)
{
int i;
if (card->options.cq == QETH_CQ_ENABLED) {
int offset = QDIO_MAX_BUFFERS_PER_Q *
(card->qdio.no_in_queues - 1);
for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
in_sbal_ptrs[offset + i] =
card->qdio.c_q->bufs[i].buffer;
}
}
static int qeth_qdio_establish(struct qeth_card *card) static int qeth_qdio_establish(struct qeth_card *card)
{ {
struct qdio_buffer **out_sbal_ptrs[QETH_MAX_OUT_QUEUES];
struct qdio_buffer **in_sbal_ptrs[QETH_MAX_IN_QUEUES];
struct qdio_initialize init_data; struct qdio_initialize init_data;
char *qib_param_field; char *qib_param_field;
struct qdio_buffer **in_sbal_ptrs; unsigned int i;
struct qdio_buffer **out_sbal_ptrs;
int i, j, k;
int rc = 0; int rc = 0;
QETH_CARD_TEXT(card, 2, "qdioest"); QETH_CARD_TEXT(card, 2, "qdioest");
...@@ -4847,32 +4832,12 @@ static int qeth_qdio_establish(struct qeth_card *card) ...@@ -4847,32 +4832,12 @@ static int qeth_qdio_establish(struct qeth_card *card)
qeth_create_qib_param_field(card, qib_param_field); qeth_create_qib_param_field(card, qib_param_field);
qeth_create_qib_param_field_blkt(card, qib_param_field); qeth_create_qib_param_field_blkt(card, qib_param_field);
in_sbal_ptrs = kcalloc(card->qdio.no_in_queues * QDIO_MAX_BUFFERS_PER_Q, in_sbal_ptrs[0] = card->qdio.in_q->qdio_bufs;
sizeof(void *), if (card->options.cq == QETH_CQ_ENABLED)
GFP_KERNEL); in_sbal_ptrs[1] = card->qdio.c_q->qdio_bufs;
if (!in_sbal_ptrs) {
rc = -ENOMEM;
goto out_free_qib_param;
}
for (i = 0; i < QDIO_MAX_BUFFERS_PER_Q; i++)
in_sbal_ptrs[i] = card->qdio.in_q->bufs[i].buffer;
qeth_qdio_establish_cq(card, in_sbal_ptrs);
out_sbal_ptrs =
kcalloc(card->qdio.no_out_queues * QDIO_MAX_BUFFERS_PER_Q,
sizeof(void *),
GFP_KERNEL);
if (!out_sbal_ptrs) {
rc = -ENOMEM;
goto out_free_in_sbals;
}
for (i = 0, k = 0; i < card->qdio.no_out_queues; ++i) for (i = 0; i < card->qdio.no_out_queues; i++)
for (j = 0; j < QDIO_MAX_BUFFERS_PER_Q; j++, k++) out_sbal_ptrs[i] = card->qdio.out_qs[i]->qdio_bufs;
out_sbal_ptrs[k] =
card->qdio.out_qs[i]->bufs[j]->buffer;
memset(&init_data, 0, sizeof(struct qdio_initialize)); memset(&init_data, 0, sizeof(struct qdio_initialize));
init_data.cdev = CARD_DDEV(card); init_data.cdev = CARD_DDEV(card);
...@@ -4917,10 +4882,6 @@ static int qeth_qdio_establish(struct qeth_card *card) ...@@ -4917,10 +4882,6 @@ static int qeth_qdio_establish(struct qeth_card *card)
break; break;
} }
out: out:
kfree(out_sbal_ptrs);
out_free_in_sbals:
kfree(in_sbal_ptrs);
out_free_qib_param:
kfree(qib_param_field); kfree(qib_param_field);
out_free_nothing: out_free_nothing:
return rc; return rc;
...@@ -5986,7 +5947,7 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card) ...@@ -5986,7 +5947,7 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
switch (card->info.type) { switch (card->info.type) {
case QETH_CARD_TYPE_IQD: case QETH_CARD_TYPE_IQD:
dev = alloc_netdev_mqs(sizeof(*priv), "hsi%d", NET_NAME_UNKNOWN, dev = alloc_netdev_mqs(sizeof(*priv), "hsi%d", NET_NAME_UNKNOWN,
ether_setup, QETH_MAX_QUEUES, 1); ether_setup, QETH_MAX_OUT_QUEUES, 1);
break; break;
case QETH_CARD_TYPE_OSM: case QETH_CARD_TYPE_OSM:
dev = alloc_etherdev(sizeof(*priv)); dev = alloc_etherdev(sizeof(*priv));
...@@ -5996,7 +5957,7 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card) ...@@ -5996,7 +5957,7 @@ static struct net_device *qeth_alloc_netdev(struct qeth_card *card)
ether_setup); ether_setup);
break; break;
default: default:
dev = alloc_etherdev_mqs(sizeof(*priv), QETH_MAX_QUEUES, 1); dev = alloc_etherdev_mqs(sizeof(*priv), QETH_MAX_OUT_QUEUES, 1);
} }
if (!dev) if (!dev)
......
...@@ -349,6 +349,8 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio) ...@@ -349,6 +349,8 @@ void zfcp_qdio_close(struct zfcp_qdio *qdio)
*/ */
int zfcp_qdio_open(struct zfcp_qdio *qdio) int zfcp_qdio_open(struct zfcp_qdio *qdio)
{ {
struct qdio_buffer **input_sbals[1] = {qdio->res_q};
struct qdio_buffer **output_sbals[1] = {qdio->req_q};
struct qdio_buffer_element *sbale; struct qdio_buffer_element *sbale;
struct qdio_initialize init_data = {0}; struct qdio_initialize init_data = {0};
struct zfcp_adapter *adapter = qdio->adapter; struct zfcp_adapter *adapter = qdio->adapter;
...@@ -374,8 +376,8 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio) ...@@ -374,8 +376,8 @@ int zfcp_qdio_open(struct zfcp_qdio *qdio)
init_data.input_handler = zfcp_qdio_int_resp; init_data.input_handler = zfcp_qdio_int_resp;
init_data.output_handler = zfcp_qdio_int_req; init_data.output_handler = zfcp_qdio_int_req;
init_data.int_parm = (unsigned long) qdio; init_data.int_parm = (unsigned long) qdio;
init_data.input_sbal_addr_array = qdio->res_q; init_data.input_sbal_addr_array = input_sbals;
init_data.output_sbal_addr_array = qdio->req_q; init_data.output_sbal_addr_array = output_sbals;
init_data.scan_threshold = init_data.scan_threshold =
QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2; QDIO_MAX_BUFFERS_PER_Q - ZFCP_QDIO_MAX_SBALS_PER_REQ * 2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment